3

I'm recording AWT events (mouse_pressed, mouse_released, key_pressed, key_released, etc.) to a log to replay them back using Robot in unit tests. But I found that I sometimes need to insert mouse_released events when they are missing, because some of my components remove themselves on mouse_pressed so the mouse_released is never dispatched. I thought that a good approach would be to insert mouse_released whenever a mouse event is seen that has modifiersEx=Button1 followed by an event that has modifiersEx=0, unless the second event is already mouse_released. But I found a problem when using a JComboBox.

Here's a simple main function containing a JComboBox with a component under it that also receives mouse events.

Screenshot of window with JComboBox

import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.InputEvent;
import java.util.logging.Logger;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class DemoEvents {
    public static void main(String[] argv) {
        JFrame jframe = new JFrame("Test events");
        jframe.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        Container contentPane = jframe.getContentPane();
        contentPane.setLayout(new BorderLayout());
        JComboBox jcomboBox = new JComboBox(new String[]{"one", "two", "three"});
        JButton jbutton = new JButton("Hello");
        JPanel outerPanel = new JPanel();
        JPanel innerPanel = new JPanel();
        innerPanel.setLayout(new BoxLayout(innerPanel, BoxLayout.PAGE_AXIS));
        innerPanel.add(jcomboBox);
        innerPanel.add(jbutton);
        outerPanel.add(innerPanel);
        contentPane.add(outerPanel, BorderLayout.CENTER);
        jframe.setSize(200, 200);
        jframe.setVisible(true);

        long mask =
            AWTEvent.MOUSE_EVENT_MASK |
            AWTEvent.MOUSE_WHEEL_EVENT_MASK |
            AWTEvent.MOUSE_MOTION_EVENT_MASK;

        final Logger logger = Logger.getLogger("awt-events");
        Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
            @Override
            public void eventDispatched(AWTEvent event) {
                InputEvent ev = (InputEvent)event;
                logger.info(ev.toString());
            }
        }, mask);
    }
}

When clicking on the JComboBox and clicking item "one", I get these events. The mouse_entered with extModifiers=Button1 doesn't make sense, because it was dispatched after the mouse_released event! Here's a simplified log from when I clicked the combo box, then clicked the first item. Look at the bolded event at the bottom:

  1. MouseEvent[MOUSE_PRESSED,(1,13),button=1,modifiers=Button1,extModifiers=Button1,clickCount=1] on MetalComboBoxButton[...]
  2. MouseEvent[MOUSE_RELEASED,(1,13),button=1,modifiers=Button1,clickCount=1] on MetalComboBoxButton[...]
  3. MouseEvent[MOUSE_MOVED,(0,14),button=0,clickCount=0] on MetalComboBoxButton[...]
  4. MouseEvent[MOUSE_EXITED,(-2,15),button=0,clickCount=0] on MetalComboBoxButton[...]
  5. MouseEvent[MOUSE_ENTERED,(81,15),button=0,clickCount=0] on JComboBox[...]
  6. MouseEvent[MOUSE_MOVED,(81,15),button=0,clickCount=0] on JComboBox[...]
  7. (more moves)
  8. MouseEvent[MOUSE_EXITED,(69,24),button=0,clickCount=0] on JComboBox[...]
  9. MouseEvent[MOUSE_ENTERED,(69,0),button=0,clickCount=0] on ComboPopup.popup
  10. MouseEvent[MOUSE_MOVED,(69,0),button=0,clickCount=0] on ComboPopup.popup
  11. MouseEvent[MOUSE_EXITED,(68,2),button=0,clickCount=0] on ComboPopup.popup
  12. MouseEvent[MOUSE_ENTERED,(67,1),button=0,clickCount=0] on ComboBox.list
  13. MouseEvent[MOUSE_MOVED,(67,1),button=0,clickCount=0] on ComboBox.list
  14. (more moves)
  15. MouseEvent[MOUSE_PRESSED,(57,9),button=1,modifiers=Button1,extModifiers=Button1,clickCount=1] on ComboBox.list
  16. MouseEvent[MOUSE_RELEASED,(57,9),button=1,modifiers=Button1,clickCount=1] on ComboBox.list
  17. MouseEvent[MOUSE_ENTERED,(25,10),button=1,modifiers=Button1,extModifiers=Button1,clickCount=1] on JButton[...]
  18. MouseEvent[MOUSE_MOVED,(26,10),button=0,clickCount=0] on JButton[...]

