Skip to content

8346753: Test javax/swing/JMenuItem/RightLeftOrientation/RightLeftOrientation.java fails on Windows Server 2025 x64 because the icons of RBMenuItem and CBMenuItem are not visible in Nimbus LookAndFeel #25907

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from

Conversation

prsadhuk
Copy link
Contributor

@prsadhuk prsadhuk commented Jun 20, 2025

Issue is RadioButtonMenuItem and CheckBoxMenuItem bullet/checkmark icon is not displayed in WindowsL&F when the test is run with NimbusL&F.
This is because WindowsIconFactory#VistaMenuItemCheckIcon.paintIcon called getLaFIcon() which returns a empty NimbusIcon which causes no icons to be drawn. This is because the test after setting WIndows L&F of the menuitem reverts back the Windows L&F to Nimbus L&F via UIManager.setLookAndFeel(save); call in the test so when frame is made visible, the L&F resets back to Nimbus L&F resulting in null NimbusIcon.

Fix is made to make sure the whole frame is updated to cater to L&F change via SwingUtilities.updateComponentTreeUI(frame); call and keep the L&F without reverting back to original L&F..


Progress

  • Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue

Issue

  • JDK-8346753: Test javax/swing/JMenuItem/RightLeftOrientation/RightLeftOrientation.java fails on Windows Server 2025 x64 because the icons of RBMenuItem and CBMenuItem are not visible in Nimbus LookAndFeel (Bug - P5)

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/25907/head:pull/25907
$ git checkout pull/25907

Update a local copy of the PR:
$ git checkout pull/25907
$ git pull https://git.openjdk.org/jdk.git pull/25907/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 25907

View PR using the GUI difftool:
$ git pr show -t 25907

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/25907.diff

Using Webrev

Link to Webrev Comment

…entation.java fails on Windows Server 2025 x64 because the icons of RBMenuItem and CBMenuItem are not visible in Nimbus LookAndFeel
@bridgekeeper
Copy link

bridgekeeper bot commented Jun 20, 2025

👋 Welcome back psadhukhan! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Jun 20, 2025

@prsadhuk This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

8346753: Test javax/swing/JMenuItem/RightLeftOrientation/RightLeftOrientation.java fails on Windows Server 2025 x64 because the icons of RBMenuItem and CBMenuItem are not visible in Nimbus LookAndFeel

Reviewed-by: abhiscxk

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 219 new commits pushed to the master branch:

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

➡️ To integrate this PR with the above commit message to the master branch, type /integrate in a new comment.

@openjdk
Copy link

openjdk bot commented Jun 20, 2025

@prsadhuk The following label will be automatically applied to this pull request:

  • client

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

@prsadhuk
Copy link
Contributor Author

/touch

@openjdk openjdk bot added the rfr Pull request is ready for review label Jun 20, 2025
@openjdk
Copy link

openjdk bot commented Jun 20, 2025

@prsadhuk The pull request is being re-evaluated and the inactivity timeout has been reset.

@prsadhuk
Copy link
Contributor Author

/touch

@openjdk
Copy link

openjdk bot commented Jun 20, 2025

@prsadhuk The pull request is being re-evaluated and the inactivity timeout has been reset.

@mlbridge
Copy link

mlbridge bot commented Jun 20, 2025

Webrevs

Copy link
Member

@aivanov-jdk aivanov-jdk left a comment

Choose a reason for hiding this comment

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

This is an invalid test. The L&F has to applied to entire component tree after the application changes it. One has not to expect anything to work correctly if the L&F is changed on the fly.

In this test, the L&F is set before menu items are created. Depending on the L&F internals, it may display well or not; for Windows L&F it doesn't.

The test has to be re-written so that a L&F is changed and the entire component tree is updated, at this pointer the tester verifies how menu items look.

Then the L&F can be changed to a next one. Ideally, all the installed L&Fs should be tested.

@prsadhuk
Copy link
Contributor Author

I dont think the test is invalid..It was in closed repo and tested for so many years before it got opensourced
L&F is anyway applied to entire component tree in the fix via SwingUtilities.updateComponentTreeUI(frame);
Similar method was used in opensourced test javax/swing/JTabbedPane/bug4499556.java by @prrace ..Its the similar strategy used in many closed/open manual tests for testing different L&Fs in applet era

@prrace Any comments on this test regarding its validity and fix?

@aivanov-jdk
Copy link
Member

I dont think the test is invalid..It was in closed repo and tested for so many years before it got opensourced L&F is anyway applied to entire component tree in the fix via SwingUtilities.updateComponentTreeUI(frame);

I believe what fixed the test is that you removed the line UIManager.setLookAndFeel(save) which restored the L&F to whatever L&F that was set before at the time when the test started, in this particular case Nimbus L&F according to the bug description.

