Skip to content

Fix iOS 26 tap regressions + ParparVM BGPainter NPE#5003

Merged
shai-almog merged 1 commit into
masterfrom
fix/ios-sim-bgpainter-npe-and-keyboard-gesture
May 22, 2026
Merged

Fix iOS 26 tap regressions + ParparVM BGPainter NPE#5003
shai-almog merged 1 commit into
masterfrom
fix/ios-sim-bgpainter-npe-and-keyboard-gesture

Conversation

@shai-almog
Copy link
Copy Markdown
Collaborator

Summary

Three independent regressions that surfaced while testing on iPhone 17 Pro / iOS 26.3 simulator under Xcode 26:

  1. ParparVM Component$BGPainter.animate NPEComponent.animate() was using bgp.getClass() != BGPainter.class to skip the default background painter. That class-literal comparison failed under ParparVM and the path ran on a BGPainter constructed via the no-arg / Style / Painter constructors (motion fields are null in those), tripping a NullPointerException on wMotion.isFinished() in Component$BGPainter.animate() ~600 ms after every form show. Replaced with !(bgp instanceof BGPainter), which is the intended check anyway -- BGPainter has no subclasses.

  2. iOS 26 keyboard-dismissal UITapGestureRecognizer ate every touch — iOS 26 auto-installs a window-level UITapGestureRecognizer whose action is _keyboardDismissalGestureRecognized: and whose default cancelsTouchesInView=YES. It runs ahead of CN1TapGestureRecognizer in the recognizer chain, so tap-down events were consumed before our touchesBegan: ran. Implemented shouldBeRequiredToFailByGestureRecognizer: on CN1TapGestureRecognizer so any window-level UITapGestureRecognizer must wait for ours to fail.

  3. UIHoverGestureRecognizer preempted touches on the simulatorUIGestureRecognizer.cancelsTouchesInView defaults to YES. In the simulator the host-mac cursor is always hovering over the window, so the hover recognizer was cancelling taps. Explicitly set cancelsTouchesInView=NO / delaysTouchesBegan=NO / delaysTouchesEnded=NO on the hover recognizer.

Net effect: form renders, tap fires pointerPressed + Button.actionPerformed, no recurring NPE in the EDT loop.

Test plan

  • Run a minimal CN1 app on the iPhone 17 Pro / iOS 26.3 simulator under Xcode 26 — form should render and stop NPE-spam in the log
  • Tap a button on the form — pointerPressed and actionPerformed should fire
  • Run the existing tests (ant test-javase) — the Component.animate change is the only Java edit and is a logically equivalent rewrite
  • Smoke test on a real iOS 17/18 device to confirm no regression on older OS versions

🤖 Generated with Claude Code

Three independent fixes surfaced while testing on iOS 26.3 simulator under
Xcode 26:

1. Component.animate(): replace `getClass() != BGPainter.class` with
   `!(bgp instanceof BGPainter)`. The class-literal comparison was being
   bypassed when bgp was a Component$BGPainter constructed via the no-arg /
   Style / Painter constructors (motion fields null), so the Form-as-animation
   path ran `bgp.animate()` and tripped a NullPointerException on
   `wMotion.isFinished()` ~600ms after every form show. instanceof is the
   intended check anyway -- BGPainter has no subclasses.

2. CN1TapGestureRecognizer: implement
   `shouldBeRequiredToFailByGestureRecognizer:` to defeat the
   `_keyboardDismissalGestureRecognized:`-target UITapGestureRecognizer that
   iOS 26 auto-installs on every UIWindow. Without this, that window-level
   recognizer (cancelsTouchesInView=YES) consumed tap-down events before our
   recognizer's touchesBegan: ran, so all taps were dropped.

3. UIHoverGestureRecognizer on the GL view: explicitly clear
   cancelsTouchesInView/delaysTouchesBegan/delaysTouchesEnded. The
   UIGestureRecognizer defaults to cancelsTouchesInView=YES, and on simulator
   builds the host mac cursor is always hovering over the window, so the
   hover recognizer was preempting touches.

Verified end-to-end on iPhone 17 Pro / iOS 26.3 simulator: form renders,
tap fires pointerPressed + Button.actionPerformed, no recurring NPE in the
EDT loop.
@github-actions
Copy link
Copy Markdown
Contributor

✅ 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 22, 2026

Compared 110 screenshots: 110 matched.

