Bug 1127 - JPopupMenu unusable over NewtCanvasAWT on Linux (even with lightweight-popups disabled)
Summary: JPopupMenu unusable over NewtCanvasAWT on Linux (even with lightweight-popups...
Alias: None
Product: Newt
Classification: JogAmp
Component: awt (show other bugs)
Version: 1
Hardware: All linux
: --- normal
Assignee: Sven Gothel
Depends on:
Reported: 2015-02-06 18:24 CET by Mike Hogye
Modified: 2015-02-06 20:19 CET (History)
1 user (show)

See Also:
Type: ---
SCM Refs:
Workaround: ---


Note You need to log in before you can comment on or make changes to this bug.
Description Mike Hogye 2015-02-06 18:24:08 CET
I have a NewtCanvasAWT, with a GLWindow child, and a mouse-press listener that shows a JPopupMenu. On Windows, it always works fine. On Linux, the popup-menu is visible for a split second, then disappears.

I am already calling "JPopupMenu.setDefaultLightWeightPopupEnabled(false)" and/or "menu.setLightWeightPopupEnabled(false)". That is not the problem here.

Sometimes, after I start my program, the popup-menu works fine a few times. But eventually, after working correctly a few times, it starts disappearing (after being visible for a split second). Once the disappearing starts, it never seems to stop again, until I close and rerun the program.

Here's a test case:

Comment 1 Mike Hogye 2015-02-06 18:29:56 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:


(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?
Comment 2 Mike Hogye 2015-02-06 18:38:53 CET
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( ) );
                        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.
Comment 3 Mike Hogye 2015-02-06 18:43:37 CET
Here's the test case with workaround: