Sfoglia il codice sorgente

Fixes #2775. Something in 1.13 broke centering child windows. (#2778)

* Fixes #2776. Pressing Alt key on a Window with only a MenuBar throws System.InvalidOperationException.

* Add unit test.

* Fix extra bracket.

* Prevents throw exception if Application.Current is null.

* Fix unit test because OnLeave is now invoked on toplevel removing, preventing two views having focus.

* Fix unit test method name.

* Fix Window by not layout on his subviews when adding a new view after the Application.Begin was already running.

* FindAndOpenMenuByHotkey now search inside Menus and inside his Children.

* Add unit test for Window LayoutSubviews and FindAndOpenChildrenMenuByHotkey menu method.

* Prevents button to be clear when it's invisible.

* Fixes 2780. Moving a Window that is Application.Top shouldn't be allowed.

* Fix condition if Window and Application.Top.

* Always LayoutSubviews and PositionToplevels after Clear.

* Fixes #2787. MenuItem with CanExecute returning false is select when a MenuBar is opened.

* Leveraging the power of CanExecute feature.

* Fixes #2789. StatusItem should have a disabled attribute if it can't execute.

* Allows positioning a child window outside the limits of the menu and the status bar.

* Change to a more appropriate name.

* Simplifies all the run actions.

* Prevents open menu bar if it's invisible and close all opened menus.

* Fix mdi run loop.

* Fix hot key on mdi toplevels.

* Fix position on mdi toplevels.

* Fix Top.Redraw by set state.Toplevel.SetNeedsDisplay if it's needed to redraw.

* Fix MdiTop by repainted when a keystroke is generated by keyboard.

* Rename local fields.

* Force redraw if application.Top needs display.

* Added more features to the scenario.

* Change the scenarios to run as Application.Top instead of sub-views.

* Add a new scenario similar but as Mdi Container.

* Add a bunch of new unit tests to prove all this PR.

* Only it's need to redraw Application.Top if it's a Mdi Container.

* Remove unnecessary code.

* Unit test that proves that a MDI child leaves no trace when the location is changed.

* Removes unnecessary Application.Init because theses uses Run<T> which already call it.

* Ensures a menu bar been closed after run an action.

* Ensures that another view can be focused if not IsMenuOpen and LastFocused is null, instead of focused the menu itself.

* Ensures a focused contentview subview being focused if MostFocused is null.

* Ensures a MdiTop subview to have priority if it's focused and thus  make it Current.

* Allow a MdiChild be closed when pressing Application.QuitKey.

* More unit tests proving the changes.

* Ensures the top.MostFocused is focused.

* Ensures MdiChild on the front if MdiTop.MostFocused isn't valid, like ContentView.

* Add unit test showing MdiChild on the front.

* Fix an issue where NullReferenceException can be throws everywhere while get the Application.MdiChildes property.

---------

Co-authored-by: Tig <[email protected]>
BDisp 1 anno fa
parent
commit
3e1637aac8

+ 79 - 16
Terminal.Gui/Core/Application.cs

