SUGGESTED FIX
But after some more investigation we found that there is nothing could break if we just handle all of xcrossing events.
So another fix look less safe but simple:
--- XWindow.java 2006-02-06 12:55:06.000000000 +0300
***************
*** 751,761 ****
if (eventLog.isLoggable(Level.FINEST)) eventLog.finest(xce.toString());
- // Skip event If it was caused by a grab
- if (xce.get_mode() != NotifyNormal) {
- return;
- }
-
// X sends XCrossing to all hierarchy so if the edge of child equals to
// ancestor and mouse enters child, the ancestor will get an event too.
// From java point the event is bogus as ancestor is obscured, so if
--- 751,756 ----
|
EVALUATION
This bug happens often (on awt-linux-01, linux machines) because (as
described in my previous email) we skip crossingEvent and doesn't
initialize XAwtState's componentEntered variable. That variable is then
used in GlobalCursorManager to change cursor shape.
Initially I though it's WM error and it just misses one
Enter/LeaveNotify event but further testing uncovered a bug in awt :
XWindow.java : handleXCrossingEvent() skip events if they are not in
NotifyNormal mode.
I found that only some actions may lead to skipping that event.
(There are two instances will be considered in following: XContentWindow
and XFramePeer.)
In particular:
1) double clicking on titlebar of the window (it if leads to maximization)
In this case we obtain
1) missed xEvent == XCrossingEvent = type = EnterNotify,
sun.awt.X11.XFramePeer@1c5f743(2c00007), mode = 2, detail = 1
2) missed xEvent == XCrossingEvent = type = EnterNotify,
sun.awt.X11.XContentWindow@2803d5(2c0000e), mode = 2, detail = 0
Mode 2 means NotifyUngrab (it happens on second mouse release)
Detail 0 means NotifyAncestor
Detail 1 - NotifyVirtual
How does it work. When there are three windows: A(this is a root
window), B(XFramePeer), C(XContentWindow) and A is a parent of B and B
is a parent of C and crossing happens from A to C then B will receive
NotifyVirtual and C - NotifyAncestor.
You would imagine that similar things happen on crossing in other direction.
2) On pressing Alt-Tab:
Now lets consider pressing ALT+TAB (although there are no complains on
it in CR)
Java window initially activated and pointer over it and over other
window so when you release kbd pointer will come to different window:
(events will arrive on PRESS - this is significant)
1) missed xEvent == XCrossingEvent = type = LeaveNotify,
sun.awt.X11.XContentWindow@2803d5(2c0000e), mode = 1, detail = 0
2) missed xEvent == XCrossingEvent = type = LeaveNotify,
sun.awt.X11.XFramePeer@1c5f743(2c00007), mode = 1, detail = 1
Similar situation - crossing happens affecting same windows like before:
Mode 1 == NotifyGrab
XContentWindow recieves NotifyAncestor and XFramePeer - NotifyVirtual
as a middle-point in this chain.
3) On pressin ALT+TAB
Other (read "native") window initially activated and pointer over it and
over Java window:
(events arrives on RELEASE - significant)
1) missed xEvent == XCrossingEvent = type = EnterNotify,
sun.awt.X11.XFramePeer@1c5f743(2c00007), mode = 2, detail = 1
2) missed xEvent == XCrossingEvent = type = EnterNotify,
sun.awt.X11.XContentWindow@2803d5(2c0000e), mode = 2, detail = 0
You would notice exactly the same situation as in case 1).
We should correctly handle these events. I'm not sure about reasons of
filtering them for now and I'd filter them more precisely respecting
cases described above.
|
SUGGESTED FIX
At first we considered the most safe fix that affected xcrossing event handling within XWindow: now we won't spik it if it has NotifyGrab or NotifyUngrab modes.
--- /net/karanar/export/dav/mustang67//webrev/src/solaris/classes/sun/awt/X11/XWindow.java ???? ?????? 20 16:42:37 2005
*** 749,760 ****
super.handleXCrossingEvent(ptr);
XCrossingEvent xce = new XCrossingEvent(ptr);
if (eventLog.isLoggable(Level.FINEST)) eventLog.finest(xce.toString());
// Skip event If it was caused by a grab
! if (xce.get_mode() != NotifyNormal) {
return;
}
// X sends XCrossing to all hierarchy so if the edge of child equals to
// ancestor and mouse enters child, the ancestor will get an event too.
--- 749,776 ----
super.handleXCrossingEvent(ptr);
XCrossingEvent xce = new XCrossingEvent(ptr);
if (eventLog.isLoggable(Level.FINEST)) eventLog.finest(xce.toString());
+ // 6242833 : Mouse cursor doesn't behave correctly after maximizing on Linux/JDS 3
+ // On Maximize with double click on titlebar
+ // or _releasing_ ALT+TAB on other window so java window becomes active
+ boolean shouldHandle = false;
+ if (xce.get_mode() == NotifyUngrab &&
+ (xce.get_detail() == NotifyVirtual ||
+ xce.get_detail() == NotifyAncestor)) {
+ shouldHandle = true;
+ }
+ //On pressing ALT+TAB on java window
+ if (xce.get_mode() == NotifyGrab &&
+ (xce.get_detail() == NotifyVirtual ||
+ xce.get_detail() == NotifyAncestor)) {
+ shouldHandle = true;
+ }
+
// Skip event If it was caused by a grab
! if (xce.get_mode() != NotifyNormal && !shouldHandle) {
return;
}
// X sends XCrossing to all hierarchy so if the edge of child equals to
// ancestor and mouse enters child, the ancestor will get an event too.
|