Summary: | JPopupMenu unusable over NewtCanvasAWT on Linux (even with lightweight-popups disabled) | ||
---|---|---|---|
Product: | [JogAmp] Newt | Reporter: | Mike Hogye <stacktracer> |
Component: | awt | Assignee: | Sven Gothel <sgothel> |
Status: | UNCONFIRMED --- | ||
Severity: | normal | CC: | geoff.ulman |
Priority: | --- | ||
Version: | 1 | ||
Hardware: | All | ||
OS: | linux | ||
Type: | --- | SCM Refs: | |
Workaround: | --- |
Description
Mike Hogye
2015-02-06 18:24:08 CET
It turns out to be pretty obvious what's going on here. NewtCanvasAWT explicitly adds a window-listener that kills the Swing menu whenever its newtChild gains focus: http://jogamp.org/git/?p=jogl.git;a=blob;f=src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java;h=5920d6de84755ed21ef24ff2f620ef3969bfe8a2;hb=HEAD#l258 (If that link doesn't work, look at NewtCanvasAWT.java, and search for "clearAWTMenusOnNewtFocus".) The listener is there for a reason -- without it, the popup menu can't be dismissed by just clicking outside it, which is quite annoying for a user. However, on Linux, the listener (usually) gets fired immediately after the popup-menu becomes visible. Don't know why. Maybe a race between the Swing EDT thread and the Newt EDT thread? Here's a workaround. Not great for all possible situations, but probably good enough in many cases. 1. Consume the window-gained-focus event, before it can trigger clearAWTMenusOnNewtFocus (note that we're adding this listener at index 0, so that it runs before clearAWTMenusOnNewtFocus): glWindow.addWindowListener( 0, new WindowAdapter( ) { public void windowGainedFocus( WindowEvent ev ) { // Consume the event, to keep it from triggering clearAWTMenusOnNewtFocus ev.setConsumed( true ); } } ); 2. Do a little extra work when popping up the menu, so that the menu gets dismissed when you click outside it: glWindow.addMouseListener( new MouseAdapter( ) { public void mousePressed( final MouseEvent ev ) { SwingUtilities.invokeLater( new Runnable( ) { public void run( ) { if ( !menu.isVisible( ) ) { menu.show( glCanvas, ev.getX( ), ev.getY( ) ); } else { menu.setVisible( false ); } } } ); } } ); That's going to swallow all window-gained-focus events, so there are cases where it’s not a good option. But in many cases it may be better than popup-menus being broken. Here's the test case with workaround: https://gist.github.com/stacktracer/0617b091d3d184f0a887 |