From b335d44c1b309cb9774a7232e8aa8272e372a545 Mon Sep 17 00:00:00 2001 From: Chris Pick Date: Sun, 15 May 2022 20:31:52 -0400 Subject: [PATCH] [#334] Fix keyboard on macOS Fixes https://github.com/renode/renode/issues/334 --- .../Main/Peripherals/Input/KeyScanCode.cs | 2 +- src/UI/UI.csproj | 1 + .../Events/OSXToKeyScanCodeConverter.cs | 331 ++++++++++++++++++ src/UI/VideoAnalyzer/Events/XWTEventSource.cs | 8 +- 4 files changed, 339 insertions(+), 3 deletions(-) create mode 100644 src/UI/VideoAnalyzer/Events/OSXToKeyScanCodeConverter.cs diff --git a/src/Emulator/Main/Peripherals/Input/KeyScanCode.cs b/src/Emulator/Main/Peripherals/Input/KeyScanCode.cs index 469b09d12..e3e168b6c 100644 --- a/src/Emulator/Main/Peripherals/Input/KeyScanCode.cs +++ b/src/Emulator/Main/Peripherals/Input/KeyScanCode.cs @@ -83,7 +83,7 @@ public enum KeyScanCode OemSemicolon = 0x33, OemQuotes = 0x34, CapsLock = 0x39, - OemPeriod= 0x36, + OemPeriod = 0x36, OemComma = 0x37, OemQuestion = 0x38, NumLock = 0x53, diff --git a/src/UI/UI.csproj b/src/UI/UI.csproj index 0ae9f9d68..134f01e8b 100644 --- a/src/UI/UI.csproj +++ b/src/UI/UI.csproj @@ -86,6 +86,7 @@ + diff --git a/src/UI/VideoAnalyzer/Events/OSXToKeyScanCodeConverter.cs b/src/UI/VideoAnalyzer/Events/OSXToKeyScanCodeConverter.cs new file mode 100644 index 000000000..e05bb6131 --- /dev/null +++ b/src/UI/VideoAnalyzer/Events/OSXToKeyScanCodeConverter.cs @@ -0,0 +1,331 @@ +// +// Copyright (c) 2010-2018 Antmicro +// Copyright (c) 2011-2015 Realtime Embedded +// +// This file is licensed under the MIT License. +// Full license text is available in 'licenses/MIT.txt'. +// +using Antmicro.Renode.Peripherals.Input; +using System.Collections.Generic; +using Xwt; + +namespace Antmicro.Renode.Extensions.Analyzers.Video.Events +{ + internal class OSXToKeyScanCodeConverter + { + static OSXToKeyScanCodeConverter() + { + Instance = new OSXToKeyScanCodeConverter(); + } + + public static OSXToKeyScanCodeConverter Instance { get; private set; } + + public KeyScanCode? GetScanCode(Key key) + { + KeyScanCode result; + return UntranslatedScanCode.TryGetValue(key, out result) ? (KeyScanCode?)result : null; + } + + /* + keycode: BackQuote 96 entryKey: 50 + keycode: K1 49 entryKey: 18 + keycode: K2 50 entryKey: 19 + keycode: K3 51 entryKey: 20 + keycode: K4 52 entryKey: 21 + keycode: K5 53 entryKey: 23 + keycode: K6 54 entryKey: 22 + keycode: K7 55 entryKey: 26 + keycode: K8 56 entryKey: 28 + keycode: K9 57 entryKey: 25 + keycode: K0 48 entryKey: 29 + keycode: Minus 45 entryKey: 27 + keycode: 61 61 entryKey: 24 + keycode: BackSpace 65288 entryKey: 51 + keycode: Tab 65289 entryKey: 48 + keycode: q 113 entryKey: 12 + keycode: w 119 entryKey: 13 + keycode: e 101 entryKey: 14 + keycode: r 114 entryKey: 15 + keycode: t 116 entryKey: 17 + keycode: y 121 entryKey: 16 + keycode: u 117 entryKey: 32 + keycode: i 105 entryKey: 34 + keycode: o 111 entryKey: 31 + keycode: p 112 entryKey: 35 + keycode: OpenSquareBracket 91 entryKey: 33 + keycode: CloseSquareBracket 93 entryKey: 30 + keycode: Backslash 92 entryKey: 42 + keycode: Escape 65307 entryKey: 53 + keycode: a 97 entryKey: 0 + keycode: s 115 entryKey: 1 + keycode: d 100 entryKey: 2 + keycode: f 102 entryKey: 3 + keycode: g 103 entryKey: 5 + keycode: h 104 entryKey: 4 + keycode: j 106 entryKey: 38 + keycode: k 107 entryKey: 40 + keycode: l 108 entryKey: 37 + keycode: Semicolon 59 entryKey: 41 + keycode: SingleQuote 39 entryKey: 39 + keycode: Return 65293 entryKey: 36 + keycode: ShiftLeft 65505 entryKey: 56 + keycode: ShiftLeft 65505 entryKey: 56 + keycode: ShiftLeft 65505 entryKey: 56 + keycode: z 122 entryKey: 6 + keycode: x 120 entryKey: 7 + keycode: c 99 entryKey: 8 + keycode: v 118 entryKey: 9 + keycode: b 98 entryKey: 11 + keycode: n 110 entryKey: 45 + keycode: m 109 entryKey: 46 + keycode: Comma 44 entryKey: 43 + keycode: Period 46 entryKey: 47 + keycode: Slash 47 entryKey: 44 + keycode: ShiftRight 65506 entryKey: 60 + keycode: ControlLeft 65507 entryKey: 59 + keycode: MetaLeft 65511 entryKey: 55 + keycode: AltLeft 65513 entryKey: 58 + keycode: Space 32 entryKey: 49 + keycode: AltRight 65514 entryKey: 61 + keycode: 16777232 16777232 entryKey: 108 + keycode: ControlRight 65508 entryKey: 62 + keycode: ShiftLeft 65505 entryKey: 56 + keycode: Tilde 126 entryKey: 50 + keycode: ShiftLeft 65505 entryKey: 56 + keycode: Exclamation 33 entryKey: 18 + keycode: At 64 entryKey: 19 + keycode: Hash 35 entryKey: 20 + keycode: Dollar 36 entryKey: 21 + keycode: Percent 37 entryKey: 23 + keycode: 94 94 entryKey: 22 + keycode: Ampersand 38 entryKey: 26 + keycode: Asterisk 42 entryKey: 28 + keycode: LeftBracket 40 entryKey: 25 + keycode: RightBracket 41 entryKey: 29 + keycode: Underscore 95 entryKey: 27 + keycode: Plus 43 entryKey: 24 + keycode: BackSpace 65288 entryKey: 51 + keycode: 65056 65056 entryKey: 48 + keycode: Q 81 entryKey: 12 + keycode: W 87 entryKey: 13 + keycode: E 69 entryKey: 14 + keycode: R 82 entryKey: 15 + keycode: T 84 entryKey: 17 + keycode: Y 89 entryKey: 16 + keycode: U 85 entryKey: 32 + keycode: I 73 entryKey: 34 + keycode: O 79 entryKey: 31 + keycode: P 80 entryKey: 35 + keycode: OpenCurlyBracket 123 entryKey: 33 + keycode: CloseCurlyBracket 125 entryKey: 30 + keycode: Pipe 124 entryKey: 42 + keycode: Escape 65307 entryKey: 53 + keycode: A 65 entryKey: 0 + keycode: S 83 entryKey: 1 + keycode: D 68 entryKey: 2 + keycode: F 70 entryKey: 3 + keycode: G 71 entryKey: 5 + keycode: H 72 entryKey: 4 + keycode: J 74 entryKey: 38 + keycode: K 75 entryKey: 40 + keycode: L 76 entryKey: 37 + keycode: Colon 58 entryKey: 41 + keycode: Quote 34 entryKey: 39 + keycode: Return 65293 entryKey: 36 + keycode: Z 90 entryKey: 6 + keycode: X 88 entryKey: 7 + keycode: C 67 entryKey: 8 + keycode: V 86 entryKey: 9 + keycode: B 66 entryKey: 11 + keycode: N 78 entryKey: 45 + keycode: M 77 entryKey: 46 + keycode: Less 60 entryKey: 43 + keycode: Greater 62 entryKey: 47 + keycode: Question 63 entryKey: 44 + keycode: ShiftRight 65506 entryKey: 60 + keycode: ShiftRight 65506 entryKey: 60 + keycode: ControlLeft 65507 entryKey: 59 + keycode: MetaLeft 65511 entryKey: 55 + keycode: Left 65361 entryKey: 70 + keycode: Up 65362 entryKey: 77 + keycode: Right 65363 entryKey: 66 + keycode: Down 65364 entryKey: 72 + keycode: 16777221 16777221 entryKey: 114 + keycode: Home 65360 entryKey: 115 + keycode: PageUp 65365 entryKey: 116 + keycode: Delete 65535 entryKey: 117 + keycode: End 65367 entryKey: 119 + keycode: PageDown 65366 entryKey: 121 + keycode: NumPadDivide 65455 entryKey: 75 + keycode: NumPadMultiply 65450 entryKey: 67 + keycode: NumPadSubtract 65453 entryKey: 78 + keycode: NumPad7 65463 entryKey: 89 + keycode: NumPad8 65464 entryKey: 91 + keycode: NumPad9 65465 entryKey: 92 + keycode: NumPadAdd 65451 entryKey: 69 + keycode: NumPad4 65460 entryKey: 86 + keycode: NumPad5 65461 entryKey: 87 + keycode: NumPad6 65462 entryKey: 88 + keycode: NumPad1 65457 entryKey: 83 + keycode: NumPad2 65458 entryKey: 84 + keycode: NumPad3 65459 entryKey: 85 + keycode: NumPad0 65456 entryKey: 82 + keycode: NumPadEnter 65421 entryKey: 76 + keycode: NumPadDecimal 65454 entryKey: 65 + keycode: NumPadEnter 65421 entryKey: 76 + keycode: F1 65470 entryKey: 122 + keycode: F2 65471 entryKey: 120 + keycode: F3 65472 entryKey: 99 + keycode: F4 65473 entryKey: 118 + keycode: F5 65474 entryKey: 96 + keycode: F6 65475 entryKey: 97 + keycode: F7 65476 entryKey: 98 + keycode: F8 65477 entryKey: 100 + keycode: F9 65478 entryKey: 101 + keycode: F10 65479 entryKey: 109 + keycode: 65481 65481 entryKey: 111 + keycode: Escape 65307 entryKey: 53 + */ + private readonly Dictionary UntranslatedScanCode = new Dictionary + { + { Key.AltLeft, KeyScanCode.AltL }, + { Key.MetaLeft, KeyScanCode.WinL }, + { Key.Space, KeyScanCode.Space }, + { Key.AltRight, KeyScanCode.AltR }, + { Key.MetaRight, KeyScanCode.WinR }, + { Key.Menu, KeyScanCode.WinMenu }, + { Key.Z, KeyScanCode.Z }, + { Key.z, KeyScanCode.Z }, + { Key.X, KeyScanCode.X }, + { Key.x, KeyScanCode.X }, + { Key.C, KeyScanCode.C }, + { Key.c, KeyScanCode.C }, + { Key.V, KeyScanCode.V }, + { Key.v, KeyScanCode.V }, + { Key.B, KeyScanCode.B }, + { Key.b, KeyScanCode.B }, + { Key.N, KeyScanCode.N }, + { Key.n, KeyScanCode.N }, + { Key.M, KeyScanCode.M }, + { Key.m, KeyScanCode.M }, + { Key.Period, KeyScanCode.OemPeriod }, + { Key.Comma, KeyScanCode.OemComma }, + { Key.Question, KeyScanCode.OemQuestion }, + { Key.ShiftRight, KeyScanCode.ShiftR }, + + { Key.CapsLock, KeyScanCode.CapsLock }, + { Key.A, KeyScanCode.A }, + { Key.a, KeyScanCode.A }, + { Key.S, KeyScanCode.S }, + { Key.s, KeyScanCode.S }, + { Key.D, KeyScanCode.D }, + { Key.d, KeyScanCode.D }, + { Key.F, KeyScanCode.F }, + { Key.f, KeyScanCode.F }, + { Key.G, KeyScanCode.G }, + { Key.g, KeyScanCode.G }, + { Key.H, KeyScanCode.H }, + { Key.h, KeyScanCode.H }, + { Key.J, KeyScanCode.J }, + { Key.j, KeyScanCode.J }, + { Key.K, KeyScanCode.K }, + { Key.k, KeyScanCode.K }, + { Key.L, KeyScanCode.L }, + { Key.l, KeyScanCode.L }, + { Key.Semicolon, KeyScanCode.OemSemicolon }, + { Key.Quote, KeyScanCode.OemQuotes }, + { Key.Return, KeyScanCode.Enter }, + + { Key.Tab, KeyScanCode.Tab }, + { Key.Q, KeyScanCode.Q }, + { Key.q, KeyScanCode.Q }, + { Key.W, KeyScanCode.W }, + { Key.w, KeyScanCode.W }, + { Key.E, KeyScanCode.E }, + { Key.e, KeyScanCode.E }, + { Key.R, KeyScanCode.R }, + { Key.r, KeyScanCode.R }, + { Key.T, KeyScanCode.T }, + { Key.t, KeyScanCode.T }, + { Key.Y, KeyScanCode.Y }, + { Key.y, KeyScanCode.Y }, + { Key.U, KeyScanCode.U }, + { Key.u, KeyScanCode.U }, + { Key.I, KeyScanCode.I }, + { Key.i, KeyScanCode.I }, + { Key.O, KeyScanCode.O }, + { Key.o, KeyScanCode.O }, + { Key.P, KeyScanCode.P }, + { Key.p, KeyScanCode.P }, + { Key.OpenCurlyBracket, KeyScanCode.OemOpenBrackets }, + { Key.OpenSquareBracket, KeyScanCode.OemOpenBrackets }, + { Key.CloseCurlyBracket, KeyScanCode.OemCloseBrackets }, + { Key.CloseSquareBracket, KeyScanCode.OemCloseBrackets }, + + { Key.Tilde, KeyScanCode.Tilde }, + { Key.BackQuote, KeyScanCode.Tilde }, + { Key.K1, KeyScanCode.Number1 }, + { Key.K2, KeyScanCode.Number2 }, + { Key.K3, KeyScanCode.Number3 }, + { Key.K4, KeyScanCode.Number4 }, + { Key.K5, KeyScanCode.Number5 }, + { Key.K6, KeyScanCode.Number6 }, + { Key.K7, KeyScanCode.Number7 }, + { Key.K8, KeyScanCode.Number8 }, + { Key.K9, KeyScanCode.Number9 }, + { Key.K0, KeyScanCode.Number0 }, + { Key.Minus, KeyScanCode.OemMinus }, + { Key.Underscore, KeyScanCode.OemMinus }, + { Key.Plus, KeyScanCode.OemPlus }, + { Key.Equal, KeyScanCode.OemPlus }, + { Key.Backslash, KeyScanCode.OemPipe }, + { Key.Pipe, KeyScanCode.OemPipe }, + { Key.BackSpace, KeyScanCode.BackSpace }, + + { Key.Escape, KeyScanCode.Escape }, + { Key.F1, KeyScanCode.F1 }, + { Key.F2, KeyScanCode.F2 }, + { Key.F3, KeyScanCode.F3 }, + { Key.F4, KeyScanCode.F4 }, + { Key.F5, KeyScanCode.F5 }, + { Key.F6, KeyScanCode.F6 }, + { Key.F7, KeyScanCode.F7 }, + { Key.F8, KeyScanCode.F8 }, + { Key.F9, KeyScanCode.F9 }, + { Key.F10, KeyScanCode.F10 }, + { Key.Print, KeyScanCode.PrtSc }, + { Key.ScrollLock, KeyScanCode.ScrollLock }, + { Key.Pause, KeyScanCode.Pause }, + + { Key.Insert, KeyScanCode.Insert }, + { Key.Home, KeyScanCode.Home }, + { Key.PageUp, KeyScanCode.PageUp }, + { Key.Delete, KeyScanCode.Delete }, + { Key.End, KeyScanCode.End }, + { Key.PageDown, KeyScanCode.PageDown }, + + { Key.Up, KeyScanCode.Up }, + { Key.Down, KeyScanCode.Down }, + { Key.Left, KeyScanCode.Left }, + { Key.Right, KeyScanCode.Right }, + + { Key.NumLock, KeyScanCode.NumLock }, + { Key.NumPad0, KeyScanCode.Keypad0 }, + { Key.NumPad1, KeyScanCode.Keypad1 }, + { Key.NumPad2, KeyScanCode.Keypad2 }, + { Key.NumPad3, KeyScanCode.Keypad3 }, + { Key.NumPad4, KeyScanCode.Keypad4 }, + { Key.NumPad5, KeyScanCode.Keypad5 }, + { Key.NumPad6, KeyScanCode.Keypad6 }, + { Key.NumPad7, KeyScanCode.Keypad7 }, + { Key.NumPad8, KeyScanCode.Keypad8 }, + { Key.NumPad9, KeyScanCode.Keypad9 }, + { Key.NumPadDivide, KeyScanCode.KeypadDivide }, + { Key.NumPadMultiply, KeyScanCode.KeypadMultiply }, + { Key.NumPadSubtract, KeyScanCode.KeypadMinus }, + { Key.NumPadAdd, KeyScanCode.KeypadPlus }, + { Key.NumPadDecimal, KeyScanCode.KeypadComma }, + { Key.NumPadEnter, KeyScanCode.KeypadEnter }, + }; + } +} diff --git a/src/UI/VideoAnalyzer/Events/XWTEventSource.cs b/src/UI/VideoAnalyzer/Events/XWTEventSource.cs index c5ee018c1..c16717f43 100644 --- a/src/UI/VideoAnalyzer/Events/XWTEventSource.cs +++ b/src/UI/VideoAnalyzer/Events/XWTEventSource.cs @@ -40,11 +40,13 @@ private void HandleKeyReleased(object sender, KeyEventArgs e) var vks = VkKeyScanEx((char)e.Key, keyboardLayout); var vsc = MapVirtualKeyEx((uint)vks & 0xff, MAPVK_VK_TO_VSC, keyboardLayout); var key = WPFToKeyScanCodeConverter.Instance.GetScanCode((int)vsc, e.Key); +#elif PLATFORM_OSX + var key = OSXToKeyScanCodeConverter.Instance.GetScanCode(e.Key); #else var entryKey = Gdk.Keymap.Default.GetEntriesForKeyval((uint)e.Key)[0].Keycode; var key = X11ToKeyScanCodeConverter.Instance.GetScanCode((int)entryKey); -#endif // !PLATFORM_WINDOWS +#endif // !(PLATFORM_WINDOWS || PLATFORM_OSX) if(key != null) { handler.KeyReleased(key.Value); @@ -63,11 +65,13 @@ private void HandleKeyPressed(object sender, KeyEventArgs e) var vks = VkKeyScanEx((char)e.Key, keyboardLayout); var vsc = MapVirtualKeyEx((uint)vks & 0xff, MAPVK_VK_TO_VSC, keyboardLayout); var key = WPFToKeyScanCodeConverter.Instance.GetScanCode((int)vsc, e.Key); +#elif PLATFORM_OSX + var key = OSXToKeyScanCodeConverter.Instance.GetScanCode(e.Key); #else var entryKey = Gdk.Keymap.Default.GetEntriesForKeyval((uint)e.Key)[0].Keycode; var key = X11ToKeyScanCodeConverter.Instance.GetScanCode((int)entryKey); -#endif // !PLATFORM_WINDOWS +#endif // !(PLATFORM_WINDOWS || PLATFORM_OSX) if(key != null) { handler.KeyPressed(key.Value);