Browse Source

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

BDisp 1 year ago
parent
commit
4610a3253d

+ 12 - 1
Terminal.Gui/ConsoleDrivers/ConsoleKeyMapping.cs

@@ -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;
         }

+ 50 - 31
Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

@@ -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));
-                    }
-
-                    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);
-                    }
-                }
+                //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);
+
+                //    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;
             }

+ 0 - 1
Terminal.Gui/ConsoleDrivers/CursesDriver/constants.cs

@@ -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;

+ 28 - 5
Terminal.Gui/ConsoleDrivers/EscSeqUtils/EscSeqUtils.cs

@@ -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
                };
     }

+ 2 - 0
Terminal.Gui/Views/Menu/MenuBar.cs

@@ -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);

+ 38 - 25
UnitTests/Input/EscSeqUtilsTests.cs

@@ -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]