Skip to content

Fix #4979: dim backdrop persists after Dialog from on-top side menu#4983

Merged
liannacasper merged 4 commits into
masterfrom
fix-4979-sidemenu-command-dialog-overlay
May 19, 2026
Merged

Fix #4979: dim backdrop persists after Dialog from on-top side menu#4983
liannacasper merged 4 commits into
masterfrom
fix-4979-sidemenu-command-dialog-overlay

Conversation

@shai-almog
Copy link
Copy Markdown
Collaborator

Summary

  • The on-top side menu's command dispatch (SideMenuBar.CommandWrapper.actionPerformed) used to fire cmd.actionPerformed(evt) synchronously right after kicking off the side menu's async dispose animation. If the command opens a modal Dialog (exactly what the initializr archetype's hello() does), the Dialog's event pump takes the EDT before the dispose animation has a chance to advance, so the detachToolbarLayeredPane onFinish never fires and the dim layered-pane backdrop stays visible after the Dialog is dismissed.
  • Adds public closeSideMenu(Runnable), closeLeftSideMenu(Runnable), closeRightSideMenu(Runnable) overloads on Toolbar that invoke the supplied callback once the dispose animation has finished and the layered pane is detached; SideMenuBar now routes the command-fire through that callback.
  • This is a sibling fix to [BUG] Toolbar side menu leaves the underlying Form shaded after close in the Simulator #4912 (commit d042971) which handled the tap-outside-to-dismiss close path; The gray overlay after the dialog closes does not clear... #4979 is the tap-a-command path where the close races with the command's Dialog.

Reproducer (from the issue)

Default initializr project — Hi form with a side-menu "Hello Command" that calls Dialog.show("Hello Codename One", "Welcome to Codename One", "OK", null). Open side menu → tap Hello Command → Dialog appears → OK → form stays shaded.

Test plan

  • New regression test ToolbarTest.sideMenuCommandFiresAfterLayeredPaneDetach captures the dim-pane reference, fires the command via pointer events, and asserts the captured pane is detached before the listener runs.
  • Full core-unittests suite passes locally on macOS / JDK 8 (2501 tests, 0 failures).
  • Manual repro on Windows 11 + Temurin 17 (the reporter's environment) once the PR is merged into a snapshot the initializr serves.
  • Verify the initializr-page browser demo's side-menu command also fires — the reporter says that bug stems from the same root cause and should clear up once this lands.

🤖 Generated with Claude Code

shai-almog and others added 2 commits May 19, 2026 07:36
Tapping a command in the on-top side menu used to translate to a
synchronous closeSideMenu() followed immediately by cmd.actionPerformed
on the same EDT call (SideMenuBar.CommandWrapper.actionPerformed). When
the command shows a modal Dialog -- which is exactly what the default
initializr archetype's `hello()` does -- the Dialog's event pump took
over the EDT before the side menu's async dispose animation had a
chance to advance. The dispose onFinish runnable that calls
detachToolbarLayeredPane never fired, so the Toolbar's dim layered-
pane backdrop (bgColor=0, bgTransparency around 64) stayed attached
to the form. After the user dismissed the Dialog the form was still
shaded.

This is a sibling of #4912 (fixed in d042971). #4912 handled the
"close the side menu by tapping outside" path; #4979 is the "tap a
command" path where the close races with the command's Dialog.

Fix lands in two pieces:

* Toolbar gains public closeSideMenu(Runnable), closeLeftSideMenu(
  Runnable), and closeRightSideMenu(Runnable) overloads that invoke
  the supplied callback once the dispose animation has completed and
  the layered pane has been detached. When no menu is open the
  callback runs synchronously. closeSideMenu(Runnable) waits for
  both left and right to finish if both are showing.
* SideMenuBar.CommandWrapper.actionPerformed routes the
  cmd.actionPerformed(evt) through this onFinish in the on-top
  branch. The non-onTop branch (lines 1812+) was already correct --
  it defers via ShowWaiter.

Regression test added: ToolbarTest.sideMenuCommandFiresAfterLayered-
PaneDetach opens the side menu, captures the dim pane reference,
fires the command button via pointer events, and asserts that when
the command's listener runs the captured pane is already detached.
The dispose animation is disabled via reflection so the test does
not depend on wall-clock animation timing (which the test EDT can't
tick while blocked on the test body). The existing right-side
dispatch test needed the same animation-disable for the same reason
-- pulled into a disableSideMenuAnimation helper.

All 2501 tests in core-unittests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SpotBugs rule SIC_INNER_SHOULD_BE_STATIC_ANON on the prior commit's
anonymous countdown Runnable inside closeSideMenu(Runnable) -- it
captured only locals (the remaining[] array and the onFinish
Runnable) and never used the enclosing Toolbar instance, so it was
holding the implicit outer-this reference for nothing.

Extracts the logic into a private static final
CloseSideMenuCountdown class with a plain int field, which is both
cleaner and SpotBugs-clean. No behavioural change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 19, 2026

Android screenshot updates

Compared 110 screenshots: 109 matched, 1 updated.

  • StatusBarTapDiagnosticScreenshotTest — updated screenshot. Screenshot differs (320x640 px, bit depth 8).

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

Native Android coverage

  • 📊 Line coverage: 11.83% (6580/55602 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.53% (33027/346425), branch 4.13% (1358/32888), complexity 5.19% (1635/31518), method 9.03% (1331/14738), class 15.12% (302/1998)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)
      • kotlinx.coroutines.kotlinx.coroutines.JobSupport – 0.00% (0/423 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 693.000 ms
Base64 CN1 encode 271.000 ms
Base64 encode ratio (CN1/native) 0.391x (60.9% faster)
Base64 native decode 1082.000 ms
Base64 CN1 decode 261.000 ms
Base64 decode ratio (CN1/native) 0.241x (75.9% faster)
Image encode benchmark status skipped (SIMD unsupported)

@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 19, 2026

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

Benchmark Results

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

Build and Run Timing

Metric Duration
Simulator Boot 100000 ms
Simulator Boot (Run) 2000 ms
App Install 16000 ms
App Launch 5000 ms
Test Execution 362000 ms

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 2130.000 ms
Base64 CN1 encode 3002.000 ms
Base64 encode ratio (CN1/native) 1.409x (40.9% slower)
Base64 native decode 1966.000 ms
Base64 CN1 decode 1777.000 ms
Base64 decode ratio (CN1/native) 0.904x (9.6% faster)
Base64 SIMD encode 1223.000 ms
Base64 encode ratio (SIMD/native) 0.574x (42.6% faster)
Base64 encode ratio (SIMD/CN1) 0.407x (59.3% faster)
Base64 SIMD decode 754.000 ms
Base64 decode ratio (SIMD/native) 0.384x (61.6% faster)
Base64 decode ratio (SIMD/CN1) 0.424x (57.6% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 160.000 ms
Image createMask (SIMD on) 24.000 ms
Image createMask ratio (SIMD on/off) 0.150x (85.0% faster)
Image applyMask (SIMD off) 287.000 ms
Image applyMask (SIMD on) 190.000 ms
Image applyMask ratio (SIMD on/off) 0.662x (33.8% faster)
Image modifyAlpha (SIMD off) 226.000 ms
Image modifyAlpha (SIMD on) 161.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.712x (28.8% faster)
Image modifyAlpha removeColor (SIMD off) 247.000 ms
Image modifyAlpha removeColor (SIMD on) 130.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.526x (47.4% faster)
Image PNG encode (SIMD off) 1367.000 ms
Image PNG encode (SIMD on) 1074.000 ms
Image PNG encode ratio (SIMD on/off) 0.786x (21.4% faster)
Image JPEG encode 548.000 ms

@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 19, 2026

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

Benchmark Results

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

Build and Run Timing

Metric Duration
Simulator Boot 89000 ms
Simulator Boot (Run) 2000 ms
App Install 21000 ms
App Launch 52000 ms
Test Execution 311000 ms

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 2090.000 ms
Base64 CN1 encode 2424.000 ms
Base64 encode ratio (CN1/native) 1.160x (16.0% slower)
Base64 native decode 2139.000 ms
Base64 CN1 decode 1534.000 ms
Base64 decode ratio (CN1/native) 0.717x (28.3% faster)
Base64 SIMD encode 648.000 ms
Base64 encode ratio (SIMD/native) 0.310x (69.0% faster)
Base64 encode ratio (SIMD/CN1) 0.267x (73.3% faster)
Base64 SIMD decode 815.000 ms
Base64 decode ratio (SIMD/native) 0.381x (61.9% faster)
Base64 decode ratio (SIMD/CN1) 0.531x (46.9% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 165.000 ms
Image createMask (SIMD on) 16.000 ms
Image createMask ratio (SIMD on/off) 0.097x (90.3% faster)
Image applyMask (SIMD off) 247.000 ms
Image applyMask (SIMD on) 193.000 ms
Image applyMask ratio (SIMD on/off) 0.781x (21.9% faster)
Image modifyAlpha (SIMD off) 180.000 ms
Image modifyAlpha (SIMD on) 81.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.450x (55.0% faster)
Image modifyAlpha removeColor (SIMD off) 305.000 ms
Image modifyAlpha removeColor (SIMD on) 501.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 1.643x (64.3% slower)
Image PNG encode (SIMD off) 3889.000 ms
Image PNG encode (SIMD on) 1072.000 ms
Image PNG encode ratio (SIMD on/off) 0.276x (72.4% faster)
Image JPEG encode 596.000 ms

PMD rule AssignmentInOperand on the prior commit's `--remaining == 0`
predecrement-then-compare in CloseSideMenuCountdown.run. Hoist the
decrement to its own statement. No behavioural change.

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

github-actions Bot commented May 19, 2026

✅ Continuous Quality Report

Test & Coverage

Static Analysis

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

Generated automatically by the PR CI workflow.

…ac is happy

The Ports/Android Ant build compiles CodenameOne/src under
encoding=ASCII (build.xml line 111). My PR-#4983 comment included a
literal U+2014 em-dash which the ASCII javac rejected with
"unmappable character (0xE2/0x80/0x94)". Swap the em-dash for a
double hyphen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@liannacasper liannacasper merged commit 315cf37 into master May 19, 2026
18 checks passed
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.

2 participants