This discussion is archived
3 Replies Latest reply: Feb 26, 2010 7:59 AM by 843807 RSS

Unable to receive grab event by using GRAB_EVENT_MASK?

843807 Newbie
Currently Being Moderated
I added an AWTEventListener to process grab event. So this listener just use sun.awt.SunToolkit.GRAB_EVENT_MASK
mark.
But This listener can not capture UngrabEvent. The tricky thing is, when a JComboBox popuped its menulist, it can capture this event.
I use the following code for testing.
Start the program, click on the empty area of the frame, click on the frame title. Then there should be an UngrabEvent. But the listener does not capture it.
Start the program, click on the combobox and make its menulist popuped. click on the
frame title. Then there should be an UngrabEvent. And the listener captures it.
It is very strange...Is there any relationship between UngrabEvent and JComboBox?
public class ComboboxLearn {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        toolkit.addAWTEventListener(new AWTEventListener() {

            @Override
            public void eventDispatched(AWTEvent event) {
                System.out.println(event);
            }
        }, sun.awt.SunToolkit.GRAB_EVENT_MASK);
        JComboBox box = new JComboBox(new Object[] { "AAA", "BBB", "CCC" });

        box.addPopupMenuListener(new PopupMenuListener() {

            @Override
            public void popupMenuCanceled(PopupMenuEvent e) {
                System.out.println(e);
            }

            @Override
            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                System.out.println(e);// Set a breakpoint here
            }

            @Override
            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
                System.out.println(e);
            }
        });

        JFrame f = new JFrame();
        f.getContentPane().setLayout(new FlowLayout());
        f.getContentPane().add(box);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(new Dimension(100, 100));

        f.setVisible(true);
    }
}
  • 1. Re: Unable to receive grab event by using GRAB_EVENT_MASK?
    843807 Newbie
    Currently Being Moderated
    A quick grep of the source shows that BasicPopupMenuUI uses GRAB_EVENT_MASK and UngrabEvent.

    One question for you is: what are you actually trying to accomplish? There is likely a better way than relying on undocumented events. Your code might not work on non-Sun JRE's, for example.
  • 2. Re: Unable to receive grab event by using GRAB_EVENT_MASK?
    843807 Newbie
    Currently Being Moderated
    I am trying to implement a popup panel using java.swing.Popup. Unlike JComboBox popup list (BasicPopupMenuUI), I wanan a popup that could chould add any component but not only item.

    The problem of Java,swing.Popup is it will not hide when userws click on ther place. So I try to add a AWTEventListener and hide Popup when some event occurs such as WINDOWS_LOSE_FOUCS. It works fine on other kinds of events, but not for grab event.

    Here is my listener:
    class PopupHider implements AWTEventListener {
    
            @Override
            public void eventDispatched(AWTEvent event) {
                if (event instanceof sun.awt.UngrabEvent) {
                    // Popup should be canceled in case of ungrab event
                    handleHide();
                    return;
                }
                if (event instanceof MouseEvent) {
    
                    MouseEvent me = (MouseEvent) event;
                    Component src = me.getComponent();
                    if (!(event instanceof MouseEvent)) {
                        return;
                    }
                    switch (me.getID()) {
                    case MouseEvent.MOUSE_PRESSED:
                        if (!isInPopupPanel(src)) {
                            // should not happen
                            handleHide();
                        }
                        break;
                    }
                } else if (event instanceof WindowEvent) {
                    switch (event.getID()) {
                    case WindowEvent.WINDOW_LOST_FOCUS:
                        handleHide();
                        break;
                    case WindowEvent.WINDOW_ACTIVATED:
                        handleHide();
                        break;
                    case WindowEvent.WINDOW_GAINED_FOCUS:
                        handleHide();
                        break;
                    }
                } else if (event instanceof KeyEvent) {
                    if (((KeyEvent) event).getKeyCode() == KeyEvent.VK_ESCAPE) {
                        handleHide();
                    }
                }
            }
        }
    Add the listener when popup shows
        private void registorListener() {
            Toolkit toolkit = Toolkit.getDefaultToolkit();
            toolkit.addAWTEventListener(hider, AWTEvent.MOUSE_EVENT_MASK
                    | AWTEvent.WINDOW_EVENT_MASK
                    | sun.awt.SunToolkit.GRAB_EVENT_MASK | AWTEvent.KEY_EVENT_MASK);
        }
    And remove it when popup hides
        private void handleHide() {
            Toolkit toolkit = Toolkit.getDefaultToolkit();
            toolkit.removeAWTEventListener(hider);
            popup.hide();
        }
  • 3. Re: Unable to receive grab event by using GRAB_EVENT_MASK?
    843807 Newbie
    Currently Being Moderated
    I must admit I'm still not 100% clear on what an "ungrab event' is, even after reading its Javadoc (specifically, what couldn't be accomplished with a WindowListener, for example). But that aside, I've implemented custom popups in the past with JWindows. You can make an undecorated window look however you want (in my case, it was custom, focusable tool tips). It was a more robust solution than using javax.swing.Popup.

    so I'd suggest trying to use JWindows instead of Popups. It might be a little more legwork, but it'll pay off in the end. I bet you can accomplish what you're trying to do without resorting to using private API's.