* X11Dnd.cs: Rework to make StartDrag a blocking call that runs
authorJackson Harper <jackson@novell.com>
Fri, 25 May 2007 21:24:02 +0000 (21:24 -0000)
committerJackson Harper <jackson@novell.com>
Fri, 25 May 2007 21:24:02 +0000 (21:24 -0000)
        it's own message loop.
        * XplatUIX11.cs: Remove some of the dnd hooks
        * X11Display.cs: Remove some of the dnd hooks.

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

mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/ChangeLog
mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/X11Display.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog
mcs/class/Managed.Windows.Forms/System.Windows.Forms/X11Dnd.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs

index a214189a45f8fc7d57234e66437b4bc12bb7d4b4..a452f901e4b1931af22456d0121eea01d4329619 100644 (file)
@@ -1,3 +1,7 @@
+2007-05-25  Jackson Harper  <jackson@ximian.com>
+
+       * X11Display.cs: Remove some of the dnd hooks.
+
 2007-05-03  Jonathan Pobst  <monkey@jpobst.com>
 
        * XplatUIX11-new.cs: Implement RaiseIdle.
index 1a4ae45aa50ee198e0d9338fbbd298905e70a0f3..2d3832993c3d4f3c12899aa51b1f8d6288d1233b 100644 (file)
@@ -1963,8 +1963,6 @@ namespace System.Windows.Forms.X11Internal {
 
                                switch (xevent.type) {
                                case XEventName.KeyPress:
-                                       if (Dnd.InDrag ())
-                                               Dnd.HandleKeyPress (ref xevent);
                                        Keyboard.KeyEvent (FocusWindow.Handle, xevent, ref msg);
                                        return true;
 
@@ -2084,12 +2082,6 @@ namespace System.Windows.Forms.X11Internal {
                                }
 
                                case XEventName.ButtonRelease:
-                                       if (Dnd.InDrag()) {
-                                               if (Dnd.HandleButtonRelease (ref xevent))
-                                                       return true;
-                                               // Don't return here, so that the BUTTONUP message can get through
-                                       }
-
                                        switch(xevent.ButtonEvent.button) {
                                        case 1:
                                                if (client) {
@@ -2167,9 +2159,6 @@ namespace System.Windows.Forms.X11Internal {
                                                                  xevent.MotionEvent.x, xevent.MotionEvent.y);
 #endif
 
-                                               if (Dnd.HandleMotionNotify (ref xevent))
-                                                       goto ProcessNextMessage;
-
                                                if (Grab.Hwnd != IntPtr.Zero)
                                                        msg.hwnd = Grab.Hwnd;
                                                else
index 42caf40a70ca4813a39953abd6eac15a3f0634e2..5cead61f9c3ec0e712434eb1e1ff4c239e916dc2 100644 (file)
@@ -1,3 +1,9 @@
+2007-05-25  Jackson Harper  <jackson@ximian.com>
+
+       * X11Dnd.cs: Rework to make StartDrag a blocking call that runs
+       it's own message loop.
+       * XplatUIX11.cs: Remove some of the dnd hooks
+
 2007-05-25  Gert Driesen  <drieseng@users.sourceforge.net>
 
        * XplatUIX11.cs: Change MinimumWindowSize to {Width=0,Height=0}
index a44f261a6759858a3dbc4a812100d2e2cbab6ca6..ce67af41c5e903213127999ee79847cd9b0911ed 100644 (file)
@@ -29,6 +29,7 @@ using System;
 using System.IO;
 using System.Text;
 using System.Drawing;
+using System.Threading;
 using System.Collections;
 using System.Runtime.Serialization;
 using System.Runtime.InteropServices;
@@ -280,6 +281,8 @@ namespace System.Windows.Forms {
                        public IntPtr Action;
                        public IntPtr [] SupportedTypes;
                        public MouseButtons MouseState;
+                       public DragDropEffects AllowedEffects;
+                       public Point CurMousePos;
                        
                        public IntPtr LastWindow;
                        public IntPtr LastTopLevel;
@@ -340,6 +343,7 @@ namespace System.Windows.Forms {
                // check out the TODO below
                //private IntPtr CurrentCursorHandle;
 
+               private bool tracking = false;
                private X11Keyboard keyboard;
 
                public X11Dnd (IntPtr display, X11Keyboard keyboard)
@@ -384,7 +388,7 @@ namespace System.Windows.Forms {
                        drag_data.MouseState = XplatUIX11.MouseState;
                        drag_data.Data = data;
                        drag_data.SupportedTypes = DetermineSupportedTypes (data);
-
+                       drag_data.AllowedEffects = allowed_effects;
                        drag_data.Action = ActionFromEffect (allowed_effects);
 
                        if (CursorNo == null) {
@@ -396,19 +400,74 @@ namespace System.Windows.Forms {
                        }
 
                        drag_data.LastTopLevel = IntPtr.Zero;
-                       return DragDropEffects.Copy;
+
+                       System.Windows.Forms.MSG msg = new MSG();
+                       object queue_id = XplatUI.StartLoop (Thread.CurrentThread);
+
+                       Timer timer = new Timer ();
+                       timer.Tick += new EventHandler (DndTickHandler);
+                       timer.Interval = 50;
+                       timer.Start ();
+
+                       int suc;
+                       drag_data.State = DragState.Dragging;
+
+                       suc = XplatUIX11.XSetSelectionOwner (display, XdndSelection,
+                                       drag_data.Window, IntPtr.Zero);
+
+                       if (suc == 0) {
+                               Console.Error.WriteLine ("Could not take ownership of XdndSelection aborting drag.");
+                               drag_data.Reset ();
+                               return DragDropEffects.None;
+                       }
+
+                       drag_data.State = DragState.Dragging;
+                       drag_data.CurMousePos = new Point ();
+                       tracking = true;
+
+                       while (tracking && XplatUI.GetMessage (queue_id, ref msg, IntPtr.Zero, 0, 0)) {
+
+                               if (msg.message >= Msg.WM_KEYFIRST && msg.message <= Msg.WM_KEYLAST) {
+                                       HandleKeyMessage (msg);
+                               } else {
+                                       switch (msg.message) {
+                                       case Msg.WM_LBUTTONUP:
+                                       case Msg.WM_RBUTTONUP:
+                                               if (msg.message == Msg.WM_LBUTTONDOWN && drag_data.MouseState != MouseButtons.Left)
+                                                       break;;
+                                               if (msg.message == Msg.WM_RBUTTONDOWN && drag_data.MouseState != MouseButtons.Right)
+                                                       break;
+                                               
+                                               HandleButtonUpMsg ();
+                                               break;
+                                       case Msg.WM_MOUSEMOVE:
+                                               drag_data.CurMousePos.X = Control.LowOrder ((int) msg.lParam.ToInt32 ());
+                                               drag_data.CurMousePos.Y = Control.HighOrder ((int) msg.lParam.ToInt32 ());
+
+                                               HandleMouseOver ();
+                                               // We don't want to dispatch mouse move
+                                               continue;
+                                       }
+
+                                       XplatUI.DispatchMessage (ref msg);
+                               }
+                       }
+
+                       timer.Stop ();
+                       if (drag_event != null)
+                               return drag_event.Effect;
+
+                       return DragDropEffects.None;
                }
 
-               public bool HandleButtonRelease (ref XEvent xevent)
+               private void DndTickHandler (object sender, EventArgs e)
                {
-                       if (drag_data == null)
-                               return false;
+                       HandleMouseOver ();
+               }
 
-                       if (!((drag_data.MouseState == MouseButtons.Left &&
-                                             xevent.ButtonEvent.button == 1) ||
-                                           (drag_data.MouseState == MouseButtons.Right &&
-                                                           xevent.ButtonEvent.button == 3)))
-                               return false;
+               public void HandleButtonUpMsg ()
+               {
+                       
 
                        if (drag_data.State == DragState.Beginning) {
                                //state = State.Accepting;
@@ -416,8 +475,8 @@ namespace System.Windows.Forms {
 
                                if (drag_data.WillAccept) {
 
-                                       if (QueryContinue (xevent, false, DragAction.Drop))
-                                               return true;
+                                       if (QueryContinue (false, DragAction.Drop))
+                                               return;
                                        
                                }
 
@@ -427,101 +486,73 @@ namespace System.Windows.Forms {
                                // handlers
                        }
 
-                       return false;
+                       return;
                }
 
-               public bool HandleMotionNotify (ref XEvent xevent)
+               public bool HandleMouseOver ()
                {
-                       if (drag_data == null)
-                               return false;
-
-                       if (drag_data.State == DragState.Beginning) {
-                               int suc;
-
-                               drag_data.State = DragState.Dragging;
-
-                               suc = XplatUIX11.XSetSelectionOwner (display, XdndSelection,
-                                               drag_data.Window,
-                                               xevent.ButtonEvent.time);
-
-                               if (suc == 0) {
-                                       Console.Error.WriteLine ("Could not take ownership of XdndSelection aborting drag.");
-                                       drag_data.Reset ();
-                                       return false;
-                               }
-
-                               drag_data.State = DragState.Dragging;
-                       } else if (drag_data.State != DragState.None) {
-                               bool dnd_aware = false;
-                               IntPtr toplevel = IntPtr.Zero;
-                               IntPtr window = XplatUIX11.RootWindowHandle;
-
-                               IntPtr root, child;
-                               int x_temp, y_temp;
-                               int mask_return;
-
-                               while (XplatUIX11.XQueryPointer (display,
-                                                      window,
-                                                      out root, out child,
-                                                      out x_temp, out y_temp,
-                                                      out xevent.MotionEvent.x,
-                                                      out xevent.MotionEvent.y,
-                                                      out mask_return)) {
+                       bool dnd_aware = false;
+                       IntPtr toplevel = IntPtr.Zero;
+                       IntPtr window = XplatUIX11.RootWindowHandle;
+
+                       IntPtr root, child;
+                       int x_temp, y_temp;
+                       int x_root, y_root;
+                       int mask_return;
+                       int x = x_root = drag_data.CurMousePos.X;
+                       int y = y_root = drag_data.CurMousePos.Y;
+
+                       while (XplatUIX11.XQueryPointer (display, window, out root, out child,
+                                              out x_temp, out y_temp, out x, out y, out mask_return)) {
                                        
-                                       if (!dnd_aware) {
-                                               dnd_aware = IsWindowDndAware (window);
-                                               if (dnd_aware) {
-                                                       toplevel = window;
-                                                       xevent.MotionEvent.x_root = x_temp;
-                                                       xevent.MotionEvent.y_root = y_temp;
-                                               }
+                               if (!dnd_aware) {
+                                       dnd_aware = IsWindowDndAware (window);
+                                       if (dnd_aware) {
+                                               toplevel = window;
+                                               x_root = x_temp;
+                                               y_root = y_temp;
                                        }
-
-                                       if (child == IntPtr.Zero)
-                                               break;
-                                       
-                                       window = child;
                                }
 
-                               if (window != drag_data.LastWindow && drag_data.State == DragState.Entered) {
-                                       drag_data.State = DragState.Dragging;
+                               if (child == IntPtr.Zero)
+                                       break;
+                                       
+                               window = child;
+                       }
 
-                                       // TODO: Send a Leave if this is an MWF window
+                       if (window != drag_data.LastWindow && drag_data.State == DragState.Entered) {
+                               drag_data.State = DragState.Dragging;
 
-                                       if (toplevel != drag_data.LastTopLevel)
-                                               SendLeave (drag_data.LastTopLevel, xevent.MotionEvent.window);
-                               }
+                               // TODO: Send a Leave if this is an MWF window
 
-                               drag_data.State = DragState.Entered;
-                               if (toplevel != drag_data.LastTopLevel) {
-                                       // Entering a new toplevel window
-                                       SendEnter (toplevel, drag_data.Window, drag_data.SupportedTypes);
-                               } else {
-                                       // Already in a toplevel window, so send a position
-                                       SendPosition (toplevel, drag_data.Window,
-                                                       drag_data.Action,
-                                                       xevent.MotionEvent.x_root,
-                                                       xevent.MotionEvent.y_root,
-                                                       xevent.MotionEvent.time);
-                               }
+                               if (toplevel != drag_data.LastTopLevel)
+                                       SendLeave (drag_data.LastTopLevel, toplevel);
+                       }
 
-                               drag_data.LastTopLevel = toplevel;
-                               drag_data.LastWindow = window;
-                               return true;
+                       drag_data.State = DragState.Entered;
+                       if (toplevel != drag_data.LastTopLevel) {
+                               // Entering a new toplevel window
+                               SendEnter (toplevel, drag_data.Window, drag_data.SupportedTypes);
+                       } else {
+                               // Already in a toplevel window, so send a position
+                               SendPosition (toplevel, drag_data.Window,
+                                               drag_data.Action,
+                                               x_root, y_root,
+                                               IntPtr.Zero);
                        }
-                       return false;
+
+                       drag_data.LastTopLevel = toplevel;
+                       drag_data.LastWindow = window;
+                       return true;
                }
 
-               public bool HandleKeyPress (ref XEvent xevent)
+               public void HandleKeyMessage (MSG msg)
                {
-                       if (VirtualKeys.VK_ESCAPE == (VirtualKeys) keyboard.EventToVkey (xevent)) {
-                               if (!QueryContinue (xevent, true, DragAction.Cancel))
-                                       return true;
+                       if (VirtualKeys.VK_ESCAPE == (VirtualKeys) msg.wParam) {
+                               QueryContinue (true, DragAction.Cancel);
                        }
-
-                       return false;
                }
-
+               
                // return true if the event is handled here
                public bool HandleClientMessage (ref XEvent xevent)
                {
@@ -578,7 +609,7 @@ namespace System.Windows.Forms {
                        return true;
                }
 
-               private bool QueryContinue (XEvent xevent, bool escape, DragAction action)
+               private bool QueryContinue (bool escape, DragAction action)
                {
                        QueryContinueDragEventArgs qce = new QueryContinueDragEventArgs ((int) XplatUI.State.ModifierKeys,
                                        escape, action);
@@ -590,14 +621,15 @@ namespace System.Windows.Forms {
                        case DragAction.Continue:
                                return true;
                        case DragAction.Drop:
-                               SendDrop (drag_data.LastTopLevel, source, xevent.ButtonEvent.time);
-                               break;
+                               SendDrop (drag_data.LastTopLevel, source, IntPtr.Zero);
+                               return true;
                        case DragAction.Cancel:
                                drag_data.Reset ();
                                c.InternalCapture = false;
                                break;
                        }
 
+                       tracking = false;
                        return false;
                }
 
@@ -692,7 +724,11 @@ namespace System.Windows.Forms {
                        pos_y = (int) xevent.ClientMessageEvent.ptr3 & 0xFFFF;
 
                        // Copy is implicitly allowed
-                       allowed = EffectFromAction (xevent.ClientMessageEvent.ptr5) | DragDropEffects.Copy;
+                       Control source_control = MwfWindow (source);
+                       if (source_control == null)
+                               allowed = EffectFromAction (xevent.ClientMessageEvent.ptr5) | DragDropEffects.Copy;
+                       else
+                               allowed = drag_data.AllowedEffects;
 
                        IntPtr parent, child, new_child, last_drop_child;
                        parent = XplatUIX11.XRootWindow (display, 0);
@@ -741,16 +777,19 @@ namespace System.Windows.Forms {
 
                        if (converts_pending > 0)
                                return true;
+
                        if (!status_sent) {
                                drag_event = new DragEventArgs (data, 0, pos_x, pos_y,
                                        allowed, DragDropEffects.None);
                                control.DndEnter (drag_event);
+                               
                                SendStatus (source, drag_event.Effect);
                                status_sent = true;
                        } else {
                                drag_event.x = pos_x;
                                drag_event.y = pos_y;
                                control.DndOver (drag_event);
+
                                SendStatus (source, drag_event.Effect);
                        }
                        
@@ -777,7 +816,7 @@ namespace System.Windows.Forms {
                        if (control != null && drag_event != null) {
                                drag_event = new DragEventArgs (data,
                                                0, pos_x, pos_y,
-                                       allowed, DragDropEffects.None);
+                                       allowed, drag_event.Effect);
                                control.DndDrop (drag_event);
                        }
                        SendFinished ();
@@ -794,9 +833,10 @@ namespace System.Windows.Forms {
 
                private bool HandleStatusEvent (ref XEvent xevent)
                {
+                       
                        if (drag_data != null && drag_data.State == DragState.Entered) {
 
-                               if (!QueryContinue (xevent, false, DragAction.Continue))
+                               if (!QueryContinue (false, DragAction.Continue))
                                        return true;
 
                                drag_data.WillAccept = ((int) xevent.ClientMessageEvent.ptr2 & 0x1) != 0;
@@ -816,6 +856,7 @@ namespace System.Windows.Forms {
                                allowed |= DragDropEffects.Move;
                        if (action == XdndActionLink)
                                allowed |= DragDropEffects.Link;
+
                        return allowed;
                }
 
@@ -1002,6 +1043,8 @@ namespace System.Windows.Forms {
                        xevent.ClientMessageEvent.ptr1 = toplevel;
 
                        XplatUIX11.XSendEvent (display, source, false, IntPtr.Zero, ref xevent);
+
+                       tracking = false;
                }
 
                // There is a somewhat decent amount of overhead
index 04600b9b961ddc5eac81110d1a5d4ebf6dd615de..2cbc33004de9b90ddb4e7bf16aaea16e3ea09068 100644 (file)
@@ -3624,8 +3624,6 @@ namespace System.Windows.Forms {
                        //
                        switch(xevent.type) {
                                case XEventName.KeyPress: {
-                                       if (Dnd.InDrag ())
-                                               Dnd.HandleKeyPress (ref xevent);
                                        Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
                                        break;
                                }
@@ -3753,12 +3751,6 @@ namespace System.Windows.Forms {
                                }
 
                                case XEventName.ButtonRelease: {
-                                       if (Dnd.InDrag()) {
-                                               if (Dnd.HandleButtonRelease (ref xevent)) {
-                                                       break;
-                                               }
-                                               // Allow the LBUTTONUP message to get through
-                                       }
 
                                        switch(xevent.ButtonEvent.button) {
                                                case 1: {
@@ -3843,8 +3835,6 @@ namespace System.Windows.Forms {
                                                        Console.WriteLine("GetMessage(): Window {0:X} MotionNotify x={1} y={2}", client ? hwnd.client_window.ToInt32() : hwnd.whole_window.ToInt32(), xevent.MotionEvent.x, xevent.MotionEvent.y);
                                                #endif
 
-                                               if (Dnd.HandleMotionNotify (ref xevent))
-                                                       goto ProcessNextMessage;
                                                if (Grab.Hwnd != IntPtr.Zero) {
                                                        msg.hwnd = Grab.Hwnd;
                                                } else {