[visad] JPopupMenus on Java 1.6 on Linux can eat mouse up events

Hi,

I am just posting this for the benefit of the list. We recently uncovered a bug in one of our applications which uses VisAD. In short, when showing a JPopupMenu above a Canvas, using Java 1.6 on Linux, Java eats any mouse up event following a mouse down that caused you to display the popup. This is a problem for VisAD as it maintains its own copy of mouse button state which becomes invalid, so most mouse behaviour stops working properly.

I have attached some sample code used to fix this, which creates a new mouse up event. The comments also provide a better description of the issue.

  Hope it helps someone.

Andrew.

--

Andrew Donaldson
Meteorological Systems Development Manager
Bureau of Meteorology
ph 03 9669 4537
...
                // Add popup listener
                popupMenu.addPopupMenuListener(
                        new SelectionPopupMenuListener());
                popupMenu.show(component, screen[0], screen[1]);
                popupMenu.repaint();
        }


        /**
         * This popup menu listener creates a MouseEvent of type MOUSE_RELEASED
         * for BUTTON3 when the popup WillBecomeInvisible.
         * This is a work around for a bug seen on Java 1.6 (up to _22) on
         * Linux, where the MOUSE_RELEASED event following the MOUSE_PRESSED
         * event which causes us to call popupMenu.show() goes missing.
         * This bug is not seen with Java 1.5 on Linux or Windows, nor
         * is it seen with Java 1.6 on Windows.
         *
         * The symptom seen in TC Module is that after a popup menu is
         * displayed in the map area, all VisAD mouse presses appear to
         * not work properly (or at all).  This is because VisAD maintains
         * its own mouse button states, which become incorrect if the
         * MOUSE_RELEASED event for the right mouse button does not arrive.
         * VisAD interprets a BUTTON1_PRESSED event while BUTTON3 is
         * thought to be down, to be a virtual button press rather than a
         * BUTTON1 press.
         *
         * This bug could have been fixed by changing VisAD to use the
         * system mouse button state rather than using its own copy, however
         * the fix implemented here is considered to be lower impact and
         * more easily removed should Java 1.6 on Linux one day send the
         * missing MOUSE_RELEASED event.
         */
        private class SelectionPopupMenuListener implements PopupMenuListener
        {
                public void popupMenuWillBecomeVisible(PopupMenuEvent e)
                {
                        ;
                }


                public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
                {
                        JPopupMenu popupMenu = (JPopupMenu)e.getSource();
                        Rectangle rectangle = popupMenu.getBounds();
                        Canvas canvas = displayRenderer.getCanvas();
                        MouseEvent mouseEvent = new MouseEvent(
                                canvas,
                                MouseEvent.MOUSE_RELEASED,
                                (new java.util.Date()).getTime(),
                                MouseEvent.BUTTON3_MASK,
                                (int)rectangle.getX(),
                                (int)rectangle.getY(),
                                1, false);
                        canvas.dispatchEvent(mouseEvent);
                }


                public void popupMenuCanceled(PopupMenuEvent e)
                {
                        ;
                }
        }