diff --git a/Terminal.Gui/Core/Application.cs b/Terminal.Gui/Core/Application.cs index 326c41421..c72ec41f5 100644 --- a/Terminal.Gui/Core/Application.cs +++ b/Terminal.Gui/Core/Application.cs @@ -658,7 +658,7 @@ namespace Terminal.Gui { var rx = x - startFrame.X; var ry = y - startFrame.Y; if (top.Visible && top.Frame.Contains (rx, ry)) { - var deep = FindDeepestView (top, rx, ry, out resx, out resy); + var deep = View.FindDeepestView (top, rx, ry, out resx, out resy); if (deep == null) return FindDeepestMdiView (top, rx, ry, out resx, out resy); if (deep != MdiTop) @@ -671,45 +671,6 @@ namespace Terminal.Gui { return start; } - /// - /// Finds the deepest view at the specified coordinates, specified relative to 's superview. - /// - /// - /// - /// - /// - /// - /// - static View FindDeepestView (View start, int x, int y, out int resx, out int resy) - { - var startFrame = start.Frame; - - if (!startFrame.Contains (x, y)) { - resx = 0; - resy = 0; - return null; - } - if (start.InternalSubviews != null) { - int count = start.InternalSubviews.Count; - if (count > 0) { - var rx = x - (startFrame.X + start.GetBoundsOffset ().X); - var ry = y - (startFrame.Y + start.GetBoundsOffset ().Y); - for (int i = count - 1; i >= 0; i--) { - View v = start.InternalSubviews [i]; - if (v.Visible && v.Frame.Contains (rx, ry)) { - var deep = FindDeepestView (v, rx, ry, out resx, out resy); - if (deep == null) - return v; - return deep; - } - } - } - } - resx = x - startFrame.X; - resy = y - startFrame.Y; - return start; - } - static View FindTopFromView (View view) { View top = view?.SuperView != null && view?.SuperView != Top @@ -832,7 +793,7 @@ namespace Terminal.Gui { return; } - var view = FindDeepestView (Current, me.X, me.Y, out int rx, out int ry); + var view = View.FindDeepestView (Current, me.X, me.Y, out int rx, out int ry); if (view != null && view.WantContinuousButtonPressed) { WantContinuousButtonPressedView = view; @@ -849,9 +810,7 @@ namespace Terminal.Gui { } if (mouseGrabView != null) { - view ??= mouseGrabView; - - var newxy = mouseGrabView.ScreenToBounds (me.X, me.Y); + var newxy = mouseGrabView.ScreenToView (me.X, me.Y); var nme = new MouseEvent () { X = newxy.X, Y = newxy.Y, @@ -873,7 +832,7 @@ namespace Terminal.Gui { && 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); + view = View.FindDeepestView (top, me.X, me.Y, out rx, out ry); if (view != null && view != MdiTop && top != Current) { MoveCurrent ((Toplevel)top); @@ -1272,6 +1231,7 @@ namespace Terminal.Gui { if (state.Toplevel != Top && (!Top._needsDisplay.IsEmpty || Top._childNeedsDisplay || Top.LayoutNeeded)) { + state.Toplevel.SetNeedsDisplay (state.Toplevel.Bounds); Top.Redraw (Top.Bounds); foreach (var top in toplevels.Reverse ()) { if (top != Top && top != state.Toplevel) { @@ -1279,7 +1239,6 @@ namespace Terminal.Gui { top.Redraw (top.Bounds); } } - state.Toplevel.SetNeedsDisplay (state.Toplevel.Bounds); } if (toplevels.Count == 1 && state.Toplevel == Top && (Driver.Cols != state.Toplevel.Frame.Width || Driver.Rows != state.Toplevel.Frame.Height) diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index e92db8d1d..f7be5dba3 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -1038,7 +1038,7 @@ namespace Terminal.Gui { // BUGBUG: v2 - ? - If layoutstyle is absolute, this overwrites the current frame h/w with 0. Hmmm... frame = new Rect (new Point (actX, actY), new Size (w, h)); // Set frame, not Frame! - + } //// BUGBUG: I think these calls are redundant or should be moved into just the AutoSize case if (IsInitialized || LayoutStyle == LayoutStyle.Absolute) { @@ -1047,7 +1047,7 @@ namespace Terminal.Gui { SetMinWidthHeight (); SetNeedsLayout (); SetNeedsDisplay (); - } + } } void TextFormatter_HotKeyChanged (object sender, KeyChangedEventArgs e) @@ -1139,8 +1139,11 @@ namespace Terminal.Gui { /// public void SetSubViewNeedsDisplay () { + if (_childNeedsDisplay) { + return; + } _childNeedsDisplay = true; - if (_superView != null) + if (_superView != null && !_superView._childNeedsDisplay) _superView.SetSubViewNeedsDisplay (); } @@ -1490,7 +1493,7 @@ namespace Terminal.Gui { /// View-relative region for the frame to be drawn. /// The padding to add around the outside of the drawn frame. /// If set to it fill will the contents. - [ObsoleteAttribute ("This method is obsolete in v2. Use use LineCanvas or Frame instead instead.", false)] + [ObsoleteAttribute ("This method is obsolete in v2. Use use LineCanvas or Frame instead.", false)] public void DrawFrame (Rect region, int padding = 0, bool fill = false) { var scrRect = ViewToScreen (region); @@ -1723,7 +1726,7 @@ namespace Terminal.Gui { } /// - /// Removes the and the setting on this view. + /// Removes the and the setting on this view. /// protected void ClearNeedsDisplay () { @@ -3480,5 +3483,47 @@ namespace Terminal.Gui { return top; } + + /// + /// Finds which view that belong to the superview at the provided location. + /// + /// The superview where to look for. + /// The column location in the superview. + /// The row location in the superview. + /// The found view screen relative column location. + /// The found view screen relative row location. + /// + /// The view that was found at the and coordinates. + /// if no view was found. + /// + public static View FindDeepestView (View start, int x, int y, out int resx, out int resy) + { + var startFrame = start.Frame; + + if (!startFrame.Contains (x, y)) { + resx = 0; + resy = 0; + return null; + } + if (start.InternalSubviews != null) { + int count = start.InternalSubviews.Count; + if (count > 0) { + var rx = x - (startFrame.X + start.GetBoundsOffset ().X); + var ry = y - (startFrame.Y + start.GetBoundsOffset ().Y); + for (int i = count - 1; i >= 0; i--) { + View v = start.InternalSubviews [i]; + if (v.Visible && v.Frame.Contains (rx, ry)) { + var deep = FindDeepestView (v, rx, ry, out resx, out resy); + if (deep == null) + return v; + return deep; + } + } + } + } + resx = x - startFrame.X; + resy = y - startFrame.Y; + return start; + } } } diff --git a/Terminal.Gui/Views/ContextMenu.cs b/Terminal.Gui/Views/ContextMenu.cs index df6da1de9..4a0ec5a5f 100644 --- a/Terminal.Gui/Views/ContextMenu.cs +++ b/Terminal.Gui/Views/ContextMenu.cs @@ -91,7 +91,7 @@ namespace Terminal.Gui { if (menuBar != null) { Hide (); } - container = Application.Current; + container = Application.Top; container.Closing += Container_Closing; container.Resized += Container_Resized; var frame = container.Frame; @@ -162,7 +162,7 @@ namespace Terminal.Gui { /// public void Hide () { - menuBar.CleanUp (); + menuBar?.CleanUp (); Dispose (); } @@ -194,7 +194,7 @@ namespace Terminal.Gui { set { var oldKey = key; key = value; - KeyChanged?.Invoke (this, new KeyChangedEventArgs(oldKey,key)); + KeyChanged?.Invoke (this, new KeyChangedEventArgs (oldKey, key)); } } @@ -206,7 +206,7 @@ namespace Terminal.Gui { set { var oldFlags = mouseFlags; mouseFlags = value; - MouseFlagsChanged?.Invoke (this, new MouseFlagsChangedEventArgs(oldFlags,value)); + MouseFlagsChanged?.Invoke (this, new MouseFlagsChangedEventArgs (oldFlags, value)); } } diff --git a/Terminal.Gui/Views/Menu.cs b/Terminal.Gui/Views/Menu.cs index 1d3072200..c0c63b831 100644 --- a/Terminal.Gui/Views/Menu.cs +++ b/Terminal.Gui/Views/Menu.cs @@ -477,6 +477,11 @@ namespace Terminal.Gui { WantMousePositionReports = host.WantMousePositionReports; } + if (Application.Current != null) { + Application.Current.DrawContentComplete += Current_DrawContentComplete; + } + Application.RootMouseEvent += Application_RootMouseEvent; + // Things this view knows how to do AddCommand (Command.LineUp, () => MoveUp ()); AddCommand (Command.LineDown, () => MoveDown ()); @@ -502,6 +507,22 @@ namespace Terminal.Gui { AddKeyBinding (Key.Enter, Command.Accept); } + private void Application_RootMouseEvent (MouseEvent me) + { + var view = View.FindDeepestView (this, me.X, me.Y, out int rx, out int ry); + if (view == this) { + var nme = new MouseEvent () { + X = rx, + Y = ry, + Flags = me.Flags, + View = view + }; + if (MouseEvent (nme) || me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1Released) { + me.Handled = true; + } + } + } + internal Attribute DetermineColorSchemeFor (MenuItem item, int index) { if (item != null) { @@ -511,9 +532,19 @@ namespace Terminal.Gui { return GetNormalColor (); } - // Draws the Menu, within the Frame public override void Redraw (Rect bounds) { + } + + // Draws the Menu, within the Frame + private void Current_DrawContentComplete (object sender, DrawEventArgs e) + { + if (barItems.Children == null) { + return; + } + var savedClip = Driver.Clip; + Application.Driver.Clip = Application.Top.Frame; + Driver.SetAttribute (GetNormalColor ()); DrawFrame (Bounds, padding: 0, fill: true); @@ -612,6 +643,8 @@ namespace Terminal.Gui { } } } + Driver.Clip = savedClip; + PositionCursor (); } @@ -905,6 +938,15 @@ namespace Terminal.Gui { return base.OnEnter (view); } + + protected override void Dispose (bool disposing) + { + if (Application.Current != null) { + Application.Current.DrawContentComplete -= Current_DrawContentComplete; + } + Application.RootMouseEvent -= Application_RootMouseEvent; + base.Dispose (disposing); + } } /// @@ -1322,31 +1364,31 @@ namespace Terminal.Gui { switch (subMenu) { case null: // Open a submenu below a MenuBar - lastFocused = lastFocused ?? (SuperView == null ? Application.Current.MostFocused : SuperView.MostFocused); + lastFocused ??= (SuperView == null ? Application.Current.MostFocused : SuperView.MostFocused); if (openSubMenu != null && !CloseMenu (false, true)) return; if (openMenu != null) { - if (SuperView == null) { - Application.Current.Remove (openMenu); - } else { - SuperView.Remove (openMenu); - } + Application.Top.Remove (openMenu); openMenu.Dispose (); + openMenu = null; } // This positions the submenu horizontally aligned with the first character of the // menu it belongs to's text for (int i = 0; i < index; i++) pos += Menus [i].TitleLength + (Menus [i].Help.ConsoleWidth > 0 ? Menus [i].Help.ConsoleWidth + 2 : 0) + leftPadding + rightPadding; - openMenu = new Menu (this, Frame.X + pos, Frame.Y + 1, Menus [index]); + var superView = SuperView == null ? Application.Top : SuperView; + Point locationOffset; + if (superView.Border != null && superView.Border.BorderStyle != BorderStyle.None) { + locationOffset = new Point (superView.Frame.X + 1, superView.Frame.Y + 1); + } else { + locationOffset = new Point (superView.Frame.X, superView.Frame.Y); + } + openMenu = new Menu (this, Frame.X + pos + locationOffset.X, Frame.Y + 1 + locationOffset.Y, Menus [index]); openCurrentMenu = openMenu; openCurrentMenu.previousSubFocused = openMenu; - if (SuperView == null) { - Application.Current.Add (openMenu); - } else { - SuperView.Add (openMenu); - } + Application.Top.Add (openMenu); openMenu.SetFocus (); break; default: @@ -1368,17 +1410,14 @@ namespace Terminal.Gui { mbi [j + 2] = subMenu.Children [j]; } var newSubMenu = new MenuBarItem (mbi); - openCurrentMenu = new Menu (this, first.Frame.Left, first.Frame.Top, newSubMenu); + ViewToScreen (first.Frame.Left, first.Frame.Top, out int rx, out int ry); + openCurrentMenu = new Menu (this, rx, ry, newSubMenu); last.Visible = false; Application.GrabMouse (openCurrentMenu); } openCurrentMenu.previousSubFocused = last.previousSubFocused; openSubMenu.Add (openCurrentMenu); - if (SuperView == null) { - Application.Current.Add (openCurrentMenu); - } else { - SuperView.Add (openCurrentMenu); - } + Application.Top.Add (openCurrentMenu); } selectedSub = openSubMenu.Count - 1; if (selectedSub > -1 && SelectEnabledItem (openCurrentMenu.barItems.Children, openCurrentMenu.current, out openCurrentMenu.current)) { @@ -1501,11 +1540,7 @@ namespace Terminal.Gui { switch (isSubMenu) { case false: if (openMenu != null) { - if (SuperView == null) { - Application.Current.Remove (openMenu); - } else { - SuperView?.Remove (openMenu); - } + Application.Top.Remove (openMenu); } SetNeedsDisplay (); if (previousFocused != null && previousFocused is Menu && openMenu != null && previousFocused.ToString () != openCurrentMenu.ToString ()) @@ -1564,11 +1599,7 @@ namespace Terminal.Gui { openCurrentMenu.SetFocus (); if (openSubMenu != null) { menu = openSubMenu [i]; - if (SuperView == null) { - Application.Current.Remove (menu); - } else { - SuperView.Remove (menu); - } + Application.Top.Remove (menu); openSubMenu.Remove (menu); menu.Dispose (); } @@ -1584,11 +1615,7 @@ namespace Terminal.Gui { { if (openSubMenu != null) { foreach (var item in openSubMenu) { - if (SuperView == null) { - Application.Current.Remove (item); - } else { - SuperView.Remove (item); - } + Application.Top.Remove (item); item.Dispose (); } } @@ -1757,7 +1784,8 @@ namespace Terminal.Gui { } if (mi.IsTopLevel) { - var menu = new Menu (this, i, 0, mi); + ViewToScreen (i, 0, out int rx, out int ry); + var menu = new Menu (this, rx, ry, mi); menu.Run (mi.Action); menu.Dispose (); } else { @@ -1878,7 +1906,8 @@ namespace Terminal.Gui { if (cx >= pos && cx < pos + leftPadding + Menus [i].TitleLength + Menus [i].Help.ConsoleWidth + rightPadding) { if (me.Flags == MouseFlags.Button1Clicked) { if (Menus [i].IsTopLevel) { - var menu = new Menu (this, i, 0, Menus [i]); + ViewToScreen (i, 0, out int rx, out int ry); + var menu = new Menu (this, rx, ry, Menus [i]); menu.Run (Menus [i].Action); menu.Dispose (); } else if (!IsMenuOpen) { diff --git a/UnitTests/Menus/ContextMenuTests.cs b/UnitTests/Menus/ContextMenuTests.cs index 875fd40ab..256c776dd 100644 --- a/UnitTests/Menus/ContextMenuTests.cs +++ b/UnitTests/Menus/ContextMenuTests.cs @@ -228,7 +228,7 @@ namespace Terminal.Gui.MenuTests { var oldKey = Key.Null; var cm = new ContextMenu (); - cm.KeyChanged += (s,e) => oldKey = e.OldKey; + cm.KeyChanged += (s, e) => oldKey = e.OldKey; cm.Key = Key.Space | Key.CtrlMask; Assert.Equal (Key.Space | Key.CtrlMask, cm.Key); @@ -241,7 +241,7 @@ namespace Terminal.Gui.MenuTests { var oldMouseFlags = new MouseFlags (); var cm = new ContextMenu (); - cm.MouseFlagsChanged += (s,e) => oldMouseFlags = e.OldValue; + cm.MouseFlagsChanged += (s, e) => oldMouseFlags = e.OldValue; cm.MouseFlags = MouseFlags.Button2Clicked; Assert.Equal (MouseFlags.Button2Clicked, cm.MouseFlags); @@ -902,5 +902,85 @@ namespace Terminal.Gui.MenuTests { Assert.True (top.Subviews [1].ProcessKey (new KeyEvent (Key.F10 | Key.ShiftMask, new KeyModifiers ()))); Assert.Null (tf.ContextMenu.MenuBar); } + + [Fact, AutoInitShutdown] + public void Draw_A_ContextManu_Over_A_Dialog () + { + var top = Application.Top; + var win = new Window (); + top.Add (win); + Application.Begin (top); + ((FakeDriver)Application.Driver).SetBufferSize (20, 15); + + Assert.Equal (new Rect (0, 0, 20, 15), win.Frame); + TestHelpers.AssertDriverContentsWithFrameAre (@" +┌──────────────────┐ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +└──────────────────┘", output); + + var dialog = new Dialog () { X = 2, Y = 2, Width = 15, Height = 4 }; + dialog.Add (new TextField ("Test") { X = Pos.Center (), Width = 10 }); + var rs = Application.Begin (dialog); + + Assert.Equal (new Rect (2, 2, 15, 4), dialog.Frame); + TestHelpers.AssertDriverContentsWithFrameAre (@" +┌──────────────────┐ +│ │ +│ ┌─────────────┐ │ +│ │ Test │ │ +│ │ │ │ +│ └─────────────┘ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +└──────────────────┘", output); + + ReflectionTools.InvokePrivate ( + typeof (Application), + "ProcessMouseEvent", + new MouseEvent () { + X = 9, + Y = 3, + Flags = MouseFlags.Button3Clicked + }); + + var firstIteration = false; + Application.RunMainLoopIteration (ref rs, true, ref firstIteration); + TestHelpers.AssertDriverContentsWithFrameAre (@" +┌──────────────────┐ +│ │ +│ ┌─────────────┐ │ +│ │ Test │ │ +┌─────────────────── +│ Select All Ctrl+ +│ Delete All Ctrl+ +│ Copy Ctrl+ +│ Cut Ctrl+ +│ Paste Ctrl+ +│ Undo Ctrl+ +│ Redo Ctrl+ +└─────────────────── +│ │ +└──────────────────┘", output); + + Application.End (rs); + } } } diff --git a/UnitTests/Menus/MenuTests.cs b/UnitTests/Menus/MenuTests.cs index cf8bd0b99..d1ed18b04 100644 --- a/UnitTests/Menus/MenuTests.cs +++ b/UnitTests/Menus/MenuTests.cs @@ -109,7 +109,7 @@ namespace Terminal.Gui.MenuTests { new MenuItem ("_New", "Creates new file.", New) }) }); - menu.MenuOpening += (s,e) => { + menu.MenuOpening += (s, e) => { Assert.Equal ("_File", e.CurrentMenu.Title); Assert.Equal ("_New", e.CurrentMenu.Children [0].Title); Assert.Equal ("Creates new file.", e.CurrentMenu.Children [0].Help); @@ -130,7 +130,7 @@ namespace Terminal.Gui.MenuTests { mi.Action (); Assert.Equal ("Copy", miAction); }; - menu.MenuClosing += (s,e) => { + menu.MenuClosing += (s, e) => { Assert.False (isMenuClosed); if (cancelClosing) { e.Cancel = true; @@ -196,7 +196,7 @@ Edit new MenuItem ("_Save", "Saves the file.", null, null) }) }); - menu.MenuOpened += (s,e) => { + menu.MenuOpened += (s, e) => { miCurrent = e.MenuItem; mCurrent = menu.openMenu; }; @@ -380,12 +380,12 @@ Edit }), new MenuBarItem ("_About", "Top-Level", () => miAction ="About") }); - menu.MenuOpening += (s,e) => mbiCurrent = e.CurrentMenu; + menu.MenuOpening += (s, e) => mbiCurrent = e.CurrentMenu; menu.MenuOpened += (s, e) => { miCurrent = e.MenuItem; mCurrent = menu.openCurrentMenu; }; - menu.MenuClosing += (s,e) => { + menu.MenuClosing += (s, e) => { mbiCurrent = null; miCurrent = null; mCurrent = null; @@ -1689,7 +1689,7 @@ Edit └──────────────────────────────────────┘", output); Assert.True (win.ProcessHotKey (new KeyEvent (Key.F9, new KeyModifiers ()))); - win.Redraw (win.Bounds); + top.Redraw (top.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" ┌──────────────────────────────────────┐ │ File Edit │ @@ -1701,7 +1701,7 @@ Edit └──────────────────────────────────────┘", output); Assert.True (menu.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); - win.Redraw (win.Bounds); + top.Redraw (top.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" ┌──────────────────────────────────────┐ │ File Edit │ @@ -1713,7 +1713,7 @@ Edit └──────────────────────────────────────┘", output); Assert.True (menu.openMenu.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); - win.Redraw (win.Bounds); + top.Redraw (top.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" ┌──────────────────────────────────────┐ │ File Edit │ @@ -1725,7 +1725,7 @@ Edit └──────────────────────────────────────┘", output); Assert.True (menu.openMenu.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ()))); - win.Redraw (win.Bounds); + top.Redraw (top.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" ┌──────────────────────────────────────┐ │ File Edit │ diff --git a/UnitTests/TopLevels/ToplevelTests.cs b/UnitTests/TopLevels/ToplevelTests.cs index 55fc97847..336bdc88d 100644 --- a/UnitTests/TopLevels/ToplevelTests.cs +++ b/UnitTests/TopLevels/ToplevelTests.cs @@ -1379,5 +1379,130 @@ namespace Terminal.Gui.TopLevelTests { Application.End (rs); } + + [Fact, AutoInitShutdown] + public void Draw_A_Top_Subview_On_A_Dialog () + { + var top = Application.Top; + var win = new Window (); + top.Add (win); + Application.Begin (top); + ((FakeDriver)Application.Driver).SetBufferSize (20, 20); + + Assert.Equal (new Rect (0, 0, 20, 20), win.Frame); + TestHelpers.AssertDriverContentsWithFrameAre (@" +┌──────────────────┐ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +└──────────────────┘", output); + + var btnPopup = new Button ("Popup"); + btnPopup.Clicked += (s, e) => { + var viewToScreen = btnPopup.ViewToScreen (top.Frame); + var view = new View () { + X = 1, + Y = viewToScreen.Y + 1, + Width = 18, + Height = 5, + Border = new Border () { BorderStyle = BorderStyle.Single } + }; + Application.Current.DrawContentComplete += Current_DrawContentComplete; + top.Add (view); + + void Current_DrawContentComplete (object sender, DrawEventArgs e) + { + Assert.Equal (new Rect (1, 14, 18, 5), view.Frame); + + var savedClip = Application.Driver.Clip; + Application.Driver.Clip = top.Frame; + view.Redraw (view.Bounds); + top.Move (2, 15); + View.Driver.AddStr ("One"); + top.Move (2, 16); + View.Driver.AddStr ("Two"); + top.Move (2, 17); + View.Driver.AddStr ("Three"); + Application.Driver.Clip = savedClip; + + Application.Current.DrawContentComplete -= Current_DrawContentComplete; + } + }; + var dialog = new Dialog ("", 15, 10, btnPopup); + var rs = Application.Begin (dialog); + + Assert.Equal (new Rect (2, 5, 15, 10), dialog.Frame); + TestHelpers.AssertDriverContentsWithFrameAre (@" +┌──────────────────┐ +│ │ +│ │ +│ │ +│ │ +│ ┌─────────────┐ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ [ Popup ] │ │ +│ └─────────────┘ │ +│ │ +│ │ +│ │ +│ │ +└──────────────────┘", output); + + ReflectionTools.InvokePrivate ( + typeof (Application), + "ProcessMouseEvent", + new MouseEvent () { + X = 9, + Y = 13, + Flags = MouseFlags.Button1Clicked + }); + + var firstIteration = false; + Application.RunMainLoopIteration (ref rs, true, ref firstIteration); + TestHelpers.AssertDriverContentsWithFrameAre (@" +┌──────────────────┐ +│ │ +│ │ +│ │ +│ │ +│ ┌─────────────┐ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ [ Popup ] │ │ +│┌────────────────┐│ +││One ││ +││Two ││ +││Three ││ +│└────────────────┘│ +└──────────────────┘", output); + + Application.End (rs); + } } } \ No newline at end of file