2008-08-20 Carlos Alberto Cortez <calberto.cortez@gmail.com>
authorCarlos Alberto Cortez <calberto.cortez@gmail.com>
Wed, 20 Aug 2008 19:07:27 +0000 (19:07 -0000)
committerCarlos Alberto Cortez <calberto.cortez@gmail.com>
Wed, 20 Aug 2008 19:07:27 +0000 (19:07 -0000)
* XplatUIX11.cs: Only do the children control bounds check for EnterNotify
if mode is NotifyUngrab, and let it flow if mode is NotifyNormal.
Also, if we are actually moving into a different window after
grabbing, generate a LeaveNotify event for the previous window, since
we need to fire the leave events until the grab ends, not when
actually moving outside of the control.

svn path=/trunk/mcs/; revision=111166

mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs

index ad17d194ca2c8bdfa476054dcf748b20316fd4bc..b984d47fc023c4927d7f5508e3594faddfa78de2 100644 (file)
@@ -1,3 +1,12 @@
+2008-08-20  Carlos Alberto Cortez <calberto.cortez@gmail.com>
+
+       * XplatUIX11.cs: Only do the children control bounds check for EnterNotify
+       if mode is NotifyUngrab, and let it flow if mode is NotifyNormal.
+       Also, if we are actually moving into a different window after
+       grabbing, generate a LeaveNotify event for the previous window, since
+       we need to fire the leave events until the grab ends, not when
+       actually moving outside of the control.
+
 2008-08-19  Carlos Alberto Cortez <calberto.cortez@gmail.com>
 
        * XplatUIX11.cs: The check inside EnterNotify case to fire MouseEnter
index 1bdb73916fa2e8844cf30eecfd362ed0e292b5ad..7857fa9705f30d7f409a872b4b22ee4a78a4b054 100644 (file)
@@ -4001,20 +4001,40 @@ namespace System.Windows.Forms {
                                        if (!hwnd.Enabled) {
                                                goto ProcessNextMessage;
                                        }
-                                       if (xevent.CrossingEvent.mode == NotifyMode.NotifyGrab || LastPointerWindow == xevent.CrossingEvent.window ||
-                                                       hwnd.client_window != xevent.AnyEvent.window) {
+                                       if (xevent.CrossingEvent.mode == NotifyMode.NotifyGrab || xevent.AnyEvent.window != hwnd.client_window) {
                                                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;
+                                       if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) { // Pseudo motion caused by grabbing
+                                               if (LastPointerWindow == xevent.AnyEvent.window)
+                                                       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;
+
+                                                       // A MouseLeave/LeaveNotify event is sent to the previous window
+                                                       // until the mouse is ungrabbed, not when actually leaving its bounds
+                                                       int x = xevent.CrossingEvent.x_root;
+                                                       int y = xevent.CrossingEvent.y_root;
+                                                       ScreenToClient (LastPointerWindow, ref x, ref y);
+
+                                                       XEvent leaveEvent = new XEvent ();
+                                                       leaveEvent.type = XEventName.LeaveNotify;
+                                                       leaveEvent.CrossingEvent.display = DisplayHandle;
+                                                       leaveEvent.CrossingEvent.window = LastPointerWindow;
+                                                       leaveEvent.CrossingEvent.x = x;
+                                                       leaveEvent.CrossingEvent.y = y;
+                                                       leaveEvent.CrossingEvent.mode = NotifyMode.NotifyNormal;
+                                                       Hwnd last_pointer_hwnd = Hwnd.ObjectFromHandle (LastPointerWindow);
+                                                       last_pointer_hwnd.Queue.EnqueueLocked (leaveEvent);
+                                               }
                                        }
 
                                        LastPointerWindow = xevent.AnyEvent.window;
@@ -4047,6 +4067,9 @@ namespace System.Windows.Forms {
                                        if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
                                                goto ProcessNextMessage;
                                        }
+                                       // If a grab is taking place, ignore it - we handle it in EnterNotify
+                                       if (Grab.Hwnd != IntPtr.Zero)
+                                               goto ProcessNextMessage;
 
                                        // Reset the cursor explicitly on X11.
                                        // X11 remembers the last set cursor for the window and in cases where