Skip to content

Mobile: start the iOS keyboard-dismissing drag clear of controls - #557

Merged
kblok merged 1 commit into
mainfrom
mobile-keyboard-drag-clear-of-controls
Oct 21, 2026
Merged

kblok merged 1 commit into
mainfrom
mobile-keyboard-drag-clear-of-controls

Conversation

@kblok

@kblok kblok commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

On an iPhone, Device.DismissKeyboardAsync() dragged from the exact centre of the screen. That point can sit on a checkbox or a button, and a horizontal drag does not scroll, so the control kept the touch and toggled. The drag now starts at the point nearest the centre that no control covers, inside a scroll view when the screen has one. A screen with no such point above the keyboard fails with UNSUPPORTED_CAPABILITY before any drag.

Ports upstream 787a5d5 (tester-army/e2e#1305): Keyboard.KeyboardDragStart is keyboardDragStart (keyboard.ts), and DeviceSession.KeyboardTop is keyboardTop. SnapshotProjection.ScreenKinds and NormalizeKind are now internal, as upstream exports SCREEN_KINDS. RawSnapshot reads the keyboard frame.

Five upstream its are ported in DeviceFixtureDismissingAKeyboardThatHasNoDismissKeyTests (one renamed, as upstream). Skipped: 'dismissing the keyboard over choice controls leaves them as they were', which needs the mobile benchmark app the port lacks. No .NET-only symbols beyond the Keyboard class name (C# has no free functions) and RawSnapshot.KeyboardFrame. Updated COMPATIBILITY.md and skills/e2e-dotnet/references/mobile.md.

Closes #552

🤖 Generated with Claude Code

https://claude.ai/code/session_01K5H3k1uaErAVw3kQv8fKro

Summary by CodeRabbit

  • Improvements
    • Improved keyboard dismissal gestures by selecting safer starting points that avoid controls and respect scrollable areas.
    • Keyboard dismissal now uses the measured keyboard position when available and reports an unsupported capability when no keyboard is present or dismissal cannot be performed.
  • Documentation
    • Added guidance on keyboard dismissal behavior, platform-specific fallbacks, safe gesture positioning, and failure conditions.

@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: hardkoded/e2e-dotnet/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: ae5617af-eb37-43cd-a855-1a6c7cc26de8
📥 Commits

Reviewing files that changed from the base of the PR and between 7f849a2 and 3c00a16.

📒 Files selected for processing: 7
  • COMPATIBILITY.md
  • skills/e2e-dotnet/references/mobile.md
  • src/E2E.Mobile/DeviceSession.Screen.cs
  • src/E2E.Mobile/DeviceSession.cs
  • src/E2E.Mobile/Keyboard.cs
  • src/E2E.Mobile/SnapshotProjection.cs
  • tests/E2E.Mobile.Tests/Engine/DeviceFixtureDismissingAKeyboardThatHasNoDismissKeyTests.cs

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 6 remain after this review.

📝 Walkthrough

The iOS keyboard-dismissal path now reads keyboard-frame geometry, selects a safe drag start above the keyboard while avoiding controls, and attempts horizontal then vertical gestures with keyboard rechecks. It reports UNSUPPORTED_CAPABILITY when no safe start exists or the keyboard remains. Tests and documentation cover the behavior.

Changes: iOS keyboard dismissal

Layer / File(s) Summary
Keyboard geometry and projected screen data
src/E2E.Mobile/DeviceSession.cs, src/E2E.Mobile/SnapshotProjection.cs
RawSnapshot now parses an optional keyboard frame. SnapshotProjection exposes screen-kind helpers to the assembly.
Safe drag-point selection and tests
src/E2E.Mobile/Keyboard.cs, tests/E2E.Mobile.Tests/Engine/DeviceFixtureDismissingAKeyboardThatHasNoDismissKeyTests.cs
Keyboard selects a safe point above the keyboard, avoids controls, and prefers scroll-view bounds when present. Tests cover safe-point selection and dismissal behavior.
Gesture orchestration and documented behavior
src/E2E.Mobile/DeviceSession.Screen.cs, skills/e2e-dotnet/references/mobile.md, COMPATIBILITY.md
DeviceSession attempts horizontal and vertical drags from a safe point, rechecking keyboard presence after each. It reports unsupported cases. The documentation describes platform behavior and alternatives.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant DeviceSession
  participant RawSnapshot
  participant Keyboard
  DeviceSession->>RawSnapshot: Read keyboard frame
  RawSnapshot-->>DeviceSession: Return optional KeyboardFrame
  DeviceSession->>Keyboard: Select drag start from projected snapshot and keyboard top
  Keyboard-->>DeviceSession: Return safe point or null
  DeviceSession->>DeviceSession: Attempt horizontal and vertical drags and recheck keyboard
Loading
Merge Risk: ⚪ Minimal · up to 3c00a

The changed keyboard-dismissal flow is mergeable after normal checks. A very narrow scroll region could be missed when choosing a drag start, but no material failure is established.

Security architecture risk: 🔵 Low · up to 3c00a

The change reduces accidental interaction with visible controls without adding device privileges or changing the public API. Remaining uncertainty concerns real-device geometry compatibility and concurrent screen changes; control avoidance remains a best-effort guarantee.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The affected outcome is touch input within the existing device session's reachable UI. The changed code chooses coordinates but continues through the existing command client, session identity, lease metadata, and configured endpoint authentication; it does not add authority over another device or tenant.

Security Findings and Attack Paths

  • inferred — Application-influenced accessibility content and device-reported geometry affect the selected touch origin. Misleading or incomplete content can therefore defeat the avoidance heuristic, but the base already issued gestures without control exclusion. The inspected comparison does not establish a new privilege boundary bypass or materially increased attacker reach.

Trust Boundaries and Controls

  • observed — RawSnapshot accepts a keyboard frame only when all four components are numeric. KeyboardTop uses the reported Y coordinate directly for visible or derived keyboard facts, otherwise falling back to keyboard-node geometry. Fixtures demonstrate the expected coordinate convention, but do not independently validate the real producer's contract.

Resilience and Maintainability Implications

  • inferred — Capture and gesture dispatch are separate operations without session-level serialization in the inspected path. Concurrent actions can invalidate a selected origin, and cancellation cannot undo input already delivered. These are pre-existing limitations, not established PR regressions; recomputing the second origin improves sequential behavior without making the transition atomic.
Pre-merge checks: Passed 4
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: starting the iOS keyboard-dismissal drag away from controls.
Linked Issues check Passed Issue #552 has coding requirements. Keyboard.KeyboardDragStart selects the nearest uncovered point, restricts candidates to scroll views when present, excludes controls, and returns no point when al…
Out of Scope Changes check Passed The changed files support issue #552. RawSnapshot.KeyboardFrame supplies keyboard position data. SnapshotProjection exposes helper members needed by Keyboard. The new helper, dismissal logic, te…
Full details: Linked Issues check

Explanation

Issue #552 has coding requirements. Keyboard.KeyboardDragStart selects the nearest uncovered point, restricts candidates to scroll views when present, excludes controls, and returns no point when all candidates are covered. DeviceSession uses the selected point, retries horizontal and vertical drags, rechecks the keyboard, and reports UNSUPPORTED_CAPABILITY before a drag when no point exists. The test fixture covers the requested drag, scroll-view, plain-text, flattened-tree, and all-controls cases. The helper and the requested documentation updates are present.

Full details: Out of Scope Changes check

Explanation

The changed files support issue #552. RawSnapshot.KeyboardFrame supplies keyboard position data. SnapshotProjection exposes helper members needed by Keyboard. The new helper, dismissal logic, tests, compatibility entry, and mobile reference documentation directly support the requested behavior. The skipped choice-controls test matches the issue's stated benchmark-app exclusion. No unrelated change is demonstrated.

✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@kblok
kblok merged commit 03df5db into main Oct 21, 2026
2 checks passed
@kblok
kblok deleted the mobile-keyboard-drag-clear-of-controls branch October 21, 2026 17:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Mobile: start the iOS keyboard-dismissing drag clear of controls (upstream #1305)

1 participant