curse you, svn, curse youuuuuuuuu
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / Control.cs
index e40a77eb630b394880e1038f9da4184c8b017e1b..b393396fd6ee66c043d269e216904f08ae3dcd70 100644 (file)
@@ -69,11 +69,11 @@ namespace System.Windows.Forms
                internal bool                   is_visible;             // true if control is visible
                internal bool                   is_entered;             // is the mouse inside the control?
                internal bool                   is_enabled;             // true if control is enabled (usable/not grayed out)
-               internal bool                   is_selected;            // true if control is selected
                internal bool                   is_accessible;          // true if the control is visible to accessibility applications
                internal bool                   is_captured;            // tracks if the control has captured the mouse
                internal bool                   is_toplevel;            // tracks if the control is a toplevel window
                internal bool                   is_recreating;          // tracks if the handle for the control is being recreated
+               internal ArrayList              children_to_recreate;   // keep track of the children which need to be recreated
                internal bool                   causes_validation;      // tracks if validation is executed on changes
                internal int                    tab_index;              // position in tab order of siblings
                internal bool                   tab_stop = true;        // is the control a tab stop?
@@ -106,7 +106,7 @@ namespace System.Windows.Forms
                internal int                    dist_bottom;            // distance to the bottom border of the parent
 
                // to be categorized...
-               static internal ArrayList       controls = new ArrayList();             // All of the application's controls, in a flat list
+               static internal ArrayList       controls = new ArrayList();  // All of the application's controls, in a flat list
                internal ControlCollection      child_controls;         // our children
                internal Control                parent;                 // our parent control
                internal AccessibleObject       accessibility_object;   // object that contains accessibility information about our control
@@ -118,7 +118,7 @@ namespace System.Windows.Forms
                private Graphics                dc_mem;                 // Graphics context for double buffering
                private GraphicsState           dc_state;               // Pristine graphics context to reset after paint code alters dc_mem
                private Bitmap                  bmp_mem;                // Bitmap for double buffering control
-               private bool                    needs_redraw = true;
+               private Region                  invalid_region;
 
                private ControlBindingsCollection data_bindings;
 
@@ -126,6 +126,11 @@ namespace System.Windows.Forms
                internal bool                   use_compatible_text_rendering;
                static internal bool            verify_thread_handle;
                private Padding                 padding;
+               private Size                    maximum_size;
+               private Size                    minimum_size;
+               private Size                    preferred_size;
+               private Padding                 margin;
+               internal Layout.LayoutEngine    layout_engine;
 #endif
 
                #endregion      // Local Variables
@@ -352,6 +357,10 @@ namespace System.Windows.Forms
                        {
                                if (impl_list == null)
                                        impl_list = new ArrayList ();
+
+                               if (AllContains (control))
+                                       return;
+
                                all_controls = null;
                                impl_list.Add (control);
 
@@ -398,7 +407,7 @@ namespace System.Windows.Forms
 
                                // MS sends remove events in reverse order
                                while (list.Count > 0) {
-                                       RemoveAt(list.Count - 1);
+                                       Remove((Control)list[list.Count - 1]);
                                }
                        }
 
@@ -487,14 +496,16 @@ namespace System.Windows.Forms
                                if (all_controls != null)
                                        return all_controls;
 
-                               if (impl_list == null)
-                                       return (Control []) list.ToArray (typeof (Control));
+                               if (impl_list == null) {
+                                       all_controls = (Control []) list.ToArray (typeof (Control));
+                                       return all_controls;
+                               }
                                
-                               Control [] res = new Control [list.Count + impl_list.Count];
-                               impl_list.CopyTo (res);
-                               list.CopyTo (res, impl_list.Count);
+                               all_controls = new Control [list.Count + impl_list.Count];
+                               impl_list.CopyTo (all_controls);
+                               list.CopyTo (all_controls, impl_list.Count);
 
-                               return res;
+                               return all_controls;
                        }
 
                        public override int GetHashCode() {
@@ -506,10 +517,10 @@ namespace System.Windows.Forms
                        }
 
                        public virtual void Remove(Control value) {
-                               all_controls = null;
-
                                owner.PerformLayout(value, "Parent");
                                owner.OnControlRemoved(new ControlEventArgs(value));
+
+                               all_controls = null;
                                list.Remove(value);
 
                                value.ChangeParent(null);
@@ -548,6 +559,7 @@ namespace System.Windows.Forms
                                        return;
                                }
 
+                               all_controls = null;
                                list.RemoveAt(old_index);
 
                                if (newIndex>list.Count) {
@@ -574,7 +586,16 @@ namespace System.Windows.Forms
                                                throw new ArgumentException("Object of type Control required", "value");
                                        }
 
-                                       list[index]=(Control)value;
+                                       all_controls = null;
+                                       Control ctrl = (Control) value;
+                                       list[index]= ctrl;
+
+                                       ctrl.ChangeParent(owner);
+
+                                       ctrl.InitLayout();
+
+                                       owner.UpdateChildrenZOrder();
+                                       owner.PerformLayout(ctrl, "Parent");
                                }
                        }
 
