Skip to content

Conversation

@ShahzaibIbrahim
Copy link
Contributor

Problem Description

In MenuItem#calculateRenderSize, a GC (graphics context) is created using this.getMenu().getShell(). However, this assumes that the menu returned by getMenu() is non-null, which is only valid for MenuItems with style SWT.CASCADE that have an explicitly assigned submenu.

For MenuItems with styles like SWT.PUSH, SWT.CHECK, or SWT.RADIO, the result of getMenu() is null, as these items do not have submenus. Attempting to call getShell() on a null Menu leads to a NullPointerException during size computation.

To address this, we replace:

GC gc = new GC(this.getMenu().getShell());

with:

GC gc = new GC(this.getParent().getShell());

This ensures that the GC is always created using the Shell associated with the parent Menu, which is guaranteed to exist, regardless of the MenuItem style.

How to Reproduce

In order to reproduce, run the runtime workspace with following plug-in added to your configuration: org.eclipse.ui.examples.contributions and add these two menuItem in menucontribution

<extension
    point="org.eclipse.ui.menus">
      <menuContribution
           locationURI="menu:org.eclipse.ui.main.menu?after=additions">
           <command
               commandId="org.eclipse.ui.window.preferences"
               label="Preferences"
               style="push">
         </command>
         <command
                 commandId="org.eclipse.ui.help.aboutAction"
                 label="About"
                 icon="icons/empty.png"
                 style="push"> 
           </command>
      </menuContribution>
  </extension>

Previously, you would have got this error:

java.lang.NullPointerException: Cannot invoke "org.eclipse.swt.widgets.Menu.getShell()" because the return value of "org.eclipse.swt.widgets.MenuItem.getMenu()" is null
	at org.eclipse.swt.widgets.MenuItem.calculateRenderedTextSize(MenuItem.java:1310)
	at org.eclipse.swt.widgets.MenuItem.wmMeasureChild(MenuItem.java:1253)
	at org.eclipse.swt.widgets.Control.WM_MEASUREITEM(Control.java:5260)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4820)
	at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:336)
	at org.eclipse.swt.widgets.Decorations.windowProc(Decorations.java:1494)
	at org.eclipse.swt.widgets.Shell.windowProc(Shell.java:2378)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:5128)
	at org.eclipse.swt.internal.win32.OS.DefWindowProc(Native Method)
	at org.eclipse.swt.widgets.Shell.callWindowProc(Shell.java:504)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4881)
	at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:336)
	at org.eclipse.swt.widgets.Decorations.windowProc(Decorations.java:1494)
	at org.eclipse.swt.widgets.Shell.windowProc(Shell.java:2371)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:5128)
	at org.eclipse.swt.internal.win32.OS.BringWindowToTop(Native Method)
	at org.eclipse.swt.widgets.Decorations.bringToTop(Decorations.java:215)
	at org.eclipse.swt.widgets.Shell.open(Shell.java:1284)
	at org.eclipse.e4.ui.workbench.renderers.swt.WBWRenderer.postProcess(WBWRenderer.java:743)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:676)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:762)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:727)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:47)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:711)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1079)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1042)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:153)
	at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:678)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:583)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:173)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:185)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:219)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:149)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:115)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:467)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:298)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:627)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:575)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1431)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1403)
	Suppressed: java.lang.NullPointerException: Cannot invoke "org.eclipse.swt.widgets.Menu.getShell()" because the return value of "org.eclipse.swt.widgets.MenuItem.getMenu()" is null
		... 44 more

Expected result

No error should appear in console.

fixes: #2247

@github-actions
Copy link
Contributor

github-actions bot commented Jul 29, 2025

Test Results

   546 files  ±0     546 suites  ±0   29m 29s ⏱️ -28s
 4 412 tests ±0   4 395 ✅ ±0   17 💤 ±0  0 ❌ ±0 
16 718 runs  ±0  16 591 ✅ ±0  127 💤 ±0  0 ❌ ±0 

Results for commit a7ec5cd. ± Comparison against base commit fc94eaf.

♻️ This comment has been updated with latest results.

Copy link
Contributor

@HeikoKlare HeikoKlare left a comment

Choose a reason for hiding this comment

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

The change looks fine. I just wonder if there is a reason to not fix getMonitorZoom() in the same way in this PR as well?

@ShahzaibIbrahim
Copy link
Contributor Author

The change looks fine. I just wonder if there is a reason to not fix getMonitorZoom() in the same way in this PR as well?

No, I just missed it.

@ShahzaibIbrahim ShahzaibIbrahim force-pushed the master-337 branch 2 times, most recently from ca49709 to b1043eb Compare July 29, 2025 15:04
Previously, calculateRenderSize() and getMonitorZoom() of MenuItem used
getMenu() to get some context providing the relevant shell instead of
getParent(). Since that menu may be null when the MenuItem has no submenu
(e.g., PUSH, CHECK styles), an NPE might have been thrown.

This change replaces getMenu().getShell() with getParent().getShell(),
ensuring a valid shell is always used regardless of item type.

Fixes eclipse-platform#2247
Copy link
Contributor

@HeikoKlare HeikoKlare left a comment

Choose a reason for hiding this comment

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

Thank you! The changes look simple and reasonable.

I have tested them with multiple configurations (including applications with DPI awareness "System" and "PerMonitorV2" and particularly including dark theme) in which the affected code is executed and relevant. I found no changes in behavior, except that the bug reported in #2247 does not occur anymore.

@HeikoKlare HeikoKlare changed the title Fix NPE in MenuItem#calculateRenderSize for non-cascade items Fix NPEs in MenuItem#calculateRenderSize() and MenuItem#getMonitorZoom() Jul 29, 2025
@HeikoKlare HeikoKlare merged commit bef3ad7 into eclipse-platform:master Jul 29, 2025
17 checks passed
@HeikoKlare HeikoKlare deleted the master-337 branch July 29, 2025 15:47
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.

Check for null when calling Menu#getShell SWT getMenu() NPE

2 participants