Skip to content

Add native desktop themes and platform fidelity testing - #5845

Merged
shai-almog merged 93 commits into
masterfrom
desktop-macos-fidelity-gate
Sep 18, 2026
Merged

shai-almog merged 93 commits into
masterfrom
desktop-macos-fidelity-gate

Conversation

@shai-almog

@shai-almog shai-almog commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator

Desktop applications currently load mobile-oriented native themes. This adds selectable Windows Fluent, macOS Aqua, and GNOME Adwaita themes for JavaSE and native desktop ports, with light/dark resources and component hover styles. JavaSE, Windows, and Linux selection is independent of mobile hints: unset/legacy preserves the existing theme, modern modes select the desktop theme, and custom installs no framework base in packaged apps or the simulator. Explicit resources and the UWP simulator preference remain overrides. Native macOS retains its historical modern iOS-style default; explicit Aqua/auto/native modes select Aqua with AppKit system weights and italic traits. Its iOS-style modes preserve their historical font mapping. Explicit font choices and legacy sizing remain supported.

Hover handling distinguishes mouse, pen, and touch, preserves device metadata, and clears hover/tooltips on exit, hiding, removal, navigation, and Window input cancellation. Terminal pointer-leave events survive queue saturation. Hover backgrounds own their animation registrations, including lead hierarchies and active style replacement, so cleanup preserves application animations and scrollbar fades. Focused text inputs retain their selected focus styling. CSS inheritance, programmatic styles, and inline-all overrides work with hover and theme refresh. Progress bars measure their native track thickness while preserving text overlays and invalidating cached dimensions when their mode changes. Custom progress artwork retains the legacy renderer and height across normal, hover, selected, disabled and lead-pressed states; plain native capsule borders remain supported. Native CSS rounded shadows require explicit zero blur, supported positive spread, and bounded offsets; unsupported shadows remain rasterized.

Native reference apps capture WinUI 3, AppKit, and GTK/libadwaita controls. Desktop baselines use host font families at 1x logical pixels and 96 DPI. All 180 hosted comparison pairs were inspected; mean scores are 89.98% Windows, 87.23% GNOME, and 85.18% macOS. Remaining differences are documented in scripts/fidelity-app/baseline/README.md. Native references and gate tolerances are unchanged. The three macOS Window-Layout references were captured in run 35169743013. Every changed pixel is in the generic Slider progress strip at rows 193–208; the other 157 captures matched and their references remain unchanged. No screenshot tolerance changed. Desktop scoring follows core and JavaSE sources, generators, the shared renderer, and spec changes; configuration validation rejects silent fallbacks, and the gate rejects disappearing baseline pairs or geometry metrics. Grouped geometry masks follow the renderer in both appearances; one iOS geometry entry is remeasured from successful captures, without changing visual score thresholds. Focus capture is applied after attachment.

Validation:

  • Clean Java 8 verification of the current framework: 6,995 core tests and 41 CSS compiler tests pass, with zero SpotBugs findings and a passing CI quality-summary gate. The progress customization and state transitions also pass 391 focused UI tests and the quality gate.
  • All 13 JavaSE theme/font tests and six packaged-wrapper tests pass. All 22 JUnit extension GUI tests pass without skips, including desktop font setup and restoration. Nine additional GUI tests verify generic Slider border compatibility and native progress sizing with the compiled Windows, macOS, GNOME and iOS themes in both light and dark modes. A compiled AppKit regression exercises all ten aliases and the actual native loader; both Apple Java ports compile and three mode-selection tests pass. All 71 backend HTTP integration tests pass locally without backend changes. The Android editor stress fixture completes all 50 cycles on API 36 with teardown verified on Android main; its old direct native teardown call caused the JDK 17 CI crash from the CN1 EDT. The fixture now uses the existing production thread handoff and forwards exceptions to its failure callback.
  • Both native queue saturation tests and the native pointer-source regression, 17 fidelity-spec regressions, five compiled gate regressions and two compiled image/geometry regressions, the current 33-component spec, and all 72 workflows pass validation. An actual desktop tile capture verifies distinct normal/focus rendering.
  • All five themes compile successfully, and their tracked resources are regenerated. Dark desktop capsule borders explicitly carry their dark fill colors. Windows, macOS, and GNOME pass the desktop fidelity gate.
  • All 114 review threads are resolved. Codex approved the current revision, including the Android CI fixture repair. Platform filters reject Linux host aliases that cannot match the GNOME fixture runner, with a compiled runtime reproduction and regression coverage. Full CI is being followed to completion. The preceding full ParparVM test phase passed, including all 71 backend HTTP tests, without backend changes.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 16, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-17T02:47:40.503312Z 9ee3b9f Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c1e1ff6076

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/scripts-fidelity-desktop.yml
@github-actions

github-actions Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Developer Guide build artifacts are available for download from this workflow run:

Developer Guide quality checks:

  • AsciiDoc linter: No issues found (report)
  • Vale: No alerts found (report)
  • Paragraph capitalization: No paragraph capitalization issues (report)
  • LanguageTool: No grammar matches (report)
  • Image references: No unused images detected (report)

@github-actions

github-actions Bot commented Sep 16, 2026

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)
    • build-hint-catalog: 0 findings (no issues)
    • build-hint-tools: 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 and others added 4 commits September 16, 2026 06:48
Its golden set is captured, reviewed and committed, so it joins Windows and GNOME
on the automatic trigger.

It has no BASELINE yet -- the hosted macOS runner queue has not yielded a scoring
slot in several hours -- and enabling it anyway is safe rather than a shortcut.
FidelityGate treats a pair with no baseline entry as new: it prints the score and
passes. So the first run that gets a runner establishes the numbers instead of
failing on their absence. Verified rather than assumed, by running the leg
locally against the committed goldens with no baseline file present: 60 pairs
scored, "[gate] OK", exit 0.

When that run lands, record its baseline from its own fidelity-compare.json --
from the runner that scored it, never locally. A Mac-recorded baseline failed the
gnome gate on eighteen pairs because the slider comes out a pixel taller on
Linux, and a locally recorded baseline passes locally forever, so the mistake is
invisible until CI disagrees.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
master reverted this work (1305813) because it was pushed there without
permission. This merge takes master's other commits -- PR #5841 and the
syndication bot's -- while keeping every file the revert removed, so the branch
holds the complete change and can be reviewed as one pull request.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The merge in the previous commit took master's deletions for every file that did
not conflict, which emptied most of the change out of this branch. Restored from
a401e5d, the branch tip recorded before the revert, so the branch now carries
the complete work.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
master reverted all 70 of my direct pushes (9bd32cd, a40a11f). This merge
takes master's other commits -- five reviewed pull requests and the syndication
bot's -- while keeping every file those reverts removed, so the branch carries
the whole change and reviews as one pull request.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@shai-almog
shai-almog force-pushed the desktop-macos-fidelity-gate branch from c1e1ff6 to 1d3c16b Compare September 16, 2026 04:02

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1d3c16ba7e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/scripts-fidelity-desktop.yml Outdated
Comment thread Ports/WindowsPort/nativeSources/cn1_windows_window.cpp
Comment thread maven/mac/pom.xml
Comment thread Ports/WindowsPort/nativeSources/cn1_windows_window.cpp Outdated
@shai-almog

