Hey,
The attached patch adds a static field to XplatUIX11 to detect if the
window receiving the EnterNotify event is actually the one having the
pointer within its bounds. For normal motion events, the code we have
right now is just fine.
But we need this special check when grabbing. When grabbing a window by
pressing the left button of the mouse and holding it, we are receiving:
1. LeaveNotify events for the control being grabbed and all its
containers, with mode param as NotifyGrab.
2. EnterNotify events are generated for each of the containers of the
Control, and finally, the control itself gets a new EnterNotify with
mode param as NotifyUngrab (and this is why in the patch we ignore if
mode param is NotifyUngrab).
3. If the pointer , still grabbed, moves to a different control, when
the button is released, we get a EnterNotify event with mode param as
NotifyUngrab for the new control.
As you see, in both steps 2 and 3 we get the same event with the same
mode param, but for case 2 we don't need to actually handle the event,
since we are already within the control bounds (as well as all of its
containers). But for step 3 we *do need* it.
That's why I added a field to check the actual last window containing
the pointer against the window receiving the EnterNotify event, and if
it's a different one, try to detect if a child contains it - in which
case we are already there and don't need to handle the event.
I hope the explanation is clear - I needed it to understand the problem,
and hopefully will make things clear to review it ;-)
Carlos.
Index: XplatUIX11.cs
===================================================================
--- XplatUIX11.cs (revisión: 110298)
+++ XplatUIX11.cs (copia de trabajo)
@@ -133,6 +133,9 @@
// Caret
private static CaretStruct Caret; //
+ // Last window containing the pointer
+ private static IntPtr LastPointerWindow; // The last window containing the pointer
+
// Our atoms
private static IntPtr WM_PROTOCOLS;
private static IntPtr WM_DELETE_WINDOW;
@@ -4009,9 +4012,24 @@
if (!hwnd.Enabled) {
goto ProcessNextMessage;
}
- if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal && xevent.CrossingEvent.window != hwnd.client_window) {
+ if (xevent.CrossingEvent.mode == NotifyMode.NotifyGrab || LastPointerWindow == xevent.CrossingEvent.window ||
+ hwnd.client_window == IntPtr.Zero) {
goto ProcessNextMessage;
}
+ if (LastPointerWindow != IntPtr.Zero) {
+ Point enter_loc = new Point (xevent.ButtonEvent.x, xevent.ButtonEvent.y);
+
+ // We need this due to EnterNotify being fired on all the parent controls
+ // of the Control being grabbed, and obviously in that scenario we are not
+ // actuallty entering them
+ Control ctrl = Control.FromHandle (hwnd.client_window);
+ foreach (Control child_control in ctrl.Controls)
+ if (child_control.Bounds.Contains (enter_loc))
+ goto ProcessNextMessage;
+ }
+
+ LastPointerWindow = xevent.AnyEvent.window;
+
msg.message = Msg.WM_MOUSE_ENTER;
HoverState.X = xevent.CrossingEvent.x;
HoverState.Y = xevent.CrossingEvent.y;
_______________________________________________
Mono-winforms-list maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-winforms-list