From d5800743eab7ce85b7bad03f8a9ca8c5af1c9f24 Mon Sep 17 00:00:00 2001 From: BDisp Date: Wed, 10 Apr 2024 17:33:47 +0100 Subject: [PATCH 1/4] Fixes #3394. View.Dispose doen't call UngrabMouse if MouseGrabView is the view itself. --- Terminal.Gui/View/View.cs | 5 +++++ UnitTests/Application/MouseTests.cs | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/Terminal.Gui/View/View.cs b/Terminal.Gui/View/View.cs index 07235e638..ee5b63f5f 100644 --- a/Terminal.Gui/View/View.cs +++ b/Terminal.Gui/View/View.cs @@ -521,6 +521,11 @@ public partial class View : Responder, ISupportInitializeNotification DisposeAdornments (); + if (Application.MouseGrabView is { } && Application.MouseGrabView == this) + { + Application.UngrabMouse (); + } + for (int i = InternalSubviews.Count - 1; i >= 0; i--) { View subview = InternalSubviews [i]; diff --git a/UnitTests/Application/MouseTests.cs b/UnitTests/Application/MouseTests.cs index 559cfbb9e..8fa320096 100644 --- a/UnitTests/Application/MouseTests.cs +++ b/UnitTests/Application/MouseTests.cs @@ -371,5 +371,29 @@ public class MouseTests } } + [Fact] + [AutoInitShutdown] + public void MouseGrabView_Is_Set_To_Null_If_A_View_Was_Disposed () + { + var count = 0; + var view = new View { Width = 1, Height = 1 }; + view.MouseEvent += (s, e) => count++; + var top = new Toplevel (); + top.Add (view); + Application.Begin (top); + + Assert.Null (Application.MouseGrabView); + Application.GrabMouse (view); + Assert.Equal (view, Application.MouseGrabView); + top.Remove (view); + view.Dispose (); +#if DEBUG_IDISPOSABLE + Assert.True (view.WasDisposed); +#endif + + Application.OnMouseEvent (new () { X = 0, Y = 0, Flags = MouseFlags.Button1Pressed }); + Assert.Null (Application.MouseGrabView); + Assert.Equal (0, count); + } #endregion } From c42c88ccbc99995ea675e6851b16cb6c5d282944 Mon Sep 17 00:00:00 2001 From: BDisp Date: Wed, 10 Apr 2024 18:16:51 +0100 Subject: [PATCH 2/4] Ensures the menu bar grabs the mouse when removing a menu. --- Terminal.Gui/Views/Menu/MenuBar.cs | 6 ++++++ UnitTests/Views/MenuBarTests.cs | 24 ++++-------------------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/Terminal.Gui/Views/Menu/MenuBar.cs b/Terminal.Gui/Views/Menu/MenuBar.cs index 07ff6912c..19f9f241a 100644 --- a/Terminal.Gui/Views/Menu/MenuBar.cs +++ b/Terminal.Gui/Views/Menu/MenuBar.cs @@ -1386,6 +1386,12 @@ public class MenuBar : View menu = _openSubMenu [i]; Application.Current.Remove (menu); _openSubMenu.Remove (menu); + + if (Application.MouseGrabView == menu) + { + Application.GrabMouse (this); + } + menu.Dispose (); } diff --git a/UnitTests/Views/MenuBarTests.cs b/UnitTests/Views/MenuBarTests.cs index 99b9dc42e..9a53bfaee 100644 --- a/UnitTests/Views/MenuBarTests.cs +++ b/UnitTests/Views/MenuBarTests.cs @@ -3262,11 +3262,7 @@ Edit Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); Assert.Equal (new Rectangle (1, 0, 8, 1), pos); - Assert.True ( - menu.NewMouseEvent ( - new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu } - ) - ); + Assert.True (menu.NewMouseEvent (new () { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); top.Draw (); expected = @" @@ -3281,11 +3277,7 @@ Edit pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); Assert.Equal (new Rectangle (1, 0, 10, 6), pos); - Assert.False ( - menu.NewMouseEvent ( - new MouseEvent { X = 1, Y = 2, Flags = MouseFlags.Button1Clicked, View = Application.Top.Subviews [1] } - ) - ); + Assert.False (menu.NewMouseEvent (new () { X = 1, Y = 2, Flags = MouseFlags.Button1Clicked, View = Application.Top.Subviews [1] })); top.Draw (); expected = @" @@ -3301,11 +3293,7 @@ Edit pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); Assert.Equal (new Rectangle (1, 0, 15, 7), pos); - Assert.False ( - menu.NewMouseEvent ( - new MouseEvent { X = 1, Y = 1, Flags = MouseFlags.Button1Clicked, View = Application.Top.Subviews [2] } - ) - ); + Assert.False (menu.NewMouseEvent (new () { X = 1, Y = 1, Flags = MouseFlags.Button1Clicked, View = Application.Top.Subviews [2] })); top.Draw (); expected = @" @@ -3320,11 +3308,7 @@ Edit pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); Assert.Equal (new Rectangle (1, 0, 10, 6), pos); - Assert.False ( - menu.NewMouseEvent ( - new MouseEvent { X = 70, Y = 2, Flags = MouseFlags.Button1Clicked, View = Application.Top } - ) - ); + Assert.False (menu.NewMouseEvent (new () { X = 70, Y = 2, Flags = MouseFlags.Button1Clicked, View = Application.Top })); top.Draw (); expected = @" From bf166a73b87a2da79778af9895c24d526bae7aca Mon Sep 17 00:00:00 2001 From: BDisp Date: Sun, 14 Apr 2024 23:42:07 +0100 Subject: [PATCH 3/4] Revert changes. --- Terminal.Gui/View/View.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Terminal.Gui/View/View.cs b/Terminal.Gui/View/View.cs index ee5b63f5f..07235e638 100644 --- a/Terminal.Gui/View/View.cs +++ b/Terminal.Gui/View/View.cs @@ -521,11 +521,6 @@ public partial class View : Responder, ISupportInitializeNotification DisposeAdornments (); - if (Application.MouseGrabView is { } && Application.MouseGrabView == this) - { - Application.UngrabMouse (); - } - for (int i = InternalSubviews.Count - 1; i >= 0; i--) { View subview = InternalSubviews [i]; From 7236dd19c73c0a7101044d38c1bf38188932b5fc Mon Sep 17 00:00:00 2001 From: BDisp Date: Sun, 14 Apr 2024 23:55:18 +0100 Subject: [PATCH 4/4] Fix unit test. --- UnitTests/Application/MouseTests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/UnitTests/Application/MouseTests.cs b/UnitTests/Application/MouseTests.cs index 8fa320096..941e6be20 100644 --- a/UnitTests/Application/MouseTests.cs +++ b/UnitTests/Application/MouseTests.cs @@ -373,7 +373,7 @@ public class MouseTests [Fact] [AutoInitShutdown] - public void MouseGrabView_Is_Set_To_Null_If_A_View_Was_Disposed () + public void View_Is_Responsible_For_Calling_UnGrabMouse_Before_Being_Disposed () { var count = 0; var view = new View { Width = 1, Height = 1 }; @@ -386,6 +386,7 @@ public class MouseTests Application.GrabMouse (view); Assert.Equal (view, Application.MouseGrabView); top.Remove (view); + Application.UngrabMouse (); view.Dispose (); #if DEBUG_IDISPOSABLE Assert.True (view.WasDisposed);