@@ -69,16 +69,15 @@ namespace Terminal.Gui {
 		/// </summary>
 		public static List<Toplevel> MdiChildes {
 			get {
+				List<Toplevel> mdiChildes = new List<Toplevel> ();
 				if (MdiTop != null) {
-					List<Toplevel> mdiChildes = new List<Toplevel> ();
 					foreach (var top in toplevels) {
 						if (top != MdiTop && !top.Modal) {
 							mdiChildes.Add (top);
 						}
 					}
-					return mdiChildes;
 				}
-				return null;
+				return mdiChildes;
 			}
 		}
 
@@ -534,8 +533,10 @@ namespace Terminal.Gui {
 
 			var chain = toplevels.ToList ();
 			foreach (var topLevel in chain) {
-				if (topLevel.ProcessHotKey (ke))
+				if (topLevel.ProcessHotKey (ke)) {
+					EnsuresMdiTopOnFrontIfMdiTopMostFocused ();
 					return;
+				}
 				if (topLevel.Modal)
 					break;
 			}
@@ -766,6 +767,7 @@ namespace Terminal.Gui {
 				return;
 			}
 
+			EnsuresMdiTopOnFrontIfMdiTopMostFocused ();
 			var view = FindDeepestView (Current, me.X, me.Y, out int rx, out int ry);
 
 			if (view != null && view.WantContinuousButtonPressed)
@@ -804,13 +806,15 @@ namespace Terminal.Gui {
 				}
 			}
 
-			if ((view == null || view == MdiTop) && !Current.Modal && MdiTop != null
+			if ((view == null || view == MdiTop || view.SuperView == MdiTop) && !Current.Modal && MdiTop != null
 				&& me.Flags != MouseFlags.ReportMousePosition && me.Flags != 0) {
 
 				var top = FindDeepestTop (Top, me.X, me.Y, out _, out _);
 				view = FindDeepestView (top, me.X, me.Y, out rx, out ry);
 
-				if (view != null && view != MdiTop && top != Current) {
+				if (view != null && view != MdiTop && top != Current && top.MostFocused != null
+					&& top.MostFocused.GetType ().Name != "ContentView") {
+
 					MoveCurrent ((Toplevel)top);
 				}
 			}
@@ -843,12 +847,23 @@ namespace Terminal.Gui {
 					WantContinuousButtonPressedView = null;
 
 				// Should we bubbled up the event, if it is not handled?
-				view.OnMouseEvent (nme);
+				if (view.OnMouseEvent (nme)) {
+					EnsuresMdiTopOnFrontIfMdiTopMostFocused ();
+				}
 
 				EnsuresTopOnFront ();
 			}
 		}
 
+		static void EnsuresMdiTopOnFrontIfMdiTopMostFocused ()
+		{
+			if (MdiTop != null && Current != MdiTop && MdiTop.MostFocused != null
+				&& MdiTop.MostFocused.GetType ().Name != "ContentView") {
+
+				MoveCurrent (Top);
+			}
+		}
+
 		// Only return true if the Current has changed.
 		static bool MoveCurrent (Toplevel top)
 		{
@@ -1188,8 +1203,12 @@ namespace Terminal.Gui {
 				Iteration?.Invoke ();
 
 				EnsureModalOrVisibleAlwaysOnTop (state.Toplevel);
+				if (!EnsuresNotModalNotRunningAndNotCurrent (state.Toplevel)) {
+					EnsuresMdiChildOnFrontIfMdiTopNotMostFocused ();
+				}
 				if ((state.Toplevel != Current && Current?.Modal == true)
 					|| (state.Toplevel != Current && Current?.Modal == false)) {
+
 					MdiTop?.OnDeactivate (state.Toplevel);
 					state.Toplevel = Current;
 					MdiTop?.OnActivate (state.Toplevel);
@@ -1217,18 +1236,42 @@ namespace Terminal.Gui {
 			}
 			if (!state.Toplevel.NeedDisplay.IsEmpty || state.Toplevel.ChildNeedsDisplay || state.Toplevel.LayoutNeeded
 				|| MdiChildNeedsDisplay ()) {
-				state.Toplevel.Redraw (state.Toplevel.Bounds);
-				if (DebugDrawBounds) {
-					DrawBounds (state.Toplevel);
-				}
-				state.Toplevel.PositionCursor ();
-				Driver.Refresh ();
+
+				bool isTopNeedsDisplay;
+				do {
+					state.Toplevel.Redraw (state.Toplevel.Bounds);
+					if (DebugDrawBounds) {
+						DrawBounds (state.Toplevel);
+					}
+					state.Toplevel.PositionCursor ();
+					Driver.Refresh ();
+					isTopNeedsDisplay = IsTopNeedsDisplay (state.Toplevel);
+					if (isTopNeedsDisplay) {
+						Top.Redraw (Top.Bounds);
+						state.Toplevel.SetNeedsDisplay ();
+					}
+				} while (isTopNeedsDisplay);
 			} else {
 				Driver.UpdateCursor ();
 			}
-			if (state.Toplevel != Top && !state.Toplevel.Modal
-				&& (!Top.NeedDisplay.IsEmpty || Top.ChildNeedsDisplay || Top.LayoutNeeded)) {
-				Top.Redraw (Top.Bounds);
+
+			bool IsTopNeedsDisplay (Toplevel toplevel)
+			{
+				if (toplevel != Top && !toplevel.Modal
+					&& (!Top.NeedDisplay.IsEmpty || Top.ChildNeedsDisplay || Top.LayoutNeeded)) {
+
+					return true;
+				}
+				return false;
+			}
+		}
+
+		static void EnsuresMdiChildOnFrontIfMdiTopNotMostFocused ()
+		{
+			if (MdiTop != null && Current == MdiTop && (MdiTop.MostFocused == null
+				|| MdiTop.MostFocused.GetType ().Name == "ContentView")) {
+
+				MoveNext ();
 			}
 		}
 
@@ -1249,6 +1292,22 @@ namespace Terminal.Gui {
 			}
 		}
 
+		static bool EnsuresNotModalNotRunningAndNotCurrent (Toplevel curRunStateTop)
+		{
+			if (MdiTop == null || !curRunStateTop.Running) {
+				return false;
+			}
+
+			foreach (var top in toplevels) {
+				if (!top.IsMdiContainer && top?.Running == false && top != Current && top?.Modal == false) {
+					MoveCurrent (top);
+					return true;
+				}
+			}
+
+			return false;
+		}
+
 		static bool MdiChildNeedsDisplay ()
 		{
 			if (MdiTop == null) {
@@ -1586,6 +1645,10 @@ namespace Terminal.Gui {
 
 		internal static bool ShowChild (Toplevel top)
 		{
+			if (Current == top) {
+				return false;
+			}
+
 			if (top.Visible && MdiTop != null && Current?.Modal == false) {
 				lock (toplevels) {
 					toplevels.MoveTo (top, 0, new ToplevelEqualityComparer ());

+ 93 - 43
Terminal.Gui/Core/Toplevel.cs

@@ -426,6 +426,32 @@ namespace Terminal.Gui {
 			return false;
 		}
 
+		///<inheritdoc/>
+		public override bool ProcessHotKey (KeyEvent keyEvent)
+		{
+			if (base.ProcessHotKey (keyEvent)) {
+				return true;
+			}
+
+			if (this.IsMdiChild && Application.Top.ProcessHotKey (keyEvent)) {
+				return true;
+			}
+			return false;
+		}
+
+		///<inheritdoc/>
+		public override bool ProcessColdKey (KeyEvent keyEvent)
+		{
+			if (base.ProcessColdKey (keyEvent)) {
+				return true;
+			}
+
+			if (ShortcutHelper.FindAndOpenByShortcut (keyEvent, this)) {
+				return true;
+			}
+			return false;
+		}
+
 		private void MovePreviousViewOrTop ()
 		{
 			if (Application.MdiTop == null) {
@@ -484,26 +510,15 @@ namespace Terminal.Gui {
 
 		private void QuitToplevel ()
 		{
-			if (Application.MdiTop != null) {
+			if (IsMdiChild) {
+				RequestStop ();
+			} else if (Application.MdiTop != null) {
 				Application.MdiTop.RequestStop ();
 			} else {
 				Application.RequestStop ();
 			}
 		}
 
-		///<inheritdoc/>
-		public override bool ProcessColdKey (KeyEvent keyEvent)
-		{
-			if (base.ProcessColdKey (keyEvent)) {
-				return true;
-			}
-
-			if (ShortcutHelper.FindAndOpenByShortcut (keyEvent, this)) {
-				return true;
-			}
-			return false;
-		}
-
 		View GetDeepestFocusedSubview (View view)
 		{
 			if (view == null) {
@@ -604,63 +619,91 @@ namespace Terminal.Gui {
 			out int nx, out int ny, out View mb, out View sb)
 		{
 			int l;
-			View superView = null;
-			if (top?.SuperView == null || top == Application.Top || top?.SuperView == Application.Top) {
+			View superView = GetSuperView (top);
+			if (superView == null || top == Application.Top || superView == Application.Top) {
 				l = Driver.Cols;
 				superView = Application.Top;
 			} else {
-				l = top.SuperView.Frame.Width;
-				superView = top.SuperView;
+				l = superView.Frame.Width;
+			}
+			mb = null; sb = null;
+			if (!(superView is Toplevel)) {
+				nx = x; ny = y;
+				return superView;
 			}
+			var superViewBorder = superView.Border != null ? (superView.Border.DrawMarginFrame ? 1 : 0) : 0;
+			var topBorder = top.Modal ? 0 : top.Border != null ? (top.Border.DrawMarginFrame ? 1 : 0) : 0;
 			nx = Math.Max (x, 0);
-			nx = nx + top.Frame.Width > l ? Math.Max (l - top.Frame.Width, 0) : nx;
-			var mfLength = top.Border?.DrawMarginFrame == true ? 2 : 1;
-			if (nx + mfLength > top.Frame.X + top.Frame.Width) {
-				nx = Math.Max (top.Frame.Right - mfLength, 0);
+			nx = !top.IsMdiChild && !top.Modal && nx + superViewBorder * 2 + top.Frame.Width >= l ? Math.Max (l - top.Frame.Width - superViewBorder * 2, 0) : nx;
+			nx = top.Modal && nx == 0 ? superViewBorder : nx;
+			nx = top.IsMdiChild && nx < superViewBorder ? superViewBorder : nx;
+			nx = top.Modal && nx + superViewBorder + top.Frame.Width >= l ? l - top.Frame.Width - superViewBorder : nx;
+			nx = top.IsMdiChild && nx + superViewBorder + top.Frame.Width >= l ? l - top.Frame.Width - superViewBorder : nx;
+			if (nx + topBorder * 2 > top.Frame.X + top.Frame.Width) {
+				nx = Math.Max (top.Frame.Right - topBorder * 2, 0);
 			}
 			//System.Diagnostics.Debug.WriteLine ($"nx:{nx}, rWidth:{rWidth}");
 			bool m = false, s = false;
-			mb = null; sb = null;
-			if (!(top is Window && top == Application.Top) && (top?.SuperView == null || top == Application.Top || top?.SuperView == Application.Top)) {
+			if (!(top is Window && top == Application.Top) && (superView == null || top == Application.Top || superView == Application.Top)) {
 				m = Application.Top.MenuBar?.Visible == true;
 				mb = Application.Top.MenuBar;
 			} else if (!(top is Window && top == Application.Top)) {
-				var t = top.SuperView;
+				var t = superView;
 				while (!(t is Toplevel)) {
-					t = t.SuperView;
+					t = GetSuperView (t);
 				}
 				m = ((Toplevel)t).MenuBar?.Visible == true;
 				mb = ((Toplevel)t).MenuBar;
 			}
-			if (top?.SuperView == null || top == Application.Top || top?.SuperView == Application.Top) {
-				l = m ? 1 : 0;
+			if (superView == null || top == Application.Top || superView == Application.Top) {
+				l = m ? 1 + (top.Modal ? superViewBorder - topBorder : 0) : 0;
 			} else {
 				l = 0;
 			}
 			ny = Math.Max (y, l);
-			if (!(top is Window && top == Application.Top) && (top?.SuperView == null || top == Application.Top || top?.SuperView == Application.Top)) {
+			ny = top.Modal && ny == 0 ? superViewBorder : ny;
+			ny = top.IsMdiChild && ny < superViewBorder + l ? ny + superViewBorder : ny;
+			if (!(top is Window && top == Application.Top) && (superView == null || top == Application.Top || superView == Application.Top)) {
 				s = Application.Top.StatusBar?.Visible == true;
 				sb = Application.Top.StatusBar;
 			} else if (!(top is Window && top == Application.Top)) {
-				var t = top.SuperView;
+				var t = superView;
 				while (!(t is Toplevel)) {
-					t = t.SuperView;
+					t = GetSuperView (t);
 				}
 				s = ((Toplevel)t).StatusBar?.Visible == true;
 				sb = ((Toplevel)t).StatusBar;
 			}
-			if (top?.SuperView == null || top == Application.Top || top?.SuperView == Application.Top) {
-				l = s ? Driver.Rows - 1 : Driver.Rows;
+			if (superView == null || top == Application.Top || superView == Application.Top) {
+				l = (s ? Driver.Rows - 1 : Driver.Rows);
 			} else {
-				l = s ? top.SuperView.Frame.Height - 1 : top.SuperView.Frame.Height;
+				l = (s ? superView.Frame.Height - 1 : superView.Frame.Height);
 			}
 			ny = Math.Min (ny, l);
-			ny = ny + top.Frame.Height >= l ? Math.Max (l - top.Frame.Height, m ? 1 : 0) : ny;
-			if (ny + mfLength > top.Frame.Y + top.Frame.Height) {
-				ny = Math.Max (top.Frame.Bottom - mfLength, 0);
+			ny = !top.IsMdiChild && !top.Modal && ny + superViewBorder * 2 + top.Frame.Height >= l ? Math.Max (l - top.Frame.Height - superViewBorder * 2, m ? 1 : 0) : ny;
+			ny = top.Modal && ny + superViewBorder * 2 + top.Frame.Height >= l ? l - top.Frame.Height - superViewBorder : ny;
+			ny = top.IsMdiChild && ny + superViewBorder + top.Frame.Height >= l ? Math.Max (l - top.Frame.Height - superViewBorder, m ? 1 : 0) : ny;
+			if (ny + topBorder * 2 > top.Frame.Y + top.Frame.Height) {
+				ny = Math.Max (top.Frame.Bottom - topBorder * 2, 0);
 			}
 			//System.Diagnostics.Debug.WriteLine ($"ny:{ny}, rHeight:{rHeight}");
 
+			if (superView != null && superView == top && superView == Application.Top) {
+				nx = superView.Frame.X; ny = superView.Frame.Y;
+			}
+
+			return superView;
+		}
+
+		View GetSuperView (View view)
+		{
+			if (view.SuperView == null) {
+				return Application.Top;
+			}
+			var superView = view.SuperView;
+			if (superView.GetType ().Name == "ContentView") {
+				return superView.SuperView;
+			}
 			return superView;
 		}
 
@@ -670,6 +713,10 @@ namespace Terminal.Gui {
 			foreach (var top in Subviews) {
 				if (top is Toplevel) {
 					PositionToplevel ((Toplevel)top);
+				} else if (top.GetType ().Name == "ContentView") {
+					foreach (var subTop in top.Subviews.Where (v => v is Toplevel)) {
+						PositionToplevel ((Toplevel)subTop);
+					}
 				}
 			}
 		}
@@ -682,16 +729,19 @@ namespace Terminal.Gui {
 		{
 			var superView = EnsureVisibleBounds (top, top.Frame.X, top.Frame.Y,
 				out int nx, out int ny, out _, out View sb);
+			if (superView != null && superView == top && superView == Application.Top) {
+				return;
+			}
 			bool layoutSubviews = false;
-			if ((top?.SuperView != null || (top != Application.Top && top.Modal)
-				|| (top?.SuperView == null && top.IsMdiChild))
-				&& (nx > top.Frame.X || ny > top.Frame.Y) && top.LayoutStyle == LayoutStyle.Computed) {
+			if ((superView != null || (top != Application.Top && top.Modal)
+				|| (superView == null && top.IsMdiChild))
+				&& (nx != top.Frame.X || ny != top.Frame.Y) && top.LayoutStyle == LayoutStyle.Computed) {
 
-				if ((top.X == null || top.X is Pos.PosAbsolute) && top.Bounds.X != nx) {
+				if ((top.X == null || top.X is Pos.PosAbsolute) && top.Frame.X != nx) {
 					top.X = nx;
 					layoutSubviews = true;
 				}
-				if ((top.Y == null || top.Y is Pos.PosAbsolute) && top.Bounds.Y != ny) {
+				if ((top.Y == null || top.Y is Pos.PosAbsolute) && top.Frame.Y != ny) {
 					top.Y = ny;
 					layoutSubviews = true;
 				}
@@ -754,7 +804,7 @@ namespace Terminal.Gui {
 			base.Redraw (Bounds);
 		}
 
-		bool OutsideTopFrame (Toplevel top)
+		internal bool OutsideTopFrame (Toplevel top)
 		{
 			if (top.Frame.X > Driver.Cols || top.Frame.Y > Driver.Rows) {
 				return true;

+ 26 - 1
Terminal.Gui/Core/Window.cs

@@ -11,6 +11,7 @@
 
 using System;
 using System.Collections;
+using System.Linq;
 using NStack;
 
 namespace Terminal.Gui {
@@ -255,11 +256,13 @@ namespace Terminal.Gui {
 			contentView.Add (view);
 			if (view.CanFocus) {
 				CanFocus = true;
+				if (contentView.HasFocus && contentView.MostFocused == null) {
+					view.SetFocus ();
+				}
 			}
 			AddMenuStatusBar (view);
 		}
 
-
 		/// <inheritdoc/>
 		public override void Remove (View view)
 		{
@@ -288,6 +291,28 @@ namespace Terminal.Gui {
 			if (!NeedDisplay.IsEmpty || ChildNeedsDisplay || LayoutNeeded) {
 				Driver.SetAttribute (GetNormalColor ());
 				Clear ();
+				var savedFrame = Frame;
+				PositionToplevels ();
+				if (Application.MdiTop != null && SuperView == null && this != Application.Top && LayoutStyle == LayoutStyle.Computed) {
+					SetRelativeLayout (Application.Top.Frame);
+					if (Frame != savedFrame) {
+						Application.Top.SetNeedsDisplay ();
+						Application.Top.Redraw (Application.Top.Bounds);
+						Redraw (Bounds);
+					}
+				}
+				LayoutSubviews ();
+				if (this == Application.MdiTop) {
+					foreach (var top in Application.MdiChildes.AsEnumerable ().Reverse ()) {
+						if (top.Frame.IntersectsWith (bounds)) {
+							if (top != this && !top.IsCurrentTop && !OutsideTopFrame (top) && top.Visible) {
+								top.SetNeedsLayout ();
+								top.SetNeedsDisplay (top.Bounds);
+								top.Redraw (top.Bounds);
+							}
+						}
+					}
+				}
 				contentView.SetNeedsDisplay ();
 			}
 			var savedClip = contentView.ClipToBounds ();

+ 4 - 0
Terminal.Gui/Views/Menu.cs

@@ -1147,6 +1147,8 @@ namespace Terminal.Gui {
 				action ();
 				return false;
 			});
+
+			CloseAllMenus ();
 		}
 
 		/// <summary>
@@ -1465,6 +1467,8 @@ namespace Terminal.Gui {
 						selected = -1;
 					}
 					LastFocused.SetFocus ();
+				} else if (LastFocused == null && !IsMenuOpen) {
+					Application.Current?.FocusFirst ();
 				} else {
 					SetFocus ();
 					PositionCursor ();

+ 1 - 1
UICatalog/Scenarios/BackgroundWorkerCollection.cs

@@ -327,7 +327,7 @@ namespace UICatalog.Scenarios {
 				};
 				Add (listView);
 
-				start = new Button ("Start") { IsDefault = true };
+				start = new Button ("Start") { IsDefault = true, ClearOnVisibleFalse = false };
 				start.Clicked += () => {
 					Staging = new Staging (DateTime.Now);
 					RequestStop ();

+ 317 - 0
UICatalog/Scenarios/CenteredWindowInsideMdiContainerWindow.cs

@@ -0,0 +1,317 @@
+using Terminal.Gui;
+
+namespace UICatalog.Scenarios {
+	[ScenarioMetadata (Name: "CenteredWindowInsideMdiContainerWindow", Description: "Centered Window Inside MdiContainer Window")]
+	[ScenarioCategory ("Controls")]
+	public class CenteredWindowInsideMdiContainerWindow : Scenario {
+		public override void Init (ColorScheme colorScheme)
+		{
+			Application.Run<ParentWindowMdiContainerClass> ();
+			Application.Shutdown ();
+		}
+
+		public override void Run ()
+		{
+		}
+	}
+
+
+	//------------------------------------------------------------------------------
+
+	//  <auto-generated>
+	//      This code was generated by:
+	//        TerminalGuiDesigner v1.0.24.0
+	//      You can make changes to this file and they will not be overwritten when saving.
+	//  </auto-generated>
+	// -----------------------------------------------------------------------------
+
+	public partial class ParentWindowMdiContainerClass {
+
+		private MdiChildWindowClass _childWindow;
+
+		public ParentWindowMdiContainerClass ()
+		{
+			InitializeComponent ();
+			// MenuBar
+			createChildMenuItem.CanExecute = CanExecuteCreateChildWindow;
+			createChildMenuItem.Action = CreateChildWindow;
+			centerChildMenuItem.CanExecute = CanExecuteCenterChildWindow;
+			centerChildMenuItem.Action = CenterChildWindow;
+			hideShowChildMenuItem.CanExecute = CanExecuteHideShowChildWindow;
+			hideShowChildMenuItem.Action = HideShowChildWindow;
+			borderChildMenuItem.CanExecute = CanExecuteCenterChildWindow;
+			borderChildMenuItem.Action = BorderToggleChildWindow;
+			parentMenu.Action = BorderToggleParentWindow;
+			// StatusBar
+			createChildStatusItem.CanExecute = CanExecuteCreateChildWindow;
+			createChildStatusItem.Action = CreateChildWindow;
+			centerChildStatusItem.CanExecute = CanExecuteCenterChildWindow;
+			centerChildStatusItem.Action = CenterChildWindow;
+			hideShowChildStatusItem.CanExecute = CanExecuteHideShowChildWindow;
+			hideShowChildStatusItem.Action = HideShowChildWindow;
+			borderChildStatusItem.CanExecute = CanExecuteCenterChildWindow;
+			borderChildStatusItem.Action = BorderToggleChildWindow;
+			borderParentStatusItem.Action = BorderToggleParentWindow;
+
+			KeyPress += ParentWindowClass_KeyPress;
+		}
+
+		private void BorderToggleParentWindow ()
+		{
+			if (Border.BorderStyle == BorderStyle.None) {
+				Border.BorderStyle = BorderStyle.Single;
+				// MenuBar
+				parentMenu.Title = "Borderless _Parent";
+				// StatusBar
+				borderParentStatusItem.Title = "~CTRL-F1~ Borderless Parent";
+			} else {
+				Border.BorderStyle = BorderStyle.None;
+				Border.DrawMarginFrame = false;
+				// MenuBar
+				parentMenu.Title = "Border _Parent";
+				// StatusBar
+				borderParentStatusItem.Title = "~CTRL-F1~ Border Parent";
+			}
+		}
+
+		private void BorderToggleChildWindow ()
+		{
+			if (_childWindow.Border.BorderStyle == BorderStyle.None) {
+				_childWindow.Border.BorderStyle = BorderStyle.Single;
+				// MenuBar
+				borderChildMenuItem.Title = "_Borderless Child";
+				// StatusBar
+				borderChildStatusItem.Title = "~CTRL-F2~ Borderless Child";
+			} else {
+				_childWindow.Border.BorderStyle = BorderStyle.None;
+				_childWindow.Border.DrawMarginFrame = false;
+				// MenuBar
+				borderChildMenuItem.Title = "_Border Child";
+				// StatusBar
+				borderChildStatusItem.Title = "~CTRL-F2~ Border Child";
+			}
+		}
+
+		private void ParentWindowClass_KeyPress (KeyEventEventArgs obj)
+		{
+			switch (obj.KeyEvent.Key) {
+			case Key.F8:
+				menuBar.Visible = !menuBar.Visible;
+				obj.Handled = true;
+				break;
+			case Key.F10:
+				statusBar.Visible = !statusBar.Visible;
+				obj.Handled = true;
+				break;
+			}
+		}
+
+		private bool CanExecuteCreateChildWindow () => _childWindow == null;
+
+		private void CreateChildWindow ()
+		{
+			_childWindow ??= new MdiChildWindowClass ();
+			Application.Top.SetNeedsDisplay ();
+			Application.Run (_childWindow);
+		}
+
+		private bool CanExecuteCenterChildWindow () => _childWindow != null && _childWindow.Visible;
+
+		private void CenterChildWindow ()
+		{
+			_childWindow.X = Pos.Center ();
+			_childWindow.Y = Pos.Center ();
+		}
+
+		private bool CanExecuteHideShowChildWindow () => _childWindow != null;
+
+		private void HideShowChildWindow ()
+		{
+			if (_childWindow.Visible) {
+				_childWindow.Visible = false;
+				// MenuBar
+				hideShowChildMenuItem.Title = "Un_Hide Child";
+				// StatusBar
+				hideShowChildStatusItem.Title = "~CTRL-F7~ UnHide Child";
+				SetNeedsDisplay ();
+			} else {
+				_childWindow.Visible = true;
+				// MenuBar
+				hideShowChildMenuItem.Title = "_Hide Child";
+				// StatusBar
+				hideShowChildStatusItem.Title = "~CTRL-F7~ Hide Child";
+				ShowChild (_childWindow);
+			}
+		}
+	}
+
+	//------------------------------------------------------------------------------
+
+	//  <auto-generated>
+	//      This code was generated by:
+	//        TerminalGuiDesigner v1.0.24.0
+	//      Changes to this file may cause incorrect behavior and will be lost if
+	//      the code is regenerated.
+	//  </auto-generated>
+	// -----------------------------------------------------------------------------
+
+	public partial class ParentWindowMdiContainerClass : Terminal.Gui.Window {
+
+		private Terminal.Gui.MenuBar menuBar;
+
+		private Terminal.Gui.MenuBarItem childMenu;
+
+		private Terminal.Gui.MenuItem createChildMenuItem;
+		private Terminal.Gui.MenuItem centerChildMenuItem;
+		private Terminal.Gui.MenuItem hideShowChildMenuItem;
+		private Terminal.Gui.MenuItem borderChildMenuItem;
+
+		private Terminal.Gui.MenuBarItem parentMenu;
+
+		private Terminal.Gui.StatusBar statusBar;
+
+		private Terminal.Gui.StatusItem createChildStatusItem;
+		private Terminal.Gui.StatusItem centerChildStatusItem;
+		private Terminal.Gui.StatusItem hideShowChildStatusItem;
+		private Terminal.Gui.StatusItem borderChildStatusItem;
+		private Terminal.Gui.StatusItem borderParentStatusItem;
+
+		private void InitializeComponent ()
+		{
+			this.IsMdiContainer = true;
+			this.menuBar = new Terminal.Gui.MenuBar ();
+			this.Width = Dim.Fill (0);
+			this.Height = Dim.Fill (0);
+			this.X = 0;
+			this.Y = 0;
+			this.Modal = false;
+			this.Border.BorderStyle = Terminal.Gui.BorderStyle.Single;
+			this.Border.BorderBrush = Terminal.Gui.Color.White;
+			this.Border.Effect3D = false;
+			this.Border.Effect3DBrush = null;
+			this.Border.DrawMarginFrame = true;
+			this.TextAlignment = Terminal.Gui.TextAlignment.Left;
+			this.Title = "Mdi Parent Window (Press F8 to Hide/Show MenuBar)(Press F10 to Hide/Show StatusBar)";
+			this.menuBar.Width = Dim.Fill (0);
+			this.menuBar.Height = 1;
+			this.menuBar.X = 0;
+			this.menuBar.Y = 0;
+			this.menuBar.Data = "menuBar";
+			this.menuBar.TextAlignment = Terminal.Gui.TextAlignment.Left;
+			this.childMenu = new Terminal.Gui.MenuBarItem ();
+			this.childMenu.Title = "Ch_ild";
+			this.parentMenu = new Terminal.Gui.MenuBarItem ();
+			this.parentMenu.Title = "Borderless _Parent";
+			this.menuBar.Menus = new Terminal.Gui.MenuBarItem [] {
+					this.childMenu, this.parentMenu};
+			this.createChildMenuItem = new Terminal.Gui.MenuItem ();
+			this.createChildMenuItem.Title = "_Create Child";
+			this.createChildMenuItem.Data = "createChildMenuItem";
+			this.centerChildMenuItem = new Terminal.Gui.MenuItem ();
+			this.centerChildMenuItem.Title = "C_enter Child";
+			this.centerChildMenuItem.Data = "centerChildMenuItem";
+			this.hideShowChildMenuItem = new Terminal.Gui.MenuItem ();
+			this.hideShowChildMenuItem.Title = "_Hide Child";
+			this.hideShowChildMenuItem.Data = "hideShowChildMenuItem";
+			this.borderChildMenuItem = new Terminal.Gui.MenuItem ();
+			this.borderChildMenuItem.Title = "_Borderless Child";
+			this.borderChildMenuItem.Data = "borderChildMenuItem";
+			this.childMenu.Children = new Terminal.Gui.MenuItem [] {
+					this.createChildMenuItem, this.centerChildMenuItem, this.hideShowChildMenuItem, this.borderChildMenuItem};
+			this.Add (this.menuBar);
+			this.statusBar = new Terminal.Gui.StatusBar ();
+			this.statusBar.Width = Dim.Fill ();
+			this.statusBar.Height = 1;
+			this.statusBar.X = 0;
+			this.statusBar.Y = Pos.AnchorEnd (1);
+			this.statusBar.Data = "statusBar";
+			this.statusBar.TextAlignment = Terminal.Gui.TextAlignment.Left;
+			this.createChildStatusItem = new Terminal.Gui.StatusItem (Key.F5 | Key.CtrlMask, "~CTRL-F5~ Create Child", null);
+			this.createChildStatusItem.Data = "createChildStatusItem";
+			this.centerChildStatusItem = new Terminal.Gui.StatusItem (Key.F6 | Key.CtrlMask, "~CTRL-F6~ Center Child", null);
+			this.centerChildStatusItem.Data = "centerChildStatusItem";
+			this.hideShowChildStatusItem = new Terminal.Gui.StatusItem (Key.F7 | Key.CtrlMask, "~CTRL-F7~ Hide Child", null);
+			this.hideShowChildStatusItem.Data = "hideShowChildStatusItem";
+			this.borderChildStatusItem = new Terminal.Gui.StatusItem (Key.F2 | Key.CtrlMask, "~CTRL-F2~ Borderless Child", null);
+			this.borderChildStatusItem.Data = "borderChildStatusItem";
+			this.borderParentStatusItem = new Terminal.Gui.StatusItem (Key.F1 | Key.CtrlMask, "~CTRL-F1~ Borderless Parent", null);
+			this.borderParentStatusItem.Data = "borderParentStatusItem";
+			this.statusBar.Items = new StatusItem [] {
+					this.createChildStatusItem, this.centerChildStatusItem, this.hideShowChildStatusItem, this.borderChildStatusItem, this.borderParentStatusItem};
+			this.Add (statusBar);
+		}
+	}
+
+	//------------------------------------------------------------------------------
+
+	//  <auto-generated>
+	//      This code was generated by:
+	//        TerminalGuiDesigner v1.0.24.0
+	//      You can make changes to this file and they will not be overwritten when saving.
+	//  </auto-generated>
+	// -----------------------------------------------------------------------------
+
+	public partial class MdiChildWindowClass {
+
+		public MdiChildWindowClass ()
+		{
+			InitializeComponent ();
+			this.button1.Clicked += Button1_Clicked;
+		}
+
+		private void Button1_Clicked ()
+		{
+			Terminal.Gui.MessageBox.Query ("Press Me", "I hope you like the child window behavior!", "Ok");
+		}
+	}
+
+
+	//------------------------------------------------------------------------------
+
+	//  <auto-generated>
+	//      This code was generated by:
+	//        TerminalGuiDesigner v1.0.24.0
+	//      Changes to this file may cause incorrect behavior and will be lost if
+	//      the code is regenerated.
+	//  </auto-generated>
+	// -----------------------------------------------------------------------------
+
+	public partial class MdiChildWindowClass : Terminal.Gui.Window {
+
+		private Terminal.Gui.Button button1;
+		private Terminal.Gui.Label Label1;
+		private Terminal.Gui.Label Label2;
+		private Terminal.Gui.Label Label3;
+		private Terminal.Gui.Label Label4;
+
+		private void InitializeComponent ()
+		{
+			this.Width = 80;
+			this.Height = 16;
+			this.X = Pos.Center ();
+			this.Y = Pos.Center ();
+			this.ColorScheme = Colors.TopLevel;
+			this.Modal = false;
+			this.Border.BorderStyle = Terminal.Gui.BorderStyle.Single;
+			this.Border.BorderBrush = Terminal.Gui.Color.White;
+			this.Border.Effect3D = false;
+			this.Border.Effect3DBrush = null;
+			this.Border.DrawMarginFrame = true;
+			this.TextAlignment = Terminal.Gui.TextAlignment.Left;
+			this.Title = "Child Window";
+			this.button1 = new Terminal.Gui.Button ();
+			this.button1.X = Pos.Center ();
+			this.button1.Y = Pos.Center ();
+			this.button1.Text = "Press Me";
+			this.Label1 = new Terminal.Gui.Label ("TL");
+			this.Label2 = new Terminal.Gui.Label ("TR");
+			this.Label2.X = Pos.AnchorEnd (2);
+			this.Label3 = new Terminal.Gui.Label ("BL");
+			this.Label3.Y = Pos.AnchorEnd (1);
+			this.Label4 = new Terminal.Gui.Label ("BR");
+			this.Label4.X = Pos.AnchorEnd (2);
+			this.Label4.Y = Pos.AnchorEnd (1);
+			this.Add (this.button1, this.Label1, this.Label2, this.Label3, this.Label4);
+		}
+	}
+}

+ 314 - 0
UICatalog/Scenarios/CenteredWindowInsideWindow.cs

@@ -0,0 +1,314 @@
+using Terminal.Gui;
+
+namespace UICatalog.Scenarios {
+	[ScenarioMetadata (Name: "CenteredWindowInsideWindow", Description: "Centered Window Inside Window")]
+	[ScenarioCategory ("Controls")]
+	public class CenteredWindowInsideWindow : Scenario {
+		public override void Init (ColorScheme colorScheme)
+		{
+			Application.Run<ParentWindowClass> ();
+			Application.Shutdown ();
+		}
+
+		public override void Run ()
+		{
+		}
+	}
+
+
+	//------------------------------------------------------------------------------
+
+	//  <auto-generated>
+	//      This code was generated by:
+	//        TerminalGuiDesigner v1.0.24.0
+	//      You can make changes to this file and they will not be overwritten when saving.
+	//  </auto-generated>
+	// -----------------------------------------------------------------------------
+
+	public partial class ParentWindowClass {
+
+		private ChildWindowClass _childWindow;
+
+		public ParentWindowClass ()
+		{
+			InitializeComponent ();
+			// MenuBar
+			createChildMenuItem.CanExecute = CanExecuteCreateChildWindow;
+			createChildMenuItem.Action = CreateChildWindow;
+			centerChildMenuItem.CanExecute = CanExecuteCenterChildWindow;
+			centerChildMenuItem.Action = CenterChildWindow;
+			hideShowChildMenuItem.CanExecute = CanExecuteHideShowChildWindow;
+			hideShowChildMenuItem.Action = HideShowChildWindow;
+			borderChildMenuItem.CanExecute = CanExecuteCenterChildWindow;
+			borderChildMenuItem.Action = BorderToggleChildWindow;
+			parentMenu.Action = BorderToggleParentWindow;
+			// StatusBar
+			createChildStatusItem.CanExecute = CanExecuteCreateChildWindow;
+			createChildStatusItem.Action = CreateChildWindow;
+			centerChildStatusItem.CanExecute = CanExecuteCenterChildWindow;
+			centerChildStatusItem.Action = CenterChildWindow;
+			hideShowChildStatusItem.CanExecute = CanExecuteHideShowChildWindow;
+			hideShowChildStatusItem.Action = HideShowChildWindow;
+			borderChildStatusItem.CanExecute = CanExecuteCenterChildWindow;
+			borderChildStatusItem.Action = BorderToggleChildWindow;
+			borderParentStatusItem.Action = BorderToggleParentWindow;
+
+			KeyPress += ParentWindowClass_KeyPress;
+		}
+
+		private void BorderToggleParentWindow ()
+		{
+			if (Border.BorderStyle == BorderStyle.None) {
+				Border.BorderStyle = BorderStyle.Single;
+				// MenuBar
+				parentMenu.Title = "Borderless _Parent";
+				// StatusBar
+				borderParentStatusItem.Title = "~CTRL-F1~ Borderless Parent";
+			} else {
+				Border.BorderStyle = BorderStyle.None;
+				Border.DrawMarginFrame = false;
+				// MenuBar
+				parentMenu.Title = "Border _Parent";
+				// StatusBar
+				borderParentStatusItem.Title = "~CTRL-F1~ Border Parent";
+			}
+		}
+
+		private void BorderToggleChildWindow ()
+		{
+			if (_childWindow.Border.BorderStyle == BorderStyle.None) {
+				_childWindow.Border.BorderStyle = BorderStyle.Single;
+				// MenuBar
+				borderChildMenuItem.Title = "_Borderless Child";
+				// StatusBar
+				borderChildStatusItem.Title = "~CTRL-F2~ Borderless Child";
+			} else {
+				_childWindow.Border.BorderStyle = BorderStyle.None;
+				_childWindow.Border.DrawMarginFrame = false;
+				// MenuBar
+				borderChildMenuItem.Title = "_Border Child";
+				// StatusBar
+				borderChildStatusItem.Title = "~CTRL-F2~ Border Child";
+			}
+		}
+
+		private void ParentWindowClass_KeyPress (KeyEventEventArgs obj)
+		{
+			switch (obj.KeyEvent.Key) {
+			case Key.F8:
+				menuBar.Visible = !menuBar.Visible;
+				obj.Handled = true;
+				break;
+			case Key.F10:
+				statusBar.Visible = !statusBar.Visible;
+				obj.Handled = true;
+				break;
+			}
+		}
+
+		private bool CanExecuteCreateChildWindow () => _childWindow == null;
+
+		private void CreateChildWindow ()
+		{
+			_childWindow ??= new ChildWindowClass ();
+			Add (_childWindow);
+		}
+
+		private bool CanExecuteCenterChildWindow () => _childWindow != null && _childWindow.Visible;
+
+		private void CenterChildWindow ()
+		{
+			_childWindow.X = Pos.Center ();
+			_childWindow.Y = Pos.Center ();
+			_childWindow.SetNeedsDisplay ();
+		}
+
+		private bool CanExecuteHideShowChildWindow () => _childWindow != null;
+
+		private void HideShowChildWindow ()
+		{
+			if (_childWindow.Visible) {
+				_childWindow.Visible = false;
+				// MenuBar
+				hideShowChildMenuItem.Title = "Un_Hide Child";
+				// StatusBar
+				hideShowChildStatusItem.Title = "~CTRL-F7~ UnHide Child";
+			} else {
+				_childWindow.Visible = true;
+				// MenuBar
+				hideShowChildMenuItem.Title = "_Hide Child";
+				// StatusBar
+				hideShowChildStatusItem.Title = "~CTRL-F7~ Hide Child";
+			}
+		}
+	}
+
+	//------------------------------------------------------------------------------
+
+	//  <auto-generated>
+	//      This code was generated by:
+	//        TerminalGuiDesigner v1.0.24.0
+	//      Changes to this file may cause incorrect behavior and will be lost if
+	//      the code is regenerated.
+	//  </auto-generated>
+	// -----------------------------------------------------------------------------
+
+	public partial class ParentWindowClass : Terminal.Gui.Window {
+
+		private Terminal.Gui.MenuBar menuBar;
+
+		private Terminal.Gui.MenuBarItem childMenu;
+
+		private Terminal.Gui.MenuItem createChildMenuItem;
+		private Terminal.Gui.MenuItem centerChildMenuItem;
+		private Terminal.Gui.MenuItem hideShowChildMenuItem;
+		private Terminal.Gui.MenuItem borderChildMenuItem;
+
+		private Terminal.Gui.MenuBarItem parentMenu;
+
+		private Terminal.Gui.StatusBar statusBar;
+
+		private Terminal.Gui.StatusItem createChildStatusItem;
+		private Terminal.Gui.StatusItem centerChildStatusItem;
+		private Terminal.Gui.StatusItem hideShowChildStatusItem;
+		private Terminal.Gui.StatusItem borderChildStatusItem;
+		private Terminal.Gui.StatusItem borderParentStatusItem;
+
+		private void InitializeComponent ()
+		{
+			this.menuBar = new Terminal.Gui.MenuBar ();
+			this.Width = Dim.Fill (0);
+			this.Height = Dim.Fill (0);
+			this.X = 0;
+			this.Y = 0;
+			this.Modal = false;
+			this.Border.BorderStyle = Terminal.Gui.BorderStyle.Single;
+			this.Border.BorderBrush = Terminal.Gui.Color.White;
+			this.Border.Effect3D = false;
+			this.Border.Effect3DBrush = null;
+			this.Border.DrawMarginFrame = true;
+			this.TextAlignment = Terminal.Gui.TextAlignment.Left;
+			this.Title = "Parent Window (Press F8 to Hide/Show MenuBar)(Press F10 to Hide/Show StatusBar)";
+			this.menuBar.Width = Dim.Fill (0);
+			this.menuBar.Height = 1;
+			this.menuBar.X = 0;
+			this.menuBar.Y = 0;
+			this.menuBar.Data = "menuBar";
+			this.menuBar.TextAlignment = Terminal.Gui.TextAlignment.Left;
+			this.childMenu = new Terminal.Gui.MenuBarItem ();
+			this.childMenu.Title = "Ch_ild";
+			this.parentMenu = new Terminal.Gui.MenuBarItem ();
+			this.parentMenu.Title = "Borderless _Parent";
+			this.menuBar.Menus = new Terminal.Gui.MenuBarItem [] {
+					this.childMenu, this.parentMenu};
+			this.createChildMenuItem = new Terminal.Gui.MenuItem ();
+			this.createChildMenuItem.Title = "_Create Child";
+			this.createChildMenuItem.Data = "createChildMenuItem";
+			this.centerChildMenuItem = new Terminal.Gui.MenuItem ();
+			this.centerChildMenuItem.Title = "C_enter Child";
+			this.centerChildMenuItem.Data = "centerChildMenuItem";
+			this.hideShowChildMenuItem = new Terminal.Gui.MenuItem ();
+			this.hideShowChildMenuItem.Title = "_Hide Child";
+			this.hideShowChildMenuItem.Data = "hideChildMenuItem";
+			this.borderChildMenuItem = new Terminal.Gui.MenuItem ();
+			this.borderChildMenuItem.Title = "_Borderless Child";
+			this.borderChildMenuItem.Data = "borderChildMenuItem";
+			this.childMenu.Children = new Terminal.Gui.MenuItem [] {
+					this.createChildMenuItem, this.centerChildMenuItem, this.hideShowChildMenuItem, this.borderChildMenuItem};
+			this.Add (this.menuBar);
+			this.statusBar = new Terminal.Gui.StatusBar ();
+			this.statusBar.Width = Dim.Fill ();
+			this.statusBar.Height = 1;
+			this.statusBar.X = 0;
+			this.statusBar.Y = Pos.AnchorEnd (1);
+			this.statusBar.Data = "statusBar";
+			this.statusBar.TextAlignment = Terminal.Gui.TextAlignment.Left;
+			this.createChildStatusItem = new Terminal.Gui.StatusItem (Key.F5 | Key.CtrlMask, "~CTRL-F5~ Create Child", null);
+			this.createChildStatusItem.Data = "createChildStatusItem";
+			this.centerChildStatusItem = new Terminal.Gui.StatusItem (Key.F6 | Key.CtrlMask, "~CTRL-F6~ Center Child", null);
+			this.centerChildStatusItem.Data = "centerChildStatusItem";
+			this.hideShowChildStatusItem = new Terminal.Gui.StatusItem (Key.F7 | Key.CtrlMask, "~CTRL-F7~ Hide Child", null);
+			this.hideShowChildStatusItem.Data = "hideChildStatusItem";
+			this.borderChildStatusItem = new Terminal.Gui.StatusItem (Key.F2 | Key.CtrlMask, "~CTRL-F2~ Borderless Child", null);
+			this.borderChildStatusItem.Data = "borderChildStatusItem";
+			this.borderParentStatusItem = new Terminal.Gui.StatusItem (Key.F1 | Key.CtrlMask, "~CTRL-F1~ Borderless Parent", null);
+			this.borderParentStatusItem.Data = "borderParentStatusItem";
+			this.statusBar.Items = new StatusItem [] {
+					this.createChildStatusItem, this.centerChildStatusItem, this.hideShowChildStatusItem, this.borderChildStatusItem, this.borderParentStatusItem};
+			this.Add (statusBar);
+		}
+	}
+
+	//------------------------------------------------------------------------------
+
+	//  <auto-generated>
+	//      This code was generated by:
+	//        TerminalGuiDesigner v1.0.24.0
+	//      You can make changes to this file and they will not be overwritten when saving.
+	//  </auto-generated>
+	// -----------------------------------------------------------------------------
+
+	public partial class ChildWindowClass {
+
+		public ChildWindowClass ()
+		{
+			InitializeComponent ();
+			this.button1.Clicked += Button1_Clicked;
+		}
+
+		private void Button1_Clicked ()
+		{
+			Terminal.Gui.MessageBox.Query ("Press Me", "I hope you like the child window behavior!", "Ok");
+		}
+	}
+
+
+	//------------------------------------------------------------------------------
+
+	//  <auto-generated>
+	//      This code was generated by:
+	//        TerminalGuiDesigner v1.0.24.0
+	//      Changes to this file may cause incorrect behavior and will be lost if
+	//      the code is regenerated.
+	//  </auto-generated>
+	// -----------------------------------------------------------------------------
+
+	public partial class ChildWindowClass : Terminal.Gui.Window {
+
+		private Terminal.Gui.Button button1;
+		private Terminal.Gui.Label Label1;
+		private Terminal.Gui.Label Label2;
+		private Terminal.Gui.Label Label3;
+		private Terminal.Gui.Label Label4;
+
+		private void InitializeComponent ()
+		{
+			this.Width = 80;
+			this.Height = 16;
+			this.X = Pos.Center ();
+			this.Y = Pos.Center ();
+			this.ColorScheme = Colors.TopLevel;
+			this.Modal = false;
+			this.Border.BorderStyle = Terminal.Gui.BorderStyle.Single;
+			this.Border.BorderBrush = Terminal.Gui.Color.White;
+			this.Border.Effect3D = false;
+			this.Border.Effect3DBrush = null;
+			this.Border.DrawMarginFrame = true;
+			this.TextAlignment = Terminal.Gui.TextAlignment.Left;
+			this.Title = "Child Window";
+			this.button1 = new Terminal.Gui.Button ();
+			this.button1.X = Pos.Center ();
+			this.button1.Y = Pos.Center ();
+			this.button1.Text = "Press Me";
+			this.Label1 = new Terminal.Gui.Label ("TL");
+			this.Label2 = new Terminal.Gui.Label ("TR");
+			this.Label2.X = Pos.AnchorEnd (2);
+			this.Label3 = new Terminal.Gui.Label ("BL");
+			this.Label3.Y = Pos.AnchorEnd (1);
+			this.Label4 = new Terminal.Gui.Label ("BR");
+			this.Label4.X = Pos.AnchorEnd (2);
+			this.Label4.Y = Pos.AnchorEnd (1);
+			this.Add (this.button1, this.Label1, this.Label2, this.Label3, this.Label4);
+		}
+	}
+}

+ 6 - 1
UICatalog/Scenarios/DynamicMenuBar.cs

@@ -16,7 +16,12 @@ namespace UICatalog.Scenarios {
 		public override void Init (ColorScheme colorScheme)
 		{
 			Application.Init ();
-			Application.Top.Add (new DynamicMenuBarSample ($"CTRL-Q to Close - Scenario: {GetName ()}"));
+			Application.Run (new DynamicMenuBarSample ($"CTRL-Q to Close - Scenario: {GetName ()}"));
+			Application.Shutdown ();
+		}
+
+		public override void Run ()
+		{
 		}
 
 		public class DynamicMenuItemList {

+ 6 - 1
UICatalog/Scenarios/DynamicStatusBar.cs

@@ -15,7 +15,12 @@ namespace UICatalog.Scenarios {
 		public override void Init (ColorScheme colorScheme)
 		{
 			Application.Init ();
-			Application.Top.Add (new DynamicStatusBarSample ($"CTRL-Q to Close - Scenario: {GetName ()}"));
+			Application.Run (new DynamicStatusBarSample ($"CTRL-Q to Close - Scenario: {GetName ()}"));
+			Application.Shutdown ();
+		}
+
+		public override void Run ()
+		{
 		}
 
 		public class DynamicStatusItemList {

+ 44 - 21
UnitTests/TopLevels/MdiTests.cs

@@ -68,24 +68,24 @@ namespace Terminal.Gui.TopLevelTests {
 			var iterations = 4;
 
 			top1.Ready += () => {
-				Assert.Null (Application.MdiChildes);
+				Assert.Empty (Application.MdiChildes);
 				Application.Run (top2);
 			};
 			top2.Ready += () => {
-				Assert.Null (Application.MdiChildes);
+				Assert.Empty (Application.MdiChildes);
 				Application.Run (top3);
 			};
 			top3.Ready += () => {
-				Assert.Null (Application.MdiChildes);
+				Assert.Empty (Application.MdiChildes);
 				Application.Run (top4);
 			};
 			top4.Ready += () => {
-				Assert.Null (Application.MdiChildes);
+				Assert.Empty (Application.MdiChildes);
 				Application.Run (d);
 			};
 
 			d.Ready += () => {
-				Assert.Null (Application.MdiChildes);
+				Assert.Empty (Application.MdiChildes);
 				// This will close the d because on a not MdiContainer the Application.Current it always used.
 				Application.RequestStop (top1);
 				Assert.True (Application.Current == d);
@@ -94,19 +94,26 @@ namespace Terminal.Gui.TopLevelTests {
 			d.Closed += (e) => Application.RequestStop (top1);
 
 			Application.Iteration += () => {
-				Assert.Null (Application.MdiChildes);
-				if (iterations == 4) 					Assert.True (Application.Current == d);
-else if (iterations == 3) 					Assert.True (Application.Current == top4);
-else if (iterations == 2) 					Assert.True (Application.Current == top3);
-else if (iterations == 1) 					Assert.True (Application.Current == top2);
-else 					Assert.True (Application.Current == top1);
+				Assert.Empty (Application.MdiChildes);
+				if (iterations == 4) {
+					Assert.True (Application.Current == d);
+				} else if (iterations == 3) {
+					Assert.True (Application.Current == top4);
+				} else if (iterations == 2) {
+					Assert.True (Application.Current == top3);
+				} else if (iterations == 1) {
+					Assert.True (Application.Current == top2);
+				} else {
+					Assert.True (Application.Current == top1);
+				}
+
 				Application.RequestStop (top1);
 				iterations--;
 			};
 
 			Application.Run (top1);
 
-			Assert.Null (Application.MdiChildes);
+			Assert.Empty (Application.MdiChildes);
 		}
 
 		class Mdi : Toplevel {
@@ -166,7 +173,9 @@ else 					Assert.True (Application.Current == top1);
 					Assert.False (d.Running);
 				} else {
 					Assert.Equal (iterations, Application.MdiChildes.Count);
-					for (int i = 0; i < iterations; i++) 						Assert.Equal ((iterations - i + 1).ToString (), Application.MdiChildes [i].Id);
+					for (int i = 0; i < iterations; i++) {
+						Assert.Equal ((iterations - i + 1).ToString (), Application.MdiChildes [i].Id);
+					}
 				}
 				iterations--;
 			};
@@ -224,7 +233,9 @@ else 					Assert.True (Application.Current == top1);
 					Assert.False (d.Running);
 				} else {
 					Assert.Equal (iterations, Application.MdiChildes.Count);
-					for (int i = 0; i < iterations; i++) 						Assert.Equal ((iterations - i + 1).ToString (), Application.MdiChildes [i].Id);
+					for (int i = 0; i < iterations; i++) {
+						Assert.Equal ((iterations - i + 1).ToString (), Application.MdiChildes [i].Id);
+					}
 				}
 				iterations--;
 			};
@@ -283,7 +294,9 @@ else 					Assert.True (Application.Current == top1);
 					Assert.False (d.Running);
 				} else {
 					Assert.Equal (iterations, Application.MdiChildes.Count);
-					for (int i = 0; i < iterations; i++) 						Assert.Equal ((iterations - i + 1).ToString (), Application.MdiChildes [i].Id);
+					for (int i = 0; i < iterations; i++) {
+						Assert.Equal ((iterations - i + 1).ToString (), Application.MdiChildes [i].Id);
+					}
 				}
 				iterations--;
 			};
@@ -381,7 +394,9 @@ else 					Assert.True (Application.Current == top1);
 					Assert.False (Application.Current.Running);
 				} else {
 					Assert.Equal (iterations, Application.MdiChildes.Count);
-					for (int i = 0; i < iterations; i++) 						Assert.Equal ((iterations - i + 1).ToString (), Application.MdiChildes [i].Id);
+					for (int i = 0; i < iterations; i++) {
+						Assert.Equal ((iterations - i + 1).ToString (), Application.MdiChildes [i].Id);
+					}
 				}
 				iterations--;
 			};
@@ -448,8 +463,10 @@ else 					Assert.True (Application.Current == top1);
 					Assert.True (c4.Running);
 				} else {
 					Assert.Equal (iterations, Application.MdiChildes.Count);
-					for (int i = 0; i < iterations; i++) 						Assert.Equal ((iterations - i + (iterations == 4 && i == 0 ? 2 : 1)).ToString (),
+					for (int i = 0; i < iterations; i++) {
+						Assert.Equal ((iterations - i + (iterations == 4 && i == 0 ? 2 : 1)).ToString (),
 							Application.MdiChildes [i].Id);
+					}
 				}
 				iterations--;
 			};
@@ -571,7 +588,10 @@ else 					Assert.True (Application.Current == top1);
 					};
 
 					stage.Closed += (_) => {
-						if (iterations == 11) 							allStageClosed = true;
+						if (iterations == 11) {
+							allStageClosed = true;
+						}
+
 						Assert.Equal (iterations, Application.MdiChildes.Count);
 						if (running) {
 							stageCompleted = true;
@@ -593,12 +613,15 @@ else 					Assert.True (Application.Current == top1);
 					running = false;
 					Assert.Equal (iterations, Application.MdiChildes.Count);
 
-				} else if (!mdiRequestStop && running && !allStageClosed) 					Assert.Equal (iterations, Application.MdiChildes.Count);
-else if (!mdiRequestStop && !running && allStageClosed) {
+				} else if (!mdiRequestStop && running && !allStageClosed) {
+					Assert.Equal (iterations, Application.MdiChildes.Count);
+				} else if (!mdiRequestStop && !running && allStageClosed) {
 					Assert.Equal (iterations, Application.MdiChildes.Count);
 					mdiRequestStop = true;
 					mdi.RequestStop ();
-				} else 					Assert.Empty (Application.MdiChildes);
+				} else {
+					Assert.Empty (Application.MdiChildes);
+				}
 			};
 
 			Application.Run (mdi);

+ 1877 - 3
UnitTests/TopLevels/ToplevelTests.cs

@@ -1,5 +1,4 @@
 using System;
-using Terminal.Gui;
 using Xunit;
 using Xunit.Abstractions;
 
@@ -212,7 +211,8 @@ namespace Terminal.Gui.TopLevelTests {
 			// top is Application.Top with a menu and without status bar.
 			top.EnsureVisibleBounds (top, 2, 2, out nx, out ny, out mb, out sb);
 			Assert.Equal (0, nx);
-			Assert.Equal (1, ny);
+			// top is Application.Top and doesn't need to positioned itself.
+			Assert.Equal (0, ny);
 			Assert.NotNull (mb);
 			Assert.Null (sb);
 
@@ -222,7 +222,8 @@ namespace Terminal.Gui.TopLevelTests {
 			// top is Application.Top with a menu and status bar.
 			top.EnsureVisibleBounds (top, 2, 2, out nx, out ny, out mb, out sb);
 			Assert.Equal (0, nx);
-			Assert.Equal (1, ny);
+			// top is Application.Top and doesn't need to positioned itself.
+			Assert.Equal (0, ny);
 			Assert.NotNull (mb);
 			Assert.NotNull (sb);
 
@@ -232,6 +233,7 @@ namespace Terminal.Gui.TopLevelTests {
 			// top is Application.Top without a menu and with a status bar.
 			top.EnsureVisibleBounds (top, 2, 2, out nx, out ny, out mb, out sb);
 			Assert.Equal (0, nx);
+			// top is Application.Top and doesn't need to positioned itself.
 			Assert.Equal (0, ny);
 			Assert.Null (mb);
 			Assert.NotNull (sb);
@@ -1139,5 +1141,1877 @@ namespace Terminal.Gui.TopLevelTests {
 			var exception = Record.Exception (() => topChild.ProcessHotKey (new KeyEvent (Key.AltMask, new KeyModifiers { Alt = true })));
 			Assert.Null (exception);
 		}
+
+		private Window Top_With_MenuBar_And_StatusBar (bool borderless = false, bool isMdiContainer = false, bool resize = true)
+		{
+			var top = new Window ();
+			if (borderless) {
+				top.Border.BorderStyle = BorderStyle.None;
+				top.Border.DrawMarginFrame = false;
+			}
+			if (isMdiContainer) {
+				top.IsMdiContainer = true;
+			}
+			var menu = new MenuBar (new MenuBarItem [] {
+				new MenuBarItem("File", new MenuItem [] {
+					new MenuItem ("New", "", null)
+				})
+			});
+			var statusBar = new StatusBar (new StatusItem [] {
+				new StatusItem(Key.F2, "~F2~ File", null)
+			});
+			top.Add (menu, statusBar);
+			if (resize) {
+				((FakeDriver)Application.Driver).SetBufferSize (20, 20);
+			}
+
+			return top;
+		}
+
+		private Window Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels (
+			bool isDimFill = false, bool borderless = false, bool isModal = false)
+		{
+			Window win;
+			if (isDimFill) {
+				win = new Window () { Width = Dim.Fill (10), Height = Dim.Fill (10), ColorScheme = Colors.TopLevel };
+			} else {
+				win = new Window () { Width = 10, Height = 10, ColorScheme = Colors.TopLevel };
+			}
+			if (borderless) {
+				win.Border.BorderStyle = BorderStyle.None;
+				win.Border.DrawMarginFrame = false;
+			}
+			if (isModal) {
+				win.Modal = true;
+			}
+			win.Add (new Label ("TL"),
+				new Label ("TR") { X = Pos.AnchorEnd (2) },
+				new Label ("BL") { Y = Pos.AnchorEnd (1) },
+				new Label ("BR") { X = Pos.AnchorEnd (2), Y = Pos.AnchorEnd (1) }
+			);
+
+			return win;
+		}
+
+		private string TopLeft_Top_With_Border_MenuBar_StatusBar_And_Window_With_Border = @"
+┌──────────────────┐
+│ File             │
+│┌────────┐        │
+││TL    TR│        │
+││        │        │
+││        │        │
+││        │        │
+││        │        │
+││        │        │
+││        │        │
+││BL    BR│        │
+│└────────┘        │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│ F2 File          │
+└──────────────────┘";
+
+		private string BottomRight_Top_With_Border_MenuBar_StatusBar_And_Window_With_Border = @"
+┌──────────────────┐
+│ File             │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│        ┌────────┐│
+│        │TL    TR││
+│        │        ││
+│        │        ││
+│        │        ││
+│        │        ││
+│        │        ││
+│        │        ││
+│        │BL    BR││
+│        └────────┘│
+│ F2 File          │
+└──────────────────┘";
+
+		private string TopLeft_Top_With_Border_MenuBar_StatusBar_And_Window_With_Border_And_Dim_Fill = @"
+┌──────────────────┐
+│ File             │
+│┌──────┐          │
+││TL  TR│          │
+││      │          │
+││      │          │
+││      │          │
+││BL  BR│          │
+│└──────┘          │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│ F2 File          │
+└──────────────────┘";
+
+		private string TopLeft_MdiTop_With_Border_MenuBar_StatusBar_And_Window_With_Border_And_Dim_Fill = @"
+┌──────────────────┐
+│ File             │
+│┌───────┐         │
+││TL   TR│         │
+││       │         │
+││       │         │
+││       │         │
+││       │         │
+││BL   BR│         │
+│└───────┘         │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│ F2 File          │
+└──────────────────┘";
+
+		private string BottomRight_Top_With_Border_MenuBar_StatusBar_And_Window_With_Border_And_Dim_Fill = @"
+┌──────────────────┐
+│ File             │
+│                  │
+│                  │
+│                  │
+│    ┌──┐          │
+│    │TR│          │
+│    │BR│          │
+│    └──┘          │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│ F2 File          │
+└──────────────────┘";
+
+		private string BottomRight_MdiTop_With_Border_MenuBar_StatusBar_And_Window_With_Border_And_Dim_Fill = @"
+┌──────────────────┐
+│ File             │
+│                  │
+│                  │
+│   ┌────┐         │
+│   │TLTR│         │
+│   │    │         │
+│   │    │         │
+│   │BLBR│         │
+│   └────┘         │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│ F2 File          │
+└──────────────────┘";
+
+		private string TopLeft_Top_With_Border_And_Modal_With_Border = @"
+┌──────────────────┐
+│┌────────┐        │
+││TL    TR│        │
+││        │        │
+││        │        │
+││        │        │
+││        │        │
+││        │        │
+││        │        │
+││BL    BR│        │
+│└────────┘        │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+└──────────────────┘";
+
+		private string BottomRight_Top_With_Border_And_Modal_With_Border = @"
+┌──────────────────┐
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│        ┌────────┐│
+│        │TL    TR││
+│        │        ││
+│        │        ││
+│        │        ││
+│        │        ││
+│        │        ││
+│        │        ││
+│        │BL    BR││
+│        └────────┘│
+└──────────────────┘";
+
+		private string TopLeft_Top_With_Border_MenuBar_StatusBar_And_Window_Without_Border = @"
+┌──────────────────┐
+│ File             │
+│TL      TR        │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│BL      BR        │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│ F2 File          │
+└──────────────────┘";
+
+		private string BottonRight_Top_With_Border_MenuBar_StatusBar_And_Window_Without_Border = @"
+┌──────────────────┐
+│ File             │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│        TL      TR│
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│        BL      BR│
+│ F2 File          │
+└──────────────────┘";
+
+		private string TopLeft_Top_With_Border_MenuBar_StatusBar_And_Window_Without_Border_And_Dim_Fill = @"
+┌──────────────────┐
+│ File             │
+│TL    TR          │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│BL    BR          │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│ F2 File          │
+└──────────────────┘";
+
+		private string TopLeft_MdiTop_With_Border_MenuBar_StatusBar_And_Window_Without_Border_And_Dim_Fill = @"
+┌──────────────────┐
+│ File             │
+│TL     TR         │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│BL     BR         │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│ F2 File          │
+└──────────────────┘";
+
+		private string BottomRight_Top_With_Border_MenuBar_StatusBar_And_Window_Without_Border_And_Dim_Fill = @"
+┌──────────────────┐
+│ File             │
+│                  │
+│                  │
+│                  │
+│    TLTR          │
+│                  │
+│                  │
+│    BLBR          │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│ F2 File          │
+└──────────────────┘";
+
+		private string BottomRight_MdiTop_With_Border_MenuBar_StatusBar_And_Window_Without_Border_And_Dim_Fill = @"
+┌──────────────────┐
+│ File             │
+│                  │
+│                  │
+│   TL  TR         │
+│                  │
+│                  │
+│                  │
+│                  │
+│   BL  BR         │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│ F2 File          │
+└──────────────────┘";
+
+		private string TopLeft_Top_With_Border_And_Modal_Without_Border = @"
+┌──────────────────┐
+│TL      TR        │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│BL      BR        │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+└──────────────────┘";
+
+		private string BottomRight_Top_With_Border_And_Modal_Without_Border = @"
+┌──────────────────┐
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│        TL      TR│
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│        BL      BR│
+└──────────────────┘";
+
+		private string TopLeft_Top_Without_Border_MenuBar_StatusBar_And_Window_With_Border = @"
+ File     
+┌────────┐
+│TL    TR│
+│        │
+│        │
+│        │
+│        │
+│        │
+│        │
+│BL    BR│
+└────────┘
+          
+          
+          
+          
+          
+          
+          
+          
+ F2 File  ";
+
+		private string BottomRight_Top_Without_Border_MenuBar_StatusBar_And_Window_With_Border = @"
+ File               
+                    
+                    
+                    
+                    
+                    
+                    
+                    
+                    
+          ┌────────┐
+          │TL    TR│
+          │        │
+          │        │
+          │        │
+          │        │
+          │        │
+          │        │
+          │BL    BR│
+          └────────┘
+ F2 File            ";
+
+		private string TopLeft_Top_Without_Border_MenuBar_StatusBar_And_Window_With_Border_And_Dim_Fill = @"
+ File     
+┌────────┐
+│TL    TR│
+│        │
+│        │
+│        │
+│        │
+│        │
+│BL    BR│
+└────────┘
+          
+          
+          
+          
+          
+          
+          
+          
+          
+ F2 File  ";
+
+		private string BottomRight_Top_Without_Border_MenuBar_StatusBar_And_Window_With_Border_And_Dim_Fill = @"
+ File     
+          
+          
+          
+    ┌────┐
+    │TLTR│
+    │    │
+    │    │
+    │BLBR│
+    └────┘
+          
+          
+          
+          
+          
+          
+          
+          
+          
+ F2 File  ";
+
+		private string TopLeft_Top_Without_Border_And_Modal_With_Border = @"
+┌────────┐
+│TL    TR│
+│        │
+│        │
+│        │
+│        │
+│        │
+│        │
+│BL    BR│
+└────────┘";
+
+		private string BottomRight_Top_Without_Border_And_Modal_With_Border = @"
+          ┌────────┐
+          │TL    TR│
+          │        │
+          │        │
+          │        │
+          │        │
+          │        │
+          │        │
+          │BL    BR│
+          └────────┘";
+
+		private string TopLeft_Top_Without_Border_MenuBar_StatusBar_And_Window_Without_Border = @"
+ File     
+TL      TR
+          
+          
+          
+          
+          
+          
+          
+          
+BL      BR
+          
+          
+          
+          
+          
+          
+          
+          
+ F2 File  ";
+
+		private string BottomRigt_Top_Without_Border_MenuBar_StatusBar_And_Window_Without_Border = @"
+ File               
+                    
+                    
+                    
+                    
+                    
+                    
+                    
+                    
+          TL      TR
+                    
+                    
+                    
+                    
+                    
+                    
+                    
+                    
+          BL      BR
+ F2 File            ";
+
+		private string TopLeft_Top_Without_Border_MenuBar_StatusBar_And_Window_Without_Border_And_Dim_Fill = @"
+ File     
+TL      TR
+          
+          
+          
+          
+          
+          
+          
+BL      BR
+          
+          
+          
+          
+          
+          
+          
+          
+          
+ F2 File  ";
+
+		private string BottomRight_Top_Without_Border_MenuBar_StatusBar_And_Window_Without_Border_And_Dim_Fill = @"
+ File     
+          
+          
+          
+    TL  TR
+          
+          
+          
+          
+    BL  BR
+          
+          
+          
+          
+          
+          
+          
+          
+          
+ F2 File  ";
+
+		private string TopLeft_Top_Without_Border_And_Modal_Without_Border = @"
+TL      TR
+          
+          
+          
+          
+          
+          
+          
+          
+BL      BR";
+
+		private string BottomRight_Top_Without_Border_And_Modal_Without_Border = @"
+          TL      TR
+                    
+                    
+                    
+                    
+                    
+                    
+                    
+                    
+          BL      BR";
+
+		[Theory, AutoInitShutdown]
+		[InlineData (false, false, 0, 1, 8, 7)]
+		[InlineData (false, true, 1, 2, 9, 8)]
+		public void EnsureVisibleBounds_Top_With_Border_MenuBar_StatusBar_And_Window_With_Border (
+			bool borderless, bool isMdiContainer, int topLeftX, int topLeftY, int bottomRightX, int bottomRightY)
+		{
+			var top = Top_With_MenuBar_And_StatusBar (borderless, isMdiContainer);
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels ();
+			if (!isMdiContainer) {
+				top.Add (win);
+			}
+			Application.Begin (top);
+			if (isMdiContainer) {
+				Application.Begin (win);
+			}
+
+			Assert.NotNull (top.MenuBar);
+			Assert.NotNull (top.StatusBar);
+			Assert.Equal (isMdiContainer, top.IsMdiContainer);
+
+			// left + top
+			win.X = 0;
+			win.Y = 0;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out int nx, out int ny, out _, out _);
+			Assert.Equal (topLeftX, nx);
+			Assert.Equal (topLeftY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (topLeftX, topLeftY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_With_Border_MenuBar_StatusBar_And_Window_With_Border, output);
+
+			// right + bottom
+			win.X = 100;
+			win.Y = 40;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out nx, out ny, out _, out _);
+			Assert.Equal (bottomRightX, nx);
+			Assert.Equal (bottomRightY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (bottomRightX, bottomRightY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (BottomRight_Top_With_Border_MenuBar_StatusBar_And_Window_With_Border, output);
+		}
+
+		[Theory, AutoInitShutdown]
+		[InlineData (false, false, 1, 2, 9, 8)]
+		[InlineData (false, true, 1, 2, 9, 8)]
+		public void EnsureVisibleBounds_Top_With_Border_MenuBar_StatusBar_And_Modal_With_Border (
+			bool borderless, bool isMdiContainer, int topLeftX, int topLeftY, int bottomRightX, int bottomRightY)
+		{
+			var top = Top_With_MenuBar_And_StatusBar (borderless, isMdiContainer);
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels (false, false, true);
+			Application.Begin (top);
+			Application.Begin (win);
+
+			Assert.NotNull (top.MenuBar);
+			Assert.NotNull (top.StatusBar);
+			Assert.Equal (isMdiContainer, top.IsMdiContainer);
+			Assert.True (win.Modal);
+
+			// left + top
+			win.X = 0;
+			win.Y = 0;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out int nx, out int ny, out _, out _);
+			Assert.Equal (topLeftX, nx);
+			Assert.Equal (topLeftY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (topLeftX, topLeftY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_With_Border_MenuBar_StatusBar_And_Window_With_Border, output);
+
+			// right + bottom
+			win.X = 100;
+			win.Y = 40;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out nx, out ny, out _, out _);
+			Assert.Equal (bottomRightX, nx);
+			Assert.Equal (bottomRightY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (bottomRightX, bottomRightY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (BottomRight_Top_With_Border_MenuBar_StatusBar_And_Window_With_Border, output);
+		}
+
+		[Theory, AutoInitShutdown]
+		[InlineData (false, false, 0, 1, 4, 4)]
+		[InlineData (false, true, 1, 2, 4, 4)]
+		public void EnsureVisibleBounds_Top_With_Border_MenuBar_StatusBar_And_Window_With_Border_And_Dim_Fill (
+			bool borderless, bool isMdiContainer, int topLeftX, int topLeftY, int bottomRightX, int bottomRightY)
+		{
+			var top = Top_With_MenuBar_And_StatusBar (borderless, isMdiContainer);
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels (true);
+			if (!isMdiContainer) {
+				top.Add (win);
+			}
+			Application.Begin (top);
+			if (isMdiContainer) {
+				Application.Begin (win);
+			}
+
+			Assert.NotNull (top.MenuBar);
+			Assert.NotNull (top.StatusBar);
+			Assert.Equal (isMdiContainer, top.IsMdiContainer);
+			Assert.False (win.Modal);
+
+			// left + top
+			win.X = 0;
+			win.Y = 0;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out int nx, out int ny, out _, out _);
+			Assert.Equal (topLeftX, nx);
+			Assert.Equal (topLeftY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			if (!isMdiContainer) {
+				Assert.Equal (new Rect (topLeftX, topLeftY, 8, 7), win.Frame);
+				TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_With_Border_MenuBar_StatusBar_And_Window_With_Border_And_Dim_Fill, output);
+
+			} else {
+				Assert.Equal (new Rect (topLeftX, topLeftY, 9, 8), win.Frame);
+				TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_MdiTop_With_Border_MenuBar_StatusBar_And_Window_With_Border_And_Dim_Fill, output);
+			}
+
+			// right + bottom
+			win.X = 4;
+			win.Y = 4;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out nx, out ny, out _, out _);
+			Assert.Equal (bottomRightX, nx);
+			Assert.Equal (bottomRightY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			if (!isMdiContainer) {
+				Assert.Equal (new Rect (bottomRightX, bottomRightY, 4, 4), win.Frame);
+				TestHelpers.AssertDriverContentsWithFrameAre (BottomRight_Top_With_Border_MenuBar_StatusBar_And_Window_With_Border_And_Dim_Fill, output);
+
+			} else {
+				Assert.Equal (new Rect (bottomRightX, bottomRightY, 6, 6), win.Frame);
+				TestHelpers.AssertDriverContentsWithFrameAre (BottomRight_MdiTop_With_Border_MenuBar_StatusBar_And_Window_With_Border_And_Dim_Fill, output);
+			}
+		}
+
+		[Theory, AutoInitShutdown]
+		[InlineData (false, false, 1, 1, 9, 9)]
+		[InlineData (false, true, 1, 1, 9, 9)]
+		public void EnsureVisibleBounds_Top_With_Border_And_Modal_With_Border (
+			bool borderless, bool isMdiContainer, int topLeftX, int topLeftY, int bottomRightX, int bottomRightY)
+		{
+			var top = Top_With_MenuBar_And_StatusBar (borderless, isMdiContainer);
+			top.MenuBar.Visible = false;
+			top.StatusBar.Visible = false;
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels (false, false, true);
+			Application.Begin (top);
+			Application.Begin (win);
+
+			Assert.False (top.MenuBar.Visible);
+			Assert.False (top.StatusBar.Visible);
+			Assert.Equal (isMdiContainer, top.IsMdiContainer);
+			Assert.True (win.Modal);
+
+			// left + top
+			win.X = 0;
+			win.Y = 0;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out int nx, out int ny, out _, out _);
+			Assert.Equal (topLeftX, nx);
+			Assert.Equal (topLeftY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (topLeftX, topLeftY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_With_Border_And_Modal_With_Border, output);
+
+			// right + bottom
+			win.X = 100;
+			win.Y = 40;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out nx, out ny, out _, out _);
+			Assert.Equal (bottomRightX, nx);
+			Assert.Equal (bottomRightY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (bottomRightX, bottomRightY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (BottomRight_Top_With_Border_And_Modal_With_Border, output);
+		}
+
+		[Theory, AutoInitShutdown]
+		[InlineData (false, false, 0, 1, 8, 7)]
+		[InlineData (false, true, 1, 2, 9, 8)]
+		public void EnsureVisibleBounds_Top_With_Border_MenuBar_StatusBar_And_Window_Without_Border (
+			bool borderless, bool isMdiContainer, int topLeftX, int topLeftY, int bottomRightX, int bottomRightY)
+		{
+			var top = Top_With_MenuBar_And_StatusBar (borderless, isMdiContainer);
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels (false, true);
+			if (!isMdiContainer) {
+				top.Add (win);
+			}
+			Application.Begin (top);
+			if (isMdiContainer) {
+				Application.Begin (win);
+			}
+
+			Assert.NotNull (top.MenuBar);
+			Assert.NotNull (top.StatusBar);
+			Assert.Equal (isMdiContainer, top.IsMdiContainer);
+			Assert.False (win.Modal);
+
+			// left + top
+			win.X = 0;
+			win.Y = 0;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out int nx, out int ny, out _, out _);
+			Assert.Equal (topLeftX, nx);
+			Assert.Equal (topLeftY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (topLeftX, topLeftY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_With_Border_MenuBar_StatusBar_And_Window_Without_Border, output);
+
+			// right + bottom
+			win.X = 100;
+			win.Y = 40;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out nx, out ny, out _, out _);
+			Assert.Equal (bottomRightX, nx);
+			Assert.Equal (bottomRightY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (bottomRightX, bottomRightY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (BottonRight_Top_With_Border_MenuBar_StatusBar_And_Window_Without_Border, output);
+		}
+
+		[Theory, AutoInitShutdown]
+		[InlineData (false, false, 1, 2, 9, 8)]
+		[InlineData (false, true, 1, 2, 9, 8)]
+		public void EnsureVisibleBounds_Top_With_Border_MenuBar_StatusBar_And_Modal_Without_Border (
+			bool borderless, bool isMdiContainer, int topLeftX, int topLeftY, int bottomRightX, int bottomRightY)
+		{
+			var top = Top_With_MenuBar_And_StatusBar (borderless, isMdiContainer);
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels (false, true, true);
+			Application.Begin (top);
+			Application.Begin (win);
+
+			Assert.NotNull (top.MenuBar);
+			Assert.NotNull (top.StatusBar);
+			Assert.Equal (isMdiContainer, top.IsMdiContainer);
+			Assert.True (win.Modal);
+
+			// left + top
+			win.X = 0;
+			win.Y = 0;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out int nx, out int ny, out _, out _);
+			Assert.Equal (topLeftX, nx);
+			Assert.Equal (topLeftY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (topLeftX, topLeftY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_With_Border_MenuBar_StatusBar_And_Window_Without_Border, output);
+
+			// right + bottom
+			win.X = 100;
+			win.Y = 40;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out nx, out ny, out _, out _);
+			Assert.Equal (bottomRightX, nx);
+			Assert.Equal (bottomRightY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (bottomRightX, bottomRightY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (BottonRight_Top_With_Border_MenuBar_StatusBar_And_Window_Without_Border, output);
+		}
+
+		[Theory, AutoInitShutdown]
+		[InlineData (false, false, 0, 1, 4, 4)]
+		[InlineData (false, true, 1, 2, 4, 4)]
+		public void EnsureVisibleBounds_Top_With_Border_MenuBar_StatusBar_And_Window_Without_Border_And_Dim_Fill (
+			bool borderless, bool isMdiContainer, int topLeftX, int topLeftY, int bottomRightX, int bottomRightY)
+		{
+			var top = Top_With_MenuBar_And_StatusBar (borderless, isMdiContainer);
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels (true, true);
+			if (!isMdiContainer) {
+				top.Add (win);
+			}
+			Application.Begin (top);
+			if (isMdiContainer) {
+				Application.Begin (win);
+			}
+
+			Assert.NotNull (top.MenuBar);
+			Assert.NotNull (top.StatusBar);
+			Assert.Equal (isMdiContainer, top.IsMdiContainer);
+			Assert.False (win.Modal);
+
+			// left + top
+			win.X = 0;
+			win.Y = 0;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out int nx, out int ny, out _, out _);
+			Assert.Equal (topLeftX, nx);
+			Assert.Equal (topLeftY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			if (!isMdiContainer) {
+				Assert.Equal (new Rect (topLeftX, topLeftY, 8, 7), win.Frame);
+				TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_With_Border_MenuBar_StatusBar_And_Window_Without_Border_And_Dim_Fill, output);
+			} else {
+				Assert.Equal (new Rect (topLeftX, topLeftY, 9, 8), win.Frame);
+				TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_MdiTop_With_Border_MenuBar_StatusBar_And_Window_Without_Border_And_Dim_Fill, output);
+			}
+
+			// right + bottom
+			win.X = 4;
+			win.Y = 4;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out nx, out ny, out _, out _);
+			Assert.Equal (bottomRightX, nx);
+			Assert.Equal (bottomRightY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			if (!isMdiContainer) {
+				Assert.Equal (new Rect (bottomRightX, bottomRightY, 4, 4), win.Frame);
+				TestHelpers.AssertDriverContentsWithFrameAre (BottomRight_Top_With_Border_MenuBar_StatusBar_And_Window_Without_Border_And_Dim_Fill, output);
+			} else {
+				Assert.Equal (new Rect (bottomRightX, bottomRightY, 6, 6), win.Frame);
+				TestHelpers.AssertDriverContentsWithFrameAre (BottomRight_MdiTop_With_Border_MenuBar_StatusBar_And_Window_Without_Border_And_Dim_Fill, output);
+			}
+		}
+
+		[Theory, AutoInitShutdown]
+		[InlineData (false, false, 1, 1, 9, 9)]
+		[InlineData (false, true, 1, 1, 9, 9)]
+		public void EnsureVisibleBounds_Top_With_Border_And_Modal_Without_Border (
+			bool borderless, bool isMdiContainer, int topLeftX, int topLeftY, int bottomRightX, int bottomRightY)
+		{
+			var top = Top_With_MenuBar_And_StatusBar (borderless, isMdiContainer);
+			top.MenuBar.Visible = false;
+			top.StatusBar.Visible = false;
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels (false, true, true);
+			Application.Begin (top);
+			Application.Begin (win);
+
+			Assert.NotNull (top.MenuBar);
+			Assert.NotNull (top.StatusBar);
+			Assert.Equal (isMdiContainer, top.IsMdiContainer);
+			Assert.True (win.Modal);
+
+			// left + top
+			win.X = 0;
+			win.Y = 0;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out int nx, out int ny, out _, out _);
+			Assert.Equal (topLeftX, nx);
+			Assert.Equal (topLeftY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (topLeftX, topLeftY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_With_Border_And_Modal_Without_Border, output);
+
+			// right + bottom
+			win.X = 100;
+			win.Y = 40;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out nx, out ny, out _, out _);
+			Assert.Equal (bottomRightX, nx);
+			Assert.Equal (bottomRightY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (bottomRightX, bottomRightY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (BottomRight_Top_With_Border_And_Modal_Without_Border, output);
+		}
+
+		[Theory, AutoInitShutdown]
+		[InlineData (true, false, 0, 1, 10, 9)]
+		[InlineData (true, true, 0, 1, 10, 9)]
+		public void EnsureVisibleBounds_Top_Without_Border_MenuBar_StatusBar_And_Window_With_Border (
+			bool borderless, bool isMdiContainer, int topLeftX, int topLeftY, int bottomRightX, int bottomRightY)
+		{
+			var top = Top_With_MenuBar_And_StatusBar (borderless, isMdiContainer);
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels ();
+			if (!isMdiContainer) {
+				top.Add (win);
+			}
+			Application.Begin (top);
+			if (isMdiContainer) {
+				Application.Begin (win);
+			}
+			Assert.NotNull (top.MenuBar);
+			Assert.NotNull (top.StatusBar);
+			Assert.Equal (isMdiContainer, top.IsMdiContainer);
+			Assert.False (win.Modal);
+
+			// left + top
+			win.X = 0;
+			win.Y = 0;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out int nx, out int ny, out _, out _);
+			Assert.Equal (topLeftX, nx);
+			Assert.Equal (topLeftY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (topLeftX, topLeftY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_Without_Border_MenuBar_StatusBar_And_Window_With_Border, output);
+
+			// right + bottom
+			win.X = 100;
+			win.Y = 40;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out nx, out ny, out _, out _);
+			Assert.Equal (bottomRightX, nx);
+			Assert.Equal (bottomRightY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (bottomRightX, bottomRightY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (BottomRight_Top_Without_Border_MenuBar_StatusBar_And_Window_With_Border, output);
+		}
+
+		[Theory, AutoInitShutdown]
+		[InlineData (true, false, 0, 1, 10, 9)]
+		[InlineData (true, true, 0, 1, 10, 9)]
+		public void EnsureVisibleBounds_Top_Without_Border_MenuBar_StatusBar_And_Modal_With_Border (
+			bool borderless, bool isMdiContainer, int topLeftX, int topLeftY, int bottomRightX, int bottomRightY)
+		{
+			var top = Top_With_MenuBar_And_StatusBar (borderless, isMdiContainer);
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels (false, false, true);
+			Application.Begin (top);
+			Application.Begin (win);
+
+			Assert.NotNull (top.MenuBar);
+			Assert.NotNull (top.StatusBar);
+			Assert.Equal (isMdiContainer, top.IsMdiContainer);
+			Assert.True (win.Modal);
+
+			// left + top
+			win.X = 0;
+			win.Y = 0;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out int nx, out int ny, out _, out _);
+			Assert.Equal (topLeftX, nx);
+			Assert.Equal (topLeftY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (topLeftX, topLeftY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_Without_Border_MenuBar_StatusBar_And_Window_With_Border, output);
+
+			// right + bottom
+			win.X = 100;
+			win.Y = 40;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out nx, out ny, out _, out _);
+			Assert.Equal (bottomRightX, nx);
+			Assert.Equal (bottomRightY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (bottomRightX, bottomRightY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (BottomRight_Top_Without_Border_MenuBar_StatusBar_And_Window_With_Border, output);
+		}
+
+		[Theory, AutoInitShutdown]
+		[InlineData (true, false, 0, 1, 4, 4)]
+		[InlineData (true, true, 0, 1, 4, 4)]
+		public void EnsureVisibleBounds_Top_Without_Border_MenuBar_StatusBar_And_Window_With_Border_And_Dim_Fill (
+			bool borderless, bool isMdiContainer, int topLeftX, int topLeftY, int bottomRightX, int bottomRightY)
+		{
+			var top = Top_With_MenuBar_And_StatusBar (borderless, isMdiContainer);
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels (true);
+			if (!isMdiContainer) {
+				top.Add (win);
+			}
+			Application.Begin (top);
+			if (isMdiContainer) {
+				Application.Begin (win);
+			}
+
+			Assert.NotNull (top.MenuBar);
+			Assert.NotNull (top.StatusBar);
+			Assert.Equal (isMdiContainer, top.IsMdiContainer);
+			Assert.False (win.Modal);
+
+			// left + top
+			win.X = 0;
+			win.Y = 0;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out int nx, out int ny, out _, out _);
+			Assert.Equal (topLeftX, nx);
+			Assert.Equal (topLeftY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (topLeftX, topLeftY, 10, 9), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_Without_Border_MenuBar_StatusBar_And_Window_With_Border_And_Dim_Fill, output);
+
+			// right + bottom
+			win.X = 4;
+			win.Y = 4;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out nx, out ny, out _, out _);
+			Assert.Equal (bottomRightX, nx);
+			Assert.Equal (bottomRightY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (bottomRightX, bottomRightY, 6, 6), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (BottomRight_Top_Without_Border_MenuBar_StatusBar_And_Window_With_Border_And_Dim_Fill, output);
+		}
+
+		[Theory, AutoInitShutdown]
+		[InlineData (true, false, 0, 0, 10, 10)]
+		[InlineData (true, true, 0, 0, 10, 10)]
+		public void EnsureVisibleBounds_Top_Without_Border_And_Modal_With_Border (
+			bool borderless, bool isMdiContainer, int topLeftX, int topLeftY, int bottomRightX, int bottomRightY)
+		{
+			var top = Top_With_MenuBar_And_StatusBar (borderless, isMdiContainer);
+			top.MenuBar.Visible = false;
+			top.StatusBar.Visible = false;
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels (false, false, true);
+			Application.Begin (top);
+			Application.Begin (win);
+
+			Assert.False (top.MenuBar.Visible);
+			Assert.False (top.StatusBar.Visible);
+			Assert.Equal (isMdiContainer, top.IsMdiContainer);
+			Assert.True (win.Modal);
+
+			// left + top
+			win.X = 0;
+			win.Y = 0;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out int nx, out int ny, out _, out _);
+			Assert.Equal (topLeftX, nx);
+			Assert.Equal (topLeftY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (topLeftX, topLeftY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_Without_Border_And_Modal_With_Border, output);
+
+			// right + bottom
+			win.X = 100;
+			win.Y = 40;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out nx, out ny, out _, out _);
+			Assert.Equal (bottomRightX, nx);
+			Assert.Equal (bottomRightY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (bottomRightX, bottomRightY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (BottomRight_Top_Without_Border_And_Modal_With_Border, output);
+		}
+
+		[Theory, AutoInitShutdown]
+		[InlineData (true, false, 0, 1, 10, 9)]
+		[InlineData (true, true, 0, 1, 10, 9)]
+		public void EnsureVisibleBounds_Top_Without_Border_MenuBar_StatusBar_And_Window_Without_Border (
+			bool borderless, bool isMdiContainer, int topLeftX, int topLeftY, int bottomRightX, int bottomRightY)
+		{
+			var top = Top_With_MenuBar_And_StatusBar (borderless, isMdiContainer);
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels (false, true);
+			if (!isMdiContainer) {
+				top.Add (win);
+			}
+			Application.Begin (top);
+			if (isMdiContainer) {
+				Application.Begin (win);
+			}
+			Assert.NotNull (top.MenuBar);
+			Assert.NotNull (top.StatusBar);
+			Assert.Equal (isMdiContainer, top.IsMdiContainer);
+			Assert.False (win.Modal);
+
+			// left + top
+			win.X = 0;
+			win.Y = 0;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out int nx, out int ny, out _, out _);
+			Assert.Equal (topLeftX, nx);
+			Assert.Equal (topLeftY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (topLeftX, topLeftY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_Without_Border_MenuBar_StatusBar_And_Window_Without_Border, output);
+
+			// right + bottom
+			win.X = 100;
+			win.Y = 40;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out nx, out ny, out _, out _);
+			Assert.Equal (bottomRightX, nx);
+			Assert.Equal (bottomRightY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (bottomRightX, bottomRightY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (BottomRigt_Top_Without_Border_MenuBar_StatusBar_And_Window_Without_Border, output);
+		}
+
+		[Theory, AutoInitShutdown]
+		[InlineData (true, false, 0, 1, 10, 9)]
+		[InlineData (true, true, 0, 1, 10, 9)]
+		public void EnsureVisibleBounds_Top_Without_Border_MenuBar_StatusBar_And_Modal_Without_Border (
+			bool borderless, bool isMdiContainer, int topLeftX, int topLeftY, int bottomRightX, int bottomRightY)
+		{
+			var top = Top_With_MenuBar_And_StatusBar (borderless, isMdiContainer);
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels (false, true, true);
+			Application.Begin (top);
+			Application.Begin (win);
+
+			Assert.NotNull (top.MenuBar);
+			Assert.NotNull (top.StatusBar);
+			Assert.Equal (isMdiContainer, top.IsMdiContainer);
+			Assert.True (win.Modal);
+
+			// left + top
+			win.X = 0;
+			win.Y = 0;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out int nx, out int ny, out _, out _);
+			Assert.Equal (topLeftX, nx);
+			Assert.Equal (topLeftY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (topLeftX, topLeftY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_Without_Border_MenuBar_StatusBar_And_Window_Without_Border, output);
+
+			// right + bottom
+			win.X = 100;
+			win.Y = 40;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out nx, out ny, out _, out _);
+			Assert.Equal (bottomRightX, nx);
+			Assert.Equal (bottomRightY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (bottomRightX, bottomRightY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (BottomRigt_Top_Without_Border_MenuBar_StatusBar_And_Window_Without_Border, output);
+		}
+
+		[Theory, AutoInitShutdown]
+		[InlineData (true, false, 0, 1, 4, 4)]
+		[InlineData (true, true, 0, 1, 4, 4)]
+		public void EnsureVisibleBounds_Top_Without_Border_MenuBar_StatusBar_And_Window_Without_Border_And_Dim_Fill (
+			bool borderless, bool isMdiContainer, int topLeftX, int topLeftY, int bottomRightX, int bottomRightY)
+		{
+			var top = Top_With_MenuBar_And_StatusBar (borderless, isMdiContainer);
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels (true, true);
+			if (!isMdiContainer) {
+				top.Add (win);
+			}
+			Application.Begin (top);
+			if (isMdiContainer) {
+				Application.Begin (win);
+			}
+
+			Assert.NotNull (top.MenuBar);
+			Assert.NotNull (top.StatusBar);
+			Assert.Equal (isMdiContainer, top.IsMdiContainer);
+			Assert.False (win.Modal);
+
+			// left + top
+			win.X = 0;
+			win.Y = 0;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out int nx, out int ny, out _, out _);
+			Assert.Equal (topLeftX, nx);
+			Assert.Equal (topLeftY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (topLeftX, topLeftY, 10, 9), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_Without_Border_MenuBar_StatusBar_And_Window_Without_Border_And_Dim_Fill, output);
+
+			// right + bottom
+			win.X = 4;
+			win.Y = 4;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out nx, out ny, out _, out _);
+			Assert.Equal (bottomRightX, nx);
+			Assert.Equal (bottomRightY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (bottomRightX, bottomRightY, 6, 6), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (BottomRight_Top_Without_Border_MenuBar_StatusBar_And_Window_Without_Border_And_Dim_Fill, output);
+		}
+
+		[Theory, AutoInitShutdown]
+		[InlineData (true, false, 0, 0, 10, 10)]
+		[InlineData (true, true, 0, 0, 10, 10)]
+		public void EnsureVisibleBounds_Top_Without_Border_And_Modal_Without_Border (
+			bool borderless, bool isMdiContainer, int topLeftX, int topLeftY, int bottomRightX, int bottomRightY)
+		{
+			var top = Top_With_MenuBar_And_StatusBar (borderless, isMdiContainer);
+			top.MenuBar.Visible = false;
+			top.StatusBar.Visible = false;
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels (false, true, true);
+			Application.Begin (top);
+			Application.Begin (win);
+
+			Assert.False (top.MenuBar.Visible);
+			Assert.False (top.StatusBar.Visible);
+			Assert.Equal (isMdiContainer, top.IsMdiContainer);
+			Assert.True (win.Modal);
+
+			// left + top
+			win.X = 0;
+			win.Y = 0;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out int nx, out int ny, out _, out _);
+			Assert.Equal (topLeftX, nx);
+			Assert.Equal (topLeftY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (topLeftX, topLeftY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_Without_Border_And_Modal_Without_Border, output);
+
+			// right + bottom
+			win.X = 100;
+			win.Y = 40;
+			top.EnsureVisibleBounds (win, win.Frame.X, win.Frame.Y, out nx, out ny, out _, out _);
+			Assert.Equal (bottomRightX, nx);
+			Assert.Equal (bottomRightY, ny);
+			win.X = nx;
+			win.Y = ny;
+			Application.Refresh ();
+			Assert.Equal (new Rect (bottomRightX, bottomRightY, 10, 10), win.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (BottomRight_Top_Without_Border_And_Modal_Without_Border, output);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void RunMainLoopIteration_Mdi_IsTopNeedsDisplay ()
+		{
+			var menu = new MenuBar (new MenuBarItem [] {
+				new MenuBarItem("File", Array.Empty<MenuItem> ())
+			}) { Visible = false };
+			var statusBar = new StatusBar (new StatusItem []{
+				new StatusItem(Key.F2, "~F2~ File", null)
+			}) { Visible = false };
+
+			var top = new Toplevel ();
+			top.IsMdiContainer = true;
+			top.Add (menu, statusBar);
+
+			Application.Begin (top);
+
+			var childWin = new Window () { Width = 5, Height = 5 };
+			var rs = Application.Begin (childWin);
+
+			Assert.Single (Application.MdiChildes);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+┌───┐
+│   │
+│   │
+│   │
+└───┘", output);
+			Assert.Equal (0, childWin.Frame.Y);
+
+			menu.Visible = true;
+			var firstIteration = false;
+			Application.RunMainLoopIteration (ref rs, true, ref firstIteration);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+ File
+┌───┐
+│   │
+│   │
+│   │
+└───┘", output);
+			Assert.Equal (1, childWin.Frame.Y);
+
+			menu.Visible = false;
+			childWin.Y = 25;
+			firstIteration = false;
+			Application.RunMainLoopIteration (ref rs, true, ref firstIteration);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+┌───┐
+│   │
+│   │
+│   │
+└───┘", output);
+			Assert.Equal (20, childWin.Frame.Y);
+
+			statusBar.Visible = true;
+			firstIteration = false;
+			Application.RunMainLoopIteration (ref rs, true, ref firstIteration);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+┌───┐   
+│   │   
+│   │   
+│   │   
+└───┘   
+ F2 File", output);
+			Assert.Equal (19, childWin.Frame.Y);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void Show_Menu_On_Front_MdiChild_By_Keyboard_And_Mouse_With_Run_Action ()
+		{
+			var top = Top_With_MenuBar_And_StatusBar (false, true);
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels ();
+			Application.Begin (top);
+			Application.Begin (win);
+
+			var isNew = false;
+			var menu = top.MenuBar;
+			var mi = menu.Menus [0].Children [0];
+			mi.Action = () => isNew = true;
+			Assert.False (menu.IsMenuOpen);
+			var expectedClosed = @"
+┌──────────────────┐
+│ File             │
+│┌────────┐        │
+││TL    TR│        │
+││        │        │
+││        │        │
+││        │        │
+││        │        │
+││        │        │
+││        │        │
+││BL    BR│        │
+│└────────┘        │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│ F2 File          │
+└──────────────────┘";
+			TestHelpers.AssertDriverContentsWithFrameAre (expectedClosed, output);
+
+			var expectedOpened = @"
+┌──────────────────┐
+│ File             │
+│┌──────┐─┐        │
+││ New  │R│        │
+│└──────┘ │        │
+││        │        │
+││        │        │
+││        │        │
+││        │        │
+││        │        │
+││BL    BR│        │
+│└────────┘        │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│ F2 File          │
+└──────────────────┘";
+
+			// using keyboard
+			ReflectionTools.InvokePrivate (
+				typeof (Application),
+				"ProcessKeyEvent",
+				new KeyEvent (menu.Key, new KeyModifiers ()));
+
+			Application.Refresh ();
+			Assert.True (menu.IsMenuOpen);
+			TestHelpers.AssertDriverContentsWithFrameAre (expectedOpened, output);
+
+			// run action
+			ReflectionTools.InvokePrivate (
+				typeof (Application),
+				"ProcessKeyEvent",
+				new KeyEvent (Key.Enter, new KeyModifiers ()));
+
+			Application.MainLoop.MainIteration ();
+			Application.Refresh ();
+			Assert.False (menu.IsMenuOpen);
+			Assert.True (isNew);
+			TestHelpers.AssertDriverContentsWithFrameAre (expectedClosed, output);
+
+			// using mouse
+			ReflectionTools.InvokePrivate (
+				typeof (Application),
+				"ProcessMouseEvent",
+				new MouseEvent () {
+					X = 1,
+					Y = 1,
+					Flags = MouseFlags.Button1Pressed
+				});
+
+			Application.Refresh ();
+			Assert.True (menu.IsMenuOpen);
+			TestHelpers.AssertDriverContentsWithFrameAre (expectedOpened, output);
+
+			// run action
+			isNew = false;
+			ReflectionTools.InvokePrivate (
+				typeof (Application),
+				"ProcessMouseEvent",
+				new MouseEvent () {
+					X = 2,
+					Y = 4,
+					Flags = MouseFlags.Button1Clicked
+				});
+
+			Application.MainLoop.MainIteration ();
+			Application.Refresh ();
+			Assert.False (menu.IsMenuOpen);
+			Assert.True (isNew);
+			TestHelpers.AssertDriverContentsWithFrameAre (expectedClosed, output);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void Toggle_MdiTop_Border_Redraw_MdiChild_Without_Border_On_Position_Changed ()
+		{
+			var top = Top_With_MenuBar_And_StatusBar (true, true);
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels (false, true);
+			Application.Begin (top);
+			var rs = Application.Begin (win);
+
+			TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_Without_Border_MenuBar_StatusBar_And_Window_Without_Border, output);
+			var attributes = new Attribute [] {
+				// 0
+				Colors.Base.Normal,
+				// 1
+				Colors.Menu.Normal,
+				// 2
+				Colors.TopLevel.Normal,
+				// 3
+				Colors.Menu.HotNormal
+			};
+			TestHelpers.AssertDriverColorsAre (@"
+11111111111111111111
+22222222220000000000
+22222222220000000000
+22222222220000000000
+22222222220000000000
+22222222220000000000
+22222222220000000000
+22222222220000000000
+22222222220000000000
+22222222220000000000
+22222222220000000000
+00000000000000000000
+00000000000000000000
+00000000000000000000
+00000000000000000000
+00000000000000000000
+00000000000000000000
+00000000000000000000
+00000000000000000000
+13311111111111111111", attributes);
+
+			top.Border.BorderStyle = BorderStyle.Single;
+			var firstIteration = false;
+			Application.RunMainLoopIteration (ref rs, true, ref firstIteration);
+			TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_With_Border_MenuBar_StatusBar_And_Window_Without_Border, output);
+			TestHelpers.AssertDriverColorsAre (@"
+00000000000000000000
+01111111111111111110
+02222222222000000000
+02222222222000000000
+02222222222000000000
+02222222222000000000
+02222222222000000000
+02222222222000000000
+02222222222000000000
+02222222222000000000
+02222222222000000000
+02222222222000000000
+00000000000000000000
+00000000000000000000
+00000000000000000000
+00000000000000000000
+00000000000000000000
+00000000000000000000
+01331111111111111110
+00000000000000000000", attributes);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void MdiTop_Border_Redraw_MdiChild_With_Border_On_Position_Changed ()
+		{
+			var top = Top_With_MenuBar_And_StatusBar (false, true);
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels ();
+			Application.Begin (top);
+			var rs = Application.Begin (win);
+
+			TestHelpers.AssertDriverContentsWithFrameAre (TopLeft_Top_With_Border_MenuBar_StatusBar_And_Window_With_Border, output);
+			var attributes = new Attribute [] {
+				// 0
+				Colors.Base.Normal,
+				// 1
+				Colors.Menu.Normal,
+				// 2
+				Colors.TopLevel.Normal,
+				// 3
+				Colors.Menu.HotNormal
+			};
+			TestHelpers.AssertDriverColorsAre (@"
+00000000000000000000
+01111111111111111110
+02222222222000000000
+02222222222000000000
+02222222222000000000
+02222222222000000000
+02222222222000000000
+02222222222000000000
+02222222222000000000
+02222222222000000000
+02222222222000000000
+02222222222000000000
+00000000000000000000
+00000000000000000000
+00000000000000000000
+00000000000000000000
+00000000000000000000
+00000000000000000000
+01331111111111111110
+00000000000000000000", attributes);
+
+			win.X = Pos.Center ();
+			win.Y = Pos.Center ();
+			Application.Refresh ();
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+┌──────────────────┐
+│ File             │
+│                  │
+│                  │
+│                  │
+│    ┌────────┐    │
+│    │TL    TR│    │
+│    │        │    │
+│    │        │    │
+│    │        │    │
+│    │        │    │
+│    │        │    │
+│    │        │    │
+│    │BL    BR│    │
+│    └────────┘    │
+│                  │
+│                  │
+│                  │
+│ F2 File          │
+└──────────────────┘", output);
+			TestHelpers.AssertDriverColorsAre (@"
+00000000000000000000
+01111111111111111110
+00000000000000000000
+00000000000000000000
+00000000000000000000
+00000222222222200000
+00000222222222200000
+00000222222222200000
+00000222222222200000
+00000222222222200000
+00000222222222200000
+00000222222222200000
+00000222222222200000
+00000222222222200000
+00000222222222200000
+00000000000000000000
+00000000000000000000
+00000000000000000000
+01331111111111111110
+00000000000000000000", attributes);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void Application_QuitKey_Close_Current_MdiChild ()
+		{
+			var top = Top_With_MenuBar_And_StatusBar (false, true);
+			var win = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels ();
+
+			Assert.True (top.IsMdiContainer);
+
+			var iterations = -1;
+			Application.Iteration += () => {
+				iterations++;
+				if (iterations == 0) {
+					Assert.True (top.Running);
+					Assert.False (win.Running);
+					Assert.Equal (top, Application.Current);
+
+					Application.Run (win);
+				} else if (iterations == 1) {
+					Assert.True (top.Running);
+					Assert.True (win.Running);
+					Assert.Equal (win, Application.Current);
+
+					ReflectionTools.InvokePrivate (
+						typeof (Application),
+						"ProcessKeyEvent",
+						new KeyEvent (Application.QuitKey, new KeyModifiers ()));
+				} else if (iterations == 2) {
+					Assert.True (top.Running);
+					Assert.False (win.Running);
+					Assert.Equal (top, Application.Current);
+
+					ReflectionTools.InvokePrivate (
+						typeof (Application),
+						"ProcessKeyEvent",
+						new KeyEvent (Application.QuitKey, new KeyModifiers ()));
+				}
+			};
+
+			Application.Run (top);
+
+			Assert.False (top.Running);
+			Assert.False (win.Running);
+			Assert.Null (Application.Current);
+			Assert.Equal (2, iterations);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void Clicking_On_MdiContainer_With_MostFocused_Null_Or_Invalid_Maintain_Current_Child_Focused ()
+		{
+			var top = Top_With_MenuBar_And_StatusBar (false, true, false);
+			var win1 = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels ();
+			var tf1 = new TextField () { Width = 6 };
+			win1.Add (tf1);
+			var win2 = Window_With_TopLeft_TopRight_BottomLeft_BottomRight_Labels ();
+			var tf2 = new TextField () { Width = 6 };
+			win2.Add (tf2);
+			win2.X = Pos.Right (win1);
+
+			Assert.True (top.IsMdiContainer);
+
+			var iterations = -1;
+			Application.Iteration += () => {
+				iterations++;
+				if (iterations == 0) {
+					Assert.True (top.Running);
+					Assert.False (win1.Running);
+					Assert.False (win2.Running);
+					Assert.Equal (top, Application.Current);
+
+					Application.Run (win1);
+				} else if (iterations == 1) {
+					Assert.True (top.Running);
+					Assert.True (win1.Running);
+					Assert.False (win2.Running);
+					Assert.Equal (win1, Application.Current);
+
+					Application.Run (win2);
+				} else if (iterations == 2) {
+					Assert.True (top.Running);
+					Assert.True (win1.Running);
+					Assert.True (win2.Running);
+					Assert.Equal (win2, Application.Current);
+					Assert.Equal (tf2, win2.MostFocused);
+					Assert.Equal (new Rect (0, 0, 80, 25), top.Frame);
+					Assert.Equal (new Rect (1, 2, 10, 10), win1.Frame);
+					Assert.Equal (new Rect (11, 2, 10, 10), win2.Frame);
+
+					ReflectionTools.InvokePrivate (
+						typeof (Application),
+						"ProcessMouseEvent",
+						new MouseEvent () {
+							X = 30,
+							Y = 2,
+							Flags = MouseFlags.Button1Clicked
+						});
+				} else if (iterations == 3) {
+					Assert.True (top.Running);
+					Assert.True (win1.Running);
+					Assert.True (win2.Running);
+					Assert.Equal (win2, Application.Current);
+					Assert.Equal (tf2, win2.MostFocused);
+
+					ReflectionTools.InvokePrivate (
+						typeof (Application),
+						"ProcessMouseEvent",
+						new MouseEvent () {
+							X = 1,
+							Y = 2,
+							Flags = MouseFlags.Button1Clicked
+						});
+				} else if (iterations == 4) {
+					Assert.True (top.Running);
+					Assert.True (win1.Running);
+					Assert.True (win2.Running);
+					Assert.Equal (win1, Application.Current);
+					Assert.Equal (tf1, win1.MostFocused);
+
+					ReflectionTools.InvokePrivate (
+						typeof (Application),
+						"ProcessMouseEvent",
+						new MouseEvent () {
+							X = 30,
+							Y = 2,
+							Flags = MouseFlags.Button1Clicked
+						});
+				} else if (iterations == 5) {
+					Assert.True (top.Running);
+					Assert.True (win1.Running);
+					Assert.True (win2.Running);
+					Assert.Equal (win1, Application.Current);
+					Assert.Equal (tf1, win1.MostFocused);
+
+					ReflectionTools.InvokePrivate (
+						typeof (Application),
+						"ProcessKeyEvent",
+						new KeyEvent (Application.QuitKey, new KeyModifiers ()));
+				} else if (iterations == 6) {
+					Assert.True (top.Running);
+					Assert.False (win1.Running);
+					Assert.True (win2.Running);
+					Assert.Equal (win2, Application.Current);
+					Assert.Equal (tf2, win2.MostFocused);
+
+					ReflectionTools.InvokePrivate (
+						typeof (Application),
+						"ProcessKeyEvent",
+						new KeyEvent (Application.QuitKey, new KeyModifiers ()));
+				} else if (iterations == 7) {
+					Assert.True (top.Running);
+					Assert.False (win1.Running);
+					Assert.False (win2.Running);
+					Assert.Equal (top, Application.Current);
+					Assert.Equal (top.Subviews [0], top.MostFocused);
+					Assert.Equal ("ContentView", top.Subviews [0].GetType ().Name);
+
+					ReflectionTools.InvokePrivate (
+						typeof (Application),
+						"ProcessKeyEvent",
+						new KeyEvent (Application.QuitKey, new KeyModifiers ()));
+				}
+			};
+
+			Application.Run (top);
+
+			Assert.False (top.Running);
+			Assert.False (win1.Running);
+			Assert.False (win2.Running);
+			Assert.Null (Application.Current);
+			Assert.Equal (7, iterations);
+		}
+
+		[Fact, AutoInitShutdown]
+		public void MdiChildes_Null_Does_Not_Throws ()
+		{
+			var top = Top_With_MenuBar_And_StatusBar (false, true);
+
+			Assert.True (top.IsMdiContainer);
+
+			Application.Begin (top);
+
+			var mdiChildes = Application.MdiChildes;
+			Assert.Empty (mdiChildes);
+
+			top.IsMdiContainer = false;
+			var exception = Record.Exception (() => mdiChildes = Application.MdiChildes);
+			Assert.Null (exception);
+			Assert.Empty (mdiChildes);
+		}
 	}
 }

+ 110 - 0
UnitTests/TopLevels/WindowTests.cs

@@ -253,5 +253,115 @@ namespace Terminal.Gui.TopLevelTests {
 			var exception = Record.Exception (() => win.ProcessHotKey (new KeyEvent (Key.AltMask, new KeyModifiers { Alt = true })));
 			Assert.Null (exception);
 		}
+
+		[Fact, AutoInitShutdown]
+		public void Adding_Center_Window_Child_To_Window_Parent_Always_LayoutSubviews ()
+		{
+			var parentWin = new Window ();
+			View childWin = null;
+
+			var menu = new MenuBar (new MenuBarItem [] {
+				new MenuBarItem ("Child", new MenuItem [] {
+					new MenuItem ("_Create Child", "", () => {
+						childWin = new Window () {
+							X = Pos.Center (),
+							Y = Pos.Center (),
+							Width = 10,
+							Height = 10
+						};
+						parentWin.Add (childWin);
+					})
+				}),
+				new MenuBarItem ("View", new MenuBarItem [] {
+					new MenuBarItem ("Create", new MenuItem [] {
+						new MenuItem("_TextField", "", () => {
+							var tf = new TextField ("Test") {
+								X = Pos.Center (),
+								Y = Pos.Center (),
+								Width = 5
+							};
+							childWin.Add (tf);
+						})
+					})
+				})
+			});
+
+			parentWin.Add (menu);
+			Application.Top.Add (parentWin);
+			Application.Begin (Application.Top);
+			((FakeDriver)Application.Driver).SetBufferSize (20, 20);
+
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+┌──────────────────┐
+│ Child  View      │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+│                  │
+└──────────────────┘", output);
+
+			Assert.True (parentWin.ProcessHotKey (new KeyEvent (Key.C | Key.AltMask, new KeyModifiers { Alt = true })));
+			Application.MainLoop.MainIteration ();
+			parentWin.Redraw (parentWin.Bounds);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+┌──────────────────┐
+│ Child  View      │
+│                  │
+│                  │
+│                  │
+│    ┌────────┐    │
+│    │        │    │
+│    │        │    │
+│    │        │    │
+│    │        │    │
+│    │        │    │
+│    │        │    │
+│    │        │    │
+│    │        │    │
+│    └────────┘    │
+│                  │
+│                  │
+│                  │
+│                  │
+└──────────────────┘", output);
+
+			Assert.True (parentWin.ProcessHotKey (new KeyEvent (Key.T | Key.AltMask, new KeyModifiers { Alt = true })));
+			Application.MainLoop.MainIteration ();
+			childWin.Redraw (childWin.Bounds);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+┌──────────────────┐
+│ Child  View      │
+│                  │
+│                  │
+│                  │
+│    ┌────────┐    │
+│    │        │    │
+│    │        │    │
+│    │        │    │
+│    │ Test   │    │
+│    │        │    │
+│    │        │    │
+│    │        │    │
+│    │        │    │
+│    └────────┘    │
+│                  │
+│                  │
+│                  │
+│                  │
+└──────────────────┘", output);
+		}
 	}
 }