From 38158ef4e891882c34beeffc1c046747004b4983 Mon Sep 17 00:00:00 2001 From: clover caruso Date: Mon, 12 Oct 2026 13:01:38 -0700 Subject: [PATCH] fix(ios): honor the ink recognizer lifecycle Forward every overridden touch callback and reset to UIKit before local filtering or state changes, and explicitly admit Pencil and direct touches. Keep the existing delegate preference checks and exclusive-touch policy. Refs #76 Assisted-by: gpt-6.1-sol --- apps/ios/Snowbound/CanvasView.swift | 1 + apps/ios/Snowbound/Ink.swift | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/apps/ios/Snowbound/CanvasView.swift b/apps/ios/Snowbound/CanvasView.swift index c85cba2e40acca347be39556b0b79de480accca3..3a8be64af32d951adb7e3d829d5b078cd9dae2ee 100644 --- a/apps/ios/Snowbound/CanvasView.swift +++ b/apps/ios/Snowbound/CanvasView.swift @@ -177,6 +177,7 @@ final class CanvasView: UIScrollView, UIScrollViewDelegate, UITextInput, UITextI addGestureRecognizer(recognizer) } // The Pencil draws; fingers, a trackpad and a mouse scroll and select. + ink.allowedTouchTypes = [UITouch.TouchType.pencil, .direct].map { NSNumber(value: $0.rawValue) } let hands = [UITouch.TouchType.direct, .indirectPointer].map { NSNumber(value: $0.rawValue) } let recognizers: [UIGestureRecognizer?] = [tap, doubleTap, grip, panGestureRecognizer, pinchGestureRecognizer] for recognizer in recognizers { diff --git a/apps/ios/Snowbound/Ink.swift b/apps/ios/Snowbound/Ink.swift index c7c1ca1fb3db21a5beb9c5d2b18efe0d1486aac7..456886bfbcea2a47a3ce6fdaefea78a639a0d2d4 100644 --- a/apps/ios/Snowbound/Ink.swift +++ b/apps/ios/Snowbound/Ink.swift @@ -68,6 +68,7 @@ final class InkGesture: UIGestureRecognizer { } override func touchesBegan(_ touches: Set, with event: UIEvent) { + super.touchesBegan(touches, with: event) for touch in touches { if tracked == nil { tracked = touch @@ -82,22 +83,26 @@ final class InkGesture: UIGestureRecognizer { } override func touchesMoved(_ touches: Set, with event: UIEvent) { + super.touchesMoved(touches, with: event) guard let tracked, touches.contains(tracked) else { return } points += (event.coalescedTouches(for: tracked) ?? [tracked]).map(sample) state = .changed } override func touchesEnded(_ touches: Set, with event: UIEvent) { + super.touchesEnded(touches, with: event) guard let tracked, touches.contains(tracked) else { return } points.append(sample(tracked)) state = .ended } override func touchesCancelled(_ touches: Set, with event: UIEvent) { + super.touchesCancelled(touches, with: event) state = .cancelled } override func reset() { + super.reset() tracked = nil points = [] } -- 2.54.0