Refactored, cleaned up
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / MdiClient.cs
index 438a253725e1e51eca6d82e9487a35695d219a8f..2a6ef608e7170c5ab4f41b08bbdf39b2f8900673 100644 (file)
@@ -32,6 +32,8 @@ using System.Drawing;
 using System.Runtime.InteropServices;
 
 namespace System.Windows.Forms {
+       [ComVisible (true)]
+       [ClassInterface(ClassInterfaceType.AutoDispatch)]
        [DesignTimeVisible(false)]
        [ToolboxItem(false)]
        public sealed class MdiClient : Control {
@@ -45,23 +47,22 @@ namespace System.Windows.Forms {
                private bool lock_sizing;
                private bool initializing_scrollbars;
                private int prev_bottom;
-               private LayoutEventHandler initial_layout_handler;
                private bool setting_windowstates = false;
                internal ArrayList mdi_child_list;
                private string form_text;
                private bool setting_form_text;
-               internal ArrayList original_order = new ArrayList (); // The order the child forms are added (used by the main menu to show the window menu)
+               private Form active_child;
 
                #endregion      // Local Variables
 
                #region Public Classes
+               [ComVisible (false)]
                public new class ControlCollection : Control.ControlCollection {
 
                        private MdiClient owner;
                        
                        public ControlCollection(MdiClient owner) : base(owner) {
                                this.owner = owner;
-                               owner.mdi_child_list = new ArrayList ();
                        }
 
                        public override void Add(Control value) {
@@ -95,12 +96,30 @@ namespace System.Windows.Forms {
                #region Public Constructors
                public MdiClient()
                {
+                       mdi_child_list = new ArrayList ();
                        BackColor = SystemColors.AppWorkspace;
                        Dock = DockStyle.Fill;
                        SetStyle (ControlStyles.Selectable, false);
                }
                #endregion      // Public Constructors
 
+               internal void SendFocusToActiveChild ()
+               {
+                       Form active = this.ActiveMdiChild;
+                       if (active == null) {
+                               ParentForm.SendControlFocus (this);
+                       } else {
+                               active.SendControlFocus (active);
+                               ParentForm.ActiveControl = active;
+                       }
+               }
+
+               internal bool HorizontalScrollbarVisible {
+                       get { return hbar != null && hbar.Visible; }
+               }
+               internal bool VerticalScrollbarVisible {
+                       get { return vbar != null && vbar.Visible; }
+               }
 
                internal void SetParentText(bool text_changed)
                {
@@ -146,42 +165,15 @@ namespace System.Windows.Forms {
                }
 
                protected override void WndProc(ref Message m) {
-                       /*
-                       switch ((Msg) m.Msg) {
-                               case Msg.WM_PAINT: {                            
-                                       Console.WriteLine ("ignoring paint");
-                                       return;
-                               }
-                       }
-                       */
                        switch ((Msg)m.Msg) {
-                       case Msg.WM_NCCALCSIZE:
-                               XplatUIWin32.NCCALCSIZE_PARAMS  ncp;
-
-                               if (m.WParam == (IntPtr) 1) {
-                                       ncp = (XplatUIWin32.NCCALCSIZE_PARAMS) Marshal.PtrToStructure (m.LParam,
-                                                       typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
-
-                                       int bw = 2;
-
-                                       ncp.rgrc1.top += bw;
-                                       ncp.rgrc1.bottom -= bw;
-                                       ncp.rgrc1.left += bw;
-                                       ncp.rgrc1.right -= bw;
-                                       
-                                       Marshal.StructureToPtr (ncp, m.LParam, true);
-                               }
-
-                               break;
-
                        case Msg.WM_NCPAINT:
-                               PaintEventArgs pe = XplatUI.PaintEventStart (Handle, false);
+                               PaintEventArgs pe = XplatUI.PaintEventStart (ref m, Handle, false);
 
                                Rectangle clip;
                                clip = new Rectangle (0, 0, Width, Height);
 
                                ControlPaint.DrawBorder3D (pe.Graphics, clip, Border3DStyle.Sunken);
-                               XplatUI.PaintEventEnd (Handle, false);
+                               XplatUI.PaintEventEnd (ref m, Handle, false);
                                m.Result = IntPtr.Zero;
                                return ;
                        }
@@ -193,13 +185,22 @@ namespace System.Windows.Forms {
                {
                        base.OnResize (e);
 
-                       if (Parent != null)
+                       if (Parent != null && Parent.IsHandleCreated)
                                XplatUI.InvalidateNC (Parent.Handle);
                        // Should probably make this into one loop
                        SizeScrollBars ();
                        ArrangeWindows ();
                }
 
+               protected override void ScaleControl (SizeF factor, BoundsSpecified specified)
+               {
+                       // Never change the MdiClient's location
+                       specified &= ~BoundsSpecified.Location;
+
+                       base.ScaleControl (factor, specified);
+               }
+               
+               [System.ComponentModel.EditorBrowsable (EditorBrowsableState.Never)]
                protected override void ScaleCore (float dx, float dy)
                {
                        base.ScaleCore (dx, dy);
@@ -221,6 +222,17 @@ namespace System.Windows.Forms {
                        }
                }
 
+               [EditorBrowsable (EditorBrowsableState.Never)]
+               [Browsable (false)]
+               public override ImageLayout BackgroundImageLayout {
+                       get {
+                               return base.BackgroundImageLayout;
+                       }
+                       set {
+                               base.BackgroundImageLayout = value;
+                       }
+               }
+
                public Form [] MdiChildren {
                        get {
                                if (mdi_child_list == null)
@@ -233,7 +245,9 @@ namespace System.Windows.Forms {
 #region Protected Instance Properties
                protected override CreateParams CreateParams {
                        get {
-                               return base.CreateParams;
+                               CreateParams result = base.CreateParams;
+                               result.ExStyle |= (int) WindowExStyles.WS_EX_CLIENTEDGE;
+                               return result;
                        }
                }
                #endregion      // Protected Instance Properties
@@ -241,24 +255,30 @@ namespace System.Windows.Forms {
                #region Public Instance Methods
                public void LayoutMdi (MdiLayout value) {
 
-                       int max_width = Int32.MaxValue;
-                       int max_height = Int32.MaxValue;
-
-                       if (Parent != null) {
-                               max_width = Parent.Width;
-                               max_height = Parent.Height;
-                       }
+                       // Don't forget to always call ArrangeIconicWindows 
+                       ArrangeIconicWindows (true);
 
                        switch (value) {
-                       case MdiLayout.Cascade:
+                       case MdiLayout.Cascade: {
                                int i = 0;
                                for (int c = Controls.Count - 1; c >= 0; c--) {
                                        Form form = (Form) Controls [c];
 
+                                       if (form.WindowState == FormWindowState.Minimized)
+                                               continue;
+
+                                       if (form.WindowState == FormWindowState.Maximized)
+                                               form.WindowState = FormWindowState.Normal;
+
+                                       form.Width = System.Convert.ToInt32 (ClientSize.Width * 0.8);
+                                       form.Height = Math.Max (
+                                                               System.Convert.ToInt32 (ClientSize.Height * 0.8),
+                                                               SystemInformation.MinimumWindowSize.Height + 2);
+
                                        int l = 22 * i;
                                        int t = 22 * i;
 
-                                       if (i != 0 && (l + form.Width > max_width || t + form.Height > max_height)) {
+                                       if (i != 0 && (l + form.Width > ClientSize.Width || t + form.Height > ClientSize.Height)) {
                                                i = 0;
                                                l = 22 * i;
                                                t = 22 * i;
@@ -270,8 +290,71 @@ namespace System.Windows.Forms {
                                        i++;
                                }
                                break;
-                       default:
-                               throw new NotImplementedException();
+                               }
+                       case MdiLayout.TileHorizontal:
+                       case MdiLayout.TileVertical: {
+                               // First count number of windows to tile
+                               int total = 0;
+                               
+                               // And space used by iconic windows
+                               int clientHeight = ClientSize.Height;
+                               
+                               for (int i = 0; i < Controls.Count; i++) {
+                                       Form form = Controls [i] as Form;
+                                       
+                                       if (form == null)
+                                               continue;
+                                       
+                                       if (!form.Visible)
+                                               continue;
+
+                                       if (form.WindowState == FormWindowState.Maximized)
+                                               form.WindowState = FormWindowState.Normal;
+                                       else if (form.WindowState == FormWindowState.Minimized) {
+                                               if (form.Bounds.Top < clientHeight)
+                                                       clientHeight = form.Bounds.Top;
+                                               continue;
+                                       }
+                                               
+                                       total++;
+                               }
+                               if (total <= 0)
+                                       return;
+
+                               // Calculate desired height and width
+                               Size newSize;
+                               Size offset;
+
+                               if (value == MdiLayout.TileHorizontal) {
+                                       newSize = new Size(ClientSize.Width, clientHeight / total);
+                                       offset = new Size (0, newSize.Height);
+                               } else {
+                                       newSize = new Size(ClientSize.Width / total, clientHeight);
+                                       offset = new Size (newSize.Width, 0);
+                               }
+                               
+                               // Loop again and set the size and location.
+                               Point nextLocation = Point.Empty;
+                               
+                               for (int i = 0; i < Controls.Count; i++) {
+                                       Form form = Controls [i] as Form;
+
+                                       if (form == null)
+                                               continue;
+
+                                       if (!form.Visible)
+                                               continue;
+
+                                       if (form.WindowState == FormWindowState.Minimized)
+                                               continue;
+
+                                       form.Size = newSize;
+                                       form.Location = nextLocation;
+                                       nextLocation += offset;
+                               }
+                               
+                               break;
+                               }
                        }
                }
                #endregion      // Public Instance Methods
@@ -283,6 +366,9 @@ namespace System.Windows.Forms {
                {
                        if (lock_sizing)
                                return;
+                       
+                       if (!IsHandleCreated)
+                               return;
 
                        if (Controls.Count == 0 || ((Form) Controls [0]).WindowState == FormWindowState.Maximized) {
                                if (hbar != null)
@@ -293,9 +379,6 @@ namespace System.Windows.Forms {
                                        sizegrip.Visible = false;
                                return;
                        }
-                               
-                       bool hbar_required = false;
-                       bool vbar_required = false;
 
                        int right = 0;
                        int left = 0;
@@ -308,57 +391,43 @@ namespace System.Windows.Forms {
                                if (child.Right > right)
                                        right = child.Right;
                                if (child.Left < left) {
-                                       hbar_required = true;
                                        left = child.Left;
                                }
                                
                                if (child.Bottom > bottom)
                                        bottom = child.Bottom;
                                if (child.Top < 0) {
-                                       vbar_required = true;
                                        top = child.Top;
                                }
                        }
 
-                       int first_right = Width;
-                       int first_bottom = Height;
-                       int right_edge = first_right;
-                       int bottom_edge = first_bottom;
-                       int prev_right_edge;
-                       int prev_bottom_edge;
+                       int available_width = ClientSize.Width;
+                       int available_height = ClientSize.Height;
 
                        bool need_hbar = false;
                        bool need_vbar = false;
 
-                       do {
-                               prev_right_edge = right_edge;
-                               prev_bottom_edge = bottom_edge;
+                       if (right - left > available_width || left < 0) {
+                               need_hbar = true;
+                               available_height -= SystemInformation.HorizontalScrollBarHeight;
+                       }
+                       if (bottom - top > available_height || top < 0) {
+                               need_vbar = true;
+                               available_width -= SystemInformation.VerticalScrollBarWidth;
 
-                               if (hbar_required || right > right_edge) {
+                               if (!need_hbar && (right - left > available_width || left < 0)) {
                                        need_hbar = true;
-                                       bottom_edge = first_bottom - SystemInformation.HorizontalScrollBarHeight;
-                               } else {
-                                       need_hbar = false;
-                                       bottom_edge = first_bottom;
-                               }
-
-                               if (vbar_required || bottom > bottom_edge) {
-                                       need_vbar = true;
-                                       right_edge = first_right - SystemInformation.VerticalScrollBarWidth;
-                               } else {
-                                       need_vbar = false;
-                                       right_edge = first_right;
+                                       available_height -= SystemInformation.HorizontalScrollBarHeight;
                                }
-
-                       } while (right_edge != prev_right_edge || bottom_edge != prev_bottom_edge);
-
+                       }
+                       
                        if (need_hbar) {
                                if (hbar == null) {
                                        hbar = new ImplicitHScrollBar ();
                                        Controls.AddImplicit (hbar);
                                }
                                hbar.Visible = true;
-                               CalcHBar (left, right, right_edge, need_vbar);
+                               CalcHBar (left, right, need_vbar);
                        } else if (hbar != null)
                                hbar.Visible = false;
 
@@ -368,57 +437,58 @@ namespace System.Windows.Forms {
                                        Controls.AddImplicit (vbar);
                                }
                                vbar.Visible = true;
-                               CalcVBar (top, bottom, bottom_edge, need_hbar);
+                               CalcVBar (top, bottom, need_hbar);
                        } else if (vbar != null)
                                vbar.Visible = false;
 
                        if (need_hbar && need_vbar) {
                                if (sizegrip == null) {
-                                       sizegrip = new SizeGrip ();
+                                       sizegrip = new SizeGrip (this.ParentForm);
                                        Controls.AddImplicit (sizegrip);
                                }
                                sizegrip.Location = new Point (hbar.Right, vbar.Bottom);
-                               sizegrip.Width = vbar.Width;
-                               sizegrip.Height = hbar.Height;
                                sizegrip.Visible = true;
+                               XplatUI.SetZOrder (sizegrip.Handle, vbar.Handle, false, false);
                        } else if (sizegrip != null) {
                                sizegrip.Visible = false;
                        }
+                       
+                       XplatUI.InvalidateNC (Handle);
                }
 
-               private void CalcHBar (int left, int right, int right_edge, bool vert_vis)
+               private void CalcHBar (int left, int right, bool vert_vis)
                {
                        initializing_scrollbars = true;
-                       int virtual_left = Math.Min (left, 0);
-                       int virtual_right = Math.Max (right, right_edge);
-                       int diff = (virtual_right - virtual_left) - right_edge;
 
                        hbar.Left = 0;
                        hbar.Top = ClientRectangle.Bottom - hbar.Height;
                        hbar.Width = ClientRectangle.Width - (vert_vis ? SystemInformation.VerticalScrollBarWidth : 0);
                        hbar.LargeChange = 50;
-                       hbar.Maximum = diff + 51 + (vert_vis ? SystemInformation.VerticalScrollBarWidth : 0);
-                       hbar.Value = -virtual_left;
+                       hbar.Minimum = Math.Min (left, 0);
+                       hbar.Maximum = Math.Max (right - ClientSize.Width + 51 + (vert_vis ? SystemInformation.VerticalScrollBarWidth : 0), 0);
+                       hbar.Value = 0;
+                       hbar_value = 0;
                        hbar.ValueChanged += new EventHandler (HBarValueChanged);
                        XplatUI.SetZOrder (hbar.Handle, IntPtr.Zero, true, false);
+                       
                        initializing_scrollbars = false;
                }
 
-               private void CalcVBar (int top, int bottom, int bottom_edge, bool horz_vis)
+               private void CalcVBar (int top, int bottom, bool horz_vis)
                {
                        initializing_scrollbars = true;
-                       int virtual_top = Math.Min (top, 0);
-                       int virtual_bottom = Math.Max (bottom, bottom_edge);
-                       int diff = (virtual_bottom - virtual_top) - bottom_edge;
                        
                        vbar.Top = 0;
                        vbar.Left = ClientRectangle.Right - vbar.Width;
                        vbar.Height = ClientRectangle.Height - (horz_vis ? SystemInformation.HorizontalScrollBarHeight : 0);
                        vbar.LargeChange = 50;
-                       vbar.Minimum = virtual_top;
-                       vbar.Maximum = diff + 51 + (horz_vis ? SystemInformation.HorizontalScrollBarHeight : 0);
+                       vbar.Minimum = Math.Min (top, 0);
+                       vbar.Maximum = Math.Max (bottom - ClientSize.Height + 51 + (horz_vis ? SystemInformation.HorizontalScrollBarHeight : 0), 0);
+                       vbar.Value = 0;
+                       vbar_value = 0;
                        vbar.ValueChanged += new EventHandler (VBarValueChanged);
                        XplatUI.SetZOrder (vbar.Handle, IntPtr.Zero, true, false);
+                       
                        initializing_scrollbars = false;
                }
 
@@ -433,15 +503,15 @@ namespace System.Windows.Forms {
                        lock_sizing = true;
 
                        try {
+                               int diff = hbar_value - hbar.Value;
                                foreach (Form child in Controls) {
-                                       child.Left += hbar_value - hbar.Value;
+                                       child.Left += diff;
                                }
                        } finally {
                                lock_sizing = false;
                        }
 
                        hbar_value = hbar.Value;
-                       lock_sizing = false;
                }
 
                private void VBarValueChanged (object sender, EventArgs e)
@@ -455,19 +525,22 @@ namespace System.Windows.Forms {
                        lock_sizing = true;
 
                        try {
+                               int diff = vbar_value - vbar.Value;
                                foreach (Form child in Controls) {
-                                       child.Top += vbar_value - vbar.Value;
+                                       child.Top += diff;
                                }
                        } finally {
                                lock_sizing = false;
                        }
 
                        vbar_value = vbar.Value;
-                       lock_sizing = false;
                }
 
                private void ArrangeWindows ()
                {
+                       if (!IsHandleCreated)
+                               return;
+                               
                        int change = 0;
                        if (prev_bottom != -1)
                                change = Bottom - prev_bottom;
@@ -480,7 +553,7 @@ namespace System.Windows.Forms {
 
                                MdiWindowManager wm = child.WindowManager as MdiWindowManager;
                                if (wm.GetWindowState () == FormWindowState.Maximized)
-                                       wm.SizeMaximized ();
+                                       child.Bounds = wm.MaximizedBounds;
 
                                if (wm.GetWindowState () == FormWindowState.Minimized) {
                                        child.Top += change;
@@ -491,17 +564,9 @@ namespace System.Windows.Forms {
                        prev_bottom = Bottom;
                }
 
-               private void FormLocationChanged (object sender, EventArgs e)
-               {
-                       SizeScrollBars ();
-               }
-
-               internal void ArrangeIconicWindows ()
+               internal void ArrangeIconicWindows (bool rearrange_all)
                {
-                       int xspacing = 160;
-                       int yspacing = 25;
-
-                       Rectangle rect = new Rectangle (0, 0, xspacing, yspacing);
+                       Rectangle rect = Rectangle.Empty;
 
                        lock_sizing = true;
                        foreach (Form form in Controls) {
@@ -510,34 +575,25 @@ namespace System.Windows.Forms {
 
                                MdiWindowManager wm = (MdiWindowManager) form.WindowManager;
                                
-                               if (wm.IconicBounds != Rectangle.Empty) {
+                               if (wm.IconicBounds != Rectangle.Empty && !rearrange_all) {
                                        if (form.Bounds != wm.IconicBounds)
                                                form.Bounds = wm.IconicBounds;
                                        continue;
                                }
                                
-                               // Need to get the width in the loop cause some themes might have
-                               // different widths for different styles
-                               int bw = ThemeEngine.Current.ManagedWindowBorderWidth (wm);
-                               
-                               // The extra one pixel is a cheap hack for now until we
-                               // handle 0 client sizes properly in the driver
-                               int height = wm.TitleBarHeight + (bw * 2) + 1;
-                               
                                bool success = true;
                                int startx, starty, currentx, currenty;
+
+                               rect.Size = wm.IconicSize;
                                
                                startx = 0;
-                               starty = Bottom - yspacing - 1;
-                               if (this.hbar != null && this.hbar.Visible)
-                                       starty -= this.hbar.Height;
+                               starty = ClientSize.Height - rect.Height;
                                currentx = startx;
                                currenty = starty;
                                
                                do {
                                        rect.X = currentx;
                                        rect.Y = currenty;
-                                       rect.Height = height;
                                        success = true;
                                        foreach (Form form2 in Controls) {
                                                if (form2 == form || form2.window_state != FormWindowState.Minimized)
@@ -549,31 +605,50 @@ namespace System.Windows.Forms {
                                                }
                                        }
                                        if (!success) { 
-                                               currentx += xspacing;
-                                               if (currentx + xspacing > Right) {
+                                               currentx += rect.Width;
+                                               if (currentx + rect.Width > Right) {
                                                        currentx = startx;
-                                                       currenty -= Math.Max(yspacing, height);
+                                                       currenty -= rect.Height;
                                                } 
                                        }
                                } while (!success);
-                               Console.WriteLine("IconicBounds = {0}", rect);
                                wm.IconicBounds = rect;
                                form.Bounds = wm.IconicBounds;
                        }
                        lock_sizing = false;
                }
 
-               internal void CloseChildForm (Form form)
+               internal void ChildFormClosed (Form form)
                {
-                       if (Controls.Count > 1) {
-                               Form next = (Form) Controls [1];
-                               if (form.WindowState == FormWindowState.Maximized)
-                                       next.WindowState = FormWindowState.Maximized;
-                               ActivateChild (next);
+                       FormWindowState closed_form_windowstate = form.WindowState;
+       
+                       form.Visible = false;
+                       Controls.Remove (form);
+                       
+                       if (Controls.Count == 0) {
+                               ((MdiWindowManager) form.window_manager).RaiseDeactivate ();
+                       } else if (closed_form_windowstate == FormWindowState.Maximized) {
+                               Form current = (Form) Controls [0];
+                               current.WindowState = FormWindowState.Maximized;
+                               ActivateChild(current);
                        }
 
-                       Controls.Remove (form);
-                       form.Close ();
+                       if (Controls.Count == 0) {
+                               XplatUI.RequestNCRecalc (Parent.Handle);
+                               ParentForm.PerformLayout ();
+
+                               // If we closed the last child, unmerge the menus.
+                               // If it's not the last child, the menu will be unmerged
+                               // when another child takes focus.
+                               MenuStrip parent_menu = form.MdiParent.MainMenuStrip;
+
+                               if (parent_menu != null)
+                                       if (parent_menu.IsCurrentlyMerged)
+                                               ToolStripManager.RevertMerge (parent_menu);
+                       }
+                       SizeScrollBars ();
+                       SetParentText (false);
+                       form.Dispose();
                }
 
                internal void ActivateNextChild ()
@@ -586,8 +661,18 @@ namespace System.Windows.Forms {
                        Form front = (Form) Controls [0];
                        Form form = (Form) Controls [1];
 
-                       front.SendToBack ();
                        ActivateChild (form);
+                       front.SendToBack ();
+               }
+
+               internal void ActivatePreviousChild ()
+               {
+                       if (Controls.Count <= 1)
+                               return;
+                       
+                       Form back = (Form) Controls [Controls.Count - 1];
+                       
+                       ActivateChild (back);
                }
 
                internal void ActivateChild (Form form)
@@ -595,19 +680,70 @@ namespace System.Windows.Forms {
                        if (Controls.Count < 1)
                                return;
 
+                       if (ParentForm.is_changing_visible_state > 0)
+                               return;
+                       
                        Form current = (Form) Controls [0];
-                       form.SuspendLayout ();
+                       bool raise_deactivate = ParentForm.ActiveControl == current;
+
+                       // We want to resize the new active form before it is 
+                       // made active to avoid flickering. Can't do it in the
+                       // normal way (form.WindowState = Maximized) since it's not
+                       // active yet and everything would just return to before. 
+                       // We also won't suspend layout, this way the layout will
+                       // happen before the form is made active (and in many cases
+                       // before it is visible, which avoids flickering as well).
+                       MdiWindowManager wm = (MdiWindowManager)form.WindowManager;
+                       
+                       if (current.WindowState == FormWindowState.Maximized && form.WindowState != FormWindowState.Maximized && form.Visible) {
+                               FormWindowState old_state = form.window_state;
+                               SetWindowState (form, old_state, FormWindowState.Maximized, true);
+                               wm.was_minimized = form.window_state == FormWindowState.Minimized;
+                               form.window_state = FormWindowState.Maximized;
+                               SetParentText (false);
+                       }
+
                        form.BringToFront ();
-                       if (vbar != null && vbar.Visible)
-                               XplatUI.SetZOrder (vbar.Handle, IntPtr.Zero, true, false);
-                       if (hbar != null && hbar.Visible)
-                               XplatUI.SetZOrder (hbar.Handle, IntPtr.Zero, true, false);
-                       SetWindowStates ((MdiWindowManager) form.window_manager);
-                       form.ResumeLayout (false);
+                       form.SendControlFocus (form);
+                       SetWindowStates (wm);
                        if (current != form) {
-                               XplatUI.InvalidateNC (current.Handle);
-                               XplatUI.InvalidateNC (form.Handle);
+                               form.has_focus = false;
+                               if (current.IsHandleCreated)
+                                       XplatUI.InvalidateNC (current.Handle);
+                               if (form.IsHandleCreated)
+                                       XplatUI.InvalidateNC (form.Handle);
+                               if (raise_deactivate) {
+                                       MdiWindowManager current_wm = (MdiWindowManager) current.window_manager;
+                                       current_wm.RaiseDeactivate ();
+                                       
+                               }
                        }
+                       active_child = (Form) Controls [0];
+                       
+                       if (active_child.Visible) {
+                               bool raise_activated = ParentForm.ActiveControl != active_child;
+                               ParentForm.ActiveControl = active_child;
+                               if (raise_activated) {
+                                       MdiWindowManager active_wm = (MdiWindowManager) active_child.window_manager;
+                                       active_wm.RaiseActivated ();
+                               }
+                       }
+               }
+
+               internal override IntPtr AfterTopMostControl ()
+               {
+                       // order of scrollbars:
+                       // top = vertical
+                       //       sizegrid
+                       // bottom = horizontal
+                       if (hbar != null && hbar.Visible)
+                               return hbar.Handle;
+                       // no need to check for sizegrip since it will only
+                       // be visible if hbar is visible.
+                       if (vbar != null && vbar.Visible)
+                               return vbar.Handle;
+                               
+                       return base.AfterTopMostControl ();
                }
                
                internal bool SetWindowStates (MdiWindowManager wm)
@@ -630,12 +766,15 @@ namespace System.Windows.Forms {
                        if (!form.Visible)
                                return false;
                        
-                       bool is_active = wm.IsActive();
+                       bool is_active = wm.IsActive;
                        bool maximize_this = false;
                        
                        if (!is_active){
                                return false;
                        }
+                       
+                       ArrayList minimize_these = new ArrayList ();
+                       ArrayList normalize_these = new ArrayList ();
 
                        setting_windowstates = true;
                        foreach (Form frm in mdi_child_list) {
@@ -646,28 +785,170 @@ namespace System.Windows.Forms {
                                }
                                if (frm.WindowState == FormWindowState.Maximized && is_active) {
                                        maximize_this = true;   
-                                       if (((MdiWindowManager) frm.window_manager).was_minimized)
-                                               frm.WindowState = FormWindowState.Minimized;
-                                       else
-                                               frm.WindowState = FormWindowState.Normal;//
+                                       if (((MdiWindowManager) frm.window_manager).was_minimized) {
+                                               minimize_these.Add (frm); 
+                                       } else {
+                                               normalize_these.Add (frm); 
+                                       }
                                }
                        }
-                       if (maximize_this) {
+
+                       if (maximize_this && form.WindowState != FormWindowState.Maximized) {
                                wm.was_minimized = form.window_state == FormWindowState.Minimized;
                                form.WindowState = FormWindowState.Maximized;
                        }
-                       SetParentText(false);
                        
-                       XplatUI.RequestNCRecalc(ParentForm.Handle);
+                       foreach (Form frm in minimize_these)
+                               frm.WindowState = FormWindowState.Minimized;
+
+                       foreach (Form frm in normalize_these)
+                               frm.WindowState = FormWindowState.Normal;
+
+
+                       SetParentText (false);
+                       
+                       XplatUI.RequestNCRecalc (ParentForm.Handle);
                        XplatUI.RequestNCRecalc (Handle);
 
                        SizeScrollBars ();
 
                        setting_windowstates = false;
 
+                       if (form.MdiParent.MainMenuStrip != null)
+                               form.MdiParent.MainMenuStrip.RefreshMdiItems ();
+
+                       // Implicit menu strip merging
+                       // - When child is activated
+                       // - Parent form must have a MainMenuStrip
+                       // - Find the first menustrip on the child
+                       // - Merge
+                       MenuStrip parent_menu = form.MdiParent.MainMenuStrip;
+
+                       if (parent_menu != null) {
+                               if (parent_menu.IsCurrentlyMerged)
+                                       ToolStripManager.RevertMerge (parent_menu);
+                                       
+                               MenuStrip child_menu = LookForChildMenu (form);
+
+                               if (form.WindowState != FormWindowState.Maximized)
+                                       RemoveControlMenuItems (wm);
+                               
+                               if (form.WindowState == FormWindowState.Maximized) {
+                                       bool found = false;
+                                       
+                                       foreach (ToolStripItem tsi in parent_menu.Items) {
+                                               if (tsi is MdiControlStrip.SystemMenuItem) {
+                                                       (tsi as MdiControlStrip.SystemMenuItem).MdiForm = form;
+                                                       found = true;
+                                               } else if (tsi is MdiControlStrip.ControlBoxMenuItem) {
+                                                       (tsi as MdiControlStrip.ControlBoxMenuItem).MdiForm = form;
+                                                       found = true;
+                                               }
+                                       }       
+                                       
+                                       if (!found) {
+                                               parent_menu.SuspendLayout ();
+                                               parent_menu.Items.Insert (0, new MdiControlStrip.SystemMenuItem (form));
+                                               parent_menu.Items.Add (new MdiControlStrip.ControlBoxMenuItem (form, MdiControlStrip.ControlBoxType.Close));
+                                               parent_menu.Items.Add (new MdiControlStrip.ControlBoxMenuItem (form, MdiControlStrip.ControlBoxType.Max));
+                                               parent_menu.Items.Add (new MdiControlStrip.ControlBoxMenuItem (form, MdiControlStrip.ControlBoxType.Min));
+                                               parent_menu.ResumeLayout ();
+                                       }
+                               }
+                               
+                               if (child_menu != null)
+                                       ToolStripManager.Merge (child_menu, parent_menu);
+                       }
+
                        return maximize_this;
                }
 
+               private MenuStrip LookForChildMenu (Control parent)
+               {
+                       foreach (Control c in parent.Controls) {
+                               if (c is MenuStrip)
+                                       return (MenuStrip)c;
+                                       
+                               if (c is ToolStripContainer || c is ToolStripPanel) {
+                                       MenuStrip ms = LookForChildMenu (c);
+                                       
+                                       if (ms != null)
+                                               return ms;
+                               }
+                       }
+                       
+                       return null;
+               }
+               
+               internal void RemoveControlMenuItems (MdiWindowManager wm)
+               {
+                       Form form = wm.form;
+                       MenuStrip parent_menu = form.MdiParent.MainMenuStrip;
+
+                       // Only remove the items if the form requesting still owns the menu items
+                       if (parent_menu != null) {
+                               parent_menu.SuspendLayout ();
+
+                               for (int i = parent_menu.Items.Count - 1; i >= 0; i--) {
+                                       if (parent_menu.Items[i] is MdiControlStrip.SystemMenuItem) {
+                                               if ((parent_menu.Items[i] as MdiControlStrip.SystemMenuItem).MdiForm == form)
+                                                       parent_menu.Items.RemoveAt (i);
+                                       } else if (parent_menu.Items[i] is MdiControlStrip.ControlBoxMenuItem) {
+                                               if ((parent_menu.Items[i] as MdiControlStrip.ControlBoxMenuItem).MdiForm == form)
+                                                       parent_menu.Items.RemoveAt (i);
+                                       }
+                               }
+                               
+                               parent_menu.ResumeLayout ();
+                       }
+               }
+
+               internal void SetWindowState (Form form, FormWindowState old_window_state, FormWindowState new_window_state, bool is_activating_child)
+               {
+                       bool mdiclient_layout;
+
+                       MdiWindowManager wm = (MdiWindowManager) form.window_manager;
+
+                       if (!is_activating_child && new_window_state == FormWindowState.Maximized && !wm.IsActive) {
+                               ActivateChild (form);
+                               return;
+                       }
+                               
+                       if (old_window_state == FormWindowState.Normal)
+                               wm.NormalBounds = form.Bounds;
+
+                       if (SetWindowStates (wm))
+                               return;
+
+                       if (old_window_state == new_window_state)
+                               return;
+
+                       mdiclient_layout = old_window_state == FormWindowState.Maximized || new_window_state == FormWindowState.Maximized;
+
+                       switch (new_window_state) {
+                       case FormWindowState.Minimized:
+                               ArrangeIconicWindows (false);
+                               break;
+                       case FormWindowState.Maximized:
+                               form.Bounds = wm.MaximizedBounds;
+                               break;
+                       case FormWindowState.Normal:
+                               form.Bounds = wm.NormalBounds;
+                               break;
+                       }
+
+                       wm.UpdateWindowDecorations (new_window_state);
+
+                       form.ResetCursor ();
+
+                       if (mdiclient_layout)
+                               Parent.PerformLayout ();
+
+                       XplatUI.RequestNCRecalc (Parent.Handle);
+                       XplatUI.RequestNCRecalc (form.Handle);
+                       if (!setting_windowstates)
+                               SizeScrollBars ();
+               }
                internal int ChildrenCreated {
                        get { return mdi_created; }
                        set { mdi_created = value; }
@@ -675,14 +956,47 @@ namespace System.Windows.Forms {
 
                internal Form ActiveMdiChild {
                        get {
+                               if (ParentForm != null && !ParentForm.Visible)
+                                       return null;
+
                                if (Controls.Count < 1)
                                        return null;
-                               return (Form) Controls [0];
+                                       
+                               if (!ParentForm.IsHandleCreated)
+                                       return null;
+                               
+                               if (!ParentForm.has_been_visible)
+                                       return null;
+                                       
+                               if (!ParentForm.Visible)
+                                       return active_child;
+                               
+                               active_child = null;
+                               for (int i = 0; i < Controls.Count; i++) {
+                                       if (Controls [i].Visible) {
+                                               active_child = (Form) Controls [i];
+                                               break;
+                                       }
+                               }
+                               return active_child;
                        }
                        set {
                                ActivateChild (value);
                        }
                }
+               
+               internal void ActivateActiveMdiChild ()
+               {
+                       if (ParentForm.is_changing_visible_state > 0)
+                               return;
+                               
+                       for (int i = 0; i < Controls.Count; i++) {
+                               if (Controls [i].Visible) {
+                                       ActivateChild ((Form) Controls [i]);
+                                       return;
+                               }
+                       }
+               }
        }
 }