2006-05-24 Peter Dennis Bartok <pbartok@novell.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / XplatUIX11.cs
index 04e25a78f3bc506cff65ccaab897ecda0ec69166..9ea34c5774fe999570e0037b2345c40b29a91c31 100644 (file)
@@ -41,6 +41,9 @@
 
 // Extra detailed debug
 #undef DriverDebugExtra
+#undef DriverDebugParent
+#undef DriverDebugCreate
+#undef DriverDebugDestroy
 
 using System;
 using System.ComponentModel;
@@ -93,7 +96,7 @@ namespace System.Windows.Forms {
                private static IntPtr           AsyncAtom;              // Support for async messages
 
                // Message Loop
-               private static XEventQueue      MessageQueue;           // Holds our queued up events
+               private static Hashtable        MessageQueues;          // Holds our thread-specific XEventQueues
                #if __MonoCS__                                          //
                private static Pollfd[]         pollfds;                // For watching the X11 socket
                #endif                                                  //
@@ -168,7 +171,7 @@ namespace System.Windows.Forms {
 
                        // Now regular initialization
                        XlibLock = new object ();
-                       MessageQueue = new XEventQueue ();
+                       MessageQueues = new Hashtable(7);
                        TimerList = new ArrayList ();
                        XInitThreads();
 
@@ -282,12 +285,30 @@ namespace System.Windows.Forms {
                                StringBuilder   sb;
                                string          x_error_text;
                                string          error;
+                               string          hwnd_text;
+                               string          control_text;
+                               Hwnd            hwnd;
+                               Control         c;
 
                                sb = new StringBuilder(160);
                                XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
                                x_error_text = sb.ToString();
+                               hwnd = Hwnd.ObjectFromHandle(ResourceID);
+                               if (hwnd != null) {
+                                       hwnd_text = hwnd.ToString();
+                                       c = Control.FromHandle(hwnd.Handle);
+                                       if (c != null) {
+                                               control_text = c.ToString();
+                                       } else {
+                                               control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle);
+                                       }
+                               } else {
+                                       hwnd_text = "<null>";
+                                       control_text = "<null>";
+                               }
 
-                               error = String.Format("\n  Error: {0}\n  Request:     {1:D} ({2})\n  Resource ID: 0x{3:x}\n  Serial:      {4}", x_error_text, RequestCode, RequestCode, ResourceID.ToInt32(), Serial);
+
+                               error = String.Format("\n  Error: {0}\n  Request:     {1:D} ({2})\n  Resource ID: 0x{3:X}\n  Serial:      {4}\n  Hwnd:        {5}\n  Control:     {6}", x_error_text, RequestCode, RequestCode, ResourceID.ToInt32(), Serial, hwnd_text, control_text);
                                return error;
                        }
                }
@@ -335,9 +356,16 @@ namespace System.Windows.Forms {
                                }
 
                                hwnd = new Hwnd();
+                               hwnd.Queue = ThreadQueue(Thread.CurrentThread);
                                hwnd.WholeWindow = FosterParent;
                                hwnd.ClientWindow = FosterParent;
 
+                               // Create a HWND for RootWIndow as well, so our queue doesn't eat the events
+                               hwnd = new Hwnd();
+                               hwnd.Queue = ThreadQueue(Thread.CurrentThread);
+                               hwnd.whole_window = RootWindow;
+                               hwnd.ClientWindow = RootWindow;
+
                                // For sleeping on the X11 socket
                                listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
                                IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
@@ -362,7 +390,7 @@ namespace System.Windows.Forms {
                                pollfds [1].events = PollEvents.POLLIN;
                                #endif
 
-                               Keyboard = new X11Keyboard(DisplayHandle);
+                               Keyboard = new X11Keyboard(DisplayHandle, FosterParent);
                                Dnd = new X11Dnd (DisplayHandle);
 
                                PostQuitState = false;
@@ -373,7 +401,8 @@ namespace System.Windows.Forms {
                                HoverState.Timer = new Timer();
                                HoverState.Timer.Enabled = false;
                                HoverState.Timer.Interval = HoverState.Interval;
-                               HoverState.Timer.Tick +=new EventHandler(MouseHover);
+                               HoverState.Timer.Tick += new EventHandler(MouseHover);
+                               HoverState.Size = new Size(4, 4);
                                HoverState.X = -1;
                                HoverState.Y = -1;
 
@@ -507,6 +536,15 @@ namespace System.Windows.Forms {
                        NetAtoms[(int)NA._NET_WM_CONTEXT_HELP] = XInternAtom(DisplayHandle, "_NET_WM_CONTEXT_HELP", false);
                        NetAtoms[(int)NA._NET_WM_WINDOW_OPACITY] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_OPACITY", false);
 
+                       NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_DESKTOP] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_DESKTOP", false);
+                       NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_DOCK] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_DOCK", false);
+                       NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_TOOLBAR] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_TOOLBAR", false);
+                       NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_MENU] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_MENU", false);
+                       NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_UTILITY] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_UTILITY", false);
+                       NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_DIALOG] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_DIALOG", false);
+                       NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_SPLASH] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_SPLASH", false);
+                       NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_NORMAL] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE_NORMAL", false);
+
                        // Clipboard support
                        NetAtoms[(int)NA.CLIPBOARD] = XInternAtom (DisplayHandle, "CLIPBOARD", false);
                        NetAtoms[(int)NA.DIB] = (IntPtr)Atom.XA_PIXMAP;
@@ -557,73 +595,81 @@ namespace System.Windows.Forms {
                        XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
                }
 