shai-almog commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 12 screenshots: 12 matched.
✅ JavaSE simulator integration screenshots matched stored baselines.

Comment thread scripts/fidelity-app/windows-native-ref/Program.cs Fixed
Comment thread scripts/fidelity-app/windows-native-ref/Program.cs Fixed
Comment thread scripts/fidelity-app/windows-native-ref/Program.cs Fixed
Comment thread scripts/fidelity-app/windows-native-ref/Program.cs Fixed
Comment thread scripts/fidelity-app/windows-native-ref/Program.cs Fixed
Comment thread scripts/fidelity-app/windows-native-ref/Program.cs Fixed
Comment thread scripts/fidelity-app/windows-native-ref/Program.cs Fixed
Comment thread scripts/fidelity-app/windows-native-ref/Program.cs Fixed
Comment thread scripts/fidelity-app/windows-native-ref/Program.cs Fixed
Comment thread scripts/fidelity-app/windows-native-ref/Program.cs Fixed
@shai-almog

shai-almog commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator Author

Native fidelity (Android, Material 3)

54 pairs compared -- median 95.6%, worst 91.3% (FlatButton_pressed_dark), 25th pct 94.9%, mean 95.7%.

Distribution -- >=99%: 2 | 95-99%: 37 | 90-95%: 15 | <90%: 0

Component State Appearance Material Fidelity SSIM mean delta vs base Geometry
FlatButton pressed dark normal 91.3% 0.899 3.10 0.0 ok
Tabs normal light normal 92.3% 0.914 3.05 0.0 ok
Button pressed dark normal 92.6% 0.949 4.32 0.0 ok
FlatButton normal dark normal 93.2% 0.938 2.69 0.0 ok
Button disabled dark normal 93.3% 0.928 2.20 0.0 ok
Button pressed light normal 93.3% 0.952 3.68 0.0 ok
FlatButton normal light normal 93.7% 0.941 2.29 0.0 ok
FlatButton pressed light normal 93.8% 0.942 2.56 0.0 ok
FloatingActionButton pressed light normal 94.4% 0.927 2.82 0.0 OFF (h 0.88)
RadioButton normal dark normal 94.5% 0.963 2.19 0.0 ok
RadioButton normal light normal 94.7% 0.964 1.85 0.0 ok
CheckBox selected dark normal 94.7% 0.950 2.60 0.0 ok
RadioButton selected dark normal 94.8% 0.963 2.42 0.0 ok
CheckBox normal dark normal 94.9% 0.952 2.69 0.0 ok
Button normal dark normal 94.9% 0.949 3.16 0.0 ok
CheckBox normal light normal 95.0% 0.953 2.30 0.0 ok
Toolbar normal dark normal 95.1% 0.906 1.60 0.0 ok
RaisedButton pressed dark normal 95.2% 0.950 2.39 0.0 ok
CheckBox disabled dark normal 95.2% 0.954 1.47 0.0 ok
CheckBox disabled light normal 95.2% 0.956 1.34 0.0 ok
Tabs normal dark normal 95.2% 0.913 3.65 0.0 ok
RadioButton disabled dark normal 95.3% 0.963 1.18 0.0 ok
RadioButton selected light normal 95.3% 0.964 1.84 0.0 ok
CheckBox selected light normal 95.4% 0.952 2.06 0.0 ok
Switch selected light normal 95.4% 0.966 1.59 0.0 ok
Switch selected dark normal 95.5% 0.966 1.86 0.0 ok
RadioButton disabled light normal 95.5% 0.966 1.08 0.0 ok
Switch disabled dark normal 95.6% 0.961 0.85 0.0 ok
Dialog normal light normal 95.7% 0.930 2.30 0.0 ok
RaisedButton pressed light normal 95.8% 0.958 2.16 0.0 ok
Button normal light normal 95.8% 0.953 2.46 0.0 ok
Dialog normal dark normal 95.8% 0.932 2.30 0.0 ok
Switch normal light normal 96.0% 0.961 1.45 0.0 ok
FloatingActionButton normal light normal 96.1% 0.937 1.14 0.0 ok
FloatingActionButton pressed dark normal 96.2% 0.951 2.45 0.0 ok
Switch normal dark normal 96.2% 0.962 1.39 0.0 ok
TextField disabled dark normal 96.2% 0.965 0.76 0.0 ok
RaisedButton normal dark normal 96.4% 0.952 1.78 0.0 ok
Switch disabled light normal 96.4% 0.970 0.61 0.0 ok
Button disabled light normal 96.8% 0.960 1.06 0.0 ok
ProgressBar normal dark normal 96.9% 0.967 2.03 0.0 OFF (h 1.50)
RaisedButton disabled dark normal 97.0% 0.955 0.89 0.0 ok
FloatingActionButton normal dark normal 97.1% 0.952 1.43 0.0 ok
ProgressBar normal light normal 97.3% 0.974 1.53 0.0 OFF (h 1.50)
RaisedButton disabled light normal 97.3% 0.961 0.79 0.0 ok
TextField disabled light normal 97.3% 0.965 0.79 0.0 ok
RaisedButton normal light normal 97.3% 0.961 1.40 0.0 ok
TextField normal dark normal 97.6% 0.958 1.83 0.0 ok
TextField normal light normal 97.6% 0.958 1.63 0.0 ok
Slider normal dark normal 98.4% 0.990 0.87 0.0 ok
Toolbar normal light normal 98.7% 0.974 1.28 0.0 ok
Slider normal light normal 99.0% 0.991 0.47 0.0 ok
Slider disabled dark normal 99.6% 0.993 0.22 0.0 ok
Slider disabled light normal 99.6% 0.993 0.18 0.0 ok
Geometry vs native (bbox offset / size ratio / center offset / corner radius) -- gated separately from the visual score
Component State Appearance bbox dx,dy (px) w ratio h ratio center off (px) radius native->cn1 (px)
FloatingActionButton pressed light +0,+0 0.929 0.881 4.0 -
FloatingActionButton normal light +0,+0 0.946 0.912 2.9 -
Button pressed dark +0,+0 0.947 0.975 2.6 -
Button disabled dark +0,+0 0.947 0.975 2.6 -
Button pressed light +0,+0 0.947 0.975 2.6 -
Button normal dark +0,+0 0.947 0.975 2.6 -
RaisedButton pressed dark +0,+0 0.945 0.975 2.6 -
RaisedButton pressed light +0,+0 0.945 0.975 2.6 -
Button normal light +0,+0 0.947 0.975 2.6 -
RaisedButton normal dark +0,+0 0.945 0.975 2.6 -
Button disabled light +0,+0 0.947 0.975 2.6 -
RaisedButton disabled dark +0,+0 0.945 0.975 2.6 -
RaisedButton disabled light +0,+0 0.945 0.975 2.6 -
RaisedButton normal light +0,+0 0.945 0.975 2.6 -
RadioButton normal dark +1,+1 1.029 1.000 2.2 -
RadioButton normal light +1,+1 1.029 1.000 2.2 -
RadioButton selected dark +1,+1 1.029 1.000 2.2 -
RadioButton disabled dark +1,+1 1.029 1.000 2.2 -
RadioButton selected light +1,+1 1.029 1.000 2.2 -
Switch selected light +0,+0 1.080 1.063 2.2 -
RadioButton disabled light +1,+1 1.029 1.000 2.2 -
CheckBox selected dark +1,+1 1.013 1.000 1.8 -
CheckBox normal dark +1,+1 1.013 1.000 1.8 -
CheckBox normal light +1,+1 1.013 1.000 1.8 -
CheckBox disabled dark +1,+1 1.013 1.000 1.8 -
CheckBox disabled light +1,+1 1.013 1.000 1.8 -
CheckBox selected light +1,+1 1.013 1.000 1.8 -
Switch selected dark +0,+0 1.060 1.031 1.6 -
Switch disabled dark +0,-1 1.060 1.031 1.6 -
Dialog normal light +0,+0 1.007 0.982 1.6 -
Dialog normal dark +0,+0 1.007 0.982 1.6 -
Switch normal light +0,-1 1.060 1.031 1.6 -
Switch normal dark +0,-1 1.060 1.031 1.6 -
Switch disabled light +0,-1 1.060 1.031 1.6 -
FloatingActionButton pressed dark +0,+0 0.963 0.963 1.4 -
FloatingActionButton normal dark +0,+0 0.963 0.963 1.4 -
Toolbar normal light -1,+1 1.000 1.000 1.4 -
FlatButton pressed dark +0,+0 0.977 0.975 1.1 -
FlatButton normal dark +0,+0 0.977 0.975 1.1 -
FlatButton normal light +0,+0 0.977 0.975 1.1 -
FlatButton pressed light +0,+0 0.977 0.975 1.1 -
TextField normal dark +0,+0 1.015 1.036 1.1 -
TextField normal light +0,+0 1.015 1.036 1.1 -
Toolbar normal dark +0,+0 1.000 1.032 1.0 -
ProgressBar normal dark +0,+0 1.000 1.500 1.0 -
ProgressBar normal light +0,+0 1.000 1.500 1.0 -
TextField disabled dark +0,+0 1.015 1.018 0.7 -
TextField disabled light +0,+0 1.015 1.018 0.7 -
Tabs normal light +0,+1 1.000 0.984 0.5 -
Slider normal dark +1,+0 0.996 1.000 0.5 -
Slider normal light +1,+0 0.996 1.000 0.5 -
Tabs normal dark +0,+0 1.000 1.000 0.0 -
Slider disabled dark +0,+0 1.000 1.000 0.0 -
Slider disabled light +0,+0 1.000 1.000 0.0 -

