Skip to content

feat(apple): admit two-finger gestures on physical iOS devices - #3838

Merged
thymikee merged 2 commits into
callstack:mainfrom
camchis:feat/ios-device-multi-touch
Oct 20, 2026
Merged

thymikee merged 2 commits into
callstack:mainfrom
camchis:feat/ios-device-multi-touch

Conversation

@camchis

@camchis camchis commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Allow pinch, rotate, transform and two-finger pan on physical iOS/iPadOS through the Apple runner. WebDriver iOS remains unsupported. Updates admission, tests, help and documentation: 16 files. Refs #582.

Validation

Retested unmodified e8445822fe66329619e26e3b9ff44b6ad0682548 on 2026-10-19: clean checkout, freshly rebuilt CLI, isolated daemon/session, no axis patch. Device: physical iPhone 12 (iPhone13,2), iOS 27.0.1 (24A446), Xcode 26.6 (17F113), wired CoreDevice; fiddl’s Loose strings open.

From that checkout, with $UDID selecting the test phone:

ad() { node bin/agent-device.mjs "$@" --platform ios --udid "$UDID" --session pr3838 --state-dir /private/tmp/ad-reverify-3838-state --json; }
ad gesture pinch 2.0 195 420
ad gesture rotate 30 195 420
ad gesture pan 195 420 60 0 500 --pointer-count 2
ad gesture transform 195 420 20 0 1.2 15 500

All four exited 0, returned success: true, pointerCount: 2, and runner gesture start/end timestamps. Responses, respectively:

  • Pinched to scale 2
  • Rotated gesture 30 degrees
  • Panned (195, 420) by (60, 0)
  • Requested transform gesture by (20, 0), scale 1.2, rotate 15 degrees

Previously recorded before, 507ef237, same pinch: UNSUPPORTED_OPERATION: gesture pinch is not supported on physical iOS devices.

pnpm check:affected --run --head 4ca831f3: passed, Node 22.20, exactCommit=true; GitHub-only/manual lanes skipped. Node 24 symlink-test failures also reproduce on base. The device runs above are at e8445822; 4ca831f3 only changes a refusal message and its test.

This replaces the earlier patched-tree evidence. It proves device dispatch/completion, not independent per-finger app telemetry. No iPad or gesture-lab run. Private XCTest API and default vertical finger geometry remain.

View guided diff

@thymikee

Copy link
Copy Markdown
Member

The code looks right for the two-finger admission change, and the one reported check passes. Before merge, the device evidence needs to be tied to a source SHA.

The only device run in the PR body is not tied to a SHA ("the head before review fixes"), and it ran on a tree with a local pinch-axis change that this PR does not contain. The device verification guide asks for the source SHA, and the PR guide asks to keep evidence attributed to its SHA. The PR is one squashed commit, so nobody can check that the delta from the tested tree to e844582 is messages-only. Only pinch ran. Rotate, transform and two-finger pan did not. So the admission flip at e844582 has no live proof, and it may not behave as shown with the shipped vertical finger geometry. Could you run unmodified e844582 (no axis patch) on a physical iPhone, with gesture pinch 2.0 <x> <y> and one of gesture rotate 30 <x> <y> or a two-finger gesture pan? Please record the SHA, device, commands, exit status and the success response (for example "Pinched to scale 2" instead of UNSUPPORTED_OPERATION), and keep the 507ef23 refusal line as the before.

Not blocking, and you can take or leave these: WebDriver iOS now refuses with "gesture pinch is not supported on ios" using the raw lowercase OS name, where the old message said "physical iOS devices", so mapping ios and ipados through APPLE_OS_DISPLAY_NAMES in gestureRefusalSubject would fix it; the Android TV, tvOS and macOS hints say gestures are supported on iOS and iPadOS while WebDriver iOS still refuses; and appleMultiTouchGestureFact and assertAppleMultiTouchSupported each encode the ios/ipados rule, so one shared predicate could serve both.

I did not run tests or devices, and I did not inspect Limrun or WebDriver live behavior, only the fact cells.

@camchis

camchis commented Oct 19, 2026

Copy link
Copy Markdown
Contributor Author

Thanks. I reran on unmodified e8445822 (no axis patch) on a physical iPhone 12 (iOS 27.0.1): pinch, rotate, two-finger pan and transform all exit 0 with success: true and pointerCount: 2. The commands, responses and the 507ef237 refusal line are in the PR body now. As you noted, only dispatch and completion are proven, not per-finger app effects.

I took one of the non-blocking items in 4ca831f3: WebDriver iOS and iPadOS refusals now say "not supported on iOS" and "iPadOS" (via APPLE_OS_DISPLAY_NAMES) instead of the lowercase OS name. A new test case covers iPadOS. check:affected --run --head 4ca831f3 passes on Node 22.20 with exactCommit=true.

I left the other two for a follow-up: the shared ios/ipados predicate for appleMultiTouchGestureFact and assertAppleMultiTouchSupported, and the Android TV / tvOS / macOS hints that say "supported on iOS and iPadOS" while WebDriver iOS still refuses. I'm happy to fold either in here if you prefer.

@thymikee

Copy link
Copy Markdown
Member

Commit 4ca831f fixes what the earlier review at e844582 was waiting on: the device evidence now covers the head. The physical iPhone 12 runs at e844582 are author-reported, and they still apply because the change since then only edits refusal wording for refused cells. The runs show dispatch and completion only, not per-finger app effects, and there was no iPad run, as you say. I did not inspect WebDriver or Limrun live behavior, only the fact cells. The one reported check passes, and there are no conflicts. Not blocking: the OS disjunction at https://github.com/callstack/agent-device/blob/4ca831f/packages/contracts/src/gesture-admission.ts#L61 lists every Apple OS except watchOS, so it reads like a selective policy but is really the display-name table minus watchOS. You could write return appleOs === 'watchos' ? undefined : APPLE_OS_DISPLAY_NAMES[appleOs];, or drop the guard if watchOS should also get its display name. Take it or leave it.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Oct 20, 2026
@thymikee
thymikee merged commit 31e2e6b into callstack:main Oct 20, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants