2006-05-24 Peter Dennis Bartok <pbartok@novell.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / XplatUIX11.cs
index 0d9b7b58068ad990568266f1020131ebeac2772a..9ea34c5774fe999570e0037b2345c40b29a91c31 100644 (file)
@@ -41,6 +41,9 @@
 
 // Extra detailed debug
 #undef DriverDebugExtra
+#undef DriverDebugParent
+#undef DriverDebugCreate
+#undef DriverDebugDestroy
 
 using System;
 using System.ComponentModel;
@@ -51,7 +54,6 @@ using System.Drawing.Drawing2D;
 using System.Drawing.Imaging;
 using System.IO;
 using System.Net;
-using N = System.Net;
 using System.Net.Sockets;
 using System.Reflection;
 using System.Runtime.InteropServices;
@@ -90,11 +92,11 @@ namespace System.Windows.Forms {
                private static ClipboardStruct  Clipboard;              // Our clipboard
 
                // Communication
-               private static int              PostAtom;               // PostMessage atom
-               private static int              AsyncAtom;              // Support for async messages
+               private static IntPtr           PostAtom;               // PostMessage atom
+               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                                                  //
@@ -125,7 +127,7 @@ namespace System.Windows.Forms {
                private static CaretStruct      Caret;                  //
 
                // Support for Window Styles
-               private static int[]            NetAtoms;               // All atoms we know
+               private static IntPtr[]         NetAtoms;               // All atoms we know
 
                // mouse hover message generation
                private static HoverStruct      HoverState;             //
@@ -169,7 +171,7 @@ namespace System.Windows.Forms {
 
                        // Now regular initialization
                        XlibLock = new object ();
-                       MessageQueue = new XEventQueue ();
+                       MessageQueues = new Hashtable(7);
                        TimerList = new ArrayList ();
                        XInitThreads();
 
@@ -283,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;
                        }
                }
@@ -325,20 +345,27 @@ namespace System.Windows.Forms {
                                }
 
                                // Generic X11 setup
-                               ScreenNo = 0;
+                               ScreenNo = XDefaultScreen(DisplayHandle);
                                RootWindow = XRootWindow(DisplayHandle, ScreenNo);
                                DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
 
                                // Create the foster parent
-                               FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 4, 0, 0);
+                               FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 4, UIntPtr.Zero, UIntPtr.Zero);
                                if (FosterParent==IntPtr.Zero) {
                                        Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
                                }
 
                                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);
@@ -363,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;
@@ -374,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;
 
@@ -392,7 +420,7 @@ namespace System.Windows.Forms {
                                SetupAtoms();
 
                                // Grab atom changes off the root window to catch certain WM events
-                               XSelectInput(DisplayHandle, RootWindow, EventMask.PropertyChangeMask);
+                               XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int)EventMask.PropertyChangeMask));
 
                                // Handle any upcoming errors
                                ErrorHandler = new XErrorHandler(HandleError);
@@ -443,7 +471,7 @@ namespace System.Windows.Forms {
 
                #region Private Methods
                private static void SetupAtoms() {
-                       NetAtoms = new int[(int)NA.LAST_NET_ATOM];
+                       NetAtoms = new IntPtr[(int)NA.LAST_NET_ATOM];
 
                        NetAtoms[(int)NA.WM_PROTOCOLS] = XInternAtom(DisplayHandle, "WM_PROTOCOLS", false);
                        NetAtoms[(int)NA.WM_DELETE_WINDOW] = XInternAtom(DisplayHandle, "WM_DELETE_WINDOW", false);
@@ -495,6 +523,7 @@ namespace System.Windows.Forms {
 
                        NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ] = XInternAtom(DisplayHandle, "_NET_WM_STATE_MAXIMIZED_HORZ", false);
                        NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT] = XInternAtom(DisplayHandle, "_NET_WM_STATE_MAXIMIZED_VERT", false);
+                       NetAtoms[(int)NA._NET_WM_STATE_HIDDEN] = XInternAtom(DisplayHandle, "_NET_WM_STATE_HIDDEN", false);
 
                        NetAtoms[(int)NA._XEMBED] = XInternAtom(DisplayHandle, "_XEMBED", false);
                        NetAtoms[(int)NA._XEMBED_INFO] = XInternAtom(DisplayHandle, "_XEMBED_INFO", false);
@@ -505,10 +534,20 @@ namespace System.Windows.Forms {
                        NetAtoms[(int)NA._NET_WM_STATE_ABOVE] = XInternAtom(DisplayHandle, "_NET_WM_STATE_ABOVE", false);
                        NetAtoms[(int)NA._NET_WM_STATE_MODAL] = XInternAtom(DisplayHandle, "_NET_WM_STATE_MODAL", false);
                        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] = (int)Atom.XA_PIXMAP;
+                       NetAtoms[(int)NA.DIB] = (IntPtr)Atom.XA_PIXMAP;
                        NetAtoms[(int)NA.OEMTEXT] = XInternAtom(DisplayHandle, "COMPOUND_TEXT", false);
                        NetAtoms[(int)NA.UNICODETEXT] = XInternAtom(DisplayHandle, "UTF8_STRING", false);
                        NetAtoms[(int)NA.TARGETS] = XInternAtom(DisplayHandle, "TARGETS", false);
@@ -538,7 +577,7 @@ namespace System.Windows.Forms {
                        xev.ClientMessageEvent.ptr1 = l0;
                        xev.ClientMessageEvent.ptr2 = l1;
                        xev.ClientMessageEvent.ptr3 = l2;
-                       XSendEvent(DisplayHandle, RootWindow, false, EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask, ref xev);
+                       XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
                }
 
                private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
@@ -553,81 +592,100 @@ namespace System.Windows.Forms {
                        xev.ClientMessageEvent.ptr1 = l0;
                        xev.ClientMessageEvent.ptr2 = l1;
                        xev.ClientMessageEvent.ptr3 = l2;
-                       XSendEvent(DisplayHandle, window, false, EventMask.NoEventMask, ref xev);
+                       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_OVERLAPPEDWINDOW) == 0) {
-                               if ((Style & (int) WindowStyles.WS_BORDER) != 0) {
-                                       border_style = FormBorderStyle.FixedSingle;
-                               } else if ((ExStyle & (int) WindowStyles.WS_EX_CLIENTEDGE) != 0) {
+                       if ((Style & (int) WindowStyles.WS_CHILD) != 0) {
+                               if ((ExStyle & (int) WindowExStyles.WS_EX_CLIENTEDGE) != 0) {
                                        border_style = FormBorderStyle.Fixed3D;
-                               } else {
+                               } 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;
-                                       if ((ExStyle & (int)WindowStyles.WS_EX_WINDOWEDGE) != 0) {
-                                               if ((ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
-                                                       if ((Style & (int)WindowStyles.WS_THICKFRAME) != 0) {
-                                                               border_style = FormBorderStyle.SizableToolWindow;
-                                                       } else {
-                                                               border_style = FormBorderStyle.FixedToolWindow;
-                                                       }
-                                               } else if ((ExStyle & (int)WindowStyles.WS_EX_DLGMODALFRAME) != 0) {
+                               border_style = FormBorderStyle.None;
+
+                               if ((Style & (int)WindowStyles.WS_THICKFRAME) != 0) {
+                                       if ((ExStyle & (int)WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
+                                               border_style = FormBorderStyle.SizableToolWindow;
+                                       } else {
+                                               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)WindowExStyles.WS_EX_DLGMODALFRAME) != 0) {
                                                        border_style = FormBorderStyle.FixedDialog;
-                                               } else if ((ExStyle & (int)WindowStyles.WS_THICKFRAME) != 0) {
-                                                       border_style = FormBorderStyle.Sizable;
-                                               } else {
+                                               } else if ((ExStyle & (int)WindowExStyles.WS_EX_TOOLWINDOW) != 0) {
+                                                       border_style = FormBorderStyle.FixedToolWindow;
+                                               } else if ((Style & (int)WindowStyles.WS_BORDER) != 0) {
                                                        border_style = FormBorderStyle.FixedSingle;
                                                }
                                        } else {
-                                               border_style = FormBorderStyle.Fixed3D;
+                                               if ((Style & (int)WindowStyles.WS_BORDER) != 0) {
+                                                       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;
                                }
                        }
                }
 
                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) {
                        MotifWmHints            mwmHints;
                        MotifFunctions          functions;
                        MotifDecorations        decorations;
-                       uint[]                  atoms;
                        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;
@@ -646,7 +704,6 @@ namespace System.Windows.Forms {
                                functions |= MotifFunctions.Move | MotifFunctions.Resize;
                                decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
                        }
-
                        if ((cp.Style & ((int)WindowStyles.WS_MINIMIZEBOX)) != 0) {
                                functions |= MotifFunctions.Minimize;
                                decorations |= MotifDecorations.Minimize;
@@ -661,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;
                        }
 
@@ -673,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;
 
@@ -686,49 +750,74 @@ 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);
 
-                               atoms = new uint[8];
+                               int[] atoms = new int[8];
                                atom_count = 0;
 
-                               if ((cp.ExStyle & ((int)WindowStyles.WS_EX_TOOLWINDOW)) != 0) {
-                                       atoms[atom_count++] = (uint)NetAtoms[(int)NA._NET_WM_STATE_NO_TASKBAR];
+                               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);
 
-                               XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._NET_WM_STATE], 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;
-                               atoms[atom_count++] = (uint)NetAtoms[(int)NA.WM_DELETE_WINDOW];
-                               if ((cp.ExStyle & (int)WindowStyles.WS_EX_CONTEXTHELP) != 0) {
-                                       atoms[atom_count++] = (uint)NetAtoms[(int)NA._NET_WM_CONTEXT_HELP];
+                               IntPtr[] atom_ptrs = new IntPtr[2];
+
+                               atom_ptrs[atom_count++] = NetAtoms[(int)NA.WM_DELETE_WINDOW];
+                               if ((cp.ExStyle & (int)WindowExStyles.WS_EX_CONTEXTHELP) != 0) {
+                                       atom_ptrs[atom_count++] = NetAtoms[(int)NA._NET_WM_CONTEXT_HELP];
                                }
 
-                               XSetWMProtocols(DisplayHandle, hwnd.whole_window, atoms, atom_count);
+                               XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
                        }
                }
 
                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], Atom.XA_CARDINAL, 32, PropertyMode.Replace, data, size);