@@ -681,6 +702,11 @@ namespace System.Windows.Forms
 #if NET_2_0
                        use_compatible_text_rendering = Application.use_compatible_text_rendering;
                        padding = new Padding(0);
+                       maximum_size = new Size();
+                       minimum_size = new Size();
+                       preferred_size = new Size();
+                       margin = this.DefaultMargin;
+                       layout_engine = new Layout.DefaultLayout();
 #endif
 
                        control_style = ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | 
@@ -714,7 +740,7 @@ namespace System.Windows.Forms
                        bounds.Y=top;
                        bounds.Width=width;
                        bounds.Height=height;
-                       SetBoundsCore(left, top, width, height, BoundsSpecified.All);
+                       SetBounds(left, top, width, height, BoundsSpecified.All);
                        Text=text;
                }
 
@@ -727,7 +753,7 @@ namespace System.Windows.Forms
                        bounds.Y=top;
                        bounds.Width=width;
                        bounds.Height=height;
-                       SetBoundsCore(left, top, width, height, BoundsSpecified.All);
+                       SetBounds(left, top, width, height, BoundsSpecified.All);
                        Text=text;
                }
 
@@ -735,6 +761,8 @@ namespace System.Windows.Forms
 
                protected override void Dispose(bool disposing) {
                        if (disposing) {
+                               Capture = false;
+
                                if (dc_mem!=null) {
                                        dc_mem.Dispose();
                                        dc_mem=null;
@@ -745,6 +773,10 @@ namespace System.Windows.Forms
                                        bmp_mem=null;
                                }
 
+                               if (invalid_region!=null) {
+                                       invalid_region.Dispose();
+                                       invalid_region=null;
+                               }
                                if (this.InvokeRequired) {
                                        if (Application.MessageLoop) {
                                                this.BeginInvokeInternal(new MethodInvoker(DestroyHandle), null, true);
@@ -752,7 +784,9 @@ namespace System.Windows.Forms
                                        }
                                } else {
                                        DestroyHandle();
-                                       controls.Remove(this);
+                                       lock (Control.controls) {
+                                               Control.controls.Remove(this);
+                                       }
                                }
 
 
@@ -767,6 +801,7 @@ namespace System.Windows.Forms
                                }
                        }
                        is_disposed = true;
+                       is_visible = false;
                        base.Dispose(disposing);
                }
                #endregion      // Public Constructors
@@ -813,6 +848,7 @@ namespace System.Windows.Forms
                        result = new AsyncMethodResult ();
                        data = new AsyncMethodData ();
 
+                       data.Handle = window.Handle;
                        data.Method = method;
                        data.Args = args;
                        data.Result = result;
@@ -844,27 +880,34 @@ namespace System.Windows.Forms
                        XplatUI.ClientToScreen (Handle, ref x, ref y);
                }
 
