2008-08-15 Carlos Alberto Cortez <calberto.cortez@gmail.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / XplatUIX11.cs
index dd7ed99df99a5bdb9c7f9445a28d14726a79c925..c83cf70c15d06533c009ea37b81112a336478021 100644 (file)
@@ -87,6 +87,9 @@ namespace System.Windows.Forms {
                private static IntPtr           FosterParent;           // Container to hold child windows until their parent exists
                private static XErrorHandler    ErrorHandler;           // Error handler delegate
                private static bool             ErrorExceptions;        // Throw exceptions on X errors
+               private int                     render_major_opcode;
+               private int                     render_first_event;
+               private int                     render_first_error;
 
                // Clipboard
                private static IntPtr           ClipMagic;
@@ -98,6 +101,7 @@ namespace System.Windows.Forms {
 
                // Message Loop
                private static Hashtable        MessageQueues;          // Holds our thread-specific XEventQueues
+               private static ArrayList        unattached_timer_list; // holds timers that are enabled but not attached to a window.
                #if __MonoCS__                                          //
                private static Pollfd[]         pollfds;                // For watching the X11 socket
                private static bool wake_waiting;
@@ -129,6 +133,9 @@ namespace System.Windows.Forms {
                // Caret
                private static CaretStruct      Caret;                  //
 
+               // Last window containing the pointer
+               private static IntPtr           LastPointerWindow;      // The last window containing the pointer
+
                // Our atoms
                private static IntPtr WM_PROTOCOLS;
                private static IntPtr WM_DELETE_WINDOW;
@@ -178,8 +185,8 @@ namespace System.Windows.Forms {
                private static IntPtr _XEMBED_INFO;
                private static IntPtr _MOTIF_WM_HINTS;
                private static IntPtr _NET_WM_STATE_SKIP_TASKBAR;
-               //private static IntPtr _NET_WM_STATE_ABOVE;
-               //private static IntPtr _NET_WM_STATE_MODAL;
+               private static IntPtr _NET_WM_STATE_ABOVE;
+               private static IntPtr _NET_WM_STATE_MODAL;
                private static IntPtr _NET_WM_STATE_HIDDEN;
                private static IntPtr _NET_WM_CONTEXT_HELP;
                private static IntPtr _NET_WM_WINDOW_OPACITY;
@@ -189,7 +196,7 @@ namespace System.Windows.Forms {
                //private static IntPtr _NET_WM_WINDOW_TYPE_MENU;
                private static IntPtr _NET_WM_WINDOW_TYPE_UTILITY;
                //private static IntPtr _NET_WM_WINDOW_TYPE_SPLASH;
-               //private static IntPtr _NET_WM_WINDOW_TYPE_DIALOG;
+               private static IntPtr _NET_WM_WINDOW_TYPE_DIALOG;
                private static IntPtr _NET_WM_WINDOW_TYPE_NORMAL;
                private static IntPtr CLIPBOARD;
                private static IntPtr PRIMARY;
@@ -223,6 +230,7 @@ namespace System.Windows.Forms {
                                                   EventMask.ExposureMask |
                                                   EventMask.FocusChangeMask |
                                                   EventMask.PointerMotionMask | 
+                                                  EventMask.PointerMotionHintMask | 
                                                   EventMask.SubstructureNotifyMask);
 
                static readonly object lockobj = new object ();
@@ -235,7 +243,9 @@ namespace System.Windows.Forms {
 
                        // Now regular initialization
                        XlibLock = new object ();
+                       X11Keyboard.XlibLock = XlibLock;
                        MessageQueues = Hashtable.Synchronized (new Hashtable(7));
+                       unattached_timer_list = ArrayList.Synchronized (new ArrayList (3));
                        XInitThreads();
 
                        ErrorExceptions = false;
@@ -387,7 +397,7 @@ namespace System.Windows.Forms {
                                }
 
 
-                               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);
+                               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, MinorCode, ResourceID.ToInt32(), Serial, hwnd_text, control_text);
                                return error;
                        }
                }
@@ -414,6 +424,13 @@ namespace System.Windows.Forms {
                                // been hacked to do this for us.
                                Graphics.FromHdcInternal (DisplayHandle);
 
+                               // query for the render extension so
+                               // we can ignore the spurious
+                               // BadPicture errors that are
+                               // generated by cairo/render.
+                               XQueryExtension (DisplayHandle, "RENDER",
+                                                ref render_major_opcode, ref render_first_event, ref render_first_error);
+
                                // Debugging support
                                if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
                                        XSynchronize(DisplayHandle, true);
@@ -429,7 +446,8 @@ namespace System.Windows.Forms {
                                DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
 
                                // Create the foster parent
-                               FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 4, UIntPtr.Zero, UIntPtr.Zero);
+                               // it is important that border_width is kept in synch with the other XCreateWindow calls
+                               FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 0, UIntPtr.Zero, UIntPtr.Zero);
                                if (FosterParent==IntPtr.Zero) {
                                        Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
                                }
@@ -497,7 +515,7 @@ namespace System.Windows.Forms {
                                SetupAtoms();
 
                                // Grab atom changes off the root window to catch certain WM events
-                               XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int)EventMask.PropertyChangeMask));
+                               XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int) (EventMask.PropertyChangeMask | Keyboard.KeyEventMask)));
 
                                // Handle any upcoming errors
                                ErrorHandler = new XErrorHandler(HandleError);
@@ -566,8 +584,8 @@ namespace System.Windows.Forms {
                                "_XEMBED_INFO",
                                "_MOTIF_WM_HINTS",
                                "_NET_WM_STATE_SKIP_TASKBAR",
-                               //"_NET_WM_STATE_ABOVE",
-                               //"_NET_WM_STATE_MODAL",
+                               "_NET_WM_STATE_ABOVE",
+                               "_NET_WM_STATE_MODAL",
                                "_NET_WM_CONTEXT_HELP",
                                "_NET_WM_WINDOW_OPACITY",
                                //"_NET_WM_WINDOW_TYPE_DESKTOP",
@@ -575,7 +593,7 @@ namespace System.Windows.Forms {
                                //"_NET_WM_WINDOW_TYPE_TOOLBAR",
                                //"_NET_WM_WINDOW_TYPE_MENU",
                                "_NET_WM_WINDOW_TYPE_UTILITY",
-                               //"_NET_WM_WINDOW_TYPE_DIALOG",
+                               "_NET_WM_WINDOW_TYPE_DIALOG",
                                //"_NET_WM_WINDOW_TYPE_SPLASH",
                                "_NET_WM_WINDOW_TYPE_NORMAL",
                                "CLIPBOARD",
@@ -640,8 +658,8 @@ namespace System.Windows.Forms {
                        _XEMBED_INFO = atoms [off++];
                        _MOTIF_WM_HINTS = atoms [off++];
                        _NET_WM_STATE_SKIP_TASKBAR = atoms [off++];
-                       //_NET_WM_STATE_ABOVE = atoms [off++];
-                       //_NET_WM_STATE_MODAL = atoms [off++];
+                       _NET_WM_STATE_ABOVE = atoms [off++];
+                       _NET_WM_STATE_MODAL = atoms [off++];
                        _NET_WM_CONTEXT_HELP = atoms [off++];
                        _NET_WM_WINDOW_OPACITY = atoms [off++];
                        //_NET_WM_WINDOW_TYPE_DESKTOP = atoms [off++];
@@ -649,7 +667,7 @@ namespace System.Windows.Forms {
                        //_NET_WM_WINDOW_TYPE_TOOLBAR = atoms [off++];
                        //_NET_WM_WINDOW_TYPE_MENU = atoms [off++];
                        _NET_WM_WINDOW_TYPE_UTILITY = atoms [off++];
-                       //_NET_WM_WINDOW_TYPE_DIALOG = atoms [off++];
+                       _NET_WM_WINDOW_TYPE_DIALOG = atoms [off++];
                        //_NET_WM_WINDOW_TYPE_SPLASH = atoms [off++];
                        _NET_WM_WINDOW_TYPE_NORMAL = atoms [off++];
                        CLIPBOARD = atoms [off++];
@@ -753,6 +771,112 @@ namespace System.Windows.Forms {
                        return (ex & (int)exws) == (int)exws;
                }
 
+               internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd)
+               {
+                       return TranslateClientRectangleToXClientRectangle (hwnd, Control.FromHandle (hwnd.Handle));
+               }
+               
+               internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd, Control ctrl)
+               {
+                       /* 
+                        * If this is a form with no window manager, X is handling all the border and caption painting
+                        * so remove that from the area (since the area we set of the window here is the part of the window 
+                        * we're painting in only)
+                        */
+                       Rectangle rect = hwnd.ClientRect;
+                       Form form = ctrl as Form;
+                       CreateParams cp = null;
+
+                       if (form != null)
+                               cp = form.GetCreateParams ();
+
+                       if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
+                               Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
+                               Rectangle xrect = rect;
+
+                               xrect.Y -= borders.top;
+                               xrect.X -= borders.left;
+                               xrect.Width += borders.left + borders.right;
+                               xrect.Height += borders.top + borders.bottom;
+
+                               rect = xrect;
+                       }
+                       
+                       if (rect.Width < 1 || rect.Height < 1) {
+                               rect.Width = 1;
+                               rect.Height = 1;
+                               rect.X = -5;
+                               rect.Y = -5;
+                       }
+                       
+                       return rect;
+               }
+
+               internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp)
+               {
+                       return TranslateWindowSizeToXWindowSize (cp, new Size (cp.Width, cp.Height));
+               }
+
+               internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp, Size size)
+               {
+                       /* 
+                        * If this is a form with no window manager, X is handling all the border and caption painting
+                        * so remove that from the area (since the area we set of the window here is the part of the window 
+                        * we're painting in only)
+                        */
+                       Form form = cp.control as Form;
+                       if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
+                               Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
+                               Size xrect = size;
+
+                               xrect.Width -= borders.left + borders.right;
+                               xrect.Height -= borders.top + borders.bottom;
+
+                               size = xrect;
+                       }
+                       if (size.Height == 0)
+                               size.Height = 1;
+                       if (size.Width == 0)
+                               size.Width = 1;
+                       return size;
+               }
+
+               internal static Size TranslateXWindowSizeToWindowSize (CreateParams cp, int xWidth, int xHeight)
+               {
+                       /* 
+                        * If this is a form with no window manager, X is handling all the border and caption painting
+                        * so remove that from the area (since the area we set of the window here is the part of the window 
+                        * we're painting in only)
+                        */
+                       Size rect = new Size (xWidth, xHeight);
+                       Form form = cp.control as Form;
+                       if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
+                               Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
+                               Size xrect = rect;
+
+                               xrect.Width += borders.left + borders.right;
+                               xrect.Height += borders.top + borders.bottom;
+
+                               rect = xrect;
+                       }
+                       return rect;
+               }
+               
+               internal static Point GetTopLevelWindowLocation (Hwnd hwnd)
+               {
+                       IntPtr dummy; 
+                       int x, y;
+                       Hwnd.Borders frame;
+
+                       XTranslateCoordinates (DisplayHandle, hwnd.whole_window, RootWindow, 0, 0, out x, out y, out dummy);
+                       frame = FrameExtents (hwnd.whole_window);
+
+                       x -= frame.left;
+                       y -= frame.top;
+                       
+                       return new Point (x, y);
+               }
+               
                private void DeriveStyles(int Style, int ExStyle, out FormBorderStyle border_style, out bool border_static, out TitleStyle title_style, out int caption_height, out int tool_caption_height) {
 
                        caption_height = 0;
@@ -844,7 +968,11 @@ namespace System.Windows.Forms {
                        int[]                   atoms;
                        int                     atom_count;
                        Rectangle               client_rect;
-
+                       Form                    form;
+                       IntPtr                  window_type;
+                       bool                    hide_from_taskbar;
+                       IntPtr                  transient_for_parent;
+                       
                        // Windows we manage ourselves don't need WM window styles.
                        if (cp.HasWindowManager && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
                                return;
@@ -854,17 +982,18 @@ namespace System.Windows.Forms {
                        mwmHints = new MotifWmHints();
                        functions = 0;
                        decorations = 0;
+                       window_type = _NET_WM_WINDOW_TYPE_NORMAL;
+                       transient_for_parent = IntPtr.Zero;
 
                        mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
                        mwmHints.functions = (IntPtr)0;
                        mwmHints.decorations = (IntPtr)0;
 
-                       if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)
-                           || !StyleSet (cp.Style, WindowStyles.WS_CAPTION | WindowStyles.WS_BORDER | WindowStyles.WS_DLGFRAME)) {
+                       form = cp.control as Form;
+
+                       if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
                                /* tool windows get no window manager
-                                  decorations, and neither do windows
-                                  which lack CAPTION/BORDER/DLGFRAME
-                                  styles.
+                                  decorations.
                                */
 
                                /* just because the window doesn't get any decorations doesn't
@@ -872,8 +1001,9 @@ namespace System.Windows.Forms {
                                   MotifFunctions.Maximize, changing the windowstate to Maximized
                                   is ignored by metacity. */
                                functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
-                       }
-                       else {
+                       } else if (form != null && form.FormBorderStyle == FormBorderStyle.None) {
+                               functions |= MotifFunctions.All;
+                       } else {
                                if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
                                        functions |= MotifFunctions.Move;
                                        decorations |= MotifDecorations.Title | MotifDecorations.Menu;
@@ -926,7 +1056,8 @@ namespace System.Windows.Forms {
 
                        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));
+                               Rectangle fixed_rectangle = new Rectangle (cp.X, cp.Y, cp.Width, cp.Height);
+                               SetWindowMinMax(hwnd.Handle, fixed_rectangle, fixed_rectangle.Size, fixed_rectangle.Size, cp);
                        } else {
                                hwnd.fixed_size = false;
                        }
@@ -934,49 +1065,63 @@ namespace System.Windows.Forms {
                        mwmHints.functions = (IntPtr)functions;
                        mwmHints.decorations = (IntPtr)decorations;
 
+#if debug
+                       Console.WriteLine ("SetWMStyles ({0}, {1}) functions = {2}, decorations = {3}", hwnd, cp, functions, decorations);
+#endif
+
+                       if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
+                               // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
+                               // and get those windows in front of their parents
+                               window_type = _NET_WM_WINDOW_TYPE_UTILITY;
+                       } else if (form != null && form.Modal) {
+                               window_type = _NET_WM_WINDOW_TYPE_DIALOG;
+                       } else {
+                               window_type = _NET_WM_WINDOW_TYPE_NORMAL;
+                       }
+                       
+                       if (!cp.IsSet (WindowExStyles.WS_EX_APPWINDOW)) {
+                               hide_from_taskbar = true;
+                       } else if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW) &&  form != null && form.Parent != null && !form.ShowInTaskbar) {
+                               hide_from_taskbar = true;
+                       } else {
+                               hide_from_taskbar = false;
+                       }
+
+                       if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
+                               if (form != null && !hwnd.reparented) {
+                                       if (form.Owner != null && form.Owner.Handle != IntPtr.Zero) {
+                                               Hwnd owner_hwnd = Hwnd.ObjectFromHandle (form.Owner.Handle);
+                                               if (owner_hwnd != null)
+                                                       transient_for_parent = owner_hwnd.whole_window;
+                                       }
+                               }
+                       } 
+                       if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
+                               transient_for_parent = hwnd.parent.whole_window;
+                       }
+                       
                        FormWindowState current_state = GetWindowState (hwnd.Handle);
                        if (current_state == (FormWindowState)(-1))
                                current_state = FormWindowState.Normal;
 
-                       client_rect = hwnd.ClientRect;
+                       client_rect = TranslateClientRectangleToXClientRectangle (hwnd);
+
                        lock (XlibLock) {
                                atom_count = 0;
 
-                               // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
-                               // and get those windows in front of their parents
-                               if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
-                                       atoms [0] = _NET_WM_WINDOW_TYPE_UTILITY.ToInt32 ();
-                                       XChangeProperty (DisplayHandle, hwnd.whole_window,  _NET_WM_WINDOW_TYPE,
-                                                        (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
-
-                                       Form f = Control.FromHandle(hwnd.Handle) as Form;
-                                       if (f != null && !hwnd.reparented) {
-                                               if (f.Owner != null && f.Owner.Handle != IntPtr.Zero) {
-                                                       Hwnd owner_hwnd = Hwnd.ObjectFromHandle(f.Owner.Handle);
-                                                       if (owner_hwnd != null)
-                                                               XSetTransientForHint(DisplayHandle, hwnd.whole_window,
-                                                                                    owner_hwnd.whole_window);
-                                               }
-                                       }
-                               }
-                               
+                               atoms [0] = window_type.ToInt32 ();
+                               XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
+
                                XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
-                               if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
-                                       atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
-                                       XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
 
-                                       XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
-                               } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) {
-                                       /* this line keeps the window from showing up in gnome's taskbar */
-                                       atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
-                               }
-                               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);
+                               if (transient_for_parent != IntPtr.Zero) {
+                                       XSetTransientForHint (DisplayHandle, hwnd.whole_window, transient_for_parent);
                                }
 
-                               if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
+                               MoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
+
+                               if (hide_from_taskbar) {
+                                       /* this line keeps the window from showing up in gnome's taskbar */
                                        atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
                                }
                                /* we need to add these atoms in the
@@ -990,6 +1135,11 @@ namespace System.Windows.Forms {
                                        atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
                                        atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
                                }
+                               
+                               if (form != null && form.Modal) {
+                                       atoms[atom_count++] = _NET_WM_STATE_MODAL.ToInt32 ();
+                               }
+                               
                                XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
 
                                atom_count = 0;
@@ -1121,28 +1271,27 @@ namespace System.Windows.Forms {
                        }
                }
 
-               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, _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;
-                       }
-
+               private static Hwnd.Borders FrameExtents (IntPtr window)
+               {
+                       IntPtr actual_atom;
+                       int actual_format;
+                       IntPtr nitems;
+                       IntPtr bytes_after;
+                       IntPtr prop = IntPtr.Zero;
+                       Hwnd.Borders rect = new Hwnd.Borders ();
+
+                       XGetWindowProperty (DisplayHandle, window, _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 (prop != IntPtr.Zero) {
-                               XFree(prop);
+                               if (nitems.ToInt32 () == 4) {
+                                       rect.left = Marshal.ReadInt32 (prop, 0);
+                                       rect.right = Marshal.ReadInt32 (prop, IntPtr.Size);
+                                       rect.top = Marshal.ReadInt32 (prop, 2 * IntPtr.Size);
+                                       rect.bottom = Marshal.ReadInt32 (prop, 3 * IntPtr.Size);
+                               }
+                               XFree (prop);
                        }
-                       return;
+                       
+                       return rect;
                }
 
                private void AddConfigureNotify (XEvent xevent) {
@@ -1151,47 +1300,33 @@ namespace System.Windows.Forms {
                        hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
 
                        // Don't waste time
-                       if (hwnd == null) {
+                       if (hwnd == null || hwnd.zombie) {
                                return;
                        }
-
-                       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 {
-                                       // 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;
-                                               }
-                                       }
+                       if ((xevent.ConfigureEvent.window == hwnd.whole_window)/* && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)*/) {
+                               if (hwnd.parent == null) {
+                                       // The location given by the event is not reliable between different wm's, 
+                                       // so use an alternative way of getting it.
+                                       Point location = GetTopLevelWindowLocation (hwnd);
+                                       hwnd.x = location.X;
+                                       hwnd.y = location.Y;
                                }
 
                                // XXX this sucks.  this isn't thread safe
-                               hwnd.width = xevent.ConfigureEvent.width;
-                               hwnd.height = xevent.ConfigureEvent.height;
+                               Control ctrl = Control.FromHandle (hwnd.Handle);
+                               Size TranslatedSize;
+                               if (ctrl != null) {
+                                       TranslatedSize = TranslateXWindowSizeToWindowSize (ctrl.GetCreateParams (), xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
+                               } else {
+                                       TranslatedSize = new Size (xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
+                               }
+                               hwnd.width = TranslatedSize.Width;
+                               hwnd.height = TranslatedSize.Height;
                                hwnd.ClientRect = Rectangle.Empty;
 
+#if debug
+                               Console.WriteLine ("AddConfigureNotify (hwnd.Handle = {1}, final hwnd.rect = {0}, reported rect={2})", new Rectangle (hwnd.x, hwnd.y, hwnd.width, hwnd.height), hwnd.Handle, new Rectangle (xevent.ConfigureEvent.x, xevent.ConfigureEvent.y, xevent.ConfigureEvent.width, xevent.ConfigureEvent.width));
+#endif                 
                                lock (hwnd.configure_lock) {
                                        if (!hwnd.configure_pending) {
                                                hwnd.Queue.EnqueueLocked (xevent);
@@ -1225,7 +1360,7 @@ namespace System.Windows.Forms {
                }
 
                private int NextTimeout (ArrayList timers, DateTime now) {
-                       int timeout = Int32.MaxValue
+                       int timeout = 0
 
                        foreach (Timer timer in timers) {
                                int next = (int) (timer.Expires - now).TotalMilliseconds;
@@ -1259,9 +1394,11 @@ namespace System.Windows.Forms {
 
                                timer = (Timer) timers [i];
 
-                               if (timer.Enabled && timer.Expires <= now) {
+                               if (timer.Enabled && timer.Expires <= now && !timer.Busy) {
+                                       timer.Busy = true;
                                        timer.Update (now);
                                        timer.FireTick ();
+                                       timer.Busy = false;
                                }
                        }
                }
@@ -1301,8 +1438,13 @@ namespace System.Windows.Forms {
 
                private void MapWindow(Hwnd hwnd, WindowType windows) {
                        if (!hwnd.mapped) {
-                               if (Control.FromHandle(hwnd.Handle) is Form)
-                                       SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
+                               Form f = Control.FromHandle(hwnd.Handle) as Form;
+                               if (f != null) {
+                                       if (f.WindowState == FormWindowState.Normal) {
+                                               f.waiting_showwindow = true;
+                                               SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
+                                       }
+                               }
 
                                // it's possible that our Hwnd is no
                                // longer valid after making that
@@ -1310,41 +1452,40 @@ namespace System.Windows.Forms {
                                if (hwnd.zombie)
                                        return;
 
-                               bool need_to_wait = false;
-
                                if ((windows & WindowType.Whole) != 0) {
                                        XMapWindow(DisplayHandle, hwnd.whole_window);
                                }
                                if ((windows & WindowType.Client) != 0) {
                                        XMapWindow(DisplayHandle, hwnd.client_window);
-
-                                       need_to_wait = true;
                                }
 
                                hwnd.mapped = true;
 
-                               if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
+                               if (f != null && f.waiting_showwindow)
                                        WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
                        }
                }
 
                private void UnmapWindow(Hwnd hwnd, WindowType windows) {
                        if (hwnd.mapped) {
-                               if (Control.FromHandle(hwnd.Handle) is Form)
-                                       SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, IntPtr.Zero, IntPtr.Zero);
+                               Form f = null;
+                               if (Control.FromHandle(hwnd.Handle) is Form) {
+                                       f = Control.FromHandle(hwnd.Handle) as Form;
+                                       if (f.WindowState == FormWindowState.Normal) {
+                                               f.waiting_showwindow = true;
+                                               SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, IntPtr.Zero, IntPtr.Zero);
+                                       }
+                               }
 
                                // it's possible that our Hwnd is no
                                // longer valid after making that
                                // SendMessage call, so check here.
+                               // FIXME: it is likely wrong, as it has already sent WM_SHOWWINDOW
                                if (hwnd.zombie)
                                        return;
 
-                               bool need_to_wait = false;
-
                                if ((windows & WindowType.Client) != 0) {
                                        XUnmapWindow(DisplayHandle, hwnd.client_window);
-
-                                       need_to_wait = true;
                                }
                                if ((windows & WindowType.Whole) != 0) {
                                        XUnmapWindow(DisplayHandle, hwnd.whole_window);
@@ -1352,7 +1493,7 @@ namespace System.Windows.Forms {
 
                                hwnd.mapped = false;
 
-                               if (need_to_wait && Control.FromHandle(hwnd.Handle) is Form)
+                               if (f != null && f.waiting_showwindow)
                                        WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
                        }
                }
@@ -1426,17 +1567,27 @@ namespace System.Windows.Forms {
 
                                        XNextEvent (DisplayHandle, ref xevent);
 
-                                       if (xevent.AnyEvent.type == XEventName.KeyPress) {
-                                               if (XFilterEvent(ref xevent, FosterParent)) {
+                                       if (xevent.AnyEvent.type == XEventName.KeyPress ||
+                                           xevent.AnyEvent.type == XEventName.KeyRelease) {
+                                               // PreFilter() handles "shift key state updates.
+                                               Keyboard.PreFilter (xevent);
+                                               if (XFilterEvent (ref xevent, Keyboard.ClientWindow)) {
+                                                       // probably here we could raise WM_IME_KEYDOWN and
+                                                       // WM_IME_KEYUP, but I'm not sure it is worthy.
                                                        continue;
                                                }
                                        }
+                                       else if (XFilterEvent (ref xevent, IntPtr.Zero))
+                                               continue;
                                }
 
                                hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
                                if (hwnd == null)
                                        continue;
 
+#if debug
+                               Console.WriteLine ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
+#endif
                                switch (xevent.type) {
                                case XEventName.Expose:
                                        AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
@@ -1583,6 +1734,10 @@ namespace System.Windows.Forms {
                                }
 
                                case XEventName.KeyPress:
+                                       hwnd.Queue.EnqueueLocked (xevent);
+                                       /* Process KeyPresses immediately. Otherwise multiple Compose messages as a result of a
+                                        * single physical keypress are not processed correctly */
+                                       return;
                                case XEventName.ButtonPress:
                                case XEventName.ButtonRelease:
                                case XEventName.EnterNotify:
@@ -1603,6 +1758,9 @@ namespace System.Windows.Forms {
                                        break;
 
                                case XEventName.PropertyNotify:
+#if debug
+                                       Console.WriteLine ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
+#endif
                                        if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
                                                IntPtr  actual_atom;
                                                int     actual_format;
@@ -1631,7 +1789,7 @@ namespace System.Windows.Forms {
                                                                // Modality handling, if we are modal and the new active window is one
                                                                // of ours but not the modal one, switch back to the modal window
 
-                                                               if (NativeWindow.FindWindow(ActiveWindow) != null) {
+                                                               if (NativeWindow.FromHandle(ActiveWindow) != null) {
                                                                        if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
                                                                                Activate((IntPtr)ModalWindows.Peek());
                                                                        }
@@ -1643,6 +1801,7 @@ namespace System.Windows.Forms {
                                        else if (xevent.PropertyEvent.atom == _NET_WM_STATE) {
                                                // invalidate our cache - we'll query again the next time someone does GetWindowState.
                                                hwnd.cached_window_state = (FormWindowState)(-1);
+                                               PostMessage (hwnd.Handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
                                        }
                                        break;
 
@@ -1696,11 +1855,29 @@ namespace System.Windows.Forms {
                        return Parent;
                }
 
-               private int HandleError(IntPtr display, ref XErrorEvent error_event) {
+               private int HandleError (IntPtr display, ref XErrorEvent error_event)
+               {
+                       // we need to workaround a problem with the
+                       // ordering of destruction of Drawables and
+                       // Pictures that exists between cairo and
+                       // RENDER on the server.
+                       if (error_event.request_code == (XRequest)render_major_opcode
+                           && error_event.minor_code == 7 /* X_RenderFreePicture from render.h */
+                           && error_event.error_code == render_first_error + 1 /* BadPicture from render.h */) {
+                               return 0;
+                       }
+
                        if (ErrorExceptions) {
-                               throw new XException(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code);
+                               XUngrabPointer (display, IntPtr.Zero);
+                               throw new XException (error_event.display, error_event.resourceid,
+                                                     error_event.serial, error_event.error_code,
+                                                     error_event.request_code, error_event.minor_code);
                        } else {
-                               Console.WriteLine("X11 Error encountered: {0}{1}\n", XException.GetMessage(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code), Environment.StackTrace);
+                               Console.WriteLine("X11 Error encountered: {0}{1}\n",
+                                                 XException.GetMessage (error_event.display, error_event.resourceid,
+                                                                        error_event.serial, error_event.error_code,
+                                                                        error_event.request_code, error_event.minor_code),
+                                                 Environment.StackTrace);
                        }
                        return 0;
                }
@@ -1754,7 +1931,7 @@ namespace System.Windows.Forms {
                        IntPtr                          ptr;
                        Rectangle                       rect;
 
-                       rect = hwnd.DefaultClientRect;
+                       rect = new Rectangle (0, 0, hwnd.Width, hwnd.Height);
 
                        ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
                        ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
@@ -1769,20 +1946,17 @@ namespace System.Windows.Forms {
                        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;
+               
+                       rect = TranslateClientRectangleToXClientRectangle (hwnd);
 
                        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);
-                               }
+                               MoveResizeWindow (DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
                        }
 
-                       AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
+                       AddExpose (hwnd, hwnd.WholeWindow == hwnd.ClientWindow, 0, 0, hwnd.Width, hwnd.Height);
                }
                #endregion      // Private Methods
 
@@ -1824,7 +1998,7 @@ namespace System.Windows.Forms {
 
                #region Public Properties
 
-               internal override int Caption {
+               internal override int CaptionHeight {
                        get {
                                return 19;
                        }
@@ -1853,7 +2027,7 @@ namespace System.Windows.Forms {
                        get {
                                return new Size(4, 4);
                        }
-               } 
+               }
 
                internal override  Size FrameBorderSize { 
                        get {
@@ -1950,13 +2124,13 @@ namespace System.Windows.Forms {
                        get {
                                return new Size (WorkingArea.Width, WorkingArea.Height);
                        }
-               } 
+               }
 
-               internal override  Size MinimizedWindowSize {
+               internal override bool MenuAccessKeysUnderlined {
                        get {
-                               return new Size(1, 1);
+                               return false;
                        }
-               } 
+               }
 
                internal override  Size MinimizedWindowSpacingSize {
                        get {
@@ -1966,16 +2140,22 @@ namespace System.Windows.Forms {
 
                internal override  Size MinimumWindowSize {
                        get {
-                               return new Size(1, 1);
+                               return new Size(110, 22);
                        }
                } 
 
-               internal override  Size MinWindowTrackSize {
-                       get {
-                               return new Size(1, 1);
-                       }
+               internal override Size MinimumFixedToolWindowSize {
+                       get { return new Size (27, 22); }
                }
 
+               internal override Size MinimumSizeableToolWindowSize {
+                       get { return new Size (37, 22); }
+               }
+
+               internal override Size MinimumNoBorderWindowSize {
+                       get { return new Size (2, 2); }
+               }
+               
                internal override Keys ModifierKeys {
                        get {
                                return Keyboard.ModifierKeys;
@@ -2165,6 +2345,12 @@ namespace System.Windows.Forms {
                #endregion      // Public properties
 
                #region Public Static Methods
+               internal override void RaiseIdle (EventArgs e)
+               {
+                       if (Idle != null)
+                               Idle (this, e);
+               }
+               
                internal override IntPtr InitializeDriver() {
                        lock (this) {
                                if (DisplayHandle==IntPtr.Zero) {
@@ -2197,6 +2383,16 @@ namespace System.Windows.Forms {
                                lock (XlibLock) {
                                        if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
                                                SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
+                                               XEventQueue q = null;
+                                               lock (unattached_timer_list) {
+                                                       foreach (Timer t in unattached_timer_list) {
+                                                               if (q == null)
+                                                                       q= (XEventQueue) MessageQueues [Thread.CurrentThread];
+                                                               t.thread = q.Thread;
+                                                               q.timer_list.Add (t);
+                                                       }
+                                                       unattached_timer_list.Clear ();
+                                               }
                                        }
 //                                     else {
 //                                             XRaiseWindow(DisplayHandle, handle);
@@ -2227,19 +2423,8 @@ namespace System.Windows.Forms {
                        }
                }
 
-               internal override bool CalculateWindowRect(ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
-                       FormBorderStyle border_style;
-                       TitleStyle      title_style;
-                       bool border_static;
-                       int caption_height;
-                       int tool_caption_height;
-
-                       DeriveStyles(Style, ExStyle, out border_style, out border_static, out title_style,
-                               out caption_height, out tool_caption_height);
-
-                       WindowRect = Hwnd.GetWindowRectangle(border_style, border_static, menu, title_style,
-                                       caption_height, tool_caption_height,
-                                       ClientRect);
+               internal override bool CalculateWindowRect(ref Rectangle ClientRect, CreateParams cp, Menu menu, out Rectangle WindowRect) {
+                       WindowRect = Hwnd.GetWindowRectangle (cp, menu, ClientRect);
                        return true;
                }
 
@@ -2389,6 +2574,7 @@ namespace System.Windows.Forms {
                {
                        XSetWindowAttributes    Attributes;
                        Hwnd                    hwnd;
+                       Hwnd                    parent_hwnd = null;
                        int                     X;
                        int                     Y;
                        int                     Width;
@@ -2396,7 +2582,6 @@ namespace System.Windows.Forms {
                        IntPtr                  ParentHandle;
                        IntPtr                  WholeWindow;
                        IntPtr                  ClientWindow;
-                       Rectangle               ClientRect;
                        SetWindowValuemask      ValueMask;
                        int[]                   atoms;
 
@@ -2412,21 +2597,24 @@ namespace System.Windows.Forms {
                        if (Height<1) Height=1;
 
                        if (cp.Parent != IntPtr.Zero) {
-                               ParentHandle = Hwnd.ObjectFromHandle(cp.Parent).client_window;
+                               parent_hwnd = Hwnd.ObjectFromHandle(cp.Parent);
+                               ParentHandle = parent_hwnd.client_window;
                        } else {
                                if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
                                        // We need to use our foster parent window until this poor child gets it's parent assigned
                                        ParentHandle=FosterParent;
-                               } else if (StyleSet (cp.Style, WindowStyles.WS_POPUP)) {
-                                       ParentHandle=RootWindow;
                                } else {
-                                       // Default position on screen, if window manager doesn't place us somewhere else
-                                       if (X<0) X = 50;
-                                       if (Y<0) Y = 50;
                                        ParentHandle=RootWindow;
                                }
                        }
 
+                       // Set the default location location for forms.
+                       Point next;
+                       if (cp.control is Form) {
+                               next = Hwnd.GetNextStackedFormLocation (cp, parent_hwnd);
+                               X = next.X;
+                               Y = next.Y;
+                       }
                        ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
 
                        Attributes.bit_gravity = Gravity.NorthWestGravity;
@@ -2450,17 +2638,20 @@ namespace System.Windows.Forms {
                        hwnd.width = Width;
                        hwnd.height = Height;
                        hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
-                       hwnd.initial_ex_style = (WindowExStyles) cp.ExStyle;
+                       hwnd.initial_style = cp.WindowStyle;
+                       hwnd.initial_ex_style = cp.WindowExStyle;
 
                        if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
                                hwnd.enabled = false;
                        }
 
-                       ClientRect = hwnd.ClientRect;
                        ClientWindow = IntPtr.Zero;
 
+                       Size XWindowSize = TranslateWindowSizeToXWindowSize (cp);
+                       Rectangle XClientRect = TranslateClientRectangleToXClientRectangle (hwnd, cp.control);
+                               
                        lock (XlibLock) {
-                               WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
+                               WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, XWindowSize.Width, XWindowSize.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);
 
@@ -2468,7 +2659,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, new UIntPtr ((uint)ValueMask), ref Attributes);
+                                       ClientWindow = XCreateWindow(DisplayHandle, WholeWindow, XClientRect.X, XClientRect.Y, XClientRect.Width, XClientRect.Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, CustomVisual, new UIntPtr ((uint)ValueMask), ref Attributes);
                                }
                        }
 
@@ -2483,7 +2674,7 @@ namespace System.Windows.Forms {
                        #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 (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
                                if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
                                        XSizeHints      hints;
@@ -2497,9 +2688,9 @@ namespace System.Windows.Forms {
                        }
 
                        lock (XlibLock) {
-                               XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask)));
+                               XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask | Keyboard.KeyEventMask)));
                                if (hwnd.whole_window != hwnd.client_window)
-                                       XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
+                                       XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | Keyboard.KeyEventMask)));
                        }
 
                        if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
@@ -2659,10 +2850,77 @@ namespace System.Windows.Forms {
                        return cursor;
                }
 
+               internal override Bitmap DefineStdCursorBitmap (StdCursor id) {
+                       CursorFontShape shape;
+                       string name;
+                       IntPtr theme;
+                       int size;
+                       Bitmap bmp = null;
+                       
+                       try {
+                               shape = StdCursorToFontShape (id);
+                               name = shape.ToString ().Replace ("XC_", string.Empty);
+                               size = XcursorGetDefaultSize (DisplayHandle);
+                               theme = XcursorGetTheme (DisplayHandle);
+                               IntPtr images_ptr = XcursorLibraryLoadImages (name, theme, size);
+#if debug
+                               Console.WriteLine ("DefineStdCursorBitmap, id={0}, #id={1}, name{2}, size={3}, theme: {4}, images_ptr={5}", id, (int) id, name, size, Marshal.PtrToStringAnsi (theme), images_ptr);
+#endif
+
+                               if (images_ptr == IntPtr.Zero) {
+                                       return null;
+                               }
+
+                               XcursorImages images = (XcursorImages) Marshal.PtrToStructure (images_ptr, typeof (XcursorImages));
+#if debug
+                               Console.WriteLine ("DefineStdCursorBitmap, cursor has {0} images", images.nimage);
+#endif
+
+                               if (images.nimage > 0) {                        
+                                       // We only care about the first image.
+                                       XcursorImage image = (XcursorImage)Marshal.PtrToStructure (Marshal.ReadIntPtr (images.images), typeof (XcursorImage));
+                                       
+#if debug
+                                       Console.WriteLine ("DefineStdCursorBitmap, loaded image <size={0}, height={1}, width={2}, xhot={3}, yhot={4}, pixels={5}", image.size, image.height, image.width, image.xhot, image.yhot, image.pixels);
+#endif
+                                       // A sanity check
+                                       if (image.width <= short.MaxValue && image.height <= short.MaxValue) {
+                                               int [] pixels = new int [image.width * image.height];
+                                               Marshal.Copy (image.pixels, pixels, 0, pixels.Length);
+                                               bmp = new Bitmap (image.width, image.height);
+                                               for (int w = 0; w < image.width; w++) {
+                                                       for (int h = 0; h < image.height; h++) {
+                                                               bmp.SetPixel (w, h, Color.FromArgb (pixels [h * image.width + w]));
+                                                       }
+                                               }
+                                       }
+                               }
+                               
+                               XcursorImagesDestroy (images_ptr);
+                               
+                       } catch (DllNotFoundException ex) {
+                               Console.WriteLine ("Could not load libXcursor: " + ex.Message + " (" + ex.GetType ().Name + ")");
+                               return null;
+                       }
+                       
+                       return bmp;
+               }
+
+               
                internal override IntPtr DefineStdCursor(StdCursor id) {
                        CursorFontShape shape;
                        IntPtr          cursor;
 
+                       shape = StdCursorToFontShape (id);
+
+                       lock (XlibLock) {
+                               cursor = XCreateFontCursor(DisplayHandle, shape);
+                       }
+                       return cursor;
+               }
+
+               internal static CursorFontShape StdCursorToFontShape (StdCursor id) {
+                       CursorFontShape shape;
                        // FIXME - define missing shapes
 
                        switch (id) {
@@ -2807,18 +3065,30 @@ namespace System.Windows.Forms {
                                }
 
                                default: {
-                                       return IntPtr.Zero;
+                                       shape = (CursorFontShape) 0;
+                                       break;
                                }
                        }
-
-                       lock (XlibLock) {
-                               cursor = XCreateFontCursor(DisplayHandle, shape);
-                       }
-                       return cursor;
+                       
+                       return shape;
                }
 
                internal override IntPtr DefWndProc(ref Message msg) {
                        switch ((Msg)msg.Msg) {
+                               
+                               case Msg.WM_IME_COMPOSITION:
+                                       string s = Keyboard.GetCompositionString ();
+                                       foreach (char c in s)
+                                               SendMessage (msg.HWnd, Msg.WM_IME_CHAR, (IntPtr) c, msg.LParam);
+                                       return IntPtr.Zero;
+
+                               case Msg.WM_IME_CHAR:
+                                       // On Windows API it sends two WM_CHAR messages for each byte, but
+                                       // I wonder if it is worthy to emulate it (also no idea how to 
+                                       // reconstruct those bytes into chars).
+                                       SendMessage (msg.HWnd, Msg.WM_CHAR, msg.WParam, msg.LParam);
+                                       return IntPtr.Zero;
+
                                case Msg.WM_PAINT: {
                                        Hwnd hwnd;
 
@@ -2841,6 +3111,33 @@ namespace System.Windows.Forms {
                                        return IntPtr.Zero;
                                }
 
+                               case Msg.WM_NCCALCSIZE: {
+                                       Hwnd hwnd;
+
+                                       if (msg.WParam == (IntPtr)1) {
+                                               hwnd = Hwnd.GetObjectFromWindow (msg.HWnd);
+                                               
+                                               XplatUIWin32.NCCALCSIZE_PARAMS ncp;
+                                               ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (msg.LParam, typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
+
+                                               // Add all the stuff X is supposed to draw.
+                                               Control ctrl = Control.FromHandle (hwnd.Handle);
+                                               
+                                               if (ctrl != null) {
+                                                       Hwnd.Borders rect = Hwnd.GetBorders (ctrl.GetCreateParams (), null);
+                                                       
+                                                       ncp.rgrc1.top += rect.top;
+                                                       ncp.rgrc1.bottom -= rect.bottom;
+                                                       ncp.rgrc1.left += rect.left;
+                                                       ncp.rgrc1.right -= rect.right;
+                                                       
+                                                       Marshal.StructureToPtr (ncp, msg.LParam, true);
+                                               }
+                                       }
+
+                                       return IntPtr.Zero;
+                               }
+
                                case Msg.WM_CONTEXTMENU: {
                                        Hwnd hwnd;
 
@@ -2984,12 +3281,14 @@ namespace System.Windows.Forms {
                                        #if DriverDebug || DriverDebugDestroy
                                        Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
                                        #endif
+                                       Keyboard.DestroyICForWindow (hwnd.whole_window);
                                        XDestroyWindow(DisplayHandle, hwnd.whole_window);
                                }
                                else if (hwnd.client_window != IntPtr.Zero) {
                                        #if DriverDebug || DriverDebugDestroy
                                        Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
                                        #endif
+                                       Keyboard.DestroyICForWindow (hwnd.client_window);
                                        XDestroyWindow(DisplayHandle, hwnd.client_window);
                                }
 
@@ -3075,6 +3374,9 @@ namespace System.Windows.Forms {
 
                internal override void DrawReversibleLine(Point start, Point end, Color backColor)
                {
+                       if (backColor.GetBrightness() < 0.5)
+                               backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
+
                        IntPtr gc = GetReversibleScreenGC (backColor);
 
                        XDrawLine (DisplayHandle, RootWindow, gc, start.X, start.Y, end.X, end.Y);
@@ -3084,6 +3386,9 @@ namespace System.Windows.Forms {
 
                internal override void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
                {
+                       if (backColor.GetBrightness() < 0.5)
+                               backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
+
                        IntPtr gc = GetReversibleScreenGC (backColor);
 
                        if (rectangle.Width < 0) {
@@ -3118,6 +3423,9 @@ namespace System.Windows.Forms {
 
                internal override void FillReversibleRectangle (Rectangle rectangle, Color backColor) 
                {
+                       if (backColor.GetBrightness() < 0.5)
+                               backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
+
                        IntPtr gc = GetReversibleScreenGC (backColor);
 
                        if (rectangle.Width < 0) {
@@ -3133,7 +3441,8 @@ namespace System.Windows.Forms {
                        XFreeGC(DisplayHandle, gc);
                }
 
-               internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
+               internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width)
+               {
                        IntPtr          gc;
                        Control control = Control.FromHandle(handle);
 
@@ -3261,6 +3570,11 @@ namespace System.Windows.Forms {
                        }
                        return IntPtr.Zero;
                }
+               
+               // This is a nop on win32 and x11
+               internal override IntPtr GetPreviousWindow(IntPtr handle) {
+                       return handle;
+               }
 
                internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
                        IntPtr  use_handle;
@@ -3297,7 +3611,10 @@ namespace System.Windows.Forms {
 
 
                internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
-                       return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);
+                       FontFamily ff = font.FontFamily;
+                       ascent = ff.GetCellAscent (font.Style);
+                       descent = ff.GetCellDescent (font.Style);
+                       return true;
                }
 
                internal override Point GetMenuOrigin(IntPtr handle) {
@@ -3352,7 +3669,7 @@ namespace System.Windows.Forms {
                        // hwnds, since much of the event handling code makes requests using the hwnd's
                        // client_window, and that'll result in BadWindow errors if there's some lag
                        // between the XDestroyWindow call and the DestroyNotify event.
-                       if (hwnd == null || hwnd.zombie) {
+                       if (hwnd == null || hwnd.zombie && xevent.AnyEvent.type != XEventName.ClientMessage) {
                                #if DriverDebug || DriverDebugDestroy
                                        Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
                                #endif
@@ -3369,14 +3686,39 @@ namespace System.Windows.Forms {
 
                        msg.hwnd = hwnd.Handle;
 
+                       // Windows sends WM_ENTERSIZEMOVE when a form resize/move operation starts and WM_EXITSIZEMOVE 
+                       // when it is done. The problem in X11 is that there is no concept of start-end of a moving/sizing.
+                       // Configure events ("this window has resized/moved") are sent for each step of the resize. We send a
+                       // WM_ENTERSIZEMOVE when we get the first Configure event. The problem is the WM_EXITSIZEMOVE.
+                       // 
+                       //  - There is no way for us to know which is the last Configure event. We can't traverse the events 
+                       //    queue, because the next configure event might not be pending yet.
+                       //  - We can't get ButtonPress/Release events for the window decorations, because they are not part 
+                       //    of the window(s) we manage.
+                       //  - We can't rely on the mouse state to change to "up" before the last Configure event. It doesn't.
+                       // 
+                       // We are almost 100% guaranteed to get another event (e.g Expose or other), but we can't know for sure 
+                       // which, so we have here to check if the mouse buttons state is "up" and send the WM_EXITSIZEMOVE
+                       //
+                       if (hwnd.resizing_or_moving) {
+                               int root_x, root_y, win_x, win_y, keys_buttons;
+                               IntPtr  root, child;
+                               XQueryPointer (DisplayHandle, hwnd.Handle, out root, out child, out root_x, out root_y, 
+                                              out win_x, out win_y, out keys_buttons);
+                               if ((keys_buttons & (int)MouseKeyMasks.Button1Mask) == 0 &&
+                                   (keys_buttons & (int)MouseKeyMasks.Button2Mask) == 0 &&
+                                   (keys_buttons & (int)MouseKeyMasks.Button3Mask) == 0) {
+                                       hwnd.resizing_or_moving = false;
+                                       SendMessage (hwnd.Handle, Msg.WM_EXITSIZEMOVE, IntPtr.Zero, IntPtr.Zero);
+                               }
+                       }
+
                        //
                        // If you add a new event to this switch make sure to add it in
                        // UpdateMessage also unless it is not coming through the X event system.
                        //
                        switch(xevent.type) {
                                case XEventName.KeyPress: {
-                                       if (Dnd.InDrag ())
-                                               Dnd.HandleKeyPress (ref xevent);
                                        Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
                                        break;
                                }
@@ -3392,12 +3734,12 @@ namespace System.Windows.Forms {
                                                        MouseState |= MouseButtons.Left;
                                                        if (client) {
                                                                msg.message = Msg.WM_LBUTTONDOWN;
+                                                               msg.wParam = GetMousewParam (0);
                                                        } else {
                                                                msg.message = Msg.WM_NCLBUTTONDOWN;
+                                                               msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
                                                                MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
                                                        }
-                                                       // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
-                                                       msg.wParam=GetMousewParam(0);
                                                        break;
                                                }
 
@@ -3405,11 +3747,12 @@ namespace System.Windows.Forms {
                                                        MouseState |= MouseButtons.Middle;
                                                        if (client) {
                                                                msg.message = Msg.WM_MBUTTONDOWN;
+                                                               msg.wParam = GetMousewParam (0);
                                                        } else {
                                                                msg.message = Msg.WM_NCMBUTTONDOWN;
+                                                               msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
                                                                MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
                                                        }
-                                                       msg.wParam=GetMousewParam(0);
                                                        break;
                                                }
 
@@ -3417,11 +3760,12 @@ namespace System.Windows.Forms {
                                                        MouseState |= MouseButtons.Right;
                                                        if (client) {
                                                                msg.message = Msg.WM_RBUTTONDOWN;
+                                                               msg.wParam = GetMousewParam (0);
                                                        } else {
                                                                msg.message = Msg.WM_NCRBUTTONDOWN;
+                                                               msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
                                                                MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
                                                        }
-                                                       msg.wParam=GetMousewParam(0);
                                                        break;
                                                }
 
@@ -3504,23 +3848,17 @@ namespace System.Windows.Forms {
                                }
 
                                case XEventName.ButtonRelease: {
-                                       if (Dnd.InDrag()) {
-                                               if (Dnd.HandleButtonRelease (ref xevent)) {
-                                                       break;
-                                               }
-                                               // Allow the LBUTTONUP message to get through
-                                       }
-
                                        switch(xevent.ButtonEvent.button) {
                                                case 1: {
                                                        if (client) {
                                                                msg.message = Msg.WM_LBUTTONUP;
                                                        } else {
                                                                msg.message = Msg.WM_NCLBUTTONUP;
+                                                               msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
                                                                MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
                                                        }
                                                        MouseState &= ~MouseButtons.Left;
-                                                       msg.wParam=GetMousewParam(0);
+                                                       msg.wParam = GetMousewParam (0);
                                                        break;
                                                }
 
@@ -3529,10 +3867,11 @@ namespace System.Windows.Forms {
                                                                msg.message = Msg.WM_MBUTTONUP;
                                                        } else {
                                                                msg.message = Msg.WM_NCMBUTTONUP;
+                                                               msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
                                                                MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
                                                        }
                                                        MouseState &= ~MouseButtons.Middle;
-                                                       msg.wParam=GetMousewParam(0);
+                                                       msg.wParam = GetMousewParam (0);
                                                        break;
                                                }
 
@@ -3541,10 +3880,11 @@ namespace System.Windows.Forms {
                                                                msg.message = Msg.WM_RBUTTONUP;
                                                        } else {
                                                                msg.message = Msg.WM_NCRBUTTONUP;
+                                                               msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
                                                                MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
                                                        }
                                                        MouseState &= ~MouseButtons.Right;
-                                                       msg.wParam=GetMousewParam(0);
+                                                       msg.wParam = GetMousewParam (0);
                                                        break;
                                                }
 
@@ -3594,12 +3934,24 @@ namespace System.Windows.Forms {
                                                        Console.WriteLine("GetMessage(): Window {0:X} MotionNotify x={1} y={2}", client ? hwnd.client_window.ToInt32() : hwnd.whole_window.ToInt32(), xevent.MotionEvent.x, xevent.MotionEvent.y);
                                                #endif
 
-                                               if (Dnd.HandleMotionNotify (ref xevent))
-                                                       goto ProcessNextMessage;
                                                if (Grab.Hwnd != IntPtr.Zero) {
                                                        msg.hwnd = Grab.Hwnd;
                                                } else {
-                                                       NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
+                                                       if (hwnd.Enabled) {
+                                                               NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
+                                                       }
+                                               }
+
+                                               if (xevent.MotionEvent.is_hint != 0)
+                                               {
+                                                       IntPtr root, child;
+                                                       int mask;
+                                                       XQueryPointer (DisplayHandle, xevent.AnyEvent.window,
+                                                                                       out root, out child,
+                                                                                       out xevent.MotionEvent.x_root, 
+                                                                                       out xevent.MotionEvent.y_root,
+                                                                                       out xevent.MotionEvent.x,      
+                                                                                       out xevent.MotionEvent.y, out mask);
                                                }
 
                                                msg.message = Msg.WM_MOUSEMOVE;
@@ -3646,14 +3998,7 @@ namespace System.Windows.Forms {
                                                        msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
                                                }
 
-                                               // The hit test is sent in screen coordinates
-                                               XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
-                                                               xevent.MotionEvent.x, xevent.MotionEvent.y,
-                                                               out screen_x, out screen_y, out dummy);
-
-                                               msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
-                                               ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
-                                                               IntPtr.Zero, msg.lParam).ToInt32 ();
+                                               ht = NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
                                                NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
 
                                                mouse_position.X = xevent.MotionEvent.x;
@@ -3667,14 +4012,38 @@ namespace System.Windows.Forms {
                                        if (!hwnd.Enabled) {
                                                goto ProcessNextMessage;
                                        }
-                                       if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
+                                       if (xevent.CrossingEvent.mode == NotifyMode.NotifyGrab || LastPointerWindow == xevent.CrossingEvent.window ||
+                                                       hwnd.client_window == IntPtr.Zero) {
                                                goto ProcessNextMessage;
                                        }
+                                       if (LastPointerWindow != IntPtr.Zero) {
+                                               Point enter_loc = new Point (xevent.ButtonEvent.x, xevent.ButtonEvent.y);
+
+                                               // We need this due to EnterNotify being fired on all the parent controls
+                                               // of the Control being grabbed, and obviously in that scenario we are not
+                                               // actuallty entering them
+                                               Control ctrl = Control.FromHandle (hwnd.client_window);
+                                               foreach (Control child_control in ctrl.Controls)
+                                                       if (child_control.Bounds.Contains (enter_loc))
+                                                               goto ProcessNextMessage;
+                                       }
+
+                                       LastPointerWindow = xevent.AnyEvent.window;
+
                                        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;
+
+                                       // Win32 sends a WM_MOUSEMOVE after mouse enter
+                                       XEvent motionEvent = new XEvent ();
+                                       motionEvent.type = XEventName.MotionNotify;
+                                       motionEvent.MotionEvent.display = DisplayHandle;
+                                       motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
+                                       motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
+                                       motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
+                                       hwnd.Queue.EnqueueLocked (motionEvent);
                                        break;
                                }
 
@@ -3689,6 +4058,14 @@ namespace System.Windows.Forms {
                                        if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
                                                goto ProcessNextMessage;
                                        }
+
+                                       // Reset the cursor explicitly on X11.
+                                       // X11 remembers the last set cursor for the window and in cases where 
+                                       // the control won't get a WM_SETCURSOR X11 will restore the last 
+                                       // known cursor, which we don't want.
+                                       // 
+                                       SetCursor (hwnd.client_window, IntPtr.Zero);
+
                                        msg.message=Msg.WM_MOUSELEAVE;
                                        HoverState.Timer.Enabled = false;
                                        HoverState.Window = IntPtr.Zero;
@@ -3711,27 +4088,13 @@ namespace System.Windows.Forms {
                                case XEventName.ReparentNotify: {
                                        if (hwnd.parent == null) {      // Toplevel
                                                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 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;
-                                                       }
+                                                       // The location given by the event is not reliable between different wm's, 
+                                                       // so use an alternative way of getting it.
+                                                       Point location = GetTopLevelWindowLocation (hwnd);
+                                                       hwnd.X = location.X;
+                                                       hwnd.Y = location.Y;
 
                                                        if (hwnd.opacity != 0xffffffff) {
                                                                IntPtr opacity;
@@ -3754,16 +4117,28 @@ namespace System.Windows.Forms {
                                                #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
-//                                             if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
-                                                       lock (hwnd.configure_lock) {
-                                                               SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
-                                                               hwnd.configure_pending = false;
-                                                       }
 
+                                               lock (hwnd.configure_lock) {
+                                                       Form form = Control.FromHandle (hwnd.client_window) as Form;
+                                                       if (form != null && !hwnd.resizing_or_moving) {
+                                                               if (hwnd.x != form.Bounds.X || hwnd.y != form.Bounds.Y) {
+                                                                       SendMessage (form.Handle, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_MOVE, IntPtr.Zero);
+                                                                       hwnd.resizing_or_moving = true;
+                                                               } else if (hwnd.width != form.Bounds.Width || hwnd.height != form.Bounds.Height) {
+                                                                       SendMessage (form.Handle, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_SIZE, IntPtr.Zero);
+                                                                       hwnd.resizing_or_moving = true;
+                                                               }
+                                                               if (hwnd.resizing_or_moving)
+                                                                       SendMessage (form.Handle, Msg.WM_ENTERSIZEMOVE, IntPtr.Zero, IntPtr.Zero);
+                                                       }
+       
+                                                       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
                                                        if (hwnd.whole_window != hwnd.client_window)
                                                                PerformNCCalc(hwnd);
-//                                             }
+                                               }
                                        }
                                        goto ProcessNextMessage;
                                }
@@ -3790,8 +4165,8 @@ namespace System.Windows.Forms {
                                                }
                                                goto ProcessNextMessage;
                                        }
-                                       Keyboard.FocusIn(FocusWindow);
                                        SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
+                                       Keyboard.FocusIn (FocusWindow);
                                        goto ProcessNextMessage;
                                }
 
@@ -3800,12 +4175,12 @@ namespace System.Windows.Forms {
                                        if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
                                                goto ProcessNextMessage;
                                        }
-                                       Keyboard.FocusOut(FocusWindow);
 
                                        while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
                                                SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
                                        }
 
+                                       Keyboard.FocusOut(hwnd.client_window);
                                        SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
                                        goto ProcessNextMessage;
                                }
@@ -3972,6 +4347,7 @@ namespace System.Windows.Forms {
 
                                        if  (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
                                                if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
+                                                       SendMessage (msg.hwnd, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_CLOSE, IntPtr.Zero);
                                                        msg.message = Msg.WM_CLOSE;
                                                        return true;
                                                }
@@ -3992,6 +4368,16 @@ namespace System.Windows.Forms {
                        return true;
                }
 
+               private HitTest NCHitTest (Hwnd hwnd, int x, int y)
+               {
+                       // The hit test is sent in screen coordinates
+                       IntPtr dummy;
+                       int screen_x, screen_y;
+                       XTranslateCoordinates (DisplayHandle, hwnd.WholeWindow, RootWindow, x, y, out screen_x, out screen_y, out dummy);
+                       return (HitTest) NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST, IntPtr.Zero, 
+                                                              (IntPtr) (screen_y << 16 | screen_x & 0xFFFF));
+               }
+
                internal override bool GetText(IntPtr handle, out string text) {
 
                        lock (XlibLock) {
@@ -4151,7 +4537,7 @@ namespace System.Windows.Forms {
                                XGrabPointer(DisplayHandle, hwnd.client_window, false, 
                                        EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
                                        EventMask.ButtonReleaseMask | EventMask.PointerMotionMask | 
-                                       EventMask.LeaveWindowMask,
+                                       EventMask.PointerMotionHintMask | EventMask.LeaveWindowMask,
                                        GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
                        }
                }
@@ -4204,7 +4590,7 @@ namespace System.Windows.Forms {
 
                        hwnd = Hwnd.ObjectFromHandle(handle);
 
-                       AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
+                       AddExpose (hwnd, hwnd.WholeWindow == hwnd.ClientWindow, 0, 0, hwnd.Width, hwnd.Height);
                }
 
                internal override bool IsEnabled(IntPtr handle) {
@@ -4222,7 +4608,12 @@ namespace System.Windows.Forms {
 
                        if (queue == null) {
                                // This isn't really an error, MS doesn't start the timer if
-                               // it has no assosciated queue
+                               // it has no assosciated queue. In this case, remove the timer
+                               // from the list of unattached timers (if it was enabled).
+                               lock (unattached_timer_list) {
+                                       if (unattached_timer_list.Contains (timer))
+                                               unattached_timer_list.Remove (timer);
+                               }
                                return;
                        }
                        queue.timer_list.Remove (timer);
@@ -4250,6 +4641,7 @@ namespace System.Windows.Forms {
                                XChangeActivePointerGrab (DisplayHandle,
                                                EventMask.ButtonMotionMask |
                                                EventMask.PointerMotionMask |
+                                               EventMask.PointerMotionHintMask |
                                                EventMask.ButtonPressMask |
                                                EventMask.ButtonReleaseMask,
                                                cursor, IntPtr.Zero);
@@ -4259,12 +4651,23 @@ namespace System.Windows.Forms {
                        OverrideCursorHandle = cursor;
                }
 
-               internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
+               internal override PaintEventArgs PaintEventStart(ref Message msg, IntPtr handle, bool client) {
                        PaintEventArgs  paint_event;
                        Hwnd            hwnd;
-
-                       hwnd = Hwnd.ObjectFromHandle(handle);
-
+                       Hwnd            paint_hwnd;
+                       
+                       // 
+                       // handle  (and paint_hwnd) refers to the window that is should be painted.
+                       // msg.HWnd (and hwnd) refers to the window that got the paint message.
+                       // 
+                       
+                       hwnd = Hwnd.ObjectFromHandle(msg.HWnd);
+                       if (msg.HWnd == handle) {
+                               paint_hwnd = hwnd;
+                       } else {
+                               paint_hwnd = Hwnd.ObjectFromHandle (handle);
+                       }
+       
                        if (Caret.Visible == true) {
                                Caret.Paused = true;
                                HideCaret();
@@ -4273,7 +4676,7 @@ namespace System.Windows.Forms {
                        Graphics dc;
 
                        if (client) {
-                               dc = Graphics.FromHwnd (hwnd.client_window);
+                               dc = Graphics.FromHwnd (paint_hwnd.client_window);
 
                                Region clip_region = new Region ();
                                clip_region.MakeEmpty();
@@ -4297,7 +4700,7 @@ namespace System.Windows.Forms {
 
                                return paint_event;
                        } else {
-                               dc = Graphics.FromHwnd (hwnd.whole_window);
+                               dc = Graphics.FromHwnd (paint_hwnd.whole_window);
 
                                if (!hwnd.nc_invalid.IsEmpty) {
                                        dc.SetClip (hwnd.nc_invalid);
@@ -4316,10 +4719,10 @@ namespace System.Windows.Forms {
                        }
                }
 
-               internal override void PaintEventEnd(IntPtr handle, bool client) {
+               internal override void PaintEventEnd(ref Message msg, IntPtr handle, bool client) {
                        Hwnd    hwnd;
 
-                       hwnd = Hwnd.ObjectFromHandle(handle);
+                       hwnd = Hwnd.ObjectFromHandle (msg.HWnd);
 
                        Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
                        dc.Flush();
@@ -4386,13 +4789,21 @@ namespace System.Windows.Forms {
                        xevent.ClientMessageEvent.ptr3 = wparam;
                        xevent.ClientMessageEvent.ptr4 = lparam;
 
-                       hwnd.Queue.EnqueueLocked (xevent);
+                       if (hwnd != null)
+                               hwnd.Queue.EnqueueLocked (xevent);
+                       else
+                               ThreadQueue(Thread.CurrentThread).EnqueueLocked (xevent);
 
                        return true;
                }
 
                internal override void PostQuitMessage(int exitCode) {
-                       PostMessage (FosterParent, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
+                       ApplicationContext ctx = Application.MWFThread.Current.Context;
+                       Form f = ctx != null ? ctx.MainForm : null;
+                       if (f != null)
+                               PostMessage (Application.MWFThread.Current.Context.MainForm.window.Handle, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
+                       else
+                               PostMessage (FosterParent, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
                        XFlush(DisplayHandle);
                }
 
@@ -4458,10 +4869,42 @@ namespace System.Windows.Forms {
                                XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
                        }
 
+                       Form form = Control.FromHandle (handle) as Form;
+                       if (form != null && form.window_manager != null) {
+                               dest_y_return -= form.window_manager.TitleBarHeight;
+                       }
+
                        x = dest_x_return;
                        y = dest_y_return;
                }
 
+               bool GraphicsExposePredicate (IntPtr display, ref XEvent xevent, IntPtr arg)
+               {
+                       return (xevent.type == XEventName.GraphicsExpose || xevent.type == XEventName.NoExpose) &&
+                               arg == xevent.GraphicsExposeEvent.drawable;
+               }
+
+               delegate bool EventPredicate (IntPtr display, ref XEvent xevent, IntPtr arg);
+
+               void ProcessGraphicsExpose (Hwnd hwnd)
+               {
+                       XEvent xevent = new XEvent ();
+                       IntPtr handle = Hwnd.HandleFromObject (hwnd);
+                       EventPredicate predicate = GraphicsExposePredicate;
+
+                       for (;;) {
+                               XIfEvent (Display, ref xevent, predicate, handle);
+                               if (xevent.type != XEventName.GraphicsExpose)
+                                       break;
+
+                               AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.GraphicsExposeEvent.x, xevent.GraphicsExposeEvent.y,
+                                               xevent.GraphicsExposeEvent.width, xevent.GraphicsExposeEvent.height);
+
+                               if (xevent.GraphicsExposeEvent.count == 0)
+                                       break;
+                       }
+               }
+
                internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
                        Hwnd            hwnd;
                        IntPtr          gc;
@@ -4500,48 +4943,23 @@ namespace System.Windows.Forms {
 
                        gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
 
-                       int src_x, src_y;
-                       int dest_x, dest_y;
-                       int width, height;
+                       Rectangle visible_rect = GetTotalVisibleArea (hwnd.client_window);
+                       visible_rect.Intersect (area);
 
-                       if (YAmount > 0) {
-                               src_y = area.Y;
-                               height = area.Height - YAmount;
-                               dest_y = area.Y + YAmount;
-                       }
-                       else {
-                               src_y = area.Y - YAmount;
-                               height = area.Height + YAmount;
-                               dest_y = area.Y;
-                       }
+                       Rectangle dest_rect = visible_rect;
+                       dest_rect.Y += YAmount;
+                       dest_rect.X += XAmount;
+                       dest_rect.Intersect (area);
 
-                       if (XAmount > 0) {
-                               src_x = area.X;
-                               width = area.Width - XAmount;
-                               dest_x = area.X + XAmount;
-                       }
-                       else {
-                               src_x = area.X - XAmount;
-                               width = area.Width + XAmount;
-                               dest_x = area.X;
-                       }
+                       Point src = new Point (dest_rect.X - XAmount, dest_rect.Y - YAmount);
+                       XCopyArea (DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src.X, src.Y, 
+                                       dest_rect.Width, dest_rect.Height, dest_rect.X, dest_rect.Y);
 
-                       XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
+                       Rectangle dirty_area = GetDirtyArea (area, dest_rect, XAmount, YAmount);
+                       AddExpose (hwnd, true, dirty_area.X, dirty_area.Y, dirty_area.Width, dirty_area.Height);
 
-                       // Generate an expose for the area exposed by the horizontal scroll
-                       // We don't use AddExpose since we're 
-                       if (XAmount > 0) {
-                               AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
-                       } else if (XAmount < 0) {
-                               AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
-                       }
+                       ProcessGraphicsExpose (hwnd);
 
-                       // Generate an expose for the area exposed by the vertical scroll
-                       if (YAmount > 0) {
-                               AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
-                       } else if (YAmount < 0) {
-                               AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
-                       }
                        XFreeGC(DisplayHandle, gc);
                }
 
@@ -4557,6 +4975,48 @@ namespace System.Windows.Forms {
                        ScrollWindow(handle, rect, XAmount, YAmount, with_children);
                }
 
+               Rectangle GetDirtyArea (Rectangle total_area, Rectangle valid_area, int XAmount, int YAmount)
+               {
+                       Rectangle dirty_area = total_area;
+
+                       if (YAmount > 0)
+                               dirty_area.Height -= valid_area.Height;
+                       else if (YAmount < 0) {
+                               dirty_area.Height -= valid_area.Height;
+                               dirty_area.Y += valid_area.Height;
+                       }
+
+                       if (XAmount > 0)
+                               dirty_area.Width -= valid_area.Width;
+                       else if (XAmount < 0) {
+                               dirty_area.Width -= valid_area.Width;
+                               dirty_area.X += valid_area.Width;
+                       }
+
+                       return dirty_area;
+               }
+
+               Rectangle GetTotalVisibleArea (IntPtr handle)
+               {
+                       Control c = Control.FromHandle (handle);
+
+                       Rectangle visible_area = c.ClientRectangle;
+                       visible_area.Location = c.PointToScreen (Point.Empty);
+
+                       for (Control parent = c.Parent; parent != null; parent = parent.Parent) {
+                               if (!parent.IsHandleCreated || !parent.Visible)
+                                       return visible_area; // Non visible, not need to finish computations
+
+                               Rectangle r = parent.ClientRectangle;
+                               r.Location = parent.PointToScreen (Point.Empty);
+
+                               visible_area.Intersect (r);
+                       }
+
+                       visible_area.Location = c.PointToClient (visible_area.Location);
+                       return visible_area;
+               }
+
                internal override void SendAsyncMethod (AsyncMethodData method) {
                        Hwnd    hwnd;
                        XEvent  xevent = new XEvent ();
@@ -4651,9 +5111,13 @@ namespace System.Windows.Forms {
 
                internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
                        Form form = Control.FromHandle (handle) as Form;
-                       if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
-                                       border_style == FormBorderStyle.SizableToolWindow)) {
-                               form.window_manager = new ToolWindowManager (form);
+                       if (form != null && form.window_manager == null) {
+                               CreateParams cp = form.GetCreateParams ();
+                               if (border_style == FormBorderStyle.FixedToolWindow ||
+                                    border_style == FormBorderStyle.SizableToolWindow || 
+                                    cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
+                                       form.window_manager = new ToolWindowManager (form);
+                               }
                        }
                        
                        RequestNCRecalc(handle);
@@ -4667,6 +5131,8 @@ namespace System.Windows.Forms {
                                Caret.X = x;
                                Caret.Y = y;
 
+                               Keyboard.SetCaretPos (Caret, handle, x, y);
+
                                if (Caret.Visible == true) {
                                        ShowCaret();
                                        Caret.Timer.Start();
@@ -4683,7 +5149,6 @@ namespace System.Windows.Forms {
                        }
 
                        hwnd.UserClip = region;
-                       Invalidate(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height), false);
                }
 
                internal override void SetCursor(IntPtr handle, IntPtr cursor) {
@@ -4826,6 +5291,10 @@ namespace System.Windows.Forms {
                                return;
                        }
 
+                       // Win32 doesn't do anything if disabled
+                       if (!hwnd.enabled)
+                               return;
+
                        prev_focus_window = FocusWindow;
                        FocusWindow = hwnd.client_window;
 
@@ -4833,6 +5302,7 @@ namespace System.Windows.Forms {
                                SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
                        }
                        SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
+                       Keyboard.FocusIn (FocusWindow);
 
                        //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
                }
@@ -4866,6 +5336,10 @@ namespace System.Windows.Forms {
                                        Activate((IntPtr)ModalWindows.Peek());
                                }
                        }
+
+                       Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
+                       Control ctrl = Control.FromHandle (handle);
+                       SetWMStyles (hwnd, ctrl.GetCreateParams ());
                }
 
                internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
@@ -4889,26 +5363,41 @@ namespace System.Windows.Forms {
 
                        if (queue == null) {
                                // This isn't really an error, MS doesn't start the timer if
-                               // it has no assosciated queue
+                               // it has no assosciated queue at this stage (it will be
+                               // enabled when a window is activated).
+                               unattached_timer_list.Add (timer);
                                return;
                        }
                        queue.timer_list.Add (timer);
                        WakeupMain ();
                }
 
-               internal override bool SetTopmost(IntPtr handle, IntPtr handle_owner, bool enabled) {
-                       Hwnd    hwnd;
-                       Hwnd    hwnd_owner;
+               internal override bool SetTopmost(IntPtr handle, bool enabled) {
 
-                       hwnd = Hwnd.ObjectFromHandle(handle);
+                       Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
 
-                       if (handle_owner != IntPtr.Zero) {
-                               hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
+                       if (enabled) {
+                               lock (XlibLock) {
+                                       int[] atoms = new int[8];
+                                       atoms[0] = _NET_WM_STATE_ABOVE.ToInt32();
+                                       XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
+                               }
                        } else {
-                               hwnd_owner = null;
+                               lock (XlibLock) {
+                                       XDeleteProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE);
+                               }
                        }
+                       return true;
+               }
 
-                       if (enabled) {
+               internal override bool SetOwner(IntPtr handle, IntPtr handle_owner) {
+                       Hwnd hwnd;
+                       Hwnd hwnd_owner;
+
+                       hwnd = Hwnd.ObjectFromHandle(handle);
+
+                       if (handle_owner != IntPtr.Zero) {
+                               hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
                                lock (XlibLock) {
                                        int[]   atoms;
 
@@ -4963,6 +5452,12 @@ namespace System.Windows.Forms {
                }
 
                internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
+                       Control ctrl = Control.FromHandle (handle);
+                       SetWindowMinMax (handle, maximized, min, max, ctrl != null ? ctrl.GetCreateParams () : null);
+               }
+
+               internal void SetWindowMinMax (IntPtr handle, Rectangle maximized, Size min, Size max, CreateParams cp)
+               {
                        Hwnd            hwnd;
                        XSizeHints      hints;
                        IntPtr          dummy;
@@ -4972,26 +5467,38 @@ namespace System.Windows.Forms {
                                return;
                        }
 
+                       min.Width = Math.Max (min.Width, SystemInformation.MinimumWindowSize.Width);
+                       min.Height = Math.Max (min.Height, SystemInformation.MinimumWindowSize.Height);
+                       
                        hints = new XSizeHints();
 
                        XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
                        if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
+                               if (cp != null)
+                                       min = TranslateWindowSizeToXWindowSize (cp, min);
                                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)) {
+                               if (cp != null)
+                                       max = TranslateWindowSizeToXWindowSize (cp, max);
                                hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
                                hints.max_width = max.Width;
                                hints.max_height = max.Height;
                        }
 
                        if (hints.flags != IntPtr.Zero) {
+                               // The Metacity team has decided that they won't care about this when clicking the maximize icon, 
+                               // they will maximize the window to fill the screen/parent no matter what.
+                               // http://bugzilla.ximian.com/show_bug.cgi?id=80021
                                XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
                        }
 
                        if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
+                               if (cp != null)
+                                       maximized.Size = TranslateWindowSizeToXWindowSize (cp);
                                hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
                                hints.x = maximized.X;
                                hints.y = maximized.Y;
@@ -5051,7 +5558,9 @@ namespace System.Windows.Forms {
                                }
 
                                lock (XlibLock) {
-                                       XMoveResizeWindow(DisplayHandle, hwnd.whole_window, x, y, width, height);
+                                       Control ctrl = Control.FromHandle (handle);
+                                       Size TranslatedSize = TranslateWindowSizeToXWindowSize (ctrl.GetCreateParams (), new Size (width, height));
+                                       MoveResizeWindow (DisplayHandle, hwnd.whole_window, x, y, TranslatedSize.Width, TranslatedSize.Height);
                                        PerformNCCalc(hwnd);
                                }
                        }
@@ -5227,18 +5736,19 @@ namespace System.Windows.Forms {
 
                                // Oh boy.
                                if (hwnd.client_window != hwnd.whole_window) {
+                                       Keyboard.DestroyICForWindow (hwnd.client_window);
                                        XDestroyWindow(DisplayHandle, hwnd.client_window);
                                        hwnd.client_window = hwnd.whole_window;
+                               }       
 
-                                       /* by virtue of the way the tests are ordered when determining if it's PAINT
-                                          or NCPAINT, client_window == whole_window will always be PAINT.  So, if we're
-                                          waiting on an nc_expose, drop it and remove the hwnd from the list (unless
-                                          there's a pending expose). */
-                                       if (hwnd.nc_expose_pending) {
-                                               hwnd.nc_expose_pending = false;
-                                               if (!hwnd.expose_pending)
-                                                       hwnd.Queue.Paint.Remove (hwnd);
-                                       }
+                               /* by virtue of the way the tests are ordered when determining if it's PAINT
+                                  or NCPAINT, client_window == whole_window will always be PAINT.  So, if we're
+                                  waiting on an nc_expose, drop it and remove the hwnd from the list (unless
+                                  there's a pending expose). */
+                               if (hwnd.nc_expose_pending) {
+                                       hwnd.nc_expose_pending = false;
+                                       if (!hwnd.expose_pending)
+                                               hwnd.Queue.Paint.Remove (hwnd);
                                }
 
                                size_hints = new XSizeHints();
@@ -5263,7 +5773,7 @@ namespace System.Windows.Forms {
 
                                // Need to pick some reasonable defaults
                                tt = new ToolTip();
-                               tt.AutomaticDelay = 100;
+                               tt.AutomaticDelay = 350;
                                tt.InitialDelay = 250;
                                tt.ReshowDelay = 250;
                                tt.ShowAlways = true;
@@ -5290,6 +5800,7 @@ namespace System.Windows.Forms {
                        if (control != null && tt != null) {
                                tt.SetToolTip(control, tip);
                                tt.Active = true;
+                               SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
                                return true;
                        } else {
                                return false;
@@ -5298,29 +5809,7 @@ namespace System.Windows.Forms {
 
                internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
 
-#if GTKSOCKET_SUPPORTS_REPARENTING
-                       Hwnd    hwnd;
-
-                       hwnd = Hwnd.ObjectFromHandle(handle);
-
-                       /* in the XEMBED spec, it mentions 3 ways for a client window to break the protocol with the embedder.
-                        * 1. The embedder can unmap the window and reparent to the root window (we should probably handle this...)
-                        * 2. The client can reparent its window out of the embedder window.
-                        * 3. The client can destroy its window.
-                        *
-                        * this call to SetParent is case 2, but in
-                        * the spec it also mentions that gtk doesn't
-                        * support this at present.  Looking at HEAD
-                        * gtksocket-x11.c jives with this statement.
-                        *
-                        * so we can't reparent.  we have to destroy.
-                        */
-                       SetParent(hwnd.whole_window, FosterParent);
-#else
-                       Control control = Control.FromHandle(handle);
-                       if (control is NotifyIcon.NotifyIconWindow)
-                               ((NotifyIcon.NotifyIconWindow)control).InternalRecreateHandle ();
-#endif
+                       SetVisible (handle, false, false);
 
                        // The caller can now re-dock it later...
                        if (tt != null) {
@@ -5329,6 +5818,14 @@ namespace System.Windows.Forms {
                        }
                }
 
+#if NET_2_0
+               internal override void SystrayBalloon(IntPtr handle, int timeout, string title, string text, ToolTipIcon icon)
+               {
+                       ThemeEngine.Current.ShowBalloonWindow (handle, timeout, title, text, icon);
+                       SendMessage(handle, Msg.WM_USER, IntPtr.Zero, (IntPtr) Msg.NIN_BALLOONSHOW);    
+               }
+#endif
+
                internal override bool Text(IntPtr handle, string text) {
                        Hwnd    hwnd;
 
@@ -5419,6 +5916,25 @@ namespace System.Windows.Forms {
                internal override event EventHandler Idle;
                #endregion      // Events
 
+#region Xcursor imports
+               [DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadCursor")]
+               internal extern static IntPtr XcursorLibraryLoadCursor (IntPtr display, [MarshalAs (UnmanagedType.LPStr)] string name);
+
+               [DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadImages")]
+               internal extern static IntPtr XcursorLibraryLoadImages ([MarshalAs (UnmanagedType.LPStr)] string file, IntPtr theme, int size);
+               
+               [DllImport ("libXcursor", EntryPoint = "XcursorImagesDestroy")]
+               internal extern static void XcursorImagesDestroy (IntPtr images);
+               
+               [DllImport ("libXcursor", EntryPoint = "XcursorGetDefaultSize")]
+               internal extern static int XcursorGetDefaultSize (IntPtr display);
+
+               [DllImport ("libXcursor", EntryPoint = "XcursorImageLoadCursor")]
+               internal extern static IntPtr XcursorImageLoadCursor (IntPtr display, IntPtr image);
+
+               [DllImport ("libXcursor", EntryPoint = "XcursorGetTheme")]
+               internal extern static IntPtr XcursorGetTheme (IntPtr display);
+#endregion
                #region X11 Imports
                [DllImport ("libX11", EntryPoint="XOpenDisplay")]
                internal extern static IntPtr XOpenDisplay(IntPtr display);
@@ -5456,7 +5972,14 @@ namespace System.Windows.Forms {
                [DllImport ("libX11", EntryPoint="XReparentWindow")]
                internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
                [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
-               internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
+               private extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
+
+               internal static int MoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height)
+               {
+                       int ret = XMoveResizeWindow (display, window, x, y, width, height);
+                       Keyboard.MoveCurrentCaretPos ();
+                       return ret;
+               }
 
                [DllImport ("libX11", EntryPoint="XResizeWindow")]
                internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
@@ -5591,9 +6114,6 @@ namespace System.Windows.Forms {
                [DllImport ("libX11", EntryPoint="XDeleteProperty")]
                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, IntPtr valuemask, ref XGCValues values);
@@ -5658,6 +6178,9 @@ namespace System.Windows.Forms {
                [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
                internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
 
+               [DllImport ("libX11", EntryPoint="XQueryExtension")]
+               internal extern static int XQueryExtension(IntPtr display, string extension_name, ref int major, ref int first_event, ref int first_error);
+
                [DllImport ("libX11", EntryPoint="XWhitePixel")]
                internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
 
@@ -5726,6 +6249,9 @@ namespace System.Windows.Forms {
 
                [DllImport ("libX11")]
                internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);
+
+               [DllImport ("libX11")]
+               internal extern static void XIfEvent (IntPtr display, ref XEvent xevent, Delegate event_predicate, IntPtr arg);
                #endregion
        }
 }