Repository navigation
feat(core): a pan takes wheel and trackpad scrolling, and a pinch a ctrl-wheel (spec:AST-094 FR43) - #8676
feat(core): a pan takes wheel and trackpad scrolling, and a pinch a ctrl-wheel (spec:AST-094 FR43)#8676vjeux wants to merge 1755 commits into
Conversation
The note's reword joined its next sentence onto one long line; it now wraps like the rest of the file. No code change.
cixzhang's meta#8589 keeps the host's touchend passive, and its contextmenu and click listeners off, until a claimer is attached (syncClaimingListeners). Ported onto this pull request's input stream with no change to what it does: install() subscribes the touchend passive, and syncClaimingListeners swaps it for a cancelling subscription and adds the contextmenu and click subscriptions while a claimer is attached. A group press brings its own click subscription only while the host has none, and the host's takes it over. Her watcher test reads those listeners on the window, where the input stream registers them; her new group test (a finger, then a mouse, under a fine pointer) sits before the detach test. The test file and the bare fixture import both her ScreenEdgePanGestureRecognizer and this layer's selection lock from utils.
Here the click guard (utils/clickGuard.ts) owns clicks, so cixzhang's meta#8589 syncClaimingListeners, ported at meta#8356, switches only the touchend's cancelability and the contextmenu subscription; the group press subscribes no click of its own. Her meta#8072 5c59af1 (a finger on an action group under a fine pointer reaches its recognizers) arms the click guard where it armed the swallower. Her watcher test reads the touchend and the contextmenu on the window, and no click listener: the guard's comes only once a gesture acts.
… the lift, under real touch input spec:AST-094 FR20's "follows the scroll to the lift" had only a jsdom test with a synthetic takeover; the FR18-FR22 verification row asks for real touch input. In Chromium with injected touches, a vertical drag on a list a watcher pan is attached to scrolls the list natively, no touchmove is cancelled, and the watcher goes from began to ended at the lift.
… at the edge stays the page's spec:AST-094 FR10: two fingers before a claim are the page's pinch. The scroll-edge hold (DEC-18) counted any finger, so with two fingers down it cancelled the pinch's moves before any drag was claimed. It now holds only while a single finger is down. The new two-finger test fails on the previous head. Co-authored-by: Christopher Chedeau <vjeuxx@gmail.com>
… other native-scroll cases
… the gesture watcher
… is down off the sheet (spec:AST-094 FR10) The lone-finger hold counts only the fingers the pan tracks, so a second finger on plain page content left the sheet's finger held, and the moves of a pinch across the sheet's edge were cancelled. This test fails until the host counts every finger on the screen.
meta#8665's review fixes: an armed press under a fine pointer brings the claiming listeners, keeps a kept press's finger and goes when the page hides; a press claimed at its own pointerdown keeps the page's selection; FR41 says what a claimed drag does with the selection; meta#8360's input-stream notes. The merge is clean.
There was a problem hiding this comment.
This pull request is on hold for an engineering owner's decision on two readings: spec:AST-094 FR43 does not say when a wheel gesture ends or what its release carries (here, 100 ms after the last wheel, with a trackpad's speed and macOS momentum kept and a mouse wheel's notches released still), and the carried FR41 rewrite lets a claimed mouse or pen drag take no new text selection and clear the page's, which FR41 as it stands rules out for a mouse. An engineering owner records that decision by commenting /approve-spec <full head SHA> on this pull request, and the author may record it too, as an engineering owner. Whatever the decision, these changes are needed:
- Reduce the diff to this change: 28,409 of its 30,450 authored lines are the open #8665 stack (land it with #8666 and #8535 first, or retarget onto #8665), and the
astryxStylexfix belongs in its own pull request. - Give a notch gesture's release zero velocity explicitly: a press within 40 ms of the last notch now releases it with the notches' speed, against the gestures README.
[Automated review]
This pull request now sits on meta#8665, so a stack carrying it and meta#8665's other dependants (meta#8676) needs no second GestureHost resolution. Two hunks in GestureHost.ts's pointerdown, both this pull request's: - the second-finger check where fingers come from pointer events stays, followed by meta#8665's rule that a right click, a pen's barrel button or a macOS ctrl-click starts no press; - the check that runs again once the new finger is delivered stays, followed by meta#8665's selection lock call, which no longer takes the window.
This pull request now sits on meta#8665, so a stack carrying it and meta#8665's other dependants (meta#8676) needs no second GestureHost resolution. Three hunks in GestureHost.ts, resolved in this pull request's own code: - the element's touchend listener for a claimed lift stays; meta#8665's removal of the fine-pointer action group's own pointerdown listener stands, in the listener sync and at detach, since meta#8665's host attaches for every pointer; - a finger's target gets a blocking listener only for an enabled participant, as here, and for a kept press under any pointer, as in meta#8665.
…the wheel's and the pen lift's No behavior change. The touchend listener's registration field, its sync and its removal now come before the touchmove listener's, and the claimed lift is recorded before the pointer is forgotten, so this pull request and its siblings on meta#8665 (meta#8676's wheel listener, meta#8670's pen lift record) no longer edit the same lines of GestureHost.ts, and a stack that carries them together merges without a resolution.
… scrollers) into uikit/c21-wheel-fr43
…st's clock reads Reported against a sheet's tests on this pull request's head: three quick 100 px notches at the content's top released at 6,250 px/s, so the sheet was thrown away. The host schedules a wheel gesture's end on its clock, while the arena reads the wheels' own timestamps, which need not share the clock's base (the sheet's tests fake the page's clock). The case fails on this head: the release velocity is 6,250, not 0.
…END_MS after its last wheel The host stamped every wheel gesture's release at the earlier of WHEEL_END_MS after its last wheel and the host's clock when it ended, so a release is never later than an input that ends it (FR16). On its own timer, though, the clock need not share the wheels' time base: where the page's clock reads behind the wheels' timestamps, the release collapsed onto the last notch and three quick notches threw a sheet away at 6,250 px/s. A gesture that ends on its own (its timer, a taker leaving, a detach) is now stamped WHEEL_END_MS after its last wheel, as before that change; only an input that ends it sooner caps the stamp, with its own time on the wheels' base (spec:AST-094 FR43).
meta#8676 makes `locksSelectionFor` take the pointer kind alone: a finger or a pen locks the selection under any primary pointer, a mouse never does (spec:AST-094 FR41, spec:AST-017 FR59). The pager still passed the view as a second argument, so the merged tree failed to type-check (TS2554 at usePager.ts:976) and the build stopped there. The pager's catch now asks with the kind that caught the settle. A test pins the mouse case beside the finger's: a mouse press stops a settle after the catch delay, as a finger's does (FR43), and the text stays selectable throughout.
There was a problem hiding this comment.
This pull request is on hold for an engineering owner's decision on two readings: spec:AST-094 FR43 does not say when a wheel gesture ends or what its release carries (here, 100 ms after the last wheel, with a trackpad's speed and macOS momentum kept and a mouse wheel's notches released still), and the carried FR41 text lets a claimed mouse or pen drag take no new text selection and clear the page's, which FR41 as it stands rules out for a mouse. An engineering owner records that decision by commenting /approve-spec <full head SHA> on this pull request, and the author may record it too, as an engineering owner. Whatever the decision, these changes are needed:
- Reduce the diff to this change: 28,409 of its 30,490 authored lines are the open #8665 stack (land it with #8666 and #8535 first, or retarget onto #8665), and the
astryxStylexfix belongs in its own pull request. - Give a notch gesture's release zero velocity explicitly: a press within 40 ms of the last notch releases it with the notches' speed, against the gestures README.
- Date a release that no input ends no later than the current wheel or the last notch: a detached pan's notch release is now stamped 100 ms ahead, which moves the next press's clock.
[Automated review]
| : endTime == null | ||
| ? end |
There was a problem hiding this comment.
When no input ends a notch gesture, this dates its release WHEEL_END_MS after the last notch, but two callers reach endWheel() before that moment: the detach at lines 763-770 and the next wheel after every taker left (lines 1921-1928). arena.ended then moves the arena's clock to that future time (GestureArena.ts:949-953), so a press within the rest of those 100 ms is dated at the stamp and its long press fires up to 100 ms late, which spec:AST-094 FR16 rules out. Could those two paths end at the current wheel's time or at gesture.last instead, leaving last + WHEEL_END_MS to the timer?
Depends on #8665, with the web input drivers (#8666) merged in for the proofs until they land. Review only this pull request's change: vjeux/astryx@c6c02fc...f9e99b8 (the harness files are #8666's).
Why
On a laptop, a trackpad swipe or a mouse wheel over an Astryx pan, such as a row with swipe actions, never reaches it: the page scrolls instead. The approved gesture spec says "On the web, a pan also takes wheel and trackpad scrolling; a pinch takes a ctrl-wheel" (
spec:AST-094FR43).What led to it
#8665 made gestures attach for every pointer; this adds the web's scroll input, as iPadOS gives a
UIPanGestureRecognizera trackpad's scroll.Options and tradeoffs
wheel: each would repeat latching, scroller edges and notch handling.Why this choice
One host decides once per wheel gesture: a pan takes it only along its own axis and only after every scroller under the pointer has reached its edge, so a list inside a sheet still scrolls first. A gesture stays latched to the pan that took it, as a browser latches a scroller. A pan opts out with
allowedScrollTypes: []; the screen-edge pan and any watcher take none (FR43, FR20). A first wheel the page already prevented, or one that cannot be cancelled, stays the page's. Mouse-wheel notches release with no speed, never stamped after the press that ends them; a trackpad keeps its momentum. A wheel nobody takes is never prevented.How to check it
Evidence