-               private bool IsRecreating {
+               internal bool IsRecreating {
                        get {
                                if (is_recreating) {
                                        return true;
                                }
 
-                               if (parent != null) {
-                                       return parent.IsRecreating;
-                               }
-
-                               return false;
+                               return ParentWaitingOnRecreation(this);
                        }
                }
 
-               private bool ParentIsRecreating {
-                       get {
-                               if (parent != null) {
-                                       return parent.IsRecreating;
-                               }
-                               return false;
+               internal bool ChildNeedsRecreating (Control child)
+               {
+                       if (children_to_recreate != null && children_to_recreate.Contains (child))
+                                       return true;
+                       return ParentWaitingOnRecreation (this);
+               }
+
+               internal void RemoveChildFromRecreateList (Control child)
+               {
+                       if (children_to_recreate != null)
+                               children_to_recreate.Remove (child);
+               }
+
+               private bool ParentWaitingOnRecreation (Control c) {
+                       if (parent != null) {
+                               return parent.ChildNeedsRecreating (c);
                        }
+                       return false;
                }
 
                internal Graphics DeviceContext {
@@ -882,6 +925,12 @@ namespace System.Windows.Forms
                        dc_state = dc_mem.Save();
                }
 
+               private void ImageBufferNeedsRedraw () {
+                       if (invalid_region != null)
+                               invalid_region.Dispose();
+                       invalid_region = new Region (ClientRectangle);
+               }
+
                private Bitmap ImageBuffer {
                        get {
                                if (bmp_mem==null) {
@@ -908,7 +957,7 @@ namespace System.Windows.Forms
 
                        bmp_mem = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                        dc_mem = Graphics.FromImage (bmp_mem);
-                       needs_redraw = true;
+                       ImageBufferNeedsRedraw ();
                }
 
                internal void InvalidateBuffers ()
@@ -921,7 +970,7 @@ namespace System.Windows.Forms
 
                        dc_mem = null;
                        bmp_mem = null;
-                       needs_redraw = true;
+                       ImageBufferNeedsRedraw ();
                }
 
                internal static void SetChildColor(Control parent) {
@@ -937,17 +986,12 @@ namespace System.Windows.Forms
                }
 
                internal bool Select(Control control) {
-                       Control                 parent;
                        IContainerControl       container;
 
                        if (control == null) {
                                return false;
                        }
 
-                       parent = control.parent;
-
-                       control.is_selected = true;
-
                        container = GetContainerControl();
                        if (container != null) {
                                container.ActiveControl = control;
@@ -958,6 +1002,12 @@ namespace System.Windows.Forms
                        return true;
                }
 
+               internal void SelectChild (Control control)
+               {
+                       if (control.IsHandleCreated)
+                               XplatUI.SetFocus (control.window.Handle);
+               }
+
                internal virtual void DoDefaultAction() {
                        // Only here to be overriden by our actual controls; this is needed by the accessibility class
                }
@@ -1110,6 +1160,26 @@ namespace System.Windows.Forms
 
                }
 
+               internal void FireEnter ()
+               {
+                       OnEnter (EventArgs.Empty);
+               }
+
+               internal void FireLeave ()
+               {
+                       OnLeave (EventArgs.Empty);
+               }
+
+               internal void FireValidating (CancelEventArgs ce)
+               {
+                       OnValidating (ce);
+               }
+
+               internal void FireValidated ()
+               {
+                       OnValidated (EventArgs.Empty);
+               }
+
                internal virtual bool ProcessControlMnemonic(char charCode) {
                        return ProcessMnemonic(charCode);
                }
@@ -1211,25 +1281,31 @@ namespace System.Windows.Forms
 
                        if (start != null) {
                                found = FindFlatBackward(start.parent, start);
-                               if (found == null && start.parent != container) {
-                                       return start.parent;
+                               if (found == null) {
+                                       if (start.parent != container) {
+                                               return start.parent;
+                                       }
+                               } else {
+                                       return found;
                                }
                        }
                        if (found == null) {
                                found = FindFlatBackward(container, start);
                        }
 
-                       while ((found != null) && ((found is IContainerControl) || found.GetStyle(ControlStyles.ContainerControl))) {
-                               found = FindControlBackward(found, null);
-                               if (found != null) {
-                                       return found;
+                       if (container != start) {
+                               while ((found != null) && (!found.Contains(start)) && ((found is IContainerControl) || found.GetStyle(ControlStyles.ContainerControl))) {
+                                       found = FindControlBackward(found, null);
+                                       if (found != null) {
+                                               return found;
+                                       }
                                }
                        }
 
                        return found;
                }
 
-               private void HandleClick(int clicks, MouseEventArgs me) {
+               internal virtual void HandleClick(int clicks, MouseEventArgs me) {
                        if (GetStyle(ControlStyles.StandardClick)) {
                                if ((clicks > 1) && GetStyle(ControlStyles.StandardDoubleClick)) {
 #if !NET_2_0
@@ -1278,9 +1354,9 @@ namespace System.Windows.Forms
 
                        parent = new_parent;
 
-                       if (IsHandleCreated && (new_parent != null) && new_parent.IsHandleCreated) {
-                               XplatUI.SetParent(Handle, new_parent.Handle);
-                       }
+                       if (IsHandleCreated)
+                               XplatUI.SetParent(Handle,
+                                                 (new_parent == null || !new_parent.IsHandleCreated) ? IntPtr.Zero : new_parent.Handle);
 
                        OnParentChanged(EventArgs.Empty);
 
@@ -1488,7 +1564,7 @@ namespace System.Windows.Forms
 
                public virtual bool AutoSize {
                        get {
-                               Console.Error.WriteLine("Unimplemented: Control::get_AutoSize()");
+                               //Console.Error.WriteLine("Unimplemented: Control::get_AutoSize()");
                                return auto_size;
                        }
                        set {
@@ -1496,6 +1572,24 @@ namespace System.Windows.Forms
                                auto_size = value;
                        }
                }
+
+               public virtual Size MaximumSize {
+                       get {
+                               return maximum_size;
+                       }
+                       set {
+                               maximum_size = value;
+                       }
+               }
+
+               public virtual Size MinimumSize {
+                       get {
+                               return minimum_size;
+                       }
+                       set {
+                               minimum_size = value;
+                       }
+               }
 #endif // NET_2_0
 
                [DispId(-501)]
@@ -1518,10 +1612,12 @@ namespace System.Windows.Forms
                                        throw new ArgumentException("Transparent background colors are not supported on this control");
                                }
 
-                               background_color=value;
-                               SetChildColor(this);
-                               OnBackColorChanged(EventArgs.Empty);
-                               Invalidate();
+                               if (background_color != value) {
+                                       background_color=value;
+                                       SetChildColor(this);
+                                       OnBackColorChanged(EventArgs.Empty);
+                                       Invalidate();
+                               }
                        }
                }
 
@@ -1579,7 +1675,7 @@ namespace System.Windows.Forms
                        }
 
                        set {
-                               SetBoundsCore(value.Left, value.Top, value.Width, value.Height, BoundsSpecified.All);
+                               SetBounds(value.Left, value.Top, value.Width, value.Height, BoundsSpecified.All);
                        }
                }
 
@@ -1709,14 +1805,19 @@ namespace System.Windows.Forms
                [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
                public bool ContainsFocus {
                        get {
-                               if (this.Focused) {
-                                       return true;
-                               }
+                               IntPtr  focused_window;
 
-                               for (int i=0; i < child_controls.Count; i++) {
-                                       if (child_controls[i].ContainsFocus) {
+                               focused_window = XplatUI.GetFocus();
+                               if (IsHandleCreated) {
+                                       if (focused_window == Handle) {
                                                return true;
                                        }
+
+                                       for (int i=0; i < child_controls.Count; i++) {
+                                               if (child_controls[i].ContainsFocus) {
+                                                       return true;
+                                               }
+                                       }
                                }
                                return false;
                        }
@@ -1786,7 +1887,7 @@ namespace System.Windows.Forms
                                                                        if (parent != null) {
                                                                                XplatUI.SetCursor(window.Handle, parent.Cursor.handle);
                                                                        } else {
-                                                                               XplatUI.SetCursor(window.Handle, Cursors.def.handle);
+                                                                               XplatUI.SetCursor(window.Handle, Cursors.Default.handle);
                                                                        }
                                                                }
                                                        }
@@ -1870,21 +1971,15 @@ namespace System.Windows.Forms
                        }
 
                        set {
-                               if (is_enabled == value) {
+                               if (Enabled == value) {
+                                       is_enabled = value;
                                        return;
                                }
 
-                               if (IsHandleCreated) {
-                                       if (this is Form) {
-                                               if (((Form)this).context == null) {
-                                                       XplatUI.EnableWindow(window.Handle, value);
-                                               }
-                                       } else {
-                                               XplatUI.EnableWindow(window.Handle, value);
-                                       }
-                               }
                                is_enabled = value;
-                               Refresh();
+
+                               // FIXME - we need to switch focus to next control if we're disabling the focused control
+
                                OnEnabledChanged (EventArgs.Empty);                             
                        }
                }
@@ -1989,7 +2084,7 @@ namespace System.Windows.Forms
                        }
 
                        set {
-                               SetBoundsCore(bounds.X, bounds.Y, bounds.Width, value, BoundsSpecified.Height);
+                               SetBounds(bounds.X, bounds.Y, bounds.Width, value, BoundsSpecified.Height);
                        }
                }
 
@@ -2056,13 +2151,21 @@ namespace System.Windows.Forms
                public bool IsHandleCreated {
                        get {
                                if ((window != null) && (window.Handle != IntPtr.Zero)) {
-                                       return true;
+                                       Hwnd hwnd = Hwnd.ObjectFromHandle (window.Handle);
+                                       if (hwnd != null && !hwnd.zombie)
+                                               return true;
                                }
 
                                return false;
                        }
                }
 
+#if NET_2_0
+               public virtual Layout.LayoutEngine LayoutEngine {
+                       get { return this.layout_engine; }
+               } 
+#endif
+
                [EditorBrowsable(EditorBrowsableState.Always)]
                [Browsable(false)]
                [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
@@ -2072,7 +2175,7 @@ namespace System.Windows.Forms
                        }
 
                        set {
-                               SetBoundsCore(value, bounds.Y, bounds.Width, bounds.Height, BoundsSpecified.X);
+                               SetBounds(value, bounds.Y, bounds.Width, bounds.Height, BoundsSpecified.X);
                        }
                }
 
@@ -2084,10 +2187,18 @@ namespace System.Windows.Forms
                        }
 
                        set {
-                               SetBoundsCore(value.X, value.Y, bounds.Width, bounds.Height, BoundsSpecified.Location);
+                               SetBounds(value.X, value.Y, bounds.Width, bounds.Height, BoundsSpecified.Location);
                        }
                }
 
+#if NET_2_0
+               [Localizable (true)]
+               public Padding Margin {
+                       get { return this.margin; }
+                       set { this.margin = value; }
+               }
+#endif
+
                [Browsable(false)]
                public string Name {
                        get {
@@ -2127,6 +2238,7 @@ namespace System.Windows.Forms
                                if (parent!=value) {
                                        if (value==null) {
                                                parent.Controls.Remove(this);
+                                               parent = null;
                                                return;
                                        }
 
@@ -2249,7 +2361,7 @@ namespace System.Windows.Forms
                        }
 
                        set {
-                               SetBoundsCore(bounds.X, bounds.Y, value.Width, value.Height, BoundsSpecified.Size);
+                               SetBounds(bounds.X, bounds.Y, value.Width, value.Height, BoundsSpecified.Size);
                        }
                }
 
@@ -2321,6 +2433,10 @@ namespace System.Windows.Forms
                                if (text!=value) {
                                        text=value;
                                        if (IsHandleCreated) {
+                                               /* we need to call .SetWindowStyle here instead of just .Text
+                                                  because the presence/absence of Text (== "" or not) can cause
+                                                  other window style things to appear/disappear */
+                                               XplatUI.SetWindowStyle(window.Handle, CreateParams);
                                                XplatUI.Text(Handle, text);
                                        }
                                        OnTextChanged (EventArgs.Empty);
@@ -2337,7 +2453,7 @@ namespace System.Windows.Forms
                        }
 
                        set {
-                               SetBoundsCore(bounds.X, value, bounds.Width, bounds.Height, BoundsSpecified.Y);
+                               SetBounds(bounds.X, value, bounds.Width, bounds.Height, BoundsSpecified.Y);
                        }
                }
 
@@ -2383,7 +2499,7 @@ namespace System.Windows.Forms
                        }
 
                        set {
-                               SetBoundsCore(bounds.X, bounds.Y, value, bounds.Height, BoundsSpecified.Width);
+                               SetBounds(bounds.X, bounds.Y, value, bounds.Height, BoundsSpecified.Width);
                        }
                }
 
