summaryrefslogtreecommitdiff
path: root/test/macos_e2e.swift
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-16 12:18:01 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commit2109098400fa37d7b448f232c848a0411c318591 (patch)
tree90955d94035e689eb3c112d3b635be7b00036dff /test/macos_e2e.swift
parent556c5b50bbfd4a6aaae192377d7810f610fc7d9e (diff)
downloadpardes-2109098400fa37d7b448f232c848a0411c318591.tar.gz
pardes-2109098400fa37d7b448f232c848a0411c318591.zip
Give macOS scrolling momentum
A swipe that was still moving when the fingers lifted stopped dead. The dial next to it has thrown properly since pardes_rotate_end, and this is that same curve on the scroll accumulator: velocity sampled between events off the monotonic clock, weighted toward the newest sample because a flick is decided by how the hand was moving when it left, and a fling that ramps up from zero at the floor rather than switching on at it. A coast stops at the end of a document rather than spinning its remaining velocity against the edge, which is why spendScroll now reports whether the pane moved and why paneAt is public. Only a step that delivered a press can report an edge — the many steps between two rows cross nothing. Nothing suppresses AppKit's own momentum, and nothing needs to: its momentum events are ordinary pardes_scroll calls, every one of which cancels the coast before spending its travel, so on a real trackpad the system takes the gesture over about a frame after the lift and the tail it ends on is below the floor. This is the path for devices AppKit does not fling for — and the only one a script can reach, since NSEvent phases have no public constructor. momentum.snap asserts both halves, which is why it needs the long scrollback: a flick with no document left proves nothing. A slow swipe is byte-identical after the release; a hard one coasts twenty-four rows further on its own, and a finger back on the pad stops it there. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Diffstat (limited to 'test/macos_e2e.swift')
-rw-r--r--test/macos_e2e.swift25
1 files changed, 25 insertions, 0 deletions
diff --git a/test/macos_e2e.swift b/test/macos_e2e.swift
index fbfa0e3e..43627a7e 100644
--- a/test/macos_e2e.swift
+++ b/test/macos_e2e.swift
@@ -790,6 +790,12 @@ private final class Driver: PardesViewDelegate {
view.drop([path], at: cell)
pump()
+ // `scroll <rows> <col> <row> [cols] [gap_ms]`. The optional gap is a
+ // real sleep BEFORE the event and means what it does for `rotate`:
+ // libpardes measures the release speed off the monotonic clock between
+ // calls, so back-to-back script lines read as an impossibly fast swipe.
+ // Pacing them is the only way a script can say a swipe was SLOW, which
+ // is the half of the momentum contract a fling test cannot show.
case "scroll":
let view = try live()
let rows = try double(args, 0, "scroll rows")
@@ -799,9 +805,28 @@ private final class Driver: PardesViewDelegate {
// other suites' scroll commands do.
var cols = 0.0
if args.count > 3 { cols = try double(args, 3, "scroll cols") }
+ if args.count > 4 {
+ Thread.sleep(forTimeInterval: try double(args, 4, "scroll gap_ms") / 1000)
+ }
view.scroll(rows: CGFloat(rows), cols: CGFloat(cols), at: cell)
pump()
+ // Fingers down and fingers up. Their own commands for the reason
+ // rotate_end is one: the fling is decided by the RELEASE SPEED, and
+ // NSEvent phases have no public constructor, so these entry points are
+ // the only way the momentum path is reachable from a script at all.
+ // The coast is then spent by idle's display clock, one step per
+ // animation frame; ordinary pumps do not move it.
+ case "scroll_begin":
+ let view = try live()
+ view.scrollBegin()
+ pump()
+
+ case "scroll_end":
+ let view = try live()
+ view.scrollEnd()
+ pump()
+
case "wheel":
let view = try live()
let button = try mouseButton(try token(args, 0, "wheel button"))