using System.Collections.Frozen; using System.Collections.Generic; using System.Runtime.InteropServices; using Robust.Shared; using System.Threading; using OpenToolkit.GraphicsLibraryFramework; using Robust.Client.Input; using Robust.Shared.Localization; using GlfwKey = OpenToolkit.GraphicsLibraryFramework.Keys; using GlfwButton = OpenToolkit.GraphicsLibraryFramework.MouseButton; using static Robust.Client.Input.Mouse; using static Robust.Client.Input.Keyboard; using Robust.Shared.IoC; using Robust.Shared.Configuration; namespace Robust.Client.Graphics.Clyde { internal partial class Clyde { private sealed partial class GlfwWindowingImpl { // TODO: to avoid having to ask the windowing thread, key names are cached. // This means they don't update correctly if the user switches keyboard mode. RIP. private readonly Dictionary _printableKeyNameMap = new(); private void InitKeyMap() { _printableKeyNameMap.Clear(); // From GLFW's source code: this is the actual list of "printable" keys // that GetKeyName returns something for. CacheKey(Keys.KeyPadEqual); for (var k = Keys.KeyPad0; k <= Keys.KeyPadAdd; k++) { CacheKey(k); } for (var k = Keys.Apostrophe; k <= Keys.World2; k++) { CacheKey(k); } void CacheKey(GlfwKey key) { var rKey = ConvertGlfwKey(key); if (rKey == Key.Unknown) return; var name = GLFW.GetKeyName(key, 0); if (!string.IsNullOrEmpty(name)) _printableKeyNameMap.Add(rKey, name); } } public string? KeyGetName(Keyboard.Key key) { if (_printableKeyNameMap.TryGetValue(key, out var name)) return name; return null; } public static Button ConvertGlfwButton(GlfwButton button) { return MouseButtonMap[button]; } private static readonly FrozenDictionary MouseButtonMap = new Dictionary() { {GlfwButton.Left, Button.Left}, {GlfwButton.Middle, Button.Middle}, {GlfwButton.Right, Button.Right}, {GlfwButton.Button4, Button.Button4}, {GlfwButton.Button5, Button.Button5}, {GlfwButton.Button6, Button.Button6}, {GlfwButton.Button7, Button.Button7}, {GlfwButton.Button8, Button.Button8}, }.ToFrozenDictionary(); private static readonly FrozenDictionary KeyMap; private static readonly FrozenDictionary KeyMapReverse; internal static Key ConvertGlfwKey(GlfwKey key) { if (KeyMap.TryGetValue(key, out var result)) { return result; } return Key.Unknown; } internal static GlfwKey ConvertGlfwKeyReverse(Key key) { if (KeyMapReverse.TryGetValue(key, out var result)) { return result; } return GlfwKey.Unknown; } static GlfwWindowingImpl() { KeyMap = new Dictionary { {GlfwKey.A, Key.A}, {GlfwKey.B, Key.B}, {GlfwKey.C, Key.C}, {GlfwKey.D, Key.D}, {GlfwKey.E, Key.E}, {GlfwKey.F, Key.F}, {GlfwKey.G, Key.G}, {GlfwKey.H, Key.H}, {GlfwKey.I, Key.I}, {GlfwKey.J, Key.J}, {GlfwKey.K, Key.K}, {GlfwKey.L, Key.L}, {GlfwKey.M, Key.M}, {GlfwKey.N, Key.N}, {GlfwKey.O, Key.O}, {GlfwKey.P, Key.P}, {GlfwKey.Q, Key.Q}, {GlfwKey.R, Key.R}, {GlfwKey.S, Key.S}, {GlfwKey.T, Key.T}, {GlfwKey.U, Key.U}, {GlfwKey.V, Key.V}, {GlfwKey.W, Key.W}, {GlfwKey.X, Key.X}, {GlfwKey.Y, Key.Y}, {GlfwKey.Z, Key.Z}, {GlfwKey.D0, Key.Num0}, {GlfwKey.D1, Key.Num1}, {GlfwKey.D2, Key.Num2}, {GlfwKey.D3, Key.Num3}, {GlfwKey.D4, Key.Num4}, {GlfwKey.D5, Key.Num5}, {GlfwKey.D6, Key.Num6}, {GlfwKey.D7, Key.Num7}, {GlfwKey.D8, Key.Num8}, {GlfwKey.D9, Key.Num9}, {GlfwKey.KeyPad0, Key.NumpadNum0}, {GlfwKey.KeyPad1, Key.NumpadNum1}, {GlfwKey.KeyPad2, Key.NumpadNum2}, {GlfwKey.KeyPad3, Key.NumpadNum3}, {GlfwKey.KeyPad4, Key.NumpadNum4}, {GlfwKey.KeyPad5, Key.NumpadNum5}, {GlfwKey.KeyPad6, Key.NumpadNum6}, {GlfwKey.KeyPad7, Key.NumpadNum7}, {GlfwKey.KeyPad8, Key.NumpadNum8}, {GlfwKey.KeyPad9, Key.NumpadNum9}, {GlfwKey.Escape, Key.Escape}, {GlfwKey.LeftControl, Key.Control}, {GlfwKey.RightControl, Key.Control}, {GlfwKey.RightShift, Key.Shift}, {GlfwKey.LeftShift, Key.Shift}, {GlfwKey.LeftAlt, Key.Alt}, {GlfwKey.RightAlt, Key.Alt}, {GlfwKey.LeftSuper, Key.LSystem}, {GlfwKey.RightSuper, Key.RSystem}, {GlfwKey.Menu, Key.Menu}, {GlfwKey.LeftBracket, Key.LBracket}, {GlfwKey.RightBracket, Key.RBracket}, {GlfwKey.Semicolon, Key.SemiColon}, {GlfwKey.Comma, Key.Comma}, {GlfwKey.Period, Key.Period}, {GlfwKey.Apostrophe, Key.Apostrophe}, {GlfwKey.Slash, Key.Slash}, {GlfwKey.Backslash, Key.BackSlash}, {GlfwKey.GraveAccent, Key.Tilde}, {GlfwKey.Equal, Key.Equal}, {GlfwKey.Space, Key.Space}, {GlfwKey.Enter, Key.Return}, {GlfwKey.KeyPadEnter, Key.NumpadEnter}, {GlfwKey.Backspace, Key.BackSpace}, {GlfwKey.Tab, Key.Tab}, {GlfwKey.PageUp, Key.PageUp}, {GlfwKey.PageDown, Key.PageDown}, {GlfwKey.End, Key.End}, {GlfwKey.Home, Key.Home}, {GlfwKey.Insert, Key.Insert}, {GlfwKey.Delete, Key.Delete}, {GlfwKey.Minus, Key.Minus}, {GlfwKey.KeyPadAdd, Key.NumpadAdd}, {GlfwKey.KeyPadSubtract, Key.NumpadSubtract}, {GlfwKey.KeyPadDivide, Key.NumpadDivide}, {GlfwKey.KeyPadMultiply, Key.NumpadMultiply}, {GlfwKey.KeyPadDecimal, Key.NumpadDecimal}, {GlfwKey.Left, Key.Left}, {GlfwKey.Right, Key.Right}, {GlfwKey.Up, Key.Up}, {GlfwKey.Down, Key.Down}, {GlfwKey.F1, Key.F1}, {GlfwKey.F2, Key.F2}, {GlfwKey.F3, Key.F3}, {GlfwKey.F4, Key.F4}, {GlfwKey.F5, Key.F5}, {GlfwKey.F6, Key.F6}, {GlfwKey.F7, Key.F7}, {GlfwKey.F8, Key.F8}, {GlfwKey.F9, Key.F9}, {GlfwKey.F10, Key.F10}, {GlfwKey.F11, Key.F11}, {GlfwKey.F12, Key.F12}, {GlfwKey.F13, Key.F13}, {GlfwKey.F14, Key.F14}, {GlfwKey.F15, Key.F15}, {GlfwKey.F16, Key.F16}, {GlfwKey.F17, Key.F17}, {GlfwKey.F18, Key.F18}, {GlfwKey.F19, Key.F19}, {GlfwKey.F20, Key.F20}, {GlfwKey.F21, Key.F21}, {GlfwKey.F22, Key.F22}, {GlfwKey.F23, Key.F23}, {GlfwKey.F24, Key.F24}, {GlfwKey.Pause, Key.Pause}, {GlfwKey.World1, Key.World1}, {GlfwKey.CapsLock, Key.CapsLock} }.ToFrozenDictionary(); var keyMapReverse = new Dictionary(); foreach (var (key, value) in KeyMap) { keyMapReverse[value] = key; } KeyMapReverse = keyMapReverse.ToFrozenDictionary(); } } } }