Repository navigation
Conversation
An iPad window that does not fill the screen reports its own screen box while its subtree arrives anchored at its own top-left. The capture published a screen-space viewport around window-relative rects: the fold clipped content to (w - x) x (h - y), a rect named no screenshot position, and a synthesized tap landed at the point minus the window origin. SnapshotContentTranslation reads the one vector from a carrier's (0,0)-anchored copy of the viewport box to the viewport itself, and SnapshotGeometrySpace.normalized translates the subtree it declares in the same pass that turns a quarter-turned subtree. CoordinateSpaceRotation now turns axes only; the digitizer origin stays where the display put it. Replayed from contracts/fixtures/window-coordinate-space.json in both languages. Refs #3899
The refusal wording belongs to the snapshot-route failure policy, not to this fix. Refs #3899
#3899) XCUIElement.frame reports a placed window's content in screen space, but XCUIElementSnapshot.frame reports it in the window's own content space, so the text-input probe saw two spaces on an iPad Windowed Apps window and refused a fill whose point was on the screen. The probe, the focus tap, and the typing reader now read the same SnapshotContentTranslation vector the capture reads, from the two live boxes that name it. Refs #3899
…ble on a placed window [ #3899 ]
Size Report
Startup median (7 runs, lower is better):
|
Device evidence (#3899 conditions 1–7)Device: iPad Pro 11-inch (M5, 12GB), iOS 27.0, simulator "Apex iPad Windowed 2". Calendar window at (324,307,386x682), later moved by drag to (175,405). Head
Validation at head: Screenshots (windowed capture, moved window, opened sheet, typed field) were held on the verification host at |
|
Follow-up for the #3914 owner (not blocking this PR): the bridge-refusal warning in |
|
I found two problems at ec7aecb that need a fix before merge. CI is green (16/16 checks), but PR CI does not run the on-device runner unit lane, so the fill read-count pin has not run at this head. The two device results listed below are also still missing. The readiness retap still uses an unconverted frame. The live window lookup is also expensive. Could the first two items share one fix? Keep the capture rule and the Not blocking, and fine to take or leave: (1) in The windowed-iPad, moved-window and full-screen parity results come from the author's comment only, and I could not run a device or the latency pin. Landscape under Windowed Apps, Stage Manager, and a placed window partly off screen remain unmeasured. #3918 (open) adds a windowed back-fallback screen point that lands correctly only with this PR's origin-free Before merge, route the readiness retap through one screen-frame owner on |
* origin/main: fix(android): bound the dumpsys reads behind dialog and foreground checks (#3936) feat(android): detect Fire OS devices as Android TV targets and document Fire TV support (#3923) docs(macos): document Electron/Chromium app automation through the accessibility tree (#3932) test(capture-kit): encode solid test PNGs unfiltered to stay inside the unit budget (#3933) fix: guard bounded lifecycle and claim recovery (#3911) fix(ios): clear a long text value wherever the caret lands (#3908) fix(snapshot): stop iOS 27 floating-bar containers from covering content (#3912) ci: cache and bound the Linux desktop dependency install (#3919)
…frame (#3899) The readiness retap re-read the input as a bare XCUIElementSnapshot and tapped its raw center through tapAt, which takes screen points, so on a windowed iPad the retap landed outside the window. The live window lookup also ran whole-app queries four to six times per fill on every iOS device. Every snapshot frame that becomes a dispatched point now passes through the one content translation, held on ResolvedTextEntryInput.frameOnScreen. The vector is read once per command and stored on TextEntryTarget.contentTranslation; the probe matching, focus tap, refresh point, caret tap and readiness retap all read that one property. The threaded translation: parameters and the per-read lookups are gone, and the once-per-command keyboard read in the typing command is reverted to the base behavior with the retap fixed.
…sis (#3899) Amends ADR 0004 to name ResolvedTextEntryInput as the probe-side owner of the content vector, cites the measured Add-button rect at (659,321), records that the runner republishes a windowed capture in screen space where the bridge-refusal warning said it was offset, and names screen space plus the app.frame origin assumption in the interactionCoordinate comment.
… offset (#3899) The vector on the target replaces the offset arithmetic in textEntryRefreshPoint, which read the snapshot frame and added the vector itself. One owner now: ResolvedTextEntryInput.frameOnScreen. The comments that restated the capture's rule at every call site are cut to the constraint the code cannot show. SnapshotCoordinateSpace.swift ships in the npm package without comment stripping, so its prose lives in ADR 0004 and the golden table instead; the same rule text is removed from the TypeScript decoder's foot note.
|
Replies point-by-point to the 2026-10-22T23:30 review. Head Blocking1. Readiness retap used an unconverted frame. Done. 2. Live window lookup was expensive. Done as proposed. The vector is read once where The shared fix. Done: Non-blocking
Evidence (all at
|
| fill ms | type ms | |
|---|---|---|
| base | 3518, 3721, 3685, 3531, 3568 (median 3568) | 970, 949, 967, 966, 967 (median 967) |
| head | 3571, 3532, 3621, 3593, 3525 (median 3571) | 943, 937, 943, 960, 955 (median 943) |
fill +3 ms median (noise), type −24 ms. No regression against the #3881/#3906/#3909 read work.
Windowed iPad — iPad Pro 11-inch (M5), iOS 27.0, Windowed Apps, agent-device 70f6faa552: a shrunken test-app window publishes its root at (230,305,375,486) in screen space; a coordinate press at the + button's published rect (554,319,37,36) opened the New Event sheet (the #3899 failure shape, now landing); fill into the field at its published rect verified "final text", fill replaced, type "!" appended with route xctest-element and read back "final text!" — the focus tap and refresh point inside a placed window land in the field. The retap branch itself fires only when focus confirmation times out and could not be forced on-device; the translated-snapshot unit test above is the requested alternative proof. One caveat, not a regression: a bare type after re-pressing the field (no fill, no replacement mode) returned TEXT_INPUT_NOT_FOCUSED on the RN field — the base runner at a9fc9a19 reproduces this identically in the same window, so it is the pre-existing synthesized-first-responder route, unchanged by this PR.
CI at 70f6faa552: 14 pass, 2 skip (deferred lanes), 0 fail.
Diff
git diff --stat origin/main...HEAD: 20 files, +890 / −132 (reviewed head ec7aecbf92: 11 files, +698/−74 on its own base). Production code-only lines (runner UITests sources + snapshot-presentation/Sources + the TS decoder, comments/blank excluded) went 245 → 418 vs the respective merge-bases. That growth is the requested design itself: frameOnScreen, the vector stored on the target and the read, threaded through the seven probe/resolve functions that previously re-derived it at call sites, the split retapAt, and the five command-entry reads. Files that grew vs the reviewed head (numstat vs ec7aecbf92, rebased-comparable):
RunnerTests+TextEntry.swift: +22/−6 → +73/−18 — vector on both types,frameOnScreen, resolve/read paths carry itRunnerTests+TextInputProbe.swift: +35/−1 → +78/−16 — vector parameter on the probe functions, candidate matching onframeOnScreen, containedliveContentTranslationRunnerTests+TextEntryFocus.swift: +45/−10 → +63/−18 — one vector read at the stabilize entry, focus tap/refresh point viaframeOnScreenRunnerTests+TextEntryReadiness.swift: new → +32/−6 — the blocking retap fixRunnerTests+CommandExecution.swift: new → +7/−1;RunnerTests+Interaction.swift: new → +14/−7 (probe vector + the item-5 comment);RunnerTests+TypeExecution.swift: new → +4/−1 (the type route's single read)UnitTests/RunnerTests+TextEntryReadinessTests.swift: new +57 (retap unit test); probe/latency/coordinate unit tests: signature updates only
Files that shrank or are gone: SnapshotCoordinateSpace.swift +88/−24 → +77/−24 and window-coordinate-space.ts +35/−10 → +24/−10 (prose moved to ADR 0004 and the golden table), CoordinateSpaceTests.swift +162/−6 → +156/−6, RunnerTests+TextTyping.swift +30/−0 → 0 (item 2 reverted). ADR 0004 +43/−0 → +48/−4; snapshot-route.ts/test +1/−1 each.
|
At 70f6faa, the earlier blocking items from the first review (#3920 (comment)) are fixed, and I found no new blocking problems in the code. CI shows 16 checks with none failing, and there are no conflicts. Before merge, the on-device evidence still needs to be confirmed, because PR CI does not run the on-device runner unit lane that exercises the changed Swift text-entry paths. Green CI therefore says nothing about the retap test or the read-count pin. The windowed-iPad run (coordinate press, fill, type inside a placed window), the iPhone Not blocking, and you can take or leave these: Would it be simpler to keep this owner but let it carry the #3060 rule too, with a non-defaulted vector that is known, none or unknown, so a failed window read cannot look like full screen? |
Summary
An iPad window that does not fill the screen (Windowed Apps, Stage Manager) reported
(0,0)-anchored subtree frames while its viewport was the window's screen box: captures clipped, rects named no screenshot position, taps landed at point minus window origin. The capture now publishes screen space through one rule,SnapshotContentTranslation.offset, in the sameSnapshotGeometrySpace.normalizedpass that turns quarter-turned subtrees; dispatch and probe-path snapshot reads follow the ADR 0004 amendment. The probe-side screen frame has one owner,ResolvedTextEntryInput.frameOnScreen: the content vector is read once per command, stored on the target and each read it produces, and the readiness retap dispatches through it. Full-screen iPad, iPhone, and ADR 0025 foldable panels read no vector and publish unchanged. Closes #3899.Validation
Head
70f6faa552:pnpm check:affected --run --headpassed all runnable checks;swift test25/25; runner unit lane on iPhone 17 (iOS 27.0): focused 119-test lane 0 failures,RunnerTests+TextEntryLatencyTests6/6 with the fill read-count pin unchanged at 17, retap translated-snapshot unit test passed. Fill/type timing on the same simulator, basea9fc9a19vs head, 5 samples each: fill 3568 vs 3571 ms median, type 967 vs 943 ms. Windowed iPad (iPad Pro 11-inch M5, iOS 27.0): coordinate press on a placed window's published button rect opened the sheet;fill, replacement, andtypeverified by read-back inside the window. Point-by-point review round with full numbers: #3920 (comment)Device: iPad Pro 11-inch (M5), iOS 27.0, Calendar, window at (324,307,386x682), then moved. Base
b08b5e796avs head, same window: base viewport 211x277 with window-relative frames; head viewport 386x682, rects at screen positions.snapshot -i --jsonin three grid scroll states: success, noregular-node-outside-cumulative-clip.Todaypresent.Addat (659,321); (509,419) after the move).press @Addopened the sheet,@Inboxopened the inbox,@Wed 21selected (verified by[selected]+ header).press 678 339/press 528 437(moved) opened the sheet.fill,type, caret re-fill verified by read-back;gesture panaccepted.press @Search→ (721,54) focused search on both.Landscape windowed is pinned by fixture arithmetic, not measured (ADR 0004).
Condition-by-condition device evidence: #3920 (comment)