The GTK mouse handlers now delegate to *_impl methods taking button and modifier state, so the real controllers and the debug input replay share one code path. The replay hook gained mouse-move/press/release, click, drag, scroll, resize, clipboard-set/dump, windows-dump and window-screenshot steps (replayed presses bypass the focus-transfer first-click rule since the replay window isn't compositor-focused). Verified in the real app on Wayland (docs/rewrite/notes/verification- V3.md): nvim (colors, status line, cursor shapes, alt-screen restore), htop (rendering, mouse-click column sorting), less (alternate scroll), tmux (splits, status bar), drag/double/triple-click selection into PRIMARY, clipboard copy, context menu, scrollback and reflow on resize, CJK/emoji/ZWJ/nerd-font widths, kitty graphics images and the unsafe paste confirmation dialog. No product bugs were found. Test Plan: - cargo test -p ghostty-apprt-gtk (incl. parse_mouse_steps)
3.6 KiB
Verification V3 (real GTK app, real programs, mouse input)
Replay hook extensions (crates/ghostty-apprt-gtk/src/debug_input.rs, class/surface.rs)
New steps: mouse-move x y [mods], mouse-press|mouse-release|click <btn> [mods], drag x1 y1 x2 y2 [mods],
scroll dx dy, resize w h, clipboard-set, clipboard-dump (also logs context-menu visibility),
windows-dump (toplevels + widget tree, shows AdwDialogs), window-screenshot (GTK render of the whole
window incl. headerbar/dialogs; the GL area content may differ from screenshot).
The GTK handlers mouse_down/mouse_up/mouse_motion/scroll_vertical were split into *_impl methods
(taking button/modifier state instead of a GdkEvent) so the replay runs the exact same code as the
gesture controllers. The replay passes assume_focus=true for presses: the replayed window is not
compositor-focused, and the "first click only transfers focus" suppression would otherwise eat every click.
Parser unit test parse_mouse_steps added.
Scenarios (GTK, Wayland, release profile)
| Scenario | Result |
|---|---|
nvim (-e nvim file.rs): syntax colors, ligatures, status line, :q |
PASS. Insert mode bar cursor OK. |
nvim from shell, :q: alternate screen restore |
PASS (prompt + prior output intact). |
| htop: meters, colors, box/bars, F10 | PASS. Mouse click on MEM% header sorts (mouse reporting; clicking twice toggles asc/desc). F10 quits. |
less on 300 lines: wheel in alt screen, q |
PASS. 5 wheel ticks -> 15 lines (3 arrow keys per tick, DECSET 1007), q restores. |
| tmux: start, ctrl+b %, status bar, exit | PASS. |
| shell drag selection | PASS (highlight; text lands in PRIMARY via copy-on-select). |
| double-click word / triple-click line | PASS ("beta"; whole line). |
| ctrl+shift+c | PASS (CLIPBOARD gets the selection). |
| right-click | PASS: context popover becomes visible (context menu visible = true). |
| wheel scrollback (10 ticks = 30 lines) | PASS. |
| long wrapped line + window resize (shrink, grow) | PASS: reflow correct both ways, viewport preserved. |
| unicode: CJK, emoji, ZWJ family, combining, fullwidth, powerline/nerd glyphs, box drawing | PASS: widths/alignment correct. |
| kitty graphics (PNG, a=T, c=8,r=4) | PASS: image rendered at the right cell size, text flows after it. |
multi-line paste into cat (no bracketed paste) |
PASS: core rejects as unsafe, GhosttyClipboardConfirmationDialog is created and mapped (widget tree dump). The dialog isn't visible in the render-texture screenshot, only verified structurally. |
| Raw mouse bytes (SGR 1006, button 1/3, wheel) | PASS: ESC[<0;10;5M/m, ESC[<2;.., ESC[<64;.. x3 per tick. |
Kitty keyboard protocol (flags 1/31) from key steps |
PASS (CSI u with text/release events). |
Bugs
No product bugs found in this pass. Observations:
- Release profile keeps
debug-assertions = true(workspace Cargo.toml), so the "debug build" banner shows; use--profile productionto get the real release look. screenshotreturns the renderer's last presented frame; right after input it can be one frame stale. Use >= 1 s waits.- Replay limits:
key <printable>bypasses the IM;textcommits bypass key events (plain bytes even under kitty flags "report all keys"); window is not compositor-focused so cursor is hollow and clicks needassume_focus. - nvim leaves swap files when the replay is
quitmid-edit; a later nvim of the same file prompts (E325) and swallows keystrokes. This looked like a bug at first but is nvim behaviour (usenvim -n).
Remaining
- Confirm/deny of the paste dialog by interacting with it not exercised; IME via real input method not exercised.
- Horizontal scroll (tab switching) not replayed.