cmux NEXT: a two-finger swipe over a browser page goes back or forward

Merged
TE
18d ago
+696-5

A two-finger horizontal swipe over a Chromium page in cmux NEXT now goes back or forward, as in Safari and Chrome. Before this, CEF tabs had no swipe. WebKit tabs already use WebKit's own swipe.

Stacked on #22268 (mouse buttons 4 and 5), which adds the shared NavigationTunables section. The diff here shows its commit until it lands.

How it works:

  • The page keeps what it would scroll. A local scroll monitor (CEFSwipeNavigation) sees each trackpad event before Chromium. When the gesture begins, and again once it has moved 6 pt mostly sideways, it asks the page (BrowserSwipeProbe):

    • whether the scroller under the fingers, or the document, can still move that way;
    • whether a script preventDefaulted a horizontal wheel in the last 600 ms (a carousel).

    Either answer keeps the gesture with the page. Only a swipe that starts at the scroll edge navigates.

  • The swipe: AppKit tracks it (trackSwipeEvent, .lockDirection). Letting go past AppKit's threshold calls goBack / goForward.

  • No history that way: the dampen threshold on that side is 0, so it rubber-bands and nothing happens.

  • The indicator: an accent pill (Palette.accentFill) with an arrow slides in from the left edge (Back) or the right edge (Forward) as the fingers move. It is at full strength once letting go would navigate, and at half strength when there is no page that way. It draws on the window's overlay host in the .pane layer, clipped to the page, because a Chromium page is a child window above the window's own views.

  • Gates: it runs only while macOS's "Swipe between pages" is on (NSEvent.isSwipeTrackingFromScrollEventsEnabled). Debug Settings > Back and Forward > browser.swipeNavigation is on by default and turns it off.

Out of scope:

  • Agent chats and internal pages. Inside a chat there is no page history (history.md 4.2b). Back leaves the chat through the tab's own history or the trail, which the side buttons (#22268) and Ctrl-- already reach. A swipe there would compete with horizontal scrolling in code blocks, and those pages have no scroll-edge answer yet.
  • WebKit pages already use allowsBackForwardNavigationGestures.

Changelog

Added: a two-finger swipe over a browser page goes back or forward when the page can't scroll that way.

Proof

Pending: a capture of the pill mid-swipe on a GUI runner (see Observed / Not run).

Observed / Not run

  • Observed: BrowserSwipeGestureTests (the gesture decisions, the probe parsing, the pill's frames) on CI.
  • Not run: a real trackpad swipe on a running build. AppKit's swipe tracking needs a real gesture, and no GUI runner has a trackpad. The double-navigation risk (Chromium's own history swiper, if this CEF build enables it) is not checked on hardware.

šŸ¤– Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

A two-finger horizontal swipe over a Chromium page in cmux NEXT now goes back or forward in the tab's history, as in Safari and Chrome. The page keeps any gesture it would scroll; only a swipe that starts at the scroll edge navigates.

  • A local scroll monitor probes the page for the scroller under the fingers and whether a script took horizontal wheels in the last 600 ms (a carousel), so carousels and wide tables keep their gestures. It walks same-origin frames under the fingers; a probe a page cannot read leaves the gesture to the page, as does a probe that answered late. overscroll-behavior-x on the document root opts a page out, as in Chrome; body's value does not propagate, so an anti-bounce rule there keeps swipes.
  • AppKit tracks the swipe with .lockDirection; an accent pill with an arrow slides in from the appropriate edge, at half strength when there is no page that way (the swipe rubber-bands instead).
  • Runs only while macOS's "Swipe between pages" is on and Debug Settings browser.swipeNavigation is enabled (default on). Agent chats and internal pages are out of scope; WebKit tabs already use WebKit's own swipe gestures.
  • The mouse side buttons ride along on this branch: buttons 4 and 5 walk the tab's history over a browser tab, else run Go Back and Go Forward; a remote desktop in control mode keeps them for its host, and a release follows the route its press chose.
  • Regenerating the cmux-next defaults drops the unused key.agentPane.searchFiles key.