diff options
| author | user <user@clank> | 2026-08-11 14:38:16 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-08-11 14:38:16 +0200 |
| commit | 844617b4ee27c2529fa16d1b53c40c62fe04fa70 (patch) | |
| tree | 822144798626c4a4451da5a56e5a6b36dd9994e8 /zellij-server/src/tab/mod.rs | |
| parent | sl0p: cap how many rows the stacked-pane picker takes (diff) | |
| download | sl0ppij-844617b4ee27c2529fa16d1b53c40c62fe04fa70.tar.gz sl0ppij-844617b4ee27c2529fa16d1b53c40c62fe04fa70.tar.xz sl0ppij-844617b4ee27c2529fa16d1b53c40c62fe04fa70.zip | |
sl0p: fix clicking a scrolled stack entry selecting the wrong pane
Regression from the picker row cap. The row -> member mapping lives in TWO
places: the renderer, and the hit-test that resolves mouse events to a pane.
Capping made the renderer draw a WINDOW of the members, so screen row 0 is
members[window_start], but the hit-test still resolved row N to members[N].
Any click or hover on a capped stack whose window had scrolled therefore
landed on the wrong pane -- with 8 members focused on the last, clicking the
top row selected member 0 instead of member 5.
Both sites now go through stack_list_window(). Clicks on the "+N more"
indicator resolve to no member rather than to a bogus one.
Caught by asking how a user reaches the panes past the cutoff, not by the
tests: the previous commit tested the window arithmetic and the rendering, but
nothing covered this second consumer of the same mapping.
Diffstat (limited to 'zellij-server/src/tab/mod.rs')
| -rw-r--r-- | zellij-server/src/tab/mod.rs | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs index 2c75c425..7f132465 100644 --- a/zellij-server/src/tab/mod.rs +++ b/zellij-server/src/tab/mod.rs @@ -1170,8 +1170,21 @@ impl Tab { if point.line() < geom.y as isize { return pane_id; } - let rank = (point.line() - geom.y as isize) as usize; - list.members.get(rank).copied().unwrap_or(pane_id) + // Screen row, NOT the member's rank: the picker draws a window of the + // members (see stack_list_window), so row 0 is members[window_start] + // once the list has scrolled. Resolving this against the raw rank picks + // the wrong pane for every capped, scrolled stack. + let row = (point.line() - geom.y as isize) as usize; + let visible_rank = list.rank_of(&list.visible).unwrap_or(0); + let (window_start, shown_count) = self.stack_list_window(list.members.len(), visible_rank); + if row >= shown_count { + // the "+N more" indicator row, which is not a member + return pane_id; + } + list.members + .get(window_start + row) + .copied() + .unwrap_or(pane_id) } pub fn suppressed_stack_list_members(&self) -> impl Iterator<Item = (&PaneId, &Box<dyn Pane>)> { self.suppressed_panes |
