Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4431868

Inconsistent mouse enter/exit events delivery

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P2 P2
    • 1.4.0
    • unknown, 1.4.0
    • client-libs
    • None
    • beta2
    • generic, sparc
    • solaris_2.5.1, solaris_8
    • Verified



      Name: dsR10078 Date: 03/29/2001


      We should clearly determine whether enter/exit events indicate that mouse
      pointer enters/exits Component bounds OR bounds of visible part of Component
      geometry.
      Currently it is not specified in javadoc and implementation arbitrarily
      chooses either of the options.
      This causes several inconsistencies in enter/exit event delivery between
      lightweights (with mouse events enabled) and heavyweights and between
      heavyweights on Win32 and Solaris/Linux.
      1.If mouse pointer is crosses a bound between a parent and its lightweight child:
          - if the parent is lightweight it receives enter/exit events
          - if the parent is heavyweight it doesn't receive enter/exit events
      2.If a heavyweight container has two children: lightweight and heavyweight, which
        has a common bound and mouse pointer crosses this bound:
          - if mouse is moved from the heavyweight child to the lightweight child
            the heavyweight container receives MOUSE_ENTERED
          - if mouse is moved from the lightweight child to the heavyweight child
            the heavyweight container receives MOUSE_EXITED
      3.If there is a top-level frame and it has a child which occupies all the frame
        rectangle and mouse pointer enters/exits the frame:
          - if the child is heavyweight:
              - on Win32 the frame doesn't receive mouse enter/exit events
              - on Solaris/Linux:
                   - if the frame is over the root window of the screen (there are no
                     other toplevel shells between the frame and the root window)
                     the frame doesn't receive mouse enter/exit events
                   - if the frame is not over the root window of the screen (there is
                     another toplevel shell between the frame and the root window)
                     the frame does receive mouse enter/exit events
          - if the child is lightweight:
              - the frame always receive enter/exit events

      The items 1 and 2 were introduced with the fix for 4150851.

      I consider this as a bug, since the section of lightweight meeting minutes
      devoted to mouse event propagation prescribes: "Lightweight components
      with any mouse events enabled behave exactly as heavyweight components".

      This bug has negative impact on Drag-and-Drop subsystem as the subsystem uses
      mouse event dispatching machinery to dispatch native drag notifications
      to java drop targets.

      Here is a test case to reproduce the problem:
      -------------------------------------------------------------------------------
      import java.awt.*;
      import java.awt.event.*;

      public class Test {
          static class LWComponent extends Component {
              static final Dimension preferredSize = new Dimension(50, 50);
              public void paint(Graphics g) {
                  final Color c = getBackground();
                  final Dimension size = getSize();
                  g.setColor(c);
                  g.fillRect(0, 0, size.width, size.height);
              }
              public Dimension getPreferredSize() {
                  return preferredSize;
              }
          }

          static class LWContainer extends Container {
              static final Dimension preferredSize = new Dimension(200, 100);
              public void paint(Graphics g) {
                  final Color c = getBackground();
                  final Dimension size = getSize();
                  g.setColor(c);
                  g.fillRect(0, 0, size.width, size.height);
                  super.paint(g);
              }
              public Dimension getPreferredSize() {
                  return preferredSize;
              }
          }

          static class HWContainer extends Panel {
              static final Dimension preferredSize = new Dimension(200, 100);
              public Dimension getPreferredSize() {
                  return preferredSize;
              }
          }

          static final MouseListener mouseListener = new MouseAdapter() {
                  public void mouseEntered(MouseEvent e) {
                      System.out.println(e);
                  }
                  public void mouseExited(MouseEvent e) {
                      System.out.println(e);
                  }
              };

          public static void main(String[] args) {
              final Component lwComponent1 = new LWComponent();
              final Component lwComponent2 = new LWComponent();
              final Container lwContainer = new LWContainer();
              final Container hwContainer = new HWContainer();
              final Frame frame = new Frame();

              lwComponent1.setBackground(Color.green);
              lwComponent2.setBackground(Color.yellow);
              lwContainer.setBackground(Color.red);
              hwContainer.setBackground(Color.blue);

              lwComponent1.setName("LW Component 1");
              lwComponent2.setName("LW Component 2");
              lwContainer.setName("LW Container");
              hwContainer.setName("HW Container");

              lwComponent1.addMouseListener(mouseListener);
              lwComponent2.addMouseListener(mouseListener);
              lwContainer.addMouseListener(mouseListener);
              hwContainer.addMouseListener(mouseListener);
              frame.addMouseListener(mouseListener);
              frame.addWindowListener(new WindowAdapter() {
                      public void windowClosing(WindowEvent e) {
                          frame.dispose();
                      }
                  });

              lwContainer.setLayout(new FlowLayout());
              hwContainer.setLayout(new FlowLayout());
              frame.setLayout(new GridLayout(2, 1));

              lwContainer.add(lwComponent1);
              hwContainer.add(lwComponent2);
              frame.add(lwContainer);
              frame.add(hwContainer);
              frame.pack();
              frame.setVisible(true);
          }
      }
      -------------------------------------------------------------------------------

      Run the test case. You will see a frame with two containers: red(lw) and blue(hw).
      Each container has a lightweight child: green and yellow respectively.
      To reproduce the problems:
      1.Position the pointer over the red container and move it
        into its green child. Here are the events dumped:
      java.awt.event.MouseEvent[MOUSE_EXITED,(124,43),mods=0,clickCount=0] on LW Container
      java.awt.event.MouseEvent[MOUSE_ENTERED,(49,38),mods=0,clickCount=0] on LW Component 1
        Then position the pointer over the blue container and move it
        into its yellow child. Here are the events dumped:
      java.awt.event.MouseEvent[MOUSE_ENTERED,(46,34),mods=0,clickCount=0] on LW Component 2
        Note that heavyweight container does not receive MOUSE_EXITED.
      2.Position the pointer over the green child and move it
        into its red container. Here are the events dumped:
      java.awt.event.MouseEvent[MOUSE_EXITED,(50,32),mods=0,clickCount=0] on LW Component 1
      java.awt.event.MouseEvent[MOUSE_ENTERED,(125,37),mods=0,clickCount=0] on LW Container
        Then position the pointer over the yellow child and move it
        into its blue container. Here are the events dumped:
      java.awt.event.MouseEvent[MOUSE_EXITED,(51,36),mods=0,clickCount=0] on LW Component 2
        Note that heavyweight container does not receive MOUSE_ENTERED.
      3.Position the pointer over the red container and move it to enter the blue container.
        Here are the events dumped:
      java.awt.event.MouseEvent[MOUSE_EXITED,(163,101),mods=0,clickCount=0] on LW Container
      java.awt.event.MouseEvent[MOUSE_EXITED,(163,123),mods=0,clickCount=0] on frame0
      java.awt.event.MouseEvent[MOUSE_ENTERED,(163,1),mods=0,clickCount=0] on HW Container
        Then position the pointer over the blue container and move it to enter the red container.
        Here are the events dumped:
      java.awt.event.MouseEvent[MOUSE_EXITED,(42,-2),mods=0,clickCount=0] on HW Container
      java.awt.event.MouseEvent[MOUSE_ENTERED,(42,120),mods=0,clickCount=0] on frame0
      java.awt.event.MouseEvent[MOUSE_ENTERED,(42,98),mods=0,clickCount=0] on LW Container
        Note that the frame receives MOUSE_ENTERED/MOUSE_ENTERED.
      4.Position the mouse pointer outside of the frame and move it to enter red container.
        When the pointer is on the red container move it back to exit the frame.
        Here are the events dumped:
      java.awt.event.MouseEvent[MOUSE_ENTERED,(191,90),mods=0,clickCount=0] on frame0
      java.awt.event.MouseEvent[MOUSE_ENTERED,(187,67),mods=0,clickCount=0] on LW Container
      java.awt.event.MouseEvent[MOUSE_EXITED,(200,70),mods=0,clickCount=0] on LW Container
      java.awt.event.MouseEvent[MOUSE_EXITED,(204,93),mods=0,clickCount=0] on frame0

        On Win32: position the mouse pointer outside of the frame and move it to enter blue
        container. When the pointer is on the red container move it back to exit the frame.
        Here are the events dumped:
      java.awt.event.MouseEvent[MOUSE_ENTERED,(199,63),mods=0,clickCount=0] on HW Container
      java.awt.event.MouseEvent[MOUSE_EXITED,(200,66),mods=0,clickCount=0] on HW Container
        Note that in case of a heavyweight child the frame doesn't receive enter/exit events.

        On Solaris/Linux: position the frame so that it is over the root window of the screen
        (there are no other toplevel shells between the frame and the root window). Then
        position the mouse pointer outside of the frame and move it to enter blue
        container. When the pointer is on the blue container move it back to exit the frame.
        Here are the events dumped:
      java.awt.event.MouseEvent[MOUSE_ENTERED,(2,53),mods=0,clickCount=0] on HW Container
      java.awt.event.MouseEvent[MOUSE_EXITED,(-6,60),mods=0,clickCount=0] on HW Container
        Note that in case of a heavyweight child the frame doesn't receive enter/exit events.
        Position the frame so that it is not over the root window of the screen
        (there is another toplevel shell between the frame and the root window). Then
        position the mouse pointer outside of the frame and move it to enter blue
        container. When the pointer is on the blue container move it back to exit the frame.
        Here are the events dumped:
      java.awt.event.MouseEvent[MOUSE_ENTERED,(148,221),mods=0,clickCount=0] on frame0
      java.awt.event.MouseEvent[MOUSE_ENTERED,(148,99),mods=0,clickCount=0] on HW Container
      java.awt.event.MouseEvent[MOUSE_EXITED,(146,102),mods=0,clickCount=0] on HW Container
      java.awt.event.MouseEvent[MOUSE_EXITED,(146,224),mods=0,clickCount=0] on frame0

      ###@###.### 2001-03-29
      ======================================================================

            dassunw Das Das (Inactive)
            dassunw Das Das (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: