Tigger Kindel 2 éve
szülő
commit
66e24905dc

+ 52 - 42
Terminal.Gui/Core/Toplevel.cs

@@ -210,7 +210,7 @@ namespace Terminal.Gui {
 
 			Application.GrabbingMouse += Application_GrabbingMouse;
 			Application.UnGrabbingMouse += Application_UnGrabbingMouse;
-      
+
 			// TODO: v2 - ALL Views (Responders??!?!) should support the commands related to 
 			//    - Focus
 			//  Move the appropriate AddCommand calls to `Responder`
@@ -378,8 +378,7 @@ namespace Terminal.Gui {
 
 		/// <summary>
 		/// <see langword="true"/> if was already loaded by the <see cref="Application.Begin(Toplevel)"/>
-		/// <see langword="false"/>, otherwise. This is used to avoid the <see cref="View._needsDisplay"/>
-		/// having wrong values while this was not yet loaded.
+		/// <see langword="false"/>, otherwise.
 		/// </summary>
 		public bool IsLoaded { get; private set; }
 
@@ -628,64 +627,68 @@ namespace Terminal.Gui {
 		/// <param name="statusBar">The new top most statusBar</param>
 		/// <returns>The <see cref="Toplevel"/> that is Application.Top</returns>
 		internal View EnsureVisibleBounds (Toplevel top, int x, int y,
-			out int nx, out int ny, out MenuBar menuBar, out StatusBar statusBar)
+					out int nx, out int ny, out MenuBar mb, out StatusBar sb)
 		{
-			int maxWidth;
+			int l;
 			View superView;
-			var isTopTop = top?.SuperView == null || top == Application.Top || top?.SuperView == Application.Top;
-			if (isTopTop) {
-				maxWidth = Driver.Cols;
+			if (top?.SuperView == null || top == Application.Top || top?.SuperView == Application.Top) {
+				l = Driver.Cols;
 				superView = Application.Top;
 			} else {
-				maxWidth = top.SuperView.Frame.Width;
-				// BUGBUG: v2 - No code ever uses the return of this function if `top` is not Application.Top
+				l = top.SuperView.Frame.Width;
 				superView = top.SuperView;
 			}
-			nx = Math.Max (x, 0);
-			nx = nx + top.Frame.Width > maxWidth ? Math.Max (maxWidth - 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);
+			if (top.Frame.Width <= l) {
+				nx = Math.Max (x, 0);
+				nx = nx + top.Frame.Width > l ? Math.Max (l - top.Frame.Width, 0) : nx;
+				if (nx + mfLength > top.Frame.X + top.Frame.Width) {
+					nx = Math.Max (top.Frame.Right - mfLength, 0);
+				}
+			} else {
+				nx = x;
 			}
 			//System.Diagnostics.Debug.WriteLine ($"nx:{nx}, rWidth:{rWidth}");
-			bool isMenuBarVisible, isStatusBarVisible;
-			if (isTopTop) {
-				isMenuBarVisible = Application.Top.MenuBar?.Visible == true;
-				menuBar = Application.Top.MenuBar;
+			bool m, s;
+			if (top?.SuperView == null || top == Application.Top || top?.SuperView == Application.Top) {
+				m = Application.Top.MenuBar?.Visible == true;
+				mb = Application.Top.MenuBar;
 			} else {
 				var t = top.SuperView;
-				while (!(t is Toplevel)) {
+				while (t is not Toplevel) {
 					t = t.SuperView;
 				}
-				isMenuBarVisible = ((Toplevel)t).MenuBar?.Visible == true;
-				menuBar = ((Toplevel)t).MenuBar;
+				m = ((Toplevel)t).MenuBar?.Visible == true;
+				mb = ((Toplevel)t).MenuBar;
 			}
-			if (isTopTop) {
-				maxWidth = isMenuBarVisible ? 1 : 0;
+			if (top?.SuperView == null || top == Application.Top || top?.SuperView == Application.Top) {
+				l = m ? 1 : 0;
 			} else {
-				maxWidth = 0;
+				l = 0;
 			}
-			ny = Math.Max (y, maxWidth);
-			if (isTopTop) {
-				isStatusBarVisible = Application.Top.StatusBar?.Visible == true;
-				statusBar = Application.Top.StatusBar;
+			ny = Math.Max (y, l);
+			if (top?.SuperView == null || top == Application.Top || top?.SuperView == Application.Top) {
+				s = Application.Top.StatusBar?.Visible == true;
+				sb = Application.Top.StatusBar;
 			} else {
 				var t = top.SuperView;
-				while (!(t is Toplevel)) {
+				while (t is not Toplevel) {
 					t = t.SuperView;
 				}
-				isStatusBarVisible = ((Toplevel)t).StatusBar?.Visible == true;
-				statusBar = ((Toplevel)t).StatusBar;
+				s = ((Toplevel)t).StatusBar?.Visible == true;
+				sb = ((Toplevel)t).StatusBar;
 			}
-			if (isTopTop) {
-				maxWidth = isStatusBarVisible ? Driver.Rows - 1 : Driver.Rows;
+			if (top?.SuperView == null || top == Application.Top || top?.SuperView == Application.Top) {
+				l = s ? Driver.Rows - 1 : Driver.Rows;
 			} else {
-				maxWidth = isStatusBarVisible ? top.SuperView.Frame.Height - 1 : top.SuperView.Frame.Height;
+				l = s ? top.SuperView.Frame.Height - 1 : top.SuperView.Frame.Height;
 			}
-			ny = Math.Min (ny, maxWidth);
-			ny = ny + top.Frame.Height >= maxWidth ? Math.Max (maxWidth - top.Frame.Height, isMenuBarVisible ? 1 : 0) : ny;
-			if (ny + mfLength > top.Frame.Y + top.Frame.Height) {
-				ny = Math.Max (top.Frame.Bottom - mfLength, 0);
+			ny = Math.Min (ny, l);
+			if (top.Frame.Height <= 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);
+				}
 			}
 			//System.Diagnostics.Debug.WriteLine ($"ny:{ny}, rHeight:{rHeight}");
 
@@ -713,15 +716,15 @@ namespace Terminal.Gui {
 			var superView = EnsureVisibleBounds (top, top.Frame.X, top.Frame.Y,
 				out int nx, out int ny, out _, out StatusBar sb);
 			bool layoutSubviews = false;
-			if ((top?.SuperView != null || (top != Application.Top && top.Modal)
+			if ((superView != top || 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) {
+				&& (top.Frame.X + top.Frame.Width > Driver.Cols || 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;
 				}
@@ -1011,6 +1014,13 @@ namespace Terminal.Gui {
 		{
 			return MostFocused?.OnLeave (view) ?? base.OnLeave (view);
 		}
+
+		///<inheritdoc/>
+		protected override void Dispose (bool disposing)
+		{
+			dragPosition = null;
+			base.Dispose (disposing);
+		}
 	}
 
 	/// <summary>

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

@@ -115,9 +115,17 @@ namespace Terminal.Gui {
 				// Make it bigger to fit the margin, border, & padding
 				frame = new Rect (frame.Location, new Size (Margin.Thickness.Horizontal + BorderFrame.Thickness.Horizontal + Padding.Thickness.Horizontal + 1, Margin.Thickness.Vertical + BorderFrame.Thickness.Vertical + Padding.Thickness.Vertical + 1));
 			}
-			Frame = frame;
 		}
 
+		///// <summary>
+		///// Enumerates the various <see cref="View"/>s in the embedded <see cref="ContentView"/>.
+		///// </summary>
+		///// <returns>The enumerator.</returns>
+		//public new IEnumerator GetEnumerator ()
+		//{
+		//	return contentView.GetEnumerator ();
+		//}
+
 		/// <inheritdoc/>
 		public override void Add (View view)
 		{

+ 3 - 2
Terminal.Gui/Windows/Dialog.cs

@@ -78,8 +78,9 @@ namespace Terminal.Gui {
 			ColorScheme = Colors.Dialog;
 			Modal = true;
 			ButtonAlignment = DefaultButtonAlignment;
-			Border = DefaultBorder;
-			//Border.Title = title;
+			if (Border == null) {
+				Border = DefaultBorder;
+			}
 
 			if (buttons != null) {
 				foreach (var b in buttons) {

+ 17 - 2
Terminal.Gui/Windows/MessageBox.cs

@@ -1,6 +1,8 @@
 using NStack;
 using System;
 using System.Collections.Generic;
+using Terminal.Gui.Configuration;
+using static Terminal.Gui.Configuration.ConfigurationManager;
 
 namespace Terminal.Gui {
 	/// <summary>
@@ -239,6 +241,17 @@ namespace Terminal.Gui {
 			return QueryFull (true, 0, 0, title, message, defaultButton, border, wrapMessagge, buttons);
 		}
 
+		/// <summary>
+		/// Defines the default border styling for <see cref="Dialog"/>. Can be configured via <see cref="ConfigurationManager"/>.
+		/// </summary>
+		[SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
+		public static Border DefaultBorder { get; set; } = new Border () {
+			BorderStyle = BorderStyle.Single,
+			DrawMarginFrame = false,
+			Effect3D = true,
+			Effect3DOffset = new Point (1, 1),
+		};
+
 		static int QueryFull (bool useErrorColors, int width, int height, ustring title, ustring message,
 			int defaultButton = 0, Border border = null, bool wrapMessagge = true, params ustring [] buttons)
 		{
@@ -277,7 +290,9 @@ namespace Terminal.Gui {
 				buttonList.Add (b);
 				count++;
 			}
-
+			if (border == null) {
+				border = DefaultBorder;
+			}
 			// Create Dialog (retain backwards compat by supporting specifying height/width)
 			Dialog d;
 			if (width == 0 & height == 0) {
@@ -326,7 +341,7 @@ namespace Terminal.Gui {
 			for (int n = 0; n < buttonList.Count; n++) {
 				int buttonId = n;
 				var b = buttonList [n];
-				b.Clicked += (s,e) => {
+				b.Clicked += (s, e) => {
 					Clicked = buttonId;
 					Application.RequestStop ();
 				};

+ 91 - 1
UnitTests/TopLevels/DialogTests.cs

@@ -582,9 +582,99 @@ namespace Terminal.Gui.TopLevelTests {
 		{
 			for (int i = 0; i < 8; i++) {
 				var fd = new FileDialog ();
-				fd.Ready += (s,e) => Application.RequestStop ();
+				fd.Ready += (s, e) => Application.RequestStop ();
 				Application.Run (fd);
 			}
 		}
+
+		[Fact, AutoInitShutdown]
+		public void Dialog_Opened_From_Another_Dialog ()
+		{
+			var btn1 = new Button ("press me 1");
+			Button btn2 = null;
+			Button btn3 = null;
+			string expected = null;
+			btn1.Clicked += (s, e) => {
+				btn2 = new Button ("Show Sub");
+				btn3 = new Button ("Close");
+				btn3.Clicked += (s, e) => Application.RequestStop ();
+				btn2.Clicked += (s, e) => { MessageBox.Query ("hey", "ya", "ok"); };
+				var dlg = new Dialog ("Hey", btn2, btn3);
+
+				Application.Run (dlg);
+			};
+
+			var iterations = -1;
+			Application.Iteration += () => {
+				iterations++;
+				if (iterations == 0) {
+					Assert.True (btn1.ProcessKey (new KeyEvent (Key.Enter, new KeyModifiers ())));
+				} else if (iterations == 1) {
+					expected = @"
+      ┌ Hey ─────────────────────────────────────────────────────────────┐
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                      [ Show Sub ] [ Close ]                      │
+      └──────────────────────────────────────────────────────────────────┘";
+					TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
+
+					Assert.True (btn2.ProcessKey (new KeyEvent (Key.Enter, new KeyModifiers ())));
+				} else if (iterations == 2) {
+					TestHelpers.AssertDriverContentsWithFrameAre (@"
+      ┌ Hey ─────────────────────────────────────────────────────────────┐
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │         ┌ hey ─────────────────────────────────────────┐         │
+      │         │                      ya                      │         │
+      │         │                                              │         │
+      │         │                   [◦ ok ◦]                   │         │
+      │         └──────────────────────────────────────────────┘         │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                                                                  │
+      │                      [ Show Sub ] [ Close ]                      │
+      └──────────────────────────────────────────────────────────────────┘", output);
+
+					Assert.True (Application.Current.ProcessKey (new KeyEvent (Key.Enter, new KeyModifiers ())));
+				} else if (iterations == 3) {
+					TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
+
+					Assert.True (btn3.ProcessKey (new KeyEvent (Key.Enter, new KeyModifiers ())));
+				} else if (iterations == 4) {
+					TestHelpers.AssertDriverContentsWithFrameAre ("", output);
+
+					Application.RequestStop ();
+				}
+			};
+
+			Application.Run ();
+			Application.Shutdown ();
+
+			Assert.Equal (4, iterations);
+		}
 	}
 }

+ 165 - 14
UnitTests/TopLevels/ToplevelTests.cs

@@ -149,7 +149,6 @@ namespace Terminal.Gui.TopLevelTests {
 		[AutoInitShutdown]
 		public void Internal_Tests ()
 		{
-			Toplevel.dragPosition = null; // dragPosition is `static` and must be reset for each instance or unit tests will fail?
 			var top = new Toplevel ();
 
 			var eventInvoked = "";
@@ -200,7 +199,7 @@ namespace Terminal.Gui.TopLevelTests {
 			Application.Begin (top);
 			Assert.Equal (top, Application.Top);
 
-			// top is Application.Top without menu and status bar.
+			// Application.Top without menu and status bar.
 			var supView = top.EnsureVisibleBounds (top, 2, 2, out int nx, out int ny, out MenuBar mb, out StatusBar sb);
 			Assert.Equal (Application.Top, supView);
 			Assert.Equal (0, nx);
@@ -211,7 +210,7 @@ namespace Terminal.Gui.TopLevelTests {
 			top.AddMenuStatusBar (new MenuBar ());
 			Assert.NotNull (top.MenuBar);
 
-			// top is Application.Top with a menu and without status bar.
+			// 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);
@@ -221,20 +220,24 @@ namespace Terminal.Gui.TopLevelTests {
 			top.AddMenuStatusBar (new StatusBar ());
 			Assert.NotNull (top.StatusBar);
 
-			// top is Application.Top with a menu and status bar.
+			// 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);
+			// The available height is lower than the Application.Top height minus
+			// the menu bar and status bar, then the top can go beyond the bottom
+			Assert.Equal (2, ny);
 			Assert.NotNull (mb);
 			Assert.NotNull (sb);
 
 			top.RemoveMenuStatusBar (top.MenuBar);
 			Assert.Null (top.MenuBar);
 
-			// top is Application.Top without a menu and with a status bar.
+			// 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);
-			Assert.Equal (0, ny);
+			// The available height is lower than the Application.Top height minus
+			// the status bar, then the top can go beyond the bottom
+			Assert.Equal (2, ny);
 			Assert.Null (mb);
 			Assert.NotNull (sb);
 
@@ -252,7 +255,7 @@ namespace Terminal.Gui.TopLevelTests {
 			supView = win.EnsureVisibleBounds (win, 0, 0, out nx, out ny, out mb, out sb);
 			Assert.Equal (Application.Top, supView);
 
-			// top is Application.Top without menu and status bar.
+			// Application.Top without menu and status bar.
 			top.EnsureVisibleBounds (win, 0, 0, out nx, out ny, out mb, out sb);
 			Assert.Equal (0, nx);
 			Assert.Equal (0, ny);
@@ -262,7 +265,7 @@ namespace Terminal.Gui.TopLevelTests {
 			top.AddMenuStatusBar (new MenuBar ());
 			Assert.NotNull (top.MenuBar);
 
-			// top is Application.Top with a menu and without status bar.
+			// Application.Top with a menu and without status bar.
 			top.EnsureVisibleBounds (win, 2, 2, out nx, out ny, out mb, out sb);
 			Assert.Equal (0, nx);
 			Assert.Equal (1, ny);
@@ -272,10 +275,12 @@ namespace Terminal.Gui.TopLevelTests {
 			top.AddMenuStatusBar (new StatusBar ());
 			Assert.NotNull (top.StatusBar);
 
-			// top is Application.Top with a menu and status bar.
+			// Application.Top with a menu and status bar.
 			top.EnsureVisibleBounds (win, 30, 20, out nx, out ny, out mb, out sb);
 			Assert.Equal (0, nx);
-			Assert.Equal (1, ny);
+			// The available height is lower than the Application.Top height minus
+			// the menu bar and status bar, then the top can go beyond the bottom
+			Assert.Equal (20, ny);
 			Assert.NotNull (mb);
 			Assert.NotNull (sb);
 
@@ -289,7 +294,7 @@ namespace Terminal.Gui.TopLevelTests {
 			win = new Window () { Width = 60, Height = 15 };
 			top.Add (win);
 
-			// top is Application.Top without menu and status bar.
+			// Application.Top without menu and status bar.
 			top.EnsureVisibleBounds (win, 0, 0, out nx, out ny, out mb, out sb);
 			Assert.Equal (0, nx);
 			Assert.Equal (0, ny);
@@ -299,7 +304,7 @@ namespace Terminal.Gui.TopLevelTests {
 			top.AddMenuStatusBar (new MenuBar ());
 			Assert.NotNull (top.MenuBar);
 
-			// top is Application.Top with a menu and without status bar.
+			// Application.Top with a menu and without status bar.
 			top.EnsureVisibleBounds (win, 2, 2, out nx, out ny, out mb, out sb);
 			Assert.Equal (2, nx);
 			Assert.Equal (2, ny);
@@ -309,7 +314,7 @@ namespace Terminal.Gui.TopLevelTests {
 			top.AddMenuStatusBar (new StatusBar ());
 			Assert.NotNull (top.StatusBar);
 
-			// top is Application.Top with a menu and status bar.
+			// Application.Top with a menu and status bar.
 			top.EnsureVisibleBounds (win, 30, 20, out nx, out ny, out mb, out sb);
 			Assert.Equal (20, nx); // 20+60=80
 			Assert.Equal (9, ny); // 9+15+1(mb)=25
@@ -1213,5 +1218,151 @@ namespace Terminal.Gui.TopLevelTests {
 				});
 			Assert.Equal (scrollView, Application.MouseGrabView);
 		}
+
+		[Fact, AutoInitShutdown]
+		public void Dialog_Bounds_Bigger_Than_Driver_Cols_And_Rows_Allow_Drag_Beyond_Left_Right_And_Bottom ()
+		{
+			var menu = new MenuBar (new MenuBarItem [] {
+				new MenuBarItem("File", new MenuItem [] {
+					new MenuItem("New", "", null)
+				})
+			});
+
+			var sb = new StatusBar (new StatusItem [] {
+				new StatusItem(Key.N, "~CTRL-N~ New", null)
+			});
+			var top = Application.Top;
+			top.Add (menu, sb);
+			var dialog = new Dialog ("Dialog", 20, 3, new Button ("Ok"));
+			Application.Begin (top);
+			((FakeDriver)Application.Driver).SetBufferSize (40, 10);
+			Application.Begin (dialog);
+			Application.Refresh ();
+			Assert.Equal (new Rect (0, 0, 40, 10), top.Frame);
+			Assert.Equal (new Rect (10, 3, 20, 3), dialog.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+ File                         
+                              
+                              
+          ┌ Dialog ──────────┐
+          │      [ Ok ]      │
+          └──────────────────┘
+                              
+                              
+                              
+ CTRL-N New                   ", output);
+
+			Assert.Null (Application.MouseGrabView);
+
+			ReflectionTools.InvokePrivate (
+				typeof (Application),
+				"ProcessMouseEvent",
+				new MouseEvent () {
+					X = 10,
+					Y = 3,
+					Flags = MouseFlags.Button1Pressed
+				});
+
+			Assert.Equal (dialog, Application.MouseGrabView);
+
+			ReflectionTools.InvokePrivate (
+				typeof (Application),
+				"ProcessMouseEvent",
+				new MouseEvent () {
+					X = -11,
+					Y = -4,
+					Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
+				});
+
+			Application.Refresh ();
+			Assert.Equal (new Rect (0, 0, 40, 10), top.Frame);
+			Assert.Equal (new Rect (0, 1, 20, 3), dialog.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+ File               
+┌ Dialog ──────────┐
+│      [ Ok ]      │
+└──────────────────┘
+                    
+                    
+                    
+                    
+                    
+ CTRL-N New         ", output);
+
+			// Changes Top size to same size as Dialog more menu and scroll bar
+			((FakeDriver)Application.Driver).SetBufferSize (20, 5);
+			ReflectionTools.InvokePrivate (
+				typeof (Application),
+				"ProcessMouseEvent",
+				new MouseEvent () {
+					X = -1,
+					Y = -1,
+					Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
+				});
+
+			Application.Refresh ();
+			Assert.Equal (new Rect (0, 0, 20, 5), top.Frame);
+			Assert.Equal (new Rect (0, 1, 20, 3), dialog.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+ File               
+┌ Dialog ──────────┐
+│      [ Ok ]      │
+└──────────────────┘
+ CTRL-N New         ", output);
+
+			// Changes Top size smaller than Dialog size
+			((FakeDriver)Application.Driver).SetBufferSize (19, 3);
+			ReflectionTools.InvokePrivate (
+				typeof (Application),
+				"ProcessMouseEvent",
+				new MouseEvent () {
+					X = -1,
+					Y = -1,
+					Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
+				});
+
+			Application.Refresh ();
+			Assert.Equal (new Rect (0, 0, 19, 3), top.Frame);
+			Assert.Equal (new Rect (-1, 1, 20, 3), dialog.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+ File              
+ Dialog ──────────┐
+      [ Ok ]      │", output);
+
+			ReflectionTools.InvokePrivate (
+				typeof (Application),
+				"ProcessMouseEvent",
+				new MouseEvent () {
+					X = 18,
+					Y = 3,
+					Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
+				});
+
+			Application.Refresh ();
+			Assert.Equal (new Rect (0, 0, 19, 3), top.Frame);
+			Assert.Equal (new Rect (18, 2, 20, 3), dialog.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+ File              
+                   
+ CTRL-N New       ┌", output);
+
+			// On a real app we can't go beyond the SuperView bounds
+			ReflectionTools.InvokePrivate (
+				typeof (Application),
+				"ProcessMouseEvent",
+				new MouseEvent () {
+					X = 19,
+					Y = 4,
+					Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
+				});
+
+			Application.Refresh ();
+			Assert.Equal (new Rect (0, 0, 19, 3), top.Frame);
+			Assert.Equal (new Rect (19, 2, 20, 3), dialog.Frame);
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+ File      
+           
+ CTRL-N New", output);
+		}
 	}
 }