@@ -2484,6 +2600,12 @@ namespace System.Windows.Forms
                        }
                }
 
+#if NET_2_0
+               protected virtual Padding DefaultMargin {
+                       get { return new Padding (3); }
+               }
+#endif
+
                protected virtual Size DefaultSize {
                        get {
                                return new Size(0, 0);
@@ -2538,17 +2660,19 @@ namespace System.Windows.Forms
                #region Public Static Methods
                [EditorBrowsable(EditorBrowsableState.Advanced)]
                public static Control FromChildHandle(IntPtr handle) {
-                       IEnumerator control = Control.controls.GetEnumerator();
-
-                       while (control.MoveNext()) {
-                               if (((Control)control.Current).window.Handle == handle) {
-                                       // Found it
-                                       if (((Control)control.Current).Parent != null) {
-                                               return ((Control)control.Current).Parent;
+                       lock (Control.controls) {
+                               IEnumerator control = Control.controls.GetEnumerator();
+
+                               while (control.MoveNext()) {
+                                       if (((Control)control.Current).window.Handle == handle) {
+                                               // Found it
+                                               if (((Control)control.Current).Parent != null) {
+                                                       return ((Control)control.Current).Parent;
+                                               }
                                        }
                                }
+                               return null;
                        }
-                       return null;
                }
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
@@ -2620,6 +2744,8 @@ namespace System.Windows.Forms
                        if (parent != null) {
                                parent.child_controls.SetChildIndex(this, 0);
                                parent.Refresh();
+                       } else {
+                               XplatUI.SetZOrder(Handle, IntPtr.Zero, false, false);
                        }
                }
 
@@ -2634,6 +2760,9 @@ namespace System.Windows.Forms
                }
 
                public void CreateControl() {
+                       if (is_disposed) {
+                               throw new ObjectDisposedException(GetType().FullName.ToString());
+                       }
                        if (is_created) {
                                return;
                        }
@@ -2727,6 +2856,21 @@ namespace System.Windows.Forms
                                return null;
                        }
 
+                       // Special cases
+                       if (this == ctl) {
+                               if (!forward) {
+                                       return FindFlatBackward(ctl, null);
+                               }
+                       } else {
+                               if ((parent == null) && (ctl is IContainerControl) && ctl.GetStyle(ControlStyles.ContainerControl)) {
+                                       if (forward) {
+                                               return FindFlatForward(this, ctl);
+                                       } else {
+                                               return FindFlatBackward(this, ctl);
+                                       }
+                               }
+                       }
+
                        // If ctl is not contained by this, we start at the first child of this
                        if (!this.Contains(ctl)) {
                                ctl = null;
@@ -2741,6 +2885,12 @@ namespace System.Windows.Forms
                        return FindControlBackward(this, ctl);
                }
 
+#if NET_2_0
+               public virtual Size GetPreferredSize (Size proposedSize) {
+                       return preferred_size;
+               }
+#endif
+
                public void Hide() {
                        this.Visible = false;
                }
@@ -2835,11 +2985,16 @@ namespace System.Windows.Forms
 
                        // Perform all Dock and Anchor calculations
                        try {
+
+#if NET_2_0
+                       this.layout_engine.Layout(this, levent);
+#else          
+                               // This has been moved to Layout/DefaultLayout.cs for 2.0, please duplicate any changes/fixes there.
                                Control         child;
                                AnchorStyles    anchor;
                                Rectangle       space;
 
-                               space= DisplayRectangle;
+                               space = DisplayRectangle;
 
                                // Deal with docking; go through in reverse, MS docs say that lowest Z-order is closest to edge
                                Control [] controls = child_controls.GetAllControls ();
@@ -2887,12 +3042,13 @@ namespace System.Windows.Forms
                                for (int i = controls.Length - 1; i >= 0; i--) {
                                        child=controls[i];
 
-                                       if (child.Visible && (child.Dock == DockStyle.Fill)) {
+                                       //if (child.Visible && (child.Dock == DockStyle.Fill)) {
+                                       if (child.Dock == DockStyle.Fill) {
                                                child.SetBounds(space.Left, space.Top, space.Width, space.Height);
                                        }
                                }
 
-                               space=DisplayRectangle;
+                               space = DisplayRectangle;
 
                                for (int i=0; i < controls.Length; i++) {
                                        int left;
@@ -2953,6 +3109,7 @@ namespace System.Windows.Forms
 
                                        child.SetBounds(left, top, width, height);
                                }
+#endif
 
                                // Let everyone know
                                OnLayout(levent);
@@ -2983,6 +3140,10 @@ namespace System.Windows.Forms
                }
 
                public virtual bool PreProcessMessage(ref Message msg) {
+                       return InternalPreProcessMessage (ref msg);
+               }
+
+               internal virtual bool InternalPreProcessMessage (ref Message msg) {
                        Keys key_data;
 
                        if ((msg.Msg == (int)Msg.WM_KEYDOWN) || (msg.Msg == (int)Msg.WM_SYSKEYDOWN)) {
@@ -3001,10 +3162,8 @@ namespace System.Windows.Forms
                                if (IsInputChar((char)msg.WParam)) {
                                        return false;
                                }
+                               return ProcessDialogChar((char)msg.WParam);
                        } else if (msg.Msg == (int)Msg.WM_SYSCHAR) {
-                               if (IsInputChar((char)msg.WParam)) {
-                                       return false;
-                               }
                                return ProcessDialogChar((char)msg.WParam);
                        }
                        return false;
@@ -3033,7 +3192,7 @@ namespace System.Windows.Forms
 
                [EditorBrowsable(EditorBrowsableState.Never)]
                public virtual void ResetBackColor() {
-                       background_color = Color.Empty;
+                       BackColor = Color.Empty;
                }
 
                [EditorBrowsable(EditorBrowsableState.Never)]
@@ -3099,13 +3258,19 @@ namespace System.Windows.Forms
                        ScaleCore(dx, dy);
                }
 
+#if NET_2_0
+               public void Scale(SizeF factor) {
+                       ScaleCore(factor.Width, factor.Height);
+               }
+#endif
+
                public void Select() {
                        Select(false, false);
                }
 
                public bool SelectNextControl(Control ctl, bool forward, bool tabStopOnly, bool nested, bool wrap) {
                        Control c;
-                               
+
                        c = ctl;
                        do {
                                c = GetNextControl(c, forward);
@@ -3117,8 +3282,8 @@ namespace System.Windows.Forms
                                        break;
                                }
 
-                               if (c.CanSelect && ((c.parent == ctl.parent) || nested) && (c.tab_stop || !tabStopOnly)) {
-                                       Select(c);
+                               if (c.CanSelect && ((c.parent == this) || nested) && (c.tab_stop || !tabStopOnly)) {
+                                       c.Select (true, true);
                                        return true;
                                }
                        } while (c != ctl);     // If we wrap back to ourselves we stop
@@ -3133,11 +3298,30 @@ namespace System.Windows.Forms
                }
 
                public void SetBounds(int x, int y, int width, int height) {
-                       SetBoundsCore(x, y, width, height, BoundsSpecified.All);
+                       SetBounds(x, y, width, height, BoundsSpecified.All);
                }
 
                public void SetBounds(int x, int y, int width, int height, BoundsSpecified specified) {
+                       if ((specified & BoundsSpecified.X) != BoundsSpecified.X) {
+                               x = Left;
+                       }
+
+                       if ((specified & BoundsSpecified.Y) != BoundsSpecified.Y) {
+                               y = Top;
+                       }
+
+                       if ((specified & BoundsSpecified.Width) != BoundsSpecified.Width) {
+                               width = Width;
+                       }
+
+                       if ((specified & BoundsSpecified.Height) != BoundsSpecified.Height) {
+                               height = Height;
+                       }
+
                        SetBoundsCore(x, y, width, height, specified);
+                       if (parent != null) {
+                               parent.PerformLayout(this, "Bounds");
+                       }
                }
 
                public void Show() {
@@ -3153,7 +3337,6 @@ namespace System.Windows.Forms
                }
 
                public void Update() {
-                       needs_redraw = true;
                        if (IsHandleCreated) {
                                XplatUI.UpdateWindow(window.Handle);
                        }
@@ -3180,7 +3363,7 @@ namespace System.Windows.Forms
                [EditorBrowsable(EditorBrowsableState.Advanced)]
                protected virtual void CreateHandle() {
                        if (IsDisposed) {
-                               throw new ObjectDisposedException(Name);
+                               throw new ObjectDisposedException(GetType().FullName.ToString());
                        }
 
                        if (IsHandleCreated && !is_recreating) {
@@ -3190,8 +3373,10 @@ namespace System.Windows.Forms
                        window.CreateHandle(CreateParams);
 
                        if (window.Handle != IntPtr.Zero) {
-                               if (!controls.Contains(window.Handle)) {
-                                       controls.Add(this);
+                               lock (Control.controls) {
+                                       if (!Control.controls.Contains(window.Handle)) {
+                                               Control.controls.Add(this);
+                                       }
                                }
 
                                creator_thread = Thread.CurrentThread;
@@ -3228,7 +3413,6 @@ namespace System.Windows.Forms
 
                                OnHandleCreated(EventArgs.Empty);
                        }
-
                }
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
@@ -3348,6 +3532,9 @@ namespace System.Windows.Forms
 
                                        key_press_event = new KeyPressEventArgs((char)msg.WParam);
                                        OnKeyPress(key_press_event);
+#if NET_2_0
+                                       msg.WParam = (IntPtr)key_press_event.KeyChar;
+#endif
                                        return key_press_event.Handled;
                                }
 
@@ -3407,6 +3594,8 @@ namespace System.Windows.Forms
                        is_recreating=true;
 
                        if (IsHandleCreated) {
+                               children_to_recreate = new ArrayList();
+                               children_to_recreate.AddRange (child_controls.GetAllControls ());
                                DestroyHandle();
                                // WM_DESTROY will CreateHandle for us
                        } else {
@@ -3415,6 +3604,8 @@ namespace System.Windows.Forms
                                } else {
                                        CreateHandle();
                                }
+                               if (parent != null)
+                                       parent.RemoveChildFromRecreateList (this);
                        }
 
                        is_recreating = false;
@@ -3524,7 +3715,7 @@ namespace System.Windows.Forms
                                size.Height = (int)(size.Height * dy);
                        }
 
-                       SetBoundsCore(location.X, location.Y, size.Width, size.Height, BoundsSpecified.All);
+                       SetBounds(location.X, location.Y, size.Width, size.Height, BoundsSpecified.All);
 
                        /* Now scale our children */
                        Control [] controls = child_controls.GetAllControls ();
@@ -3537,32 +3728,15 @@ namespace System.Windows.Forms
 
                protected virtual void Select(bool directed, bool forward) {
                        IContainerControl       container;
-
+                       
                        container = GetContainerControl();
-                       if (container != null) {
+                       if (container != null)
                                container.ActiveControl = this;
-                       }
                }
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
                protected virtual void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
                        // SetBoundsCore updates the Win32 control itself. UpdateBounds updates the controls variables and fires events, I'm guessing - pdb
-                       if ((specified & BoundsSpecified.X) != BoundsSpecified.X) {
-                               x = Left;
-                       }
-
-                       if ((specified & BoundsSpecified.Y) != BoundsSpecified.Y) {
-                               y = Top;
-                       }
-
-                       if ((specified & BoundsSpecified.Width) != BoundsSpecified.Width) {
-                               width = Width;
-                       }
-
-                       if ((specified & BoundsSpecified.Height) != BoundsSpecified.Height) {
-                               height = Height;
-                       }
-
                        if (IsHandleCreated) {
                                XplatUI.SetWindowPos(Handle, x, y, width, height);
                        }
@@ -3586,7 +3760,7 @@ namespace System.Windows.Forms
                                return;
                        }
 
-                       SetBoundsCore(bounds.X, bounds.Y, WindowRect.Width, WindowRect.Height, BoundsSpecified.Size);
+                       SetBounds(bounds.X, bounds.Y, WindowRect.Width, WindowRect.Height, BoundsSpecified.Size);
                }
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
@@ -3619,7 +3793,7 @@ namespace System.Windows.Forms
 
                protected virtual void SetVisibleCore(bool value) {
                        if (value!=is_visible) {
-                               if (value && !is_created) {
+                               if (value && (window.Handle == IntPtr.Zero) || !is_created) {
                                        CreateControl();
                                }
 
@@ -3636,7 +3810,7 @@ namespace System.Windows.Forms
 
                                OnVisibleChanged(EventArgs.Empty);
 
-                               if (value == false && parent != null) {
+                               if (value == false && parent != null && Focused) {
                                        Control container;
 
                                        // Need to start at parent, GetContainerControl might return ourselves if we're a container
@@ -3774,7 +3948,7 @@ namespace System.Windows.Forms
                                        OnHandleDestroyed(EventArgs.Empty);
                                        window.InvalidateHandle();
 
-                                       if (ParentIsRecreating) {
+                                       if (ParentWaitingOnRecreation (this)) {
                                                RecreateHandle();
                                        } else if (is_recreating) {
                                                CreateHandle();
@@ -3806,7 +3980,7 @@ namespace System.Windows.Forms
                                                return;
                                        }
 
-                                       if (!needs_redraw) {
+                                       if (invalid_region != null && !invalid_region.IsVisible (paint_event.ClipRectangle)) {
                                                // Just blit the previous image
                                                paint_event.Graphics.DrawImage (ImageBuffer, paint_event.ClipRectangle, paint_event.ClipRectangle, GraphicsUnit.Pixel);
                                                XplatUI.PaintEventEnd(Handle, true);
@@ -3814,6 +3988,7 @@ namespace System.Windows.Forms
                                        }
 
                                        Graphics dc = null;
+                                       Rectangle old_clip_rect = Rectangle.Empty;
                                        if (ThemeEngine.Current.DoubleBufferingSupported) {
                                                if ((control_style & ControlStyles.DoubleBuffer) != 0) {
                                                        dc = paint_event.SetGraphics (DeviceContext);
@@ -3835,9 +4010,10 @@ namespace System.Windows.Forms
 
                                        if (ThemeEngine.Current.DoubleBufferingSupported)
                                                if ((control_style & ControlStyles.DoubleBuffer) != 0) {
+                                                       paint_event.SetClipRectangle (old_clip_rect);
                                                        dc.DrawImage (ImageBuffer, paint_event.ClipRectangle, paint_event.ClipRectangle, GraphicsUnit.Pixel);
                                                        paint_event.SetGraphics (dc);
-                                                       needs_redraw = false;
+                                                       invalid_region.Exclude (paint_event.ClipRectangle);
                                                }
 
                                        XplatUI.PaintEventEnd(Handle, true);
@@ -3879,8 +4055,8 @@ namespace System.Windows.Forms
                                }
                                        
                                case Msg.WM_LBUTTONDOWN: {
-                                       if (CanSelect && !is_selected) {
-                                               Select(this);
+                                       if (CanSelect) {
+                                               Select (true, true);
                                        }
                                        InternalCapture = true;
                                        OnMouseDown (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), 
@@ -4081,32 +4257,15 @@ namespace System.Windows.Forms
                                }
 
                                case Msg.WM_KILLFOCUS: {
-                                       OnLeave(EventArgs.Empty);
-                                       if (CausesValidation) {
-                                               CancelEventArgs e;
-                                               e = new CancelEventArgs(false);
-
-                                               OnValidating(e);
-
-                                               if (e.Cancel) {
-                                                       Focus();
-                                                       return;
-                                               }
-
-                                               OnValidated(EventArgs.Empty);
-                                       }
-
                                        this.has_focus = false;
-                                       this.is_selected = false;
-                                       OnLostFocus(EventArgs.Empty);
+                                       OnLostFocusInternal (EventArgs.Empty);
                                        return;
                                }
 
                                case Msg.WM_SETFOCUS: {
                                        if (!has_focus) {
-                                               OnEnter(EventArgs.Empty);
                                                this.has_focus = true;
-                                               OnGotFocus(EventArgs.Empty);
+                                               OnGotFocusInternal (EventArgs.Empty);
                                        }
                                        return;
                                }
@@ -4233,8 +4392,24 @@ namespace System.Windows.Forms
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
                protected virtual void OnEnabledChanged(EventArgs e) {
-                       if (EnabledChanged!=null) EnabledChanged(this, e);
-                       for (int i=0; i<child_controls.Count; i++) child_controls[i].OnParentEnabledChanged(e);
+                       if (IsHandleCreated) {
+                               if (this is Form) {
+                                       if (((Form)this).context == null) {
+                                               XplatUI.EnableWindow(window.Handle, Enabled);
+                                       }
+                               } else {
+                                       XplatUI.EnableWindow(window.Handle, Enabled);
+                               }
+                               Refresh();
+                       }
+
+                       if (EnabledChanged != null) {
+                               EnabledChanged(this, e);
+                       }
+
+                       for (int i=0; i<child_controls.Count; i++) {
+                               child_controls[i].OnParentEnabledChanged(e);
+                       }
                }
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
@@ -4285,7 +4460,20 @@ namespace System.Windows.Forms
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
                protected virtual void OnInvalidated(InvalidateEventArgs e) {
-                       needs_redraw = true;
+                       // should this block be here?  seems like it
+                       // would be more at home in
+                       // NotifyInvalidated..
+                       if (e.InvalidRect == ClientRectangle) {
+                               ImageBufferNeedsRedraw ();
+                       }
+                       else {
+                               // we need this Inflate call here so
+                               // that the border of the rectangle is
+                               // considered Visible (the
+                               // invalid_region.IsVisible call) in
+                               // the WM_PAINT handling below.
+                               invalid_region.Union (Rectangle.Inflate(e.InvalidRect, 1,1));
+                       }
                        if (Invalidated!=null) Invalidated(this, e);
                }
 
@@ -4383,6 +4571,16 @@ namespace System.Windows.Forms
                        // Override me
                }
 
+               internal virtual void OnGotFocusInternal (EventArgs e)
+               {
+                       OnGotFocus (e);
+               }
+
+               internal virtual void OnLostFocusInternal (EventArgs e)
+               {
+                       OnLostFocus (e);
+               }
+
                [EditorBrowsable(EditorBrowsableState.Advanced)]
                protected virtual void OnPaintBackground(PaintEventArgs pevent) {
                        PaintControlBackground (pevent);
@@ -4419,12 +4617,8 @@ namespace System.Windows.Forms
 
                [EditorBrowsable(EditorBrowsableState.Advanced)]
                protected virtual void OnParentEnabledChanged(EventArgs e) {
-                       if (is_enabled != Parent.is_enabled) {
-                               is_enabled=Parent.is_enabled;
-                               Invalidate();
-                               if (EnabledChanged != null) {
-                                       EnabledChanged(this, e);
-                               }
+                       if (is_enabled) {
+                               OnEnabledChanged(e);
                        }
                }
 
@@ -4532,8 +4726,6 @@ namespace System.Windows.Forms
                                }
                        }
 
-                       needs_redraw = true;
-                       
                        if (VisibleChanged!=null) VisibleChanged(this, e);
 
                        // We need to tell our kids