Question: When is the order of mouse_pressed/mouse_released inconsistent with the modifiers of other mouse events? Is it only mouse_entered/mouse_exited events that happen with inconsistent modifiers? Does this only happen when clicking onJComboBox's popup?

I'm running Java 1.6 on Ubuntu.

Edit: included a longer log for clarity.

yonran
  • 18,156
  • 8
  • 72
  • 97

1 Answers1

1

On my platform, "clicking on the JComboBox and clicking item one" produces the events shown below.

The result may depend on com.apple.laf.AquaComboBoxButton, the platform's ComboBoxUI delegate. I am unable to account for the absence of MOUSE_CLICKED in your result. I did not move the mouse after clicking on the JComboBox; it appears that you did, and that result is recorded.

Note that "Extended modifiers represent the state of all modal keys, such as ALT, CTRL, META, and the mouse buttons just after the event occurred," so the presence of extModifiers on some events does not seem inconsistent. I don't see anything indicating that MOUSE_MOVED events include any modifiers at all.

I don't know a solution to the underlying problem, except to re-examine the need for a synthetic MOUSE_RELEASED event. As an alternative, you might verify that a component is removed by examining the containment hierarchy.

May 11, 2012 10:36:36 AM DemoEvents$1 eventDispatched
INFO: java.awt.event.MouseEvent[MOUSE_PRESSED,(85,9),absolute(124,58),button=1,modifiers=Button1,extModifiers=Button1,clickCount=1] on com.apple.laf.AquaComboBoxButton[…]
May 11, 2012 10:36:36 AM DemoEvents$1 eventDispatched
INFO: java.awt.event.MouseEvent[MOUSE_RELEASED,(85,9),absolute(124,58),button=1,modifiers=Button1,clickCount=1] on com.apple.laf.AquaComboBoxButton[…]
May 11, 2012 10:36:36 AM DemoEvents$1 eventDispatched
INFO: java.awt.event.MouseEvent[MOUSE_CLICKED,(85,9),absolute(124,58),button=1,modifiers=Button1,clickCount=1] on com.apple.laf.AquaComboBoxButton[…]
May 11, 2012 10:36:38 AM DemoEvents$1 eventDispatched
INFO: java.awt.event.MouseEvent[MOUSE_ENTERED,(91,6),absolute(124,58),button=1,modifiers=Button1,extModifiers=Button1,clickCount=1] on ComboBox.list
May 11, 2012 10:36:38 AM DemoEvents$1 eventDispatched
INFO: java.awt.event.MouseEvent[MOUSE_PRESSED,(91,6),absolute(124,58),button=1,modifiers=Button1,extModifiers=Button1,clickCount=1] on ComboBox.list
May 11, 2012 10:36:38 AM DemoEvents$1 eventDispatched
INFO: java.awt.event.MouseEvent[MOUSE_RELEASED,(91,6),absolute(124,58),button=1,modifiers=Button1,clickCount=1] on ComboBox.list
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • The event that I was referring to was right after your log, after the second click. In Ubuntu, after the second mouse_released there is a mouse_entered that still has a modifier. – yonran May 11 '12 at 17:29
  • OK, every `MOUSE_PRESSED` has `extModifiers`, but I see it on `MOUSE_ENTERED` only during `MOUSE_DRAGGED`, i.e. while the mouse button is still down. – trashgod May 11 '12 at 19:06
  • I don't know what's happends on *nix platform(s) +1 – mKorbel May 11 '12 at 22:13