This ensures the current L&F remains Windows L&F so that the missing resources are now found. If there were another L&F to test, or if Windows L&F weren't the last in the list, the test will continue to fail because the current L&F will again be different from Windows L&F.

Indeed, it does. If I comment out UIManager.setLookAndFeel(save) from the original test code, the menu items under Windows do have check marks and bullets.

At the same time, SwingUtilities.updateComponentTreeUI(frame) has no effect… however, it does change the L&F of the menu bar and the menu items on the menu bar.

The menu items that are displayed in popups aren't visible and aren't part of the component hierarchy, therefore they remain at the assigned L&F which was active when they were created.

Similar method was used in opensourced test javax/swing/JTabbedPane/bug4499556.java by @prrace ..Its the similar strategy used in many closed/open manual tests for testing different L&Fs in applet era

Yes, I've seen other tests which employ this strategy… where several components in a container are created with different L&Fs. And often everything seem to work… except for the cases where it doesn't.

This is the case where it doesn't…

Continuing with my example above where I commented out the line UIManager.setLookAndFeel(save), the Windows menu looks good but clicking the Metal menu now throws NPE:

java.lang.NullPointerException: Cannot invoke "java.awt.Font.hashCode()" because "font" is null
	at java.desktop/sun.font.FontDesignMetrics$MetricsKey.init(FontDesignMetrics.java:213)
	at java.desktop/sun.font.FontDesignMetrics.getMetrics(FontDesignMetrics.java:282)
	at java.desktop/sun.swing.SwingUtilities2.getFontMetrics(SwingUtilities2.java:1235)
	at java.desktop/javax.swing.JComponent.getFontMetrics(JComponent.java:1700)
	at java.desktop/sun.swing.MenuItemLayoutHelper.reset(MenuItemLayoutHelper.java:126)
	at java.desktop/javax.swing.plaf.synth.SynthMenuItemLayoutHelper.<init>(SynthMenuItemLayoutHelper.java:118)
	at java.desktop/javax.swing.plaf.synth.SynthGraphicsUtils.paint(SynthGraphicsUtils.java:578)
	at java.desktop/javax.swing.plaf.synth.SynthMenuUI.paint(SynthMenuUI.java:278)
	at java.desktop/javax.swing.plaf.synth.SynthMenuUI.update(SynthMenuUI.java:245)
	at java.desktop/javax.swing.JComponent.paintComponent(JComponent.java:852)
	at java.desktop/javax.swing.JComponent.paint(JComponent.java:1128)
	at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:961)
	at java.desktop/javax.swing.JComponent.paint(JComponent.java:1137)
	at java.desktop/javax.swing.JComponent.paintToOffscreen(JComponent.java:5324)

This makes sense, the Metal menu itself was created while Nimbus was the active L&F. (Yes, you moved the menu creation after the new L&F was set.) This just proves my point that multiple L&Fs aren't really supported.

@prrace Any comments on this test regarding its validity and fix?

I'm looking forward to seeing Phil's comments.

@prsadhuk
Copy link
Contributor Author

If there were another L&F to test, or if Windows L&F weren't the last in the list, the test will continue to fail because the current L&F will again be different from Windows L&F.

But there isn't..The L&F the test wanted to test and had tested since closed days are now working with the fix and this allows the test to run ok...I dont think its a product bug since the L&F was not propagated to all nodes of the Swing components after L&F change so it should be a test issue which was solved.
Rewriting the test, if needed, could be done as part of new issue but this one fixes the issue and let manual testing team run the test in all L&F

I commented out the line UIManager.setLookAndFeel(save), the Windows menu looks good but clicking the Metal menu now throws NPE:

I couldn't reproduce this problem with the current PR..What L&F you started the test with? I tested the test with Metal/Windows/Nimbus from the commandline and couldn't find any issue.

@aivanov-jdk
Copy link
Member

I dont think its a product bug since the L&F was not propagated to all nodes of the Swing components after L&F change so it should be a test issue which was solved.

I didn't say it was a product bug, it is rather a product feature: multiple L&Fs at the same time aren't really supported, have never been.

As I said above, the problem wasn't that the L&F wasn't propagated to all nodes of the Swing components. The problem is and was that the current L&F doesn't match the L&F with which a component was created.

Rewriting the test, if needed, could be done as part of new issue but this one fixes the issue and let manual testing team run the test in all L&F

Why not now? We have a bug in the test, your fix doesn't fix the fundamental problem with the test, but rather tweaks the test so that the problem isn't visible any more.

I commented out the line UIManager.setLookAndFeel(save), the Windows menu looks good but clicking the Metal menu now throws NPE:

