Repository navigation
Mouse support across every screen - #2
Merged
Merged
Conversation
The wheel scrolls the pane under the pointer — over a list it moves the selection, over a preview it scrolls by three lines per notch. A left click selects the row it lands on and focuses the pane it hit; clicked rows resolve against the layout at click time, before a focus change can re-window them (clicking the one-row peek while reading returns to the list on the same item). In the menu launchpad a click on the already-selected entry launches it, matching what a click on a menu means everywhere else. Mouse mode is requested per-view (bubbletea v2's View.MouseMode) via the new tui.ScreenView helper every screen now builds its view through, so alt-screen and mouse state stay consistent across diff, log, stash, stage, the tests lens, and the menu. Cell-motion tracking only — no motion events. RIFT_MOUSE=off opts out entirely for users who prefer the terminal's native text selection; most terminals also bypass tracking with shift-click, so copying from a diff works either way. Modal states behave like the keyboard: the help overlay and inline confirm prompts ignore the mouse; the wheel still works while filtering.
The big one: stage's three view sites were never converted to tui.ScreenView, so MouseMode stayed unset and — since bubbletea v2 drives terminal mouse tracking from the returned view — the stage screen never enabled tracking and its whole mouse handler was unreachable from a real terminal. The SGR-injection testing used to verify the feature couldn't catch this (bubbletea parses injected sequences whether or not tracking was requested); verification now greps the raw terminal output for the cell-motion enable sequence per screen, including the RIFT_MOUSE=off suppression. Also: - Route mouse input to the drilled view while a log drilldown is open. It previously fell through to the hidden commit list, silently moving its selection — esc landed on a different commit and a subsequent cherry-pick/revert would have targeted it. - Bound menu clicks by the panel's visible height, not just the item count, so border/footer clicks on a short terminal can't select (or launch) entries that are clipped out of view. - Make no-op stage clicks no-ops: clicking an already-focused pane no longer re-runs the layout (which snapped the diff scroll back to the selected hunk), and a selection-changing click issues one diff load instead of two (selectTo's was always discarded when applyLayout bumped the request ID again). selectTo also gains the same boundary guard stepList has, so wheeling past the list edge stops resetting the hunk selection and re-rendering. - Delegate preview/diff wheel events to the bubbles viewport, which handles them natively (including horizontal wheel) — deleting the WheelLines constant that duplicated viewport.MouseWheelDelta. - Share the windowed click-to-row mapping (tui.ClickedRow) between SplitList and stage instead of two drifting copies; route click focus through relayout like the keyboard path; dedupe the menu's enter/click activation; correct MouseEnabled's accepted-values doc.
- Cancel superseded stage diff loads: requestDiff now cancels the in-flight load's context before starting a new one, so a wheel flick across uncached files kills each superseded difftastic run instead of letting dozens complete into discarded results (the splitlist screens already had this via their stream cancel; stage did not). - One pane-switch path per screen: stage gains the focusPane helper its keyboard and mouse handlers now share (same-pane no-op included), and splitlist's tab/enter route through the focusPane the mouse work introduced instead of inlining the flip. - The log drilldown's three input-routing gates collapse into one type-switch (keys, mouse, editor-close all belong to the visible view); an allowlist by design — the parent's untagged async traffic must keep flowing to the hidden list. - Menu derives its panel geometry from one contentHeight helper for both render and click hit-test, activates through one path, and its loading frame goes through ScreenView like every other view — the last stray tea.NewView, which made ScreenView's every-screen claim false and dropped alt-screen/mouse mode on the entry frame. - Wheel handlers pass WheelDelta straight to the selection steppers (which already no-op on zero/boundary), dropping a branch per site; the unfireable navH guard in the splitlist hit-test is gone; stage's vim-jump pre-check was subsumed by selectTo's new boundary guard.
Dragging across a preview selects display lines — highlighted in reverse video as you drag (re-asserted across the content's own SGR resets, so styled diff lines highlight end to end) — and releasing copies them through the same clipboard path as y, so the OSC 52 fallback covers SSH sessions. The copy is the displayed text, ANSI-stripped and right-trimmed: no panel borders, no scrollbar column, none of the artifacts a terminal-native selection would grab. Selection is anchored to display-line indices at press time, and the focus change a click normally performs waits for a clean release — focusing can collapse the list strip and shift the content under the pointer mid-drag. A plain click (press + release, no motion) focuses the preview exactly as before; cell-motion tracking already reports drag motion, so no new tracking mode is requested.
Clicking the preview used to enter the reading layout — the strip snapping down to a one-row peek under the pointer, which reads as the file list 'scoping down' to the selected file. Focus and the peek collapse are now separate: a click focuses the pane it hit (border highlight, key routing) while the layout stays put, and the collapse remains a deliberate keyboard gesture (⇥/⏎ set peek; focusing the list by any route leaves it, so clicking the peek row still expands).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First-class mouse interaction for all six screens (diff, log, stash, stage, tests lens, menu):
⇥/⏎); clicking the one-row peek still expands back to the list. Rows are resolved against the layout at click time, so clicking the one-row peek while reading returns to the list on the same item instead of re-windowing under the pointer.y, so OSC 52 covers SSH. Selection anchors at press time and the click's focus change defers to a clean release, so the layout never shifts under an in-progress drag.RIFT_MOUSE=off(also0/none/false) disables tracking entirely for users who prefer native terminal text selection (shift-click bypasses tracking in most terminals regardless).Implementation: bubbletea v2 requests mouse mode per view, so
tui.ScreenView(alt-screen + cell-motion mouse, honoring the opt-out) is the single place every screen builds itstea.View— SplitList covers four screens with one handler; stage (horizontal split, X-based hit-testing) and menu get small handlers reusing their existing selection/focus paths, with the windowed click→row mapping shared viatui.ClickedRowand pane switching unified per screen behind afocusPanehelper the keyboard paths also use. Modal states mirror the keyboard: help overlay and confirm prompts ignore the mouse; the wheel still works while filtering. No motion tracking, no drag, no new dependencies.Review
The branch went through
/code-review high --fix(8 finder angles → recall-biased verification, all 10 reported findings CONFIRMED) and a/simplifypass. The review caught two serious bugs in the original commit: stage's views never requested mouse mode (its whole mouse handler was unreachable from a real terminal — the SGR-injection testing used initially couldn't detect a missing mode request), and log drilldowns leaked mouse events to the hidden commit list (selection drifted invisibly; a later cherry-pick/revert would have hit the wrong commit). Also fixed: menu clicks activating entries clipped off short terminals, no-op stage clicks snapping the diff scroll back, doubled diff loads on stage file clicks, boundary wheel churn, and — from the simplify pass — cancellation of superseded stage diff loads (a wheel flick no longer piles up doomed difftastic subprocesses).Verification
mise run checkgreen; unit tests cover the click→row mapping (windowed, scrolled, border/past-end) and focus-driven relayout.\e[?1002h) on every screen including stage, and its absence underRIFT_MOUSE=off.🤖 Generated with Claude Code
https://claude.ai/code/session_01EB5anNK6czSCdjg51CH7VD