Fixes #3540. V2: Keyboard input not working on Unix platforms

This commit is contained in:
BDisp
2024-06-16 00:14:08 +01:00
parent bd0045340e
commit 4610a3253d
6 changed files with 129 additions and 62 deletions

View File

@@ -859,13 +859,24 @@ public static class ConsoleKeyMapping
case ConsoleKey.F24:
keyCode = KeyCode.F24;
break;
case ConsoleKey.Clear:
keyCode = KeyCode.Clear;
break;
case ConsoleKey.Tab:
keyCode = KeyCode.Tab;
break;
default:
keyCode = (KeyCode)consoleKeyInfo.KeyChar;
if ((int)consoleKeyInfo.KeyChar is >= 1 and <= 26)
{
keyCode = (KeyCode)(consoleKeyInfo.KeyChar + 64);
}
else
{
keyCode = (KeyCode)consoleKeyInfo.KeyChar;
}
break;
}

View File

@@ -515,9 +515,10 @@ internal class CursesDriver : ConsoleDriver
{
// The ESC-number handling, debatable.
// Simulates the AltMask itself by pressing Alt + Space.
// Needed for macOS
if (wch2 == (int)KeyCode.Space)
{
k = KeyCode.AltMask;
k = KeyCode.AltMask | KeyCode.Space;
}
else if (wch2 - (int)KeyCode.Space >= (uint)KeyCode.A
&& wch2 - (int)KeyCode.Space <= (uint)KeyCode.Z)
@@ -532,41 +533,51 @@ internal class CursesDriver : ConsoleDriver
{
k = (KeyCode)((uint)KeyCode.AltMask + (uint)KeyCode.D0 + (wch2 - (uint)KeyCode.D0));
}
else if (wch2 == Curses.KeyCSI)
else
{
ConsoleKeyInfo [] cki =
{
new ((char)KeyCode.Esc, 0, false, false, false), new ('[', 0, false, false, false)
};
[
new ((char)KeyCode.Esc, 0, false, false, false), new ((char)wch2, 0, false, false, false)
];
HandleEscSeqResponse (ref code, ref k, ref wch2, ref key, ref cki);
return;
}
else
{
// Unfortunately there are no way to differentiate Ctrl+Alt+alfa and Ctrl+Shift+Alt+alfa.
if (((KeyCode)wch2 & KeyCode.CtrlMask) != 0)
{
k = (KeyCode)((uint)KeyCode.CtrlMask + (wch2 & ~(int)KeyCode.CtrlMask));
}
//else if (wch2 == Curses.KeyCSI)
//{
// ConsoleKeyInfo [] cki =
// {
// new ((char)KeyCode.Esc, 0, false, false, false), new ('[', 0, false, false, false)
// };
// HandleEscSeqResponse (ref code, ref k, ref wch2, ref key, ref cki);
if (wch2 == 0)
{
k = KeyCode.CtrlMask | KeyCode.AltMask | KeyCode.Space;
}
else if (wch >= (uint)KeyCode.A && wch <= (uint)KeyCode.Z)
{
k = KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.Space;
}
else if (wch2 < 256)
{
k = (KeyCode)wch2; // | KeyCode.AltMask;
}
else
{
k = (KeyCode)((uint)(KeyCode.AltMask | KeyCode.CtrlMask) + wch2);
}
}
// return;
//}
//else
//{
// // Unfortunately there are no way to differentiate Ctrl+Alt+alfa and Ctrl+Shift+Alt+alfa.
// if (((KeyCode)wch2 & KeyCode.CtrlMask) != 0)
// {
// k = (KeyCode)((uint)KeyCode.CtrlMask + (wch2 & ~(int)KeyCode.CtrlMask));
// }
// if (wch2 == 0)
// {
// k = KeyCode.CtrlMask | KeyCode.AltMask | KeyCode.Space;
// }
// //else if (wch >= (uint)KeyCode.A && wch <= (uint)KeyCode.Z)
// //{
// // k = KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.Space;
// //}
// else if (wch2 < 256)
// {
// k = (KeyCode)wch2; // | KeyCode.AltMask;
// }
// else
// {
// k = (KeyCode)((uint)(KeyCode.AltMask | KeyCode.CtrlMask) + wch2);
// }
//}
key = new Key (k);
}
@@ -584,6 +595,13 @@ internal class CursesDriver : ConsoleDriver
OnKeyDown (new Key (k));
OnKeyUp (new Key (k));
}
else if (wch == 127)
{
// Backspace needed for macOS
k = KeyCode.Backspace;
OnKeyDown (new Key (k));
OnKeyUp (new Key (k));
}
else
{
// Unfortunately there are no way to differentiate Ctrl+alfa and Ctrl+Shift+alfa.
@@ -611,7 +629,8 @@ internal class CursesDriver : ConsoleDriver
}
// Strip the KeyCode.Space flag off if it's set
if (k != KeyCode.Space && k.HasFlag (KeyCode.Space))
//if (k != KeyCode.Space && k.HasFlag (KeyCode.Space))
if (Key.GetIsKeyCodeAtoZ (k) && (k & KeyCode.Space) != 0)
{
k &= ~KeyCode.Space;
}

