Add native desktop themes and platform fidelity testing - #5845
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 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".
|
Developer Guide build artifacts are available for download from this workflow run:
Developer Guide quality checks: |
✅ Continuous Quality ReportTest & Coverage
Static Analysis
Generated automatically by the PR CI workflow. |
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>
c1e1ff6 to
1d3c16b
Compare
There was a problem hiding this comment.
💡 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".
|
Compared 12 screenshots: 12 matched. |
Native fidelity (Android, Material 3)54 pairs compared -- median 95.6%, worst 91.3% ( Distribution --
Geometry vs native (bbox offset / size ratio / center offset / corner radius) -- gated separately from the visual score
Side-by-side comparisons (worst first)
|
Cloudflare Preview
|
|
Compared 151 screenshots: 151 matched. Native Android coverage
✅ Native Android screenshot tests passed. Native Android coverage
Benchmark ResultsDetailed Performance Metrics
|
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>
There was a problem hiding this comment.
💡 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".
|
Compared 166 screenshots: 166 matched. Benchmark ResultsDetailed Performance Metrics
|
|
Compared 166 screenshots: 166 matched. Benchmark ResultsDetailed Performance Metrics
|
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>
There was a problem hiding this comment.
💡 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".
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>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
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>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Codex Review: Didn't find any major issues. Keep it up! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
|
@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. |
|
Codex Review: Didn't find any major issues. 👍 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
|
@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. |
|
Compared 148 screenshots: 148 matched. Benchmark Results
Detailed Performance Metrics
|
There was a problem hiding this comment.
💡 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".
|
@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. |
|
Codex Review: Didn't find any major issues. Another round soon, please! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
|
@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. |
|
@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. |
|
Codex Review: Didn't find any major issues. Already looking forward to the next diff. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
|
Compared 160 screenshots: 160 matched. Benchmark Results
Detailed Performance Metrics
|
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>
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>












































































































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: