diff --git a/config.go b/config.go index 23d4c84..86c64e5 100644 --- a/config.go +++ b/config.go @@ -87,6 +87,7 @@ type Config struct { LocalAuthMode string `json:"localAuthMode"` //TODO: fix it with migration WakeOnLanDevices []WakeOnLanDevice `json:"wake_on_lan_devices"` KeyboardMacros []KeyboardMacro `json:"keyboard_macros"` + KeyboardLayout string `json:"keyboard_layout"` EdidString string `json:"hdmi_edid_string"` ActiveExtension string `json:"active_extension"` DisplayMaxBrightness int `json:"display_max_brightness"` @@ -107,6 +108,7 @@ var defaultConfig = &Config{ AutoUpdateEnabled: true, // Set a default value ActiveExtension: "", KeyboardMacros: []KeyboardMacro{}, + KeyboardLayout: "en_US", DisplayMaxBrightness: 64, DisplayDimAfterSec: 120, // 2 minutes DisplayOffAfterSec: 1800, // 30 minutes diff --git a/jsonrpc.go b/jsonrpc.go index d35f635..13280d9 100644 --- a/jsonrpc.go +++ b/jsonrpc.go @@ -863,6 +863,18 @@ func rpcSetScrollSensitivity(sensitivity string) error { return nil } +func rpcGetKeyboardLayout() (string, error) { + return config.KeyboardLayout, nil +} + +func rpcSetKeyboardLayout(layout string) error { + config.KeyboardLayout = layout + if err := SaveConfig(); err != nil { + return fmt.Errorf("failed to save config: %w", err) + } + return nil +} + func getKeyboardMacros() (interface{}, error) { macros := make([]KeyboardMacro, len(config.KeyboardMacros)) copy(macros, config.KeyboardMacros) @@ -1028,6 +1040,8 @@ var rpcHandlers = map[string]RPCHandler{ "setCloudUrl": {Func: rpcSetCloudUrl, Params: []string{"apiUrl", "appUrl"}}, "getScrollSensitivity": {Func: rpcGetScrollSensitivity}, "setScrollSensitivity": {Func: rpcSetScrollSensitivity, Params: []string{"sensitivity"}}, + "getKeyboardLayout": {Func: rpcGetKeyboardLayout}, + "setKeyboardLayout": {Func: rpcSetKeyboardLayout, Params: []string{"layout"}}, "getKeyboardMacros": {Func: getKeyboardMacros}, "setKeyboardMacros": {Func: setKeyboardMacros, Params: []string{"params"}}, } diff --git a/ui/src/components/popovers/PasteModal.tsx b/ui/src/components/popovers/PasteModal.tsx index 643f55b..d557306 100644 --- a/ui/src/components/popovers/PasteModal.tsx +++ b/ui/src/components/popovers/PasteModal.tsx @@ -8,14 +8,21 @@ import { GridCard } from "@components/Card"; import { TextAreaWithLabel } from "@components/TextArea"; import { SettingsPageHeader } from "@components/SettingsPageheader"; import { useJsonRpc } from "@/hooks/useJsonRpc"; -import { useHidStore, useRTCStore, useUiStore } from "@/hooks/stores"; -import { chars, keys, modifiers } from "@/keyboardMappings"; +import { useHidStore, useRTCStore, useUiStore, useDeviceSettingsStore } from "@/hooks/stores"; +import { keys, modifiers } from "@/keyboardMappings"; +import { layouts, chars } from "@/keyboardLayouts"; import notifications from "@/notifications"; const hidKeyboardPayload = (keys: number[], modifier: number) => { return { keys, modifier }; }; +const modifierCode = (shift?: boolean, altRight?: boolean) => { + return (shift ? modifiers["ShiftLeft"] : 0) + | (altRight ? modifiers["AltRight"] : 0) +} +const noModifier = 0 + export default function PasteModal() { const TextAreaRef = useRef(null); const setPasteMode = useHidStore(state => state.setPasteModeEnabled); @@ -27,6 +34,18 @@ export default function PasteModal() { const [invalidChars, setInvalidChars] = useState([]); const close = useClose(); + const keyboardLayout = useDeviceSettingsStore(state => state.keyboardLayout); + const setKeyboardLayout = useDeviceSettingsStore( + state => state.setKeyboardLayout, + ); + + useEffect(() => { + send("getKeyboardLayout", {}, resp => { + if ("error" in resp) return; + setKeyboardLayout(resp.result as string); + }); + }, []); + const onCancelPasteMode = useCallback(() => { setPasteMode(false); setDisableVideoFocusTrap(false); @@ -37,27 +56,43 @@ export default function PasteModal() { setPasteMode(false); setDisableVideoFocusTrap(false); if (rpcDataChannel?.readyState !== "open" || !TextAreaRef.current) return; + if (!keyboardLayout) return; + if (!chars[keyboardLayout]) return; const text = TextAreaRef.current.value; try { for (const char of text) { - const { key, shift } = chars[char] ?? {}; + const { key, shift, altRight, deadKey, accentKey } = chars[keyboardLayout][char] if (!key) continue; - await new Promise((resolve, reject) => { - send( - "keyboardReport", - hidKeyboardPayload([keys[key]], shift ? modifiers["ShiftLeft"] : 0), - params => { - if ("error" in params) return reject(params.error); - send("keyboardReport", hidKeyboardPayload([], 0), params => { + const keyz = [ keys[key] ]; + const modz = [ modifierCode(shift, altRight) ]; + + if (deadKey) { + keyz.push(keys["Space"]); + modz.push(noModifier); + } + if (accentKey) { + keyz.unshift(keys[accentKey.key]) + modz.unshift(modifierCode(accentKey.shift, accentKey.altRight)) + } + + for (const [index, kei] of keyz.entries()) { + await new Promise((resolve, reject) => { + send( + "keyboardReport", + hidKeyboardPayload([kei], modz[index]), + params => { if ("error" in params) return reject(params.error); - resolve(); - }); - }, - ); - }); + send("keyboardReport", hidKeyboardPayload([], 0), params => { + if ("error" in params) return reject(params.error); + resolve(); + }); + }, + ); + }); + } } } catch (error) { console.error(error); @@ -113,7 +148,7 @@ export default function PasteModal() { // @ts-expect-error TS doesn't recognize Intl.Segmenter in some environments [...new Intl.Segmenter().segment(value)] .map(x => x.segment) - .filter(char => !chars[char]), + .filter(char => !chars[keyboardLayout][char]), ), ]; @@ -132,6 +167,11 @@ export default function PasteModal() { )} +
+

+ Sending key codes using keyboard layout {layouts[keyboardLayout]} +

+
diff --git a/ui/src/hooks/stores.ts b/ui/src/hooks/stores.ts index db1fd04..14b8bb1 100644 --- a/ui/src/hooks/stores.ts +++ b/ui/src/hooks/stores.ts @@ -336,6 +336,8 @@ export interface DeviceSettingsState { trackpadThreshold: number; scrollSensitivity: "low" | "default" | "high"; setScrollSensitivity: (sensitivity: DeviceSettingsState["scrollSensitivity"]) => void; + keyboardLayout: string; + setKeyboardLayout: (layout: string) => void; } export const useDeviceSettingsStore = create(set => ({ @@ -397,6 +399,9 @@ export const useDeviceSettingsStore = create(set => ({ scrollSensitivity: sensitivity, }); }, + + keyboardLayout: "en_US", + setKeyboardLayout: layout => set({ keyboardLayout: layout }), })); export interface RemoteVirtualMediaState { @@ -893,4 +898,4 @@ export const useMacrosStore = create((set, get) => ({ set({ loading: false }); } } -})); \ No newline at end of file +})); diff --git a/ui/src/keyboardLayouts.ts b/ui/src/keyboardLayouts.ts new file mode 100644 index 0000000..8dc0dec --- /dev/null +++ b/ui/src/keyboardLayouts.ts @@ -0,0 +1,42 @@ +import { chars as chars_cs_CZ, name as name_cs_CZ } from "@/keyboardLayouts/cs_CZ" +import { chars as chars_en_UK, name as name_en_UK } from "@/keyboardLayouts/en_UK" +import { chars as chars_en_US, name as name_en_US } from "@/keyboardLayouts/en_US" +import { chars as chars_fr_FR, name as name_fr_FR } from "@/keyboardLayouts/fr_FR" +import { chars as chars_de_DE, name as name_de_DE } from "@/keyboardLayouts/de_DE" +import { chars as chars_it_IT, name as name_it_IT } from "@/keyboardLayouts/it_IT" +import { chars as chars_nb_NO, name as name_nb_NO } from "@/keyboardLayouts/nb_NO" +import { chars as chars_es_ES, name as name_es_ES } from "@/keyboardLayouts/es_ES" +import { chars as chars_sv_SE, name as name_sv_SE } from "@/keyboardLayouts/sv_SE" +import { chars as chars_fr_CH, name as name_fr_CH } from "@/keyboardLayouts/fr_CH" +import { chars as chars_de_CH, name as name_de_CH } from "@/keyboardLayouts/de_CH" + +type KeyInfo = { key: string | number; shift?: boolean, altRight?: boolean } +export type KeyCombo = KeyInfo & { deadKey?: boolean, accentKey?: KeyInfo } + +export const layouts: Record = { + cs_CZ: name_cs_CZ, + en_UK: name_en_UK, + en_US: name_en_US, + fr_FR: name_fr_FR, + de_DE: name_de_DE, + it_IT: name_it_IT, + nb_NO: name_nb_NO, + es_ES: name_es_ES, + sv_SE: name_sv_SE, + fr_CH: name_fr_CH, + de_CH: name_de_CH, +} + +export const chars: Record> = { + cs_CZ: chars_cs_CZ, + en_UK: chars_en_UK, + en_US: chars_en_US, + fr_FR: chars_fr_FR, + de_DE: chars_de_DE, + it_IT: chars_it_IT, + nb_NO: chars_nb_NO, + es_ES: chars_es_ES, + sv_SE: chars_sv_SE, + fr_CH: chars_fr_CH, + de_CH: chars_de_CH, +}; diff --git a/ui/src/keyboardLayouts/cs_CZ.ts b/ui/src/keyboardLayouts/cs_CZ.ts new file mode 100644 index 0000000..ee2799c --- /dev/null +++ b/ui/src/keyboardLayouts/cs_CZ.ts @@ -0,0 +1,244 @@ +import { KeyCombo } from "../keyboardLayouts" + +export const name = "Czech"; + +const keyTrema = { key: "Backslash" } // tréma (umlaut), two dots placed above a vowel +const keyAcute = { key: "Equal" } // accent aigu (acute accent), mark ´ placed above the letter +const keyHat = { key: "Digit3", shift: true, altRight: true } // accent circonflexe (accent hat), mark ^ placed above the letter +const keyCaron = { key: "Equal", shift: true } // caron or haček (inverted hat), mark ˇ placed above the letter +const keyGrave = { key: "Digit7", shift: true, altRight: true } // accent grave, mark ` placed above the letter +const keyTilde = { key: "Digit1", shift: true, altRight: true } // tilde, mark ~ placed above the letter +const keyRing = { key: "Backquote", shift: true } // kroužek (little ring), mark ° placed above the letter +const keyOverdot = { key: "Digit8", shift: true, altRight: true } // overdot (dot above), mark ˙ placed above the letter +const keyHook = { key: "Digit6", shift: true, altRight: true } // ogonoek (little hook), mark ˛ placed beneath a letter +const keyCedille = { key: "Equal", shift: true, altRight: true } // accent cedille (cedilla), mark ¸ placed beneath a letter + +export const chars = { + A: { key: "KeyA", shift: true }, + "Ä": { key: "KeyA", shift: true, accentKey: keyTrema }, + "Á": { key: "KeyA", shift: true, accentKey: keyAcute }, + "Â": { key: "KeyA", shift: true, accentKey: keyHat }, + "À": { key: "KeyA", shift: true, accentKey: keyGrave }, + "Ã": { key: "KeyA", shift: true, accentKey: keyTilde }, + "Ȧ": { key: "KeyA", shift: true, accentKey: keyOverdot }, + "Ą": { key: "KeyA", shift: true, accentKey: keyHook }, + B: { key: "KeyB", shift: true }, + "Ḃ": { key: "KeyB", shift: true, accentKEy: keyOverdot }, + C: { key: "KeyC", shift: true }, + "Č": { key: "KeyC", shift: true, accentKey: keyCaron }, + "Ċ": { key: "KeyC", shift: true, accentKey: keyOverdot }, + "Ç": { key: "KeyC", shift: true, accentKey: keyCedille }, + D: { key: "KeyD", shift: true }, + "Ď": { key: "KeyD", shift: true, accentKey: keyCaron }, + "Ḋ": { key: "KeyD", shift: true, accentKey: keyOverdot }, + E: { key: "KeyE", shift: true }, + "Ë": { key: "KeyE", shift: true, accentKey: keyTrema }, + "É": { key: "KeyE", shift: true, accentKey: keyAcute }, + "Ê": { key: "KeyE", shift: true, accentKey: keyHat }, + "Ě": { key: "KeyE", shift: true, accentKey: keyCaron }, + "È": { key: "KeyE", shift: true, accentKey: keyGrave }, + "Ẽ": { key: "KeyE", shift: true, accentKey: keyTilde }, + "Ė": { key: "KeyE", shift: true, accentKEy: keyOverdot }, + "Ę": { key: "KeyE", shift: true, accentKey: keyHook }, + F: { key: "KeyF", shift: true }, + "Ḟ": { key: "KeyF", shift: true, accentKey: keyOverdot }, + G: { key: "KeyG", shift: true }, + "Ġ": { key: "KeyG", shift: true, accentKey: keyOverdot }, + H: { key: "KeyH", shift: true }, + "Ḣ": { key: "KeyH", shift: true, accentKey: keyOverdot }, + I: { key: "KeyI", shift: true }, + "Ï": { key: "KeyI", shift: true, accentKey: keyTrema }, + "Í": { key: "KeyI", shift: true, accentKey: keyAcute }, + "Î": { key: "KeyI", shift: true, accentKey: keyHat }, + "Ì": { key: "KeyI", shift: true, accentKey: keyGrave }, + "Ĩ": { key: "KeyI", shift: true, accentKey: keyTilde }, + "İ": { key: "KeyI", shift: true, accentKey: keyOverdot }, + "Į": { key: "KeyI", shift: true, accentKey: keyHook }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + "Ŀ": { key: "KeyL", shift: true }, + M: { key: "KeyM", shift: true }, + "Ṁ": { key: "KeyM", shift: true }, + N: { key: "KeyN", shift: true }, + "Ň": { key: "KeyN", shift: true, accentKey: keyCaron }, + "Ñ": { key: "KeyN", shift: true, accentKey: keyTilde }, + "Ṅ": { key: "KeyN", shift: true, accentKEy: keyOverdot }, + O: { key: "KeyO", shift: true }, + "Ö": { key: "KeyO", shift: true, accentKey: keyTrema }, + "Ó": { key: "KeyO", shift: true, accentKey: keyAcute }, + "Ô": { key: "KeyO", shift: true, accentKey: keyHat }, + "Ò": { key: "KeyO", shift: true, accentKey: keyGrave }, + "Õ": { key: "KeyO", shift: true, accentKey: keyTilde }, + "Ȯ": { key: "KeyO", shift: true, accentKey: keyOverdot }, + "Ǫ": { key: "KeyO", shift: true, accentKey: keyHook }, + P: { key: "KeyP", shift: true }, + "Ṗ": { key: "KeyP", shift: true, accentKey: keyOverdot }, + Q: { key: "KeyQ", shift: true }, + R: { key: "KeyR", shift: true }, + "Ř": { key: "KeyR", shift: true, accentKey: keyCaron }, + "Ṙ": { key: "KeyR", shift: true, accentKey: keyOverdot }, + S: { key: "KeyS", shift: true }, + "Š": { key: "KeyS", shift: true, accentKey: keyCaron }, + "Ṡ": { key: "KeyS", shift: true, accentKey: keyOverdot }, + T: { key: "KeyT", shift: true }, + "Ť": { key: "KeyT", shift: true, accentKey: keyCaron }, + "Ṫ": { key: "KeyT", shift: true, accentKey: keyOverdot }, + U: { key: "KeyU", shift: true }, + "Ü": { key: "KeyU", shift: true, accentKey: keyTrema }, + "Ú": { key: "KeyU", shift: true, accentKey: keyAcute }, + "Û": { key: "KeyU", shift: true, accentKey: keyHat }, + "Ù": { key: "KeyU", shift: true, accentKey: keyGrave }, + "Ũ": { key: "KeyU", shift: true, accentKey: keyTilde }, + "Ů": { key: "KeyU", shift: true, accentKey: keyRing }, + "Ų": { key: "KeyU", shift: true, accentKey: keyHook }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyW", shift: true }, + "Ẇ": { key: "KeyW", shift: true, accentKey: keyOverdot }, + X: { key: "KeyX", shift: true }, + "Ẋ": { key: "KeyX", shift: true, accentKey: keyOverdot }, + Y: { key: "KeyY", shift: true }, + "Ý": { key: "KeyY", shift: true, accentKey: keyAcute }, + "Ẏ": { key: "KeyY", shift: true, accentKey: keyOverdot }, + Z: { key: "KeyZ", shift: true }, + "Ż": { key: "KeyZ", shift: true, accentKey: keyOverdot }, + a: { key: "KeyA" }, + "ä": { key: "KeyA", accentKey: keyTrema }, + "â": { key: "KeyA", accentKey: keyHat }, + "à": { key: "KeyA", accentKey: keyGrave }, + "ã": { key: "KeyA", accentKey: keyTilde }, + "ȧ": { key: "KeyA", accentKey: keyOverdot }, + "ą": { key: "KeyA", accentKey: keyHook }, + b: { key: "KeyB" }, + "{": { key: "KeyB", altRight: true }, + "ḃ": { key: "KeyB", accentKey: keyOverdot }, + c: { key: "KeyC" }, + "&": { key: "KeyC", altRight: true }, + "ç": { key: "KeyC", accentKey: keyCedille }, + "ċ": { key: "KeyC", accentKey: keyOverdot }, + d: { key: "KeyD" }, + "ď": { key: "KeyD", accentKey: keyCaron }, + "ḋ": { key: "KeyD", accentKey: keyOverdot }, + "Đ": { key: "KeyD", altRight: true }, + e: { key: "KeyE" }, + "ë": { key: "KeyE", accentKey: keyTrema }, + "ê": { key: "KeyE", accentKey: keyHat }, + "ẽ": { key: "KeyE", accentKey: keyTilde }, + "è": { key: "KeyE", accentKey: keyGrave }, + "ė": { key: "KeyE", accentKey: keyOverdot }, + "ę": { key: "KeyE", accentKey: keyHook }, + "€": { key: "KeyE", altRight: true }, + f: { key: "KeyF" }, + "ḟ": { key: "KeyF", accentKey: keyOverdot }, + "[": { key: "KeyF", altRight: true }, + g: { key: "KeyG" }, + "ġ": { key: "KeyG", accentKey: keyOverdot }, + "]": { key: "KeyF", altRight: true }, + h: { key: "KeyH" }, + "ḣ": { key: "KeyH", accentKey: keyOverdot }, + i: { key: "KeyI" }, + "ï": { key: "KeyI", accentKey: keyTrema }, + "î": { key: "KeyI", accentKey: keyHat }, + "ì": { key: "KeyI", accentKey: keyGrave }, + "ĩ": { key: "KeyI", accentKey: keyTilde }, + "ı": { key: "KeyI", accentKey: keyOverdot }, + "į": { key: "KeyI", accentKey: keyHook }, + j: { key: "KeyJ" }, + "ȷ": { key: "KeyJ", accentKey: keyOverdot }, + k: { key: "KeyK" }, + "ł": { key: "KeyK", altRight: true }, + l: { key: "KeyL" }, + "ŀ": { key: "KeyL", accentKey: keyOverdot }, + "Ł": { key: "KeyL", altRight: true }, + m: { key: "KeyM" }, + "ṁ": { key: "KeyM", accentKey: keyOverdot }, + n: { key: "KeyN" }, + "}": { key: "KeyN", altRight: true }, + "ň": { key: "KeyN", accentKey: keyCaron }, + "ñ": { key: "KeyN", accentKey: keyTilde }, + "ṅ": { key: "KeyN", accentKey: keyOverdot }, + o: { key: "KeyO" }, + "ö": { key: "Key0", accentKey: keyTrema }, + "ó": { key: "KeyO", accentKey: keyAcute }, + "ô": { key: "KeyO", accentKey: keyHat }, + "ò": { key: "KeyO", accentKey: keyGrave }, + "õ": { key: "KeyO", accentKey: keyTilde }, + "ȯ": { key: "KeyO", accentKey: keyOverdot }, + "ǫ": { key: "KeyO", accentKey: keyHook }, + p: { key: "KeyP" }, + "ṗ": { key: "KeyP", accentKey: keyOverdot }, + q: { key: "KeyQ" }, + r: { key: "KeyR" }, + "ṙ": { key: "KeyR", accentKey: keyOverdot }, + s: { key: "KeyS" }, + "ṡ": { key: "KeyS", accentKey: keyOverdot }, + "đ": { key: "KeyS", altRight: true }, + t: { key: "KeyT" }, + "ť": { key: "KeyT", accentKey: keyCaron }, + "ṫ": { key: "KeyT", accentKey: keyOverdot }, + u: { key: "KeyU" }, + "ü": { key: "KeyU", accentKey: keyTrema }, + "û": { key: "KeyU", accentKey: keyHat }, + "ù": { key: "KeyU", accentKey: keyGrave }, + "ũ": { key: "KeyU", accentKey: keyTilde }, + "ų": { key: "KeyU", accentKey: keyHook }, + v: { key: "KeyV" }, + "@": { key: "KeyV", altRight: true }, + w: { key: "KeyW" }, + "ẇ": { key: "KeyW", accentKey: keyOverdot }, + x: { key: "KeyX" }, + "#": { key: "KeyX", altRight: true }, + "ẋ": { key: "KeyX", accentKey: keyOverdot }, + y: { key: "KeyY" }, + "ẏ": { key: "KeyY", accentKey: keyOverdot }, + z: { key: "KeyZ" }, + "ż": { key: "KeyZ", accentKey: keyOverdot }, + ";": { key: "Backquote" }, + "°": { key: "Backquote", shift: true, deadKey: true }, + "+": { key: "Digit1" }, + 1: { key: "Digit1", shift: true }, + "ě": { key: "Digit2" }, + 2: { key: "Digit2", shift: true }, + "š": { key: "Digit3" }, + 3: { key: "Digit3", shift: true }, + "č": { key: "Digit4" }, + 4: { key: "Digit4", shift: true }, + "ř": { key: "Digit5" }, + 5: { key: "Digit5", shift: true }, + "ž": { key: "Digit6" }, + 6: { key: "Digit6", shift: true }, + "ý": { key: "Digit7" }, + 7: { key: "Digit7", shift: true }, + "á": { key: "Digit8" }, + 8: { key: "Digit8", shift: true }, + "í": { key: "Digit9" }, + 9: { key: "Digit9", shift: true }, + "é": { key: "Digit0" }, + 0: { key: "Digit0", shift: true }, + "=": { key: "Minus" }, + "%": { key: "Minus", shift: true }, + "ú": { key: "BracketLeft" }, + "/": { key: "BracketLeft", shift: true }, + ")": { key: "BracketRight" }, + "(": { key: "BracketRight", shift: true }, + "ů": { key: "Semicolon" }, + "\"": { key: "Semicolon", shift: true }, + "§": { key: "Quote" }, + "!": { key: "Quote", shift: true }, + "'": { key: "Backslash", shift: true }, + ",": { key: "Comma" }, + "?": { key: "Comma", shift: true }, + "<": { key: "Comma", altRight: true }, + ".": { key: "Period" }, + ":": { key: "Period", shift: true }, + ">": { key: "Period", altRight: true }, + "-": { key: "Slash" }, + "_": { key: "Slash", shift: true }, + "*": { key: "Slash", altRight: true }, + "\\": { key: "IntlBackslash" }, + "|": { key: "IntlBackslash", shift: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record; diff --git a/ui/src/keyboardLayouts/de_CH.ts b/ui/src/keyboardLayouts/de_CH.ts new file mode 100644 index 0000000..c3f1f8c --- /dev/null +++ b/ui/src/keyboardLayouts/de_CH.ts @@ -0,0 +1,165 @@ +import { KeyCombo } from "../keyboardLayouts" + +export const name = "Swiss German"; + +const keyTrema = { key: "BracketRight" } // tréma (umlaut), two dots placed above a vowel +const keyAcute = { key: "Minus", altRight: true } // accent aigu (acute accent), mark ´ placed above the letter +const keyHat = { key: "Equal" } // accent circonflexe (accent hat), mark ^ placed above the letter +const keyGrave = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter +const keyTilde = { key: "Equal", altRight: true } // tilde, mark ~ placed above the letter + +export const chars = { + A: { key: "KeyA", shift: true }, + "Ä": { key: "KeyA", shift: true, accentKey: keyTrema }, + "Á": { key: "KeyA", shift: true, accentKey: keyAcute }, + "Â": { key: "KeyA", shift: true, accentKey: keyHat }, + "À": { key: "KeyA", shift: true, accentKey: keyGrave }, + "Ã": { key: "KeyA", shift: true, accentKey: keyTilde }, + B: { key: "KeyB", shift: true }, + C: { key: "KeyC", shift: true }, + D: { key: "KeyD", shift: true }, + E: { key: "KeyE", shift: true }, + "Ë": { key: "KeyE", shift: true, accentKey: keyTrema }, + "É": { key: "KeyE", shift: true, accentKey: keyAcute }, + "Ê": { key: "KeyE", shift: true, accentKey: keyHat }, + "È": { key: "KeyE", shift: true, accentKey: keyGrave }, + "Ẽ": { key: "KeyE", shift: true, accentKey: keyTilde }, + F: { key: "KeyF", shift: true }, + G: { key: "KeyG", shift: true }, + H: { key: "KeyH", shift: true }, + I: { key: "KeyI", shift: true }, + "Ï": { key: "KeyI", shift: true, accentKey: keyTrema }, + "Í": { key: "KeyI", shift: true, accentKey: keyAcute }, + "Î": { key: "KeyI", shift: true, accentKey: keyHat }, + "Ì": { key: "KeyI", shift: true, accentKey: keyGrave }, + "Ĩ": { key: "KeyI", shift: true, accentKey: keyTilde }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + M: { key: "KeyM", shift: true }, + N: { key: "KeyN", shift: true }, + O: { key: "KeyO", shift: true }, + "Ö": { key: "KeyO", shift: true, accentKey: keyTrema }, + "Ó": { key: "KeyO", shift: true, accentKey: keyAcute }, + "Ô": { key: "KeyO", shift: true, accentKey: keyHat }, + "Ò": { key: "KeyO", shift: true, accentKey: keyGrave }, + "Õ": { key: "KeyO", shift: true, accentKey: keyTilde }, + P: { key: "KeyP", shift: true }, + Q: { key: "KeyQ", shift: true }, + R: { key: "KeyR", shift: true }, + S: { key: "KeyS", shift: true }, + T: { key: "KeyT", shift: true }, + U: { key: "KeyU", shift: true }, + "Ü": { key: "KeyU", shift: true, accentKey: keyTrema }, + "Ú": { key: "KeyU", shift: true, accentKey: keyAcute }, + "Û": { key: "KeyU", shift: true, accentKey: keyHat }, + "Ù": { key: "KeyU", shift: true, accentKey: keyGrave }, + "Ũ": { key: "KeyU", shift: true, accentKey: keyTilde }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyW", shift: true }, + X: { key: "KeyX", shift: true }, + Y: { key: "KeyZ", shift: true }, + Z: { key: "KeyY", shift: true }, + a: { key: "KeyA" }, + "á": { key: "KeyA", accentKey: keyAcute }, + "â": { key: "KeyA", accentKey: keyHat }, + "ã": { key: "KeyA", accentKey: keyTilde }, + b: { key: "KeyB" }, + c: { key: "KeyC" }, + d: { key: "KeyD" }, + e: { key: "KeyE" }, + "ë": { key: "KeyE", accentKey: keyTrema }, + "ê": { key: "KeyE", accentKey: keyHat }, + "ẽ": { key: "KeyE", accentKey: keyTilde }, + "€": { key: "KeyE", altRight: true }, + f: { key: "KeyF" }, + g: { key: "KeyG" }, + h: { key: "KeyH" }, + i: { key: "KeyI" }, + "ï": { key: "KeyI", accentKey: keyTrema }, + "í": { key: "KeyI", accentKey: keyAcute }, + "î": { key: "KeyI", accentKey: keyHat }, + "ì": { key: "KeyI", accentKey: keyGrave }, + "ĩ": { key: "KeyI", accentKey: keyTilde }, + j: { key: "KeyJ" }, + k: { key: "KeyK" }, + l: { key: "KeyL" }, + m: { key: "KeyM" }, + n: { key: "KeyN" }, + o: { key: "KeyO" }, + "ó": { key: "KeyO", accentKey: keyAcute }, + "ô": { key: "KeyO", accentKey: keyHat }, + "ò": { key: "KeyO", accentKey: keyGrave }, + "õ": { key: "KeyO", accentKey: keyTilde }, + p: { key: "KeyP" }, + q: { key: "KeyQ" }, + r: { key: "KeyR" }, + s: { key: "KeyS" }, + t: { key: "KeyT" }, + u: { key: "KeyU" }, + "ú": { key: "KeyU", accentKey: keyAcute }, + "û": { key: "KeyU", accentKey: keyHat }, + "ù": { key: "KeyU", accentKey: keyGrave }, + "ũ": { key: "KeyU", accentKey: keyTilde }, + v: { key: "KeyV" }, + w: { key: "KeyW" }, + x: { key: "KeyX" }, + y: { key: "KeyZ" }, + z: { key: "KeyY" }, + "§": { key: "Backquote" }, + "°": { key: "Backquote", shift: true }, + 1: { key: "Digit1" }, + "+": { key: "Digit1", shift: true }, + "|": { key: "Digit1", altRight: true }, + 2: { key: "Digit2" }, + "\"": { key: "Digit2", shift: true }, + "@": { key: "Digit2", altRight: true }, + 3: { key: "Digit3" }, + "*": { key: "Digit3", shift: true }, + "#": { key: "Digit3", altRight: true }, + 4: { key: "Digit4" }, + "ç": { key: "Digit4", shift: true }, + 5: { key: "Digit5" }, + "%": { key: "Digit5", shift: true }, + 6: { key: "Digit6" }, + "&": { key: "Digit6", shift: true }, + 7: { key: "Digit7" }, + "/": { key: "Digit7", shift: true }, + 8: { key: "Digit8" }, + "(": { key: "Digit8", shift: true }, + 9: { key: "Digit9" }, + ")": { key: "Digit9", shift: true }, + 0: { key: "Digit0" }, + "=": { key: "Digit0", shift: true }, + "'": { key: "Minus" }, + "?": { key: "Minus", shift: true }, + "^": { key: "Equal", deadKey: true }, + "`": { key: "Equal", shift: true }, + "~": { key: "Equal", altRight: true, deadKey: true }, + "ü": { key: "BracketLeft" }, + "è": { key: "BracketLeft", shift: true }, + "[": { key: "BracketLeft", altRight: true }, + "!": { key: "BracketRight", shift: true }, + "]": { key: "BracketRight", altRight: true }, + "ö": { key: "Semicolon" }, + "é": { key: "Semicolon", shift: true }, + "ä": { key: "Quote" }, + "à": { key: "Quote", shift: true }, + "{": { key: "Quote", altRight: true }, + "$": { key: "Backslash" }, + "£": { key: "Backslash", shift: true }, + "}": { key: "Backslash", altRight: true }, + ",": { key: "Comma" }, + ";": { key: "Comma", shift: true }, + ".": { key: "Period" }, + ":": { key: "Period", shift: true }, + "-": { key: "Slash" }, + "_": { key: "Slash", shift: true }, + "<": { key: "IntlBackslash" }, + ">": { key: "IntlBackslash", shift: true }, + "\\": { key: "IntlBackslash", altRight: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record; diff --git a/ui/src/keyboardLayouts/de_DE.ts b/ui/src/keyboardLayouts/de_DE.ts new file mode 100644 index 0000000..2833909 --- /dev/null +++ b/ui/src/keyboardLayouts/de_DE.ts @@ -0,0 +1,152 @@ +import { KeyCombo } from "../keyboardLayouts" + +export const name = "German"; + +const keyAcute = { key: "Equal" } // accent aigu (acute accent), mark ´ placed above the letter +const keyHat = { key: "Backquote" } // accent circonflexe (accent hat), mark ^ placed above the letter +const keyGrave = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter + +export const chars = { + A: { key: "KeyA", shift: true }, + "Á": { key: "KeyA", shift: true, accentKey: keyAcute }, + "Â": { key: "KeyA", shift: true, accentKey: keyHat }, + "À": { key: "KeyA", shift: true, accentKey: keyGrave }, + B: { key: "KeyB", shift: true }, + C: { key: "KeyC", shift: true }, + D: { key: "KeyD", shift: true }, + E: { key: "KeyE", shift: true }, + "É": { key: "KeyE", shift: true, accentKey: keyAcute }, + "Ê": { key: "KeyE", shift: true, accentKey: keyHat }, + "È": { key: "KeyE", shift: true, accentKey: keyGrave }, + F: { key: "KeyF", shift: true }, + G: { key: "KeyG", shift: true }, + H: { key: "KeyH", shift: true }, + I: { key: "KeyI", shift: true }, + "Í": { key: "KeyI", shift: true, accentKey: keyAcute }, + "Î": { key: "KeyI", shift: true, accentKey: keyHat }, + "Ì": { key: "KeyI", shift: true, accentKey: keyGrave }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + M: { key: "KeyM", shift: true }, + N: { key: "KeyN", shift: true }, + O: { key: "KeyO", shift: true }, + "Ó": { key: "KeyO", shift: true, accentKey: keyAcute }, + "Ô": { key: "KeyO", shift: true, accentKey: keyHat }, + "Ò": { key: "KeyO", shift: true, accentKey: keyGrave }, + P: { key: "KeyP", shift: true }, + Q: { key: "KeyQ", shift: true }, + R: { key: "KeyR", shift: true }, + S: { key: "KeyS", shift: true }, + T: { key: "KeyT", shift: true }, + U: { key: "KeyU", shift: true }, + "Ú": { key: "KeyU", shift: true, accentKey: keyAcute }, + "Û": { key: "KeyU", shift: true, accentKey: keyHat }, + "Ù": { key: "KeyU", shift: true, accentKey: keyGrave }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyW", shift: true }, + X: { key: "KeyX", shift: true }, + Y: { key: "KeyZ", shift: true }, + Z: { key: "KeyY", shift: true }, + a: { key: "KeyA" }, + "á": { key: "KeyA", accentKey: keyAcute }, + "â": { key: "KeyA", accentKey: keyHat }, + "à": { key: "KeyA", accentKey: keyGrave}, + b: { key: "KeyB" }, + c: { key: "KeyC" }, + d: { key: "KeyD" }, + e: { key: "KeyE" }, + "é": { key: "KeyE", accentKey: keyAcute}, + "ê": { key: "KeyE", accentKey: keyHat }, + "è": { key: "KeyE", accentKey: keyGrave }, + "€": { key: "KeyE", altRight: true }, + f: { key: "KeyF" }, + g: { key: "KeyG" }, + h: { key: "KeyH" }, + i: { key: "KeyI" }, + "í": { key: "KeyI", accentKey: keyAcute }, + "î": { key: "KeyI", accentKey: keyHat }, + "ì": { key: "KeyI", accentKey: keyGrave }, + j: { key: "KeyJ" }, + k: { key: "KeyK" }, + l: { key: "KeyL" }, + m: { key: "KeyM" }, + "µ": { key: "KeyM", altRight: true }, + n: { key: "KeyN" }, + o: { key: "KeyO" }, + "ó": { key: "KeyO", accentKey: keyAcute }, + "ô": { key: "KeyO", accentKey: keyHat }, + "ò": { key: "KeyO", accentKey: keyGrave }, + p: { key: "KeyP" }, + q: { key: "KeyQ" }, + "@": { key: "KeyQ", altRight: true }, + r: { key: "KeyR" }, + s: { key: "KeyS" }, + t: { key: "KeyT" }, + u: { key: "KeyU" }, + "ú": { key: "KeyU", accentKey: keyAcute }, + "û": { key: "KeyU", accentKey: keyHat }, + "ù": { key: "KeyU", accentKey: keyGrave }, + v: { key: "KeyV" }, + w: { key: "KeyW" }, + x: { key: "KeyX" }, + y: { key: "KeyZ" }, + z: { key: "KeyY" }, + "°": { key: "Backquote", shift: true }, + "^": { key: "Backquote", deadKey: true }, + 1: { key: "Digit1" }, + "!": { key: "Digit1", shift: true }, + 2: { key: "Digit2" }, + "\"": { key: "Digit2", shift: true }, + "²": { key: "Digit2", altRight: true }, + 3: { key: "Digit3" }, + "§": { key: "Digit3", shift: true }, + "³": { key: "Digit3", altRight: true }, + 4: { key: "Digit4" }, + "$": { key: "Digit4", shift: true }, + 5: { key: "Digit5" }, + "%": { key: "Digit5", shift: true }, + 6: { key: "Digit6" }, + "&": { key: "Digit6", shift: true }, + 7: { key: "Digit7" }, + "/": { key: "Digit7", shift: true }, + "{": { key: "Digit7", altRight: true }, + 8: { key: "Digit8" }, + "(": { key: "Digit8", shift: true }, + "[": { key: "Digit8", altRight: true }, + 9: { key: "Digit9" }, + ")": { key: "Digit9", shift: true }, + "]": { key: "Digit9", altRight: true }, + 0: { key: "Digit0" }, + "=": { key: "Digit0", shift: true }, + "}": { key: "Digit0", altRight: true }, + "ß": { key: "Minus" }, + "?": { key: "Minus", shift: true }, + "\\": { key: "Minus", altRight: true }, + "´": { key: "Equal", deadKey: true }, + "`": { key: "Equal", shift: true, deadKey: true }, + "ü": { key: "BracketLeft" }, + "Ü": { key: "BracketLeft", shift: true }, + "+": { key: "BracketRight" }, + "*": { key: "BracketRight", shift: true }, + "~": { key: "BracketRight", altRight: true }, + "ö": { key: "Semicolon" }, + "Ö": { key: "Semicolon", shift: true }, + "ä": { key: "Quote" }, + "Ä": { key: "Quote", shift: true }, + "#": { key: "Backslash" }, + "'": { key: "Backslash", shift: true }, + ",": { key: "Comma" }, + ";": { key: "Comma", shift: true }, + ".": { key: "Period" }, + ":": { key: "Period", shift: true }, + "-": { key: "Slash" }, + "_": { key: "Slash", shift: true }, + "<": { key: "IntlBackslash" }, + ">": { key: "IntlBackslash", shift: true }, + "|": { key: "IntlBackslash", altRight: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record; diff --git a/ui/src/keyboardLayouts/en_UK.ts b/ui/src/keyboardLayouts/en_UK.ts new file mode 100644 index 0000000..ed0c8dd --- /dev/null +++ b/ui/src/keyboardLayouts/en_UK.ts @@ -0,0 +1,107 @@ +import { KeyCombo } from "../keyboardLayouts" + +export const name = "English (UK)"; + +export const chars = { + A: { key: "KeyA", shift: true }, + B: { key: "KeyB", shift: true }, + C: { key: "KeyC", shift: true }, + D: { key: "KeyD", shift: true }, + E: { key: "KeyE", shift: true }, + F: { key: "KeyF", shift: true }, + G: { key: "KeyG", shift: true }, + H: { key: "KeyH", shift: true }, + I: { key: "KeyI", shift: true }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + M: { key: "KeyM", shift: true }, + N: { key: "KeyN", shift: true }, + O: { key: "KeyO", shift: true }, + P: { key: "KeyP", shift: true }, + Q: { key: "KeyQ", shift: true }, + R: { key: "KeyR", shift: true }, + S: { key: "KeyS", shift: true }, + T: { key: "KeyT", shift: true }, + U: { key: "KeyU", shift: true }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyW", shift: true }, + X: { key: "KeyX", shift: true }, + Y: { key: "KeyY", shift: true }, + Z: { key: "KeyZ", shift: true }, + a: { key: "KeyA" }, + b: { key: "KeyB" }, + c: { key: "KeyC" }, + d: { key: "KeyD" }, + e: { key: "KeyE" }, + f: { key: "KeyF" }, + g: { key: "KeyG" }, + h: { key: "KeyH" }, + i: { key: "KeyI" }, + j: { key: "KeyJ" }, + k: { key: "KeyK" }, + l: { key: "KeyL" }, + m: { key: "KeyM" }, + n: { key: "KeyN" }, + o: { key: "KeyO" }, + p: { key: "KeyP" }, + q: { key: "KeyQ" }, + r: { key: "KeyR" }, + s: { key: "KeyS" }, + t: { key: "KeyT" }, + u: { key: "KeyU" }, + v: { key: "KeyV" }, + w: { key: "KeyW" }, + x: { key: "KeyX" }, + y: { key: "KeyY" }, + z: { key: "KeyZ" }, + 1: { key: "Digit1" }, + "!": { key: "Digit1", shift: true }, + 2: { key: "Digit2" }, + "\"": { key: "Digit2", shift: true }, + 3: { key: "Digit3" }, + "£": { key: "Digit3", shift: true }, + 4: { key: "Digit4" }, + $: { key: "Digit4", shift: true }, + "€": { key: "Digit4", altRight: true }, + 5: { key: "Digit5" }, + "%": { key: "Digit5", shift: true }, + 6: { key: "Digit6" }, + "^": { key: "Digit6", shift: true }, + 7: { key: "Digit7" }, + "&": { key: "Digit7", shift: true }, + 8: { key: "Digit8" }, + "*": { key: "Digit8", shift: true }, + 9: { key: "Digit9" }, + "(": { key: "Digit9", shift: true }, + 0: { key: "Digit0" }, + ")": { key: "Digit0", shift: true }, + "-": { key: "Minus" }, + _: { key: "Minus", shift: true }, + "=": { key: "Equal" }, + "+": { key: "Equal", shift: true }, + "'": { key: "Quote" }, + '@': { key: "Quote", shift: true }, + ",": { key: "Comma" }, + "<": { key: "Comma", shift: true }, + "/": { key: "Slash" }, + "?": { key: "Slash", shift: true }, + ".": { key: "Period" }, + ">": { key: "Period", shift: true }, + ";": { key: "Semicolon" }, + ":": { key: "Semicolon", shift: true }, + "[": { key: "BracketLeft" }, + "{": { key: "BracketLeft", shift: true }, + "]": { key: "BracketRight" }, + "}": { key: "BracketRight", shift: true }, + "#": { key: "Backslash" }, + "~": { key: "Backslash", shift: true }, + "`": { key: "Backquote" }, + "¬": { key: "Backquote", shift: true }, + "\\": { key: "IntlBackslash" }, + "|": { key: "IntlBackslash", shift: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record diff --git a/ui/src/keyboardLayouts/en_US.ts b/ui/src/keyboardLayouts/en_US.ts new file mode 100644 index 0000000..3ae1c2e --- /dev/null +++ b/ui/src/keyboardLayouts/en_US.ts @@ -0,0 +1,106 @@ +import { KeyCombo } from "../keyboardLayouts" + +export const name = "English (US)"; + +export const chars = { + A: { key: "KeyA", shift: true }, + B: { key: "KeyB", shift: true }, + C: { key: "KeyC", shift: true }, + D: { key: "KeyD", shift: true }, + E: { key: "KeyE", shift: true }, + F: { key: "KeyF", shift: true }, + G: { key: "KeyG", shift: true }, + H: { key: "KeyH", shift: true }, + I: { key: "KeyI", shift: true }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + M: { key: "KeyM", shift: true }, + N: { key: "KeyN", shift: true }, + O: { key: "KeyO", shift: true }, + P: { key: "KeyP", shift: true }, + Q: { key: "KeyQ", shift: true }, + R: { key: "KeyR", shift: true }, + S: { key: "KeyS", shift: true }, + T: { key: "KeyT", shift: true }, + U: { key: "KeyU", shift: true }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyW", shift: true }, + X: { key: "KeyX", shift: true }, + Y: { key: "KeyY", shift: true }, + Z: { key: "KeyZ", shift: true }, + a: { key: "KeyA" }, + b: { key: "KeyB" }, + c: { key: "KeyC" }, + d: { key: "KeyD" }, + e: { key: "KeyE" }, + f: { key: "KeyF" }, + g: { key: "KeyG" }, + h: { key: "KeyH" }, + i: { key: "KeyI" }, + j: { key: "KeyJ" }, + k: { key: "KeyK" }, + l: { key: "KeyL" }, + m: { key: "KeyM" }, + n: { key: "KeyN" }, + o: { key: "KeyO" }, + p: { key: "KeyP" }, + q: { key: "KeyQ" }, + r: { key: "KeyR" }, + s: { key: "KeyS" }, + t: { key: "KeyT" }, + u: { key: "KeyU" }, + v: { key: "KeyV" }, + w: { key: "KeyW" }, + x: { key: "KeyX" }, + y: { key: "KeyY" }, + z: { key: "KeyZ" }, + 1: { key: "Digit1" }, + "!": { key: "Digit1", shift: true }, + 2: { key: "Digit2" }, + "@": { key: "Digit2", shift: true }, + 3: { key: "Digit3" }, + "#": { key: "Digit3", shift: true }, + 4: { key: "Digit4" }, + $: { key: "Digit4", shift: true }, + "%": { key: "Digit5", shift: true }, + 5: { key: "Digit5" }, + "^": { key: "Digit6", shift: true }, + 6: { key: "Digit6" }, + "&": { key: "Digit7", shift: true }, + 7: { key: "Digit7" }, + "*": { key: "Digit8", shift: true }, + 8: { key: "Digit8" }, + "(": { key: "Digit9", shift: true }, + 9: { key: "Digit9" }, + ")": { key: "Digit0", shift: true }, + 0: { key: "Digit0" }, + "-": { key: "Minus" }, + _: { key: "Minus", shift: true }, + "=": { key: "Equal" }, + "+": { key: "Equal", shift: true }, + "'": { key: "Quote" }, + '"': { key: "Quote", shift: true }, + ",": { key: "Comma" }, + "<": { key: "Comma", shift: true }, + "/": { key: "Slash" }, + "?": { key: "Slash", shift: true }, + ".": { key: "Period" }, + ">": { key: "Period", shift: true }, + ";": { key: "Semicolon" }, + ":": { key: "Semicolon", shift: true }, + "[": { key: "BracketLeft" }, + "{": { key: "BracketLeft", shift: true }, + "]": { key: "BracketRight" }, + "}": { key: "BracketRight", shift: true }, + "\\": { key: "Backslash" }, + "|": { key: "Backslash", shift: true }, + "`": { key: "Backquote" }, + "~": { key: "Backquote", shift: true }, + "§": { key: "IntlBackslash" }, + "±": { key: "IntlBackslash", shift: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record diff --git a/ui/src/keyboardLayouts/es_ES.ts b/ui/src/keyboardLayouts/es_ES.ts new file mode 100644 index 0000000..f979205 --- /dev/null +++ b/ui/src/keyboardLayouts/es_ES.ts @@ -0,0 +1,168 @@ +import { KeyCombo } from "../keyboardLayouts" + +export const name = "Spanish"; + +const keyTrema = { key: "Quote", shift: true } // tréma (umlaut), two dots placed above a vowel +const keyAcute = { key: "Quote" } // accent aigu (acute accent), mark ´ placed above the letter +const keyHat = { key: "BracketRight", shift: true } // accent circonflexe (accent hat), mark ^ placed above the letter +const keyGrave = { key: "BracketRight" } // accent grave, mark ` placed above the letter +const keyTilde = { key: "Key4", altRight: true } // tilde, mark ~ placed above the letter + +export const chars = { + A: { key: "KeyA", shift: true }, + "Ä": { key: "KeyA", shift: true, accentKey: keyTrema }, + "Á": { key: "KeyA", shift: true, accentKey: keyAcute }, + "Â": { key: "KeyA", shift: true, accentKey: keyHat }, + "À": { key: "KeyA", shift: true, accentKey: keyGrave }, + "Ã": { key: "KeyA", shift: true, accentKey: keyTilde }, + B: { key: "KeyB", shift: true }, + C: { key: "KeyC", shift: true }, + D: { key: "KeyD", shift: true }, + E: { key: "KeyE", shift: true }, + "Ë": { key: "KeyE", shift: true, accentKey: keyTrema }, + "É": { key: "KeyE", shift: true, accentKey: keyAcute }, + "Ê": { key: "KeyE", shift: true, accentKey: keyHat }, + "È": { key: "KeyE", shift: true, accentKey: keyGrave }, + "Ẽ": { key: "KeyE", shift: true, accentKey: keyTilde }, + F: { key: "KeyF", shift: true }, + G: { key: "KeyG", shift: true }, + H: { key: "KeyH", shift: true }, + I: { key: "KeyI", shift: true }, + "Ï": { key: "KeyI", shift: true, accentKey: keyTrema }, + "Í": { key: "KeyI", shift: true, accentKey: keyAcute }, + "Î": { key: "KeyI", shift: true, accentKey: keyHat }, + "Ì": { key: "KeyI", shift: true, accentKey: keyGrave }, + "Ĩ": { key: "KeyI", shift: true, accentKey: keyTilde }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + M: { key: "KeyM", shift: true }, + N: { key: "KeyN", shift: true }, + O: { key: "KeyO", shift: true }, + "Ö": { key: "KeyO", shift: true, accentKey: keyTrema }, + "Ó": { key: "KeyO", shift: true, accentKey: keyAcute }, + "Ô": { key: "KeyO", shift: true, accentKey: keyHat }, + "Ò": { key: "KeyO", shift: true, accentKey: keyGrave }, + "Õ": { key: "KeyO", shift: true, accentKey: keyTilde }, + P: { key: "KeyP", shift: true }, + Q: { key: "KeyQ", shift: true }, + R: { key: "KeyR", shift: true }, + S: { key: "KeyS", shift: true }, + T: { key: "KeyT", shift: true }, + U: { key: "KeyU", shift: true }, + "Ü": { key: "KeyU", shift: true, accentKey: keyTrema }, + "Ú": { key: "KeyU", shift: true, accentKey: keyAcute }, + "Û": { key: "KeyU", shift: true, accentKey: keyHat }, + "Ù": { key: "KeyU", shift: true, accentKey: keyGrave }, + "Ũ": { key: "KeyU", shift: true, accentKey: keyTilde }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyW", shift: true }, + X: { key: "KeyX", shift: true }, + Y: { key: "KeyY", shift: true }, + Z: { key: "KeyZ", shift: true }, + a: { key: "KeyA" }, + "ä": { key: "KeyA", accentKey: keyTrema }, + "á": { key: "KeyA", accentKey: keyAcute }, + "â": { key: "KeyA", accentKey: keyHat }, + "à": { key: "KeyA", accentKey: keyGrave }, + "ã": { key: "KeyA", accentKey: keyTilde }, + b: { key: "KeyB" }, + c: { key: "KeyC" }, + d: { key: "KeyD" }, + e: { key: "KeyE" }, + "ë": { key: "KeyE", accentKey: keyTrema }, + "é": { key: "KeyE", accentKey: keyAcute }, + "ê": { key: "KeyE", accentKey: keyHat }, + "è": { key: "KeyE", accentKey: keyGrave }, + "ẽ": { key: "KeyE", accentKey: keyTilde }, + "€": { key: "KeyE", altRight: true }, + f: { key: "KeyF" }, + g: { key: "KeyG" }, + h: { key: "KeyH" }, + i: { key: "KeyI" }, + "ï": { key: "KeyI", accentKey: keyTrema }, + "í": { key: "KeyI", accentKey: keyAcute }, + "î": { key: "KeyI", accentKey: keyHat }, + "ì": { key: "KeyI", accentKey: keyGrave }, + "ĩ": { key: "KeyI", accentKey: keyTilde }, + j: { key: "KeyJ" }, + k: { key: "KeyK" }, + l: { key: "KeyL" }, + m: { key: "KeyM" }, + n: { key: "KeyN" }, + o: { key: "KeyO" }, + "ö": { key: "KeyO", accentKey: keyTrema }, + "ó": { key: "KeyO", accentKey: keyAcute }, + "ô": { key: "KeyO", accentKey: keyHat }, + "ò": { key: "KeyO", accentKey: keyGrave }, + "õ": { key: "KeyO", accentKey: keyTilde }, + p: { key: "KeyP" }, + q: { key: "KeyQ" }, + r: { key: "KeyR" }, + s: { key: "KeyS" }, + t: { key: "KeyT" }, + u: { key: "KeyU" }, + "ü": { key: "KeyU", accentKey: keyTrema }, + "ú": { key: "KeyU", accentKey: keyAcute }, + "û": { key: "KeyU", accentKey: keyHat }, + "ù": { key: "KeyU", accentKey: keyGrave }, + "ũ": { key: "KeyU", accentKey: keyTilde }, + v: { key: "KeyV" }, + w: { key: "KeyW" }, + x: { key: "KeyX" }, + y: { key: "KeyY" }, + z: { key: "KeyZ" }, + "º": { key: "Backquote" }, + "ª": { key: "Backquote", shift: true }, + "\\": { key: "Backquote", altRight: true }, + 1: { key: "Digit1" }, + "!": { key: "Digit1", shift: true }, + "|": { key: "Digit1", altRight: true }, + 2: { key: "Digit2" }, + "\"": { key: "Digit2", shift: true }, + "@": { key: "Digit2", altRight: true }, + 3: { key: "Digit3" }, + "·": { key: "Digit3", shift: true }, + "#": { key: "Digit3", altRight: true }, + 4: { key: "Digit4" }, + "$": { key: "Digit4", shift: true }, + 5: { key: "Digit5" }, + "%": { key: "Digit5", shift: true }, + 6: { key: "Digit6" }, + "&": { key: "Digit6", shift: true }, + "¬": { key: "Digit6", altRight: true }, + 7: { key: "Digit7" }, + "/": { key: "Digit7", shift: true }, + 8: { key: "Digit8" }, + "(": { key: "Digit8", shift: true }, + 9: { key: "Digit9" }, + ")": { key: "Digit9", shift: true }, + 0: { key: "Digit0" }, + "=": { key: "Digit0", shift: true }, + "'": { key: "Minus" }, + "?": { key: "Minus", shift: true }, + "¡": { key: "Equal", deadKey: true }, + "¿": { key: "Equal", shift: true }, + "[": { key: "BracketLeft", altRight: true }, + "+": { key: "BracketRight" }, + "*": { key: "BracketRight", shift: true }, + "]": { key: "BracketRight", altRight: true }, + "ñ": { key: "Semicolon" }, + "Ñ": { key: "Semicolon", shift: true }, + "{": { key: "Quote", altRight: true }, + "ç": { key: "Backslash" }, + "Ç": { key: "Backslash", shift: true }, + "}": { key: "Backslash", altRight: true }, + ",": { key: "Comma" }, + ";": { key: "Comma", shift: true }, + ".": { key: "Period" }, + ":": { key: "Period", shift: true }, + "-": { key: "Slash" }, + "_": { key: "Slash", shift: true }, + "<": { key: "IntlBackslash" }, + ">": { key: "IntlBackslash", shift: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record; diff --git a/ui/src/keyboardLayouts/fr_CH.ts b/ui/src/keyboardLayouts/fr_CH.ts new file mode 100644 index 0000000..e47af1d --- /dev/null +++ b/ui/src/keyboardLayouts/fr_CH.ts @@ -0,0 +1,14 @@ +import { KeyCombo } from "../keyboardLayouts" +import { chars as chars_de_CH } from "./de_CH" + +export const name = "Swiss French"; + +export const chars = { + ...chars_de_CH, + "è": { key: "BracketLeft" }, + "ü": { key: "BracketLeft", shift: true }, + "é": { key: "Semicolon" }, + "ö": { key: "Semicolon", shift: true }, + "à": { key: "Quote" }, + "ä": { key: "Quote", shift: true }, +} as Record; diff --git a/ui/src/keyboardLayouts/fr_FR.ts b/ui/src/keyboardLayouts/fr_FR.ts new file mode 100644 index 0000000..a489807 --- /dev/null +++ b/ui/src/keyboardLayouts/fr_FR.ts @@ -0,0 +1,139 @@ +import { KeyCombo } from "../keyboardLayouts" + +export const name = "French"; + +const keyTrema = { key: "BracketLeft", shift: true } // tréma (umlaut), two dots placed above a vowel +const keyHat = { key: "BracketLeft" } // accent circonflexe (accent hat), mark ^ placed above the letter + +export const chars = { + A: { key: "KeyQ", shift: true }, + "Ä": { key: "KeyQ", shift: true, accentKey: keyTrema }, + "Â": { key: "KeyQ", shift: true, accentKey: keyHat }, + B: { key: "KeyB", shift: true }, + C: { key: "KeyC", shift: true }, + D: { key: "KeyD", shift: true }, + E: { key: "KeyE", shift: true }, + "Ë": { key: "KeyE", shift: true, accentKey: keyTrema }, + "Ê": { key: "KeyE", shift: true, accentKey: keyHat }, + F: { key: "KeyF", shift: true }, + G: { key: "KeyG", shift: true }, + H: { key: "KeyH", shift: true }, + I: { key: "KeyI", shift: true }, + "Ï": { key: "KeyI", shift: true, accentKey: keyTrema }, + "Î": { key: "KeyI", shift: true, accentKey: keyHat }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + M: { key: "Semicolon", shift: true }, + N: { key: "KeyN", shift: true }, + O: { key: "KeyO", shift: true }, + "Ö": { key: "KeyO", shift: true, accentKey: keyTrema }, + "Ô": { key: "KeyO", shift: true, accentKey: keyHat }, + P: { key: "KeyP", shift: true }, + Q: { key: "KeyA", shift: true }, + R: { key: "KeyR", shift: true }, + S: { key: "KeyS", shift: true }, + T: { key: "KeyT", shift: true }, + U: { key: "KeyU", shift: true }, + "Ü": { key: "KeyU", shift: true, accentKey: keyTrema }, + "Û": { key: "KeyU", shift: true, accentKey: keyHat }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyZ", shift: true }, + X: { key: "KeyX", shift: true }, + Y: { key: "KeyY", shift: true }, + Z: { key: "KeyW", shift: true }, + a: { key: "KeyQ" }, + "ä": { key: "KeyQ", accentKey: keyTrema }, + "â": { key: "KeyQ", accentKey: keyHat }, + b: { key: "KeyB" }, + c: { key: "KeyC" }, + d: { key: "KeyD" }, + e: { key: "KeyE" }, + "ë": { key: "KeyE", accentKey: keyTrema }, + "ê": { key: "KeyE", accentKey: keyHat }, + "€": { key: "KeyE", altRight: true }, + f: { key: "KeyF" }, + g: { key: "KeyG" }, + h: { key: "KeyH" }, + i: { key: "KeyI" }, + "ï": { key: "KeyI", accentKey: keyTrema }, + "î": { key: "KeyI", accentKey: keyHat }, + j: { key: "KeyJ" }, + k: { key: "KeyK" }, + l: { key: "KeyL" }, + m: { key: "Semicolon" }, + n: { key: "KeyN" }, + o: { key: "KeyO" }, + "ö": { key: "KeyO", accentKey: keyTrema }, + "ô": { key: "KeyO", accentKey: keyHat }, + p: { key: "KeyP" }, + q: { key: "KeyA" }, + r: { key: "KeyR" }, + s: { key: "KeyS" }, + t: { key: "KeyT" }, + u: { key: "KeyU" }, + "ü": { key: "KeyU", accentKey: keyTrema }, + "û": { key: "KeyU", accentKey: keyHat }, + v: { key: "KeyV" }, + w: { key: "KeyZ" }, + x: { key: "KeyX" }, + y: { key: "KeyY" }, + z: { key: "KeyW" }, + "²": { key: "Backquote" }, + "&": { key: "Digit1" }, + 1: { key: "Digit1", shift: true }, + "é": { key: "Digit2" }, + 2: { key: "Digit2", shift: true }, + "~": { key: "Digit2", altRight: true }, + "\"": { key: "Digit3" }, + 3: { key: "Digit3", shift: true }, + "#": { key: "Digit3", altRight: true }, + "'": { key: "Digit4" }, + 4: { key: "Digit4", shift: true }, + "{": { key: "Digit4", altRight: true }, + "(": { key: "Digit5" }, + 5: { key: "Digit5", shift: true }, + "[": { key: "Digit5", altRight: true }, + "-": { key: "Digit6" }, + 6: { key: "Digit6", shift: true }, + "|": { key: "Digit6", altRight: true }, + "è": { key: "Digit7" }, + 7: { key: "Digit7", shift: true }, + "`": { key: "Digit7", altRight: true }, + "_": { key: "Digit8" }, + 8: { key: "Digit8", shift: true }, + "\\": { key: "Digit8", altRight: true }, + "ç": { key: "Digit9" }, + 9: { key: "Digit9", shift: true }, + "^": { key: "Digit9", altRight: true }, + "à": { key: "Digit0" }, + 0: { key: "Digit0", shift: true }, + "@": { key: "Digit0", altRight: true }, + ")": { key: "Minus" }, + "°": { key: "Minus", shift: true }, + "]": { key: "Minus", altRight: true }, + "=": { key: "Equal" }, + "+": { key: "Equal", shift: true }, + "}": { key: "Equal", altRight: true }, + "$": { key: "BracketRight" }, + "£": { key: "BracketRight", shift: true }, + "¤": { key: "BracketRight", altRight: true }, + "ù": { key: "Quote" }, + "%": { key: "Quote", shift: true }, + "*": { key: "Backslash" }, + "µ": { key: "Backslash", shift: true }, + ",": { key: "KeyM" }, + "?": { key: "KeyM", shift: true }, + ";": { key: "Comma" }, + ".": { key: "Comma", shift: true }, + ":": { key: "Period" }, + "/": { key: "Period", shift: true }, + "!": { key: "Slash" }, + "§": { key: "Slash", shift: true }, + "<": { key: "IntlBackslash" }, + ">": { key: "IntlBackslash", shift: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record; diff --git a/ui/src/keyboardLayouts/it_IT.ts b/ui/src/keyboardLayouts/it_IT.ts new file mode 100644 index 0000000..012734c --- /dev/null +++ b/ui/src/keyboardLayouts/it_IT.ts @@ -0,0 +1,113 @@ +import { KeyCombo } from "../keyboardLayouts" + +export const name = "Italian"; + +export const chars = { + A: { key: "KeyA", shift: true }, + B: { key: "KeyB", shift: true }, + C: { key: "KeyC", shift: true }, + D: { key: "KeyD", shift: true }, + E: { key: "KeyE", shift: true }, + F: { key: "KeyF", shift: true }, + G: { key: "KeyG", shift: true }, + H: { key: "KeyH", shift: true }, + I: { key: "KeyI", shift: true }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + M: { key: "KeyM", shift: true }, + N: { key: "KeyN", shift: true }, + O: { key: "KeyO", shift: true }, + P: { key: "KeyP", shift: true }, + Q: { key: "KeyQ", shift: true }, + R: { key: "KeyR", shift: true }, + S: { key: "KeyS", shift: true }, + T: { key: "KeyT", shift: true }, + U: { key: "KeyU", shift: true }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyW", shift: true }, + X: { key: "KeyX", shift: true }, + Y: { key: "KeyY", shift: true }, + Z: { key: "KeyZ", shift: true }, + a: { key: "KeyA" }, + b: { key: "KeyB" }, + c: { key: "KeyC" }, + d: { key: "KeyD" }, + e: { key: "KeyE" }, + "€": { key: "KeyE", altRight: true }, + f: { key: "KeyF" }, + g: { key: "KeyG" }, + h: { key: "KeyH" }, + i: { key: "KeyI" }, + j: { key: "KeyJ" }, + k: { key: "KeyK" }, + l: { key: "KeyL" }, + m: { key: "KeyM" }, + n: { key: "KeyN" }, + o: { key: "KeyO" }, + p: { key: "KeyP" }, + q: { key: "KeyQ" }, + r: { key: "KeyR" }, + s: { key: "KeyS" }, + t: { key: "KeyT" }, + u: { key: "KeyU" }, + v: { key: "KeyV" }, + w: { key: "KeyW" }, + x: { key: "KeyX" }, + y: { key: "KeyY" }, + z: { key: "KeyZ" }, + "\\": { key: "Backquote" }, + "|": { key: "Backquote", shift: true }, + 1: { key: "Digit1" }, + "!": { key: "Digit1", shift: true }, + 2: { key: "Digit2" }, + "\"": { key: "Digit2", shift: true }, + 3: { key: "Digit3" }, + "£": { key: "Digit3", shift: true }, + 4: { key: "Digit4" }, + "$": { key: "Digit4", shift: true }, + 5: { key: "Digit5" }, + "%": { key: "Digit5", shift: true }, + 6: { key: "Digit6" }, + "&": { key: "Digit6", shift: true }, + 7: { key: "Digit7" }, + "/": { key: "Digit7", shift: true }, + 8: { key: "Digit8" }, + "(": { key: "Digit8", shift: true }, + 9: { key: "Digit9" }, + ")": { key: "Digit9", shift: true }, + 0: { key: "Digit0" }, + "=": { key: "Digit0", shift: true }, + "'": { key: "Minus" }, + "?": { key: "Minus", shift: true }, + "ì": { key: "Equal" }, + "^": { key: "Equal", shift: true }, + "è": { key: "BracketLeft" }, + "é": { key: "BracketLeft", shift: true }, + "[": { key: "BracketLeft", altRight: true }, + "{": { key: "BracketLeft", shift: true, altRight: true }, + "+": { key: "BracketRight" }, + "*": { key: "BracketRight", shift: true }, + "]": { key: "BracketRight", altRight: true }, + "}": { key: "BracketRight", shift: true, altRight: true }, + "ò": { key: "Semicolon" }, + "ç": { key: "Semicolon", shift: true }, + "@": { key: "Semicolon", altRight: true }, + "à": { key: "Quote" }, + "°": { key: "Quote", shift: true }, + "#": { key: "Quote", altRight: true }, + "ù": { key: "Backslash" }, + "§": { key: "Backslash", shift: true }, + ",": { key: "Comma" }, + ";": { key: "Comma", shift: true }, + ".": { key: "Period" }, + ":": { key: "Period", shift: true }, + "-": { key: "Slash" }, + "_": { key: "Slash", shift: true }, + "<": { key: "IntlBackslash" }, + ">": { key: "IntlBackslash", shift: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record; diff --git a/ui/src/keyboardLayouts/nb_NO.ts b/ui/src/keyboardLayouts/nb_NO.ts new file mode 100644 index 0000000..1507ed3 --- /dev/null +++ b/ui/src/keyboardLayouts/nb_NO.ts @@ -0,0 +1,167 @@ +import { KeyCombo } from "../keyboardLayouts" + +export const name = "Norwegian"; + +const keyTrema = { key: "BracketRight" } // tréma (umlaut), two dots placed above a vowel +const keyAcute = { key: "Equal", altRight: true } // accent aigu (acute accent), mark ´ placed above the letter +const keyHat = { key: "BracketRight", shift: true } // accent circonflexe (accent hat), mark ^ placed above the letter +const keyGrave = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter +const keyTilde = { key: "BracketRight", altRight: true } // tilde, mark ~ placed above the letter + +export const chars = { + A: { key: "KeyA", shift: true }, + "Ä": { key: "KeyA", shift: true, accentKey: keyTrema }, + "Á": { key: "KeyA", shift: true, accentKey: keyAcute }, + "Â": { key: "KeyA", shift: true, accentKey: keyHat }, + "À": { key: "KeyA", shift: true, accentKey: keyGrave }, + "Ã": { key: "KeyA", shift: true, accentKey: keyTilde }, + B: { key: "KeyB", shift: true }, + C: { key: "KeyC", shift: true }, + D: { key: "KeyD", shift: true }, + E: { key: "KeyE", shift: true }, + "Ë": { key: "KeyE", shift: true, accentKey: keyTrema }, + "É": { key: "KeyE", shift: true, accentKey: keyAcute }, + "Ê": { key: "KeyE", shift: true, accentKey: keyHat }, + "È": { key: "KeyE", shift: true, accentKey: keyGrave }, + "Ẽ": { key: "KeyE", shift: true, accentKey: keyTilde }, + F: { key: "KeyF", shift: true }, + G: { key: "KeyG", shift: true }, + H: { key: "KeyH", shift: true }, + I: { key: "KeyI", shift: true }, + "Ï": { key: "KeyI", shift: true, accentKey: keyTrema }, + "Í": { key: "KeyI", shift: true, accentKey: keyAcute }, + "Î": { key: "KeyI", shift: true, accentKey: keyHat }, + "Ì": { key: "KeyI", shift: true, accentKey: keyGrave }, + "Ĩ": { key: "KeyI", shift: true, accentKey: keyTilde }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + M: { key: "KeyM", shift: true }, + N: { key: "KeyN", shift: true }, + O: { key: "KeyO", shift: true }, + "Ö": { key: "KeyO", shift: true, accentKey: keyTrema }, + "Ó": { key: "KeyO", shift: true, accentKey: keyAcute }, + "Ô": { key: "KeyO", shift: true, accentKey: keyHat }, + "Ò": { key: "KeyO", shift: true, accentKey: keyGrave }, + "Õ": { key: "KeyO", shift: true, accentKey: keyTilde }, + P: { key: "KeyP", shift: true }, + Q: { key: "KeyQ", shift: true }, + R: { key: "KeyR", shift: true }, + S: { key: "KeyS", shift: true }, + T: { key: "KeyT", shift: true }, + U: { key: "KeyU", shift: true }, + "Ü": { key: "KeyU", shift: true, accentKey: keyTrema }, + "Ú": { key: "KeyU", shift: true, accentKey: keyAcute }, + "Û": { key: "KeyU", shift: true, accentKey: keyHat }, + "Ù": { key: "KeyU", shift: true, accentKey: keyGrave }, + "Ũ": { key: "KeyU", shift: true, accentKey: keyTilde }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyW", shift: true }, + X: { key: "KeyX", shift: true }, + Y: { key: "KeyZ", shift: true }, + Z: { key: "KeyY", shift: true }, + a: { key: "KeyA" }, + "ä": { key: "KeyA", accentKey: keyTrema }, + "á": { key: "KeyA", accentKey: keyAcute }, + "â": { key: "KeyA", accentKey: keyHat }, + "à": { key: "KeyA", accentKey: keyGrave }, + "ã": { key: "KeyA", accentKey: keyTilde }, + b: { key: "KeyB" }, + c: { key: "KeyC" }, + d: { key: "KeyD" }, + e: { key: "KeyE" }, + "ë": { key: "KeyE", accentKey: keyTrema }, + "é": { key: "KeyE", accentKey: keyAcute }, + "ê": { key: "KeyE", accentKey: keyHat }, + "è": { key: "KeyE", accentKey: keyGrave }, + "ẽ": { key: "KeyE", accentKey: keyTilde }, + "€": { key: "KeyE", altRight: true }, + f: { key: "KeyF" }, + g: { key: "KeyG" }, + h: { key: "KeyH" }, + i: { key: "KeyI" }, + "ï": { key: "KeyI", accentKey: keyTrema }, + "í": { key: "KeyI", accentKey: keyAcute }, + "î": { key: "KeyI", accentKey: keyHat }, + "ì": { key: "KeyI", accentKey: keyGrave }, + "ĩ": { key: "KeyI", accentKey: keyTilde }, + j: { key: "KeyJ" }, + k: { key: "KeyK" }, + l: { key: "KeyL" }, + m: { key: "KeyM" }, + n: { key: "KeyN" }, + o: { key: "KeyO" }, + "ö": { key: "KeyO", accentKey: keyTrema }, + "ó": { key: "KeyO", accentKey: keyAcute }, + "ô": { key: "KeyO", accentKey: keyHat }, + "ò": { key: "KeyO", accentKey: keyGrave }, + "õ": { key: "KeyO", accentKey: keyTilde }, + p: { key: "KeyP" }, + q: { key: "KeyQ" }, + r: { key: "KeyR" }, + s: { key: "KeyS" }, + t: { key: "KeyT" }, + u: { key: "KeyU" }, + "ü": { key: "KeyU", accentKey: keyTrema }, + "ú": { key: "KeyU", accentKey: keyAcute }, + "û": { key: "KeyU", accentKey: keyHat }, + "ù": { key: "KeyU", accentKey: keyGrave }, + "ũ": { key: "KeyU", accentKey: keyTilde }, + v: { key: "KeyV" }, + w: { key: "KeyW" }, + x: { key: "KeyX" }, + y: { key: "KeyZ" }, + z: { key: "KeyY" }, + "|": { key: "Backquote" }, + "§": { key: "Backquote", shift: true }, + 1: { key: "Digit1" }, + "!": { key: "Digit1", shift: true }, + 2: { key: "Digit2" }, + "\"": { key: "Digit2", shift: true }, + "@": { key: "Digit2", altRight: true }, + 3: { key: "Digit3" }, + "#": { key: "Digit3", shift: true }, + "£": { key: "Digit3", altRight: true }, + 4: { key: "Digit4" }, + "¤": { key: "Digit4", shift: true }, + "$": { key: "Digit4", altRight: true }, + 5: { key: "Digit5" }, + "%": { key: "Digit5", shift: true }, + 6: { key: "Digit6" }, + "&": { key: "Digit6", shift: true }, + 7: { key: "Digit7" }, + "/": { key: "Digit7", shift: true }, + "{": { key: "Digit7", altRight: true }, + 8: { key: "Digit8" }, + "(": { key: "Digit8", shift: true }, + "[": { key: "Digit8", altRight: true }, + 9: { key: "Digit9" }, + ")": { key: "Digit9", shift: true }, + "]": { key: "Digit9", altRight: true }, + 0: { key: "Digit0" }, + "=": { key: "Digit0", shift: true }, + "}": { key: "Digit0", altRight: true }, + "+": { key: "Minus" }, + "?": { key: "Minus", shift: true }, + "\\": { key: "Equal" }, + "å": { key: "BracketLeft" }, + "Å": { key: "BracketLeft", shift: true }, + "ø": { key: "Semicolon" }, + "Ø": { key: "Semicolon", shift: true }, + "æ": { key: "Quote" }, + "Æ": { key: "Quote", shift: true }, + "'": { key: "Backslash" }, + "*": { key: "Backslash", shift: true }, + ",": { key: "Comma" }, + ";": { key: "Comma", shift: true }, + ".": { key: "Period" }, + ":": { key: "Period", shift: true }, + "-": { key: "Slash" }, + "_": { key: "Slash", shift: true }, + "<": { key: "IntlBackslash" }, + ">": { key: "IntlBackslash", shift: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record; diff --git a/ui/src/keyboardLayouts/sv_SE.ts b/ui/src/keyboardLayouts/sv_SE.ts new file mode 100644 index 0000000..d2af302 --- /dev/null +++ b/ui/src/keyboardLayouts/sv_SE.ts @@ -0,0 +1,164 @@ +import { KeyCombo } from "../keyboardLayouts" + +export const name = "Swedish"; + +const keyTrema = { key: "BracketRight" } // tréma (umlaut), two dots placed above a vowel +const keyAcute = { key: "Equal" } // accent aigu (acute accent), mark ´ placed above the letter +const keyHat = { key: "BracketRight", shift: true } // accent circonflexe (accent hat), mark ^ placed above the letter +const keyGrave = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter +const keyTilde = { key: "BracketRight", altRight: true } // tilde, mark ~ placed above the letter + +export const chars = { + A: { key: "KeyA", shift: true }, + "Á": { key: "KeyA", shift: true, accentKey: keyAcute }, + "Â": { key: "KeyA", shift: true, accentKey: keyHat }, + "À": { key: "KeyA", shift: true, accentKey: keyGrave }, + "Ã": { key: "KeyA", shift: true, accentKey: keyTilde }, + B: { key: "KeyB", shift: true }, + C: { key: "KeyC", shift: true }, + D: { key: "KeyD", shift: true }, + E: { key: "KeyE", shift: true }, + "Ë": { key: "KeyE", shift: true, accentKey: keyTrema }, + "É": { key: "KeyE", shift: true, accentKey: keyAcute }, + "Ê": { key: "KeyE", shift: true, accentKey: keyHat }, + "È": { key: "KeyE", shift: true, accentKey: keyGrave }, + "Ẽ": { key: "KeyE", shift: true, accentKey: keyTilde }, + F: { key: "KeyF", shift: true }, + G: { key: "KeyG", shift: true }, + H: { key: "KeyH", shift: true }, + I: { key: "KeyI", shift: true }, + "Ï": { key: "KeyI", shift: true, accentKey: keyTrema }, + "Í": { key: "KeyI", shift: true, accentKey: keyAcute }, + "Î": { key: "KeyI", shift: true, accentKey: keyHat }, + "Ì": { key: "KeyI", shift: true, accentKey: keyGrave }, + "Ĩ": { key: "KeyI", shift: true, accentKey: keyTilde }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + M: { key: "KeyM", shift: true }, + N: { key: "KeyN", shift: true }, + O: { key: "KeyO", shift: true }, + "Ó": { key: "KeyO", shift: true, accentKey: keyAcute }, + "Ô": { key: "KeyO", shift: true, accentKey: keyHat }, + "Ò": { key: "KeyO", shift: true, accentKey: keyGrave }, + "Õ": { key: "KeyO", shift: true, accentKey: keyTilde }, + P: { key: "KeyP", shift: true }, + Q: { key: "KeyQ", shift: true }, + R: { key: "KeyR", shift: true }, + S: { key: "KeyS", shift: true }, + T: { key: "KeyT", shift: true }, + U: { key: "KeyU", shift: true }, + "Ü": { key: "KeyU", shift: true, accentKey: keyTrema }, + "Ú": { key: "KeyU", shift: true, accentKey: keyAcute }, + "Û": { key: "KeyU", shift: true, accentKey: keyHat }, + "Ù": { key: "KeyU", shift: true, accentKey: keyGrave }, + "Ũ": { key: "KeyU", shift: true, accentKey: keyTilde }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyW", shift: true }, + X: { key: "KeyX", shift: true }, + Y: { key: "KeyZ", shift: true }, + Z: { key: "KeyY", shift: true }, + a: { key: "KeyA" }, + "á": { key: "KeyA", accentKey: keyAcute }, + "â": { key: "KeyA", accentKey: keyHat }, + "à": { key: "KeyA", accentKey: keyGrave }, + "ã": { key: "KeyA", accentKey: keyTilde }, + b: { key: "KeyB" }, + c: { key: "KeyC" }, + d: { key: "KeyD" }, + e: { key: "KeyE" }, + "ë": { key: "KeyE", accentKey: keyTrema }, + "é": { key: "KeyE", accentKey: keyAcute }, + "ê": { key: "KeyE", accentKey: keyHat }, + "è": { key: "KeyE", accentKey: keyGrave }, + "ẽ": { key: "KeyE", accentKey: keyTilde }, + "€": { key: "KeyE", altRight: true }, + f: { key: "KeyF" }, + g: { key: "KeyG" }, + h: { key: "KeyH" }, + i: { key: "KeyI" }, + "ï": { key: "KeyI", accentKey: keyTrema }, + "í": { key: "KeyI", accentKey: keyAcute }, + "î": { key: "KeyI", accentKey: keyHat }, + "ì": { key: "KeyI", accentKey: keyGrave }, + "ĩ": { key: "KeyI", accentKey: keyTilde }, + j: { key: "KeyJ" }, + k: { key: "KeyK" }, + l: { key: "KeyL" }, + m: { key: "KeyM" }, + n: { key: "KeyN" }, + o: { key: "KeyO" }, + "ó": { key: "KeyO", accentKey: keyAcute }, + "ô": { key: "KeyO", accentKey: keyHat }, + "ò": { key: "KeyO", accentKey: keyGrave }, + "õ": { key: "KeyO", accentKey: keyTilde }, + p: { key: "KeyP" }, + q: { key: "KeyQ" }, + r: { key: "KeyR" }, + s: { key: "KeyS" }, + t: { key: "KeyT" }, + u: { key: "KeyU" }, + "ü": { key: "KeyU", accentKey: keyTrema }, + "ú": { key: "KeyU", accentKey: keyAcute }, + "û": { key: "KeyU", accentKey: keyHat }, + "ù": { key: "KeyU", accentKey: keyGrave }, + "ũ": { key: "KeyU", accentKey: keyTilde }, + v: { key: "KeyV" }, + w: { key: "KeyW" }, + x: { key: "KeyX" }, + y: { key: "KeyZ" }, + z: { key: "KeyY" }, + "§": { key: "Backquote" }, + "½": { key: "Backquote", shift: true }, + 1: { key: "Digit1" }, + "!": { key: "Digit1", shift: true }, + 2: { key: "Digit2" }, + "\"": { key: "Digit2", shift: true }, + "@": { key: "Digit2", altRight: true }, + 3: { key: "Digit3" }, + "#": { key: "Digit3", shift: true }, + "£": { key: "Digit3", altRight: true }, + 4: { key: "Digit4" }, + "¤": { key: "Digit4", shift: true }, + "$": { key: "Digit4", altRight: true }, + 5: { key: "Digit5" }, + "%": { key: "Digit5", shift: true }, + 6: { key: "Digit6" }, + "&": { key: "Digit6", shift: true }, + 7: { key: "Digit7" }, + "/": { key: "Digit7", shift: true }, + "{": { key: "Digit7", altRight: true }, + 8: { key: "Digit8" }, + "(": { key: "Digit8", shift: true }, + "[": { key: "Digit8", altRight: true }, + 9: { key: "Digit9" }, + ")": { key: "Digit9", shift: true }, + "]": { key: "Digit9", altRight: true }, + 0: { key: "Digit0" }, + "=": { key: "Digit0", shift: true }, + "}": { key: "Digit0", altRight: true }, + "+": { key: "Minus" }, + "?": { key: "Minus", shift: true }, + "\\": { key: "Minus", altRight: true }, + "å": { key: "BracketLeft" }, + "Å": { key: "BracketLeft", shift: true }, + "ö": { key: "Semicolon" }, + "Ö": { key: "Semicolon", shift: true }, + "ä": { key: "Quote" }, + "Ä": { key: "Quote", shift: true }, + "'": { key: "Backslash" }, + "*": { key: "Backslash", shift: true }, + ",": { key: "Comma" }, + ";": { key: "Comma", shift: true }, + ".": { key: "Period" }, + ":": { key: "Period", shift: true }, + "-": { key: "Slash" }, + "_": { key: "Slash", shift: true }, + "<": { key: "IntlBackslash" }, + ">": { key: "IntlBackslash", shift: true }, + "|": { key: "IntlBackslash", altRight: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record; diff --git a/ui/src/keyboardMappings.ts b/ui/src/keyboardMappings.ts index 347939a..c98efeb 100644 --- a/ui/src/keyboardMappings.ts +++ b/ui/src/keyboardMappings.ts @@ -43,7 +43,7 @@ export const keys = { F13: 0x68, Home: 0x4a, Insert: 0x49, - IntlBackslash: 0x31, + IntlBackslash: 0x64, KeyA: 0x04, KeyB: 0x05, KeyC: 0x06, @@ -99,109 +99,6 @@ export const keys = { Tab: 0x2b, } as Record; -export const chars = { - A: { key: "KeyA", shift: true }, - B: { key: "KeyB", shift: true }, - C: { key: "KeyC", shift: true }, - D: { key: "KeyD", shift: true }, - E: { key: "KeyE", shift: true }, - F: { key: "KeyF", shift: true }, - G: { key: "KeyG", shift: true }, - H: { key: "KeyH", shift: true }, - I: { key: "KeyI", shift: true }, - J: { key: "KeyJ", shift: true }, - K: { key: "KeyK", shift: true }, - L: { key: "KeyL", shift: true }, - M: { key: "KeyM", shift: true }, - N: { key: "KeyN", shift: true }, - O: { key: "KeyO", shift: true }, - P: { key: "KeyP", shift: true }, - Q: { key: "KeyQ", shift: true }, - R: { key: "KeyR", shift: true }, - S: { key: "KeyS", shift: true }, - T: { key: "KeyT", shift: true }, - U: { key: "KeyU", shift: true }, - V: { key: "KeyV", shift: true }, - W: { key: "KeyW", shift: true }, - X: { key: "KeyX", shift: true }, - Y: { key: "KeyY", shift: true }, - Z: { key: "KeyZ", shift: true }, - a: { key: "KeyA", shift: false }, - b: { key: "KeyB", shift: false }, - c: { key: "KeyC", shift: false }, - d: { key: "KeyD", shift: false }, - e: { key: "KeyE", shift: false }, - f: { key: "KeyF", shift: false }, - g: { key: "KeyG", shift: false }, - h: { key: "KeyH", shift: false }, - i: { key: "KeyI", shift: false }, - j: { key: "KeyJ", shift: false }, - k: { key: "KeyK", shift: false }, - l: { key: "KeyL", shift: false }, - m: { key: "KeyM", shift: false }, - n: { key: "KeyN", shift: false }, - o: { key: "KeyO", shift: false }, - p: { key: "KeyP", shift: false }, - q: { key: "KeyQ", shift: false }, - r: { key: "KeyR", shift: false }, - s: { key: "KeyS", shift: false }, - t: { key: "KeyT", shift: false }, - u: { key: "KeyU", shift: false }, - v: { key: "KeyV", shift: false }, - w: { key: "KeyW", shift: false }, - x: { key: "KeyX", shift: false }, - y: { key: "KeyY", shift: false }, - z: { key: "KeyZ", shift: false }, - 1: { key: "Digit1", shift: false }, - "!": { key: "Digit1", shift: true }, - 2: { key: "Digit2", shift: false }, - "@": { key: "Digit2", shift: true }, - 3: { key: "Digit3", shift: false }, - "#": { key: "Digit3", shift: true }, - 4: { key: "Digit4", shift: false }, - $: { key: "Digit4", shift: true }, - "%": { key: "Digit5", shift: true }, - 5: { key: "Digit5", shift: false }, - "^": { key: "Digit6", shift: true }, - 6: { key: "Digit6", shift: false }, - "&": { key: "Digit7", shift: true }, - 7: { key: "Digit7", shift: false }, - "*": { key: "Digit8", shift: true }, - 8: { key: "Digit8", shift: false }, - "(": { key: "Digit9", shift: true }, - 9: { key: "Digit9", shift: false }, - ")": { key: "Digit0", shift: true }, - 0: { key: "Digit0", shift: false }, - "-": { key: "Minus", shift: false }, - _: { key: "Minus", shift: true }, - "=": { key: "Equal", shift: false }, - "+": { key: "Equal", shift: true }, - "'": { key: "Quote", shift: false }, - '"': { key: "Quote", shift: true }, - ",": { key: "Comma", shift: false }, - "<": { key: "Comma", shift: true }, - "/": { key: "Slash", shift: false }, - "?": { key: "Slash", shift: true }, - ".": { key: "Period", shift: false }, - ">": { key: "Period", shift: true }, - ";": { key: "Semicolon", shift: false }, - ":": { key: "Semicolon", shift: true }, - "[": { key: "BracketLeft", shift: false }, - "{": { key: "BracketLeft", shift: true }, - "]": { key: "BracketRight", shift: false }, - "}": { key: "BracketRight", shift: true }, - "\\": { key: "Backslash", shift: false }, - "|": { key: "Backslash", shift: true }, - "`": { key: "Backquote", shift: false }, - "~": { key: "Backquote", shift: true }, - "§": { key: "IntlBackslash", shift: false }, - "±": { key: "IntlBackslash", shift: true }, - " ": { key: "Space", shift: false }, - "\n": { key: "Enter", shift: false }, - Enter: { key: "Enter", shift: false }, - Tab: { key: "Tab", shift: false }, -} as Record; - export const modifiers = { ControlLeft: 0x01, ControlRight: 0x10, diff --git a/ui/src/main.tsx b/ui/src/main.tsx index f4bdd34..18ae323 100644 --- a/ui/src/main.tsx +++ b/ui/src/main.tsx @@ -32,7 +32,8 @@ import { CLOUD_API, DEVICE_API } from "./ui.config"; import OtherSessionRoute from "./routes/devices.$id.other-session"; import MountRoute from "./routes/devices.$id.mount"; import * as SettingsRoute from "./routes/devices.$id.settings"; -import SettingsKeyboardMouseRoute from "./routes/devices.$id.settings.mouse"; +import SettingsMouseRoute from "./routes/devices.$id.settings.mouse"; +import SettingsKeyboardRoute from "./routes/devices.$id.settings.keyboard"; import api from "./api"; import * as SettingsIndexRoute from "./routes/devices.$id.settings._index"; import SettingsAdvancedRoute from "./routes/devices.$id.settings.advanced"; @@ -147,7 +148,11 @@ if (isOnDevice) { }, { path: "mouse", - element: , + element: , + }, + { + path: "keyboard", + element: , }, { path: "advanced", @@ -276,7 +281,11 @@ if (isOnDevice) { }, { path: "mouse", - element: , + element: , + }, + { + path: "keyboard", + element: , }, { path: "advanced", diff --git a/ui/src/routes/devices.$id.settings.keyboard.tsx b/ui/src/routes/devices.$id.settings.keyboard.tsx new file mode 100644 index 0000000..b4981af --- /dev/null +++ b/ui/src/routes/devices.$id.settings.keyboard.tsx @@ -0,0 +1,77 @@ +import { useCallback, useEffect } from "react"; + +import { useDeviceSettingsStore } from "@/hooks/stores"; +import { useJsonRpc } from "@/hooks/useJsonRpc"; +import notifications from "@/notifications"; +import { SettingsPageHeader } from "@components/SettingsPageheader"; +import { layouts } from "@/keyboardLayouts"; + +import { FeatureFlag } from "../components/FeatureFlag"; +import { SelectMenuBasic } from "../components/SelectMenuBasic"; + +import { SettingsItem } from "./devices.$id.settings"; + +export default function SettingsKeyboardRoute() { + const keyboardLayout = useDeviceSettingsStore(state => state.keyboardLayout); + const setKeyboardLayout = useDeviceSettingsStore( + state => state.setKeyboardLayout, + ); + + const layoutOptions = Object.entries(layouts).map(([code, language]) => { return { value: code, label: language } }) + + const [send] = useJsonRpc(); + + useEffect(() => { + send("getKeyboardLayout", {}, resp => { + if ("error" in resp) return; + setKeyboardLayout(resp.result as string); + }); + }, []); + + const onKeyboardLayoutChange = useCallback( + (e: React.ChangeEvent) => { + const layout = e.target.value; + send("setKeyboardLayout", { layout }, resp => { + if ("error" in resp) { + notifications.error( + `Failed to set keyboard layout: ${resp.error.data || "Unknown error"}`, + ); + } + notifications.success("Keyboard layout set successfully"); + setKeyboardLayout(layout); + }); + }, + [send, setKeyboardLayout], + ); + + return ( +
+ + +
+ + { /* this menu item could be renamed to plain "Keyboard layout" in the future, when also the virtual keyboard layout mappings are being implemented */ } + + + +

+ Pasting text sends individual key strokes to the target device. The keyboard layout determines which key codes are being sent. Ensure that the keyboard layout in JetKVM matches the settings in the operating system. +

+
+
+
+ ); +} diff --git a/ui/src/routes/devices.$id.settings.mouse.tsx b/ui/src/routes/devices.$id.settings.mouse.tsx index d6223d0..14cc890 100644 --- a/ui/src/routes/devices.$id.settings.mouse.tsx +++ b/ui/src/routes/devices.$id.settings.mouse.tsx @@ -18,7 +18,7 @@ import { SettingsItem } from "./devices.$id.settings"; type ScrollSensitivity = "low" | "default" | "high"; -export default function SettingsKeyboardMouseRoute() { +export default function SettingsMouseRoute() { const hideCursor = useSettingsStore(state => state.isCursorHidden); const setHideCursor = useSettingsStore(state => state.setCursorVisibility); diff --git a/ui/src/routes/devices.$id.settings.tsx b/ui/src/routes/devices.$id.settings.tsx index f8e5262..182f873 100644 --- a/ui/src/routes/devices.$id.settings.tsx +++ b/ui/src/routes/devices.$id.settings.tsx @@ -1,6 +1,7 @@ import { NavLink, Outlet, useLocation } from "react-router-dom"; import { LuSettings, + LuMouse, LuKeyboard, LuVideo, LuCpu, @@ -148,11 +149,22 @@ export default function SettingsRoute() { className={({ isActive }) => (isActive ? "active" : "")} >
- +

Mouse

+
+ (isActive ? "active" : "")} + > +
+ +

Keyboard

+
+
+