-
Bug
-
Resolution: Fixed
-
P2
-
unknown, 1.4.0
-
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
======================================================================
- duplicates
-
JDK-4035623 Inconsistent mouse enter/exit notification based on LayoutManager
-
- Closed
-
- relates to
-
JDK-4395290 Bad calling order for DropTargetListener.dragExit() and drop()
-
- Resolved
-
-
JDK-4150851 Frame enter/exit events broken
-
- Resolved
-
-
JDK-6234311 Reg-test java/awt/Mouse/MouseEnterExitTest3/MouseEnterExitTest3.html fails
-
- Open
-
-
JDK-4848842 Event delivery change from JDK 1.3.1
-
- Closed
-