Browse Source

The KeyPress event must only be used by the most focused view in the ProcessHotKey event. (#1614)

BDisp 3 năm trước cách đây
mục cha
commit
a9a0d176c1
3 tập tin đã thay đổi với 110 bổ sung14 xóa
  1. 6 9
      Terminal.Gui/Core/View.cs
  2. 3 5
      UnitTests/ConsoleDriverTests.cs
  3. 101 0
      UnitTests/ViewTests.cs

+ 6 - 9
Terminal.Gui/Core/View.cs

@@ -1730,15 +1730,12 @@ namespace Terminal.Gui {
 			}
 
 			KeyEventEventArgs args = new KeyEventEventArgs (keyEvent);
-			KeyPress?.Invoke (args);
-			if (args.Handled)
-				return true;
-			if (Focused?.Enabled == true) {
-				Focused?.KeyPress?.Invoke (args);
+			if (MostFocused?.Enabled == true) {
+				MostFocused?.KeyPress?.Invoke (args);
 				if (args.Handled)
 					return true;
 			}
-			if (Focused?.Enabled == true && Focused?.ProcessKey (keyEvent) == true)
+			if (MostFocused?.Enabled == true && MostFocused?.ProcessKey (keyEvent) == true)
 				return true;
 			if (subviews == null || subviews.Count == 0)
 				return false;
@@ -1759,12 +1756,12 @@ namespace Terminal.Gui {
 			KeyPress?.Invoke (args);
 			if (args.Handled)
 				return true;
-			if (Focused?.Enabled == true) {
-				Focused?.KeyPress?.Invoke (args);
+			if (MostFocused?.Enabled == true) {
+				MostFocused?.KeyPress?.Invoke (args);
 				if (args.Handled)
 					return true;
 			}
-			if (Focused?.Enabled == true && Focused?.ProcessKey (keyEvent) == true)
+			if (MostFocused?.Enabled == true && MostFocused?.ProcessKey (keyEvent) == true)
 				return true;
 			if (subviews == null || subviews.Count == 0)
 				return false;

+ 3 - 5
UnitTests/ConsoleDriverTests.cs

@@ -430,7 +430,7 @@ namespace Terminal.Gui.ConsoleDrivers {
 			var okClicked = false;
 			var closing = false;
 			var cursorRight = false;
-			var cancelHasFocus = false;
+			var endingKeyPress = false;
 			var closed = false;
 
 			var top = Application.Top;
@@ -464,9 +464,7 @@ namespace Terminal.Gui.ConsoleDrivers {
 					if (!cursorRight) {
 						cursorRight = true;
 					} else if (ok.HasFocus) {
-						e.Handled = true;
-					} else {
-						cancelHasFocus = true;
+						e.Handled = endingKeyPress = true;
 					}
 				}
 			};
@@ -497,7 +495,7 @@ namespace Terminal.Gui.ConsoleDrivers {
 			Assert.True (okClicked);
 			Assert.True (closing);
 			Assert.True (cursorRight);
-			Assert.True (cancelHasFocus);
+			Assert.True (endingKeyPress);
 			Assert.True (closed);
 			Assert.Empty (FakeConsole.MockKeyPresses);
 		}

+ 101 - 0
UnitTests/ViewTests.cs

@@ -1727,5 +1727,106 @@ namespace Terminal.Gui.Views {
 			Assert.Equal (win2, Application.Current.Focused);
 			Assert.Equal (view2, Application.Current.MostFocused);
 		}
+
+		[Fact]
+		[AutoInitShutdown]
+		public void ProcessHotKey_Will_Invoke_ProcessKey_Only_For_The_MostFocused_With_Top_KeyPress_Event ()
+		{
+			var sbQuiting = false;
+			var tfQuiting = false;
+			var topQuiting = false;
+			var sb = new StatusBar (new StatusItem [] {
+				new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => sbQuiting = true )
+			});
+			var tf = new TextField ();
+			tf.KeyPress += Tf_KeyPress;
+
+			void Tf_KeyPress (View.KeyEventEventArgs obj)
+			{
+				if (obj.KeyEvent.Key == (Key.Q | Key.CtrlMask)) {
+					obj.Handled = tfQuiting = true;
+				}
+			}
+
+			var win = new Window ();
+			win.Add (sb, tf);
+			var top = Application.Top;
+			top.KeyPress += Top_KeyPress;
+
+			void Top_KeyPress (View.KeyEventEventArgs obj)
+			{
+				if (obj.KeyEvent.Key == (Key.Q | Key.CtrlMask)) {
+					obj.Handled = topQuiting = true;
+				}
+			}
+
+			top.Add (win);
+			Application.Begin (top);
+
+			Assert.False (sbQuiting);
+			Assert.False (tfQuiting);
+			Assert.False (topQuiting);
+
+			Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true);
+			Assert.False (sbQuiting);
+			Assert.True (tfQuiting);
+			Assert.False (topQuiting);
+
+			tf.KeyPress -= Tf_KeyPress;
+			tfQuiting = false;
+			Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true);
+			Application.MainLoop.MainIteration ();
+			Assert.True (sbQuiting);
+			Assert.False (tfQuiting);
+			Assert.False (topQuiting);
+
+			sb.RemoveItem (0);
+			sbQuiting = false;
+			Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true);
+			Application.MainLoop.MainIteration ();
+			Assert.False (sbQuiting);
+			Assert.False (tfQuiting);
+			Assert.True (topQuiting);
+		}
+
+		[Fact]
+		[AutoInitShutdown]
+		public void ProcessHotKey_Will_Invoke_ProcessKey_Only_For_The_MostFocused_Without_Top_KeyPress_Event ()
+		{
+			var sbQuiting = false;
+			var tfQuiting = false;
+			var sb = new StatusBar (new StatusItem [] {
+				new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => sbQuiting = true )
+			});
+			var tf = new TextField ();
+			tf.KeyPress += Tf_KeyPress;
+
+			void Tf_KeyPress (View.KeyEventEventArgs obj)
+			{
+				if (obj.KeyEvent.Key == (Key.Q | Key.CtrlMask)) {
+					obj.Handled = tfQuiting = true;
+				}
+			}
+
+			var win = new Window ();
+			win.Add (sb, tf);
+			var top = Application.Top;
+			top.Add (win);
+			Application.Begin (top);
+
+			Assert.False (sbQuiting);
+			Assert.False (tfQuiting);
+
+			Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true);
+			Assert.False (sbQuiting);
+			Assert.True (tfQuiting);
+
+			tf.KeyPress -= Tf_KeyPress;
+			tfQuiting = false;
+			Application.Driver.SendKeys ('q', ConsoleKey.Q, false, false, true);
+			Application.MainLoop.MainIteration ();
+			Assert.True (sbQuiting);
+			Assert.False (tfQuiting);
+		}
 	}
 }