-               private void DeriveStyles(IntPtr handle, int Style, int ExStyle, out FormBorderStyle border_style, out TitleStyle title_style, out int caption_height, out int tool_caption_height) {
+               private void DeriveStyles(int Style, int ExStyle, out FormBorderStyle border_style, out TitleStyle title_style, out int caption_height, out int tool_caption_height) {
 
                        // Only MDI windows get caption_heights
                        caption_height = 0;
                        tool_caption_height = 19;
 
                        if ((Style & (int) WindowStyles.WS_CHILD) != 0) {
-                               if ((Style & (int) WindowStyles.WS_BORDER) == 0) {
-                                       border_style = FormBorderStyle.None;
-                               } else if ((ExStyle & (int) WindowStyles.WS_EX_CLIENTEDGE) != 0) {
+                               if ((ExStyle & (int) WindowExStyles.WS_EX_CLIENTEDGE) != 0) {
                                        border_style = FormBorderStyle.Fixed3D;
+                               } else if ((Style & (int) WindowStyles.WS_BORDER) == 0) {
+                                       border_style = FormBorderStyle.None;
                                } else {
                                        border_style = FormBorderStyle.FixedSingle;
                                }
                                title_style = TitleStyle.None;
-                       } else {
-                               bool is_mdi = false;
 
-                               if ((ExStyle & (int) WindowStyles.WS_EX_MDICHILD) != 0) {
+                               if ((ExStyle & (int) WindowExStyles.WS_EX_MDICHILD) != 0) {
                                        caption_height = 26;
-                                       is_mdi = true;
+
+                                       if ((Style & (int)WindowStyles.WS_CAPTION) != 0) {
+                                               if ((ExStyle & (int)WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
+                                                       title_style = TitleStyle.Tool;
+                                               } else {
+                                                       title_style = TitleStyle.Normal;
+                                               }
+                                       }
+
+                                       if ((Style & (int) WindowStyles.WS_OVERLAPPEDWINDOW) != 0 ||
+                                                       (ExStyle & (int) WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
+                                               border_style = (FormBorderStyle) 0xFFFF;
+                                       } else {
+                                               border_style = FormBorderStyle.None;
+                                       }
                                }
 
+                       } else {
                                title_style = TitleStyle.None;
                                if ((Style & (int)WindowStyles.WS_CAPTION) != 0) {
-                                       if ((ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
+                                       if ((ExStyle & (int)WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
                                                title_style = TitleStyle.Tool;
                                        } else {
                                                title_style = TitleStyle.Normal;
                                        }
                                }
 
-                               if (!is_mdi) {
-                                       border_style = FormBorderStyle.None;
+                               border_style = FormBorderStyle.None;
 
-                                       if ((Style & (int)WindowStyles.WS_THICKFRAME) != 0) {
-                                               if ((ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
-                                                       border_style = FormBorderStyle.SizableToolWindow;
-                                               } else {
-                                                       border_style = FormBorderStyle.Sizable;
-                                               }
+                               if ((Style & (int)WindowStyles.WS_THICKFRAME) != 0) {
+                                       if ((ExStyle & (int)WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
+                                               border_style = FormBorderStyle.SizableToolWindow;
                                        } else {
-                                               if ((ExStyle & (int)WindowStyles.WS_EX_CLIENTEDGE) != 0) {
+                                               border_style = FormBorderStyle.Sizable;
+                                       }
+                               } else {
+                                       if ((Style & (int)WindowStyles.WS_CAPTION) == (int)WindowStyles.WS_CAPTION) {
+                                               if ((ExStyle & (int)WindowExStyles.WS_EX_CLIENTEDGE) != 0) {
                                                        border_style = FormBorderStyle.Fixed3D;
-                                               } else if ((ExStyle & (int)WindowStyles.WS_EX_DLGMODALFRAME) != 0) {
+                                               } else if ((ExStyle & (int)WindowExStyles.WS_EX_DLGMODALFRAME) != 0) {
                                                        border_style = FormBorderStyle.FixedDialog;
-                                               } else if ((ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
+                                               } else if ((ExStyle & (int)WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
                                                        border_style = FormBorderStyle.FixedToolWindow;
                                                } else if ((Style & (int)WindowStyles.WS_BORDER) != 0) {
-                                                       border_style = FormBorderStyle.Sizable;
-                                               } else {
-                                                       border_style = FormBorderStyle.None;
+                                                       border_style = FormBorderStyle.FixedSingle;
                                                }
-                                       }
-                               } else {
-                                       if ((Style & (int) WindowStyles.WS_OVERLAPPEDWINDOW) != 0 ||
-                                                       (ExStyle & (int) WindowStyles.WS_EX_TOOLWINDOW) != 0) {
-                                               border_style = (FormBorderStyle) 0xFFFF;
                                        } else {
-                                               border_style = FormBorderStyle.None;
+                                               if ((Style & (int)WindowStyles.WS_BORDER) != 0) {
+                                                       border_style = FormBorderStyle.FixedSingle;
+                                               }
                                        }
                                }
                        }
                }
 
                private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
-                       DeriveStyles(hwnd.Handle, cp.Style, cp.ExStyle, out hwnd.border_style, out hwnd.title_style, out hwnd.caption_height, out hwnd.tool_caption_height);
+                       DeriveStyles(cp.Style, cp.ExStyle, out hwnd.border_style, out hwnd.title_style, out hwnd.caption_height, out hwnd.tool_caption_height);
                }
 
                private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
@@ -632,6 +678,14 @@ namespace System.Windows.Forms {
                        MotifDecorations        decorations;
                        int                     atom_count;
                        Rectangle               client_rect;
+                       bool                    transient;
+
+                       // Child windows don't need WM window styles
+                       if ((cp.Style & (int)WindowStyles.WS_CHILDWINDOW) != 0) {
+                               return;
+                       }
+
+                       transient = false;
 
                        mwmHints = new MotifWmHints();
                        functions = 0;
@@ -664,7 +718,7 @@ namespace System.Windows.Forms {
                                functions |= MotifFunctions.Close;
                        }
 
-                       if ((cp.ExStyle & ((int)WindowStyles.WS_EX_DLGMODALFRAME)) != 0) {
+                       if ((cp.ExStyle & ((int)WindowExStyles.WS_EX_DLGMODALFRAME)) != 0) {
                                decorations |= MotifDecorations.Border;
                        }
 
@@ -676,11 +730,18 @@ namespace System.Windows.Forms {
                                decorations |= MotifDecorations.Border;
                        }
 
-                       if ((cp.ExStyle & ((int)WindowStyles.WS_EX_TOOLWINDOW)) != 0) {
+                       if ((cp.ExStyle & ((int)WindowExStyles.WS_EX_TOOLWINDOW)) != 0) {
                                functions = 0;
                                decorations = 0;
                        }
 
+                       if ((functions & MotifFunctions.Resize) == 0) {
+                               hwnd.fixed_size = true;
+                               XplatUI.SetWindowMinMax(hwnd.Handle, new Rectangle(cp.X, cp.Y, cp.Width, cp.Height), new Size(cp.Width, cp.Height), new Size(cp.Width, cp.Height));
+                       } else {
+                               hwnd.fixed_size = false;
+                       }
+
                        mwmHints.functions = (IntPtr)functions;
                        mwmHints.decorations = (IntPtr)decorations;
 
@@ -689,23 +750,46 @@ namespace System.Windows.Forms {
                                XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._MOTIF_WM_HINTS], NetAtoms[(int)NA._MOTIF_WM_HINTS], 32, PropertyMode.Replace, ref mwmHints, 5);
 
                                if (((cp.Style & (int)WindowStyles.WS_POPUP) != 0)  && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
+                                       transient = true;
                                        XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
+                               } else if ((cp.ExStyle & (int)WindowExStyles.WS_EX_APPWINDOW) == 0) {
+                                       transient = true;
+                                       XSetTransientForHint(DisplayHandle, hwnd.whole_window, FosterParent);
+                               }
+                               if ((client_rect.Width < 1) || (client_rect.Height < 1)) {
+                                       XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
+                               } else {
+                                       XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
                                }
-                               XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
 
                                int[] atoms = new int[8];
                                atom_count = 0;
 
-                               if ((cp.ExStyle & ((int)WindowStyles.WS_EX_TOOLWINDOW)) != 0) {
+                               if ((cp.ExStyle & ((int)WindowExStyles.WS_EX_TOOLWINDOW)) != 0) {
                                        atoms[atom_count++] = NetAtoms[(int)NA._NET_WM_STATE_NO_TASKBAR].ToInt32();
                                }
                                XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
 
+                               if ((cp.ExStyle & (int)WindowExStyles.WS_EX_TOPMOST) != 0) {
+                                       atom_count = 0;
+                                       atoms[atom_count++] = atoms[atom_count++] = NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_DOCK].ToInt32();
+                                       XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._NET_WM_WINDOW_TYPE], (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
+                               } else if (transient) {
+                                       atom_count = 0;
+
+                                       if ((cp.ExStyle & ((int)WindowExStyles.WS_EX_TOOLWINDOW)) != 0) {
+                                               atoms[atom_count++] = atoms[atom_count++] = NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_DOCK].ToInt32();
+                                       } else {
+                                               atoms[atom_count++] = atoms[atom_count++] = NetAtoms[(int)NA._NET_WM_WINDOW_TYPE_DIALOG].ToInt32();
+                                       }
+                                       XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._NET_WM_WINDOW_TYPE], (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
+                               }
+
                                atom_count = 0;
                                IntPtr[] atom_ptrs = new IntPtr[2];
 
                                atom_ptrs[atom_count++] = NetAtoms[(int)NA.WM_DELETE_WINDOW];
-                               if ((cp.ExStyle & (int)WindowStyles.WS_EX_CONTEXTHELP) != 0) {
+                               if ((cp.ExStyle & (int)WindowExStyles.WS_EX_CONTEXTHELP) != 0) {
                                        atom_ptrs[atom_count++] = NetAtoms[(int)NA._NET_WM_CONTEXT_HELP];
                                }
 
@@ -716,22 +800,23 @@ namespace System.Windows.Forms {
                private void SetIcon(Hwnd hwnd, Icon icon) {
                        Bitmap          bitmap;
                        int             size;
-                       uint[]          data;
+                       IntPtr[]        data;
                        int             index;
 
                        bitmap = icon.ToBitmap();
                        index = 0;
                        size = bitmap.Width * bitmap.Height + 2;
-                       data = new uint[size];
+                       data = new IntPtr[size];
 
-                       data[index++] = (uint)bitmap.Width;
-                       data[index++] = (uint)bitmap.Height;
+                       data[index++] = (IntPtr)bitmap.Width;
+                       data[index++] = (IntPtr)bitmap.Height;
 
                        for (int y = 0; y < bitmap.Height; y++) {
                                for (int x = 0; x < bitmap.Width; x++) {
-                                       data[index++] = (uint)bitmap.GetPixel(x, y).ToArgb();
+                                       data[index++] = (IntPtr)bitmap.GetPixel(x, y).ToArgb();
                                }
                        }
+
                        XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._NET_WM_ICON], (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, data, size);
                }
 
@@ -743,6 +828,18 @@ namespace System.Windows.Forms {
                        wake.Send (new byte [] { 0xFF });
                }
 
+               private XEventQueue ThreadQueue(Thread thread) {
+                       XEventQueue     queue;
+
+                       queue = (XEventQueue)MessageQueues[thread];
+                       if (queue == null) {
+                               queue = new XEventQueue(thread);
+                               MessageQueues[thread] = queue;
+                       }
+
+                       return queue;
+               }
+
                private void TranslatePropertyToClipboard(IntPtr property) {
                        IntPtr                  actual_atom;
                        int                     actual_format;
@@ -771,25 +868,36 @@ namespace System.Windows.Forms {
                        }
                }
 
-               private void AddExpose (XEvent xevent) {
-                       Hwnd    hwnd;
-
-                       hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
-
+               private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
                        // Don't waste time
-                       if (hwnd == null) {     
+                       if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
                                return;
                        }
 
-                       if (xevent.AnyEvent.window == hwnd.client_window) {
-                               hwnd.AddInvalidArea(xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
+                       // Keep the invalid area as small as needed
+                       if ((x + width) > hwnd.width) {
+                               width = hwnd.width - x;
+                       }
+
+                       if ((y + height) > hwnd.height) {
+                               height = hwnd.height - y;
+                       }
+
+                       if (client) {
+                               hwnd.AddInvalidArea(x, y, width, height);
                                if (!hwnd.expose_pending) {
-                                       MessageQueue.Enqueue(xevent);
+                                       if (!hwnd.nc_expose_pending) {
+                                               hwnd.Queue.Paint.Enqueue(hwnd);
+                                       }
                                        hwnd.expose_pending = true;
                                }
                        } else {
+                               hwnd.AddNcInvalidArea (x, y, width, height);
+                               
                                if (!hwnd.nc_expose_pending) {
-                                       MessageQueue.Enqueue(xevent);
+                                       if (!hwnd.expose_pending) {
+                                               hwnd.Queue.Paint.Enqueue(hwnd);
+                                       }
                                        hwnd.nc_expose_pending = true;
                                }
                        }
@@ -805,22 +913,10 @@ namespace System.Windows.Forms {
 
                private void InvalidateWholeWindow(IntPtr handle, Rectangle rectangle) {
                        Hwnd    hwnd;
-                       XEvent  xevent;
 
                        hwnd = Hwnd.ObjectFromHandle(handle);
 
-
-                       xevent = new XEvent ();
-                       xevent.type = XEventName.Expose;
-                       xevent.ExposeEvent.display = DisplayHandle;
-                       xevent.ExposeEvent.window = hwnd.whole_window;
-
-                       xevent.ExposeEvent.x = rectangle.X;
-                       xevent.ExposeEvent.y = rectangle.Y;
-                       xevent.ExposeEvent.width = rectangle.Width;
-                       xevent.ExposeEvent.height = rectangle.Height;
-
-                       AddExpose (xevent);
+                       AddExpose (hwnd, false, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
                }
 
                private void WholeToScreen(IntPtr handle, ref int x, ref int y) {
@@ -892,10 +988,10 @@ namespace System.Windows.Forms {
 
                        XGetWindowProperty(DisplayHandle, window, NetAtoms[(int)NA._NET_FRAME_EXTENTS], IntPtr.Zero, new IntPtr (16), false, (IntPtr)Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
                        if (((long)nitems == 4) && (prop != IntPtr.Zero)) {
-                               left = Marshal.ReadInt32(prop, 0);
-                               //right = Marshal.ReadInt32(prop, 4);
-                               top = Marshal.ReadInt32(prop, 8);
-                               //bottom = Marshal.ReadInt32(prop, 12);
+                               left = Marshal.ReadIntPtr(prop, 0).ToInt32();
+                               //right = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
+                               top = Marshal.ReadIntPtr(prop, IntPtr.Size * 2).ToInt32();
+                               //bottom = Marshal.ReadIntPtr(prop, IntPtr.Size * 3).ToInt32();
                        } else {
                                left = 0;
                                top = 0;
@@ -917,7 +1013,7 @@ namespace System.Windows.Forms {
                                return;
                        }
 
-                       if (xevent.ConfigureEvent.window == hwnd.whole_window) {
+                       if ((xevent.ConfigureEvent.window == hwnd.whole_window) && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)) {
                                if (!hwnd.reparented) {
                                        hwnd.x = xevent.ConfigureEvent.x;
                                        hwnd.y = xevent.ConfigureEvent.y;
@@ -931,7 +1027,6 @@ namespace System.Windows.Forms {
                                        // The only sane WM seems to be KDE
 
                                        if (!xevent.ConfigureEvent.send_event) {
-                                               int     dummy_int;
                                                IntPtr  dummy_ptr;
 
                                                XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, -xevent.ConfigureEvent.x, -xevent.ConfigureEvent.y, out hwnd.x, out hwnd.y, out dummy_ptr);
@@ -951,9 +1046,10 @@ namespace System.Windows.Forms {
                                }
                                hwnd.width = xevent.ConfigureEvent.width;
                                hwnd.height = xevent.ConfigureEvent.height;
+                               hwnd.ClientRect = Rectangle.Empty;
 
                                if (!hwnd.configure_pending) {
-                                       MessageQueue.Enqueue(xevent);
+                                       hwnd.Queue.Enqueue(xevent);
                                        hwnd.configure_pending = true;
                                }
                        }
@@ -1000,6 +1096,8 @@ namespace System.Windows.Forms {
                                timeout = Timer.Minimum;
                        }
 
+                       if (timeout > 1000)
+                               timeout = 1000;
                        return timeout;
                }
 
@@ -1026,9 +1124,30 @@ namespace System.Windows.Forms {
                        }
                }
 
-               private void UpdateMessageQueue () {
+               private void MapWindow(Hwnd hwnd, WindowType windows) {
+                       hwnd.mapped = true;
+                       if ((windows & WindowType.Whole) != 0) {
+                               XMapWindow(DisplayHandle, hwnd.whole_window);
+                       }
+                       if ((windows & WindowType.Client) != 0) {
+                               XMapWindow(DisplayHandle, hwnd.client_window);
+                       }
+               }
+
+               private void UnmapWindow(Hwnd hwnd, WindowType windows) {
+                       hwnd.mapped = false;
+                       if ((windows & WindowType.Whole) != 0) {
+                               XUnmapWindow(DisplayHandle, hwnd.whole_window);
+                       }
+                       if ((windows & WindowType.Client) != 0) {
+                               XUnmapWindow(DisplayHandle, hwnd.client_window);
+                       }
+               }
+
+               private void UpdateMessageQueue (XEventQueue queue) {
                        DateTime        now;
                        int             pending;
+                       Hwnd            hwnd;
 
                        now = DateTime.Now;
 
@@ -1049,6 +1168,10 @@ namespace System.Windows.Forms {
                        if (pending == 0) {
                                int     timeout;
 
+                               if ((queue != null) && (queue.Paint.Count > 0)) {
+                                       return;
+                               }
+
                                timeout = NextTimeout (now);
                                if (timeout > 0) {
                                        #if __MonoCS__
@@ -1077,11 +1200,25 @@ namespace System.Windows.Forms {
 
                                lock (XlibLock) {
                                        XNextEvent (DisplayHandle, ref xevent);
+
+                                       if (xevent.AnyEvent.type == XEventName.KeyPress) {
+                                               if (XFilterEvent(ref xevent, FosterParent)) {
+                                                       continue;
+                                               }
+                                       }
                                }
 //Console.WriteLine("Got x event {0}", xevent);
+
+                               hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
+                               if (hwnd == null) {
+                                       if (xevent.type == XEventName.Expose) {
+                                       }
+                                       pending = XPending (DisplayHandle);
+                                       continue;
+                               }
                                switch (xevent.type) {
                                        case XEventName.Expose:
-                                               AddExpose (xevent);
+                                               AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
                                                break;
 
                                        case XEventName.SelectionClear: {
@@ -1197,6 +1334,20 @@ namespace System.Windows.Forms {
                                                break;
                                        }
 
+                                       case XEventName.MapNotify: {
+                                               if (hwnd.client_window == xevent.MapEvent.window) {
+                                                       hwnd.mapped = true;
+                                               }
+                                               break;
+                                       }
+
+                                       case XEventName.UnmapNotify: {
+                                               if (hwnd.client_window == xevent.MapEvent.window) {
+                                                       hwnd.mapped = false;
+                                               }
+                                               break;
+                                       }
+
                                        case XEventName.KeyPress:
                                        case XEventName.KeyRelease:
                                        case XEventName.ButtonPress:
@@ -1210,7 +1361,7 @@ namespace System.Windows.Forms {
                                        case XEventName.FocusOut:
                                        case XEventName.ClientMessage:
                                        case XEventName.ReparentNotify:
-                                               MessageQueue.Enqueue (xevent);
+                                               hwnd.Queue.Enqueue (xevent);
                                                break;
 
                                        case XEventName.ConfigureNotify:
@@ -1320,7 +1471,7 @@ namespace System.Windows.Forms {
                        return 0;
                }
 
-               private void DestroyChildWindow(Control c) {
+               private void SendWMDestroyMessages(Control c) {
                        Hwnd            hwnd;
                        int             i;
                        Control[]       controls;
@@ -1328,37 +1479,82 @@ namespace System.Windows.Forms {
                        if (c != null) {
                                controls = c.child_controls.GetAllControls ();
 
+                               if (c.IsHandleCreated && !c.IsDisposed) {
+                                       #if DriverDebugDestroy
+                                               Console.WriteLine("Destroying {0}, child of {1}", XplatUI.Window(c.Handle), (c.Parent != null) ? XplatUI.Window(c.Parent.Handle) : "<none>");
+                                       #endif
+
+                                       hwnd = Hwnd.ObjectFromHandle(c.Handle);
+                                       SendMessage(c.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
+                               }
+
                                for (i = 0; i < controls.Length; i++) {
+                                       SendWMDestroyMessages(controls[i]);
                                        if (controls[i].IsHandleCreated) {
                                                hwnd = Hwnd.ObjectFromHandle(controls[i].Handle);
-                                               SendMessage(controls[i].Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
-                                               hwnd.Dispose();
+                                               if (hwnd != null) {
+                                                       hwnd.Dispose();
+                                               }
                                        }
-                                       DestroyChildWindow(controls[i]);
                                }
                        }
                }
 
+               private void PerformNCCalc(Hwnd hwnd) {
+                       XplatUIWin32.NCCALCSIZE_PARAMS  ncp;
+                       IntPtr                          ptr;
+                       Rectangle                       rect;
+
+                       rect = hwnd.DefaultClientRect;
+
+                       ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
+                       ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
+
+                       ncp.rgrc1.left = rect.Left;
+                       ncp.rgrc1.top = rect.Top;
+                       ncp.rgrc1.right = rect.Right;
+                       ncp.rgrc1.bottom = rect.Bottom;
+
+                       Marshal.StructureToPtr(ncp, ptr, true);
+                       NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
+                       ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
+                       Marshal.FreeHGlobal(ptr);
+
+                       // FIXME - debug this with Menus
+
+                       rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
+                       hwnd.ClientRect = rect;
+
+                       if (hwnd.visible) {
+                               if ((rect.Width < 1) || (rect.Height < 1)) {
+                                       XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
+                               } else {
+                                       XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
+                               }
+                       }
+               }
                #endregion      // Private Methods
 
                #region Callbacks
                private void MouseHover(object sender, EventArgs e) {
-                       if ((HoverState.X == MousePosition.X) && (HoverState.Y == MousePosition.Y)) {
-                               XEvent xevent;
+                       XEvent  xevent;
+                       Hwnd    hwnd;
 
-                               HoverState.Timer.Enabled = false;
+                       HoverState.Timer.Enabled = false;
 
-                               if (HoverState.Window != IntPtr.Zero) {
+                       if (HoverState.Window != IntPtr.Zero) {
+                               hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
+                               if (hwnd != null) {
                                        xevent = new XEvent ();
 
                                        xevent.type = XEventName.ClientMessage;
                                        xevent.ClientMessageEvent.display = DisplayHandle;
-                                       xevent.ClientMessageEvent.window = (IntPtr)HoverState.Window;
-                                       xevent.ClientMessageEvent.message_type = (IntPtr)HoverState.Atom;
+                                       xevent.ClientMessageEvent.window = HoverState.Window;
+                                       xevent.ClientMessageEvent.message_type = HoverState.Atom;
                                        xevent.ClientMessageEvent.format = 32;
                                        xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
 
-                                       MessageQueue.EnqueueLocked (xevent);
+                                       hwnd.Queue.EnqueueLocked (xevent);
 
                                        WakeupMain ();
                                }
@@ -1379,7 +1575,7 @@ namespace System.Windows.Forms {
 
                internal override int Caption {
                        get {
-                               return 25; 
+                               return 19;
                        }
                }
 
@@ -1605,6 +1801,20 @@ namespace System.Windows.Forms {
                        }
                } 
 
+               internal override Size MouseHoverSize {
+                       get {
+                               return new Size (1, 1);
+                       }
+               }
+
+               internal override int MouseHoverTime {
+                       get {
+                               return HoverState.Interval;
+                       }
+               }
+
+
+
                internal override  bool MouseWheelPresent {
                        get {
                                return true;    // FIXME - how to detect?
@@ -1628,9 +1838,9 @@ namespace System.Windows.Forms {
                                int                     height;
 
                                XGetWindowProperty(DisplayHandle, RootWindow, NetAtoms[(int)NA._NET_DESKTOP_GEOMETRY], IntPtr.Zero, new IntPtr (256), false, (IntPtr)Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
-                               if (((long)nitems == 2) && (prop != IntPtr.Zero)) {
-                                       width = Marshal.ReadInt32(prop, 0);
-                                       height = Marshal.ReadInt32(prop, 4);
+                               if (((long)nitems == 2) && (prop != IntPtr.Zero) && IntPtr.Size == 4) {
+                                       width = Marshal.ReadIntPtr(prop, 0).ToInt32();
+                                       height = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
 
                                        XFree(prop);
                                        return new Rectangle(0, 0, width, height);
@@ -1690,40 +1900,33 @@ namespace System.Windows.Forms {
 
 
                internal override void CaretVisible(IntPtr handle, bool visible) {
-                       // Visible is cumulative; two hides require two shows before the caret is visible again
                        if (Caret.Hwnd == handle) {
                                if (visible) {
-                                       if (Caret.Visible < 1) {
-                                               Caret.Visible++;
-                                               Caret.On = false;
-                                               if (Caret.Visible == 1) {
-                                                       ShowCaret();
-                                                       Caret.Timer.Start();
-                                               }
+                                       if (!Caret.Visible) {
+                                               Caret.Visible = true;
+                                               ShowCaret();
+                                               Caret.Timer.Start();
                                        }
                                } else {
-                                       Caret.Visible--;
-                                       if (Caret.Visible == 0) {
-                                               Caret.Timer.Stop();
-                                               HideCaret();
-                                       }
+                                       Caret.Visible = false;
+                                       Caret.Timer.Stop();
+                                       HideCaret();
                                }
                        }
                }
 
-               internal override bool CalculateWindowRect(IntPtr handle, ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
+               internal override bool CalculateWindowRect(ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
                        FormBorderStyle border_style;
                        TitleStyle      title_style;
                        int caption_height;
                        int tool_caption_height;
 
-                       DeriveStyles(handle, Style, ExStyle, out border_style, out title_style,
+                       DeriveStyles(Style, ExStyle, out border_style, out title_style,
                                out caption_height, out tool_caption_height);
 
                        WindowRect = Hwnd.GetWindowRectangle(border_style, menu, title_style,
                                        caption_height, tool_caption_height,
                                        ClientRect);
-
                        return true;
                }
 
@@ -1760,7 +1963,7 @@ namespace System.Windows.Forms {
 
                                Clipboard.Enumerating = true;
                                while (Clipboard.Enumerating) {
-                                       UpdateMessageQueue();
+                                       UpdateMessageQueue(null);
                                }
                                f = f.Next;
                        }
@@ -1768,7 +1971,7 @@ namespace System.Windows.Forms {
                        result = new int[Clipboard.Formats.Count];
 
                        for (int i = 0; i < Clipboard.Formats.Count; i++) {
-                               result[i] = (int)Clipboard.Formats[i];
+                               result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
                        }
 
                        Clipboard.Formats = null;
@@ -1816,7 +2019,7 @@ namespace System.Windows.Forms {
 
                        Clipboard.Retrieving = true;
                        while (Clipboard.Retrieving) {
-                               UpdateMessageQueue();
+                               UpdateMessageQueue(null);
                        }
 
                        return Clipboard.Item;
@@ -1849,7 +2052,7 @@ namespace System.Windows.Forms {
                        Caret.Window = hwnd.client_window;
                        Caret.Width = width;
                        Caret.Height = height;
-                       Caret.Visible = 0;
+                       Caret.Visible = false;
                        Caret.On = false;
 
                        gc_values = new XGCValues();
@@ -1911,7 +2114,7 @@ namespace System.Windows.Forms {
                        Attributes.win_gravity = Gravity.NorthWestGravity;
 
                        // Save what's under the toolwindow
-                       if ((cp.ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
+                       if ((cp.ExStyle & (int)WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
                                Attributes.save_under = true;
                                ValueMask |= SetWindowValuemask.SaveUnder;
                        }
@@ -1955,25 +2158,39 @@ namespace System.Windows.Forms {
                                throw new Exception("Could not create X11 windows");
                        }
 
+                       hwnd.Queue = ThreadQueue(Thread.CurrentThread);
                        hwnd.WholeWindow = WholeWindow;
                        hwnd.ClientWindow = ClientWindow;
 
-                       #if DriverDebug
-                               Console.WriteLine("Created window {0:X} / {1:X} parent {2:X}", ClientWindow.ToInt32(), WholeWindow.ToInt32(), hwnd.parent != null ? hwnd.parent.Handle.ToInt32() : 0);
+                       #if DriverDebug || DriverDebugCreate
+                               Console.WriteLine("Created window {0:X} / {1:X} parent {2:X}, Style {3}, ExStyle {4}", ClientWindow.ToInt32(), WholeWindow.ToInt32(), hwnd.parent != null ? hwnd.parent.Handle.ToInt32() : 0, (WindowStyles)cp.Style, (WindowExStyles)cp.ExStyle);
                        #endif
-                                      
+
+                       if ((cp.Style & (int)WindowStyles.WS_CHILD) == 0) {
+                               if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
+                                       XSizeHints      hints;
+
+                                       hints = new XSizeHints();
+                                       hints.x = X;
+                                       hints.y = Y;
+                                       hints.flags = (IntPtr)XSizeHintsFlags.USPosition;
+                                       XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
+                               }
+                       }
+
                        lock (XlibLock) {
                                XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)SelectInputMask));
                                XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)SelectInputMask));
 
                                if ((cp.Style & (int)WindowStyles.WS_VISIBLE) != 0) {
-                                       XMapWindow(DisplayHandle, hwnd.whole_window);
-                                       XMapWindow(DisplayHandle, hwnd.client_window);
+                                       MapWindow(hwnd, WindowType.Both);
                                        hwnd.visible = true;
                                }
                        }
 
-                       if ((cp.ExStyle & (int) WindowStyles.WS_EX_TOPMOST) != 0) {
+                       if ((cp.ExStyle & (int)WindowExStyles.WS_EX_TOPMOST) != 0) {
+                               XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
+                       } else if ((cp.ExStyle & (int)WindowExStyles.WS_EX_APPWINDOW) == 0) {
                                XSetTransientForHint (DisplayHandle, hwnd.whole_window, FosterParent);
                        }
 
@@ -2256,12 +2473,104 @@ namespace System.Windows.Forms {
                }
 
                internal override IntPtr DefWndProc(ref Message msg) {
+                       switch ((Msg)msg.Msg) {
+                               case Msg.WM_PAINT: {
+                                       Hwnd hwnd;
+
+                                       hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
+                                       if (hwnd != null) {
+                                               hwnd.expose_pending = false;
+                                       }
+
+                                       return IntPtr.Zero;
+                               }
+
+                               case Msg.WM_NCPAINT: {
+                                       Hwnd hwnd;
+
+                                       hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
+                                       if (hwnd != null) {
+                                               hwnd.nc_expose_pending = false;
+                                       }
+
+                                       return IntPtr.Zero;
+                               }
+
+                               case Msg.WM_CONTEXTMENU: {
+                                       Hwnd hwnd;
+
+                                       hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
+
+                                       if ((hwnd != null) && (hwnd.parent != null)) {
+                                               SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
+                                       }
+                                       return IntPtr.Zero;
+                               }
+
+                               case Msg.WM_SETCURSOR: {
+                                       Hwnd    hwnd;
+
+                                       hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
+                                       if (hwnd == null)
+                                               break; // not sure how this happens, but it does
+
+                                       // Pass to parent window first
+                                       while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
+                                               hwnd = hwnd.parent;
+                                               msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
+                                       }
+
+                                       if (msg.Result == IntPtr.Zero) {
+                                               IntPtr handle;
+
+                                               switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
+                                                       case HitTest.HTBOTTOM:          handle = Cursors.SizeNS.handle; break;
+                                                       case HitTest.HTBORDER:          handle = Cursors.SizeNS.handle; break;
+                                                       case HitTest.HTBOTTOMLEFT:      handle = Cursors.SizeNESW.handle; break;
+                                                       case HitTest.HTBOTTOMRIGHT:     handle = Cursors.SizeNWSE.handle; break;
+                                                       case HitTest.HTERROR:           if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
+                                                                                               AudibleAlert();
+                                                                                       }
+                                                                                       handle = Cursors.Default.handle;
+                                                                                       break;
+
+                                                       case HitTest.HTHELP:            handle = Cursors.Help.handle; break;
+                                                       case HitTest.HTLEFT:            handle = Cursors.SizeWE.handle; break;
+                                                       case HitTest.HTRIGHT:           handle = Cursors.SizeWE.handle; break;
+                                                       case HitTest.HTTOP:             handle = Cursors.SizeNS.handle; break;
+                                                       case HitTest.HTTOPLEFT:         handle = Cursors.SizeNWSE.handle; break;
+                                                       case HitTest.HTTOPRIGHT:        handle = Cursors.SizeNESW.handle; break;
+
+                                                       #if SameAsDefault
+                                                       case HitTest.HTGROWBOX:
+                                                       case HitTest.HTSIZE:
+                                                       case HitTest.HTZOOM:
+                                                       case HitTest.HTVSCROLL:
+                                                       case HitTest.HTSYSMENU:
+                                                       case HitTest.HTREDUCE:
+                                                       case HitTest.HTNOWHERE:
+                                                       case HitTest.HTMAXBUTTON:
+                                                       case HitTest.HTMINBUTTON:
+                                                       case HitTest.HTMENU:
+                                                       case HitTest.HSCROLL:
+                                                       case HitTest.HTBOTTOM:
+                                                       case HitTest.HTCAPTION:
+                                                       case HitTest.HTCLIENT:
+                                                       case HitTest.HTCLOSE:
+                                                       #endif
+                                                       default: handle = Cursors.Default.handle; break;
+                                               }
+                                               SetCursor(msg.HWnd, handle);
+                                       }
+                                       return (IntPtr)1;
+                               }
+                       }
                        return IntPtr.Zero;
                }
 
                internal override void DestroyCaret(IntPtr handle) {
                        if (Caret.Hwnd == handle) {
-                               if (Caret.Visible == 1) {
+                               if (Caret.Visible == true) {
                                        Caret.Timer.Stop();
                                        HideCaret();
                                }
@@ -2270,11 +2579,24 @@ namespace System.Windows.Forms {
                                        Caret.gc = IntPtr.Zero;
                                }
                                Caret.Hwnd = IntPtr.Zero;
-                               Caret.Visible = 0;
+                               Caret.Visible = false;
                                Caret.On = false;
                        }
                }
 
+               private void DestroyCaretInternal() {
+                       if (Caret.Visible == true) {
+                               Caret.Timer.Stop();
+                       }
+                       if (Caret.gc != IntPtr.Zero) {
+                               XFreeGC(DisplayHandle, Caret.gc);
+                               Caret.gc = IntPtr.Zero;
+                       }
+                       Caret.Hwnd = IntPtr.Zero;
+                       Caret.Visible = false;
+                       Caret.On = false;
+               }
+
                internal override void DestroyCursor(IntPtr cursor) {
                        lock (XlibLock) {
                                XFreeCursor(DisplayHandle, cursor);
@@ -2287,13 +2609,13 @@ namespace System.Windows.Forms {
                        hwnd = Hwnd.ObjectFromHandle(handle);
 
                        if (hwnd == null) {
-                               #if DriverDebug
+                               #if DriverDebug || DriverDebugDestroy
                                        Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
                                #endif
                                return;
                        }
 
-                       #if DriverDebug
+                       #if DriverDebug || DriverDebugDestroy
                                Console.WriteLine("Destroying window {0:X}", handle.ToInt32());
                        #endif
 
@@ -2302,11 +2624,12 @@ namespace System.Windows.Forms {
                                DestroyCaret(handle);
                        }
 
-                       // Mark our children as gone as well
-                       DestroyChildWindow(Control.ControlNativeWindow.ControlFromHandle(handle));
+                       if (ActiveWindow == handle) {
+                               SendMessage(handle, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
+                               ActiveWindow = IntPtr.Zero;
+                       }
 
-                       // Send destroy message
-                       SendMessage(handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
+                       SendWMDestroyMessages(Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle));
 
                        lock (XlibLock) {
                                if (hwnd.client_window != IntPtr.Zero) {
@@ -2368,8 +2691,8 @@ namespace System.Windows.Forms {
 
                        uint mask = foreground ^ background; 
 
-                       XSetForeground(DisplayHandle, gc, (IntPtr)0xffffffff);
-                       XSetBackground(DisplayHandle, gc, (IntPtr)background);
+                       XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
+                       XSetBackground(DisplayHandle, gc, (UIntPtr)background);
                        XSetFunction(DisplayHandle,   gc, GXFunction.GXxor);
                        XSetPlaneMask(DisplayHandle,  gc, (IntPtr)mask);
 
@@ -2386,13 +2709,16 @@ namespace System.Windows.Forms {
                }
 
                internal override void DoEvents() {
-                       MSG msg = new MSG ();
+                       MSG     msg = new MSG ();
+                       Object  queue_id;
 
                        if (OverrideCursorHandle != IntPtr.Zero) {
                                OverrideCursorHandle = IntPtr.Zero;
                        }
 
-                       while (PeekMessage(ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
+                       queue_id = (Object)ThreadQueue(Thread.CurrentThread);
+
+                       while (PeekMessage(queue_id, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
                                TranslateMessage (ref msg);
                                DispatchMessage (ref msg);
                        }
@@ -2439,8 +2765,22 @@ namespace System.Windows.Forms {
                        return active;
                }
 
+               internal override Region GetClipRegion(IntPtr handle) {
+                       Hwnd    hwnd;
+
+                       hwnd = Hwnd.ObjectFromHandle(handle);
+                       if (hwnd != null) {
+                               return hwnd.UserClip;
+                       }
+
+                       return null;
+               }
+
                internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
-                       throw new NotImplementedException ();
+                       width = 20;
+                       height = 20;
+                       hotspot_x = 0;
+                       hotspot_y = 0;
                }
 
                internal override void GetDisplaySize(out Size size) {
@@ -2520,20 +2860,23 @@ namespace System.Windows.Forms {
                        return Point.Empty;
                }
 
-               internal override bool GetMessage(ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
+               [MonoTODO("Implement filtering")]
+               internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
                        XEvent  xevent;
                        bool    client;
                        Hwnd    hwnd;
 
                        ProcessNextMessage:
 
-                       if (MessageQueue.Count > 0) {
-                               xevent = (XEvent) MessageQueue.Dequeue ();
+                       if (((XEventQueue)queue_id).Count > 0) {
+                               xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
                        } else {
-                               UpdateMessageQueue ();
+                               UpdateMessageQueue ((XEventQueue)queue_id);
 
-                               if (MessageQueue.Count > 0) {
-                                       xevent = (XEvent) MessageQueue.Dequeue ();
+                               if (((XEventQueue)queue_id).Count > 0) {
+                                       xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
+                               } else if (((XEventQueue)queue_id).Paint.Count > 0) {
+                                       xevent = ((XEventQueue)queue_id).Paint.Dequeue();
                                } else {
                                        if (!PostQuitState) {
                                                msg.hwnd= IntPtr.Zero;
@@ -2548,8 +2891,6 @@ namespace System.Windows.Forms {
                                }
                        }
 
-                       // FIXME - handle filtering
-
                        hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
 
                        // Handle messages for windows that are already or are about to be destroyed
@@ -2688,7 +3029,11 @@ namespace System.Windows.Forms {
                                }
 
                                case XEventName.ButtonRelease: {
-                                       Dnd.HandleButtonRelease (ref xevent);
+                                       if (Dnd.InDrag()) {
+                                               Dnd.HandleButtonRelease (ref xevent);
+                                               break;
+                                       }
+
                                        switch(xevent.ButtonEvent.button) {
                                                case 1: {
                                                        MouseState &= ~MouseButtons.Left;
@@ -2779,30 +3124,47 @@ namespace System.Windows.Forms {
                                                        msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
                                                }
 
-                                               HoverState.X = MousePosition.X = xevent.MotionEvent.x;
-                                               HoverState.Y = MousePosition.Y = xevent.MotionEvent.y;
+                                               MousePosition.X = xevent.MotionEvent.x;
+                                               MousePosition.Y = xevent.MotionEvent.y;
+
+                                               if ((HoverState.Timer.Enabled) &&
+                                                   (((MousePosition.X + HoverState.Size.Width) < HoverState.X) ||
+                                                   ((MousePosition.X - HoverState.Size.Width) > HoverState.X) ||
+                                                   ((MousePosition.Y + HoverState.Size.Height) < HoverState.Y) ||
+                                                   ((MousePosition.Y - HoverState.Size.Height) > HoverState.Y))) {
+                                                       HoverState.Timer.Stop();
+                                                       HoverState.Timer.Start();
+                                                       HoverState.X = MousePosition.X;
+                                                       HoverState.Y = MousePosition.Y;
+                                               }
 
                                                break;
                                        } 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);
                                                #endif
                                                msg.message = Msg.WM_NCMOUSEMOVE;
-                                               msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
 
                                                if (!hwnd.Enabled) {
-                                                       IntPtr dummy;
-
                                                        msg.hwnd = hwnd.EnabledHwnd;
                                                        XTranslateCoordinates(DisplayHandle, xevent.AnyEvent.window, Hwnd.ObjectFromHandle(msg.hwnd).ClientWindow, xevent.MotionEvent.x, xevent.MotionEvent.y, out xevent.MotionEvent.x, out xevent.MotionEvent.y, out dummy);
                                                        msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
                                                }
 
-                                               #if notyet
-                                                       // Not sure we need this...
-                                                       HitTest ht;
-                                                       ht = NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCHITTEST, IntPtr.Zero, msg.lParam);
-                                               #endif
+                                               // The hit test is sent in screen coordinates
+                                               XTranslateCoordinates (DisplayHandle, hwnd.client_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 ();
+                                               NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
 
                                                MousePosition.X = xevent.MotionEvent.x;
                                                MousePosition.Y = xevent.MotionEvent.y;
@@ -2819,6 +3181,8 @@ namespace System.Windows.Forms {
                                                goto ProcessNextMessage;
                                        }
                                        msg.message = Msg.WM_MOUSE_ENTER;
+                                       HoverState.X = xevent.CrossingEvent.x;
+                                       HoverState.Y = xevent.CrossingEvent.y;
                                        HoverState.Timer.Enabled = true;
                                        HoverState.Window = xevent.CrossingEvent.window;
                                        break;
@@ -2828,7 +3192,7 @@ namespace System.Windows.Forms {
                                        if (!hwnd.Enabled) {
                                                goto ProcessNextMessage;
                                        }
-                                       if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
+                                       if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
                                                goto ProcessNextMessage;
                                        }
                                        msg.message=Msg.WM_MOUSE_LEAVE;
@@ -2875,86 +3239,74 @@ namespace System.Windows.Forms {
                                                                hwnd.whacky_wm = true;
                                                        }
 
-                                                       msg.message = Msg.WM_WINDOWPOSCHANGED;
                                                        if (hwnd.opacity != 0xffffffff) {
-                                                               uint opacity;
+                                                               IntPtr opacity;
 
-                                                               opacity = hwnd.opacity;
+                                                               opacity = (IntPtr)(Int32)hwnd.opacity;
                                                                XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), NetAtoms[(int)NA._NET_WM_WINDOW_OPACITY], (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
                                                        }
+                                                       SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
+                                                       goto ProcessNextMessage;
                                                } else {
                                                        hwnd.Reparented = false;
                                                        goto ProcessNextMessage;
                                                }
                                        }
-                                       break;
+                                       goto ProcessNextMessage;
                                }
 
                                case XEventName.ConfigureNotify: {
-                                       if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {        // Ignore events for children (SubstructureNotify) and client areas
-                                               XplatUIWin32.NCCALCSIZE_PARAMS  ncp;
-                                               IntPtr                          ptr;
-                                               Rectangle                       rect;
-
+                                       if (PostQuitState || !client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {       // Ignore events for children (SubstructureNotify) and client areas
                                                #if DriverDebugExtra
                                                        Console.WriteLine("GetMessage(): Window {0:X} ConfigureNotify x={1} y={2} width={3} height={4}", hwnd.client_window.ToInt32(), xevent.ConfigureEvent.x, xevent.ConfigureEvent.y, xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
                                                #endif
-                                               msg.message = Msg.WM_WINDOWPOSCHANGED;
+                                               SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
                                                hwnd.configure_pending = false;
 
                                                // We need to adjust our client window to track the resize of whole_window
-                                               rect = hwnd.DefaultClientRect;
-
-                                               ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
-                                               ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
-
-                                               ncp.rgrc1.left = rect.Left;
-                                               ncp.rgrc1.top = rect.Top;
-                                               ncp.rgrc1.right = rect.Right;
-                                               ncp.rgrc1.bottom = rect.Bottom;
-
-                                               Marshal.StructureToPtr(ncp, ptr, true);
-                                               NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
-                                               ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
-                                               Marshal.FreeHGlobal(ptr);
-
-                                               // FIXME - debug this with Menus, need to set hwnd.ClientRect
-
-                                               rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
-
-                                               XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
-                                       } else {
-                                               goto ProcessNextMessage;
+                                               PerformNCCalc(hwnd);
                                        }
-
-                                       msg.lParam=IntPtr.Zero;         // FIXME - Generate LPWINDOWPOS structure and pass on
-                                       break;
+                                       goto ProcessNextMessage;
                                }
 
                                case XEventName.FocusIn: {
-                                       if (!hwnd.Enabled) {
+                                       // We received focus. We use X11 focus only to know if the app window does or does not have focus
+                                       // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
+                                       // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know 
+                                       // about it having focus again
+                                       if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
                                                goto ProcessNextMessage;
                                        }
-                                       msg.message=Msg.WM_SETFOCUS;
-                                       msg.wParam=IntPtr.Zero;
-                                       break;
+                                       Keyboard.FocusIn(FocusWindow);
+                                       SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
+                                       goto ProcessNextMessage;
                                }
 
                                case XEventName.FocusOut: {
-                                       if (!hwnd.Enabled) {
+                                       // Se the comment for our FocusIn handler
+                                       if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
                                                goto ProcessNextMessage;
                                        }
-                                       msg.message=Msg.WM_KILLFOCUS;
-                                       msg.wParam=IntPtr.Zero;
-                                       break;
+                                       Keyboard.FocusOut(FocusWindow);
+
+                                       while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
+                                               SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
+                                       }
+
+                                       SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
+                                       goto ProcessNextMessage;
                                }
 
                                case XEventName.Expose: {
-                                       if (PostQuitState) {
+                                       if (PostQuitState || !hwnd.Mapped) {
+                                               if (client) {
+                                                       hwnd.expose_pending = false;
+                                               } else {
+                                                       hwnd.nc_expose_pending = false;
+                                               }
                                                goto ProcessNextMessage;
                                        }
 
-
                                        if (client) {
                                                if (!hwnd.expose_pending) {
                                                        goto ProcessNextMessage;
@@ -2969,7 +3321,7 @@ namespace System.Windows.Forms {
                                                                Graphics g;
 
                                                                g = Graphics.FromHwnd(hwnd.whole_window);
-                                                               ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height));
+                                                               ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
                                                                g.Dispose();
                                                                break;
                                                        }
@@ -2992,18 +3344,17 @@ namespace System.Windows.Forms {
                                                IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
                                                msg.message = Msg.WM_NCPAINT;
                                                msg.wParam = hrgn;
-                                               hwnd.nc_expose_pending = false;
                                                break;
                                        }
                                        #if DriverDebugExtra
                                                Console.WriteLine("GetMessage(): Window {0:X} Exposed area {1},{2} {3}x{4}", hwnd.client_window.ToInt32(), xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
                                        #endif
-                                       if (Caret.Visible == 1) {
+                                       if (Caret.Visible == true) {
                                                Caret.Paused = true;
                                                HideCaret();
                                        }
 
-                                       if (Caret.Visible == 1) {
+                                       if (Caret.Visible == true) {
                                                ShowCaret();
                                                Caret.Paused = false;
                                        }
@@ -3017,7 +3368,20 @@ namespace System.Windows.Forms {
                                        hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
 
                                        // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
-                                       if (hwnd.client_window == xevent.DestroyWindowEvent.window) {
+                                       if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
+                                               if (ActiveWindow == hwnd.client_window) {
+                                                       SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
+                                                       ActiveWindow = IntPtr.Zero;
+                                               }
+
+                                               if (Caret.Window == hwnd.client_window) {
+                                                       DestroyCaretInternal();
+                                               }
+
+                                               #if DriverDebugDestroy
+                                                       Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
+                                               #endif
+
                                                msg.hwnd = hwnd.client_window;
                                                msg.message=Msg.WM_DESTROY;
                                                hwnd.Dispose();
@@ -3037,16 +3401,16 @@ namespace System.Windows.Forms {
                                                goto ProcessNextMessage;
                                        }
 
-                                       if (xevent.ClientMessageEvent.message_type == (IntPtr)AsyncAtom) {
+                                       if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
                                                XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
-                                               break;
+                                               goto ProcessNextMessage;
                                        }
 
-                                       if (xevent.ClientMessageEvent.message_type == (IntPtr)HoverState.Atom) {
+                                       if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
                                                msg.message = Msg.WM_MOUSEHOVER;
                                                msg.wParam = GetMousewParam(0);
                                                msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
-                                               break;
+                                               return true;
                                        }
 
                                        if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
@@ -3054,7 +3418,7 @@ namespace System.Windows.Forms {
                                                msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
                                                msg.wParam = xevent.ClientMessageEvent.ptr3;
                                                msg.lParam = xevent.ClientMessageEvent.ptr4;
-                                               break;
+                                               return true;
                                        }
 
                                        #if dontcare
@@ -3068,7 +3432,7 @@ namespace System.Windows.Forms {
                                                if (xevent.ClientMessageEvent.ptr1 == NetAtoms[(int)NA.WM_DELETE_WINDOW]) {
                                                        msg.message = Msg.WM_CLOSE;
                                                        Graphics.FromHdcInternal (IntPtr.Zero);
-                                                       break;
+                                                       return true;
                                                }
 
                                                // We should not get this, but I'll leave the code in case we need it in the future
@@ -3076,12 +3440,12 @@ namespace System.Windows.Forms {
                                                        goto ProcessNextMessage;
                                                }
                                        }
-                                       break;
+                                       goto ProcessNextMessage;
                                }
 
                                case XEventName.TimerNotify: {
                                        xevent.TimerNotifyEvent.handler (this, EventArgs.Empty);
-                                       break;
+                                       goto ProcessNextMessage;
                                }
                                        
                                default: {
@@ -3113,7 +3477,6 @@ namespace System.Windows.Forms {
 
                internal override void GetWindowPos(IntPtr handle, bool is_toplevel, out int x, out int y, out int width, out int height, out int client_width, out int client_height) {
                        Hwnd            hwnd;
-                       Rectangle       rect;
 
                        hwnd = Hwnd.ObjectFromHandle(handle);
 
@@ -3123,10 +3486,12 @@ namespace System.Windows.Forms {
                                width = hwnd.width;
                                height = hwnd.height;
 
-                               rect = Hwnd.GetClientRectangle(hwnd.border_style, hwnd.menu, hwnd.title_style, hwnd.caption_height, hwnd.tool_caption_height, width, height);
+                               if (hwnd.ClientRect.IsEmpty) {
+                                       PerformNCCalc(hwnd);
+                               }
 
-                               client_width = rect.Width;
-                               client_height = rect.Height;
+                               client_width = hwnd.ClientRect.Width;
+                               client_height = hwnd.ClientRect.Height;
 
                                return;
                        }
@@ -3244,29 +3609,14 @@ namespace System.Windows.Forms {
 
                internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
                        Hwnd    hwnd;
-                       XEvent  xevent;
 
                        hwnd = Hwnd.ObjectFromHandle(handle);
 
-
-                       xevent = new XEvent ();
-                       xevent.type = XEventName.Expose;
-                       xevent.ExposeEvent.display = DisplayHandle;
-                       xevent.ExposeEvent.window = hwnd.client_window;
-
                        if (clear) {
-                               xevent.ExposeEvent.x = hwnd.X;
-                               xevent.ExposeEvent.y = hwnd.Y;
-                               xevent.ExposeEvent.width = hwnd.Width;
-                               xevent.ExposeEvent.height = hwnd.Height;
+                               AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
                        } else {
-                               xevent.ExposeEvent.x = rc.X;
-                               xevent.ExposeEvent.y = rc.Y;
-                               xevent.ExposeEvent.width = rc.Width;
-                               xevent.ExposeEvent.height = rc.Height;
+                               AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
                        }
-
-                       AddExpose (xevent);
                }
 
                internal override bool IsEnabled(IntPtr handle) {
@@ -3309,21 +3659,50 @@ namespace System.Windows.Forms {
 
                        hwnd = Hwnd.ObjectFromHandle(handle);
 
-                       if (Caret.Visible == 1) {
+                       if (Caret.Visible == true) {
                                Caret.Paused = true;
                                HideCaret();
                        }
-
+                       
                        if (client) {
+#if true
                                hwnd.client_dc = Graphics.FromHwnd (hwnd.client_window);
-                               hwnd.client_dc.SetClip(hwnd.invalid);
-                               paint_event = new PaintEventArgs(hwnd.client_dc, hwnd.invalid);
+#else
+                               // Protected against illegal cross-thread painting
+                               lock (XlibLock) {
+                                       if (hwnd.client_dc != null) {
+                                               return null;
+                                       }
+
+                                       hwnd.client_dc = Graphics.FromHwnd (hwnd.client_window);
+                               }
+#endif
+
+                               Region clip_region = new Region ();
+                               clip_region.MakeEmpty();
+
+                               foreach (Rectangle r in hwnd.ClipRectangles) {
+                                       clip_region.Union (r);
+                               }
+
+                               if (hwnd.UserClip != null) {
+                                       clip_region.Intersect(hwnd.UserClip);
+                               }
+
+                               hwnd.client_dc.Clip = clip_region;
+                               paint_event = new PaintEventArgs(hwnd.client_dc, hwnd.Invalid);
                                hwnd.expose_pending = false;
 
                                return paint_event;
                        } else {
-                               hwnd.client_dc = Graphics.FromHwnd (hwnd.whole_window);
-                               paint_event = new PaintEventArgs(hwnd.client_dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
+                               hwnd.non_client_dc = Graphics.FromHwnd (hwnd.whole_window);
+
+                               if (!hwnd.nc_invalid.IsEmpty) {
+                                       hwnd.non_client_dc.SetClip (hwnd.nc_invalid);
+                                       paint_event = new PaintEventArgs(hwnd.non_client_dc, hwnd.nc_invalid);
+                               } else {
+                                       paint_event = new PaintEventArgs(hwnd.non_client_dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
+                               }
                                hwnd.nc_expose_pending = false;
 
                                return paint_event;
@@ -3337,35 +3716,52 @@ namespace System.Windows.Forms {
 
                        if (client) {
                                hwnd.ClearInvalidArea();
+
+#if true
+                               hwnd.client_dc.Flush();
+                               hwnd.client_dc.Dispose();
+                               hwnd.client_dc = null;
+#else
+                               lock (XlibLock) {
+                                       hwnd.client_dc.Flush();
+                                       hwnd.client_dc.Dispose();
+                                       hwnd.client_dc = null;
+                               }
+#endif
+                       } else {
+                               hwnd.ClearNcInvalidArea ();
+
+                               hwnd.non_client_dc.Flush ();
+                               hwnd.non_client_dc.Dispose ();
+                               hwnd.non_client_dc = null;
                        }
 
-                       hwnd.client_dc.Flush();
-                       hwnd.client_dc.Dispose();
-                       hwnd.client_dc = null;
+                       
 
-                       if (Caret.Visible == 1) {
+                       if (Caret.Visible == true) {
                                ShowCaret();
                                Caret.Paused = false;
                        }
                }
 
-               internal override bool PeekMessage(ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
+               [MonoTODO("Implement filtering and PM_NOREMOVE")]
+               internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
                        bool    pending;
 
-                       // FIXME - imlement filtering
-
                        if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
                                throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet");    // FIXME - Implement PM_NOREMOVE flag
                        }
 
                        pending = false;
-                       if (MessageQueue.Count > 0) {
+                       if (((XEventQueue)queue_id).Count > 0) {
                                pending = true;
                        } else {
                                // Only call UpdateMessageQueue if real events are pending 
                                // otherwise we go to sleep on the socket
                                if (XPending(DisplayHandle) != 0) {
-                                       UpdateMessageQueue();
+                                       UpdateMessageQueue((XEventQueue)queue_id);
+                                       pending = true;
+                               } else if (((XEventQueue)queue_id).Paint.Count > 0) {
                                        pending = true;
                                }
                        }
@@ -3375,7 +3771,7 @@ namespace System.Windows.Forms {
                        if (!pending) {
                                return false;
                        }
-                       return GetMessage(ref msg, hWnd, wFilterMin, wFilterMax);
+                       return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
                }
 
                // FIXME - I think this should just enqueue directly
@@ -3399,7 +3795,7 @@ namespace System.Windows.Forms {
                        xevent.ClientMessageEvent.ptr3 = wparam;
                        xevent.ClientMessageEvent.ptr4 = lparam;
 
-                       MessageQueue.Enqueue (xevent);
+                       hwnd.Queue.Enqueue (xevent);
 
                        return true;
                }
@@ -3412,6 +3808,35 @@ namespace System.Windows.Forms {
                        Graphics.FromHdcInternal (IntPtr.Zero);
                }
 
+               internal override void RequestNCRecalc(IntPtr handle) {
+                       Hwnd                            hwnd;
+
+                       hwnd = Hwnd.ObjectFromHandle(handle);
+
+                       if (hwnd == null) {
+                               return;
+                       }
+
+                       PerformNCCalc(hwnd);
+                       SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
+                       InvalidateWholeWindow(handle);
+               }
+
+               internal override void ResetMouseHover(IntPtr handle) {
+                       Hwnd    hwnd;
+
+                       hwnd = Hwnd.ObjectFromHandle(handle);
+                       if (hwnd == null) {
+                               return;
+                       }
+
+                       HoverState.Timer.Enabled = true;
+                       HoverState.X = MousePosition.X;
+                       HoverState.Y = MousePosition.Y;
+                       HoverState.Window = handle;
+               }
+
+
                internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
                        int     dest_x_return;
                        int     dest_y_return;
@@ -3448,26 +3873,30 @@ namespace System.Windows.Forms {
                        Hwnd            hwnd;
                        IntPtr          gc;
                        XGCValues       gc_values;
+                       Rectangle       r;
 
                        hwnd = Hwnd.ObjectFromHandle(handle);
 
-                       if (hwnd.invalid != Rectangle.Empty) {
-                               // BIG FAT WARNING. This only works with how we use this function right now
-                               // where we basically still scroll the whole window, but work around areas
-                               // that are covered by our children
+                       r = hwnd.Invalid;
+                       if (r != Rectangle.Empty) {
+                               /* We have an invalid area in the window we're scrolling. 
+                                  Adjust our stored invalid rectangle to to match the scrolled amount */
 
-                               hwnd.invalid.X += XAmount;
-                               hwnd.invalid.Y += YAmount;
+                               r.X += XAmount;
+                               r.Y += YAmount;
 
-                               if (hwnd.invalid.X < 0) {
-                                       hwnd.invalid.Width += hwnd.invalid.X;
-                                       hwnd.invalid.X =0;
+                               if (r.X < 0) {
+                                       r.Width += r.X;
+                                       r.X =0;
                                }
 
-                               if (hwnd.invalid.Y < 0) {
-                                       hwnd.invalid.Height += hwnd.invalid.Y;
-                                       hwnd.invalid.Y =0;
+                               if (r.Y < 0) {
+                                       r.Height += r.Y;
+                                       r.Y =0;
                                }
+
+                               hwnd.ClearInvalidArea();
+                               hwnd.AddInvalidArea(r);
                        }
 
                        gc_values = new XGCValues();
@@ -3478,36 +3907,68 @@ namespace System.Windows.Forms {
 
                        gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
 
-                       XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, area.X - XAmount, area.Y - YAmount, area.Width, area.Height, area.X, area.Y);
+                       int src_x, src_y;
+                       int dest_x, dest_y;
+                       int width, height;
+
+                       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;
+                       }
+
+                       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;
+                       }
+
+                       XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
 
                        // Generate an expose for the area exposed by the horizontal scroll
+                       // We don't use AddExpose since we're 
                        if (XAmount > 0) {
-                               hwnd.AddInvalidArea (area.X, area.Y, XAmount, area.Height);
+                               AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
                        } else if (XAmount < 0) {
-                               hwnd.AddInvalidArea (XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
+                               AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
                        }
 
                        // Generate an expose for the area exposed by the vertical scroll
                        if (YAmount > 0) {
-                               hwnd.AddInvalidArea (area.X, area.Y, area.Width, YAmount);
+                               AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
                        } else if (YAmount < 0) {
-                               hwnd.AddInvalidArea (area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
+                               AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
                        }
                        XFreeGC(DisplayHandle, gc);
-
-                       UpdateWindow(handle);
                }
 
                internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
-                       Hwnd    hwnd;
+                       Hwnd            hwnd;
+                       Rectangle       rect;
 
                        hwnd = Hwnd.GetObjectFromWindow(handle);
 
-                       ScrollWindow(handle, hwnd.ClientRect, XAmount, YAmount, with_children);
+                       rect = hwnd.ClientRect;
+                       rect.X = 0;
+                       rect.Y = 0;
+                       ScrollWindow(handle, rect, XAmount, YAmount, with_children);
                }
 
                internal override void SendAsyncMethod (AsyncMethodData method) {
-                       XEvent xevent = new XEvent ();
+                       Hwnd    hwnd;
+                       XEvent  xevent = new XEvent ();
+
+                       hwnd = Hwnd.ObjectFromHandle(FosterParent);
 
                        xevent.type = XEventName.ClientMessage;
                        xevent.ClientMessageEvent.display = DisplayHandle;
@@ -3516,7 +3977,7 @@ namespace System.Windows.Forms {
                        xevent.ClientMessageEvent.format = 32;
                        xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
 
-                       MessageQueue.EnqueueLocked (xevent);
+                       hwnd.Queue.EnqueueLocked (xevent);
 
                        WakeupMain ();
                }
@@ -3547,10 +4008,7 @@ namespace System.Windows.Forms {
                        hwnd = Hwnd.ObjectFromHandle(handle);
 
                        hwnd.border_style = border_style;
-
-                       XMoveResizeWindow(DisplayHandle, hwnd.client_window, hwnd.ClientRect.X, hwnd.ClientRect.Y, hwnd.ClientRect.Width, hwnd.ClientRect.Height);
-
-                       InvalidateWholeWindow(handle);
+                       RequestNCRecalc(handle);
                }
 
                internal override void SetCaretPos(IntPtr handle, int x, int y) {
@@ -3561,13 +4019,25 @@ namespace System.Windows.Forms {
                                Caret.X = x;
                                Caret.Y = y;
 
-                               if (Caret.Visible == 1) {
+                               if (Caret.Visible == true) {
                                        ShowCaret();
                                        Caret.Timer.Start();
                                }
                        }
                }
 
+               internal override void SetClipRegion(IntPtr handle, Region region) {
+                       Hwnd    hwnd;
+
+                       hwnd = Hwnd.ObjectFromHandle(handle);
+                       if (hwnd == null) {
+                               return;
+                       }
+
+                       hwnd.UserClip = region;
+                       Invalidate(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height), false);
+               }
+
                internal override void SetCursor(IntPtr handle, IntPtr cursor) {
                        Hwnd    hwnd;
 
@@ -3618,10 +4088,14 @@ namespace System.Windows.Forms {
 
                        hwnd = Hwnd.ObjectFromHandle(handle);
 
+                       if (hwnd.client_window == FocusWindow) {
+                               return;
+                       }
+
+                       SendMessage(hwnd.client_window, Msg.WM_SETFOCUS, FocusWindow, IntPtr.Zero);
                        if (FocusWindow != IntPtr.Zero) {
-                               PostMessage(FocusWindow, Msg.WM_KILLFOCUS, hwnd.client_window, IntPtr.Zero);
+                               SendMessage(FocusWindow, Msg.WM_KILLFOCUS, hwnd.client_window, IntPtr.Zero);
                        }
-                       PostMessage(hwnd.client_window, Msg.WM_SETFOCUS, FocusWindow, IntPtr.Zero);
                        FocusWindow = hwnd.client_window;
 
                        //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
@@ -3642,7 +4116,7 @@ namespace System.Windows.Forms {
                        hwnd = Hwnd.ObjectFromHandle(handle);
                        hwnd.menu = menu;
 
-                       // FIXME - do we need to trigger some resize?
+                       RequestNCRecalc(handle);
                }
 
                internal override void SetModal(IntPtr handle, bool Modal) {
@@ -3665,8 +4139,8 @@ namespace System.Windows.Forms {
                        hwnd.parent = Hwnd.ObjectFromHandle(parent);
 
                        lock (XlibLock) {
-                               #if DriverDebug
-                                       Console.WriteLine("Parent for window {0:X} / {1:X} = {2:X} (Handle:{3:X})", hwnd.ClientWindow.ToInt32(), hwnd.WholeWindow.ToInt32(), hwnd.parent != null ? hwnd.parent.Handle.ToInt32() : 0, parent.ToInt32());
+                               #if DriverDebug || DriverDebugParent
+                                       Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
                                #endif
                                XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent.client_window, hwnd.x, hwnd.y);
                        }
@@ -3698,7 +4172,7 @@ namespace System.Windows.Forms {
                                        if (hwnd_owner != null) {
                                                XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
                                        } else {
-                                               XSetTransientForHint(DisplayHandle, hwnd.whole_window, FosterParent);
+                                               XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
                                        }
                                }
                        } else {
@@ -3722,19 +4196,19 @@ namespace System.Windows.Forms {
 
                                                s = ((Form)Control.FromHandle(handle)).WindowState;
 
-                                               XMapWindow(DisplayHandle, hwnd.whole_window);
-                                               XMapWindow(DisplayHandle, hwnd.client_window);
+                                               MapWindow(hwnd, WindowType.Both);
 
                                                switch(s) {
                                                        case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
                                                        case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
                                                }
+
                                        } else {
-                                               XMapWindow(DisplayHandle, hwnd.whole_window);
-                                               XMapWindow(DisplayHandle, hwnd.client_window);
+                                               MapWindow(hwnd, WindowType.Both);
                                        }
+                                       SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
                                } else {
-                                       XUnmapWindow(DisplayHandle, hwnd.whole_window);
+                                       UnmapWindow(hwnd, WindowType.Whole);
                                }
                        }
                        return true;
@@ -3750,22 +4224,23 @@ namespace System.Windows.Forms {
                        }
 
                        hints = new XSizeHints();
-
-                       if (min != Size.Empty) {
+                       if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
                                hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
                                hints.min_width = min.Width;
                                hints.min_height = min.Height;
                        }
 
-                       if (max != Size.Empty) {
+                       if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
                                hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
                                hints.max_width = max.Width;
                                hints.max_height = max.Height;
                        }
 
-                       XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
+                       if (hints.flags != IntPtr.Zero) {
+                               XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
+                       }
 
-                       if (maximized != Rectangle.Empty) {
+                       if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
                                hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
                                hints.x = maximized.X;
                                hints.y = maximized.Y;
@@ -3780,41 +4255,37 @@ namespace System.Windows.Forms {
 
                internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
                        Hwnd            hwnd;
-                       Rectangle       client_rect;
 
                        hwnd = Hwnd.ObjectFromHandle(handle);
 
                        // X requires a sanity check for width & height; otherwise it dies
                        if (hwnd.zero_sized && width > 0 && height > 0) {
                                if (hwnd.visible) {
-                                       XMapWindow(DisplayHandle, hwnd.whole_window);
+                                       MapWindow(hwnd, WindowType.Whole);
                                }
                                hwnd.zero_sized = false;
                        }
 
-                       if (width < 1) {
+                       if ((width < 1) || (height < 1)) {
                                hwnd.zero_sized = true;
-                               XUnmapWindow(DisplayHandle, hwnd.whole_window);
+                               UnmapWindow(hwnd, WindowType.Whole);
                        }
 
-                       if (height < 1) {
-                               hwnd.zero_sized = true;
-                               XUnmapWindow(DisplayHandle, hwnd.whole_window);
-                       }
-
-                       client_rect = Hwnd.GetClientRectangle(hwnd.border_style, hwnd.menu, hwnd.title_style, hwnd.caption_height, hwnd.tool_caption_height, width, height);
-
                        // Save a server roundtrip (and prevent a feedback loop)
                        if ((hwnd.x == x) && (hwnd.y == y) && 
-                               (hwnd.width == width) && (hwnd.height == height) &&
-                               (hwnd.ClientRect == client_rect)) {
+                               (hwnd.width == width) && (hwnd.height == height)) {
                                return;
                        }
 
                        if (!hwnd.zero_sized) {
+
+                               if (hwnd.fixed_size) {
+                                       SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
+                               }
+
                                lock (XlibLock) {
                                        XMoveResizeWindow(DisplayHandle, hwnd.whole_window, x, y, width, height);
-                                       XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
+                                       PerformNCCalc(hwnd);
                                }
                        }
 
@@ -3829,7 +4300,12 @@ namespace System.Windows.Forms {
 
                        hwnd = Hwnd.ObjectFromHandle(handle);
 
-                       current_state = GetWindowState(handle);
+                       try {
+                               current_state = GetWindowState(handle);
+                       }
+                       catch (NotSupportedException) {
+                               current_state = (FormWindowState)(-1);
+                       }
 
                        if (current_state == state) {
                                return;
@@ -3839,10 +4315,9 @@ namespace System.Windows.Forms {
                                case FormWindowState.Normal: {
                                        lock (XlibLock) {
                                                if (current_state == FormWindowState.Minimized) {
-                                                       XMapWindow(DisplayHandle, hwnd.whole_window);
-                                                       XMapWindow(DisplayHandle, hwnd.client_window);
+                                                       MapWindow(hwnd, WindowType.Both);
                                                } else if (current_state == FormWindowState.Maximized) {
-                                                       SendNetWMMessage(hwnd.whole_window, (IntPtr)(uint)NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)2 /* toggle */, NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT]);
+                                                       SendNetWMMessage(hwnd.whole_window, NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)2 /* toggle */, NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT]);
                                                }
                                        }
                                        Activate(handle);
@@ -3862,8 +4337,7 @@ namespace System.Windows.Forms {
                                case FormWindowState.Maximized: {
                                        lock (XlibLock) {
                                                if (current_state == FormWindowState.Minimized) {
-                                                       XMapWindow(DisplayHandle, hwnd.whole_window);
-                                                       XMapWindow(DisplayHandle, hwnd.client_window);
+                                                       MapWindow(hwnd, WindowType.Both);
                                                }
 
                                                SendNetWMMessage(hwnd.whole_window, NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)1 /* Add */, NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT]);
@@ -3884,7 +4358,7 @@ namespace System.Windows.Forms {
 
                internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
                        Hwnd    hwnd;
-                       uint    opacity;
+                       IntPtr  opacity;
 
                        hwnd = Hwnd.ObjectFromHandle(handle);
 
@@ -3893,7 +4367,7 @@ namespace System.Windows.Forms {
                        }
 
                        hwnd.opacity = (uint)(0xffffffff * transparency);
-                       opacity = hwnd.opacity;
+                       opacity = (IntPtr)((int)hwnd.opacity);
 
                        if (hwnd.reparented) {
                                XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), NetAtoms[(int)NA._NET_WM_WINDOW_OPACITY], (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
@@ -3940,8 +4414,8 @@ namespace System.Windows.Forms {
                        ;       // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
                }
 
-               internal override void StartLoop(Thread thread) {
-                       // Future place for prepping a new queue for this specific thread
+               internal override object StartLoop(Thread thread) {
+                       return (Object) ThreadQueue(thread);
                }
 
                internal override bool SupportsTransparency() {
@@ -3961,8 +4435,7 @@ namespace System.Windows.Forms {
                                        Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
                                #endif
 
-                               XUnmapWindow(DisplayHandle, hwnd.whole_window);
-                               XUnmapWindow(DisplayHandle, hwnd.client_window);
+                               UnmapWindow(hwnd, WindowType.Whole);
 
                                // Oh boy.
                                XDestroyWindow(DisplayHandle, hwnd.client_window);
@@ -4030,7 +4503,7 @@ namespace System.Windows.Forms {
 
                        hwnd = Hwnd.ObjectFromHandle(handle);
 
-                       XUnmapWindow(DisplayHandle, hwnd.whole_window);
+                       UnmapWindow(hwnd, WindowType.Whole);
                        SetParent(hwnd.whole_window, FosterParent);
 
                        // The caller can now re-dock it later...
@@ -4053,27 +4526,29 @@ namespace System.Windows.Forms {
                }
 
                internal override void UpdateWindow(IntPtr handle) {
-                       XEvent  xevent;
                        Hwnd    hwnd;
 
                        hwnd = Hwnd.ObjectFromHandle(handle);
 
-                       if (!hwnd.visible || hwnd.expose_pending) {
+                       if (!hwnd.visible || !hwnd.expose_pending) {
                                return;
                        }
 
-#if not
                        SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
-#else
-                       xevent = new XEvent();
-                       xevent.type = XEventName.Expose;
-                       xevent.ExposeEvent.display = DisplayHandle;
-                       xevent.ExposeEvent.window = hwnd.client_window;
+                       hwnd.Queue.Paint.Remove(hwnd);
+               }
 
-                       MessageQueue.Enqueue(xevent);
-                       hwnd.expose_pending = true;
-#endif
+               private bool WindowIsMapped(IntPtr handle) {
+                       XWindowAttributes attributes;
+
+                       attributes = new XWindowAttributes();
+                       XGetWindowAttributes(DisplayHandle, handle, ref attributes);
+                       if (attributes.map_state == MapState.IsUnmapped) {
+                               return false;
+                       }
+                       return true;
                }
+
                #endregion      // Public Static Methods
 
                #region Events
@@ -4228,12 +4703,18 @@ namespace System.Windows.Forms {
                [DllImport ("libX11", EntryPoint="XChangeProperty")]
                internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
 
+               [DllImport ("libX11", EntryPoint="XChangeProperty")]
+               internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
+
                [DllImport ("libX11", EntryPoint="XChangeProperty")]
                internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
 
                [DllImport ("libX11", EntryPoint="XChangeProperty")]
                internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
 
+               [DllImport ("libX11", EntryPoint="XChangeProperty")]
+               internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
+
                [DllImport ("libX11", EntryPoint="XChangeProperty")]
                internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
 
@@ -4350,16 +4831,19 @@ namespace System.Windows.Forms {
                internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
 
                [DllImport ("libX11", EntryPoint="XSetForeground")]
-               internal extern static int XSetForeground(IntPtr display, IntPtr gc, IntPtr foreground);
+               internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
 
                [DllImport ("libX11", EntryPoint="XSetBackground")]
-               internal extern static int XSetBackground(IntPtr display, IntPtr gc, IntPtr background);
+               internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
 
                [DllImport ("libX11", EntryPoint="XBell")]
                internal extern static int XBell(IntPtr display, int percent);
 
                [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
                internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
+
+               [DllImport ("libX11", EntryPoint="XFilterEvent")]
+               internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
                #endregion
        }
 }