Skip to content

fix(flterm): forward wheel/trackpad scroll to app under mouse tracking - #119

Closed
jacobaraujo7 wants to merge 6 commits into
elias8:mainfrom
jacobaraujo7:fix/flterm-tui-scroll-forwarding
Closed

fix(flterm): forward wheel/trackpad scroll to app under mouse tracking#119
jacobaraujo7 wants to merge 6 commits into
elias8:mainfrom
jacobaraujo7:fix/flterm-tui-scroll-forwarding

Conversation

@jacobaraujo7

Copy link
Copy Markdown
Contributor

Summary

Follow-up to the now-merged #116. When #115 was closed in favour of #116, only
the Windows text-input half landed upstream — the TUI scroll-forwarding fixes
were left out. This PR brings just those two, rebased on top of current main,
so there's no overlap with #116.

Both target internal scrolling in alt-buffer TUIs (e.g. Claude Code / vim),
where the app expects mouse wheel reports rather than the Flutter Scrollable
consuming the scroll.

Fixes

1. Forward the wheel to the app under mouse tracking

With mouse tracking enabled, the gesture detector had no onPointerSignal
handler, so the inner Scrollable swallowed the wheel — scrolling the frozen
alt-buffer scrollback while the app itself never received a mouse report, so its
internal scroll did nothing.

When tracked, the wheel is now forwarded to the app as mouse button 4 (up) / 5
(down) presses — proportional for mouse notches, accumulated fractions for
trackpad; Shift+wheel bypasses so it stays local. The inner Scrollable uses
NeverScrollableScrollPhysics under mouse tracking so the two don't fight over
the pointer signal.

2. Forward macOS trackpad (pan/zoom) scroll too

Two-finger trackpad scroll on macOS frequently arrives as pan/zoom gestures
rather than PointerScrollEvent, so internal TUI scroll did nothing on the
trackpad. We now also handle onPointerPanZoomStart/Update, routing the pan
delta through the same wheel-forward path.

Tests

flutter analyze clean and the full flterm widget suite passes (300 tests).

jacobaraujo7 and others added 2 commits July 25, 2026 20:07
…scroll)

With mouse tracking enabled (TUIs like Claude Code / vim in the alt-buffer), the
gesture detector only handled pointer down/move/up — there was no onPointerSignal
for the wheel, so the inner Scrollable swallowed it (scrolling the viewport
scrollback, which is empty/frozen in the alt-buffer). The app never received the
wheel as a mouse report, so its internal scroll did nothing.

Now, when tracked, onPointerSignal forwards the wheel to the app as mouse button
four (up) / five (down) presses (proportional for mouse notches, accumulated
fractions for trackpad; Shift bypasses so Shift+wheel stays local). The inner
Scrollable is set to NeverScrollableScrollPhysics under mouse tracking so the two
don't fight over the pointer signal (which was killing the app's internal scroll).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
(cherry picked from commit a987855)
PointerScrollEvent only covers the mouse wheel and macOS's synthesized
trackpad scroll; two-finger trackpad on macOS frequently arrives as pan/zoom
gestures instead, which weren't forwarded, so internal TUI scroll did nothing
on the trackpad. Handle onPointerPanZoomStart/Update as well, routing the pan
delta through the same wheel-forward path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jacobaraujo7

Copy link
Copy Markdown
Contributor Author

@elias8 This is a critical bug in Windows.

Fixes the analyze/format CI check on this branch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@elias8

elias8 commented Aug 14, 2026

Copy link
Copy Markdown
Owner

Superseded by #143.

@elias8 elias8 closed this Aug 14, 2026
elias8 added a commit that referenced this pull request Aug 14, 2026
Separate terminal-session behavior from Flutter view state so
`TerminalController` owns libghostty state, geometry, selection, and
backend callbacks while `TerminalView` owns focus, text input,
scrolling, gestures, and rendering lifecycle.

- Keep `TerminalController` as an abstract contract for
application-level test doubles; move focus and soft-keyboard control to
`TerminalView`, make callbacks setter-only, stop exporting
`KeyboardState` and `TerminalScrollPosition`, and reject concurrent view
attachments.
- Route measured geometry through one controller-owned transaction, emit
in-band resize output before backend `onResize`, and keep terminal,
mouse, and selection geometry synchronized.
- Harden input and lifecycle handling across AltGr, IME newline/deletion
pairing, lock modifiers, mouse and stylus button transitions, gesture
ownership, controller swaps, and font-data changes, with focused
coverage for each behavior.

Supersedes #119
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants