[MWF] Implement multi-display support on Linux (Fixes #325669)
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / XplatUIWin32.cs
index d84c82a051fa51e8a254ca2d985e0ccc2af72e46..e541b1fdb97e8ac428e21922b014da5a404fed6f 100644 (file)
@@ -35,6 +35,7 @@ using System.Diagnostics;
 using System.IO;
 using System.Runtime.InteropServices;
 using System.Text;
+using System.Threading;
 
 
 /// Win32 Version
@@ -52,7 +53,6 @@ namespace System.Windows.Forms {
                internal static Rectangle       grab_area;
                internal static WndProc         wnd_proc;
                internal static IntPtr          prev_mouse_hwnd;
-               internal static IntPtr          override_cursor;
                internal static bool            caret_visible;
 
                internal static bool            themes_enabled;
@@ -101,8 +101,8 @@ namespace System.Windows.Forms {
                        }
 
                        #region Instance Properties
-                       public int Height { get { return bottom - top + 1; } }
-                       public int Width { get { return right - left + 1; } }
+                       public int Height { get { return bottom - top; } }
+                       public int Width { get { return right - left; } }
                        public Size Size { get { return new Size (Width, Height); } }
                        public Point Location { get { return new Point (left, top); } }
                        #endregion
@@ -145,12 +145,37 @@ namespace System.Windows.Forms {
                }
 
                internal enum SPIAction {
-                       SPI_GETKEYBOARDSPEED    = 0x000A,
+                       SPI_GETACTIVEWINDOWTRACKING = 0x1000,
+                       SPI_GETACTIVEWNDTRKTIMEOUT = 0x2002,
+                       SPI_GETANIMATION = 0x0048,
+                       SPI_GETCARETWIDTH = 0x2006,
+                       SPI_GETCOMBOBOXANIMATION = 0x1004,
+                       SPI_GETDRAGFULLWINDOWS  = 0x0026,
+                       SPI_GETDROPSHADOW = 0x1024,
+                       SPI_GETFONTSMOOTHING = 0x004A,
+                       SPI_GETFONTSMOOTHINGCONTRAST = 0x200C,
+                       SPI_GETFONTSMOOTHINGTYPE = 0x200A,
+                       SPI_GETGRADIENTCAPTIONS = 0x1008,
+                       SPI_GETHOTTRACKING = 0x100E,
+                       SPI_GETICONTITLEWRAP = 0x0019,
+                       SPI_GETKEYBOARDSPEED = 0x000A,
                        SPI_GETKEYBOARDDELAY    = 0x0016,
-                       SPI_GETWORKAREA         = 0x0030,
+                       SPI_GETKEYBOARDCUES             = 0x100A,
+                       SPI_GETKEYBOARDPREF = 0x0044,
+                       SPI_GETLISTBOXSMOOTHSCROLLING = 0x1006,
+                       SPI_GETMENUANIMATION = 0x1002,
+                       SPI_GETMENUDROPALIGNMENT = 0x001B,
+                       SPI_GETMENUFADE = 0x1012,
+                       SPI_GETMENUSHOWDELAY = 0x006A,
+                       SPI_GETMOUSESPEED = 0x0070,
+                       SPI_GETSELECTIONFADE = 0x1014,
+                       SPI_GETSNAPTODEFBUTTON = 0x005F,
+                       SPI_GETTOOLTIPANIMATION = 0x1016,
+                       SPI_GETWORKAREA = 0x0030,
                        SPI_GETMOUSEHOVERWIDTH  = 0x0062,
                        SPI_GETMOUSEHOVERHEIGHT = 0x0064,
                        SPI_GETMOUSEHOVERTIME   = 0x0066,
+                       SPI_GETUIEFFECTS = 0x103E,
                        SPI_GETWHEELSCROLLLINES = 0x0068
                }
 
@@ -250,6 +275,15 @@ namespace System.Windows.Forms {
                        internal short wParamH;
                }
 
+               [StructLayout (LayoutKind.Sequential)]
+               internal struct ICONINFO {
+                       internal bool fIcon;
+                       internal Int32 xHotspot;
+                       internal Int32 yHotspot;
+                       internal IntPtr hbmMask;
+                       internal IntPtr hbmColor;
+               }    
+               
                [StructLayout(LayoutKind.Explicit)]
                internal struct INPUT {
                        [FieldOffset(0)]
@@ -265,7 +299,12 @@ namespace System.Windows.Forms {
                        internal HARDWAREINPUT hi;
                }
 
-
+               [StructLayout (LayoutKind.Sequential)]
+               public struct ANIMATIONINFO {
+                       internal uint cbSize;
+                       internal int iMinAnimate;
+               }
+               
                internal enum InputFlags {
                        KEYEVENTF_EXTENDEDKEY   = 0x0001,
                        KEYEVENTF_KEYUP                 = 0x0002,
@@ -381,6 +420,12 @@ namespace System.Windows.Forms {
                        Last                            = 32651
                }
 
+               private enum AncestorType {
+                       GA_PARENT = 1,
+                       GA_ROOT = 2, 
+                       GA_ROOTOWNER = 3
+               }
+
                [Flags]
                private enum WindowLong {
                        GWL_WNDPROC                     = -4,
@@ -586,18 +631,28 @@ namespace System.Windows.Forms {
                        NIF_MESSAGE                     = 0x00000001,
                        NIF_ICON                        = 0x00000002,
                        NIF_TIP                         = 0x00000004,
+                       NIF_STATE                       = 0x00000008,
+                       NIF_INFO                        = 0x00000010                    
                }
 
                [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
                internal struct NOTIFYICONDATA {
-                       internal uint                   cbSize;
-                       internal IntPtr                 hWnd;
-                       internal uint                   uID;
+                       internal uint                           cbSize;
+                       internal IntPtr                         hWnd;
+                       internal uint                           uID;
                        internal NotifyIconFlags        uFlags;
-                       internal uint                   uCallbackMessage;
-                       internal IntPtr                 hIcon;
+                       internal uint                           uCallbackMessage;
+                       internal IntPtr                         hIcon;
+                       [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
+                       internal string                         szTip;
+                       internal int                            dwState;
+                       internal int                            dwStateMask;
+                       [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)]
+                       internal string                         szInfo;
+                       internal int                            uTimeoutOrVersion;
                        [MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)]
-                       internal string                 szTip;
+                       internal string                         szInfoTitle;
+                       internal ToolTipIcon            dwInfoFlags;
                }
 
                [Flags]
@@ -749,7 +804,30 @@ namespace System.Windows.Forms {
                        LWA_ALPHA                       = 0x2,
                }
 
-               
+               public enum ACLineStatus : byte {
+                       Offline = 0,
+                       Online = 1,
+                       Unknown = 255
+               }
+
+               public enum BatteryFlag : byte {
+                       High = 1,
+                       Low = 2,
+                       Critical = 4,
+                       Charging = 8,
+                       NoSystemBattery = 128,
+                       Unknown = 255
+               }
+
+               [StructLayout (LayoutKind.Sequential)]
+               public class SYSTEMPOWERSTATUS {
+                       public ACLineStatus _ACLineStatus;
+                       public BatteryFlag _BatteryFlag;
+                       public Byte _BatteryLifePercent;
+                       public Byte _Reserved1;
+                       public Int32 _BatteryLifeTime;
+                       public Int32 _BatteryFullLifeTime;
+               }
                #endregion
 
                #region Constructor & Destructor
@@ -760,13 +838,16 @@ namespace System.Windows.Forms {
                        mouse_state = MouseButtons.None;
                        mouse_position = Point.Empty;
 
+                       grab_confined = false;
+                       grab_area = Rectangle.Empty;
+
                        message_queue = new Queue();
 
                        themes_enabled = false;
 
                        wnd_proc = new WndProc(InternalWndProc);
 
-                       FosterParent=Win32CreateWindow((int)WindowExStyles.WS_EX_TOOLWINDOW, "static", "Foster Parent Window", (int)WindowStyles.WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
+                       FosterParent=Win32CreateWindow(WindowExStyles.WS_EX_TOOLWINDOW, "static", "Foster Parent Window", WindowStyles.WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
 
                        if (FosterParent==IntPtr.Zero) {
                                Win32MessageBox(IntPtr.Zero, "Could not create foster window, win32 error " + Win32GetLastError().ToString(), "Oops", 0);
@@ -968,9 +1049,201 @@ namespace System.Windows.Forms {
 
                        return dup;
                }
+               
+               private int GetSystemParametersInfoInt (SPIAction spi)
+               {
+                       int value = 0;
+                       
+                       Win32SystemParametersInfo (spi, 0, ref value, 0);
+                       
+                       return value;
+               }
+
+               private bool GetSystemParametersInfoBool (SPIAction spi)
+               {
+                       bool value = false;
+                       
+                       Win32SystemParametersInfo (spi, 0, ref value, 0);
+
+                       return value;
+               }
                #endregion      // Private Support Methods
 
                #region Static Properties
+               internal override int ActiveWindowTrackingDelay {
+                       get { return GetSystemParametersInfoInt (SPIAction.SPI_GETACTIVEWNDTRKTIMEOUT); }
+               }
+
+               internal override int CaretWidth {
+                       get { 
+                               // Supported on 2k, XP, 2k3 +
+                               if (Environment.OSVersion.Version.Major < 5)
+                                       throw new NotSupportedException ();
+                                       
+                               return GetSystemParametersInfoInt (SPIAction.SPI_GETCARETWIDTH);
+                       }
+               }
+
+               internal override int FontSmoothingContrast {
+                       get {
+                               // Supported on XP, 2k3 +
+                               if (Environment.OSVersion.Version.Major < 5 || (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 0))
+                                       throw new NotSupportedException ();
+                                       
+                               return GetSystemParametersInfoInt (SPIAction.SPI_GETFONTSMOOTHINGCONTRAST);
+                       }
+               }
+
+               internal override int FontSmoothingType {
+                       get {
+                               // Supported on XP, 2k3 +
+                               if (Environment.OSVersion.Version.Major < 5 || (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 0))
+                                       throw new NotSupportedException ();
+
+                               return GetSystemParametersInfoInt (SPIAction.SPI_GETFONTSMOOTHINGTYPE);
+                       }
+               }
+
+               internal override int HorizontalResizeBorderThickness {
+                       get { return Win32GetSystemMetrics (SystemMetrics.SM_CXSIZEFRAME); }
+               }
+
+               internal override bool IsActiveWindowTrackingEnabled {
+                       get { return GetSystemParametersInfoBool (SPIAction.SPI_GETACTIVEWINDOWTRACKING); }
+               }
+
+               internal override bool IsComboBoxAnimationEnabled {
+                       get { return GetSystemParametersInfoBool (SPIAction.SPI_GETCOMBOBOXANIMATION); }
+               }
+
+               internal override bool IsDropShadowEnabled {
+                       get {
+                               // Supported on XP, 2k3 +
+                               if (Environment.OSVersion.Version.Major < 5 || (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 0))
+                                       throw new NotSupportedException ();
+
+                               return GetSystemParametersInfoBool (SPIAction.SPI_GETDROPSHADOW);
+                       }
+               }
+
+               internal override bool IsFontSmoothingEnabled {
+                       get { return GetSystemParametersInfoBool (SPIAction.SPI_GETFONTSMOOTHING); }
+               }
+
+               internal override bool IsHotTrackingEnabled {
+                       get { return GetSystemParametersInfoBool (SPIAction.SPI_GETHOTTRACKING); }
+               }
+
+               internal override bool IsIconTitleWrappingEnabled {
+                       get { return GetSystemParametersInfoBool (SPIAction.SPI_GETICONTITLEWRAP); }
+               }
+
+               internal override bool IsKeyboardPreferred {
+                       get { return GetSystemParametersInfoBool (SPIAction.SPI_GETKEYBOARDPREF); }
+               }
+
+               internal override bool IsListBoxSmoothScrollingEnabled {
+                       get { return GetSystemParametersInfoBool (SPIAction.SPI_GETLISTBOXSMOOTHSCROLLING); }
+               }
+
+               internal override bool IsMenuAnimationEnabled {
+                       get { return GetSystemParametersInfoBool (SPIAction.SPI_GETMENUANIMATION); }
+               }
+
+               internal override bool IsMenuFadeEnabled {
+                       get { return GetSystemParametersInfoBool (SPIAction.SPI_GETMENUFADE); }
+               }
+
+               internal override bool IsMinimizeRestoreAnimationEnabled {
+                       get {
+                               ANIMATIONINFO ai = new ANIMATIONINFO ();
+                               ai.cbSize = (uint)Marshal.SizeOf (ai);
+                               
+                               Win32SystemParametersInfo (SPIAction.SPI_GETANIMATION, 0, ref ai, 0);
+                               return ai.iMinAnimate == 0 ? false : true;
+                       }
+               }
+
+               internal override bool IsSelectionFadeEnabled {
+                       get { return GetSystemParametersInfoBool (SPIAction.SPI_GETSELECTIONFADE); }
+               }
+
+               internal override bool IsSnapToDefaultEnabled {
+                       get { return GetSystemParametersInfoBool (SPIAction.SPI_GETSNAPTODEFBUTTON); }
+               }
+
+               internal override bool IsTitleBarGradientEnabled {
+                       get { return GetSystemParametersInfoBool (SPIAction.SPI_GETGRADIENTCAPTIONS); }
+               }
+
+               internal override bool IsToolTipAnimationEnabled {
+                       get { return GetSystemParametersInfoBool (SPIAction.SPI_GETTOOLTIPANIMATION); }
+               }
+
+               internal override Size MenuBarButtonSize {
+                       get {
+                               return new Size (Win32GetSystemMetrics (SystemMetrics.SM_CXMENUSIZE),
+                                       Win32GetSystemMetrics (SystemMetrics.SM_CYMENUSIZE));
+                       }
+               }
+
+               public override Size MenuButtonSize {
+                       get {
+                               return new Size (
+                                       Win32GetSystemMetrics (SystemMetrics.SM_CXMENUSIZE),
+                                       Win32GetSystemMetrics (SystemMetrics.SM_CYMENUSIZE));
+                       }
+               }
+
+               internal override int MenuShowDelay {
+                       get { return GetSystemParametersInfoInt (SPIAction.SPI_GETMENUSHOWDELAY); }
+               }
+
+               internal override int MouseSpeed {
+                       get { return GetSystemParametersInfoInt (SPIAction.SPI_GETMOUSESPEED); }
+               }
+
+               internal override LeftRightAlignment PopupMenuAlignment {
+                       get { return GetSystemParametersInfoBool (SPIAction.SPI_GETMENUDROPALIGNMENT) == true ? LeftRightAlignment.Left : LeftRightAlignment.Right; }
+               }
+
+               internal override PowerStatus PowerStatus {
+                       get {
+                               SYSTEMPOWERSTATUS p = new SYSTEMPOWERSTATUS ();
+                               
+                               Win32GetSystemPowerStatus (p);
+                               
+                               PowerStatus ps = new PowerStatus ((BatteryChargeStatus)p._BatteryFlag, p._BatteryFullLifeTime, (float)p._BatteryLifePercent / 255f, p._BatteryLifeTime, (PowerLineStatus)p._ACLineStatus);
+                               
+                               return ps;
+                       }
+               }
+
+               internal override int SizingBorderWidth {
+                       get { return Win32GetSystemMetrics (SystemMetrics.SM_CXSIZEFRAME); }
+               }
+
+               internal override Size SmallCaptionButtonSize {
+                       get {
+                               return new Size (Win32GetSystemMetrics (SystemMetrics.SM_CXSMSIZE),
+                                       Win32GetSystemMetrics (SystemMetrics.SM_CYSMSIZE));
+                       }
+               }
+
+               internal override bool UIEffectsEnabled {
+                       get { return GetSystemParametersInfoBool (SPIAction.SPI_GETUIEFFECTS); }
+               }
+
+               internal override int VerticalResizeBorderThickness {
+                       get { return Win32GetSystemMetrics (SystemMetrics.SM_CYSIZEFRAME); }
+               }
+
+               internal override void RaiseIdle (EventArgs e)
+               {
+                       if (Idle != null)
+                               Idle (this, e);
+               }
+
                internal override Keys ModifierKeys {
                        get {
                                short   state;
@@ -1061,6 +1334,20 @@ namespace System.Windows.Forms {
                        }
                }
 
+               internal override Size Border3DSize {
+                       get {
+                               return new Size (Win32GetSystemMetrics (SystemMetrics.SM_CXEDGE),
+                                       Win32GetSystemMetrics (SystemMetrics.SM_CYEDGE));
+                       }
+               }
+
+               internal override Size BorderSize {
+                       get {
+                               return new Size (Win32GetSystemMetrics (SystemMetrics.SM_CXBORDER),
+                                       Win32GetSystemMetrics (SystemMetrics.SM_CYBORDER));
+                       }
+               }
+
                internal override bool DropTarget {
                        get {
                                return false;
@@ -1073,7 +1360,14 @@ namespace System.Windows.Forms {
                        }
                }
 
-               internal override int Caption {
+               internal override Size CaptionButtonSize {
+                       get {
+                               return new Size (Win32GetSystemMetrics (SystemMetrics.SM_CXSIZE),
+                                       Win32GetSystemMetrics (SystemMetrics.SM_CYSIZE));
+                       }
+               }
+
+               internal override int CaptionHeight {
                        get {
                                return Win32GetSystemMetrics(SystemMetrics.SM_CYCAPTION);
                        }
@@ -1087,7 +1381,9 @@ namespace System.Windows.Forms {
 
                internal override bool DragFullWindows {
                        get {
-                               return true;
+                               int full = 0;
+                               Win32SystemParametersInfo (SPIAction.SPI_GETDRAGFULLWINDOWS, 0, ref full, 0);
+                               return (full != 0);
                        }
                }
 
@@ -1097,6 +1393,26 @@ namespace System.Windows.Forms {
                        }
                }
 
+               internal override Size DoubleClickSize {
+                       get {
+                               return new Size (Win32GetSystemMetrics (SystemMetrics.SM_CXDOUBLECLK),
+                                       Win32GetSystemMetrics (SystemMetrics.SM_CYDOUBLECLK));
+                       }
+               }
+
+               internal override int DoubleClickTime {
+                       get {
+                               return Win32GetDoubleClickTime ();
+                       }
+               }
+
+               internal override Size FixedFrameBorderSize {
+                       get {
+                               return new Size (Win32GetSystemMetrics (SystemMetrics.SM_CXFIXEDFRAME),
+                                       Win32GetSystemMetrics (SystemMetrics.SM_CYFIXEDFRAME));
+                       }
+               }
+
                internal override Size FrameBorderSize { 
                        get {
                                return new Size(Win32GetSystemMetrics(SystemMetrics.SM_CXFRAME), Win32GetSystemMetrics(SystemMetrics.SM_CYFRAME));
@@ -1115,6 +1431,14 @@ namespace System.Windows.Forms {
                        }
                }
 
+               internal override bool MenuAccessKeysUnderlined {
+                       get {
+                               int underlined = 0;
+                               Win32SystemParametersInfo (SPIAction.SPI_GETKEYBOARDCUES, 0, ref underlined, 0);
+                               return (underlined != 0);
+                       }
+               }
+
                internal override Size MinimizedWindowSize {
                        get {
                                return new Size(Win32GetSystemMetrics(SystemMetrics.SM_CXMINIMIZED), Win32GetSystemMetrics(SystemMetrics.SM_CYMINIMIZED));
@@ -1181,13 +1505,39 @@ namespace System.Windows.Forms {
                        }
                }
 
+               [MonoTODO]
+               internal override Screen[] AllScreens {
+                       get {
+                               // To support multiples, we need to use GetMonitorInfo API on Win32
+                               return null;
+                       }
+               }
+
                internal override bool ThemesEnabled {
                        get {
                                return XplatUIWin32.themes_enabled;
                        }
                }
 
+               internal override bool RequiresPositiveClientAreaSize {
+                       get {
+                               return false;
+                       }
+               }
+
+               public override int ToolWindowCaptionHeight {
+                       get {
+                               return Win32GetSystemMetrics (SystemMetrics.SM_CYSMCAPTION);
+                       }
+               }
+
+               public override Size ToolWindowCaptionButtonSize {
+                       get {
+                               return new Size (
+                                       Win32GetSystemMetrics (SystemMetrics.SM_CXSMSIZE),
+                                       Win32GetSystemMetrics (SystemMetrics.SM_CYSMSIZE));
+                       }
+               }
                #endregion      // Static Properties
 
                #region Singleton Specific Code
@@ -1220,8 +1570,27 @@ namespace System.Windows.Forms {
                        Console.WriteLine("Xplat version $revision: $");
                }
 
-               internal override void AudibleAlert() {
-                       Win32PlaySound("Default", IntPtr.Zero, SndFlags.SND_ALIAS | SndFlags.SND_ASYNC | SndFlags.SND_NOSTOP | SndFlags.SND_NOWAIT);
+               string GetSoundAlias (AlertType alert)
+               {
+                       switch (alert) {
+                               case AlertType.Error:
+                                       return "SystemHand";
+                               case AlertType.Question:
+                                       return "SystemQuestion";
+                               case AlertType.Warning:
+                                       return "SystemExclamation";
+                               case AlertType.Information:
+                                       return "SystemAsterisk";
+                               default:
+                                       return "SystemDefault";
+                       }
+               }
+
+               internal override void AudibleAlert(AlertType alert) {
+                       Win32PlaySound(GetSoundAlias (alert), IntPtr.Zero, SndFlags.SND_ALIAS_ID | SndFlags.SND_ASYNC | SndFlags.SND_NOSTOP | SndFlags.SND_NOWAIT);
+               }
+
+               internal override void BeginMoveResize (IntPtr handle) {
                }
 
                internal override void GetDisplaySize(out Size size) {
@@ -1256,23 +1625,33 @@ namespace System.Windows.Forms {
                                ParentHandle = FosterParent;
                        }
 
-                       FakeStyles (cp);
+                       Point location;
+                       if (cp.HasWindowManager) {
+                               location = Hwnd.GetNextStackedFormLocation (cp, Hwnd.ObjectFromHandle (cp.Parent));
+                       } else {
+                               location = new Point (cp.X, cp.Y);
+                       }
 
                        string class_name = RegisterWindowClass (cp.ClassStyle);
                        HwndCreating = hwnd;
 
-                       WindowHandle = Win32CreateWindow ((uint)cp.ExStyle, class_name, cp.Caption, (uint)cp.Style, cp.X, cp.Y, cp.Width, cp.Height, ParentHandle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
+                       // We cannot actually send the WS_EX_MDICHILD flag to Windows because we
+                       // are faking MDI, not uses Windows' version.
+                       if ((cp.WindowExStyle & WindowExStyles.WS_EX_MDICHILD) == WindowExStyles.WS_EX_MDICHILD)
+                               cp.WindowExStyle ^= WindowExStyles.WS_EX_MDICHILD;
+                               
+                       WindowHandle = Win32CreateWindow (cp.WindowExStyle, class_name, cp.Caption, cp.WindowStyle, location.X, location.Y, cp.Width, cp.Height, ParentHandle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
 
                        HwndCreating = null;
 
                        if (WindowHandle==IntPtr.Zero) {
-                               uint error = Win32GetLastError();
+                               int error = Marshal.GetLastWin32Error ();
 
                                Win32MessageBox(IntPtr.Zero, "Error : " + error.ToString(), "Failed to create window, class '"+cp.ClassName+"'", 0);
                        }
 
                        hwnd.ClientWindow = WindowHandle;
-
+                       hwnd.Mapped = true;
                        Win32SetWindowLong(WindowHandle, WindowLong.GWL_USERDATA, (uint)ThemeEngine.Current.DefaultControlBackColor.ToArgb());
 
                        return WindowHandle;
@@ -1287,7 +1666,7 @@ namespace System.Windows.Forms {
                        create_params.Width = Width;
                        create_params.Height = Height;
 
-                       create_params.ClassName=XplatUI.DefaultClassName;
+                       create_params.ClassName=XplatUI.GetDefaultClassName (GetType ());
                        create_params.ClassStyle = 0;
                        create_params.ExStyle=0;
                        create_params.Parent=IntPtr.Zero;
@@ -1343,12 +1722,15 @@ namespace System.Windows.Forms {
 
                internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
 
-                       FakeStyles (cp);
-
                        Win32SetWindowLong(handle, WindowLong.GWL_STYLE, (uint)cp.Style);
                        Win32SetWindowLong(handle, WindowLong.GWL_EXSTYLE, (uint)cp.ExStyle);
 
-                       if ((cp.ExStyle & (int) WindowExStyles.WS_EX_TOOLWINDOW) > 0)
+                       // From MSDN:
+                       // Certain window data is cached, so changes you make using SetWindowLong
+                       // will not take effect until you call the SetWindowPos function. Specifically, 
+                       // if you change any of the frame styles, you must call SetWindowPos with
+                       // the SWP_FRAMECHANGED flag for the cache to be updated properly.
+                       if (cp.control is Form)
                                XplatUI.RequestNCRecalc (handle);
                }
 
@@ -1419,7 +1801,7 @@ namespace System.Windows.Forms {
                        Win32UpdateWindow(handle);
                }
 
-               internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
+               internal override PaintEventArgs PaintEventStart(ref Message msg, IntPtr handle, bool client) {
                        IntPtr          hdc;
                        PAINTSTRUCT     ps;
                        PaintEventArgs  paint_event;
@@ -1431,33 +1813,42 @@ namespace System.Windows.Forms {
                        rect = new RECT();
                        ps = new PAINTSTRUCT();
 
-                       hwnd = Hwnd.ObjectFromHandle(handle);
-
+                       hwnd = Hwnd.ObjectFromHandle(msg.HWnd);
+                       
                        if (client) {
-                               if (Win32GetUpdateRect(handle, ref rect, false)) {
-                                       hdc = Win32BeginPaint(handle, ref ps);
-
-                                       hwnd.drawing_stack.Push (ps);
-
-                                       clip_rect = new Rectangle(ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right-ps.rcPaint.left, ps.rcPaint.bottom-ps.rcPaint.top);
+                               if (Win32GetUpdateRect(msg.HWnd, ref rect, false)) {
+                                       if (handle != msg.HWnd) {
+                                               // We need to validate the window where the paint message
+                                               // was generated, otherwise we'll never stop getting paint 
+                                               // messages.
+                                               Win32GetClientRect (msg.HWnd, out rect);
+                                               Win32ValidateRect (msg.HWnd, ref rect);
+                                               hdc = Win32GetDC (handle);
+                                       } else {
+                                               hdc = Win32BeginPaint (handle, ref ps);
+                                               rect = ps.rcPaint;
+                                       }
                                } else {
                                        hdc = Win32GetDC(handle);
-                                       // FIXME: Add the DC to internal list
-
-                                       hwnd.drawing_stack.Push (null);
-
-                                       clip_rect = new Rectangle(rect.top, rect.left, rect.right-rect.left, rect.bottom-rect.top);
                                }
+                               clip_rect = rect.ToRectangle ();
                        } else {
                                hdc = Win32GetWindowDC (handle);
 
-                               hwnd.drawing_stack.Push (hdc);
-
                                // HACK this in for now
                                Win32GetWindowRect (handle, out rect);
-                               clip_rect = new Rectangle(0, 0, rect.right-rect.left, rect.bottom-rect.top);
+                               clip_rect = new Rectangle (0, 0, rect.Width, rect.Height);
                        }
 
+                       // If we called BeginPaint, store the PAINTSTRUCT,
+                       // otherwise store hdc, so that PaintEventEnd can know
+                       // whether to call EndPaint or ReleaseDC.
+                       if (ps.hdc != IntPtr.Zero) {
+                               hwnd.drawing_stack.Push (ps);
+                       } else {
+                               hwnd.drawing_stack.Push (hdc);
+                       }
+                       
                        Graphics dc = Graphics.FromHdc(hdc);
                        hwnd.drawing_stack.Push (dc);
 
@@ -1466,23 +1857,21 @@ namespace System.Windows.Forms {
                        return paint_event;
                }
 
-               internal override void PaintEventEnd(IntPtr handle, bool client) {
+               internal override void PaintEventEnd(ref Message m, IntPtr handle, bool client) {
                        Hwnd            hwnd;
 
-                       hwnd = Hwnd.ObjectFromHandle(handle);
+                       hwnd = Hwnd.ObjectFromHandle(m.HWnd);
 
                        Graphics dc = (Graphics)hwnd.drawing_stack.Pop();
                        dc.Dispose ();
 
-                       if (client) {
-                               object o = hwnd.drawing_stack.Pop();
-                               if (o != null) {
-                                       PAINTSTRUCT ps = (PAINTSTRUCT)o;
-                                       Win32EndPaint(handle, ref ps);
-                               }
-                       } else {
-                               IntPtr hdc = (IntPtr)hwnd.drawing_stack.Pop();
-                               Win32ReleaseDC(handle, hdc);
+                       object o = hwnd.drawing_stack.Pop();
+                       if (o is IntPtr) {
+                               IntPtr hdc = (IntPtr) o;
+                               Win32ReleaseDC (handle, hdc);
+                       } else if (o is PAINTSTRUCT) {
+                               PAINTSTRUCT ps = (PAINTSTRUCT) o;
+                               Win32EndPaint (handle, ref ps);
                        }
                }
 
@@ -1504,8 +1893,9 @@ namespace System.Windows.Forms {
                        pt.x=rect.left;
                        pt.y=rect.top;
 
-                       parent = Win32GetParent(handle);
-                       Win32ScreenToClient(parent, ref pt);
+                       parent = Win32GetAncestor (handle, AncestorType.GA_PARENT);
+                       if (parent != IntPtr.Zero && parent != Win32GetDesktopWindow ())
+                               Win32ScreenToClient(parent, ref pt);
 
                        x = pt.x;
                        y = pt.y;
@@ -1518,6 +1908,16 @@ namespace System.Windows.Forms {
 
                internal override void Activate(IntPtr handle) {
                        Win32SetActiveWindow(handle);
+                       // delayed timer enabled
+                       lock (timer_list) {
+                               foreach (Timer t in timer_list.Values) {
+                                       if (t.Enabled && t.window == IntPtr.Zero) {
+                                               t.window = handle;
+                                               int id = t.GetHashCode ();
+                                               Win32SetTimer(handle, id, (uint)t.Interval, IntPtr.Zero);
+                                       }
+                               }
+                       }
                }
 
                internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
@@ -1565,11 +1965,12 @@ namespace System.Windows.Forms {
                internal override void DoEvents() {
                        MSG msg = new MSG();
 
-                       if (override_cursor != IntPtr.Zero) {
-                               Cursor.Current = null;
-                       }
-
                        while (GetMessage(ref msg, IntPtr.Zero, 0, 0, false)) {
+                               Message m = Message.Create (msg.hwnd, (int)msg.message, msg.wParam, msg.lParam);
+
+                               if (Application.FilterMessage (ref m))
+                                       continue;
+
                                XplatUI.TranslateMessage(ref msg);
                                XplatUI.DispatchMessage(ref msg);
                        }
@@ -1684,6 +2085,8 @@ namespace System.Windows.Forms {
                                        if (msg.hwnd != prev_mouse_hwnd) {
                                                TRACKMOUSEEVENT tme;
 
+                                               mouse_state = Control.FromParamToMouseButtons ((int)msg.lParam.ToInt32());
+
                                                // The current message will be sent out next time around
                                                StoreMessage(ref msg);
 
@@ -1705,7 +2108,9 @@ namespace System.Windows.Forms {
                                case Msg.WM_NCMOUSEMOVE: {
                                        if (wm_nc_registered == null || !wm_nc_registered.Contains (msg.hwnd))
                                                break;
-                                               
+
+                                       mouse_state = Control.FromParamToMouseButtons ((int)msg.lParam.ToInt32 ());
+
                                        TRACKMOUSEEVENT tme;
 
                                        tme = new TRACKMOUSEEVENT ();
@@ -1824,6 +2229,11 @@ namespace System.Windows.Forms {
                internal override bool IsEnabled(IntPtr handle) {
                        return IsWindowEnabled (handle);
                }
+
+               internal override bool IsKeyLocked (VirtualKeys key)
+               {
+                       return (Win32GetKeyState (key) & 1) == 1;
+               }
                
                internal override bool IsVisible(IntPtr handle) {
                        return IsWindowVisible (handle);
@@ -1835,14 +2245,39 @@ namespace System.Windows.Forms {
                                if (!(c is Form)) {
                                        Win32ShowWindow(handle, WindowPlacementFlags.SW_HIDE);
                                }
+                       } else {
+                               if (!(c is Form)) {
+                                       SetVisible (handle, c.is_visible, true);
+                               }
+                       }       
+                       // The Win32SetParent is lame, it can very well move the window
+                       // ref: http://groups.google.com/group/microsoft.public.vb.winapi/browse_thread/thread/1b82ccc54231ecee/afa82835bfc0422a%23afa82835bfc0422a
+                       // Here we save the position before changing the parent, and if it has changed afterwards restore it.
+                       // Another possibility would be to intercept WM_WINDOWPOSCHANGING and restore the coords there, but this would require plumbing in weird places
+                       // (either inside Control or add handling to InternalWndProc)
+                       // We also need to remove WS_CHILD if making the window parent-less, and add it if we're parenting it.
+                       RECT rect, rect2;
+                       IntPtr result;
+                       WindowStyles style, new_style;
+                       
+                       Win32GetWindowRect (handle, out rect);
+                       style = (WindowStyles) Win32GetWindowLong (handle, WindowLong.GWL_STYLE);
+                       
+                       if (parent == IntPtr.Zero) {
+                               new_style = style & ~WindowStyles.WS_CHILD;
+                               result = Win32SetParent (handle, FosterParent);
+                       } else {
+                               new_style = style | WindowStyles.WS_CHILD;
+                               result = Win32SetParent (handle, parent);
                        }
-                       else
-                               SetVisible (handle, c.is_visible, true);
-                               
-                       if (parent == IntPtr.Zero)
-                               return Win32SetParent (handle, FosterParent);
-                       else
-                               return Win32SetParent(handle, parent);
+                       if (style != new_style && c is Form) {
+                               Win32SetWindowLong (handle, WindowLong.GWL_STYLE, (uint) new_style);
+                       }
+                       Win32GetWindowRect (handle, out rect2);
+                       if (rect.top != rect2.top && rect.left != rect2.left && c is Form) {
+                               Win32SetWindowPos (handle, IntPtr.Zero, rect.top, rect.left, rect.Width, rect.Height, SetWindowPosFlags.SWP_NOZORDER |  SetWindowPosFlags.SWP_NOREDRAW | SetWindowPosFlags.SWP_NOOWNERZORDER | SetWindowPosFlags.SWP_NOENDSCHANGING | SetWindowPosFlags.SWP_NOACTIVATE);
+                       }
+                       return result;
                }
 
                // If we ever start using this, we should probably replace FosterParent with IntPtr.Zero
@@ -1850,6 +2285,11 @@ namespace System.Windows.Forms {
                        return Win32GetParent(handle);
                }
 
+               // This is a nop on win32 and x11
+               internal override IntPtr GetPreviousWindow(IntPtr handle) {
+                       return handle;
+               }
+
                internal override void GrabWindow(IntPtr hWnd, IntPtr ConfineToHwnd) {
                        grab_hwnd = hWnd;
                        Win32SetCapture(hWnd);
@@ -1878,7 +2318,7 @@ namespace System.Windows.Forms {
                        grab_hwnd = IntPtr.Zero;
                }
 
-               internal override bool CalculateWindowRect(ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
+               internal override bool CalculateWindowRect(ref Rectangle ClientRect, CreateParams cp, Menu menu, out Rectangle WindowRect) {
                        RECT    rect;
 
                        rect.left=ClientRect.Left;
@@ -1886,7 +2326,7 @@ namespace System.Windows.Forms {
                        rect.right=ClientRect.Right;
                        rect.bottom=ClientRect.Bottom;
 
-                       if (!Win32AdjustWindowRectEx(ref rect, Style, menu != null, ExStyle)) {
+                       if (!Win32AdjustWindowRectEx(ref rect, cp.Style, menu != null, cp.ExStyle)) {
                                WindowRect = new Rectangle(ClientRect.Left, ClientRect.Top, ClientRect.Width, ClientRect.Height);
                                return false;
                        }
@@ -1954,6 +2394,22 @@ namespace System.Windows.Forms {
                        return cursor;
                }
 
+               internal override Bitmap DefineStdCursorBitmap (StdCursor id)
+               {
+                       // We load the cursor, create a bitmap, draw the cursor onto the bitmap and return the bitmap.
+                       IntPtr cursor = DefineStdCursor (id);
+                       // Windows only have one possible cursor size!
+                       int width = Win32GetSystemMetrics (SystemMetrics.SM_CXCURSOR);
+                       int height = Win32GetSystemMetrics (SystemMetrics.SM_CYCURSOR);
+                       Bitmap bmp = new Bitmap (width, height);
+                       Graphics gc = Graphics.FromImage (bmp);
+                       IntPtr hdc = gc.GetHdc ();
+                       Win32DrawIcon (hdc, 0, 0, cursor);
+                       gc.ReleaseHdc (hdc);
+                       gc.Dispose ();
+                       return bmp;
+               }
+
                [MonoTODO("Define the missing cursors")]
                internal override IntPtr DefineStdCursor(StdCursor id) {
                        switch(id) {
@@ -1997,10 +2453,15 @@ namespace System.Windows.Forms {
 
                [MonoTODO]
                internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
+                       ICONINFO ii = new ICONINFO ();
+                       
+                       if (!Win32GetIconInfo (cursor, out ii))
+                               throw new Win32Exception ();
+                               
                        width = 20;
                        height = 20;
-                       hotspot_x = 0;
-                       hotspot_y = 0;
+                       hotspot_x = ii.xHotspot;
+                       hotspot_y = ii.yHotspot;
                }
 
                internal override void SetCursorPos(IntPtr handle, int x, int y) {
@@ -2018,7 +2479,10 @@ namespace System.Windows.Forms {
                }
 
                internal override void SetClipRegion(IntPtr hwnd, Region region) {
-                       Win32SetWindowRgn(hwnd, region.GetHrgn(Graphics.FromHwnd(hwnd)), true);
+                       if (region == null)
+                               Win32SetWindowRgn (hwnd, IntPtr.Zero, true);
+                       else
+                               Win32SetWindowRgn(hwnd, region.GetHrgn(Graphics.FromHwnd(hwnd)), true);
                }
 
                internal override void EnableWindow(IntPtr handle, bool Enable) {
@@ -2079,8 +2543,12 @@ namespace System.Windows.Forms {
  
                        Win32GetWindowRect(handle, out rect);
                        x -= rect.left + SystemInformation.FrameBorderSize.Width;
-                       y -= rect.top + SystemInformation.FrameBorderSize.Height + ThemeEngine.Current.CaptionHeight;
-                       return;
+                       y -= rect.top + SystemInformation.FrameBorderSize.Height;
+
+                       WindowStyles style = (WindowStyles) Win32GetWindowLong (handle, WindowLong.GWL_STYLE);
+                       if (CreateParams.IsSet (style, WindowStyles.WS_CAPTION)) {
+                               y -= ThemeEngine.Current.CaptionHeight;
+                       }
                }
   
                internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {                      
@@ -2091,7 +2559,7 @@ namespace System.Windows.Forms {
                        y += rect.top + SystemInformation.FrameBorderSize.Height + ThemeEngine.Current.CaptionHeight;
                        return;
                }
-  
+
                internal override void SendAsyncMethod (AsyncMethodData method)
                {
                        Win32PostMessage(FosterParent, Msg.WM_ASYNC_MESSAGE, IntPtr.Zero, (IntPtr)GCHandle.Alloc (method));
@@ -2107,7 +2575,10 @@ namespace System.Windows.Forms {
                                timer_list[index]=timer;
                        }
 
-                       Win32SetTimer(FosterParent, index, (uint)timer.Interval, IntPtr.Zero);
+                       if (Win32SetTimer(FosterParent, index, (uint)timer.Interval, IntPtr.Zero) != IntPtr.Zero)
+                               timer.window = FosterParent;
+                       else
+                               timer.window = IntPtr.Zero;
                }
 
                internal override void KillTimer (Timer timer)
@@ -2116,24 +2587,13 @@ namespace System.Windows.Forms {
 
                        index = timer.GetHashCode();
 
-                       Win32KillTimer(FosterParent, index);
+                       Win32KillTimer(timer.window, index);
 
                        lock (timer_list) {
                                timer_list.Remove(index);
                        }
                }
                
-               private void FakeStyles (CreateParams cp)
-               {
-                       if (cp.HasWindowManager) {
-                               // Remove all styles but WS_VISIBLE.
-                               cp.WindowStyle &= WindowStyles.WS_VISIBLE;
-                               // Set styles that enables us to use the window manager.
-                               cp.WindowStyle |= WindowStyles.WS_CHILD | WindowStyles.WS_CLIPCHILDREN | WindowStyles.WS_CLIPSIBLINGS;
-                               cp.ExStyle = 0;
-                       }
-               }
-               
                internal override void CreateCaret(IntPtr hwnd, int width, int height) {
                        Win32CreateCaret(hwnd, IntPtr.Zero, width, height);
                        caret_visible = false;
@@ -2175,19 +2635,25 @@ namespace System.Windows.Forms {
 
                internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
                        IntPtr          dc;
+                       IntPtr          prevobj;
                        TEXTMETRIC      tm;
 
                        tm = new TEXTMETRIC();
 
-                       dc = Win32GetDC(IntPtr.Zero);
-                       Win32SelectObject(dc, font.ToHfont());
-                       if (Win32GetTextMetrics(dc, ref tm) == false) {
-                               Win32ReleaseDC(IntPtr.Zero, dc);
+                       dc = Win32GetDC (IntPtr.Zero);
+                       prevobj = Win32SelectObject (dc, font.ToHfont ());
+                       
+                       if (Win32GetTextMetrics (dc, ref tm) == false) {
+                               prevobj = Win32SelectObject (dc, prevobj);
+                               Win32DeleteObject (prevobj);
+                               Win32ReleaseDC (IntPtr.Zero, dc);
                                ascent = 0;
                                descent = 0;
                                return false;
                        }
-                       Win32ReleaseDC(IntPtr.Zero, dc);
+                       prevobj = Win32SelectObject (dc, prevobj);
+                       Win32DeleteObject (prevobj);
+                       Win32ReleaseDC (IntPtr.Zero, dc);
 
                        ascent = tm.tmAscent;
                        descent = tm.tmDescent;
@@ -2276,6 +2742,23 @@ namespace System.Windows.Forms {
                        Win32Shell_NotifyIcon(NotifyIconMessage.NIM_DELETE, ref nid);
                }
 
+               internal override void SystrayBalloon(IntPtr hwnd, int timeout, string title, string text, ToolTipIcon icon)
+               {
+                       NOTIFYICONDATA  nid;
+
+                       nid = new NOTIFYICONDATA();
+
+                       nid.cbSize = (uint)Marshal.SizeOf(nid);
+                       nid.hWnd = hwnd;
+                       nid.uID = 1;
+                       nid.uFlags = NotifyIconFlags.NIF_INFO;
+                       nid.uTimeoutOrVersion = timeout;
+                       nid.szInfoTitle = title;
+                       nid.szInfo = text;
+                       nid.dwInfoFlags = icon;
+                       
+                       Win32Shell_NotifyIcon(NotifyIconMessage.NIM_MODIFY, ref nid);
+               }
 
                internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
                        // Nothing to do on Win32
@@ -2287,6 +2770,20 @@ namespace System.Windows.Forms {
                }
 
                internal override Point GetMenuOrigin(IntPtr handle) {
+                       Form form = Control.FromHandle (handle) as Form;
+                       
+                       if (form != null) {
+                               if (form.FormBorderStyle == FormBorderStyle.None)
+                                       return Point.Empty;
+                                       
+                               int bordersize = (form.Width - form.ClientSize.Width) / 2;
+                                       
+                               if (form.FormBorderStyle == FormBorderStyle.FixedToolWindow || form.FormBorderStyle == FormBorderStyle.SizableToolWindow)
+                                       return new Point (bordersize, bordersize + SystemInformation.ToolWindowCaptionHeight);
+                               else
+                                       return new Point (bordersize, bordersize + SystemInformation.CaptionHeight);
+                       }
+                       
                        return new Point(SystemInformation.FrameBorderSize.Width, SystemInformation.FrameBorderSize.Height + ThemeEngine.Current.CaptionHeight);
                }
 
@@ -2419,10 +2916,9 @@ namespace System.Windows.Forms {
 
                }
 
-               internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
-                       byte[]  data;
-                       IntPtr  hmem;
-                       IntPtr  hmem_ptr;
+               internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter, bool copy)
+               {
+                       byte[]  data = null;
 
                        if (handle != clip_magic) {
                                throw new ArgumentException("handle is not a valid clipboard handle");
@@ -2430,7 +2926,8 @@ namespace System.Windows.Forms {
 
                        if (obj == null) {
                                // Just clear it
-                               Win32EmptyClipboard();
+                               if (!Win32EmptyClipboard())
+                                       throw new ExternalException("Win32EmptyClipboard");
                                return;
                        }
 
@@ -2443,47 +2940,106 @@ namespace System.Windows.Forms {
                        }
 
                        if (type == DataFormats.GetFormat(DataFormats.Rtf).Id) {
-                               hmem = Marshal.StringToHGlobalAnsi((string)obj);
-                               Win32SetClipboardData((uint)type, hmem);
-                               return;
+                               data = StringToAnsi ((string)obj);
                        } else switch((ClipboardFormats)type) {
                                case ClipboardFormats.CF_UNICODETEXT: {
-                                       hmem = Marshal.StringToHGlobalUni((string)obj);
-                                       Win32SetClipboardData((uint)type, hmem);
-                                       return;
+                                       data = StringToUnicode ((string)obj);
+                                       break;
                                }
 
                                case ClipboardFormats.CF_TEXT: {
-                                       hmem = Marshal.StringToHGlobalAnsi((string)obj);
-                                       Win32SetClipboardData((uint)type, hmem);
-                                       return;
+                                       data = StringToAnsi ((string)obj);
+                                       break;
                                }
 
                                case ClipboardFormats.CF_BITMAP:
                                case ClipboardFormats.CF_DIB: {
-                                       data = ImageToDIB((Image)obj);
-
-                                       hmem = Win32GlobalAlloc(GAllocFlags.GMEM_MOVEABLE | GAllocFlags.GMEM_DDESHARE, data.Length);
-                                       hmem_ptr = Win32GlobalLock(hmem);
-                                       Marshal.Copy(data, 0, hmem_ptr, data.Length);
-                                       Win32GlobalUnlock(hmem);
-                                       Win32SetClipboardData((uint)ClipboardFormats.CF_DIB, hmem);
-                                       return;
+                                       data = ImageToDIB ((Image)obj);
+                                       type = (int)ClipboardFormats.CF_DIB;
+                                       break;
                                }
 
                                default: {
-                                       if (converter != null && converter(ref type, obj, out data)) {
-                                               hmem = Win32GlobalAlloc(GAllocFlags.GMEM_MOVEABLE | GAllocFlags.GMEM_DDESHARE, data.Length);
-                                               hmem_ptr = Win32GlobalLock(hmem);
-                                               Marshal.Copy(data, 0, hmem_ptr, data.Length);
-                                               Win32GlobalUnlock(hmem);
-                                               Win32SetClipboardData((uint)type, hmem);
+                                       if (converter != null && !converter(ref type, obj, out data)) {
+                                               data = null; // ensure that a failed conversion leaves null.
                                        }
-                                       return;
+                                       break;
                                }
                        }
+                       if (data != null) {
+                               SetClipboardData ((uint)type, data);
+                       }
+               }
+
+               internal static byte[] StringToUnicode (string text)
+               {
+                       return Encoding.Unicode.GetBytes (text + "\0");
+               }
+
+               internal static byte[] StringToAnsi (string text)
+               {
+                       // FIXME, follow the behaviour of the previous code using UTF-8,
+                       // but this should be 'ANSI' on Windows, i.e. the current code page.
+                       // Does Encoding.Default work on Windows?
+                       return Encoding.UTF8.GetBytes (text + "\0");
+               }
+
+               private void SetClipboardData (uint type, byte[] data)
+               {
+                       if (data.Length == 0)
+                               // Shouldn't call Win32SetClipboard with NULL, as, from MSDN:
+                               // "This parameter can be NULL, indicating that the window provides data 
+                               //  in the specified clipboard format (renders the format) upon request."
+                               // and I don't think we support that...
+                               // Note this is unrelated to the fact that passing a null obj to 
+                               // ClipboardStore is actually a request to empty the clipboard!
+                               return;
+                       IntPtr hmem = CopyToMoveableMemory (data);
+                       if (hmem == IntPtr.Zero)
+                               // As above, should not call with null.
+                               // (Not that CopyToMoveableMemory should ever return null!)
+                               throw new ExternalException ("CopyToMoveableMemory failed.");
+                       if (Win32SetClipboardData (type, hmem) == IntPtr.Zero)
+                               throw new ExternalException ("Win32SetClipboardData");
+               }
+
+               /// <summary>
+               /// Creates a memory block with GlobalAlloc(GMEM_MOVEABLE), copies the data 
+               /// into it, and returns the handle to the memory.
+               /// </summary>
+               /// -
+               /// <param name="data">The data.  Must not be null or zero-length &#x2014; 
+               /// see the exception notes.</param>
+               /// -
+               /// <returns>The *handle* to the allocated GMEM_MOVEABLE block.</returns>
+               /// -
+               /// <exception cref="T:System.ArgumentException">The data was null or zero 
+               /// length.  This is disallowed since a zero length allocation can't be made
+               /// </exception>
+               /// <exception cref="T:System.ComponentModel.Win32Exception">The allocation, 
+               /// or locking (handle->pointer) failed.
+               /// Either out of memory or the handle table is full (256 max currently).
+               /// Note Win32Exception is a subclass of ExternalException so this is OK in 
+               /// the documented Clipboard interface.
+               /// </exception>
+               internal static IntPtr CopyToMoveableMemory (byte[] data)
+               {
+                       if (data == null || data.Length == 0)
+                               // detect this before GlobalAlloc does.
+                               throw new ArgumentException ("Can't create a zero length memory block.");
+
+                       IntPtr hmem = Win32GlobalAlloc (GAllocFlags.GMEM_MOVEABLE | GAllocFlags.GMEM_DDESHARE, data.Length);
+                       if (hmem == IntPtr.Zero)
+                               throw new Win32Exception ();
+                       IntPtr hmem_ptr = Win32GlobalLock (hmem);
+                       if (hmem_ptr == IntPtr.Zero) // If the allocation was valid this shouldn't occur.
+                               throw new Win32Exception ();
+                       Marshal.Copy (data, 0, hmem_ptr, data.Length);
+                       Win32GlobalUnlock (hmem);
+                       return hmem;
                }
 
+
                internal override void SetAllowDrop(IntPtr hwnd, bool allowed) {
                        if (allowed) {
                                Win32DnD.RegisterDropTarget(hwnd);
@@ -2770,6 +3326,11 @@ namespace System.Windows.Forms {
                        Win32DeleteDC (wb.hdc);
                }
 
+               internal override void SetForegroundWindow (IntPtr handle)
+               {
+                       Win32SetForegroundWindow(handle);
+               }
+
                internal override event EventHandler Idle;
                #endregion      // Public Static Methods
 
@@ -2778,7 +3339,7 @@ namespace System.Windows.Forms {
                private extern static uint Win32GetLastError();
 
                [DllImport ("user32.dll", EntryPoint="CreateWindowExW", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.StdCall)]
-               internal extern static IntPtr Win32CreateWindow(uint dwExStyle, string lpClassName, string lpWindowName, uint dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lParam);
+               internal extern static IntPtr Win32CreateWindow(WindowExStyles dwExStyle, string lpClassName, string lpWindowName, WindowStyles dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lParam);
 
                [DllImport ("user32.dll", EntryPoint="DestroyWindow", CallingConvention=CallingConvention.StdCall)]
                internal extern static bool Win32DestroyWindow(IntPtr hWnd);
@@ -2831,6 +3392,9 @@ namespace System.Windows.Forms {
                [DllImport ("user32.dll", EntryPoint="DestroyCursor", CallingConvention=CallingConvention.StdCall)]
                private extern static bool Win32DestroyCursor(IntPtr hCursor);
 
+               [DllImport ("user32.dll", EntryPoint = "DrawIcon", CallingConvention = CallingConvention.StdCall)]
+               private extern static bool Win32DrawIcon (IntPtr hDC, int X, int Y, IntPtr hIcon);
+               
                [DllImport ("user32.dll", EntryPoint="DefWindowProcW", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.StdCall)]
                private extern static IntPtr Win32DefWindowProc(IntPtr hWnd, Msg Msg, IntPtr wParam, IntPtr lParam);
 
@@ -2849,6 +3413,9 @@ namespace System.Windows.Forms {
                [DllImport ("user32.dll", EntryPoint="BeginPaint", CallingConvention=CallingConvention.StdCall)]
                private extern static IntPtr Win32BeginPaint(IntPtr hWnd, ref PAINTSTRUCT ps);
 
+               [DllImport ("user32.dll", EntryPoint = "ValidateRect", CallingConvention = CallingConvention.StdCall)]
+               private extern static IntPtr Win32ValidateRect (IntPtr hWnd, ref RECT rect);
+               
                [DllImport ("user32.dll", EntryPoint="EndPaint", CallingConvention=CallingConvention.StdCall)]
                private extern static bool Win32EndPaint(IntPtr hWnd, ref PAINTSTRUCT ps);
 
@@ -2891,9 +3458,14 @@ namespace System.Windows.Forms {
                [DllImport ("user32.dll", EntryPoint="ClientToScreen", CallingConvention=CallingConvention.StdCall)]
                private extern static bool Win32ClientToScreen(IntPtr hWnd, ref POINT pt);
 
+               // This function returns the parent OR THE OWNER!
+               // Use GetAncestor to only get the parent.
                [DllImport ("user32.dll", EntryPoint="GetParent", CallingConvention=CallingConvention.StdCall)]
                private extern static IntPtr Win32GetParent(IntPtr hWnd);
 
+               [DllImport ("user32.dll", EntryPoint = "GetAncestor", CallingConvention = CallingConvention.StdCall)]
+               private extern static IntPtr Win32GetAncestor (IntPtr hWnd, AncestorType flags);
+
                [DllImport ("user32.dll", EntryPoint="SetActiveWindow", CallingConvention=CallingConvention.StdCall)]
                private extern static IntPtr Win32SetActiveWindow(IntPtr hWnd);
 
@@ -2934,7 +3506,7 @@ namespace System.Windows.Forms {
                private extern static uint Win32GetLayeredWindowAttributes (IntPtr hwnd, out COLORREF pcrKey, out byte pbAlpha, out LayeredWindowAttributes pwdFlags);
 
                [DllImport ("gdi32.dll", EntryPoint="DeleteObject", CallingConvention=CallingConvention.StdCall)]
-               private extern static bool Win32DeleteObject(IntPtr o);
+               public extern static bool Win32DeleteObject(IntPtr o);
 
                [DllImport ("user32.dll", EntryPoint="GetKeyState", CallingConvention=CallingConvention.StdCall)]
                private extern static short Win32GetKeyState(VirtualKeys nVirtKey);
@@ -3041,8 +3613,14 @@ namespace System.Windows.Forms {
                //[DllImport ("user32.dll", EntryPoint="SystemParametersInfoW", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.StdCall)]
                //private extern static bool Win32SystemParametersInfo(SPIAction uiAction, uint uiParam, ref uint value, uint fWinIni);
 
-               [DllImport ("user32.dll", EntryPoint="SystemParametersInfoW", CharSet=CharSet.Unicode, CallingConvention=CallingConvention.StdCall)]
-               private extern static bool Win32SystemParametersInfo(SPIAction uiAction, uint uiParam, ref int value, uint fWinIni);
+               [DllImport ("user32.dll", EntryPoint = "SystemParametersInfoW", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
+               private extern static bool Win32SystemParametersInfo (SPIAction uiAction, uint uiParam, ref int value, uint fWinIni);
+
+               [DllImport ("user32.dll", EntryPoint = "SystemParametersInfoW", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
+               private extern static bool Win32SystemParametersInfo (SPIAction uiAction, uint uiParam, ref bool value, uint fWinIni);
+
+               [DllImport ("user32.dll", EntryPoint = "SystemParametersInfoW", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
+               private extern static bool Win32SystemParametersInfo (SPIAction uiAction, uint uiParam, ref ANIMATIONINFO value, uint fWinIni);
 
                [DllImport ("user32.dll", EntryPoint="OpenClipboard", CallingConvention=CallingConvention.StdCall)]
                private extern static bool Win32OpenClipboard(IntPtr hwnd);
@@ -3119,6 +3697,9 @@ namespace System.Windows.Forms {
                [DllImport ("winmm.dll", EntryPoint="PlaySoundW", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Unicode)]
                internal extern static IntPtr Win32PlaySound(string pszSound, IntPtr hmod, SndFlags fdwSound);
 
+               [DllImport ("user32.dll", EntryPoint="GetDoubleClickTime", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Unicode)]
+               private extern static int Win32GetDoubleClickTime ();
+
                [DllImport ("user32.dll", EntryPoint="SetWindowRgn", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Unicode)]
                internal extern static int Win32SetWindowRgn(IntPtr hWnd, IntPtr hRgn, bool redraw);
 
@@ -3143,6 +3724,15 @@ namespace System.Windows.Forms {
 
                [DllImport ("gdi32.dll", EntryPoint="CreateCompatibleBitmap", CallingConvention=CallingConvention.StdCall)]
                internal static extern IntPtr Win32CreateCompatibleBitmap (IntPtr hdc, int nWidth, int nHeight);
+
+               [DllImport ("kernel32.dll", EntryPoint = "GetSystemPowerStatus", CallingConvention = CallingConvention.StdCall)]
+               internal static extern Boolean Win32GetSystemPowerStatus (SYSTEMPOWERSTATUS sps);
+
+               [DllImport ("user32.dll", EntryPoint = "GetIconInfo", CallingConvention = CallingConvention.StdCall)]
+               internal static extern bool Win32GetIconInfo (IntPtr hIcon, out ICONINFO piconinfo);
+
+               [DllImport ("user32.dll", EntryPoint="SetForegroundWindow", CallingConvention=CallingConvention.StdCall)]
+               extern static bool Win32SetForegroundWindow(IntPtr hWnd);
                #endregion
        }
 }