Hi all, I dedicate this mail to Barry because he reported the issue first, and besides, I miss him ;-)
The issue Barry pointed out earlier, on Ubuntu, was that ImageJ2 started behaving strangely with regards to the menu: as soon as the mouse was hovering over the tool bar, the menu would go away. Back then, I could not reproduce the issue, but today I could, so I went on a hunt, and here is the write-up for everybody to enjoy: First of all, I figured that I should find out whether some strange AWT events were processed, so I fired up Eclipse -- because I wanted to use Eclipse's debugger to investigate the issue -- and added this code to the end of AbstractSwingUI#createUI(): -- snip -- Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { @Override public void eventDispatched(AWTEvent event) { System.err.println("event: " + event); } }, -1); -- snap -- Basically, this code asks Java to output all the UI events as they happen. Then, I set a breakpoint on the first line and started ImageJ2 in debug mode. A little-known gem is that Eclipse's Console window not only shows the standard output and standard error stream of the debugged program, but also accepts the standard input. I used this fact by adding some empty lines (simply focusing the Console window and hitting the Return key a couple of times) as soon as the main window was visible because the events that had been shown so far could not be responsible (or so I thought). But after moving the mouse over the toolbar (and the menu bar vanishing), really only the obvious events were shown: mouse enter, mouse moves (and then mouse leave). So I imagined that another way to debug the issue might be to look whether there actually *was* a menu bar still when the tool bar was painted after the mouse entered the main window. To this end, I patched in a paintComponent method into the SwingToolBar class: -- snip -- @Override public void paintComponent(final Graphics g) { Container c = getParent(); c = c.getParent(); c = c.getParent(); c = c.getParent(); System.err.println(c); System.err.println(((JFrame)c).getJMenuBar()); super.paintComponent(g); } -- snap -- Of course, that was not the initial version. The initial version assumed that already the direct parent container of the tool bar would be the JFrame, and in hindsight, I'd better have written something like: Container c = getParent(); while (c != null && !(c instanceof JFrame)) { c = c.getParent(); } but hindsight is 20/20 and I did not have the luxury of that yet. However, I had the luxury of incremental compilation (as performed by Eclipse, one of the few things I really like about Eclipse): I could set a breakpoint on the "System.err.println(c);" call, launch ImageJ2 in debug mode, and then insert the "c = c.getParent();" lines one by one, saving them, which would trigger Eclipse's incremental compiler and move execution back to the first line of the method, until I had the right amount. And sure enough, the first time round, there was a menu bar, but after moving the mouse over the main window the menu bar was null! Therefore the next step was to find out when it was set to null. To find out, I edited the SwingApplicationFrame class (which I found out from inspecting the "c" variable in the SwingToolBar#paintComponent(Graphics) method above) like so: -- snip -- @Override public void setJMenuBar(final JMenuBar bar) { super.setJMenuBar(bar); } -- snap -- and -- you probably guessed it by now -- added a breakpoint on the "super.setJMenuBar(bar);" line. It turns out that it is called the first time from AbstractSwingUI#createUI(), as expected, but then -- unexpectedly -- from MacOSXPlatform#onEvent(WinActivatedEvent)! On Linux, no less... There we have the culprit. As I found out by inserting -- snip -- if (c.getName().endsWith("WinActivatedEvent")) { System.err.println(); } -- snap -- into the DefaultEventService#subscribe(Class, EventSubscriber) method and -- you probably guessed that again -- setting a breakpoint on the "System.err.println();" line (after importing scijava-common into the Eclipse workspace and adjusting ImageJ2's pom.xml to set the scijava-common.version property to point to the checked out version), MacOSXPlatform is registered as an event listener. This is the consequence of some subtle, recent change that at the same time a Context is injected, the class is also automatically registered as event listener if it has @EventHandler-annotated methods). Now, MacOSXPlatform's onEvent() method does not verify that the current platform is actually MacOSX, nor does the EventService "forget" the MacOSXPlatform as one would expect when the MacOSXPlatform is garbage-collected after it has been determined that it does not match the current platform because the PlatformService is now a SingletonService that does not let go of its instances... So we actually need two changes to fix this: 1) MacOSXPlatform#onEvent(WinActivatedEvent) needs to be safe, and 2) the DefaultPlatformService must not keep references to Platform instances that are not applicable to the currently-running platform. https://github.com/imagej/imagej/commit/c814f4b0 addresses 1) while https://github.com/scijava/scijava-common/commit/46f64db2 and https://github.com/scijava/scijava-common/commit/522f524 address 2) Ciao, Dscho _______________________________________________ ImageJ-devel mailing list ImageJ-devel@imagej.net http://imagej.net/mailman/listinfo/imagej-devel