Side-by-side comparisons (worst first)

  • FlatButton_pressed_dark -- 91.25% fidelity (SSIM 0.8985) (no change)

    native FlatButton_pressed_dark cn1 FlatButton_pressed_dark
    Left: native widget. Right: Codename One render.

  • Tabs_normal_light -- 92.28% fidelity (SSIM 0.9140) (no change)

    native Tabs_normal_light cn1 Tabs_normal_light
    Left: native widget. Right: Codename One render.

  • Button_pressed_dark -- 92.61% fidelity (SSIM 0.9485) (no change)

    native Button_pressed_dark cn1 Button_pressed_dark
    Left: native widget. Right: Codename One render.

  • FlatButton_normal_dark -- 93.24% fidelity (SSIM 0.9381) (no change)

    native FlatButton_normal_dark cn1 FlatButton_normal_dark
    Left: native widget. Right: Codename One render.

  • Button_disabled_dark -- 93.26% fidelity (SSIM 0.9278) (no change)

    native Button_disabled_dark cn1 Button_disabled_dark
    Left: native widget. Right: Codename One render.

  • Button_pressed_light -- 93.34% fidelity (SSIM 0.9521) (no change)

    native Button_pressed_light cn1 Button_pressed_light
    Left: native widget. Right: Codename One render.

  • FlatButton_normal_light -- 93.72% fidelity (SSIM 0.9410) (no change)

    native FlatButton_normal_light cn1 FlatButton_normal_light
    Left: native widget. Right: Codename One render.

  • FlatButton_pressed_light -- 93.77% fidelity (SSIM 0.9424) (no change)

    native FlatButton_pressed_light cn1 FlatButton_pressed_light
    Left: native widget. Right: Codename One render.

  • FloatingActionButton_pressed_light -- 94.44% fidelity (SSIM 0.9273) (no change)

    native FloatingActionButton_pressed_light cn1 FloatingActionButton_pressed_light
    Left: native widget. Right: Codename One render.

  • RadioButton_normal_dark -- 94.46% fidelity (SSIM 0.9630) (no change)

    native RadioButton_normal_dark cn1 RadioButton_normal_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_normal_light -- 94.69% fidelity (SSIM 0.9643) (no change)

    native RadioButton_normal_light cn1 RadioButton_normal_light
    Left: native widget. Right: Codename One render.

  • CheckBox_selected_dark -- 94.71% fidelity (SSIM 0.9502) (no change)

    native CheckBox_selected_dark cn1 CheckBox_selected_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_selected_dark -- 94.79% fidelity (SSIM 0.9630) (no change)

    native RadioButton_selected_dark cn1 RadioButton_selected_dark
    Left: native widget. Right: Codename One render.

  • CheckBox_normal_dark -- 94.93% fidelity (SSIM 0.9516) (no change)

    native CheckBox_normal_dark cn1 CheckBox_normal_dark
    Left: native widget. Right: Codename One render.

  • Button_normal_dark -- 94.94% fidelity (SSIM 0.9491) (no change)

    native Button_normal_dark cn1 Button_normal_dark
    Left: native widget. Right: Codename One render.

  • CheckBox_normal_light -- 95.03% fidelity (SSIM 0.9531) (no change)

    native CheckBox_normal_light cn1 CheckBox_normal_light
    Left: native widget. Right: Codename One render.

  • Toolbar_normal_dark -- 95.07% fidelity (SSIM 0.9059) (no change)

    native Toolbar_normal_dark cn1 Toolbar_normal_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_pressed_dark -- 95.19% fidelity (SSIM 0.9501) (no change)

    native RaisedButton_pressed_dark cn1 RaisedButton_pressed_dark
    Left: native widget. Right: Codename One render.

  • CheckBox_disabled_dark -- 95.20% fidelity (SSIM 0.9538) (no change)

    native CheckBox_disabled_dark cn1 CheckBox_disabled_dark
    Left: native widget. Right: Codename One render.

  • CheckBox_disabled_light -- 95.21% fidelity (SSIM 0.9562) (no change)

    native CheckBox_disabled_light cn1 CheckBox_disabled_light
    Left: native widget. Right: Codename One render.

  • Tabs_normal_dark -- 95.23% fidelity (SSIM 0.9125) (no change)

    native Tabs_normal_dark cn1 Tabs_normal_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_disabled_dark -- 95.29% fidelity (SSIM 0.9630) (no change)

    native RadioButton_disabled_dark cn1 RadioButton_disabled_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_selected_light -- 95.33% fidelity (SSIM 0.9642) (no change)

    native RadioButton_selected_light cn1 RadioButton_selected_light
    Left: native widget. Right: Codename One render.

  • CheckBox_selected_light -- 95.37% fidelity (SSIM 0.9524) (no change)

    native CheckBox_selected_light cn1 CheckBox_selected_light
    Left: native widget. Right: Codename One render.

  • Switch_selected_light -- 95.37% fidelity (SSIM 0.9658) (no change)

    native Switch_selected_light cn1 Switch_selected_light
    Left: native widget. Right: Codename One render.

  • Switch_selected_dark -- 95.45% fidelity (SSIM 0.9656) (no change)

    native Switch_selected_dark cn1 Switch_selected_dark
    Left: native widget. Right: Codename One render.

  • RadioButton_disabled_light -- 95.46% fidelity (SSIM 0.9657) (no change)

    native RadioButton_disabled_light cn1 RadioButton_disabled_light
    Left: native widget. Right: Codename One render.

  • Switch_disabled_dark -- 95.57% fidelity (SSIM 0.9613) (no change)

    native Switch_disabled_dark cn1 Switch_disabled_dark
    Left: native widget. Right: Codename One render.

  • Dialog_normal_light -- 95.65% fidelity (SSIM 0.9300) (no change)

    native Dialog_normal_light cn1 Dialog_normal_light
    Left: native widget. Right: Codename One render.

  • RaisedButton_pressed_light -- 95.78% fidelity (SSIM 0.9578) (no change)

    native RaisedButton_pressed_light cn1 RaisedButton_pressed_light
    Left: native widget. Right: Codename One render.

  • Button_normal_light -- 95.79% fidelity (SSIM 0.9528) (no change)

    native Button_normal_light cn1 Button_normal_light
    Left: native widget. Right: Codename One render.

  • Dialog_normal_dark -- 95.79% fidelity (SSIM 0.9322) (no change)

    native Dialog_normal_dark cn1 Dialog_normal_dark
    Left: native widget. Right: Codename One render.

  • Switch_normal_light -- 95.97% fidelity (SSIM 0.9612) (no change)

    native Switch_normal_light cn1 Switch_normal_light
    Left: native widget. Right: Codename One render.

  • FloatingActionButton_normal_light -- 96.09% fidelity (SSIM 0.9367) (no change)

    native FloatingActionButton_normal_light cn1 FloatingActionButton_normal_light
    Left: native widget. Right: Codename One render.

  • FloatingActionButton_pressed_dark -- 96.16% fidelity (SSIM 0.9513) (no change)

    native FloatingActionButton_pressed_dark cn1 FloatingActionButton_pressed_dark
    Left: native widget. Right: Codename One render.

  • Switch_normal_dark -- 96.17% fidelity (SSIM 0.9616) (no change)

    native Switch_normal_dark cn1 Switch_normal_dark
    Left: native widget. Right: Codename One render.

  • TextField_disabled_dark -- 96.21% fidelity (SSIM 0.9648) (no change)

    native TextField_disabled_dark cn1 TextField_disabled_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_normal_dark -- 96.41% fidelity (SSIM 0.9516) (no change)

    native RaisedButton_normal_dark cn1 RaisedButton_normal_dark
    Left: native widget. Right: Codename One render.

  • Switch_disabled_light -- 96.43% fidelity (SSIM 0.9698) (no change)

    native Switch_disabled_light cn1 Switch_disabled_light
    Left: native widget. Right: Codename One render.

  • Button_disabled_light -- 96.80% fidelity (SSIM 0.9596) (no change)

    native Button_disabled_light cn1 Button_disabled_light
    Left: native widget. Right: Codename One render.

  • ProgressBar_normal_dark -- 96.91% fidelity (SSIM 0.9669) (no change)

    native ProgressBar_normal_dark cn1 ProgressBar_normal_dark
    Left: native widget. Right: Codename One render.

  • RaisedButton_disabled_dark -- 97.02% fidelity (SSIM 0.9549) (no change)

    native RaisedButton_disabled_dark cn1 RaisedButton_disabled_dark
    Left: native widget. Right: Codename One render.

  • FloatingActionButton_normal_dark -- 97.07% fidelity (SSIM 0.9521) (no change)

    native FloatingActionButton_normal_dark cn1 FloatingActionButton_normal_dark
    Left: native widget. Right: Codename One render.

  • ProgressBar_normal_light -- 97.26% fidelity (SSIM 0.9739) (no change)

    native ProgressBar_normal_light cn1 ProgressBar_normal_light
    Left: native widget. Right: Codename One render.

  • RaisedButton_disabled_light -- 97.26% fidelity (SSIM 0.9611) (no change)

    native RaisedButton_disabled_light cn1 RaisedButton_disabled_light
    Left: native widget. Right: Codename One render.

  • TextField_disabled_light -- 97.29% fidelity (SSIM 0.9649) (no change)

    native TextField_disabled_light cn1 TextField_disabled_light
    Left: native widget. Right: Codename One render.

  • RaisedButton_normal_light -- 97.32% fidelity (SSIM 0.9613) (no change)

    native RaisedButton_normal_light cn1 RaisedButton_normal_light
    Left: native widget. Right: Codename One render.

  • TextField_normal_dark -- 97.61% fidelity (SSIM 0.9583) (no change)

    native TextField_normal_dark cn1 TextField_normal_dark
    Left: native widget. Right: Codename One render.

  • TextField_normal_light -- 97.62% fidelity (SSIM 0.9582) (no change)

    native TextField_normal_light cn1 TextField_normal_light
    Left: native widget. Right: Codename One render.

  • Slider_normal_dark -- 98.39% fidelity (SSIM 0.9900) (no change)

    native Slider_normal_dark cn1 Slider_normal_dark
    Left: native widget. Right: Codename One render.

  • Toolbar_normal_light -- 98.69% fidelity (SSIM 0.9739) (no change)

    native Toolbar_normal_light cn1 Toolbar_normal_light
    Left: native widget. Right: Codename One render.

  • Slider_normal_light -- 98.95% fidelity (SSIM 0.9908) (no change)

    native Slider_normal_light cn1 Slider_normal_light
    Left: native widget. Right: Codename One render.

  • Slider_disabled_dark -- 99.56% fidelity (SSIM 0.9927) (no change)

    native Slider_disabled_dark cn1 Slider_disabled_dark
    Left: native widget. Right: Codename One render.

  • Slider_disabled_light -- 99.59% fidelity (SSIM 0.9932) (no change)

    native Slider_disabled_light cn1 Slider_disabled_light
    Left: native widget. Right: Codename One render.