Native Android coverage

  • 📊 Line coverage: 11.93% (6776/56788 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.68% (34048/351672), branch 4.18% (1395/33359), complexity 5.22% (1672/32007), method 9.08% (1359/14973), class 14.77% (303/2051)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)
      • kotlinx.coroutines.kotlinx.coroutines.JobSupport – 0.00% (0/423 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 11.93% (6776/56788 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.68% (34048/351672), branch 4.18% (1395/33359), complexity 5.22% (1672/32007), method 9.08% (1359/14973), class 14.77% (303/2051)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)
      • kotlinx.coroutines.kotlinx.coroutines.JobSupport – 0.00% (0/423 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 835.000 ms
Base64 CN1 encode 145.000 ms
Base64 encode ratio (CN1/native) 0.174x (82.6% faster)
Base64 native decode 860.000 ms
Base64 CN1 decode 206.000 ms
Base64 decode ratio (CN1/native) 0.240x (76.0% faster)
Image encode benchmark status skipped (SIMD unsupported)

@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 22, 2026

iOS Metal screenshot updates

Compared 109 screenshots: 108 matched, 1 updated.

  • graphics-draw-rect — updated screenshot. Screenshot differs (1x1 px, bit depth 8).

    graphics-draw-rect
    Preview info: JPEG preview quality 70; JPEG preview quality 70.
    Full-resolution PNG saved as graphics-draw-rect.png in workflow artifacts.

Benchmark Results

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

Build and Run Timing

Metric Duration
Simulator Boot 63000 ms
Simulator Boot (Run) 1000 ms
App Install 28000 ms
App Launch 4000 ms
Test Execution 270000 ms

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 805.000 ms
Base64 CN1 encode 1239.000 ms
Base64 encode ratio (CN1/native) 1.539x (53.9% slower)
Base64 native decode 265.000 ms
Base64 CN1 decode 865.000 ms
Base64 decode ratio (CN1/native) 3.264x (226.4% slower)
Base64 SIMD encode 376.000 ms
Base64 encode ratio (SIMD/native) 0.467x (53.3% faster)
Base64 encode ratio (SIMD/CN1) 0.303x (69.7% faster)
Base64 SIMD decode 393.000 ms
Base64 decode ratio (SIMD/native) 1.483x (48.3% slower)
Base64 decode ratio (SIMD/CN1) 0.454x (54.6% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 56.000 ms
Image createMask (SIMD on) 9.000 ms
Image createMask ratio (SIMD on/off) 0.161x (83.9% faster)
Image applyMask (SIMD off) 116.000 ms
Image applyMask (SIMD on) 50.000 ms
Image applyMask ratio (SIMD on/off) 0.431x (56.9% faster)
Image modifyAlpha (SIMD off) 124.000 ms
Image modifyAlpha (SIMD on) 56.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.452x (54.8% faster)
Image modifyAlpha removeColor (SIMD off) 135.000 ms
Image modifyAlpha removeColor (SIMD on) 61.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.452x (54.8% faster)
Image PNG encode (SIMD off) 1209.000 ms
Image PNG encode (SIMD on) 912.000 ms
Image PNG encode ratio (SIMD on/off) 0.754x (24.6% faster)
Image JPEG encode 472.000 ms

@shai-almog shai-almog merged commit 77295bc into master May 22, 2026
20 checks passed
@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 22, 2026

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

Benchmark Results

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

Build and Run Timing

Metric Duration
Simulator Boot 114000 ms
Simulator Boot (Run) 2000 ms
App Install 17000 ms
App Launch 12000 ms
Test Execution 387000 ms

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 999.000 ms
Base64 CN1 encode 1878.000 ms
Base64 encode ratio (CN1/native) 1.880x (88.0% slower)
Base64 native decode 542.000 ms
Base64 CN1 decode 1459.000 ms
Base64 decode ratio (CN1/native) 2.692x (169.2% slower)
Base64 SIMD encode 767.000 ms
Base64 encode ratio (SIMD/native) 0.768x (23.2% faster)
Base64 encode ratio (SIMD/CN1) 0.408x (59.2% faster)
Base64 SIMD decode 570.000 ms
Base64 decode ratio (SIMD/native) 1.052x (5.2% slower)
Base64 decode ratio (SIMD/CN1) 0.391x (60.9% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 88.000 ms
Image createMask (SIMD on) 15.000 ms
Image createMask ratio (SIMD on/off) 0.170x (83.0% faster)
Image applyMask (SIMD off) 227.000 ms
Image applyMask (SIMD on) 218.000 ms
Image applyMask ratio (SIMD on/off) 0.960x (4.0% faster)
Image modifyAlpha (SIMD off) 311.000 ms
Image modifyAlpha (SIMD on) 139.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.447x (55.3% faster)
Image modifyAlpha removeColor (SIMD off) 217.000 ms
Image modifyAlpha removeColor (SIMD on) 476.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 2.194x (119.4% slower)
Image PNG encode (SIMD off) 2045.000 ms
Image PNG encode (SIMD on) 1335.000 ms
Image PNG encode ratio (SIMD on/off) 0.653x (34.7% faster)
Image JPEG encode 875.000 ms

shai-almog added a commit that referenced this pull request May 22, 2026
iOS build was failing because IOSSimd.m uses ARM NEON intrinsics guarded
by `#if defined(__aarch64__)` and a `generic/platform=iOS Simulator`
destination triggers a universal build whose x86_64 slice has no
`uint32x4_t` etc. Mirror what run-ios-ui-tests.sh does for hellocodenameone:
detect host arch via `uname -m`, force `ARCHS=$HOST_ARCH ONLY_ACTIVE_ARCH=YES`
and pin `-sdk iphonesimulator -configuration Debug`.

JS Playwright driver: `page.mouse.click` was missing because the CN1 JS
port registers pointer listeners on a sibling `<div id="cn1-peers-container">`,
not on `<canvas id="codenameone-canvas">` (which has `pointer-events:none`).
Page-level clicks land on body and never reach the listener. Dispatch
synthetic `MouseEvent`s on `#cn1-peers-container` via `page.evaluate`
so the CN1 dispatcher actually sees mousedown / mousemove / mouseup --
still exercises every CN1 listener that a PR #5003-class bug would
break.

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

* Add input-validation pipeline: XCUITest + Playwright gesture suite

Scaffolds a minimal CN1 app under scripts/input-validation-app whose
only job is to assert that physical taps, drags, and long-presses
reach Component listeners end-to-end on each port. Driven by OS-level
automation (XCUITest on iOS, Playwright on JavaScript) and asserted
via a structured CN1IV:EVENT:* log stream -- no screenshots, no
chunked Base64, no reference comparisons.

Closes the test-coverage gap exposed by PR #5003: three independent
input-chain regressions shipped on iOS 26 because the existing
hellocodenameone suite builds every form programmatically from
runTest() and never depends on a touch event actually firing.

CI workflow is scaffolded but gated `if: false` pending generalisation
of scripts/build-ios-app.sh (currently hard-coded to the
hellocodenameone module name); manual local runs work today per the
README.

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

* Remove unused `missing` variable in Playwright driver

The misses are already reported by the for-loop over REQUIRED_EVENTS
below, so the precomputed array was dead code. Flagged by
github-code-quality on PR #5005.

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

* Wire input-validation iOS + JS jobs into actual CI runs

Generalise the two build scripts via CN1_APP_DIR / CN1_APP_MAIN_NAME /
CN1_APP_PACKAGE_NAME env overrides -- defaults stay pointed at
hellocodenameone so the existing scripts-ios.yml / scripts-javascript.yml
pipelines remain unchanged:

* scripts/build-ios-app.sh: read APP_MAIN_NAME from
  codenameone_settings.properties; templated workspace, scheme and Xcode
  project names off it so any CN1 app can be built.
* scripts/build-javascript-port-hellocodenameone.sh: read
  packageName/mainName from settings, parameterise the generated
  JavaScript launcher and the ByteCodeTranslator invocation.

Add the input-validation app's CN1 project metadata so the CN1 plugin
knows what to name everything: codenameone_settings.properties (mainName=
InputValidationApp, packageName=com.codenameone.inputvalidation), a stub
icon.png copied from hellocodenameone, and the Maven wrapper alongside.

Rewrite .github/workflows/input-validation.yml so both jobs actually run
rather than being gated by `if: false`:

* `build-port` (reusable from scripts-ios.yml) builds + caches the CN1
  iOS port.
* `ios` consumes that cache, runs build-ios-app.sh with CN1_APP_DIR=
  scripts/input-validation-app, builds the .app via xcodebuild for the
  simulator, and hands it to drivers/run-ios.sh which drives gestures via
  XCUITest and asserts CN1IV:* lines in the os_log stream.
* `javascript` builds the ParparVM browser bundle, serves it from
  python3 -m http.server, and drives Chromium via drivers/run-js.sh.

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

* Fix iOS arch mismatch + dispatch JS events on peersContainer

iOS build was failing because IOSSimd.m uses ARM NEON intrinsics guarded
by `#if defined(__aarch64__)` and a `generic/platform=iOS Simulator`
destination triggers a universal build whose x86_64 slice has no
`uint32x4_t` etc. Mirror what run-ios-ui-tests.sh does for hellocodenameone:
detect host arch via `uname -m`, force `ARCHS=$HOST_ARCH ONLY_ACTIVE_ARCH=YES`
and pin `-sdk iphonesimulator -configuration Debug`.

JS Playwright driver: `page.mouse.click` was missing because the CN1 JS
port registers pointer listeners on a sibling `<div id="cn1-peers-container">`,
not on `<canvas id="codenameone-canvas">` (which has `pointer-events:none`).
Page-level clicks land on body and never reach the listener. Dispatch
synthetic `MouseEvent`s on `#cn1-peers-container` via `page.evaluate`
so the CN1 dispatcher actually sees mousedown / mousemove / mouseup --
still exercises every CN1 listener that a PR #5003-class bug would
break.

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

* Pin iOS sim by availability; broaden JS dispatch to touch + pointer

iOS: previous run-ios.sh hard-coded `iPhone 17 Pro` which only exists on
Xcode 26 -- the macos-15 runner default Xcode is 16.4, top device is
iPhone 16. Auto-pick the newest available iPhone runtime and fall back
through the list if the user-supplied CN1IV_DEVICE_NAME isn't installed.

JS Playwright driver: add a layout pre-flight that fires its own
mousedown probe on `#cn1-peers-container` to confirm dispatchEvent
actually reaches the listener (rules out "synthetic events are silently
dropped" before we blame CN1). Also fire PointerEvent + TouchEvent
variants alongside MouseEvent in case the JS port's pointer dispatcher
only listens to one channel. Same gesture flow, just multi-modal.

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

* Mark input-validation jobs advisory; capture iOS xcresult

Both jobs run, build, install, launch -- but the actual gesture-dispatch
endpoints turn out to need port-side work:

* iOS: XCUITest application-only mode (no host-app) errors with the
  opaque `** TEST FAILED **` under Xcode 16.4. The runner build + simctl
  install + log-stream path is verified. Capture the .xcresult and run
  xcresulttool against it so the artifact has the real failure reason
  for post-hoc diagnosis rather than a generic xcodebuild line.
* JavaScript: the layout dump shows synthetic mousedown reaches main-
  thread listeners we add (`selfTestFired:true`) but the CN1 JS port
  registers its pointer listeners through a host-bridge proxy from
  inside a Web Worker; synthetic events don't traverse that proxy the
  way real OS events do. End-to-end input validation here needs
  JS-port-side work.

Mark both jobs `continue-on-error: true` so the infrastructure lands
without gating PRs on issues that are about the ports, not about this
pipeline. README updated with the current state.

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

* Drop JS job; fix iOS XCUITest with a host-app stub

Two changes:

1. Drop the JavaScript job entirely. The CN1 JS port registers its
   pointer listeners through a host-bridge proxy from inside a Web
   Worker; synthetic browser events on the main thread don't traverse
   that proxy the way real OS events do. The diagnostic from the
   previous run confirms this (the driver's layout self-test fires its
   own listener -- `selfTestFired:true` -- but CN1's listeners never
   fire). End-to-end input validation on JS needs port-side changes
   that don't belong in this PR. Removing the job, the JS module, the
   Playwright driver, and reverting the JS build-script generalisation
   keeps the diff focused.

2. Fix the iOS XCUITest by giving it a proper host-app target.
   Application-only UI testing (TEST_TARGET_NAME="" + USES_XCTRUNNER)
   was exiting with an opaque `** TEST FAILED **` under Xcode 16.4 --
   that mode is finicky and not how the standard XCUITest pipeline
   works. The XcodeGen project now declares a minimal `HostStub`
   target (a UIApplicationMain that does nothing) and points
   TEST_TARGET_NAME at it. The UI test code is unchanged -- it still
   attaches to the already-installed CN1 app by bundle id via
   `XCUIApplication(bundleIdentifier:)`. The stub is purely there so
   the XCUITest runner has a regular host to launch into.

`continue-on-error: true` removed -- it was masking failure, not
fixing anything.

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

* Fix iOS XCUITest: correct bundle id, drop misleading env var

The xcresult artifact from the previous run pinpointed the actual
failure: "Failed to launch com.codenameone.examples.inputvalidation".
The Swift fallback had `examples.` baked in but the CN1 maven plugin
derives CFBundleIdentifier straight from `codename1.packageName`,
which is `com.codenameone.inputvalidation` (no `examples.`) per
common/codenameone_settings.properties.

The CN1IV_BUNDLE_ID env override was also broken: `xcodebuild test
KEY=VALUE` sets a *build setting*, not a runtime environment variable
for the test process. The Swift code's ProcessInfo lookup would never
see it, so the fallback was always used.

Hard-code the correct id; drop the broken env var passing; warn from
run-ios.sh if the installed bundle id doesn't match what the test
will request.

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 23, 2026
…omponent (#5013)

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

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>

* Input-validation: add keytype step (XCUITest coverage for #5010)

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>

* Input-validation: fix keytype tap-target placement so XCUITest hits it

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>

---------

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