View File

@@ -106,7 +106,6 @@ public partial class Curses
public const int KeyPPage = 0x153;
public const int KeyHome = 0x106;
public const int KeyMouse = 0x199;
public const int KeyCSI = 0x5b;
public const int KeyEnd = 0x168;
public const int KeyDeleteChar = 0x14a;
public const int KeyInsertChar = 0x14b;

View File

@@ -195,6 +195,7 @@ public static class EscSeqUtils
buttonState = new List<MouseFlags> { 0 };
pos = default (Point);
isResponse = false;
char keyChar = '\0';
switch (c1Control)
{
@@ -242,10 +243,10 @@ public static class EscSeqUtils
break;
case "SS3":
key = GetConsoleKey (terminator [0], values [0], ref mod);
key = GetConsoleKey (terminator [0], values [0], ref mod, ref keyChar);
newConsoleKeyInfo = new ConsoleKeyInfo (
'\0',
keyChar,
key,
(mod & ConsoleModifiers.Shift) != 0,
(mod & ConsoleModifiers.Alt) != 0,
@@ -271,7 +272,7 @@ public static class EscSeqUtils
if (!string.IsNullOrEmpty (terminator))
{
key = GetConsoleKey (terminator [0], values [0], ref mod);
key = GetConsoleKey (terminator [0], values [0], ref mod, ref keyChar);
if (key != 0 && values.Length > 1)
{
@@ -279,7 +280,7 @@ public static class EscSeqUtils
}
newConsoleKeyInfo = new ConsoleKeyInfo (
'\0',
keyChar,
key,
(mod & ConsoleModifiers.Shift) != 0,
(mod & ConsoleModifiers.Alt) != 0,
@@ -344,13 +345,23 @@ public static class EscSeqUtils
/// <param name="value">The value.</param>
/// <param name="mod">The <see cref="ConsoleModifiers"/> which may changes.</param>
/// <returns>The <see cref="ConsoleKey"/> and probably the <see cref="ConsoleModifiers"/>.</returns>
public static ConsoleKey GetConsoleKey (char terminator, string? value, ref ConsoleModifiers mod)
public static ConsoleKey GetConsoleKey (char terminator, string? value, ref ConsoleModifiers mod, ref char keyChar)
{
if (terminator == 'Z')
{
mod |= ConsoleModifiers.Shift;
}
if (terminator == 'l')
{
keyChar = '+';
}
if (terminator == 'm')
{
keyChar = '-';
}
return (terminator, value) switch
{
('A', _) => ConsoleKey.UpArrow,
@@ -376,6 +387,18 @@ public static class EscSeqUtils
('~', "21") => ConsoleKey.F10,
('~', "23") => ConsoleKey.F11,
('~', "24") => ConsoleKey.F12,
('l', _) => ConsoleKey.Add,
('m', _) => ConsoleKey.Subtract,
('p', _) => ConsoleKey.Insert,
('q', _) => ConsoleKey.End,
('r', _) => ConsoleKey.DownArrow,
('s', _) => ConsoleKey.PageDown,
('t', _) => ConsoleKey.LeftArrow,
('u', _) => ConsoleKey.Clear,
('v', _) => ConsoleKey.RightArrow,
('w', _) => ConsoleKey.Home,
('x', _) => ConsoleKey.UpArrow,
('y', _) => ConsoleKey.PageUp,
(_, _) => 0
};
}

View File

@@ -136,6 +136,8 @@ public class MenuBar : View
// TODO: Why do we have two keybindings for opening the menu? Ctrl-Space and Key?
KeyBindings.Add (Key.Space.WithCtrl, keyBinding);
// This is needed for macOS because Key.Space.WithCtrl doesn't work
KeyBindings.Add (Key.Space.WithAlt, keyBinding);
// TODO: Figure out how to make Alt work (on Windows)
//KeyBindings.Add (Key.WithAlt, keyBinding);

View File

@@ -968,32 +968,45 @@ public class EscSeqUtilsTests
public void GetConsoleKey_Tests ()
{
ConsoleModifiers mod = 0;
Assert.Equal (ConsoleKey.UpArrow, EscSeqUtils.GetConsoleKey ('A', "", ref mod));
Assert.Equal (ConsoleKey.DownArrow, EscSeqUtils.GetConsoleKey ('B', "", ref mod));
Assert.Equal (_key = ConsoleKey.RightArrow, EscSeqUtils.GetConsoleKey ('C', "", ref mod));
Assert.Equal (ConsoleKey.LeftArrow, EscSeqUtils.GetConsoleKey ('D', "", ref mod));
Assert.Equal (ConsoleKey.End, EscSeqUtils.GetConsoleKey ('F', "", ref mod));
Assert.Equal (ConsoleKey.Home, EscSeqUtils.GetConsoleKey ('H', "", ref mod));
Assert.Equal (ConsoleKey.F1, EscSeqUtils.GetConsoleKey ('P', "", ref mod));
Assert.Equal (ConsoleKey.F2, EscSeqUtils.GetConsoleKey ('Q', "", ref mod));
Assert.Equal (ConsoleKey.F3, EscSeqUtils.GetConsoleKey ('R', "", ref mod));
Assert.Equal (ConsoleKey.F4, EscSeqUtils.GetConsoleKey ('S', "", ref mod));
Assert.Equal (ConsoleKey.Tab, EscSeqUtils.GetConsoleKey ('Z', "", ref mod));
char keyChar = '\0';
Assert.Equal (ConsoleKey.UpArrow, EscSeqUtils.GetConsoleKey ('A', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.DownArrow, EscSeqUtils.GetConsoleKey ('B', "", ref mod, ref keyChar));
Assert.Equal (_key = ConsoleKey.RightArrow, EscSeqUtils.GetConsoleKey ('C', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.LeftArrow, EscSeqUtils.GetConsoleKey ('D', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.End, EscSeqUtils.GetConsoleKey ('F', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.Home, EscSeqUtils.GetConsoleKey ('H', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.F1, EscSeqUtils.GetConsoleKey ('P', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.F2, EscSeqUtils.GetConsoleKey ('Q', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.F3, EscSeqUtils.GetConsoleKey ('R', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.F4, EscSeqUtils.GetConsoleKey ('S', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.Tab, EscSeqUtils.GetConsoleKey ('Z', "", ref mod, ref keyChar));
Assert.Equal (ConsoleModifiers.Shift, mod);
Assert.Equal (0, (int)EscSeqUtils.GetConsoleKey ('\0', "", ref mod));
Assert.Equal (ConsoleKey.Insert, EscSeqUtils.GetConsoleKey ('~', "2", ref mod));
Assert.Equal (ConsoleKey.Delete, EscSeqUtils.GetConsoleKey ('~', "3", ref mod));
Assert.Equal (ConsoleKey.PageUp, EscSeqUtils.GetConsoleKey ('~', "5", ref mod));
Assert.Equal (ConsoleKey.PageDown, EscSeqUtils.GetConsoleKey ('~', "6", ref mod));
Assert.Equal (ConsoleKey.F5, EscSeqUtils.GetConsoleKey ('~', "15", ref mod));
Assert.Equal (ConsoleKey.F6, EscSeqUtils.GetConsoleKey ('~', "17", ref mod));
Assert.Equal (ConsoleKey.F7, EscSeqUtils.GetConsoleKey ('~', "18", ref mod));
Assert.Equal (ConsoleKey.F8, EscSeqUtils.GetConsoleKey ('~', "19", ref mod));
Assert.Equal (ConsoleKey.F9, EscSeqUtils.GetConsoleKey ('~', "20", ref mod));
Assert.Equal (ConsoleKey.F10, EscSeqUtils.GetConsoleKey ('~', "21", ref mod));
Assert.Equal (ConsoleKey.F11, EscSeqUtils.GetConsoleKey ('~', "23", ref mod));
Assert.Equal (ConsoleKey.F12, EscSeqUtils.GetConsoleKey ('~', "24", ref mod));
Assert.Equal (0, (int)EscSeqUtils.GetConsoleKey ('~', "", ref mod));
Assert.Equal (0, (int)EscSeqUtils.GetConsoleKey ('\0', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.Insert, EscSeqUtils.GetConsoleKey ('~', "2", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.Delete, EscSeqUtils.GetConsoleKey ('~', "3", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.PageUp, EscSeqUtils.GetConsoleKey ('~', "5", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.PageDown, EscSeqUtils.GetConsoleKey ('~', "6", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.F5, EscSeqUtils.GetConsoleKey ('~', "15", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.F6, EscSeqUtils.GetConsoleKey ('~', "17", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.F7, EscSeqUtils.GetConsoleKey ('~', "18", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.F8, EscSeqUtils.GetConsoleKey ('~', "19", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.F9, EscSeqUtils.GetConsoleKey ('~', "20", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.F10, EscSeqUtils.GetConsoleKey ('~', "21", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.F11, EscSeqUtils.GetConsoleKey ('~', "23", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.F12, EscSeqUtils.GetConsoleKey ('~', "24", ref mod, ref keyChar));
Assert.Equal (0, (int)EscSeqUtils.GetConsoleKey ('~', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.Add, EscSeqUtils.GetConsoleKey ('l', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.Subtract, EscSeqUtils.GetConsoleKey ('m', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.Insert, EscSeqUtils.GetConsoleKey ('p', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.End, EscSeqUtils.GetConsoleKey ('q', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.DownArrow, EscSeqUtils.GetConsoleKey ('r', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.PageDown, EscSeqUtils.GetConsoleKey ('s', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.LeftArrow, EscSeqUtils.GetConsoleKey ('t', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.Clear, EscSeqUtils.GetConsoleKey ('u', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.RightArrow, EscSeqUtils.GetConsoleKey ('v', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.Home, EscSeqUtils.GetConsoleKey ('w', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.UpArrow, EscSeqUtils.GetConsoleKey ('x', "", ref mod, ref keyChar));
Assert.Equal (ConsoleKey.PageUp, EscSeqUtils.GetConsoleKey ('y', "", ref mod, ref keyChar));
}
[Fact]