浏览代码

Improved View Key event handling

+ Added Handled property of type bool to the KeyEventEventArgs class.
+ Added ability to stop further propagation for already handled events on Views for Keyboard related event subscribers (like KeyDown, KeyUp and KeyPress). The driver will check the Handled property of the KeyEventEventArgs passed to the subscribers and will stop any further invocations when its found true.
+ Updated Example project to expose the ability to programatically Open/Close a MenuBar from custom keystrokes.

This commit fixes an issue where the library would crash if the Subviews collection of the currently active View gets updated from inside any of the Keyboard event handlers, such as when the view is updated as a result of a custom Hotkey/Coldkey press.
Fabian R 5 年之前
父节点
当前提交
46b4c9025b
共有 2 个文件被更改,包括 40 次插入6 次删除
  1. 14 1
      Example/demo.cs
  2. 26 5
      Terminal.Gui/Core.cs

+ 14 - 1
Example/demo.cs

@@ -190,7 +190,7 @@ static class Demo {
 			new DateField (3, 22, DateTime.Now),
 			new DateField (23, 22, DateTime.Now, true),
 			progress,
-			new Label (3, 24, "Press F9 (on Unix, ESC+9 is an alias) to activate the menubar"),
+			new Label (3, 24, "Press F9 (on Unix, ESC+9 is an alias) or Ctrl+T to activate the menubar"),
 			menuKeysStyle,
 			menuAutoMouseNav
 
@@ -636,10 +636,23 @@ static class Demo {
 		};
 #endif
 
+		win.KeyPress += Win_KeyPress;
+
 
 		top.Add (win);
 		//top.Add (menu);
 		top.Add (menu, statusBar);
 		Application.Run ();
 	}
+
+	private static void Win_KeyPress (object sender, View.KeyEventEventArgs e)
+	{
+		if (e.KeyEvent.Key == Key.ControlT) {
+			if (menu.IsMenuOpen)
+				menu.CloseMenu ();
+			else
+				menu.OpenMenu ();
+			e.Handled = true;
+		}
+	}
 }

+ 26 - 5
Terminal.Gui/Core.cs

@@ -1087,6 +1087,11 @@ namespace Terminal.Gui {
 			/// The <see cref="KeyEvent"/> for the event.
 			/// </summary>
 			public KeyEvent KeyEvent { get; set; }
+			/// <summary>
+			/// Indicates if the current Key event has already been processed and the driver should stop notifying any other event subscriber.
+			/// Its important to set this value to true specially when updating any View's layout from inside the subscriber method.
+			/// </summary>
+			public bool Handled { get; set; } = false;
 		}
 
 		/// <summary>
@@ -1097,7 +1102,11 @@ namespace Terminal.Gui {
 		/// <inheritdoc cref="ProcessKey"/>
 		public override bool ProcessKey (KeyEvent keyEvent)
 		{
-			KeyPress?.Invoke (this, new KeyEventEventArgs(keyEvent));
+
+			KeyEventEventArgs args = new KeyEventEventArgs (keyEvent);
+			KeyPress?.Invoke (this, args);
+			if (args.Handled)
+				return true;
 			if (Focused?.ProcessKey (keyEvent) == true)
 				return true;
 
@@ -1107,7 +1116,10 @@ namespace Terminal.Gui {
 		/// <inheritdoc cref="ProcessHotKey"/>
 		public override bool ProcessHotKey (KeyEvent keyEvent)
 		{
-			KeyPress?.Invoke (this, new KeyEventEventArgs (keyEvent));
+			KeyEventEventArgs args = new KeyEventEventArgs (keyEvent);
+			KeyPress?.Invoke (this, args);
+			if (args.Handled)
+				return true;
 			if (subviews == null || subviews.Count == 0)
 				return false;
 			foreach (var view in subviews)
@@ -1119,7 +1131,10 @@ namespace Terminal.Gui {
 		/// <inheritdoc cref="ProcessColdKey"/>
 		public override bool ProcessColdKey (KeyEvent keyEvent)
 		{
-			KeyPress?.Invoke (this, new KeyEventEventArgs(keyEvent));
+			KeyEventEventArgs args = new KeyEventEventArgs (keyEvent);
+			KeyPress?.Invoke (this, args);
+			if (args.Handled)
+				return true;
 			if (subviews == null || subviews.Count == 0)
 				return false;
 			foreach (var view in subviews)
@@ -1136,7 +1151,10 @@ namespace Terminal.Gui {
 		/// <param name="keyEvent">Contains the details about the key that produced the event.</param>
 		public override bool OnKeyDown (KeyEvent keyEvent)
 		{
-			KeyDown?.Invoke (this, new KeyEventEventArgs (keyEvent));
+			KeyEventEventArgs args = new KeyEventEventArgs (keyEvent);
+			KeyDown?.Invoke (this, args);
+			if (args.Handled)
+				return true;
 			if (subviews == null || subviews.Count == 0)
 				return false;
 			foreach (var view in subviews)
@@ -1154,7 +1172,10 @@ namespace Terminal.Gui {
 		/// <param name="keyEvent">Contains the details about the key that produced the event.</param>
 		public override bool OnKeyUp (KeyEvent keyEvent)
 		{
-			KeyUp?.Invoke (this, new KeyEventEventArgs (keyEvent));
+			KeyEventEventArgs args = new KeyEventEventArgs (keyEvent);
+			KeyUp?.Invoke (this, args);
+			if (args.Handled)
+				return true;
 			if (subviews == null || subviews.Count == 0)
 				return false;
 			foreach (var view in subviews)