From c9dd3cd926577b975e54385428f184d171a02f71 Mon Sep 17 00:00:00 2001 From: Marc Brooks Date: Thu, 15 May 2025 10:05:53 -0500 Subject: [PATCH] feat(ui): Enhance Virtual Keyboard for US (#449) * feat(ui): Add Ctrl+Alt-Backspace combination key to Virtual Keyboard Fixes #445 (somewhat) * fix(ui): Correct virtual keyboard display when shift key is down. Somewhere along the way, the handling of the shift-key state for letters and numbers was lost and we stopped displaying the capital/symbol for the key. Also update page up and page down to have the space in the on-screen key. * feat(ui): Add missing keys for virtual keyboard Enable insert, delete, numpad equal, print scree, scroll lock, pause, system request, break keys. --- ui/src/components/VirtualKeyboard.tsx | 43 +++++++++++------------ ui/src/keyboardMappings.ts | 49 +++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 24 deletions(-) diff --git a/ui/src/components/VirtualKeyboard.tsx b/ui/src/components/VirtualKeyboard.tsx index 09a94a6..03cb331 100644 --- a/ui/src/components/VirtualKeyboard.tsx +++ b/ui/src/components/VirtualKeyboard.tsx @@ -143,6 +143,16 @@ function KeyboardWrapper() { return; } + if (key === "CtrlAltBackspace") { + sendKeyboardEvent( + [keys["Backspace"]], + [modifiers["ControlLeft"], modifiers["AltLeft"]], + ); + + setTimeout(resetKeyboardState, 100); + return; + } + if (isKeyShift || isKeyCaps) { toggleLayout(); @@ -257,13 +267,13 @@ function KeyboardWrapper() { buttonTheme={[ { class: "combination-key", - buttons: "CtrlAltDelete AltMetaEscape", + buttons: "CtrlAltDelete AltMetaEscape CtrlAltBackspace", }, ]} display={keyDisplayMap} layout={{ default: [ - "CtrlAltDelete AltMetaEscape", + "CtrlAltDelete AltMetaEscape CtrlAltBackspace", "Escape F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12", "Backquote Digit1 Digit2 Digit3 Digit4 Digit5 Digit6 Digit7 Digit8 Digit9 Digit0 Minus Equal Backspace", "Tab KeyQ KeyW KeyE KeyR KeyT KeyY KeyU KeyI KeyO KeyP BracketLeft BracketRight Backslash", @@ -272,7 +282,7 @@ function KeyboardWrapper() { "ControlLeft AltLeft MetaLeft Space MetaRight AltRight", ], shift: [ - "CtrlAltDelete AltMetaEscape", + "CtrlAltDelete AltMetaEscape CtrlAltBackspace", "Escape F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12", "(Backquote) (Digit1) (Digit2) (Digit3) (Digit4) (Digit5) (Digit6) (Digit7) (Digit8) (Digit9) (Digit0) (Minus) (Equal) (Backspace)", "Tab (KeyQ) (KeyW) (KeyE) (KeyR) (KeyT) (KeyY) (KeyU) (KeyI) (KeyO) (KeyP) (BracketLeft) (BracketRight) (Backslash)", @@ -282,7 +292,7 @@ function KeyboardWrapper() { ], }} disableButtonHold={true} - mergeDisplay={true} + syncInstanceInputs={true} debug={false} /> @@ -290,34 +300,25 @@ function KeyboardWrapper() { diff --git a/ui/src/keyboardMappings.ts b/ui/src/keyboardMappings.ts index 79ed11a..2c770b7 100644 --- a/ui/src/keyboardMappings.ts +++ b/ui/src/keyboardMappings.ts @@ -86,16 +86,21 @@ export const keys = { NumpadAdd: 0x57, NumpadDivide: 0x54, NumpadEnter: 0x58, + NumpadEqual: 0x67, NumpadMultiply: 0x55, NumpadSubtract: 0x56, NumpadDecimal: 0x63, PageDown: 0x4e, PageUp: 0x4b, Period: 0x37, + PrintScreen: 0x46, + Pause: 0x48, Quote: 0x34, + ScrollLock: 0x47, Semicolon: 0x33, Slash: 0x38, Space: 0x2c, + SystemRequest: 0x9a, Tab: 0x2b, } as Record; @@ -200,6 +205,13 @@ export const chars = { "\n": { key: "Enter", shift: false }, Enter: { key: "Enter", shift: false }, Tab: { key: "Tab", shift: false }, + PrintScreen: { key: "Prt Sc", shift: false }, + SystemRequest: { key: "Prt Sc", shift: true }, + ScrollLock: { key: "ScrollLock", shift: false}, + Pause: { key: "Pause", shift: false }, + Break: { key: "Pause", shift: true }, + Insert: { key: "Insert", shift: false }, + Delete: { key: "Delete", shift: false }, } as Record; export const modifiers = { @@ -227,6 +239,7 @@ export const modifierDisplayMap: Record = { export const keyDisplayMap: Record = { CtrlAltDelete: "Ctrl + Alt + Delete", AltMetaEscape: "Alt + Meta + Escape", + CtrlAltBackspace: "Ctrl + Alt + Backspace", Escape: "esc", Tab: "tab", Backspace: "backspace", @@ -240,11 +253,12 @@ export const keyDisplayMap: Record = { MetaLeft: "meta", MetaRight: "meta", Space: " ", + Insert: "insert", Home: "home", - PageUp: "pageup", + PageUp: "page up", Delete: "delete", End: "end", - PageDown: "pagedown", + PageDown: "page down", ArrowLeft: "←", ArrowRight: "→", ArrowUp: "↑", @@ -258,22 +272,45 @@ export const keyDisplayMap: Record = { KeyU: "u", KeyV: "v", KeyW: "w", KeyX: "x", KeyY: "y", KeyZ: "z", + // Capital letters + "(KeyA)": "A", "(KeyB)": "B", "(KeyC)": "C", "(KeyD)": "D", "(KeyE)": "E", + "(KeyF)": "F", "(KeyG)": "G", "(KeyH)": "H", "(KeyI)": "I", "(KeyJ)": "J", + "(KeyK)": "K", "(KeyL)": "L", "(KeyM)": "M", "(KeyN)": "N", "(KeyO)": "O", + "(KeyP)": "P", "(KeyQ)": "Q", "(KeyR)": "R", "(KeyS)": "S", "(KeyT)": "T", + "(KeyU)": "U", "(KeyV)": "V", "(KeyW)": "W", "(KeyX)": "X", "(KeyY)": "Y", + "(KeyZ)": "Z", + // Numbers Digit1: "1", Digit2: "2", Digit3: "3", Digit4: "4", Digit5: "5", Digit6: "6", Digit7: "7", Digit8: "8", Digit9: "9", Digit0: "0", + // Shifted Numbers + "(Digit1)": "!", "(Digit2)": "@", "(Digit3)": "#", "(Digit4)": "$", "(Digit5)": "%", + "(Digit6)": "^", "(Digit7)": "&", "(Digit8)": "*", "(Digit9)": "(", "(Digit0)": ")", + // Symbols Minus: "-", + "(Minus)": "_", Equal: "=", + "(Equal)": "+", BracketLeft: "[", + "(BracketLeft)": "{", BracketRight: "]", + "(BracketRight)": "}", Backslash: "\\", + "(Backslash)": "|", Semicolon: ";", + "(Semicolon)": ":", Quote: "'", + "(Quote)": "\"", Comma: ",", + "(Comma)": "<", Period: ".", + "(Period)": ">", Slash: "/", + "(Slash)": "?", Backquote: "`", + "(Backquote)": "~", IntlBackslash: "\\", // Function keys @@ -287,5 +324,11 @@ export const keyDisplayMap: Record = { Numpad6: "Num 6", Numpad7: "Num 7", Numpad8: "Num 8", Numpad9: "Num 9", NumpadAdd: "Num +", NumpadSubtract: "Num -", NumpadMultiply: "Num *", NumpadDivide: "Num /", NumpadDecimal: "Num .", - NumpadEnter: "Num Enter" + NumpadEqual: "Num =", NumpadEnter: "Num Enter", + NumLock: "Num Lock", + + // Modals + PrintScreen: "prt sc", ScrollLock: "scr lk", Pause: "pause", + "(PrintScreen)": "sys rq", "(Pause)": "break", + SystemRequest: "sys rq", Break: "break" };