From bd33600ee741bc8f3876b136dce46e4cd66ba32c Mon Sep 17 00:00:00 2001 From: Karim Jerbi Date: Wed, 12 Aug 2026 22:46:57 +0100 Subject: [PATCH] fix(dock): single-panel drag preview is one full-height slot drop_index previously mapped a pointer position inside a lone full-height panel to a top/bottom insertion split, offering an impossible drop. Clamp to the single slot when the edge holds one panel, and cover the multi-slot mapping with tests. --- src/ui/dock.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/ui/dock.rs b/src/ui/dock.rs index 1649e6a3a..9bbc2cc21 100644 --- a/src/ui/dock.rs +++ b/src/ui/dock.rs @@ -211,6 +211,11 @@ pub fn drop_index(y: f32, total: usize, avail: f32) -> usize { } let h = avail / total as f32; let idx = (y / h).round() as usize; + // A single full-height panel must not offer a top/bottom split: any drop + // lands in the one available slot. + if total <= 1 { + return 0; + } idx.min(total) } @@ -297,6 +302,24 @@ mod tests { assert_eq!(drop_index(50.0, 0, 300.0), 0); } + #[test] + fn drop_index_single_slot_is_always_zero() { + // One panel sharing the full edge height: any pointer y lands in the + // single slot, so the insertion index must be 0 (no top/bottom split). + assert_eq!(drop_index(5.0, 1, 900.0), 0); + assert_eq!(drop_index(450.0, 1, 900.0), 0); + assert_eq!(drop_index(895.0, 1, 900.0), 0); + } + + #[test] + fn drop_index_multi_slot_maps_position() { + // Two panels on an edge produce insertion positions 0..=total: pointer + // near the top lands before the first slot (0); pointer near the bottom + // of the last slot lands after the last (== total, append). + assert_eq!(drop_index(10.0, 2, 900.0), 0); + assert_eq!(drop_index(890.0, 2, 900.0), 2); + } + #[test] fn len_reports_stack_size() { let state = DockState::default();