diff options
Diffstat (limited to 'src/macos/Sources')
| -rw-r--r-- | src/macos/Sources/PardesView.swift | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/src/macos/Sources/PardesView.swift b/src/macos/Sources/PardesView.swift index 5df1fd73..ba3677e7 100644 --- a/src/macos/Sources/PardesView.swift +++ b/src/macos/Sources/PardesView.swift @@ -1842,6 +1842,20 @@ final class PardesView: NSView { fed() } + /// Fingers down and fingers up on a precise scroll. Entry points of their + /// own for the same reason rotateEnd is one: NSEvent phases have no public + /// constructor, and a fling nothing can synthesize is a fling nothing can + /// assert. + func scrollBegin() { + pardes_scroll_begin() + fed() + } + + func scrollEnd() { + pardes_scroll_end() + fed() + } + func rotate(degrees: CGFloat) { guard degrees != 0 else { return } pardes_rotate(Float(degrees)) @@ -2086,12 +2100,32 @@ final class PardesView: NSView { return } if event.hasPreciseScrollingDeltas { + // Phases first: a finger back on the pad has to catch a coast before + // its own travel is spent, or the first millimetre of the new swipe + // would be added to the old fling instead of replacing it. + // + // Momentum events carry `phase == .none` and a momentumPhase + // instead, so neither branch here fires for them — they are just + // more travel, and libpardes lets them take the gesture over. That + // is deliberate: AppKit's fling is the one the rest of the system + // uses, and a second fling of our own underneath it would scroll + // everything at double speed. `pardes_scroll_end` exists for the + // devices AppKit does NOT fling for. + if event.phase == .began { scrollBegin() } // The core scrolls a cell at a time, so libpardes accumulates the // sub-cell travel and spends it as wheel presses — which is why the // cell has to travel with the delta. scroll(rows: -event.scrollingDeltaY / cellHeight, cols: -event.scrollingDeltaX / cellWidth, at: at) + switch event.phase { + case .ended: scrollEnd() + // A gesture the system took away should not be thrown. scrollBegin + // is the catching half of the pair — coast stopped, bank and + // velocity cleared — which is exactly what a cancellation means. + case .cancelled: scrollBegin() + default: break + } } else { // AppKit's sign is the opposite of the DOM's: positive deltaY means the // content moved down, which is a scroll back through history. |
