Browse Source

Support for remapping basic unicode keychars that come from OS with ConsoleKey.Packet. Affects only WindowsDriver

Thomas 2 years ago
parent
commit
9897bb903e
2 changed files with 61 additions and 0 deletions
  1. 37 0
      Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
  2. 24 0
      UnitTests/ConsoleDriverTests.cs

+ 37 - 0
Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

@@ -1244,6 +1244,9 @@ namespace Terminal.Gui {
 				keyModifiers.Scrolllock = scrolllock;
 
 			var ConsoleKeyInfo = new ConsoleKeyInfo (keyEvent.UnicodeChar, (ConsoleKey)keyEvent.wVirtualKeyCode, shift, alt, control);
+
+			ConsoleKeyInfo = RemapPacketKey(ConsoleKeyInfo);
+
 			return new WindowsConsole.ConsoleKeyInfoEx (ConsoleKeyInfo, capslock, numlock);
 		}
 
@@ -1757,6 +1760,40 @@ namespace Terminal.Gui {
 		public override void CookMouse ()
 		{
 		}
+
+
+		/// <summary>
+		/// Handles case when the 'key' providied is ConsoleKey.Packet by
+		/// returning a new <see cref="ConsoleKeyInfo"/> where key is remapped
+		/// by parsing the Unicode char data of the <see cref="ConsoleKeyInfo"/>
+		/// </summary>
+		internal static ConsoleKeyInfo RemapPacketKey (ConsoleKeyInfo original)
+		{
+			// If the key struck was virtual
+			if(original.Key == ConsoleKey.Packet)
+			{
+				// Try to parse the unicode key e.g. 'A' into a value in ConsoleKey
+				// so that other parts of the program consider it as a regular button
+				// press
+				ConsoleKey remappedkey;
+				if(Enum.TryParse<ConsoleKey>(
+					// have to turn e.g. 'a' to something parseable as
+					// an enum value (i.e. Upper it)
+					original.KeyChar.ToString().ToUpper(), 
+					out remappedkey))
+				{
+					return new ConsoleKeyInfo(
+						original.KeyChar,
+						remappedkey,
+						original.Modifiers.HasFlag(ConsoleModifiers.Shift),
+						original.Modifiers.HasFlag(ConsoleModifiers.Alt),
+						original.Modifiers.HasFlag(ConsoleModifiers.Control)
+					);
+				}
+			}
+
+			return original;
+		}
 		#endregion
 	}
 

+ 24 - 0
UnitTests/ConsoleDriverTests.cs

@@ -608,5 +608,29 @@ namespace Terminal.Gui.ConsoleDrivers {
 			Application.Run (win);
 			Application.Shutdown ();
 		}
+
+		/// <summary>
+		/// Sometimes when using remoting tools EventKeyRecord sends 'virtual keystrokes'.
+		/// These are indicated with the wVirtualKeyCode of 231.  When we see this code
+		/// then we need to look to the unicode character (UnicodeChar) instead of the key
+		/// when telling the rest of the framework what button was pressed. For full details
+		/// see: https://github.com/gui-cs/Terminal.Gui/issues/2008
+		/// </summary>
+		[Theory]
+		[InlineData('A',true,false,false,ConsoleKey.A)]
+		[InlineData('z',false,false,false,ConsoleKey.Z)]
+		public void TestVKPacket(char unicodeCharacter,bool shift, bool alt, bool control, ConsoleKey expectedRemapping)
+		{
+			var before = new ConsoleKeyInfo(unicodeCharacter,ConsoleKey.Packet,shift,alt,control);
+			var after = WindowsDriver.RemapPacketKey(before);
+
+			Assert.Equal(before.KeyChar, after.KeyChar);
+
+			// The thing we are really interested in, did we correctly convert
+			// the input ConsoleKey.Packet to the correct physical key
+			Assert.Equal(expectedRemapping,after.Key);
+
+			Assert.Equal(after.Modifiers,before.Modifiers);
+		}
 	}
 }