+
+                       XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._NET_WM_ICON], (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, data, size);
                }
 
                private IntPtr ImageToPixmap(Image image) {
@@ -739,23 +828,35 @@ namespace System.Windows.Forms {
                        wake.Send (new byte [] { 0xFF });
                }
 
-               private void TranslatePropertyToClipboard(int property) {
-                       Atom                    actual_atom;
+               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;
-                       int                     nitems;
-                       int                     bytes_after;
+                       IntPtr                  nitems;
+                       IntPtr                  bytes_after;
                        IntPtr                  prop = IntPtr.Zero;
 
                        Clipboard.Item = null;
 
-                       XGetWindowProperty(DisplayHandle, FosterParent, property, 0, 0x7fffffff, true, Atom.AnyPropertyType, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
+                       XGetWindowProperty(DisplayHandle, FosterParent, property, IntPtr.Zero, new IntPtr (0x7fffffff), true, (IntPtr)Atom.AnyPropertyType, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
 
-                       if (nitems > 0) {
-                               if (property == (int)Atom.XA_STRING) {
+                       if ((long)nitems > 0) {
+                               if (property == (IntPtr)Atom.XA_STRING) {
                                        Clipboard.Item = Marshal.PtrToStringAnsi(prop);
-                               } else if (property == (int)Atom.XA_BITMAP) {
+                               } else if (property == (IntPtr)Atom.XA_BITMAP) {
                                        // FIXME - convert bitmap to image
-                               } else if (property == (int)Atom.XA_PIXMAP) {
+                               } else if (property == (IntPtr)Atom.XA_PIXMAP) {
                                        // FIXME - convert pixmap to image
                                } else if (property == NetAtoms[(int)NA.OEMTEXT]) {
                                        Clipboard.Item = Marshal.PtrToStringAnsi(prop);
@@ -767,27 +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 || !hwnd.visible) {  // Can'd check visible; we might loose expose for whole_windows
-                       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;
                                }
                        }
@@ -803,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) {
@@ -837,6 +935,74 @@ namespace System.Windows.Forms {
                        y = dest_y_return;
                }
 
+               private void AbsoluteGeometry(IntPtr window, out int ret_x, out int ret_y, out int width, out int height) {
+                       IntPtr  root;
+                       IntPtr  win;
+                       IntPtr  parent;
+                       IntPtr  children;
+                       int     x;
+                       int     y;
+                       int     w;
+                       int     h;
+                       int     absX;
+                       int     absY;
+                       int     b;
+                       int     d;
+                       int     nchildren;
+
+                       absX = 0;
+                       absY = 0;
+                       win = window;
+                       width = 0;
+                       height = 0;
+                       do {
+                               XGetGeometry(DisplayHandle, win, out root, out x, out y, out w, out h, out b, out d);
+                               if (win == window) {
+                                       width = w;
+                                       height = h;
+                               }
+                               absX += x;
+                               absY += y;
+                               if (XQueryTree(DisplayHandle, win, out root, out parent,  out children, out nchildren) == 0) {
+                                       break;
+                               }
+
+                               if (children != IntPtr.Zero) {
+                                       XFree(children);
+                               }
+                               win = parent;
+                       } while (win != root);
+
+                       ret_x = absX;
+                       ret_y = absY;
+
+//Console.WriteLine("Absolute pos for window {0} = {1},{2} {3}x{4}", XplatUI.Window(window), ret_x, ret_y, width, height);
+               }
+
+               private void FrameExtents(IntPtr window, out int left, out int top) {
+                       IntPtr                  actual_atom;
+                       int                     actual_format;
+                       IntPtr                  nitems;
+                       IntPtr                  bytes_after;
+                       IntPtr                  prop = IntPtr.Zero;
+
+                       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.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;
+                       }
+
+                       if (prop != IntPtr.Zero) {
+                               XFree(prop);
+                       }
+                       return;
+               }
+
                private void AddConfigureNotify (XEvent xevent) {
                        Hwnd    hwnd;
 
@@ -847,22 +1013,43 @@ 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;
                                } else {
-                                       int     dummy_int;
-                                       IntPtr  dummy_ptr;
-
-                                       XGetGeometry(DisplayHandle, XGetParent(hwnd.whole_window), out dummy_ptr, out hwnd.x, out hwnd.y, out dummy_int, out dummy_int, out dummy_int, out dummy_int);
+                                       // This sucks ass, part 1
+                                       // Every WM does the ConfigureEvents of toplevel windows different, so there's
+                                       // no standard way of getting our adjustment. 
+                                       // The code below is needed for KDE and FVWM, the 'whacky_wm' part is for metacity
+                                       // Several other WMs do their decorations different yet again and we fail to deal 
+                                       // with that, since I couldn't find any frigging commonality between them.
+                                       // The only sane WM seems to be KDE
+
+                                       if (!xevent.ConfigureEvent.send_event) {
+                                               IntPtr  dummy_ptr;
+
+                                               XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, -xevent.ConfigureEvent.x, -xevent.ConfigureEvent.y, out hwnd.x, out hwnd.y, out dummy_ptr);
+                                       } else {
+                                               // This is a synthetic event, coordinates are in root space
+                                               hwnd.x = xevent.ConfigureEvent.x;
+                                               hwnd.y = xevent.ConfigureEvent.y;
+                                               if (hwnd.whacky_wm) {
+                                                       int frame_left;
+                                                       int frame_top;
+
+                                                       FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
+                                                       hwnd.x -= frame_left;
+                                                       hwnd.y -= frame_top;
+                                               }
+                                       }
                                }
-
                                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;
                                }
                        }
@@ -909,6 +1096,8 @@ namespace System.Windows.Forms {
                                timeout = Timer.Minimum;
                        }
 
+                       if (timeout > 1000)
+                               timeout = 1000;
                        return timeout;
                }
 
@@ -935,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;
 
@@ -958,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__
@@ -986,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: {
@@ -1011,35 +1239,35 @@ namespace System.Windows.Forms {
                                                sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
                                                sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
                                                sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
-                                               sel_event.SelectionEvent.property = 0;
+                                               sel_event.SelectionEvent.property = IntPtr.Zero;
 
                                                // Seems that some apps support asking for supported types
                                                if (xevent.SelectionEvent.target == NetAtoms[(int)NA.TARGETS]) {
-                                                       uint[]  atoms;
+                                                       int[]   atoms;
                                                        int     atom_count;
 
-                                                       atoms = new uint[5];
+                                                       atoms = new int[5];
                                                        atom_count = 0;
 
                                                        if (Clipboard.Item is String) {
-                                                               atoms[atom_count++] = (uint)Atom.XA_STRING;
-                                                               atoms[atom_count++] = (uint)NetAtoms[(int)NA.OEMTEXT];
-                                                               atoms[atom_count++] = (uint)NetAtoms[(int)NA.UNICODETEXT];
+                                                               atoms[atom_count++] = (int)Atom.XA_STRING;
+                                                               atoms[atom_count++] = (int)NetAtoms[(int)NA.OEMTEXT];
+                                                               atoms[atom_count++] = (int)NetAtoms[(int)NA.UNICODETEXT];
                                                        } else if (Clipboard.Item is Image) {
-                                                               atoms[atom_count++] = (uint)Atom.XA_PIXMAP;
-                                                               atoms[atom_count++] = (uint)Atom.XA_BITMAP;
+                                                               atoms[atom_count++] = (int)Atom.XA_PIXMAP;
+                                                               atoms[atom_count++] = (int)Atom.XA_BITMAP;
                                                        } else {
                                                                // FIXME - handle other types
                                                        }
 
-                                                       XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, xevent.SelectionRequestEvent.property, xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
+                                                       XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
                                                } else if (Clipboard.Item is string) {
                                                        IntPtr  buffer;
                                                        int     buflen;
 
                                                        buflen = 0;
 
-                                                       if (xevent.SelectionRequestEvent.target == (int)Atom.XA_STRING) {
+                                                       if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
                                                                Byte[] bytes;
 
                                                                bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
@@ -1065,27 +1293,27 @@ namespace System.Windows.Forms {
                                                        }
 
                                                        if (buffer != IntPtr.Zero) {
-                                                               XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, xevent.SelectionRequestEvent.property, xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
+                                                               XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
                                                                sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
                                                                Marshal.FreeHGlobal(buffer);
                                                        }
                                                } else if (Clipboard.Item is Image) {
-                                                       if (xevent.SelectionEvent.target == (int)Atom.XA_PIXMAP) {
+                                                       if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
                                                                // FIXME - convert image and store as property
-                                                       } else if (xevent.SelectionEvent.target == (int)Atom.XA_PIXMAP) {
+                                                       } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
                                                                // FIXME - convert image and store as property
                                                        }
                                                }
 
-                                               XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, EventMask.NoEventMask, ref sel_event);
+                                               XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
                                                break;
                                        }
 
                                        case XEventName.SelectionNotify: {
                                                if (Clipboard.Enumerating) {
                                                        Clipboard.Enumerating = false;
-                                                       if (xevent.SelectionEvent.property != 0) {
-                                                               XDeleteProperty(DisplayHandle, FosterParent, xevent.SelectionEvent.property);
+                                                       if (xevent.SelectionEvent.property != IntPtr.Zero) {
+                                                               XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
                                                                if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
                                                                        Clipboard.Formats.Add(xevent.SelectionEvent.property);
                                                                        #if DriverDebugExtra
@@ -1095,7 +1323,7 @@ namespace System.Windows.Forms {
                                                        }
                                                } else if (Clipboard.Retrieving) {
                                                        Clipboard.Retrieving = false;
-                                                       if (xevent.SelectionEvent.property != 0) {
+                                                       if (xevent.SelectionEvent.property != IntPtr.Zero) {
                                                                TranslatePropertyToClipboard(xevent.SelectionEvent.property);
                                                        } else {
                                                                Clipboard.Item = null;
@@ -1106,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:
@@ -1119,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:
@@ -1128,16 +1370,16 @@ namespace System.Windows.Forms {
 
                                        case XEventName.PropertyNotify:
                                                if (xevent.PropertyEvent.atom == NetAtoms[(int)NA._NET_ACTIVE_WINDOW]) {
-                                                       Atom    actual_atom;
+                                                       IntPtr  actual_atom;
                                                        int     actual_format;
-                                                       int     nitems;
-                                                       int     bytes_after;
+                                                       IntPtr  nitems;
+                                                       IntPtr  bytes_after;
                                                        IntPtr  prop = IntPtr.Zero;
                                                        IntPtr  prev_active;;
 
                                                        prev_active = ActiveWindow;
-                                                       XGetWindowProperty(DisplayHandle, RootWindow, NetAtoms[(int)NA._NET_ACTIVE_WINDOW], 0, 1, false, Atom.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
-                                                       if ((nitems > 0) && (prop != IntPtr.Zero)) {
+                                                       XGetWindowProperty(DisplayHandle, RootWindow, NetAtoms[(int)NA._NET_ACTIVE_WINDOW], IntPtr.Zero, new IntPtr (1), false, (IntPtr)Atom.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
+                                                       if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
                                                                ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
                                                                XFree(prop);
 
@@ -1229,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;
@@ -1237,37 +1479,82 @@ namespace System.Windows.Forms {
                        if (c != null) {
                                controls = c.child_controls.GetAllControls ();
 
-                               for (i = 0; i < controls.Length; i++) {
-                                       hwnd = Hwnd.ObjectFromHandle(controls[i].Handle);
+                               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
 
-                                       if (hwnd != null) {
-                                               hwnd.destroy_pending = true;
+                                       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);
+                                               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 ();
                                }
@@ -1288,7 +1575,7 @@ namespace System.Windows.Forms {
 
                internal override int Caption {
                        get {
-                               return 25; 
+                               return 19;
                        }
                }
 
@@ -1514,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?
@@ -1528,18 +1829,18 @@ namespace System.Windows.Forms {
 
                internal override  Rectangle WorkingArea {
                        get {
-                               Atom                    actual_atom;
+                               IntPtr                  actual_atom;
                                int                     actual_format;
-                               int                     nitems;
-                               int                     bytes_after;
+                               IntPtr                  nitems;
+                               IntPtr                  bytes_after;
                                IntPtr                  prop = IntPtr.Zero;
                                int                     width;
                                int                     height;
 
-                               XGetWindowProperty(DisplayHandle, RootWindow, NetAtoms[(int)NA._NET_DESKTOP_GEOMETRY], 0, 256, false, Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
-                               if ((nitems == 2) && (prop != IntPtr.Zero)) {
-                                       width = Marshal.ReadInt32(prop, 0);
-                                       height = Marshal.ReadInt32(prop, 4);
+                               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) && 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);
@@ -1586,7 +1887,7 @@ namespace System.Windows.Forms {
                        hwnd = Hwnd.ObjectFromHandle(handle);
 
                        if (hwnd != null) lock (XlibLock) {
-                               SendNetWMMessage(hwnd.whole_window, (IntPtr)NetAtoms[(int)NA._NET_ACTIVE_WINDOW], IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
+                               SendNetWMMessage(hwnd.whole_window, NetAtoms[(int)NA._NET_ACTIVE_WINDOW], IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
                                //XRaiseWindow(DisplayHandle, handle);
                        }
                        return;
@@ -1599,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;
                }
 
@@ -1665,11 +1959,11 @@ namespace System.Windows.Forms {
                        Clipboard.Formats = new ArrayList();
 
                        while (f != null) {
-                               XConvertSelection(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD], f.Id, f.Id, FosterParent, IntPtr.Zero);
+                               XConvertSelection(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD], (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
 
                                Clipboard.Enumerating = true;
                                while (Clipboard.Enumerating) {
-                                       UpdateMessageQueue();
+                                       UpdateMessageQueue(null);
                                }
                                f = f.Next;
                        }
@@ -1677,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;
@@ -1702,18 +1996,18 @@ namespace System.Windows.Forms {
                        //else if (format == "SymbolicLink" ) return 4;
                        //else if (format == "DataInterchangeFormat" ) return 5;
                        //else if (format == "Tiff" ) return 6;
-                       else if (format == "OEMText" ) return XInternAtom(DisplayHandle, "COMPOUND_TEXT", false);
+                       else if (format == "OEMText" ) return XInternAtom(DisplayHandle, "COMPOUND_TEXT", false).ToInt32();
                        else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
                        else if (format == "Palette" ) return (int)Atom.XA_COLORMAP;    // Useless
                        //else if (format == "PenData" ) return 10;
                        //else if (format == "RiffAudio" ) return 11;
                        //else if (format == "WaveAudio" ) return 12;
-                       else if (format == "UnicodeText" ) return XInternAtom(DisplayHandle, "UTF8_STRING", false);
+                       else if (format == "UnicodeText" ) return XInternAtom(DisplayHandle, "UTF8_STRING", false).ToInt32();
                        //else if (format == "EnhancedMetafile" ) return 14;
                        //else if (format == "FileDrop" ) return 15;
                        //else if (format == "Locale" ) return 16;
 
-                       return XInternAtom(DisplayHandle, format, false);
+                       return XInternAtom(DisplayHandle, format, false).ToInt32();
                }
 
                internal override IntPtr ClipboardOpen() {
@@ -1721,11 +2015,11 @@ namespace System.Windows.Forms {
                }
 
                internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
-                       XConvertSelection(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD], type, type, FosterParent, IntPtr.Zero);
+                       XConvertSelection(DisplayHandle, NetAtoms[(int)NA.CLIPBOARD], (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
 
                        Clipboard.Retrieving = true;
                        while (Clipboard.Retrieving) {
-                               UpdateMessageQueue();
+                               UpdateMessageQueue(null);
                        }
 
                        return Clipboard.Item;
@@ -1758,13 +2052,13 @@ 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();
                        gc_values.line_width = width;
 
-                       Caret.gc = XCreateGC(DisplayHandle, Caret.Window, GCFunction.GCLineWidth, ref gc_values);
+                       Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
                        if (Caret.gc == IntPtr.Zero) {
                                Caret.Hwnd = IntPtr.Zero;
                                return;
@@ -1820,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;
                        }
@@ -1848,7 +2142,7 @@ namespace System.Windows.Forms {
                        ClientWindow = IntPtr.Zero;
 
                        lock (XlibLock) {
-                               WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, ValueMask, ref Attributes);
+                               WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
                                if (WholeWindow != IntPtr.Zero) {
                                        ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
 
@@ -1856,7 +2150,7 @@ namespace System.Windows.Forms {
                                                ValueMask = SetWindowValuemask.ColorMap;
                                                Attributes.colormap = CustomColormap;
                                        }
-                                       ClientWindow = XCreateWindow(DisplayHandle, WholeWindow, ClientRect.X, ClientRect.Y, ClientRect.Width, ClientRect.Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, CustomVisual, ValueMask, ref Attributes);
+                                       ClientWindow = XCreateWindow(DisplayHandle, WholeWindow, ClientRect.X, ClientRect.Y, ClientRect.Width, ClientRect.Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, CustomVisual, new UIntPtr ((uint)ValueMask), ref Attributes);
                                }
                        }
 
@@ -1864,26 +2158,50 @@ 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, SelectInputMask);
-                               XSelectInput(DisplayHandle, hwnd.client_window, SelectInputMask);
+                               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)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);
+                       }
+
                        SetWMStyles(hwnd, cp);
 
+                       if ((cp.Style & (int)WindowStyles.WS_MINIMIZE) != 0) {
+                               SetWindowState(hwnd.Handle, FormWindowState.Minimized);
+                       } else if ((cp.Style & (int)WindowStyles.WS_MAXIMIZE) != 0) {
+                               SetWindowState(hwnd.Handle, FormWindowState.Maximized);
+                       }
+
                        // for now make all windows dnd enabled
                        Dnd.SetAllowDrop (hwnd, true);
 
@@ -2155,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();
                                }
@@ -2169,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);
@@ -2186,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
 
@@ -2201,11 +2624,12 @@ namespace System.Windows.Forms {
                                DestroyCaret(handle);
                        }
 
-                       // The window is a goner, don't send it stuff like WM_PAINT anymore
-                       hwnd.destroy_pending = true;
+                       if (ActiveWindow == handle) {
+                               SendMessage(handle, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
+                               ActiveWindow = IntPtr.Zero;
+                       }
 
-                       // Mark our children as gone as well
-                       DestroyChildWindow(Control.ControlNativeWindow.ControlFromHandle(handle));
+                       SendWMDestroyMessages(Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle));
 
                        lock (XlibLock) {
                                if (hwnd.client_window != IntPtr.Zero) {
@@ -2216,6 +2640,7 @@ namespace System.Windows.Forms {
                                        XDestroyWindow(DisplayHandle, hwnd.whole_window);
                                }
                        }
+                       hwnd.Dispose();
                }
 
                internal override IntPtr DispatchMessage(ref MSG msg) {
@@ -2243,7 +2668,7 @@ namespace System.Windows.Forms {
                        //XSetPlaneMask(DisplayHandle,  gc, mask);
 
 
-                       gc = XCreateGC(DisplayHandle, hwnd.client_window, GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground, ref gc_values);
+                       gc = XCreateGC(DisplayHandle, hwnd.client_window, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
                        uint foreground;
                        uint background;
 
@@ -2266,10 +2691,10 @@ namespace System.Windows.Forms {
 
                        uint mask = foreground ^ background; 
 
-                       XSetForeground(DisplayHandle, gc, 0xffffffff);
-                       XSetBackground(DisplayHandle, gc, background);
+                       XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
+                       XSetBackground(DisplayHandle, gc, (UIntPtr)background);
                        XSetFunction(DisplayHandle,   gc, GXFunction.GXxor);
-                       XSetPlaneMask(DisplayHandle,  gc, mask);
+                       XSetPlaneMask(DisplayHandle,  gc, (IntPtr)mask);
 
                        if ((rect.Width > 0) && (rect.Height > 0)) {
                                XDrawRectangle(DisplayHandle, hwnd.client_window, gc, rect.Left, rect.Top, rect.Width, rect.Height);
@@ -2284,17 +2709,18 @@ 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)) {
-                               if (msg.message == Msg.WM_PAINT) {
-                                       TranslateMessage (ref msg);
-                                       DispatchMessage (ref msg);
-                               }
+                       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);
                        }
                }
 
@@ -2307,16 +2733,21 @@ namespace System.Windows.Forms {
                        }
                }
 
+               internal override void EndLoop(Thread thread) {
+                       // This is where we one day will shut down the loop for the thread
+               }
+
+
                internal override IntPtr GetActive() {
-                       Atom    actual_atom;
+                       IntPtr  actual_atom;
                        int     actual_format;
-                       int     nitems;
-                       int     bytes_after;
+                       IntPtr  nitems;
+                       IntPtr  bytes_after;
                        IntPtr  prop = IntPtr.Zero;
                        IntPtr  active = IntPtr.Zero;
 
-                       XGetWindowProperty(DisplayHandle, RootWindow, NetAtoms[(int)NA._NET_ACTIVE_WINDOW], 0, 1, false, Atom.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
-                       if ((nitems > 0) && (prop != IntPtr.Zero)) {
+                       XGetWindowProperty(DisplayHandle, RootWindow, NetAtoms[(int)NA._NET_ACTIVE_WINDOW], IntPtr.Zero, new IntPtr (1), false, (IntPtr)Atom.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
+                       if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
                                active = (IntPtr)Marshal.ReadInt32(prop);
                                XFree(prop);
                        }
@@ -2334,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) {
@@ -2404,14 +2849,6 @@ namespace System.Windows.Forms {
                        return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);
                }
 
-               internal override Graphics GetMenuDC(IntPtr handle, IntPtr ncpaint_region) {
-                       Hwnd            hwnd;
-
-                       hwnd = Hwnd.ObjectFromHandle(handle);
-
-                       return Graphics.FromHwnd(hwnd.whole_window);
-               }
-
                internal override Point GetMenuOrigin(IntPtr handle) {
                        Hwnd    hwnd;
 
@@ -2423,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;
@@ -2451,19 +2891,14 @@ 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
-                       if (hwnd == null || hwnd.destroy_pending) {
-                               // We need to let the DestroyNotify go through so that the owning control can learn about it, too
-                               if (hwnd == null || xevent.type != XEventName.DestroyNotify) {
-                                       #if DriverDebug
-                                               Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
-                                       #endif
-                                       goto ProcessNextMessage;
-                               }
+                       if (hwnd == null) {
+                               #if DriverDebug
+                                       Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
+                               #endif
+                               goto ProcessNextMessage;
                        }
 
                        if (hwnd.client_window == xevent.AnyEvent.window) {
@@ -2594,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;
@@ -2685,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;
@@ -2725,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;
@@ -2734,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;
@@ -2758,89 +3216,97 @@ namespace System.Windows.Forms {
 
                                case XEventName.ReparentNotify: {
                                        if (hwnd.parent == null) {      // Toplevel
-                                               if (xevent.ReparentEvent.parent != IntPtr.Zero) {
+                                               if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
                                                        // We need to adjust x/y
+                                                       // This sucks ass, part 2
+                                                       // Every WM does the reparenting of toplevel windows different, so there's
+                                                       // no standard way of getting our adjustment considering frames/decorations
+                                                       // The code below is needed for metacity. KDE doesn't works just fine without this
                                                        int     dummy_int;
                                                        IntPtr  dummy_ptr;
+                                                       int     new_x;
+                                                       int     new_y;
+                                                       int     frame_left;
+                                                       int     frame_top;
 
                                                        hwnd.Reparented = true;
 
-                                                       XGetGeometry(DisplayHandle, XGetParent(hwnd.whole_window), out dummy_ptr, out hwnd.x, out hwnd.y, out dummy_int, out dummy_int, out dummy_int, out dummy_int);
-                                                       msg.message = Msg.WM_WINDOWPOSCHANGED;
+                                                       XGetGeometry(DisplayHandle, XGetParent(hwnd.whole_window), out dummy_ptr, out new_x, out new_y, out dummy_int, out dummy_int, out dummy_int, out dummy_int);
+                                                       FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
+                                                       if ((frame_left != 0) && (frame_top != 0) && (new_x != frame_left) && (new_y != frame_top)) {
+                                                               hwnd.x = new_x;
+                                                               hwnd.y = new_y;
+                                                               hwnd.whacky_wm = true;
+                                                       }
+
+                                                       if (hwnd.opacity != 0xffffffff) {
+                                                               IntPtr 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;
@@ -2855,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;
                                                        }
@@ -2878,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;
                                        }
@@ -2904,6 +3369,19 @@ namespace System.Windows.Forms {
 
                                        // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
                                        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();
@@ -2923,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) {
@@ -2940,34 +3418,34 @@ 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
-                                       if  (xevent.ClientMessageEvent.message_type == (IntPtr)NetAtoms[(int)NA._XEMBED]) {
+                                       if  (xevent.ClientMessageEvent.message_type == NetAtoms[(int)NA._XEMBED]) {
                                                Console.WriteLine("GOT EMBED MESSAGE {0:X}", xevent.ClientMessageEvent.ptr2.ToInt32());
                                                break;
                                        }
                                        #endif
 
-                                       if  (xevent.ClientMessageEvent.message_type == (IntPtr)NetAtoms[(int)NA.WM_PROTOCOLS]) {
-                                               if (xevent.ClientMessageEvent.ptr1 == (IntPtr)NetAtoms[(int)NA.WM_DELETE_WINDOW]) {
+                                       if  (xevent.ClientMessageEvent.message_type == NetAtoms[(int)NA.WM_PROTOCOLS]) {
+                                               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
-                                               if (xevent.ClientMessageEvent.ptr1 == (IntPtr)NetAtoms[(int)NA.WM_TAKE_FOCUS]) {
+                                               if (xevent.ClientMessageEvent.ptr1 == NetAtoms[(int)NA.WM_TAKE_FOCUS]) {
                                                        goto ProcessNextMessage;
                                                }
                                        }
-                                       break;
+                                       goto ProcessNextMessage;
                                }
 
                                case XEventName.TimerNotify: {
                                        xevent.TimerNotifyEvent.handler (this, EventArgs.Empty);
-                                       break;
+                                       goto ProcessNextMessage;
                                }
                                        
                                default: {
@@ -2999,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);
 
@@ -3009,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;
                        }
@@ -3029,41 +3508,47 @@ namespace System.Windows.Forms {
                }
 
                internal override FormWindowState GetWindowState(IntPtr handle) {
-                       Atom                    actual_atom;
+                       IntPtr                  actual_atom;
                        int                     actual_format;
-                       int                     nitems;
-                       int                     bytes_after;
+                       IntPtr                  nitems;
+                       IntPtr                  bytes_after;
                        IntPtr                  prop = IntPtr.Zero;
                        IntPtr                  atom;
                        int                     maximized;
+                       bool                    minimized;
                        XWindowAttributes       attributes;
                        Hwnd                    hwnd;
 
                        hwnd = Hwnd.ObjectFromHandle(handle);
 
                        maximized = 0;
-                       XGetWindowProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._NET_WM_STATE], 0, 256, false, Atom.XA_ATOM, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
-                       if ((nitems > 0) && (prop != IntPtr.Zero)) {
-                               for (int i = 0; i < nitems; i++) {
+                       minimized = false;
+                       XGetWindowProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._NET_WM_STATE], IntPtr.Zero, new IntPtr (256), false, (IntPtr)Atom.XA_ATOM, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
+                       if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
+                               for (int i = 0; i < (long)nitems; i++) {
                                        atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
-                                       if ((atom == (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ]) || (atom == (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT])) {
+                                       if ((atom == NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ]) || (atom == NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT])) {
                                                maximized++;
+                                       } else if (atom == NetAtoms[(int)NA._NET_WM_STATE_HIDDEN]) {
+                                               minimized = true;
                                        }
                                }
                                XFree(prop);
                        }
 
-                       if (maximized == 2) {
+                       if (minimized) {
+                               return FormWindowState.Minimized;
+                       } else if (maximized == 2) {
                                return FormWindowState.Maximized;
                        }
 
-
                        attributes = new XWindowAttributes();
                        XGetWindowAttributes(DisplayHandle, handle, ref attributes);
                        if (attributes.map_state == MapState.IsUnmapped) {
-                               return FormWindowState.Minimized;
+                               throw new NotSupportedException("Cannot retrieve the state of an unmapped window");
                        }
 
+
                        return FormWindowState.Normal;
                }
 
@@ -3103,13 +3588,13 @@ namespace System.Windows.Forms {
                                XGrabPointer(DisplayHandle, hwnd.client_window, false, 
                                        EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
                                        EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
-                                       GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, 0, 0);
+                                       GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
                        }
                }
 
                internal override void UngrabWindow(IntPtr hwnd) {
                        lock (XlibLock) {
-                               XUngrabPointer(DisplayHandle, 0);
+                               XUngrabPointer(DisplayHandle, IntPtr.Zero);
                                XFlush(DisplayHandle);
                        }
                        Grab.Hwnd = IntPtr.Zero;
@@ -3124,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) {
@@ -3189,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;
@@ -3217,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;
                                }
                        }
@@ -3255,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
@@ -3279,7 +3795,7 @@ namespace System.Windows.Forms {
                        xevent.ClientMessageEvent.ptr3 = wparam;
                        xevent.ClientMessageEvent.ptr4 = lparam;
 
-                       MessageQueue.Enqueue (xevent);
+                       hwnd.Queue.Enqueue (xevent);
 
                        return true;
                }
@@ -3292,10 +3808,35 @@ namespace System.Windows.Forms {
                        Graphics.FromHdcInternal (IntPtr.Zero);
                }
 
-               internal override void ReleaseMenuDC(IntPtr handle, Graphics dc) {
-                       dc.Dispose();
+               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;
@@ -3332,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();
@@ -3360,38 +3905,70 @@ namespace System.Windows.Forms {
                                gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
                        }
 
-                       gc = XCreateGC(DisplayHandle, hwnd.client_window, 0, ref gc_values);
+                       gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
+
+                       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, area.X - XAmount, area.Y - YAmount, area.Width, area.Height, area.X, area.Y);
+                       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;
@@ -3400,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 ();
                }
@@ -3431,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) {
@@ -3445,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;
 
@@ -3502,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);
@@ -3526,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) {
@@ -3549,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);
                        }
@@ -3582,12 +4172,12 @@ 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 {
                                lock (XlibLock) {
-                                       XDeleteProperty(DisplayHandle, hwnd.whole_window, (int)Atom.XA_WM_TRANSIENT_FOR);
+                                       XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
                                }
                        }
                        return true;
@@ -3601,52 +4191,101 @@ namespace System.Windows.Forms {
 
                        lock (XlibLock) {
                                if (visible) {
-                                       XMapWindow(DisplayHandle, hwnd.whole_window);
-                                       XMapWindow(DisplayHandle, hwnd.client_window);
+                                       if (Control.FromHandle(handle) is Form) {
+                                               FormWindowState s;
+
+                                               s = ((Form)Control.FromHandle(handle)).WindowState;
+
+                                               MapWindow(hwnd, WindowType.Both);
+
+                                               switch(s) {
+                                                       case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
+                                                       case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
+                                               }
+
+                                       } else {
+                                               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;
                }
 
+               internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
+                       Hwnd            hwnd;
+                       XSizeHints      hints;
+
+                       hwnd = Hwnd.ObjectFromHandle(handle);
+                       if (hwnd == null) {
+                               return;
+                       }
+
+                       hints = new XSizeHints();
+                       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) && (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;
+                       }
+
+                       if (hints.flags != IntPtr.Zero) {
+                               XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
+                       }
+
+                       if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
+                               hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
+                               hints.x = maximized.X;
+                               hints.y = maximized.Y;
+                               hints.width = maximized.Width;
+                               hints.height = maximized.Height;
+
+                               // Metacity does not seem to follow this constraint for maximized (zoomed) windows
+                               XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
+                       }
+               }
+
+
                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);
                                }
                        }
 
@@ -3661,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;
@@ -3671,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 */, (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], (IntPtr)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);
@@ -3684,9 +4327,9 @@ namespace System.Windows.Forms {
                                case FormWindowState.Minimized: {
                                        lock (XlibLock) {
                                                if (current_state == FormWindowState.Maximized) {
-                                                       SendNetWMMessage(hwnd.whole_window, (IntPtr)NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)2 /* toggle */, (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], (IntPtr)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]);
                                                }
-                                               XIconifyWindow(DisplayHandle, hwnd.whole_window, 0);
+                                               XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
                                        }
                                        return;
                                }
@@ -3694,11 +4337,10 @@ 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, (IntPtr)NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)1 /* Add */, (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT]);
+                                               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]);
                                        }
                                        Activate(handle);
                                        return;
@@ -3715,6 +4357,21 @@ namespace System.Windows.Forms {
                }
 
                internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
+                       Hwnd    hwnd;
+                       IntPtr  opacity;
+
+                       hwnd = Hwnd.ObjectFromHandle(handle);
+
+                       if (hwnd == null) {
+                               return;
+                       }
+
+                       hwnd.opacity = (uint)(0xffffffff * transparency);
+                       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);
+                       }
                }
 
                internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
@@ -3757,11 +4414,19 @@ namespace System.Windows.Forms {
                        ;       // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
                }
 
+               internal override object StartLoop(Thread thread) {
+                       return (Object) ThreadQueue(thread);
+               }
+
+               internal override bool SupportsTransparency() {
+                       // We need to check if the x compositing manager is running
+                       return true;
+               }
+
                internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
                        GetSystrayManagerWindow();
 
                        if (SystrayMgrWindow != IntPtr.Zero) {
-                               uint[]          atoms;
                                XSizeHints      size_hints;
                                Hwnd            hwnd;
 
@@ -3770,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);
@@ -3790,9 +4454,9 @@ namespace System.Windows.Forms {
                                size_hints.base_height = icon.Height;
                                XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
 
-                               atoms = new uint[2];
-                               atoms[0] = 1;   // Version 1
-                               atoms[1] = 0;   // We're not mapped
+                               int[] atoms = new int[2];
+                               atoms [0] = 1;                  // Version 1
+                               atoms [1] = 0;                  // We're not mapped
 
                                // This line cost me 3 days...
                                XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._XEMBED_INFO], NetAtoms[(int)NA._XEMBED_INFO], 32, PropertyMode.Replace, atoms, 2);
@@ -3814,7 +4478,7 @@ namespace System.Windows.Forms {
                                // Make sure the window exists
                                XSync(DisplayHandle, hwnd.whole_window);
 
-                               SendNetClientMessage(SystrayMgrWindow, (IntPtr)NetAtoms[(int)NA._NET_SYSTEM_TRAY_OPCODE], IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
+                               SendNetClientMessage(SystrayMgrWindow, NetAtoms[(int)NA._NET_SYSTEM_TRAY_OPCODE], IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
                                return true;
                        }
                        tt = null;
@@ -3839,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...
@@ -3862,45 +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.destroy_pending) {
+                       if (!hwnd.visible || !hwnd.expose_pending) {
                                return;
                        }
 
                        SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
-#if not
-#if true
-                       xevent = new XEvent();
-                       xevent.type = XEventName.Expose;
-                       xevent.ExposeEvent.display = DisplayHandle;
-                       xevent.ExposeEvent.window = hwnd.client_window;
-
-                       MessageQueue.Enqueue(xevent);
-                       hwnd.expose_pending = true;
-#else
-                       // This would force an immediate paint (SendMessage, instead of PostMessage)
-                       if (!hwnd.visible) {
-                               return;
-                       }
+                       hwnd.Queue.Paint.Remove(hwnd);
+               }
 
-                       if (!hwnd.expose_pending) {
-                               xevent = new XEvent();
-                               xevent.type = XEventName.Expose;
-                               xevent.ExposeEvent.display = DisplayHandle;
-                               xevent.ExposeEvent.window = hwnd.client_window;
+               private bool WindowIsMapped(IntPtr handle) {
+                       XWindowAttributes attributes;
 
-                               MessageQueue.Enqueue(xevent);
-                               hwnd.expose_pending = true;
+                       attributes = new XWindowAttributes();
+                       XGetWindowAttributes(DisplayHandle, handle, ref attributes);
+                       if (attributes.map_state == MapState.IsUnmapped) {
+                               return false;
                        }
-                       NativeWindow.WndProc(hwnd.client_window, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
-#endif
-#endif
+                       return true;
                }
+
                #endregion      // Public Static Methods
 
                #region Events
@@ -3916,9 +4564,9 @@ namespace System.Windows.Forms {
                internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
 
                [DllImport ("libX11", EntryPoint="XCreateWindow")]
-               internal extern static IntPtr XCreateWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, int depth, int xclass, IntPtr visual, SetWindowValuemask valuemask, ref XSetWindowAttributes attributes);
+               internal extern static IntPtr XCreateWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, int depth, int xclass, IntPtr visual, UIntPtr valuemask, ref XSetWindowAttributes attributes);
                [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
-               internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, int border, int background);
+               internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
                [DllImport ("libX11", EntryPoint="XMapWindow")]
                internal extern static int XMapWindow(IntPtr display, IntPtr window);
                [DllImport ("libX11", EntryPoint="XUnmapWindow")]
@@ -3935,12 +4583,8 @@ namespace System.Windows.Forms {
                internal extern static int XConnectionNumber (IntPtr diplay);
                [DllImport ("libX11")]
                internal extern static int XPending (IntPtr diplay);
-               [DllImport ("libX11")]
-               internal extern static bool XCheckWindowEvent (IntPtr display, IntPtr window, EventMask mask, ref XEvent xevent);
-               [DllImport ("libX11")]
-               internal extern static bool XCheckMaskEvent (IntPtr display, EventMask mask, ref XEvent xevent);
                [DllImport ("libX11", EntryPoint="XSelectInput")]
-               internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, EventMask mask);
+               internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
 
                [DllImport ("libX11", EntryPoint="XDestroyWindow")]
                internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
@@ -3969,7 +4613,7 @@ namespace System.Windows.Forms {
                internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
 
                [DllImport ("libX11", EntryPoint="XSendEvent")]
-               internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, EventMask event_mask, ref XEvent send_event);
+               internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
 
                [DllImport ("libX11", EntryPoint="XQueryTree")]
                internal extern static int XQueryTree(IntPtr display, IntPtr window, out IntPtr root_return, out IntPtr parent_return, out IntPtr children_return, out int nchildren_return);
@@ -3987,16 +4631,16 @@ namespace System.Windows.Forms {
                internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
 
                [DllImport ("libX11", EntryPoint="XInternAtom")]
-               internal extern static int XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
+               internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
 
                [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
-               internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, uint[] protocols, int count);
+               internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
 
                [DllImport ("libX11", EntryPoint="XGrabPointer")]
-               internal extern static int XGrabPointer(IntPtr display, IntPtr window, bool owner_events, EventMask event_mask, GrabMode pointer_mode, GrabMode keyboard_mode, IntPtr confine_to, uint cursor, uint timestamp);
+               internal extern static int XGrabPointer(IntPtr display, IntPtr window, bool owner_events, EventMask event_mask, GrabMode pointer_mode, GrabMode keyboard_mode, IntPtr confine_to, IntPtr cursor, IntPtr timestamp);
 
                [DllImport ("libX11", EntryPoint="XUngrabPointer")]
-               internal extern static int XUngrabPointer(IntPtr display, uint timestamp);
+               internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
 
                [DllImport ("libX11", EntryPoint="XQueryPointer")]
                internal extern static bool XQueryPointer(IntPtr display, IntPtr window, out IntPtr root, out IntPtr child, out int root_x, out int root_y, out int win_x, out int win_y, out int keys_buttons);
@@ -4038,6 +4682,9 @@ namespace System.Windows.Forms {
                [DllImport ("libX11", EntryPoint="XDefaultDepth")]
                internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
 
+               [DllImport ("libX11", EntryPoint="XDefaultScreen")]
+               internal extern static int XDefaultScreen(IntPtr display);
+
                [DllImport ("libX11", EntryPoint="XDefaultColormap")]
                internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
 
@@ -4051,32 +4698,38 @@ namespace System.Windows.Forms {
                internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
 
                [DllImport ("libX11", EntryPoint="XChangeProperty")]
-               internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, int type, int format, PropertyMode  mode, ref MotifWmHints data, int nelements);
+               internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
+
+               [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, int property, Atom format, int type, PropertyMode  mode, uint[] atoms, int nelements);
+               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, int property, int format, int type, PropertyMode  mode, uint[] atoms, int nelements);
+               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, int property, int format, int type, PropertyMode  mode, IntPtr atoms, int nelements);
+               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, int property, Atom format, int type, PropertyMode  mode, IntPtr atoms, int nelements);
+               internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
 
                [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
-               internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, int type, int format, PropertyMode  mode, string text, int text_length);
+               internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
 
                [DllImport ("libX11", EntryPoint="XDeleteProperty")]
-               internal extern static int XDeleteProperty(IntPtr display, IntPtr window, int property);
+               internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
 
                [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
                internal extern static bool GetFontMetrics(IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
 
                // Drawing
                [DllImport ("libX11", EntryPoint="XCreateGC")]
-               internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, GCFunction valuemask, ref XGCValues values);
+               internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
 
                [DllImport ("libX11", EntryPoint="XFreeGC")]
                internal extern static int XFreeGC(IntPtr display, IntPtr gc);
@@ -4096,11 +4749,8 @@ namespace System.Windows.Forms {
                [DllImport ("libX11", EntryPoint="XCopyArea")]
                internal extern static int XCopyArea(IntPtr display, IntPtr src, IntPtr dest, IntPtr gc, int src_x, int src_y, int width, int height, int dest_x, int dest_y);
 
-               [DllImport ("libX11", EntryPoint="XGetAtomName")]
-               internal extern static string XGetAtomName(IntPtr display, int atom);
-
                [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
-               internal extern static int XGetWindowProperty(IntPtr display, IntPtr window, int atom, int long_offset, int long_length, bool delete, Atom req_type, out Atom actual_type, out int actual_format, out int nitems, out int bytes_after, ref IntPtr prop);
+               internal extern static int XGetWindowProperty(IntPtr display, IntPtr window, IntPtr atom, IntPtr long_offset, IntPtr long_length, bool delete, IntPtr req_type, out IntPtr actual_type, out int actual_format, out IntPtr nitems, out IntPtr bytes_after, ref IntPtr prop);
 
                [DllImport ("libX11", EntryPoint="XSetInputFocus")]
                internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
@@ -4147,6 +4797,9 @@ namespace System.Windows.Forms {
                [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
                internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
 
+               [DllImport ("libX11", EntryPoint="XSetZoomHints")]
+               internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
+
                [DllImport ("libX11", EntryPoint="XSetWMHints")]
                internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
 
@@ -4166,25 +4819,31 @@ namespace System.Windows.Forms {
                internal extern static int XInitThreads();
 
                [DllImport ("libX11", EntryPoint="XConvertSelection")]
-               internal extern static int XConvertSelection(IntPtr display, int selection, int target, int property, IntPtr requestor, IntPtr time);
+               internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
 
                [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
-               internal extern static IntPtr XGetSelectionOwner(IntPtr display, int selection);
+               internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
 
                [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
-               internal extern static int XSetSelectionOwner(IntPtr display, int selection, IntPtr owner, IntPtr time);
+               internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
 
                [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
-               internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, uint mask);
+               internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
 
                [DllImport ("libX11", EntryPoint="XSetForeground")]
-               internal extern static int XSetForeground(IntPtr display, IntPtr gc, uint 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, uint 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
        }
 }