2008-09-17 Ivan N. Zlatev <contact@i-nz.net>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / XplatUIX11.cs
index d3f3faece905ebfa2ff8685ca4591255f351899e..6e91d4e726253a4c80b451f75809a7da2ec1ad5f 100644 (file)
@@ -133,6 +133,9 @@ namespace System.Windows.Forms {
                // 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;
@@ -1357,7 +1360,7 @@ namespace System.Windows.Forms {
                }
 
                private int NextTimeout (ArrayList timers, DateTime now) {
-                       int timeout = Int32.MaxValue
+                       int timeout = 0
 
                        foreach (Timer timer in timers) {
                                int next = (int) (timer.Expires - now).TotalMilliseconds;
@@ -1953,7 +1956,7 @@ namespace System.Windows.Forms {
                                MoveResizeWindow (DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
                        }
 
-                       AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
+                       AddExpose (hwnd, hwnd.WholeWindow == hwnd.ClientWindow, 0, 0, hwnd.Width, hwnd.Height);
                }
                #endregion      // Private Methods
 
@@ -2129,12 +2132,6 @@ namespace System.Windows.Forms {
                        }
                }
 
-               internal override  Size MinimizedWindowSize {
-                       get {
-                               return new Size(1, 1);
-                       }
-               } 
-
                internal override  Size MinimizedWindowSpacingSize {
                        get {
                                return new Size(1, 1);
@@ -2159,12 +2156,6 @@ namespace System.Windows.Forms {
                        get { return new Size (2, 2); }
                }
                
-               internal override  Size MinWindowTrackSize {
-                       get {
-                               return new Size(1, 1);
-                       }
-               }
-
                internal override Keys ModifierKeys {
                        get {
                                return Keyboard.ModifierKeys;
@@ -2267,6 +2258,12 @@ namespace System.Windows.Forms {
                        }
                } 
 
+               internal override MouseButtons MouseButtons {
+                       get {
+                               return MouseState;
+                       }
+               }
+
                internal override  Rectangle VirtualScreen {
                        get {
                                IntPtr                  actual_atom;
@@ -3743,12 +3740,12 @@ namespace System.Windows.Forms {
                                                        MouseState |= MouseButtons.Left;
                                                        if (client) {
                                                                msg.message = Msg.WM_LBUTTONDOWN;
+                                                               msg.wParam = GetMousewParam (0);
                                                        } else {
                                                                msg.message = Msg.WM_NCLBUTTONDOWN;
+                                                               msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
                                                                MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
                                                        }
-                                                       // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
-                                                       msg.wParam=GetMousewParam(0);
                                                        break;
                                                }
 
@@ -3756,11 +3753,12 @@ namespace System.Windows.Forms {
                                                        MouseState |= MouseButtons.Middle;
                                                        if (client) {
                                                                msg.message = Msg.WM_MBUTTONDOWN;
+                                                               msg.wParam = GetMousewParam (0);
                                                        } else {
                                                                msg.message = Msg.WM_NCMBUTTONDOWN;
+                                                               msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
                                                                MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
                                                        }
-                                                       msg.wParam=GetMousewParam(0);
                                                        break;
                                                }
 
@@ -3768,11 +3766,12 @@ namespace System.Windows.Forms {
                                                        MouseState |= MouseButtons.Right;
                                                        if (client) {
                                                                msg.message = Msg.WM_RBUTTONDOWN;
+                                                               msg.wParam = GetMousewParam (0);
                                                        } else {
                                                                msg.message = Msg.WM_NCRBUTTONDOWN;
+                                                               msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
                                                                MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
                                                        }
-                                                       msg.wParam=GetMousewParam(0);
                                                        break;
                                                }
 
@@ -3838,34 +3837,23 @@ namespace System.Windows.Forms {
                                        
                                        if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN) {
                                                SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y);
-
-                                               // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
-                                               // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after 
-                                               // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
-                                               XEvent motionEvent = new XEvent ();
-                                               motionEvent.type = XEventName.MotionNotify;
-                                               motionEvent.MotionEvent.display = DisplayHandle;
-                                               motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
-                                               motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
-                                               motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
-                                               hwnd.Queue.EnqueueLocked (motionEvent);
                                        }
                                        
                                        break;
                                }
 
                                case XEventName.ButtonRelease: {
-
                                        switch(xevent.ButtonEvent.button) {
                                                case 1: {
                                                        if (client) {
                                                                msg.message = Msg.WM_LBUTTONUP;
                                                        } else {
                                                                msg.message = Msg.WM_NCLBUTTONUP;
+                                                               msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
                                                                MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
                                                        }
                                                        MouseState &= ~MouseButtons.Left;
-                                                       msg.wParam=GetMousewParam(0);
+                                                       msg.wParam = GetMousewParam (0);
                                                        break;
                                                }
 
@@ -3874,10 +3862,11 @@ namespace System.Windows.Forms {
                                                                msg.message = Msg.WM_MBUTTONUP;
                                                        } else {
                                                                msg.message = Msg.WM_NCMBUTTONUP;
+                                                               msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
                                                                MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
                                                        }
                                                        MouseState &= ~MouseButtons.Middle;
-                                                       msg.wParam=GetMousewParam(0);
+                                                       msg.wParam = GetMousewParam (0);
                                                        break;
                                                }
 
@@ -3886,10 +3875,11 @@ namespace System.Windows.Forms {
                                                                msg.message = Msg.WM_RBUTTONUP;
                                                        } else {
                                                                msg.message = Msg.WM_NCRBUTTONUP;
+                                                               msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
                                                                MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
                                                        }
                                                        MouseState &= ~MouseButtons.Right;
-                                                       msg.wParam=GetMousewParam(0);
+                                                       msg.wParam = GetMousewParam (0);
                                                        break;
                                                }
 
@@ -3989,8 +3979,6 @@ namespace System.Windows.Forms {
                                        } else {
                                                HitTest ht;
                                                IntPtr dummy;
-                                               int screen_x;
-                                               int screen_y;
 
                                                #if DriverDebugExtra
                                                        Console.WriteLine("GetMessage(): non-client area {0:X} MotionNotify x={1} y={2}", client ? hwnd.client_window.ToInt32() : hwnd.whole_window.ToInt32(), xevent.MotionEvent.x, xevent.MotionEvent.y);
@@ -4003,14 +3991,7 @@ namespace System.Windows.Forms {
                                                        msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
                                                }
 
-                                               // The hit test is sent in screen coordinates
-                                               XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
-                                                               xevent.MotionEvent.x, xevent.MotionEvent.y,
-                                                               out screen_x, out screen_y, out dummy);
-
-                                               msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
-                                               ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
-                                                               IntPtr.Zero, msg.lParam).ToInt32 ();
+                                               ht = NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
                                                NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
 
                                                mouse_position.X = xevent.MotionEvent.x;
@@ -4024,9 +4005,44 @@ namespace System.Windows.Forms {
                                        if (!hwnd.Enabled) {
                                                goto ProcessNextMessage;
                                        }
-                                       if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal && xevent.CrossingEvent.window != hwnd.client_window) {
+                                       if (xevent.CrossingEvent.mode == NotifyMode.NotifyGrab || xevent.AnyEvent.window != hwnd.client_window) {
                                                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;
+
                                        msg.message = Msg.WM_MOUSE_ENTER;
                                        HoverState.X = xevent.CrossingEvent.x;
                                        HoverState.Y = xevent.CrossingEvent.y;
@@ -4055,6 +4071,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 
@@ -4162,8 +4181,8 @@ namespace System.Windows.Forms {
                                                }
                                                goto ProcessNextMessage;
                                        }
-                                       Keyboard.FocusIn(hwnd.client_window);
                                        SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
+                                       Keyboard.FocusIn (FocusWindow);
                                        goto ProcessNextMessage;
                                }
 
@@ -4172,12 +4191,12 @@ namespace System.Windows.Forms {
                                        if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
                                                goto ProcessNextMessage;
                                        }
-                                       Keyboard.FocusOut(hwnd.client_window);
 
                                        while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
                                                SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
                                        }
 
+                                       Keyboard.FocusOut(hwnd.client_window);
                                        SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
                                        goto ProcessNextMessage;
                                }
@@ -4365,6 +4384,16 @@ namespace System.Windows.Forms {
                        return true;
                }
 
+               private HitTest NCHitTest (Hwnd hwnd, int x, int y)
+               {
+                       // The hit test is sent in screen coordinates
+                       IntPtr dummy;
+                       int screen_x, screen_y;
+                       XTranslateCoordinates (DisplayHandle, hwnd.WholeWindow, RootWindow, x, y, out screen_x, out screen_y, out dummy);
+                       return (HitTest) NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST, IntPtr.Zero, 
+                                                              (IntPtr) (screen_y << 16 | screen_x & 0xFFFF));
+               }
+
                internal override bool GetText(IntPtr handle, out string text) {
 
                        lock (XlibLock) {
@@ -4577,7 +4606,7 @@ namespace System.Windows.Forms {
 
                        hwnd = Hwnd.ObjectFromHandle(handle);
 
-                       AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
+                       AddExpose (hwnd, hwnd.WholeWindow == hwnd.ClientWindow, 0, 0, hwnd.Width, hwnd.Height);
                }
 
                internal override bool IsEnabled(IntPtr handle) {
@@ -4865,6 +4894,33 @@ namespace System.Windows.Forms {
                        y = dest_y_return;
                }
 
+               bool GraphicsExposePredicate (IntPtr display, ref XEvent xevent, IntPtr arg)
+               {
+                       return (xevent.type == XEventName.GraphicsExpose || xevent.type == XEventName.NoExpose) &&
+                               arg == xevent.GraphicsExposeEvent.drawable;
+               }
+
+               delegate bool EventPredicate (IntPtr display, ref XEvent xevent, IntPtr arg);
+
+               void ProcessGraphicsExpose (Hwnd hwnd)
+               {
+                       XEvent xevent = new XEvent ();
+                       IntPtr handle = Hwnd.HandleFromObject (hwnd);
+                       EventPredicate predicate = GraphicsExposePredicate;
+
+                       for (;;) {
+                               XIfEvent (Display, ref xevent, predicate, handle);
+                               if (xevent.type != XEventName.GraphicsExpose)
+                                       break;
+
+                               AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.GraphicsExposeEvent.x, xevent.GraphicsExposeEvent.y,
+                                               xevent.GraphicsExposeEvent.width, xevent.GraphicsExposeEvent.height);
+
+                               if (xevent.GraphicsExposeEvent.count == 0)
+                                       break;
+                       }
+               }
+
                internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
                        Hwnd            hwnd;
                        IntPtr          gc;
@@ -4903,48 +4959,23 @@ namespace System.Windows.Forms {
 
                        gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
 
-                       int src_x, src_y;
-                       int dest_x, dest_y;
-                       int width, height;
+                       Rectangle visible_rect = GetTotalVisibleArea (hwnd.client_window);
+                       visible_rect.Intersect (area);
 
-                       if (YAmount > 0) {
-                               src_y = area.Y;
-                               height = area.Height - YAmount;
-                               dest_y = area.Y + YAmount;
-                       }
-                       else {
-                               src_y = area.Y - YAmount;
-                               height = area.Height + YAmount;
-                               dest_y = area.Y;
-                       }
+                       Rectangle dest_rect = visible_rect;
+                       dest_rect.Y += YAmount;
+                       dest_rect.X += XAmount;
+                       dest_rect.Intersect (area);
 
-                       if (XAmount > 0) {
-                               src_x = area.X;
-                               width = area.Width - XAmount;
-                               dest_x = area.X + XAmount;
-                       }
-                       else {
-                               src_x = area.X - XAmount;
-                               width = area.Width + XAmount;
-                               dest_x = area.X;
-                       }
+                       Point src = new Point (dest_rect.X - XAmount, dest_rect.Y - YAmount);
+                       XCopyArea (DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src.X, src.Y, 
+                                       dest_rect.Width, dest_rect.Height, dest_rect.X, dest_rect.Y);
 
-                       XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
+                       Rectangle dirty_area = GetDirtyArea (area, dest_rect, XAmount, YAmount);
+                       AddExpose (hwnd, true, dirty_area.X, dirty_area.Y, dirty_area.Width, dirty_area.Height);
 
-                       // Generate an expose for the area exposed by the horizontal scroll
-                       // We don't use AddExpose since we're 
-                       if (XAmount > 0) {
-                               AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
-                       } else if (XAmount < 0) {
-                               AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
-                       }
+                       ProcessGraphicsExpose (hwnd);
 
-                       // Generate an expose for the area exposed by the vertical scroll
-                       if (YAmount > 0) {
-                               AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
-                       } else if (YAmount < 0) {
-                               AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
-                       }
                        XFreeGC(DisplayHandle, gc);
                }
 
@@ -4960,6 +4991,48 @@ namespace System.Windows.Forms {
                        ScrollWindow(handle, rect, XAmount, YAmount, with_children);
                }
 
+               Rectangle GetDirtyArea (Rectangle total_area, Rectangle valid_area, int XAmount, int YAmount)
+               {
+                       Rectangle dirty_area = total_area;
+
+                       if (YAmount > 0)
+                               dirty_area.Height -= valid_area.Height;
+                       else if (YAmount < 0) {
+                               dirty_area.Height -= valid_area.Height;
+                               dirty_area.Y += valid_area.Height;
+                       }
+
+                       if (XAmount > 0)
+                               dirty_area.Width -= valid_area.Width;
+                       else if (XAmount < 0) {
+                               dirty_area.Width -= valid_area.Width;
+                               dirty_area.X += valid_area.Width;
+                       }
+
+                       return dirty_area;
+               }
+
+               Rectangle GetTotalVisibleArea (IntPtr handle)
+               {
+                       Control c = Control.FromHandle (handle);
+
+                       Rectangle visible_area = c.ClientRectangle;
+                       visible_area.Location = c.PointToScreen (Point.Empty);
+
+                       for (Control parent = c.Parent; parent != null; parent = parent.Parent) {
+                               if (!parent.IsHandleCreated || !parent.Visible)
+                                       return visible_area; // Non visible, not need to finish computations
+
+                               Rectangle r = parent.ClientRectangle;
+                               r.Location = parent.PointToScreen (Point.Empty);
+
+                               visible_area.Intersect (r);
+                       }
+
+                       visible_area.Location = c.PointToClient (visible_area.Location);
+                       return visible_area;
+               }
+
                internal override void SendAsyncMethod (AsyncMethodData method) {
                        Hwnd    hwnd;
                        XEvent  xevent = new XEvent ();
@@ -5054,9 +5127,13 @@ namespace System.Windows.Forms {
 
                internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
                        Form form = Control.FromHandle (handle) as Form;
-                       if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
-                                       border_style == FormBorderStyle.SizableToolWindow)) {
-                               form.window_manager = new ToolWindowManager (form);
+                       if (form != null && form.window_manager == null) {
+                               CreateParams cp = form.GetCreateParams ();
+                               if (border_style == FormBorderStyle.FixedToolWindow ||
+                                    border_style == FormBorderStyle.SizableToolWindow || 
+                                    cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
+                                       form.window_manager = new ToolWindowManager (form);
+                               }
                        }
                        
                        RequestNCRecalc(handle);
@@ -5236,12 +5313,12 @@ namespace System.Windows.Forms {
 
                        prev_focus_window = FocusWindow;
                        FocusWindow = hwnd.client_window;
-                       Keyboard.FocusIn (hwnd.client_window);
 
                        if (prev_focus_window != IntPtr.Zero) {
                                SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
                        }
                        SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
+                       Keyboard.FocusIn (FocusWindow);
 
                        //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
                }
@@ -5317,13 +5394,20 @@ namespace System.Windows.Forms {
 
                        if (enabled) {
                                lock (XlibLock) {
-                                       int[] atoms = new int[8];
-                                       atoms[0] = _NET_WM_STATE_ABOVE.ToInt32();
-                                       XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
+                                       if (hwnd.Mapped) {
+                                               SendNetWMMessage(hwnd.WholeWindow, _NET_WM_STATE, (IntPtr) NetWmStateRequest._NET_WM_STATE_ADD, _NET_WM_STATE_ABOVE, IntPtr.Zero);
+                                       } else {
+                                               int[] atoms = new int[8];
+                                               atoms[0] = _NET_WM_STATE_ABOVE.ToInt32();
+                                               XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
+                                       }
                                }
                        } else {
                                lock (XlibLock) {
-                                       XDeleteProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE);
+                                       if (hwnd.Mapped)
+                                               SendNetWMMessage(hwnd.WholeWindow, _NET_WM_STATE, (IntPtr) NetWmStateRequest._NET_WM_STATE_REMOVE, _NET_WM_STATE_ABOVE, IntPtr.Zero);
+                                       else
+                                               XDeleteProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE);
                                }
                        }
                        return true;
@@ -6188,6 +6272,9 @@ namespace System.Windows.Forms {
 
                [DllImport ("libX11")]
                internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);
+
+               [DllImport ("libX11")]
+               internal extern static void XIfEvent (IntPtr display, ref XEvent xevent, Delegate event_predicate, IntPtr arg);
                #endregion
        }
 }