I couldn't reproduce this problem with the current PR..What L&F you started the test with? I tested the test with Metal/Windows/Nimbus from the commandline and couldn't find any issue.

Nimbus, as specified in the command line in the bug description:

-vmoption:-Dswing.defaultlaf=javax.swing.plaf.nimbus.NimbusLookAndFeel

You can't reproduce NPE if there's a call to SwingUtilities.updateComponentTreeUI(frame) because it updates the L&F of the top-level menu items, those that are on the menu bar.

@prsadhuk
Copy link
Contributor Author

Rewriting the test, if needed, could be done as part of new issue but this one fixes the issue and let manual testing team run the test in all L&F

Why not now? We have a bug in the test, your fix doesn't fix the fundamental problem with the test, but rather tweaks the test so that the problem isn't visible any more.

I commented out the line UIManager.setLookAndFeel(save), the Windows menu looks good but clicking the Metal menu now throws NPE:

I couldn't reproduce this problem with the current PR..What L&F you started the test with? I tested the test with Metal/Windows/Nimbus from the commandline and couldn't find any issue.

Nimbus, as specified in the command line in the bug description:

-vmoption:-Dswing.defaultlaf=javax.swing.plaf.nimbus.NimbusLookAndFeel

You can't reproduce NPE if there's a call to SwingUtilities.updateComponentTreeUI(frame) because it updates the L&F of the top-level menu items, those that are on the menu bar.

I dont want to do it as I already told before..Its the same strategy used in other recently opensourced tests I mentioned before where SwingUtilities.updateComponentTreeUI(frame) is used ...

@aivanov-jdk
Copy link
Member

I dont want to do it as I already told before..Its the same strategy used in other recently opensourced tests I mentioned before where SwingUtilities.updateComponentTreeUI(frame) is used ...

But missing SwingUtilities.updateComponentTreeUI(frame) wasn't the problem, wasn't the root cause… in this particular case.

@prsadhuk
Copy link
Contributor Author

I dont want to do it as I already told before..Its the same strategy used in other recently opensourced tests I mentioned before where SwingUtilities.updateComponentTreeUI(frame) is used ...

But missing SwingUtilities.updateComponentTreeUI(frame) wasn't the problem, wasn't the root cause… in this particular case.

Adding this call and removing UIManager.setLookAndFeel(save) is what is used to not fallback to old L&F (this restoration to old L&F is also not used in other tests opensourced) and I stand by it..

@@ -83,7 +86,7 @@ public static void main(String[] args) throws Exception {
}

