Skip to content

Fix #5010: don't swallow UIPress events while editing a native text component#5013

Merged
shai-almog merged 3 commits into
masterfrom
fix-5010-presses-swallow-during-editing
May 23, 2026
Merged

Fix #5010: don't swallow UIPress events while editing a native text component#5013
shai-almog merged 3 commits into
masterfrom
fix-5010-presses-swallow-during-editing

Conversation

@shai-almog
Copy link
Copy Markdown
Collaborator

Summary

  • CodenameOne_GLViewController.m's pressesBegan: / pressesEnded: / pressesCancelled: treat every UIPress whose UIKey maps to a non-zero CN1 keycode as consumed. cn1MapUIKeyToKeyCode returns the unicode codepoint for any printable character, so every printable HW-keyboard keystroke was being silently swallowed once a CN1UITextField/CN1UITextView was up. UIKit's text-input pipeline never got the press, so no insertText: ever fired on the focused field. On iOS 26.x devices, where some on-screen keyboard interactions also surface as UIPress events on the responder chain, the same path also kills virtual-keyboard typing — the reporter's "cursor blinks but typing does nothing" symptom in Unresposive App when trying to type to input field #5010.
  • Bypass the intercept entirely while editingComponent != nil. Verified on iPhone 17 Pro / iOS 26.3 simulator: HW-keyboard typing into a focused TextField now lands characters in the field; previously the same keystrokes were dropped.
  • Extends the input-validation XCUITest pipeline (added in Add input-validation pipeline: XCUITest + Playwright gesture suite #5005) with a fourth keytype step that taps a CN1 TextField then drives XCUIApplication.typeText. typeText synthesises HW-keyboard keystrokes, so this step exercises the exact UIPress path Unresposive App when trying to type to input field #5010 broke. Without the fix the step times out; with the fix the suite asserts CN1IV:EVENT:keytype end-to-end.

Test plan

  • Manual: tap TextField, type via the simulator HW keyboard — characters now appear in the field (iPhone 17 Pro / iOS 26.3 simulator).
  • Source-tree iOS port builds cleanly (mvn -pl ios -am clean install).
  • xcodebuild test for the input-validation XCUITest target — pending CI to verify on a clean runner.
  • Reporter (iPhone 14 Plus / iOS 26.4.2) verifies that virtual-keyboard typing on a real device is now restored — this is the part the simulator could not reproduce.

shai-almog and others added 2 commits May 23, 2026 14:15
…omponent

The hardware-keyboard handler in CodenameOne_GLViewController consumed
every UIPress whose UIKey mapped to a non-zero CN1 keycode -- and for
printable characters cn1MapUIKeyToKeyCode returns the unicode codepoint,
which is always non-zero. With handled=YES the press was never forwarded
to [super pressesBegan:], so UIKit's text-input pipeline never converted
it into insertText: on the focused CN1UITextField / CN1UITextView.

That broke hardware-keyboard typing outright on iOS 13.4+ (BT keyboards,
Magic Keyboard, simulator HW keyboard) the moment a text field was being
edited. On iOS 26.x devices, where some on-screen keyboard interactions
also reach the responder chain as UIPress events, the same path also
swallowed virtual-keyboard typing -- the reporter's "cursor blinks but
typing does nothing" symptom in #5010.

Bypass the intercept entirely while editingComponent != nil. CN1 KeyEvent
listeners legitimately stop firing during text editing, which matches the
intuition that arrow keys etc. should move the caret rather than trigger
app-level navigation while a field is focused.

Verified on iPhone 17 Pro / iOS 26.3 simulator: with a single TextField
focused, typing on the Mac host keyboard now lands characters in the
field. Prior to the fix the same keystrokes were silently dropped.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Extends the input-validation pipeline with a fourth gesture step that
proves keyboard input lands in a CN1 TextField. The driver taps the
field to bring up native iOS editing, then synthesises keystrokes via
XCUIApplication.typeText -- which routes through the simulator's
HW-keyboard pathway, raising UIPress events that walk through
CodenameOne_GLViewController on iOS 13.4+.

Without the companion fix in CodenameOne_GLViewController.m, every
printable keystroke is consumed by pressesBegan: before UIKit converts
it into insertText: on the focused CN1UITextField, the
DataChangedListener never fires, and this step times out. With the
fix, "cn1" propagates end-to-end through CN1UITextField ->
UITextFieldTextDidChangeNotification -> EAGLView.textFieldDidChange
-> stringEdit -> TextField.setText -> DataChangedListener and the
step asserts CN1IV:EVENT:keytype.

The pipeline already covers #5003's tap/drag/longpress regressions
along the same touch chain; #5010 sits one layer deeper on the
responder chain (UIPress instead of UITouch) and needs its own probe.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 23, 2026

✅ Continuous Quality Report

Test & Coverage

Static Analysis

  • SpotBugs [Report archive]
    • ByteCodeTranslator: 0 findings (no issues)
    • android: 0 findings (no issues)
    • codenameone-maven-plugin: 0 findings (no issues)
    • core-unittests: 0 findings (no issues)
    • ios: 0 findings (no issues)
  • PMD: 0 findings (no issues) [Report archive]
  • Checkstyle: 0 findings (no issues) [Report archive]

Generated automatically by the PR CI workflow.

@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 23, 2026

Compared 110 screenshots: 110 matched.
✅ Native iOS screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 259 seconds

Build and Run Timing

Metric Duration
Simulator Boot 61000 ms
Simulator Boot (Run) 6000 ms
App Install 13000 ms
App Launch 16000 ms
Test Execution 291000 ms

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 475.000 ms
Base64 CN1 encode 1210.000 ms
Base64 encode ratio (CN1/native) 2.547x (154.7% slower)
Base64 native decode 311.000 ms
Base64 CN1 decode 1271.000 ms
Base64 decode ratio (CN1/native) 4.087x (308.7% slower)
Base64 SIMD encode 406.000 ms
Base64 encode ratio (SIMD/native) 0.855x (14.5% faster)
Base64 encode ratio (SIMD/CN1) 0.336x (66.4% faster)
Base64 SIMD decode 375.000 ms
Base64 decode ratio (SIMD/native) 1.206x (20.6% slower)
Base64 decode ratio (SIMD/CN1) 0.295x (70.5% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 57.000 ms
Image createMask (SIMD on) 9.000 ms
Image createMask ratio (SIMD on/off) 0.158x (84.2% faster)
Image applyMask (SIMD off) 157.000 ms
Image applyMask (SIMD on) 65.000 ms
Image applyMask ratio (SIMD on/off) 0.414x (58.6% faster)
Image modifyAlpha (SIMD off) 142.000 ms
Image modifyAlpha (SIMD on) 65.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.458x (54.2% faster)
Image modifyAlpha removeColor (SIMD off) 146.000 ms
Image modifyAlpha removeColor (SIMD on) 68.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.466x (53.4% faster)
Image PNG encode (SIMD off) 1056.000 ms
Image PNG encode (SIMD on) 955.000 ms
Image PNG encode ratio (SIMD on/off) 0.904x (9.6% faster)
Image JPEG encode 490.000 ms

@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 23, 2026

Compared 110 screenshots: 110 matched.
✅ Native iOS Metal screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 352 seconds

Build and Run Timing

Metric Duration
Simulator Boot 87000 ms
Simulator Boot (Run) 1000 ms
App Install 22000 ms
App Launch 14000 ms
Test Execution 314000 ms

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 1121.000 ms
Base64 CN1 encode 1951.000 ms
Base64 encode ratio (CN1/native) 1.740x (74.0% slower)
Base64 native decode 562.000 ms
Base64 CN1 decode 1662.000 ms
Base64 decode ratio (CN1/native) 2.957x (195.7% slower)
Base64 SIMD encode 437.000 ms
Base64 encode ratio (SIMD/native) 0.390x (61.0% faster)
Base64 encode ratio (SIMD/CN1) 0.224x (77.6% faster)
Base64 SIMD decode 824.000 ms
Base64 decode ratio (SIMD/native) 1.466x (46.6% slower)
Base64 decode ratio (SIMD/CN1) 0.496x (50.4% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 90.000 ms
Image createMask (SIMD on) 9.000 ms
Image createMask ratio (SIMD on/off) 0.100x (90.0% faster)
Image applyMask (SIMD off) 224.000 ms
Image applyMask (SIMD on) 63.000 ms
Image applyMask ratio (SIMD on/off) 0.281x (71.9% faster)
Image modifyAlpha (SIMD off) 302.000 ms
Image modifyAlpha (SIMD on) 60.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.199x (80.1% faster)
Image modifyAlpha removeColor (SIMD off) 290.000 ms
Image modifyAlpha removeColor (SIMD on) 111.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.383x (61.7% faster)
Image PNG encode (SIMD off) 1381.000 ms
Image PNG encode (SIMD on) 1181.000 ms
Image PNG encode ratio (SIMD on/off) 0.855x (14.5% faster)
Image JPEG encode 786.000 ms

The first CI run of the new keytype step timed out: XCUITest threw
"Neither element nor any descendant has keyboard focus" from
`app.typeText("cn1")` because the (0.5, 0.18) tap landed in empty
space below the TextField. The field had been added to
BorderLayout.NORTH of the target area, which on the CI iPhone SE
runner put it well above the y=0.18 band the driver tapped, so the
field never entered editing mode and no first responder was available
for typeText to write into.

Switch the layout to match TapStep / LongPressStep: TextField in
BorderLayout.CENTER with the same padding+margin sizing, tapped at
the centered (0.5, 0.5) coordinate the other steps already use
successfully. Also bumps the post-tap sleep to 2.0s for the slower
boot of the CI simulator's keyboard animation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@shai-almog shai-almog merged commit 18502ed into master May 23, 2026
19 checks passed
shai-almog added a commit that referenced this pull request May 24, 2026
…editing

The #5013 hotfix changed pressesBegan/Ended/Cancelled to call
[super pressesBegan:] when a native text editor was up, instead of
swallowing the press via the cn1MapUIKeyToKeyCode path. The intent was
to let UIKit's text-input pipeline deliver the press to the focused
CN1UITextField. That worked on the iOS 26.3 simulator (where the
verification happened) but did not fix the freeze the reporter saw on
iPhone 14 Plus / iOS 26.4.2.

The CN1UITextField is the first responder. iOS delivers UIPress events
to the first responder first; the field's own pressesBegan: /
insertText: handles printable keys before the event walks up the
responder chain to our view controller. Forwarding to
[super pressesBegan:] from our override re-enters UIViewController's
default chain walk, which on iOS 26.4.2 hangs the next inbound key
delivery -- the user sees a focused field where typing does nothing
and the rest of the app freezes, requiring a restart.

Change each press handler to return immediately when editingComponent
is set, with no [super pressesBegan:] forwarding. The override is now
fully transparent while editing: the field's own handling stands and
the chain stops here. HW-keyboard support (#3498 / #4982) for non-
editing state is preserved by the unchanged fallthrough.

Also adds bounded CN1Log markers at each press handler entry and at
editStringAtImpl entry so any future device log can correlate edit
session start, press routing, and the editing-vs-not branch taken.
Volume is bounded -- pressesBegan only fires on physical key events,
and editStringAtImpl only fires once per edit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request May 24, 2026
KeyTypeStep was added in #5013 to assert that HW-keyboard typeText
(XCUITest's HW-keyboard pathway, surfacing as UIPress events on iOS
13.4+) reaches the focused CN1UITextField's insertText: via the
responder chain walk through CodenameOne_GLViewController. That walk
depends on the controller's pressesBegan: forwarding to
[super pressesBegan:] while a field is being edited.

The companion commit on this branch makes pressesBegan / pressesEnded
/ pressesCancelled return early without forwarding super while
editingComponent != nil, because that same forwarding is the suspected
trigger for the iOS-26.4.2 freeze the reporter still sees after #5026.
The two fixes are mutually exclusive on the simulator: enable HW
typing via super forwarding (KeyTypeStep passes, virtual-keyboard
freeze persists), or block super forwarding (freeze hopefully fixed,
KeyTypeStep times out on the typeText path).

Disable KeyTypeStep here while we ship the freeze probe to the
reporter. All three layers are commented (not deleted) so re-enabling
is a one-line revert once the right fix that preserves both paths is
known:

  - GestureSuite.java: KeyTypeStep dropped from the steps[] array
  - InputValidationUITests.swift: driveKeyType call commented, helper
    kept
  - drivers/run-ios.sh: CN1IV:READY:keytype + CN1IV:EVENT:keytype
    dropped from REQUIRED_EVENTS

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request May 24, 2026
…editing (#5027)

* Fix #5010: make pressesBegan/Ended/Cancelled fully transparent while editing

The #5013 hotfix changed pressesBegan/Ended/Cancelled to call
[super pressesBegan:] when a native text editor was up, instead of
swallowing the press via the cn1MapUIKeyToKeyCode path. The intent was
to let UIKit's text-input pipeline deliver the press to the focused
CN1UITextField. That worked on the iOS 26.3 simulator (where the
verification happened) but did not fix the freeze the reporter saw on
iPhone 14 Plus / iOS 26.4.2.

The CN1UITextField is the first responder. iOS delivers UIPress events
to the first responder first; the field's own pressesBegan: /
insertText: handles printable keys before the event walks up the
responder chain to our view controller. Forwarding to
[super pressesBegan:] from our override re-enters UIViewController's
default chain walk, which on iOS 26.4.2 hangs the next inbound key
delivery -- the user sees a focused field where typing does nothing
and the rest of the app freezes, requiring a restart.

Change each press handler to return immediately when editingComponent
is set, with no [super pressesBegan:] forwarding. The override is now
fully transparent while editing: the field's own handling stands and
the chain stops here. HW-keyboard support (#3498 / #4982) for non-
editing state is preserved by the unchanged fallthrough.

Also adds bounded CN1Log markers at each press handler entry and at
editStringAtImpl entry so any future device log can correlate edit
session start, press routing, and the editing-vs-not branch taken.
Volume is bounded -- pressesBegan only fires on physical key events,
and editStringAtImpl only fires once per edit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Input validation: disable KeyTypeStep pending #5010 resolution

KeyTypeStep was added in #5013 to assert that HW-keyboard typeText
(XCUITest's HW-keyboard pathway, surfacing as UIPress events on iOS
13.4+) reaches the focused CN1UITextField's insertText: via the
responder chain walk through CodenameOne_GLViewController. That walk
depends on the controller's pressesBegan: forwarding to
[super pressesBegan:] while a field is being edited.

The companion commit on this branch makes pressesBegan / pressesEnded
/ pressesCancelled return early without forwarding super while
editingComponent != nil, because that same forwarding is the suspected
trigger for the iOS-26.4.2 freeze the reporter still sees after #5026.
The two fixes are mutually exclusive on the simulator: enable HW
typing via super forwarding (KeyTypeStep passes, virtual-keyboard
freeze persists), or block super forwarding (freeze hopefully fixed,
KeyTypeStep times out on the typeText path).

Disable KeyTypeStep here while we ship the freeze probe to the
reporter. All three layers are commented (not deleted) so re-enabling
is a one-line revert once the right fix that preserves both paths is
known:

  - GestureSuite.java: KeyTypeStep dropped from the steps[] array
  - InputValidationUITests.swift: driveKeyType call commented, helper
    kept
  - drivers/run-ios.sh: CN1IV:READY:keytype + CN1IV:EVENT:keytype
    dropped from REQUIRED_EVENTS

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request May 26, 2026
…firmed (#5041)

Removes the iOS native edits and the input-validation test scaffolding
that were added to chase issue #5010. The bug reporter's symptoms could
not be independently reproduced, so the workarounds are removed:

- pressesBegan/Ended/Cancelled editingComponent guards in
  CodenameOne_GLViewController (PRs #5013, #5027)
- ignoreEvent extension on CN1TapGestureRecognizer (PR #5026)
- CN1Log [#5010] diagnostic markers in editStringAtImpl and the press
  handlers (PR #5027)
- KeyTypeStep + driveKeyType XCUITest scaffolding that only existed to
  validate the fix path (PR #5013)

CodenameOne_GLViewController.m is now byte-identical to its pre-#5010
baseline; CN1TapGestureRecognizer.m differs only in two trailing-
whitespace cleanups.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

1 participant