diff --git a/Terminal.Gui/ConsoleDrivers/ConsoleKeyMapping.cs b/Terminal.Gui/ConsoleDrivers/ConsoleKeyMapping.cs
index bab26eb32f..3c9d00da27 100644
--- a/Terminal.Gui/ConsoleDrivers/ConsoleKeyMapping.cs
+++ b/Terminal.Gui/ConsoleDrivers/ConsoleKeyMapping.cs
@@ -2,8 +2,6 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using static Terminal.Gui.WindowsConsole;
-using System.Text;
namespace Terminal.Gui.ConsoleDrivers {
///
@@ -33,7 +31,7 @@ public bool Equals (ScanCodeMapping other)
}
}
- static ConsoleModifiers GetModifiers (uint unicodeChar, ConsoleModifiers modifiers, bool isConsoleKey)
+ static ConsoleModifiers GetModifiers (ConsoleModifiers modifiers)
{
if (modifiers.HasFlag (ConsoleModifiers.Shift)
&& !modifiers.HasFlag (ConsoleModifiers.Alt)
@@ -41,14 +39,8 @@ static ConsoleModifiers GetModifiers (uint unicodeChar, ConsoleModifiers modifie
return ConsoleModifiers.Shift;
} else if (modifiers == (ConsoleModifiers.Alt | ConsoleModifiers.Control)) {
return modifiers;
- } else if ((!isConsoleKey || modifiers.HasFlag (ConsoleModifiers.Shift)
- || modifiers.HasFlag (ConsoleModifiers.Alt)
- || modifiers.HasFlag (ConsoleModifiers.Control))
- && unicodeChar >= (uint)ConsoleKey.A && unicodeChar <= (uint)ConsoleKey.Z) {
- // BUGBUG: I think this is the bug. We should not be adding shift to ConsoleKey.A as it should
- // result in unicodeChar of 97 ('a')
- return ConsoleModifiers.Shift;
}
+
return 0;
}
@@ -77,7 +69,7 @@ static ScanCodeMapping GetScanCode (string propName, uint keyValue, ConsoleModif
///
///
///
- public static ConsoleKey GetConsoleKeyFromKey (KeyCode key)
+ public static ConsoleKeyInfo GetConsoleKeyFromKey (KeyCode key)
{
var mod = new ConsoleModifiers ();
if (key.HasFlag (KeyCode.ShiftMask)) {
@@ -89,28 +81,28 @@ public static ConsoleKey GetConsoleKeyFromKey (KeyCode key)
if (key.HasFlag (KeyCode.CtrlMask)) {
mod |= ConsoleModifiers.Control;
}
- return (ConsoleKey)GetConsoleKeyFromKey ((uint)(key & ~KeyCode.CtrlMask & ~KeyCode.ShiftMask & ~KeyCode.AltMask), mod, out _, out _);
+ return GetConsoleKeyFromKey ((uint)(key & ~KeyCode.CtrlMask & ~KeyCode.ShiftMask & ~KeyCode.AltMask), mod, out _);
}
///
- /// Get the from a unicode character and modifiers (e.g. (Key)'a' and (Key)Key.CtrlMask).
+ /// Get the from a unicode character and modifiers (e.g. (Key)'a' and (Key)Key.CtrlMask).
///
/// The key as a unicode codepoint.
/// The modifier keys.
/// The resulting scan code.
- /// The resulting output character.
- /// The or the .
- public static uint GetConsoleKeyFromKey (uint keyValue, ConsoleModifiers modifiers, out uint scanCode, out uint outputChar)
+ /// The .
+ public static ConsoleKeyInfo GetConsoleKeyFromKey (uint keyValue, ConsoleModifiers modifiers, out uint scanCode)
{
scanCode = 0;
- outputChar = keyValue;
+ uint outputChar = keyValue;
if (keyValue == 0) {
- return 0;
+ return new ConsoleKeyInfo ((char)keyValue, ConsoleKey.None, modifiers.HasFlag (ConsoleModifiers.Shift),
+ modifiers.HasFlag (ConsoleModifiers.Alt), modifiers.HasFlag (ConsoleModifiers.Control));
}
- uint consoleKey = MapKeyToConsoleKey ((KeyCode)keyValue, out bool mappable);
+ uint consoleKey = (uint)MapKeyToConsoleKey ((KeyCode)keyValue, modifiers, out bool mappable);
if (mappable) {
- var mod = GetModifiers (keyValue, modifiers, false);
+ var mod = GetModifiers (modifiers);
var scode = GetScanCode ("UnicodeChar", keyValue, mod);
if (scode != null) {
consoleKey = scode.VirtualKey;
@@ -118,11 +110,13 @@ public static uint GetConsoleKeyFromKey (uint keyValue, ConsoleModifiers modifie
outputChar = scode.UnicodeChar;
} else {
// If the consoleKey is < 255, retain the lower 8 bits of the key value and set the upper bits to 0xff.
- // But why????
+ // This is a shifted value that will be used by the GetKeyCharFromConsoleKey to do the correct action
+ // because keyValue maybe a UnicodeChar or a ConsoleKey, e.g. for PageUp is passed the ConsoleKey.PageUp
consoleKey = consoleKey < 0xff ? consoleKey & 0xff | 0xff << 8 : consoleKey;
+ outputChar = GetKeyCharFromConsoleKey (consoleKey, modifiers, out consoleKey, out scanCode);
}
} else {
- var mod = GetModifiers (keyValue, modifiers, false);
+ var mod = GetModifiers (modifiers);
var scode = GetScanCode ("VirtualKey", consoleKey, mod);
if (scode != null) {
consoleKey = scode.VirtualKey;
@@ -131,23 +125,25 @@ public static uint GetConsoleKeyFromKey (uint keyValue, ConsoleModifiers modifie
}
}
- return consoleKey;
+ return new ConsoleKeyInfo ((char)outputChar, (ConsoleKey)consoleKey, modifiers.HasFlag (ConsoleModifiers.Shift),
+ modifiers.HasFlag (ConsoleModifiers.Alt), modifiers.HasFlag (ConsoleModifiers.Control));
}
///
- /// Get the output character from the .
+ /// Get the output character from the , the correct
+ /// and the scan code used on .
///
/// The unicode character.
/// The modifiers keys.
/// The resulting console key.
/// The resulting scan code.
/// The output character or the .
- public static uint GetKeyCharFromConsoleKey (uint unicodeChar, ConsoleModifiers modifiers, out uint consoleKey, out uint scanCode)
+ static uint GetKeyCharFromConsoleKey (uint unicodeChar, ConsoleModifiers modifiers, out uint consoleKey, out uint scanCode)
{
uint decodedChar = unicodeChar >> 8 == 0xff ? unicodeChar & 0xff : unicodeChar;
uint keyChar = decodedChar;
consoleKey = 0;
- var mod = GetModifiers (decodedChar, modifiers, true);
+ var mod = GetModifiers (modifiers);
scanCode = 0;
var scode = unicodeChar != 0 && unicodeChar >> 8 != 0xff ? GetScanCode ("VirtualKey", decodedChar, mod) : null;
if (scode != null) {
@@ -180,93 +176,93 @@ public static uint GetKeyCharFromConsoleKey (uint unicodeChar, ConsoleModifiers
return keyChar;
}
- // BUGBUG: This API should take a Key and return a ConsoleKey, not uints
///
/// Maps a unicode character (e.g. (Key)'a') to a uint representing a .
///
/// The key value.
+ /// The modifiers keys.
///
/// means the return value can be mapped to a valid unicode character.
/// means the return value is in the ConsoleKey enum.
///
/// The or the .
- public static uint MapKeyToConsoleKey (KeyCode keyValue, out bool isMappable)
+ public static ConsoleKey MapKeyToConsoleKey (KeyCode keyValue, ConsoleModifiers modifiers, out bool isMappable)
{
isMappable = false;
switch (keyValue) {
case KeyCode.Delete:
- return (uint)ConsoleKey.Delete;
+ return ConsoleKey.Delete;
case KeyCode.CursorUp:
- return (uint)ConsoleKey.UpArrow;
+ return ConsoleKey.UpArrow;
case KeyCode.CursorDown:
- return (uint)ConsoleKey.DownArrow;
+ return ConsoleKey.DownArrow;
case KeyCode.CursorLeft:
- return (uint)ConsoleKey.LeftArrow;
+ return ConsoleKey.LeftArrow;
case KeyCode.CursorRight:
- return (uint)ConsoleKey.RightArrow;
+ return ConsoleKey.RightArrow;
case KeyCode.PageUp:
- return (uint)ConsoleKey.PageUp;
+ return ConsoleKey.PageUp;
case KeyCode.PageDown:
- return (uint)ConsoleKey.PageDown;
+ return ConsoleKey.PageDown;
case KeyCode.Home:
- return (uint)ConsoleKey.Home;
+ return ConsoleKey.Home;
case KeyCode.End:
- return (uint)ConsoleKey.End;
+ return ConsoleKey.End;
case KeyCode.InsertChar:
- return (uint)ConsoleKey.Insert;
+ return ConsoleKey.Insert;
case KeyCode.DeleteChar:
- return (uint)ConsoleKey.Delete;
+ return ConsoleKey.Delete;
case KeyCode.F1:
- return (uint)ConsoleKey.F1;
+ return ConsoleKey.F1;
case KeyCode.F2:
- return (uint)ConsoleKey.F2;
+ return ConsoleKey.F2;
case KeyCode.F3:
- return (uint)ConsoleKey.F3;
+ return ConsoleKey.F3;
case KeyCode.F4:
- return (uint)ConsoleKey.F4;
+ return ConsoleKey.F4;
case KeyCode.F5:
- return (uint)ConsoleKey.F5;
+ return ConsoleKey.F5;
case KeyCode.F6:
- return (uint)ConsoleKey.F6;
+ return ConsoleKey.F6;
case KeyCode.F7:
- return (uint)ConsoleKey.F7;
+ return ConsoleKey.F7;
case KeyCode.F8:
- return (uint)ConsoleKey.F8;
+ return ConsoleKey.F8;
case KeyCode.F9:
- return (uint)ConsoleKey.F9;
+ return ConsoleKey.F9;
case KeyCode.F10:
- return (uint)ConsoleKey.F10;
+ return ConsoleKey.F10;
case KeyCode.F11:
- return (uint)ConsoleKey.F11;
+ return ConsoleKey.F11;
case KeyCode.F12:
- return (uint)ConsoleKey.F12;
+ return ConsoleKey.F12;
case KeyCode.F13:
- return (uint)ConsoleKey.F13;
+ return ConsoleKey.F13;
case KeyCode.F14:
- return (uint)ConsoleKey.F14;
+ return ConsoleKey.F14;
case KeyCode.F15:
- return (uint)ConsoleKey.F15;
+ return ConsoleKey.F15;
case KeyCode.F16:
- return (uint)ConsoleKey.F16;
+ return ConsoleKey.F16;
case KeyCode.F17:
- return (uint)ConsoleKey.F17;
+ return ConsoleKey.F17;
case KeyCode.F18:
- return (uint)ConsoleKey.F18;
+ return ConsoleKey.F18;
case KeyCode.F19:
- return (uint)ConsoleKey.F19;
+ return ConsoleKey.F19;
case KeyCode.F20:
- return (uint)ConsoleKey.F20;
+ return ConsoleKey.F20;
case KeyCode.F21:
- return (uint)ConsoleKey.F21;
+ return ConsoleKey.F21;
case KeyCode.F22:
- return (uint)ConsoleKey.F22;
+ return ConsoleKey.F22;
case KeyCode.F23:
- return (uint)ConsoleKey.F23;
+ return ConsoleKey.F23;
case KeyCode.F24:
- return (uint)ConsoleKey.F24;
+ return ConsoleKey.F24;
case KeyCode.Tab | KeyCode.ShiftMask:
- return (uint)ConsoleKey.Tab;
+ return ConsoleKey.Tab;
case KeyCode.Unknown:
isMappable = true;
return 0;
@@ -274,11 +270,18 @@ public static uint MapKeyToConsoleKey (KeyCode keyValue, out bool isMappable)
isMappable = true;
- //if (keyValue is >= Key.A and <= Key.Z) {
- // return (uint)keyValue + 32;
- //}
+ if (modifiers == ConsoleModifiers.Shift && keyValue - 32 is >= KeyCode.A and <= KeyCode.Z) {
+ return (ConsoleKey)(keyValue - 32);
+ } else if (modifiers == ConsoleModifiers.None && keyValue is >= KeyCode.A and <= KeyCode.Z) {
+ return (ConsoleKey)(keyValue + 32);
+ }
+ if (modifiers == ConsoleModifiers.Shift && keyValue - 32 is >= (KeyCode)'À' and <= (KeyCode)'Ý') {
+ return (ConsoleKey)(keyValue - 32);
+ } else if (modifiers == ConsoleModifiers.None && keyValue is >= (KeyCode)'À' and <= (KeyCode)'Ý') {
+ return (ConsoleKey)(keyValue + 32);
+ }
- return (uint)keyValue;
+ return (ConsoleKey)keyValue;
}
///
@@ -579,24 +582,20 @@ public static KeyCode MapKeyModifiers (ConsoleKeyInfo keyInfo, KeyCode key)
};
///
- ///
+ /// Decode a that is using .
///
- ///
- ///
+ /// The console key info.
+ /// The decoded or the .
+ /// If it's a the may be
+ /// a or a value.
+ ///
public static ConsoleKeyInfo FromVKPacketToKConsoleKeyInfo (ConsoleKeyInfo consoleKeyInfo)
{
if (consoleKeyInfo.Key != ConsoleKey.Packet) {
return consoleKeyInfo;
}
- var mod = consoleKeyInfo.Modifiers;
- bool shift = (mod & ConsoleModifiers.Shift) != 0;
- bool alt = (mod & ConsoleModifiers.Alt) != 0;
- bool control = (mod & ConsoleModifiers.Control) != 0;
-
- uint keyChar = GetKeyCharFromConsoleKey (consoleKeyInfo.KeyChar, consoleKeyInfo.Modifiers, out uint virtualKey, out _);
-
- return new ConsoleKeyInfo ((char)keyChar, (ConsoleKey)virtualKey, shift, alt, control);
+ return GetConsoleKeyFromKey (consoleKeyInfo.KeyChar, consoleKeyInfo.Modifiers, out _);
}
}
}
\ No newline at end of file
diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
index f4701aec6b..98181f0699 100644
--- a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
@@ -724,10 +724,10 @@ public override void SendKeys (char keyChar, ConsoleKey consoleKey, bool shift,
if (control) {
mod |= ConsoleModifiers.Control;
}
- var kchar = ConsoleKeyMapping.GetKeyCharFromConsoleKey (keyChar, mod, out uint ckey, out _);
- key = ConsoleKeyMapping.MapConsoleKeyToKey ((ConsoleKey)ckey, out bool mappable);
+ var cKeyInfo = ConsoleKeyMapping.GetConsoleKeyFromKey (keyChar, mod, out _);
+ key = ConsoleKeyMapping.MapConsoleKeyToKey ((ConsoleKey)cKeyInfo.Key, out bool mappable);
if (mappable) {
- key = (KeyCode)kchar;
+ key = (KeyCode)cKeyInfo.KeyChar;
}
} else {
key = (KeyCode)keyChar;
diff --git a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeConsole.cs b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeConsole.cs
index e2fcbbfd81..4cec5cb019 100644
--- a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeConsole.cs
+++ b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeConsole.cs
@@ -800,7 +800,7 @@ public static void PushMockKeyPress (KeyCode key)
{
MockKeyPresses.Push (new ConsoleKeyInfo (
(char)(key & ~KeyCode.CtrlMask & ~KeyCode.ShiftMask & ~KeyCode.AltMask),
- ConsoleKeyMapping.GetConsoleKeyFromKey (key),
+ ConsoleKeyMapping.GetConsoleKeyFromKey (key).Key,
key.HasFlag (KeyCode.ShiftMask),
key.HasFlag (KeyCode.AltMask),
key.HasFlag (KeyCode.CtrlMask)));
diff --git a/Terminal.Gui/ConsoleDrivers/NetDriver.cs b/Terminal.Gui/ConsoleDrivers/NetDriver.cs
index 14118a51e6..5aaff3439c 100644
--- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs
@@ -998,9 +998,9 @@ ConsoleKeyInfo FromVKPacketToKConsoleKeyInfo (ConsoleKeyInfo consoleKeyInfo)
var alt = (mod & ConsoleModifiers.Alt) != 0;
var control = (mod & ConsoleModifiers.Control) != 0;
- var keyChar = ConsoleKeyMapping.GetKeyCharFromConsoleKey (consoleKeyInfo.KeyChar, consoleKeyInfo.Modifiers, out uint virtualKey, out _);
+ var cKeyInfo = ConsoleKeyMapping.GetConsoleKeyFromKey (consoleKeyInfo.KeyChar, consoleKeyInfo.Modifiers, out _);
- return new ConsoleKeyInfo ((char)keyChar, (ConsoleKey)virtualKey, shift, alt, control);
+ return new ConsoleKeyInfo (cKeyInfo.KeyChar, cKeyInfo.Key, shift, alt, control);
}
KeyCode MapKey (ConsoleKeyInfo keyInfo)
@@ -1082,10 +1082,10 @@ KeyCode MapKey (ConsoleKeyInfo keyInfo)
return (KeyCode)((uint)KeyCode.A + delta) | KeyCode.ShiftMask;
}
}
-
- if (((KeyCode)((uint)keyInfo.KeyChar) & KeyCode.Space) == KeyCode.Space) {
- return (KeyCode)((uint)keyInfo.KeyChar) & ~KeyCode.Space;
- }
+ // This is buggy because is converting a lower case to a upper case and mustn't
+ //if (((KeyCode)((uint)keyInfo.KeyChar) & KeyCode.Space) == KeyCode.Space) {
+ // return (KeyCode)((uint)keyInfo.KeyChar) & ~KeyCode.Space;
+ //}
return (KeyCode)(uint)keyInfo.KeyChar;
}
if (key is >= ConsoleKey.D0 and <= ConsoleKey.D9) {
diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
index 30f3966828..b78d0d2dc3 100644
--- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
@@ -379,7 +379,7 @@ public struct KeyEventRecord {
[FieldOffset (12), MarshalAs (UnmanagedType.U4)]
public ControlKeyState dwControlKeyState;
- public override readonly string ToString () => $"[KeyEventRecord({(bKeyDown ? "down" : "up")},{wRepeatCount},{wVirtualKeyCode},{wVirtualScanCode},{new Rune(UnicodeChar).MakePrintable()},{dwControlKeyState})]";
+ public override readonly string ToString () => $"[KeyEventRecord({(bKeyDown ? "down" : "up")},{wRepeatCount},{wVirtualKeyCode},{wVirtualScanCode},{new Rune (UnicodeChar).MakePrintable ()},{dwControlKeyState})]";
}
[Flags]
@@ -617,7 +617,7 @@ public readonly string ToString (ConsoleKeyInfoEx ex)
sb.Append ((ex.CapsLock ? "caps," : string.Empty));
sb.Append ((ex.NumLock ? "num," : string.Empty));
sb.Append ((ex.ScrollLock ? "scroll," : string.Empty));
- var s = sb.ToString ().TrimEnd (',').TrimEnd(' ');
+ var s = sb.ToString ().TrimEnd (',').TrimEnd (' ');
return $"[ConsoleKeyInfoEx({s})]";
}
}
@@ -1005,12 +1005,12 @@ KeyCode MapKey (WindowsConsole.ConsoleKeyInfoEx keyInfoEx)
if (((keyInfo.Modifiers == ConsoleModifiers.Shift) ^ (keyInfoEx.CapsLock))) {
if (keyInfo.KeyChar <= (uint)KeyCode.Z) {
return (KeyCode)((uint)KeyCode.A + delta) | KeyCode.ShiftMask;
- }
+ }
}
if (((KeyCode)((uint)keyInfo.KeyChar) & KeyCode.Space) == 0) {
return (KeyCode)((uint)keyInfo.KeyChar) & ~KeyCode.Space;
- }
+ }
if (((KeyCode)((uint)keyInfo.KeyChar) & KeyCode.Space) != 0) {
if (((KeyCode)((uint)keyInfo.KeyChar) & ~KeyCode.Space) == (KeyCode)keyInfo.Key) {
@@ -1077,7 +1077,7 @@ internal void ProcessInput (WindowsConsole.InputRecord inputEvent)
inputEvent.KeyEvent = FromVKPacketToKeyEventRecord (inputEvent.KeyEvent);
}
var keyInfo = ToConsoleKeyInfoEx (inputEvent.KeyEvent);
- Debug.WriteLine ($"event: {inputEvent.ToString()} {keyInfo.ToString (keyInfo)}");
+ Debug.WriteLine ($"event: {inputEvent.ToString ()} {keyInfo.ToString (keyInfo)}");
var map = MapKey (keyInfo);
@@ -1437,14 +1437,14 @@ public WindowsConsole.KeyEventRecord FromVKPacketToKeyEventRecord (WindowsConsol
keyEvent.dwControlKeyState.HasFlag (WindowsConsole.ControlKeyState.RightControlPressed)) {
mod |= ConsoleModifiers.Control;
}
- var keyChar = ConsoleKeyMapping.GetKeyCharFromConsoleKey (keyEvent.UnicodeChar, mod, out uint virtualKey, out uint scanCode);
+ var cKeyInfo = ConsoleKeyMapping.GetConsoleKeyFromKey (keyEvent.UnicodeChar, mod, out uint scanCode);
return new WindowsConsole.KeyEventRecord {
- UnicodeChar = (char)keyChar,
+ UnicodeChar = cKeyInfo.KeyChar,
bKeyDown = keyEvent.bKeyDown,
dwControlKeyState = keyEvent.dwControlKeyState,
wRepeatCount = keyEvent.wRepeatCount,
- wVirtualKeyCode = (ushort)virtualKey,
+ wVirtualKeyCode = (ushort)cKeyInfo.Key,
wVirtualScanCode = (ushort)scanCode
};
}
diff --git a/UICatalog/Scenarios/VkeyPacketSimulator.cs b/UICatalog/Scenarios/VkeyPacketSimulator.cs
index 4c59e5f0bb..4bb4fdd2e4 100644
--- a/UICatalog/Scenarios/VkeyPacketSimulator.cs
+++ b/UICatalog/Scenarios/VkeyPacketSimulator.cs
@@ -162,8 +162,8 @@ public override void Setup ()
mod |= ConsoleModifiers.Control;
}
for (int i = 0; i < _keyboardStrokes.Count; i++) {
- var consoleKey = ConsoleKeyMapping.GetConsoleKeyFromKey ((uint)_keyboardStrokes [i], mod, out _, out _);
- Application.Driver.SendKeys ((char)consoleKey, ConsoleKey.Packet, mod.HasFlag (ConsoleModifiers.Shift),
+ var consoleKeyInfo = ConsoleKeyMapping.GetConsoleKeyFromKey ((uint)_keyboardStrokes [i], mod, out _);
+ Application.Driver.SendKeys (consoleKeyInfo.KeyChar, ConsoleKey.Packet, mod.HasFlag (ConsoleModifiers.Shift),
mod.HasFlag (ConsoleModifiers.Alt), mod.HasFlag (ConsoleModifiers.Control));
}
//}
diff --git a/UnitTests/ConsoleDrivers/ConsoleKeyMappingTests.cs b/UnitTests/ConsoleDrivers/ConsoleKeyMappingTests.cs
new file mode 100644
index 0000000000..26cb60ec5a
--- /dev/null
+++ b/UnitTests/ConsoleDrivers/ConsoleKeyMappingTests.cs
@@ -0,0 +1,218 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Xunit;
+
+namespace Terminal.Gui.ConsoleDrivers;
+public class ConsoleKeyMappingTests {
+ [Theory]
+ [InlineData ((KeyCode)'a' | KeyCode.ShiftMask, ConsoleKey.A, KeyCode.A, 'A')]
+ [InlineData ((KeyCode)'A', ConsoleKey.A, (KeyCode)'a', 'a')]
+ [InlineData ((KeyCode)'à' | KeyCode.ShiftMask, ConsoleKey.A, (KeyCode)'À', 'À')]
+ [InlineData ((KeyCode)'À', ConsoleKey.A, (KeyCode)'à', 'à')]
+ [InlineData ((KeyCode)'ü' | KeyCode.ShiftMask, ConsoleKey.U, (KeyCode)'Ü', 'Ü')]
+ [InlineData ((KeyCode)'Ü', ConsoleKey.U, (KeyCode)'ü', 'ü')]
+ [InlineData ((KeyCode)'ý' | KeyCode.ShiftMask, ConsoleKey.Y, (KeyCode)'Ý', 'Ý')]
+ [InlineData ((KeyCode)'Ý', ConsoleKey.Y, (KeyCode)'ý', 'ý')]
+ [InlineData ((KeyCode)'!' | KeyCode.ShiftMask, ConsoleKey.D1, (KeyCode)'!', '!')]
+ [InlineData (KeyCode.D1, ConsoleKey.D1, KeyCode.D1, '1')]
+ [InlineData ((KeyCode)'/' | KeyCode.ShiftMask, ConsoleKey.D7, (KeyCode)'/', '/')]
+ [InlineData (KeyCode.D7, ConsoleKey.D7, KeyCode.D7, '7')]
+ [InlineData (KeyCode.PageDown | KeyCode.ShiftMask, ConsoleKey.PageDown, KeyCode.Null, '\0')]
+ [InlineData (KeyCode.PageDown, ConsoleKey.PageDown, KeyCode.Null, '\0')]
+
+ public void TestIfEqual (KeyCode key, ConsoleKey expectedConsoleKey, KeyCode expectedKey, char expectedChar)
+ {
+ var consoleKeyInfo = ConsoleKeyMapping.GetConsoleKeyFromKey (key);
+ Assert.Equal (consoleKeyInfo.Key, expectedConsoleKey);
+ Assert.Equal ((char)expectedKey, expectedChar);
+ Assert.Equal (consoleKeyInfo.KeyChar, expectedChar);
+ }
+
+ static object packetLock = new object ();
+
+ ///
+ /// Sometimes when using remote 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
+ ///
+ [Theory]
+ [AutoInitShutdown]
+ [ClassData (typeof (PacketTest))]
+ public void TestVKPacket (uint unicodeCharacter, bool shift, bool alt, bool control, uint initialVirtualKey,
+ uint initialScanCode, KeyCode expectedRemapping, uint expectedVirtualKey, uint expectedScanCode)
+ {
+ lock (packetLock) {
+ Application._forceFakeConsole = true;
+ Application.Init ();
+
+ var modifiers = new ConsoleModifiers ();
+ if (shift) {
+ modifiers |= ConsoleModifiers.Shift;
+ }
+ if (alt) {
+ modifiers |= ConsoleModifiers.Alt;
+ }
+ if (control) {
+ modifiers |= ConsoleModifiers.Control;
+ }
+ ConsoleKeyInfo consoleKeyInfo = ConsoleKeyMapping.GetConsoleKeyFromKey (unicodeCharacter, modifiers, out uint scanCode);
+
+ Assert.Equal ((uint)consoleKeyInfo.Key, initialVirtualKey);
+
+
+ if (scanCode > 0 && consoleKeyInfo.KeyChar == 0) {
+ Assert.Equal (0, (double)consoleKeyInfo.KeyChar);
+ } else {
+ Assert.Equal (consoleKeyInfo.KeyChar, unicodeCharacter);
+ }
+ Assert.Equal ((uint)consoleKeyInfo.Key, expectedVirtualKey);
+ Assert.Equal (scanCode, initialScanCode);
+ Assert.Equal (scanCode, expectedScanCode);
+
+ var top = Application.Top;
+
+ top.KeyDown += (s, e) => {
+ Assert.Equal (Key.ToString (expectedRemapping), Key.ToString (e.KeyCode));
+ e.Handled = true;
+ Application.RequestStop ();
+ };
+
+ int iterations = -1;
+
+ Application.Iteration += (s, a) => {
+ iterations++;
+ if (iterations == 0) {
+ Application.Driver.SendKeys (consoleKeyInfo.KeyChar, ConsoleKey.Packet, shift, alt, control);
+ }
+ };
+ Application.Run ();
+ Application.Shutdown ();
+ }
+ }
+
+ public class PacketTest : IEnumerable, IEnumerable