private static JFrame createTestUI() {
JFrame frame = new JFrame("RightLeftOrientation");
frame = new JFrame("RightLeftOrientation");
JMenuBar menuBar = new JMenuBar();

menuBar.add(createMenu("javax.swing.plaf.metal.MetalLookAndFeel",
Copy link
Contributor

Choose a reason for hiding this comment

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

I tried to extend the test (with this PR changes included) for all installed L&Fs and then create the menu for each L&F.

    UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels();
    for (final UIManager.LookAndFeelInfo lafInfo : lafs) {
        System.out.println("installed laf className : " + lafInfo.getClassName());
        System.out.println("installed laf Name : " + lafInfo.getName());
        menuBar.add(createMenu(lafInfo.getClassName(), lafInfo.getName()));
    }

Then the test failed with this exception

    java.lang.NullPointerException: Cannot invoke "java.awt.Font.hashCode()" because "font" is null
at java.desktop/sun.font.FontDesignMetrics$MetricsKey.init(FontDesignMetrics.java:213)
at java.desktop/sun.font.FontDesignMetrics.getMetrics(FontDesignMetrics.java:282)
at java.desktop/sun.swing.SwingUtilities2.getFontMetrics(SwingUtilities2.java:1235)

Otherwise the RBMI and CBMI does contain the icon after the fix.

Copy link
Member

Choose a reason for hiding this comment

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

This is similar to the exception that I got above. It's just a result of mixing several L&Fs at the same time.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes but it was not supposed to come when SwingUtilities.updateComponentTreeUI(frame) is used to update all UI components.

Copy link
Member

Choose a reason for hiding this comment

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

Yes but it was not supposed to come when SwingUtilities.updateComponentTreeUI(frame) is used to update all UI components.

Why not?

In fact, I expected that all the menu items would switch to the latest L&F after updating the component tree.

But it doesn't happen… because the menu bar isn't part of the component hierarchy (yet). If you move the call frame.setJMenuBar(menuBar) before each L&F menu is created, all the popup menus are displayed in Windows L&F, the latest installed L&F.

Either way, the test doesn't work correctly.

@kumarabhi006
Copy link
Contributor

One more thing I observed is "If we change the order of menu creation" then the icons rendered are different.
For e.g. if the order is

menuBar.add(createMenu("javax.swing.plaf.metal.MetalLookAndFeel",
            "Metal"));
    menuBar.add(createMenu("com.sun.java.swing.plaf.windows.WindowsLookAndFeel",
            "Windows"));
    menuBar.add(createMenu("com.sun.java.swing.plaf.motif.MotifLookAndFeel",
            "Motif"));

then the icons are
Windows_Second_Pos

and when Windows L&F is at last pos then rendered icons are
Windows_Last_Pos

Shouldn't the icons for the L&Fs be same ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Don't think it is required in the summary The tester is asked to compare left-to-right and right-to-left menus and judge whether they are mirror images of each other., it is mentioned in instruction.

Not mandatory but still for consistency, you can move This test checks if menu items lay out correctly when their on the same line as @summary.

@summary This test checks if menu items lay out correctly when their

@aivanov-jdk
Copy link
Member

One more thing I observed is "If we change the order of menu creation" then the icons rendered are different. For e.g. if the order is

Shouldn't the icons for the L&Fs be same ?

That's the purpose of the test but it fails to test it.

You've just found another proof that multiple L&Fs can't be used concurrently. I've been talking about it since the very start of this code review.

When you change L&F, all the UIDefaults of the old L&F are removed and values for the newly installed L&F are added.

If a component or its UI doesn't store a setting, such as color, font or icon, in its field, the setting is retrieved from UIDefaults — but the values are different now.

This is what happens in the current test without any changes. After Windows L&F is installed, the L&F is switched back to the whatever L&F was initially. As the result, there are no check marks and bullets in Windows L&F.

The test has to re-create its UI after testing for a L&F is complete. Such a scenario isn't supported by PassFailJFrame at the moment, see JDK-8357455 and #24439 (comment). There's no easy workaround.

The test doesn't receive events from PassFailJFrame, so the needs to be a custom UI, or the test should be run several times for different L&Fs.

@prsadhuk
Copy link
Contributor Author

prsadhuk commented Jul 4, 2025

The test has to re-create its UI after testing for a L&F is complete. Such a scenario isn't supported by PassFailJFrame at the moment, see JDK-8357455 and #24439 (comment). There's no easy workaround.

The test doesn't receive events from PassFailJFrame, so the needs to be a custom UI, or the test should be run several times for different L&Fs.

So do you propose to test like what is being done in https://github.com/openjdk/jdk/pull/24439/files passing L&F argument to jtreg tag?

@aivanov-jdk
Copy link
Member

The test has to re-create its UI after testing for a L&F is complete. Such a scenario isn't supported by PassFailJFrame at the moment, see JDK-8357455 and #24439 (comment). There's no easy workaround.
The test doesn't receive events from PassFailJFrame, so the needs to be a custom UI, or the test should be run several times for different L&Fs.

So do you propose to test like what is being done in https://github.com/openjdk/jdk/pull/24439/files passing L&F argument to jtreg tag?

Yes, this is the simplest way.

Another option is to have a driver class. For example, if no arguments are passed to main, the test gets the list of all available or specific L&F as hard-coded now, then runs the same test with a parameter that specifies a L&F to test. The driver then captures both standard output and error streams of the process and throws an exception if the exit code from the subprocess isn't 0.

The first approach is simpler as it uses jtreg to run the test with different parameters.

@prsadhuk
Copy link
Contributor Author

prsadhuk commented Jul 7, 2025

ok..test rewritten to have L&F run as different test via jtreg tags..

Copy link
Member

@aivanov-jdk aivanov-jdk left a comment

Choose a reason for hiding this comment

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

Looks good now, although I haven't run the test now.

There's a small nit around formatting to make the test code easier to read.

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Jul 7, 2025
@openjdk openjdk bot removed the ready Pull request is ready to be integrated label Jul 7, 2025
Copy link
Contributor

@kumarabhi006 kumarabhi006 left a comment

Choose a reason for hiding this comment

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

Ran the test on Windows platform and it works as expected.

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Jul 7, 2025
@prsadhuk
Copy link
Contributor Author

prsadhuk commented Jul 8, 2025

/integrate

@openjdk
Copy link

openjdk bot commented Jul 8, 2025

Going to push as commit 5205eae.
Since your change was applied there have been 225 commits pushed to the master branch:

Your commit was automatically rebased without conflicts.

@openjdk openjdk bot added the integrated Pull request has been integrated label Jul 8, 2025
@openjdk openjdk bot closed this Jul 8, 2025
@openjdk openjdk bot removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Jul 8, 2025
@openjdk
Copy link

openjdk bot commented Jul 8, 2025

@prsadhuk Pushed as commit 5205eae.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
client [email protected] integrated Pull request has been integrated
Development

Successfully merging this pull request may close these issues.

3 participants