@github-actions

Copy link
Copy Markdown
Contributor

Cloudflare Preview

@shai-almog

shai-almog commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 151 screenshots: 151 matched.

Native Android coverage

  • 📊 Line coverage: 9.24% (9188/99417 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.00% (47232/524920), branch 3.56% (1772/49739), complexity 3.53% (1873/53026), method 5.44% (1516/27888), class 10.92% (408/3736)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6367 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.ClassReader – 0.00% (0/1524 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1187 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.MethodWriter – 0.00% (0/922 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/736 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • okio.okio.Buffer – 0.00% (0/687 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/625 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.Frame – 0.00% (0/570 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 9.24% (9188/99417 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.00% (47232/524920), branch 3.56% (1772/49739), complexity 3.53% (1873/53026), method 5.44% (1516/27888), class 10.92% (408/3736)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6367 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.ClassReader – 0.00% (0/1524 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1187 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.MethodWriter – 0.00% (0/922 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/736 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • okio.okio.Buffer – 0.00% (0/687 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/625 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.Frame – 0.00% (0/570 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend scalar fallback (no native SIMD)
SIMD int-add (64K x300) java 98ms / native 99ms = 0.9x speedup
SIMD float-mul (64K x300) java 105ms / native 81ms = 1.2x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 78.000 ms
Base64 CN1 decode 87.000 ms
Base64 native encode 386.000 ms
Base64 encode ratio (CN1/native) 0.202x (79.8% faster)
Base64 native decode 311.000 ms
Base64 decode ratio (CN1/native) 0.280x (72.0% faster)
Image encode benchmark status skipped (SIMD unsupported)

shai-almog and others added 2 commits September 16, 2026 07:32
ComponentSpec, FidelitySpec and FidelitySpecParser carried a header that was
missing its "DO NOT ALTER OR REMOVE COPYRIGHT NOTICES" line, so the gate read it
as unsupported. Pre-existing, and only in scope because this change touches those
files. Replaced verbatim from a file that passes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
cn1_windows_window.cpp is C++ and wraps its whole body in an extern "C" block
that closes near the end of the file. I appended the native after it, so it got
C++ name mangling while the generated C calls the unmangled name. It compiles
and the LINKER fails:

  lld-link: error: undefined symbol:
    com_codename1_impl_windows_WindowsNative_systemUsesDarkTheme___R_boolean

Worth recording that scripts/check-native-signatures.sh passed on this. It
verifies the NAME encodes the Java signature correctly, which it did; linkage is
a different property and the verifier does not look at it. The only thing that
reported this was a real Windows build, which is what the cross-compile leg is
for.

The Linux equivalent needs no change: cn1_linux_window.c is C, where there is no
mangling to avoid.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9cc51f2193

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/run-desktop-fidelity-tests.sh
Comment thread docs/developer-guide/Native-Themes.asciidoc Outdated
@shai-almog

shai-almog commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 166 screenshots: 166 matched.
Native Windows port (x64 / Intel-AMD): full hellocodenameone screenshot suite rendered offscreen with Direct2D/DirectWrite, plus the real benchmarks (base64 native/CN1/SIMD, image createMask/applyMask/modifyAlpha/PNG/JPEG, SSE2 SIMD kernels). Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 63ms / native 4ms = 15.7x speedup
SIMD float-mul (64K x300) java 70ms / native 4ms = 17.5x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 201.000 ms
Base64 CN1 decode 130.000 ms
Base64 SIMD encode 102.000 ms
Base64 encode ratio (SIMD/CN1) 0.507x (49.3% faster)
Base64 SIMD decode 108.000 ms
Base64 decode ratio (SIMD/CN1) 0.831x (16.9% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 39.000 ms
Image createMask (SIMD on) 4.000 ms
Image createMask ratio (SIMD on/off) 0.103x (89.7% faster)
Image applyMask (SIMD off) 41.000 ms
Image applyMask (SIMD on) 70.000 ms
Image applyMask ratio (SIMD on/off) 1.707x (70.7% slower)
Image modifyAlpha (SIMD off) 56.000 ms
Image modifyAlpha (SIMD on) 52.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.929x (7.1% faster)
Image modifyAlpha removeColor (SIMD off) 54.000 ms
Image modifyAlpha removeColor (SIMD on) 52.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.963x (3.7% faster)

@shai-almog

shai-almog commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 166 screenshots: 166 matched.
Native Windows port (arm64 / Apple Silicon - Arm): full hellocodenameone screenshot suite rendered offscreen with Direct2D/DirectWrite, plus the real benchmarks (base64 native/CN1/SIMD, image createMask/applyMask/modifyAlpha/PNG/JPEG, NEON SIMD kernels). Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 57ms / native 3ms = 19.0x speedup
SIMD float-mul (64K x300) java 57ms / native 4ms = 14.2x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 244.000 ms
Base64 CN1 decode 128.000 ms
Base64 SIMD encode 66.000 ms
Base64 encode ratio (SIMD/CN1) 0.270x (73.0% faster)
Base64 SIMD decode 62.000 ms
Base64 decode ratio (SIMD/CN1) 0.484x (51.6% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 6.000 ms
Image createMask (SIMD on) 3.000 ms
Image createMask ratio (SIMD on/off) 0.500x (50.0% faster)
Image applyMask (SIMD off) 23.000 ms
Image applyMask (SIMD on) 17.000 ms
Image applyMask ratio (SIMD on/off) 0.739x (26.1% faster)
Image modifyAlpha (SIMD off) 16.000 ms
Image modifyAlpha (SIMD on) 41.000 ms
Image modifyAlpha ratio (SIMD on/off) 2.563x (156.3% slower)
Image modifyAlpha removeColor (SIMD off) 21.000 ms
Image modifyAlpha removeColor (SIMD on) 11.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.524x (47.6% faster)

shai-almog and others added 4 commits September 16, 2026 08:10
Codex caught this: the gated leg set was still gnome+windows. The macOS gate
commit was cherry-picked onto this branch and then silently undone, because the
merge with master restored these two files from a401e5d -- the branch tip
recorded BEFORE the cherry-pick.

My own check for it was wrong too: I grepped for the string and matched the
`all)` case one line below, so the file read as correct.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The Android and Desktop sections appeared twice, the second copy carrying the
stale numbers from before the widget fixes (80.8/84.7, macOS "not captured yet").
A merge artifact from rebuilding the branch.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Each was checked against the code before being acted on; all five were real.

**The dark-mode native could not link** (P1). Already fixed in 9cc51f2 --
cn1_windows_window.cpp is C++ and the definition sat after the extern "C" block
closed.

**Bundling MacOSAquaTheme.res did not make the Mac port use it** (P1).
MacImplementation inherits IOSImplementation.installNativeTheme(), whose only
choices are iOSModernTheme, iOS7Theme and iPhoneTheme, so a native Mac
application installed an iPhone design language however its hints were set.
IOSImplementation gains a protected nativeThemeResourceName(mode) hook that
returns null -- iOS behaviour unchanged -- and MacImplementation overrides it to
answer MacOSAquaTheme for auto/aqua/native while letting modern/ios7 fall through
to the iOS chain, so a project that deliberately wants the iOS look keeps it.

**Hover was never cleared when the pointer left the window** (P2). Motion simply
stops, and Form only re-pointed its tracked hover when a DIFFERENT component was
reported, so the last control stayed lit with the cursor elsewhere. Windows now
arms TrackMouseEvent and handles WM_MOUSELEAVE; Linux connects leave-notify-event.
Two things that had to be found by reading rather than by taking the review at
face value: the GTK handler would have been dead code without adding
GDK_LEAVE_NOTIFY_MASK to the widget's event mask, and Form.pointerHover only
updated hover inside `if (cmp != null)`, so the leave event would have done
nothing at all. The update now happens unconditionally, and the tooltip lookup
just above it is guarded -- a null cmp is reachable for the first time.

**getFlattenedStyle had no hover branch** (P2). A UIID deriving from one that
declares .hover, without redeclaring it, merged the parent chain with its own raw
(empty) hover map and silently lost the parent's rollover colours. Hover now
dispatches like every other state.

**The Windows leg could not find its JDK** (P1). setup-java hands back a native
C:\... path and Git Bash's `test -x` does not resolve it, so the leg would exit 25
without rendering a tile -- a "no java" message on a runner that has one.
Normalized with cygpath, the way the fidelity app's own mvnw already does, with
the .exe suffix handled rather than assumed.

**The documented desktop default was wrong** (P2). The guide said auto/native;
resolveDesktopNativeTheme returns legacy when the hint is unset. Codex offered
either fix and the doc is the correct one to change: keeping an existing desktop
project on the theme it has always loaded is the deliberate back-compat policy,
not an oversight.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
github-code-quality raised ten findings in this file. One holds up and is fixed;
nine do not, and the reasons are written into the file header rather than left in
a review thread nobody reads.

FIXED. RasterizationScale was compared with != 1.0. It is a double, and a display
that is 1x in every way that matters can report a value a hair off it, which
would raise a blocker about a scale nobody set. Now a tolerance. The `!= 0`
beside it stays exact on purpose: that is not a measurement, it is the sentinel
for "XamlRoot was null", assigned literally and exactly representable.

PUSHED BACK, "calls to unmanaged code". There is no managed equivalent for any of
it. The program exists to photograph what the compositor actually put on screen
-- PrintWindow with PW_RENDERFULLCONTENT, BitBlt with CAPTUREBLT, DwmFlush,
TrackMouseEvent. A managed screenshot API answers a different question, "what
does XAML think it drew" rather than "what did DWM composite", and that exact
substitution is what made an earlier version of this app report success while
capturing unstyled controls.

PUSHED BACK, "generic catch clause", six times. Narrowing them would make the app
worse at its one job. It is a capture probe whose contract is that it refuses to
produce a reference set it cannot vouch for, so every failure has to become a
recorded blocker rather than an escaping exception that kills the process with no
manifest. Each broad catch is paired with a documented fallback or with a blocker
naming the stage and the HRESULT. A typed list would have to enumerate every COM
failure a hosted runner can produce, and the ones it missed would crash silently
instead of being reported.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Comment thread scripts/fidelity-app/windows-native-ref/Program.cs
Comment thread scripts/fidelity-app/windows-native-ref/Program.cs Fixed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1c9bd626c7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Ports/MacPort/src/com/codename1/impl/mac/MacImplementation.java
Comment thread Ports/LinuxPort/nativeSources/cn1_linux_window.c Outdated
Comment thread Ports/WindowsPort/src/com/codename1/impl/windows/WindowsImplementation.java Outdated
Comment thread CodenameOne/src/com/codename1/ui/Form.java Outdated
Vale: "Use 'doesn't' instead of 'does not'" in the desktop theme default I just
rewrote. The same rule PR #5841 applied to the earlier text in this file.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

Setting the CN1 progress bar to 60 to match the desktop reference apps changed it
for the MOBILE rows too, and their goldens are captured at 0.5 --
RefWidgets.java sets setProgress(50) and NativeRef.swift sets p.progress = 0.5.
So a desktop fix quietly moved the iOS and Android suites off their own
references.

Now scoped by row: slider 0.5 everywhere, progress 0.6 on desktop and 0.5 on
mobile, each mirroring the reference app that captured that set. Desktop scores
are unchanged by the scoping (Windows mean 82.2%, progress 74.5/74.7).

Found by asking whether an unrelated Android leg's failure could be mine rather
than assuming the emulator flaked. The emulator trouble in that run was real and
separate; this was underneath it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

Reviewed commit: ad9dca5355

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review the full PR at e1a67fc, including any remaining findings. Native macOS screenshot CI exposed that the earlier AppKit alias fix affected modern-mode apps too. The fix now uses AppKit aliases only for Aqua/auto/native and preserves the historical iOS-style mapping, with the compatibility reason in source. Three actual Apple-port mode tests and the AppKit resolver test pass; nine GUI progress tests pass. All 71 backend HTTP integration tests also pass locally without changes. Native screenshot CI will verify that the remaining differences are confined to the three Window-Layout progress strips, where the custom-border guard intentionally preserves the generic Slider rounded rectangle.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: e1a67fc944

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review the full PR at 960a2a9 for any remaining findings. This follow-up changes only the three Window-Layout PNGs and records their provenance. Hosted run 35169743013 confirmed 157 screenshots equal and exactly these three different after the scoped font fix. Every changed pixel is inside rows 193–208 of the progress strip; text, layout, and window dimensions are unchanged. The generic Slider rounded rectangle intentionally preserves its border and height, covered by the source comment and GUI regression test. All three captured images pass the unchanged strict comparator against the updated references. No tolerances or native-fidelity baselines changed; fresh CI and desktop fidelity are running.

@shai-almog

shai-almog commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 148 screenshots: 148 matched.
✅ Native Mac screenshot tests passed.

Benchmark Results

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

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 59ms / native 13ms = 4.5x speedup
SIMD float-mul (64K x300) java 55ms / native 2ms = 27.5x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 155.000 ms
Base64 CN1 decode 89.000 ms
Base64 native encode 578.000 ms
Base64 encode ratio (CN1/native) 0.268x (73.2% faster)
Base64 native decode 225.000 ms
Base64 decode ratio (CN1/native) 0.396x (60.4% faster)
Base64 SIMD encode 47.000 ms
Base64 encode ratio (SIMD/CN1) 0.303x (69.7% faster)
Base64 SIMD decode 43.000 ms
Base64 decode ratio (SIMD/CN1) 0.483x (51.7% faster)
Base64 encode ratio (SIMD/native) 0.081x (91.9% faster)
Base64 decode ratio (SIMD/native) 0.191x (80.9% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 8.000 ms
Image createMask (SIMD on) 2.000 ms
Image createMask ratio (SIMD on/off) 0.250x (75.0% faster)
Image applyMask (SIMD off) 37.000 ms
Image applyMask (SIMD on) 28.000 ms
Image applyMask ratio (SIMD on/off) 0.757x (24.3% faster)
Image modifyAlpha (SIMD off) 26.000 ms
Image modifyAlpha (SIMD on) 24.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.923x (7.7% faster)
Image modifyAlpha removeColor (SIMD off) 31.000 ms
Image modifyAlpha removeColor (SIMD on) 24.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.774x (22.6% faster)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 960a2a92fb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/check-fidelity-spec.py Outdated
@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review the full PR at f356e67 for any remaining findings. The latest Linux/GNOME platform-filter finding is fixed, tested against the actual compiled ComponentSpec, explained in a source comment, and its thread is resolved. All 17 validator regressions and the 33-component spec pass. This does not change rendering, current spec rows, or the three inspected Window references. Please review the complete final change, including any other issues.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

Reviewed commit: f356e67a4c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review the full PR at 0d56f82. The final follow-up fixes the Android CI crash traced to InPlaceEditViewTest calling native stopEdit on the CN1 EDT. It now uses the existing AndroidImplementation.stopEditing UI-thread handoff, keeps all 50 edit/relayout/teardown cycles, and propagates EDT exceptions instead of swallowing them. A clean Android app build and the full targeted fixture passed on an isolated API 36 emulator: 50 teardown calls all on Android main, suite finished in 11 seconds, no wrong-thread or message-queue errors. Please check correctness and scope of this repair along with the complete theme changes.

@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review the latest head 9ee3b9f, including the Android fixture repair described above. The only change after 0d56f82 is the standard copyright header required for this newly touched file; the full changed-source header check now passes. Runtime verification remains the 50-cycle API 36 stress run, with all native teardowns on Android main.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

Reviewed commit: 9ee3b9f5b3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@shai-almog

shai-almog commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 160 screenshots: 160 matched.
✅ Native Mac screenshot tests passed.

Benchmark Results

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

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 54ms / native 3ms = 18.0x speedup
SIMD float-mul (64K x300) java 56ms / native 2ms = 28.0x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 183.000 ms
Base64 CN1 decode 101.000 ms
Image encode benchmark iterations 100
Image createMask (SIMD off) 12.000 ms
Image createMask (SIMD on) 8.000 ms
Image createMask ratio (SIMD on/off) 0.667x (33.3% faster)
Image applyMask (SIMD off) 64.000 ms
Image applyMask (SIMD on) 44.000 ms
Image applyMask ratio (SIMD on/off) 0.688x (31.3% faster)
Image modifyAlpha (SIMD off) 44.000 ms
Image modifyAlpha (SIMD on) 46.000 ms
Image modifyAlpha ratio (SIMD on/off) 1.045x (4.5% slower)
Image modifyAlpha removeColor (SIMD off) 41.000 ms
Image modifyAlpha removeColor (SIMD on) 48.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 1.171x (17.1% slower)

shai-almog and others added 8 commits September 17, 2026 10:25
The Boot simulator step twice hung with no output at all and burned the
job's entire 90-minute budget -- on this branch (run 35175449094) and
independently on master (run 35130437729), at the identical step. Both
ended as CANCELLED, which reads as "a human stopped it" rather than as a
failure, and both step logs were empty, so there was not even evidence of
which of the four simctl calls hung.

Move the step into a script that puts each call on a deadline, samples the
hung process before killing it, and recovers once by restarting
CoreSimulatorService. The one retry is allowed here because the thing
retried is not ours and carries no signal about the code under test; the
script's header records that reasoning, the two runs above, and the two
simctl call sites in the tree that remain unguarded.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three gaps in the desktop theme hint, all of them things a developer
reading DesktopBuild could not find out:

- desktop.themeMode accepted "modern" at runtime and the annotation's
  valuePattern rejected it, so the compiler refused a value the port
  honours.
- There was no single hint for "look like the platform, everywhere".
  nativeTheme=modern reaches iOS and Android only, and deliberately so --
  it predates the desktop themes by years, so a desktop application that
  set it for its phone builds never asked for its desktop screens to move.
  ThemeMode.NATIVE is that value: modern plus the desktop.
- Nothing said which hint governs which platform, or what each value
  installs. Both tables now live on the DesktopBuild annotation type,
  not on the attribute: an attribute's prose is harvested verbatim into
  the developer guide's AsciiDoc hint table, where a markdown table
  collapses onto one line with every pipe escaped.

"native" had to be taught to every consumer, because an unrecognised
theme mode is never an error -- it falls back, silently, and each fallback
was wrong in a different direction. IPhoneBuilder mapped it to "auto",
which installNativeTheme() resolves to the FLAT iOS 7 theme; the Android
runtime fell through to Holo Light. macOS already answered Aqua for it and
needed nothing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The smoke job greps CodenameOne/src for the removed browser editor's name.
That name is also a principality and a monospace font, and core is four
thousand files of framework source, so the bare word over it was never a
tripwire -- it was a guarantee of an eventual false positive. It fired:
PhoneNumberField's dialing-code table lists the principality, and the job
went red on a pull request that had touched neither the editor nor that
file. The workflow only triggers on scripts/cn1playground changes, so the
table sat there unnoticed for two and a half weeks and then detonated on
the first unrelated change that happened to touch the playground tree.

Over core the name now counts only where it is shaped like a dependency --
adjacent to '-', '.' or '/'. That is every way the editor is really
referenced (package name, JS namespace, loader path) and none of the ways
the word occurs in prose or a font stack; checked against five realistic
reintroductions and three legitimate uses. The playground's own tree is
small and controlled, so the bare name stays forbidden there.

No \b in the pattern, deliberately: `git grep -E` honours neither \b nor \<
on macOS, so a word-boundary version would match NOTHING on a developer
machine and pass for that reason.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A build hint attribute's javadoc is harvested verbatim into the guide's
hint table, so it is published prose and Vale lints it as such. The two
paragraphs added for the native theme mode tripped four alerts -- two
Microsoft.Contractions errors on "does not" and two Microsoft.Adverbs
warnings on "deliberately" -- and the docs job treats warnings as
build-breaking.

The DesktopBuild paragraph also carried a parenthetical explaining to the
next editor why javadoc link syntax is avoided there. That is an internal
authoring note, and it was being published in a customer-facing document.
It moves to a // comment ABOVE the /// run, which is invisible to the
harvester -- below would be worse than invisible, because a non-/// line
discards the pending comment and the attribute would reach the guide with
no description at all.

Verified with the CI configuration: vale --config docs/developer-guide/.vale.ini
--minAlertLevel=suggestion now reports 0 alerts over the whole guide. The two
"table cell has been truncated" PDF errors in the same log are pre-existing --
the same count appears in the last run of this workflow that passed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
An Android job died on three HTTP 500s from GitHub releases inside six
seconds, and the same URL served a range request perfectly a few minutes
later. Three attempts two seconds apart all land inside the same outage
window: they cost the runner six seconds, buy nothing, and throw away a
sixteen-minute job over a transient upstream error.

Four attempts now, with the wait GROWING -- 10s, 40s, 160s. That is the
lesson scripts/ci/retry.sh already records for Maven Central 403s, applied
to the other download an Android build cannot proceed without. The worst
case adds about three and a half minutes before giving up, which is cheap
next to the job it saves. The wait is also logged, so a failure says how
long it actually tried.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
"Add place and route-stop labels to vector maps" (#5853) changed
TileRenderer, MapStyle, MapView and Routing and reseeded no screenshot
baseline on any port, so master has been red on build-macos ever since:
NativeMapFallback, RealOsmVector, VectorMapDarkStyle, VectorMapMarkers and
VectorMapShapes, pass=183 fail=5 skip=4, identical on master and here.

Every frame was reviewed before adopting it. Each keeps its own test
content -- the single marker, the three markers, the circle/polyline/
rectangle overlays, the dark palette with light-on-dark label text -- and
gains only the street and place labels the feature adds. No regression.

Adopted from the runner's own output. The five PNGs are byte identical
between master's run (35188870596) and this branch's (35239993396), so the
desktop theme work in this branch does not touch them and it does not
matter which run they came from; the committed files verify against both.

Only macOS noticed. Every other port ships a .tolerance sidecar for these
tests (maxChannelDelta=40, maxMismatchPercent=10.0) and scripts/macos has
no tolerance files at all, so it compares exactly. The labels cover under
10% of the pixels, which means Android, Linux, iOS, JavaScript and Windows
absorbed the change silently and their goldens now depict a map the app no
longer draws. That decay is real but it is not failing, and reseeding it
needs frames those passing runs do not upload.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The four server processes each redirect their combined output to a file and
nothing ever read one back, so an intermittent failure arrived as
"expected: <200> but was: <-1>" and nothing else. That does not separate the
three answers that matter -- the server refused the request, the server never
saw it, or the server is gone -- and without the distinction there is nothing
to debug from.

Two vm-tests runs were lost to exactly that. aLargeUploadIsReadWhole answered
an empty reply in 0.020s and aZeroMinimumBodyRateDoesNotKillTheConnection in
0.304s, both on a body that needs a second read, and neither says whether a
connection was dropped or a process had died. A full local reproduction --
18 clean runs of the class, plus pipelined, split-boundary, 2MB-upload and
48-connection stress against a locally built server -- did not reproduce
either, so the next occurrence has to carry its own evidence.

A TestWatcher rather than a message on each assertion, because the next
occurrence will not be in a test anyone thought to instrument. Proven to fire
by injecting a failure: it prints each server's liveness and the tail of its
log, which is how the pool-mode worker counts and the small-upload server's
clamped settings became visible at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
openTls() installed a TrustManager whose check methods are empty, which
verifies nothing at all -- including that the server presented the
certificate it was configured with, the one thing a TLS test is in a
position to assert. CodeQL rates it a high-severity alert, and it is the
shape every "disable certificate checking" answer on the internet has, so
leaving a copy in this repository invites it to be pasted somewhere it is
not a throwaway localhost socket.

Pinned to the self-signed certificate startTlsServer already writes, as a
trust anchor. Path validation only: these sockets reach 127.0.0.1 while the
certificate names localhost, and a raw SSLSocket does no hostname check
unless one is asked for.

Verified both ways, because a trust manager that accepts everything and one
that is correct both look like a passing suite: 71/71 with 0 skipped against
the real certificate, and pinning a DIFFERENT self-signed certificate turns
the four TLS tests into "PKIX path validation failed: Path does not chain
with any of the trust anchors".

Pre-existing, and identical on master -- it surfaced here only because
CodeQL's diff-informed analysis re-read the region after the 72-line
diagnostics change above it shifted the file.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@shai-almog
shai-almog merged commit a8da698 into master Sep 18, 2026
100 checks passed
@shai-almog
shai-almog deleted the desktop-macos-fidelity-gate branch September 18, 2026 03:07
shai-almog added a commit that referenced this pull request Sep 18, 2026
A native defined in a .cpp or .mm file is name-mangled unless it is declared extern "C".
The file compiles. The symbol it exports is not the one the generated code calls. The
link fails on the device, in a file nobody touched, naming a symbol that is visibly right
there in the source.

NativeSignatureVerifier cannot see this, and not by oversight: it checks that a native's
NAME matches its Java method, and a mangled function has the right name too. Linkage is
not part of a name. #5845 shipped exactly this in cn1_windows_window.cpp and only a real
Windows build caught it, which is why this PR's two new menu natives were written inside
extern "C" by hand and why that being right by hand is not good enough.

scripts/check-native-cpp-linkage.py reads every tracked .cpp/.cc/.cxx/.mm, needs no
compiler and no build output, and has no baseline and no exclusions -- a native without C
linkage is never intentional and the fix is always one line.

Verified it bites rather than assuming it does. The historical bug is not reproducible
from master (#5845 fixed it before merge), so the probe removes the extern "C" wrapper
from cn1_windows_menu.cpp with the braces kept balanced: the gate names
menuSetCommands___java_lang_String at its line and exits 1. It stays silent on the four
things it must not report -- a prototype, a commented-out native, a port-internal C++
helper, and the single-declaration extern "C" form.

That last one was a false positive on the first version, worth recording because the fix
is not obvious: the definition regex starts at the line break, so a 200-character lookback
for extern "C" ended BEFORE it. Anchoring the test inside the declaration itself fixes it
and closes a false NEGATIVE at the same time -- a loose lookback would have accepted

    extern "C" void somethingElse(void);
    JAVA_VOID com_codename1_..._native(...) { }

where the linkage belongs to the line above.

--self-test carries nine fixtures and runs in CI beside the gate, because the way a gate
like this fails is silent: a parser that stops recognising definitions reports zero
findings, which reads exactly like a clean tree. Confirmed by breaking the regex in a
scratch copy -- three cases fail and it exits 1.

The script is re-included in pr.yml's paths on BOTH triggers. scripts/** is excluded
there, so without that a change weakening this gate would merge without it ever running,
which is the reason already written above the native-warnings entries.

Co-Authored-By: Claude Opus 5 (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