Community
Participate
Working Groups
This is a tricky bug! I have a situation where File > Exit properly has visible set to false by the CocoaUIHandler, but is magically made visible again. It happens as the Exit item is added through a MenuContribution. I have an e4 application with an app.e4xmi and fragment.e4xmi. The app.e4xmi defines a window with a top-level menu containing a "File" menu. The fragment.e4xmi defines a menu contribution that contributes an "Exit" to the "File" menu. This exit is a handled menu item for "org.eclipse.ui.file.exit". The CocoaUIHandler from o.e.e4.ui.workbench.renderer.swt.cocoa correctly causes the Exit item to be made invisible; that menu functionality is now handled through the app's menu. BUT the "Exit" item magically re-appears when rendering the File menu! I'll attach a demo app and a patch in a sec.
Created attachment 185026 [details] e4photo-about Bundle providing an e4 fragment demonstrating the bug
In tracing this through, it turns out that the MenuManagerRenderer$ContributionRecord #updateVisibility is updating the menu item's visibility with its *contribution*'s visibility (stack trace below): public void updateVisibility(IEclipseContext context) { ExpressionContext exprContext = new ExpressionContext(context); boolean isVisible = ContributionsAnalyzer.isVisible( menuContribution, exprContext); for (MMenuElement item : generatedElements) { if (isVisible && item.getVisibleWhen() != null) { MenuManagerRenderer.updateVisibility(getManagerForModel(), item, exprContext); } else { item.setVisible(isVisible); //*** } } getManagerForModel().markDirty(); } At line "***", item is our menu-item-that-should-be-hidden, and isVisible is calculated based on the *contribution* providing that menu item. I think this code should instead look like: public void updateVisibility(IEclipseContext context) { ExpressionContext exprContext = new ExpressionContext(context); for (MMenuElement item : generatedElements) { if (item.getVisibleWhen() != null) { MenuManagerRenderer.updateVisibility(getManagerForModel(), item, exprContext); } } getManagerForModel().markDirty(); //?? } I'm not sure if the last line is necessary either. At least, this produces the expected results. Daemon Thread [Thread-0] (Suspended (entry into method setVisible in UIElementImpl)) HandledMenuItemImpl(UIElementImpl).setVisible(boolean) line: 327 MenuManagerRenderer$ContributionRecord.updateVisibility(IEclipseContext) line: 529 MenuManagerRendererFilter.updateElementVisibility(MMenu, MenuManagerRenderer, MenuManager, IEclipseContext, boolean) line: 272 MenuManagerRendererFilter.showMenu(Event, Menu, MMenu, MenuManager) line: 248 MenuManagerRendererFilter.handleShow(Event, Menu, MMenu, MenuManager) line: 202 MenuManagerRendererFilter.safeHandleEvent(Event) line: 184 MenuManagerRendererFilter.access$1(MenuManagerRendererFilter, Event) line: 141 MenuManagerRendererFilter$SafeWrapper.run() line: 128 SafeRunner.run(ISafeRunnable) line: 42 MenuManagerRendererFilter.handleEvent(Event) line: 138 EventTable.sendEvent(Event) line: 84 Display.filterEvent(Event) line: 1044 Display.sendEvent(EventTable, Event) line: 3954 Menu(Widget).sendEvent(Event) line: 1435 Menu(Widget).sendEvent(int, Event, boolean) line: 1458 Menu(Widget).sendEvent(int) line: 1439 Menu.menuWillOpen(long, long, long) line: 728 Display.windowProc(long, long, long) line: 5299 OS.objc_msgSendSuper(objc_super, long, long, long, long, boolean) line: not available [native method] Display.applicationNextEventMatchingMask(long, long, long, long, long, long) line: 4701 Display.applicationProc(long, long, long, long, long, long) line: 5000 OS.objc_msgSend(long, long, long, long, long, boolean) line: not available [native method] NSApplication.nextEventMatchingMask(long, NSDate, NSString, boolean) line: 94 Display.readAndDispatch() line: 3448 PartRenderingEngine$6.run() line: 808 Realm.runWithDefault(Realm, Runnable) line: 332 PartRenderingEngine.run(MApplicationElement, IEclipseContext) line: 724 E4Workbench.createAndRunUI(MApplicationElement) line: 89 E4Application.start(IApplicationContext) line: 131 EclipseAppHandle.run(Object) line: 196 EclipseAppLauncher.runApplication(Object) line: 110 EclipseAppLauncher.start(Object) line: 79 EclipseStarter.run(Object) line: 369 EclipseStarter.run(String[], Runnable) line: 179 NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39 DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 Method.invoke(Object, Object...) line: 597 Main.invokeFramework(String[], URL[]) line: 622 Main.basicRun(String[]) line: 577 Main.run(String[]) line: 1410 Main.main(String[]) line: 1386
This is where we end up either 1) overly complex or 2) we simply don't have enough states :-) There's only one visible flag on the MenuItem in the end, which gets propagated to the renderer. We simply use the expression in the static MMenuContribution to calculate visibility on each SWT.Show. Do we provide a userVisible flag that can supplant the standard visible flag? So setting userVisible to TRUE or FALSE will override visible==(true|false)? PW
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant. -- The automated Eclipse Genie.
This is a mass change to close all e4 bugs marked with "stalebug" whiteboard. If this bug is still valid, please reopen and remove the "stalebug" keyword.