From 057bbcaea85269db8b277a8348fbe19dfbacc60b Mon Sep 17 00:00:00 2001 From: BDisp Date: Mon, 6 Feb 2023 23:47:09 +0000 Subject: [PATCH] Fixes #2326. Invisible cursor after modal dialog. --- Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 4 ++ Terminal.Gui/Core/Application.cs | 3 ++ Terminal.Gui/Core/Toplevel.cs | 12 +++++ Terminal.Gui/Views/TextView.cs | 20 ++++----- UnitTests/TopLevels/ToplevelTests.cs | 47 +++++++++++++++++--- 5 files changed, 71 insertions(+), 15 deletions(-) diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index 8d1b71646..0d7722090 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -116,6 +116,10 @@ namespace Terminal.Gui { public bool GetCursorVisibility (out CursorVisibility visibility) { + if (ScreenBuffer == IntPtr.Zero) { + visibility = CursorVisibility.Invisible; + return false; + } if (!GetConsoleCursorInfo (ScreenBuffer, out ConsoleCursorInfo info)) { var err = Marshal.GetLastWin32Error (); if (err != 0) { diff --git a/Terminal.Gui/Core/Application.cs b/Terminal.Gui/Core/Application.cs index b5f6e5984..27c51eee5 100644 --- a/Terminal.Gui/Core/Application.cs +++ b/Terminal.Gui/Core/Application.cs @@ -933,6 +933,8 @@ namespace Terminal.Gui { if (Top != null && toplevel != Top && !toplevels.Contains (Top)) { Top.Dispose (); Top = null; + } else if (Top != null && toplevel != Top && toplevels.Contains (Top)) { + Top.OnLeave (toplevel); } if (string.IsNullOrEmpty (toplevel.Id.ToString ())) { var count = 1; @@ -1043,6 +1045,7 @@ namespace Terminal.Gui { MdiTop.OnAllChildClosed (); } else { SetCurrentAsTop (); + Current.OnEnter (Current); } Refresh (); } diff --git a/Terminal.Gui/Core/Toplevel.cs b/Terminal.Gui/Core/Toplevel.cs index fddabb692..1df0278bb 100644 --- a/Terminal.Gui/Core/Toplevel.cs +++ b/Terminal.Gui/Core/Toplevel.cs @@ -960,6 +960,18 @@ namespace Terminal.Gui { } return false; } + + /// + public override bool OnEnter (View view) + { + return MostFocused?.OnEnter (view) ?? base.OnEnter (view); + } + + /// + public override bool OnLeave (View view) + { + return MostFocused?.OnLeave (view) ?? base.OnLeave (view); + } } /// diff --git a/Terminal.Gui/Views/TextView.cs b/Terminal.Gui/Views/TextView.cs index 3c9e54b09..dd609f12c 100644 --- a/Terminal.Gui/Views/TextView.cs +++ b/Terminal.Gui/Views/TextView.cs @@ -2035,6 +2035,16 @@ namespace Terminal.Gui { return base.OnEnter (view); } + /// + public override bool OnLeave (View view) + { + if (Application.MouseGrabView != null && Application.MouseGrabView == this) { + Application.UngrabMouse (); + } + + return base.OnLeave (view); + } + // Returns an encoded region start..end (top 32 bits are the row, low32 the column) void GetEncodedRegionBounds (out long start, out long end, int? startRow = null, int? startCol = null, int? cRow = null, int? cCol = null) @@ -4447,16 +4457,6 @@ namespace Terminal.Gui { line = r; } - /// - public override bool OnLeave (View view) - { - if (Application.MouseGrabView != null && Application.MouseGrabView == this) { - Application.UngrabMouse (); - } - - return base.OnLeave (view); - } - /// /// Allows clearing the items updating the original text. /// diff --git a/UnitTests/TopLevels/ToplevelTests.cs b/UnitTests/TopLevels/ToplevelTests.cs index 7cd2b1d06..88f9181dd 100644 --- a/UnitTests/TopLevels/ToplevelTests.cs +++ b/UnitTests/TopLevels/ToplevelTests.cs @@ -696,7 +696,7 @@ namespace Terminal.Gui.TopLevelTests { ((FakeDriver)Application.Driver).SetBufferSize (40, 15); MessageBox.Query ("About", "Hello Word", "Ok"); - } else if (iterations == 1) TestHelpers.AssertDriverContentsWithFrameAre (@" + } else if (iterations == 1) TestHelpers.AssertDriverContentsWithFrameAre (@" File ┌ Window ──────────────────────────────┐ │ │ @@ -712,7 +712,7 @@ namespace Terminal.Gui.TopLevelTests { │ │ └──────────────────────────────────────┘ CTRL-N New ", output); -else if (iterations == 2) { + else if (iterations == 2) { Assert.Null (Application.MouseGrabView); // Grab the mouse ReflectionTools.InvokePrivate ( @@ -815,8 +815,8 @@ else if (iterations == 2) { Assert.Null (Application.MouseGrabView); - } else if (iterations == 8) Application.RequestStop (); -else if (iterations == 9) Application.RequestStop (); + } else if (iterations == 8) Application.RequestStop (); + else if (iterations == 9) Application.RequestStop (); }; Application.Run (); @@ -956,7 +956,7 @@ else if (iterations == 9) Application.RequestStop (); Assert.Null (Application.MouseGrabView); - } else if (iterations == 8) Application.RequestStop (); + } else if (iterations == 8) Application.RequestStop (); }; Application.Run (); @@ -974,5 +974,42 @@ else if (iterations == 9) Application.RequestStop (); exception = Record.Exception (() => ((FakeDriver)Application.Driver).SetBufferSize (10, 0)); Assert.Null (exception); } + + [Fact, AutoInitShutdown] + public void OnEnter_OnLeave_Triggered_On_Application_Begin_End () + { + var isEnter = false; + var isLeave = false; + var v = new View (); + v.Enter += (_) => isEnter = true; + v.Leave += (_) => isLeave = true; + var top = Application.Top; + top.Add (v); + + Assert.False (v.CanFocus); + var exception = Record.Exception (() => top.OnEnter (top)); + Assert.Null (exception); + exception = Record.Exception (() => top.OnLeave (top)); + Assert.Null (exception); + + v.CanFocus = true; + Application.Begin (top); + + Assert.True (isEnter); + Assert.False (isLeave); + + isEnter = false; + var d = new Dialog (); + var rs = Application.Begin (d); + + Assert.False (isEnter); + Assert.True (isLeave); + + isLeave = false; + Application.End (rs); + + Assert.True (isEnter); + Assert.False (isLeave); + } } } \ No newline at end of file