mirror of https://github.com/jetkvm/kvm.git
Compare commits
4 Commits
ba0a325e78
...
b1c1ef8e51
Author | SHA1 | Date |
---|---|---|
|
b1c1ef8e51 | |
|
681b9c0b6e | |
|
efb7539537 | |
|
f26862d2e3 |
|
@ -264,7 +264,10 @@ export default function Actionbar({
|
|||
theme="light"
|
||||
text="Settings"
|
||||
LeadingIcon={LuSettings}
|
||||
onClick={() => navigateTo("/settings")}
|
||||
onClick={() => {
|
||||
setDisableVideoFocusTrap(true);
|
||||
navigateTo("/settings")
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ export function JigglerSetting({
|
|||
},
|
||||
);
|
||||
|
||||
const [send] = useJsonRpc();
|
||||
const { send } = useJsonRpc();
|
||||
const [timezones, setTimezones] = useState<string[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
import { useState } from "react";
|
||||
import { LuPlus } from "react-icons/lu";
|
||||
|
||||
import { KeySequence } from "@/hooks/stores";
|
||||
import { Button } from "@/components/Button";
|
||||
import { InputFieldWithLabel, FieldError } from "@/components/InputField";
|
||||
import FieldLabel from "@/components/FieldLabel";
|
||||
import Fieldset from "@/components/Fieldset";
|
||||
import { InputFieldWithLabel, FieldError } from "@/components/InputField";
|
||||
import { MacroStepCard } from "@/components/MacroStepCard";
|
||||
import {
|
||||
DEFAULT_DELAY,
|
||||
MAX_STEPS_PER_MACRO,
|
||||
MAX_KEYS_PER_STEP,
|
||||
} from "@/constants/macros";
|
||||
import FieldLabel from "@/components/FieldLabel";
|
||||
import { KeySequence } from "@/hooks/stores";
|
||||
import { useKeyboardLayout } from "@/hooks/useKeyboardLayout";
|
||||
|
||||
interface ValidationErrors {
|
||||
name?: string;
|
||||
|
@ -44,6 +45,7 @@ export function MacroForm({
|
|||
const [keyQueries, setKeyQueries] = useState<Record<number, string>>({});
|
||||
const [errors, setErrors] = useState<ValidationErrors>({});
|
||||
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
||||
const { keyboard } = useKeyboardLayout();
|
||||
|
||||
const showTemporaryError = (message: string) => {
|
||||
setErrorMessage(message);
|
||||
|
@ -234,6 +236,7 @@ export function MacroForm({
|
|||
}
|
||||
onDelayChange={delay => handleDelayChange(stepIndex, delay)}
|
||||
isLastStep={stepIndex === (macro.steps?.length || 0) - 1}
|
||||
keyboard={keyboard}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
@ -4,19 +4,22 @@ import { Button } from "@/components/Button";
|
|||
import { Combobox } from "@/components/Combobox";
|
||||
import { SelectMenuBasic } from "@/components/SelectMenuBasic";
|
||||
import Card from "@/components/Card";
|
||||
import { keys, modifiers, keyDisplayMap } from "@/keyboardMappings";
|
||||
import { MAX_KEYS_PER_STEP, DEFAULT_DELAY } from "@/constants/macros";
|
||||
import FieldLabel from "@/components/FieldLabel";
|
||||
import { MAX_KEYS_PER_STEP, DEFAULT_DELAY } from "@/constants/macros";
|
||||
import { KeyboardLayout } from "@/keyboardLayouts";
|
||||
import { keys, modifiers } from "@/keyboardMappings";
|
||||
|
||||
// Filter out modifier keys since they're handled in the modifiers section
|
||||
const modifierKeyPrefixes = ['Alt', 'Control', 'Shift', 'Meta'];
|
||||
|
||||
const keyOptions = Object.keys(keys)
|
||||
const keyOptions = (keyDisplayMap: Record<string, string>) => {
|
||||
return Object.keys(keys)
|
||||
.filter(key => !modifierKeyPrefixes.some(prefix => key.startsWith(prefix)))
|
||||
.map(key => ({
|
||||
value: key,
|
||||
label: keyDisplayMap[key] || key,
|
||||
}));
|
||||
}
|
||||
|
||||
const modifierOptions = Object.keys(modifiers).map(modifier => ({
|
||||
value: modifier,
|
||||
|
@ -67,6 +70,7 @@ interface MacroStepCardProps {
|
|||
onModifierChange: (modifiers: string[]) => void;
|
||||
onDelayChange: (delay: number) => void;
|
||||
isLastStep: boolean;
|
||||
keyboard: KeyboardLayout
|
||||
}
|
||||
|
||||
const ensureArray = <T,>(arr: T[] | null | undefined): T[] => {
|
||||
|
@ -84,11 +88,14 @@ export function MacroStepCard({
|
|||
keyQuery,
|
||||
onModifierChange,
|
||||
onDelayChange,
|
||||
isLastStep
|
||||
isLastStep,
|
||||
keyboard
|
||||
}: MacroStepCardProps) {
|
||||
const { keyDisplayMap } = keyboard;
|
||||
|
||||
const getFilteredKeys = () => {
|
||||
const selectedKeys = ensureArray(step.keys);
|
||||
const availableKeys = keyOptions.filter(option => !selectedKeys.includes(option.value));
|
||||
const availableKeys = keyOptions(keyDisplayMap).filter(option => !selectedKeys.includes(option.value));
|
||||
|
||||
if (keyQuery === '') {
|
||||
return availableKeys;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { ChevronDownIcon } from "@heroicons/react/16/solid";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import Keyboard from "react-simple-keyboard";
|
||||
|
||||
import Card from "@components/Card";
|
||||
|
@ -14,7 +14,8 @@ import DetachIconRaw from "@/assets/detach-icon.svg";
|
|||
import { cx } from "@/cva.config";
|
||||
import { useHidStore, useUiStore } from "@/hooks/stores";
|
||||
import useKeyboard from "@/hooks/useKeyboard";
|
||||
import { keyDisplayMap, keys } from "@/keyboardMappings";
|
||||
import { useKeyboardLayout } from "@/hooks/useKeyboardLayout";
|
||||
import { keys, modifiers, latchingKeys, decodeModifiers } from "@/keyboardMappings";
|
||||
|
||||
export const DetachIcon = ({ className }: { className?: string }) => {
|
||||
return <img src={DetachIconRaw} alt="Detach Icon" className={className} />;
|
||||
|
@ -25,31 +26,40 @@ const AttachIcon = ({ className }: { className?: string }) => {
|
|||
};
|
||||
|
||||
function KeyboardWrapper() {
|
||||
const [layoutName] = useState("default");
|
||||
|
||||
const keyboardRef = useRef<HTMLDivElement>(null);
|
||||
const { isAttachedVirtualKeyboardVisible, setAttachedVirtualKeyboardVisibility } = useUiStore();
|
||||
const { keysDownState, isVirtualKeyboardEnabled, setVirtualKeyboardEnabled } = useHidStore();
|
||||
const { keysDownState, /* keyboardLedState,*/ isVirtualKeyboardEnabled, setVirtualKeyboardEnabled } = useHidStore();
|
||||
const { handleKeyPress, executeMacro } = useKeyboard();
|
||||
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
const [position, setPosition] = useState({ x: 0, y: 0 });
|
||||
const [newPosition, setNewPosition] = useState({ x: 0, y: 0 });
|
||||
|
||||
/*
|
||||
// These will be used to display the currently pressed keys and modifiers on the virtual keyboard
|
||||
const { keyboard } = useKeyboardLayout();
|
||||
|
||||
// used to show the modifier keys that are in the "down state" on the virtual keyboard
|
||||
const keyNamesFromModifierMask = (activeModifiers: number): string[] => {
|
||||
return Object.entries(modifiers).filter(m => (activeModifiers & m[1]) !== 0).map(m => m[0]);
|
||||
}
|
||||
//const isCapsLockActive = useMemo(() => {
|
||||
// return (keyboardLedState.caps_lock);
|
||||
//}, [keyboardLedState]);
|
||||
|
||||
// used to show the regular keys that are in the "down state" on the virtual keyboard
|
||||
const keyNamesFromDownKeys = (downKeys: number[]) => {
|
||||
return Object.entries(keys).filter(([_, code]) => downKeys.includes(code)).map(([name, _]) => name);
|
||||
}
|
||||
*/
|
||||
const { isShiftActive, /*isControlActive, isAltActive, isMetaActive, isAltGrActive*/ } = useMemo(() => {
|
||||
return decodeModifiers(keysDownState.modifier);
|
||||
}, [keysDownState]);
|
||||
|
||||
const mainLayoutName = useMemo(() => {
|
||||
const layoutName = isShiftActive ? "shift": "default";
|
||||
return layoutName;
|
||||
}, [isShiftActive]);
|
||||
|
||||
const keyNamesForDownKeys = useMemo(() => {
|
||||
const activeModifierMask = keysDownState.modifier || 0;
|
||||
const modifierNames = Object.entries(modifiers).filter(([_, mask]) => (activeModifierMask & mask) !== 0).map(([name, _]) => name);
|
||||
|
||||
const keysDown = keysDownState.keys || [];
|
||||
const keyNames = Object.entries(keys).filter(([_, value]) => keysDown.includes(value)).map(([name, _]) => name);
|
||||
|
||||
return [...modifierNames,...keyNames, ' ']; // we have to have at least one space to avoid keyboard whining
|
||||
}, [keysDownState]);
|
||||
|
||||
const startDrag = useCallback((e: MouseEvent | TouchEvent) => {
|
||||
if (!keyboardRef.current) return;
|
||||
if (e instanceof TouchEvent && e.touches.length > 1) return;
|
||||
|
@ -119,10 +129,18 @@ function KeyboardWrapper() {
|
|||
};
|
||||
}, [endDrag, onDrag, startDrag]);
|
||||
|
||||
const onKeyUp = useCallback(
|
||||
async (_: string, e: MouseEvent | undefined) => {
|
||||
e?.preventDefault();
|
||||
e?.stopPropagation();
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const onKeyDown = useCallback(
|
||||
async (key: string) => {
|
||||
const latchingKeys = ["CapsLock", "ScrollLock", "NumLock", "Meta", "Compose", "Kana"];
|
||||
const dynamicKeys = ["ShiftLeft", "ShiftRight", "ControlLeft", "ControlRight", "AltLeft", "AltRight", "MetaLeft", "MetaRight"];
|
||||
async (key: string, e: MouseEvent | undefined) => {
|
||||
e?.preventDefault();
|
||||
e?.stopPropagation();
|
||||
|
||||
// handle the fake key-macros we have defined for common combinations
|
||||
if (key === "CtrlAltDelete") {
|
||||
|
@ -149,8 +167,8 @@ function KeyboardWrapper() {
|
|||
}
|
||||
|
||||
// if they press any of the dynamic keys, we send a keypress down event but we don't release it until they click it again
|
||||
if (dynamicKeys.includes(key)) {
|
||||
const currentlyDown = keysDownState.keys.includes(keys[key]);
|
||||
if (Object.keys(modifiers).includes(key)) {
|
||||
const currentlyDown = keyNamesForDownKeys.includes(key);
|
||||
console.debug(`Dynamic key pressed: ${key} was currently down: ${currentlyDown}, toggling state`);
|
||||
handleKeyPress(keys[key], !currentlyDown)
|
||||
return;
|
||||
|
@ -162,16 +180,9 @@ function KeyboardWrapper() {
|
|||
handleKeyPress(keys[cleanKey], true);
|
||||
setTimeout(() => handleKeyPress(keys[cleanKey], false), 50);
|
||||
},
|
||||
[executeMacro, handleKeyPress, keysDownState],
|
||||
[executeMacro, handleKeyPress, keyNamesForDownKeys],
|
||||
);
|
||||
|
||||
// TODO handle the display of down keys and the layout change for shift/caps lock
|
||||
// const { isCapsLockActive } = useShallow(useHidStore());
|
||||
// // Handle toggle of layout for shift or caps lock
|
||||
// const toggleLayout = () => {
|
||||
// setLayoutName(prevLayout => (prevLayout === "default" ? "shift" : "default"));
|
||||
// };
|
||||
|
||||
return (
|
||||
<div
|
||||
className="transition-all duration-500 ease-in-out"
|
||||
|
@ -245,66 +256,71 @@ function KeyboardWrapper() {
|
|||
<div className="flex flex-col bg-blue-50/80 md:flex-row dark:bg-slate-700">
|
||||
<Keyboard
|
||||
baseClass="simple-keyboard-main"
|
||||
layoutName={layoutName}
|
||||
layoutName={mainLayoutName}
|
||||
onKeyPress={onKeyDown}
|
||||
onKeyReleased={onKeyUp}
|
||||
buttonTheme={[
|
||||
{
|
||||
class: "combination-key",
|
||||
buttons: "CtrlAltDelete AltMetaEscape CtrlAltBackspace",
|
||||
},
|
||||
{
|
||||
class: "down-key",
|
||||
buttons: keyNamesForDownKeys.join(" "),
|
||||
},
|
||||
]}
|
||||
display={keyDisplayMap}
|
||||
layout={{
|
||||
default: [
|
||||
"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",
|
||||
"CapsLock KeyA KeyS KeyD KeyF KeyG KeyH KeyJ KeyK KeyL Semicolon Quote Enter",
|
||||
"ShiftLeft KeyZ KeyX KeyC KeyV KeyB KeyN KeyM Comma Period Slash ShiftRight",
|
||||
"ControlLeft AltLeft MetaLeft Space MetaRight AltRight",
|
||||
],
|
||||
shift: [
|
||||
"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)",
|
||||
"CapsLock (KeyA) (KeyS) (KeyD) (KeyF) (KeyG) (KeyH) (KeyJ) (KeyK) (KeyL) (Semicolon) (Quote) Enter",
|
||||
"ShiftLeft (KeyZ) (KeyX) (KeyC) (KeyV) (KeyB) (KeyN) (KeyM) (Comma) (Period) (Slash) ShiftRight",
|
||||
"ControlLeft AltLeft MetaLeft Space MetaRight AltRight",
|
||||
],
|
||||
}}
|
||||
display={keyboard.keyDisplayMap}
|
||||
layout={keyboard.virtualKeyboard.main}
|
||||
disableButtonHold={true}
|
||||
syncInstanceInputs={true}
|
||||
debug={false}
|
||||
preventMouseDownDefault={true}
|
||||
preventMouseUpDefault={true}
|
||||
stopMouseDownPropagation={true}
|
||||
stopMouseUpPropagation={true}
|
||||
physicalKeyboardHighlight={true}
|
||||
physicalKeyboardHighlightPress={true}
|
||||
physicalKeyboardHighlightPreventDefault={true}
|
||||
enableLayoutCandidates={false}
|
||||
/>
|
||||
|
||||
<div className="controlArrows">
|
||||
<Keyboard
|
||||
baseClass="simple-keyboard-control"
|
||||
theme="simple-keyboard hg-theme-default hg-layout-default"
|
||||
layoutName={layoutName}
|
||||
layoutName="default"
|
||||
onKeyPress={onKeyDown}
|
||||
display={keyDisplayMap}
|
||||
layout={{
|
||||
default: ["PrintScreen ScrollLock Pause", "Insert Home Pageup", "Delete End Pagedown"],
|
||||
shift: ["(PrintScreen) ScrollLock (Pause)", "Insert Home Pageup", "Delete End Pagedown"],
|
||||
}}
|
||||
syncInstanceInputs={true}
|
||||
onKeyReleased={onKeyUp}
|
||||
display={keyboard.keyDisplayMap}
|
||||
layout={keyboard.virtualKeyboard.control}
|
||||
debug={false}
|
||||
preventMouseDownDefault={true}
|
||||
preventMouseUpDefault={true}
|
||||
stopMouseDownPropagation={true}
|
||||
stopMouseUpPropagation={true}
|
||||
physicalKeyboardHighlight={true}
|
||||
physicalKeyboardHighlightPress={true}
|
||||
physicalKeyboardHighlightPreventDefault={true}
|
||||
enableLayoutCandidates={false}
|
||||
/>
|
||||
<Keyboard
|
||||
baseClass="simple-keyboard-arrows"
|
||||
theme="simple-keyboard hg-theme-default hg-layout-default"
|
||||
onKeyPress={onKeyDown}
|
||||
display={keyDisplayMap}
|
||||
layout={{
|
||||
default: ["ArrowUp", "ArrowLeft ArrowDown ArrowRight"],
|
||||
}}
|
||||
syncInstanceInputs={true}
|
||||
onKeyReleased={onKeyUp}
|
||||
display={keyboard.keyDisplayMap}
|
||||
layout={keyboard.virtualKeyboard.arrows}
|
||||
debug={false}
|
||||
preventMouseDownDefault={true}
|
||||
preventMouseUpDefault={true}
|
||||
stopMouseDownPropagation={true}
|
||||
stopMouseUpPropagation={true}
|
||||
physicalKeyboardHighlight={true}
|
||||
physicalKeyboardHighlightPress={true}
|
||||
physicalKeyboardHighlightPreventDefault={true}
|
||||
enableLayoutCandidates={false}
|
||||
/>
|
||||
</div>
|
||||
{ /* TODO add optional number pad */ }
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { LuCornerDownLeft } from "react-icons/lu";
|
||||
import { ExclamationCircleIcon } from "@heroicons/react/16/solid";
|
||||
import { useClose } from "@headlessui/react";
|
||||
|
@ -10,7 +10,8 @@ import { SettingsPageHeader } from "@components/SettingsPageheader";
|
|||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||
import { useHidStore, useRTCStore, useUiStore, useSettingsStore } from "@/hooks/stores";
|
||||
import { keys, modifiers } from "@/keyboardMappings";
|
||||
import { KeyStroke, KeyboardLayout, selectedKeyboard } from "@/keyboardLayouts";
|
||||
import { KeyStroke } from "@/keyboardLayouts";
|
||||
import { useKeyboardLayout } from "@/hooks/useKeyboardLayout";
|
||||
import notifications from "@/notifications";
|
||||
|
||||
const hidKeyboardPayload = (modifier: number, keys: number[]) => {
|
||||
|
@ -18,8 +19,8 @@ const hidKeyboardPayload = (modifier: number, keys: number[]) => {
|
|||
};
|
||||
|
||||
const modifierCode = (shift?: boolean, altRight?: boolean) => {
|
||||
return (shift ? modifiers["ShiftLeft"] : 0)
|
||||
| (altRight ? modifiers["AltRight"] : 0)
|
||||
return (shift ? modifiers.ShiftLeft : 0)
|
||||
| (altRight ? modifiers.AltRight : 0)
|
||||
}
|
||||
const noModifier = 0
|
||||
|
||||
|
@ -34,15 +35,8 @@ export default function PasteModal() {
|
|||
const [invalidChars, setInvalidChars] = useState<string[]>([]);
|
||||
const close = useClose();
|
||||
|
||||
const { keyboardLayout, setKeyboardLayout } = useSettingsStore();
|
||||
|
||||
// this ensures we always get the en-US if it hasn't been set yet
|
||||
// and if we get en_US from the backend, we convert it to en-US
|
||||
const safeKeyboardLayout = useMemo(() => {
|
||||
if (keyboardLayout && keyboardLayout.length > 0)
|
||||
return keyboardLayout.replace("en_US", "en-US");
|
||||
return "en-US";
|
||||
}, [keyboardLayout]);
|
||||
const { setKeyboardLayout } = useSettingsStore();
|
||||
const { keyboard } = useKeyboardLayout();
|
||||
|
||||
useEffect(() => {
|
||||
send("getKeyboardLayout", {}, resp => {
|
||||
|
@ -62,7 +56,6 @@ export default function PasteModal() {
|
|||
setDisableVideoFocusTrap(false);
|
||||
|
||||
if (rpcDataChannel?.readyState !== "open" || !TextAreaRef.current) return;
|
||||
const keyboard: KeyboardLayout = selectedKeyboard(safeKeyboardLayout);
|
||||
if (!keyboard) return;
|
||||
|
||||
const text = TextAreaRef.current.value;
|
||||
|
@ -109,7 +102,7 @@ export default function PasteModal() {
|
|||
);
|
||||
});
|
||||
}
|
||||
}, [rpcDataChannel?.readyState, safeKeyboardLayout, send, setDisableVideoFocusTrap, setPasteModeEnabled]);
|
||||
}, [keyboard, rpcDataChannel?.readyState, send, setDisableVideoFocusTrap, setPasteModeEnabled]);
|
||||
|
||||
useEffect(() => {
|
||||
if (TextAreaRef.current) {
|
||||
|
@ -159,7 +152,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 => !selectedKeyboard(safeKeyboardLayout).chars[char]),
|
||||
.filter(char => !keyboard.chars[char]),
|
||||
),
|
||||
];
|
||||
|
||||
|
@ -180,7 +173,7 @@ export default function PasteModal() {
|
|||
</div>
|
||||
<div className="space-y-4">
|
||||
<p className="text-xs text-slate-600 dark:text-slate-400">
|
||||
Sending text using keyboard layout: {selectedKeyboard(safeKeyboardLayout).name}
|
||||
Sending text using keyboard layout: {keyboard.isoCode}-{keyboard.name}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -6,9 +6,7 @@ import { hidKeyToModifierMask, keys, modifiers } from "@/keyboardMappings";
|
|||
|
||||
export default function useKeyboard() {
|
||||
const { send } = useJsonRpc();
|
||||
|
||||
const { rpcDataChannel } = useRTCStore();
|
||||
|
||||
const { keysDownState, setKeysDownState } = useHidStore();
|
||||
|
||||
// INTRODUCTION: The earlier version of the JetKVM device shipped with all keyboard state
|
||||
|
@ -23,8 +21,8 @@ export default function useKeyboard() {
|
|||
// getKeysDownState API.
|
||||
const { keyPressReportApiAvailable, setkeyPressReportApiAvailable} = useHidStore();
|
||||
|
||||
// sendKeyboardEvent is used to send the full keyboard state to the device for macro handling and resetting keyboard state.
|
||||
// It sends the keys currently pressed and the modifier state.
|
||||
// sendKeyboardEvent is used to send the full keyboard state to the device for macro handling
|
||||
// and resetting keyboard state. It sends the keys currently pressed and the modifier state.
|
||||
// The device will respond with the keysDownState if it supports the keyPressReport API
|
||||
// or just accept the state if it does not support (returning no result)
|
||||
const sendKeyboardEvent = useCallback(
|
||||
|
@ -93,7 +91,6 @@ export default function useKeyboard() {
|
|||
// is clean.
|
||||
const resetKeyboardState = useCallback(
|
||||
async () => {
|
||||
console.debug("Resetting keyboard state");
|
||||
// Reset the keys buffer to zeros and the modifier state to zero
|
||||
keysDownState.keys.length = hidKeyBufferSize;
|
||||
keysDownState.keys.fill(0);
|
||||
|
@ -139,6 +136,7 @@ export default function useKeyboard() {
|
|||
const handleKeyPress = useCallback(
|
||||
async (key: number, press: boolean) => {
|
||||
if (rpcDataChannel?.readyState !== "open") return;
|
||||
if ((key || 0) === 0) return; // ignore zero key presses (they are bad mappings)
|
||||
|
||||
if (keyPressReportApiAvailable) {
|
||||
// if the keyPress api is available, we can just send the key press event
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import { useMemo } from "react";
|
||||
|
||||
import { useSettingsStore } from "@/hooks/stores";
|
||||
import { KeyboardLayout, selectedKeyboard } from "@/keyboardLayouts";
|
||||
|
||||
export function useKeyboardLayout(): { keyboard: KeyboardLayout } {
|
||||
const { keyboardLayout } = useSettingsStore();
|
||||
|
||||
const isoCode = useMemo(() => {
|
||||
console.log("Current keyboard layout from store:", keyboardLayout);
|
||||
if (keyboardLayout && keyboardLayout.length > 0)
|
||||
return keyboardLayout.replace("en_US", "en-US");
|
||||
return "en-US";
|
||||
}, [keyboardLayout]);
|
||||
|
||||
const keyboard = useMemo(() => {
|
||||
console.log("Selected keyboard layout:", isoCode);
|
||||
return selectedKeyboard(isoCode);
|
||||
}, [isoCode]);
|
||||
|
||||
return { keyboard };
|
||||
}
|
|
@ -315,6 +315,11 @@ video::-webkit-media-controls {
|
|||
@apply inline-flex h-auto! w-auto! grow-0 py-1 text-xs;
|
||||
}
|
||||
|
||||
.hg-theme-default .hg-row .down-key {
|
||||
background: rgb(28, 28, 28);
|
||||
@apply text-white! font-bold!;
|
||||
}
|
||||
|
||||
.hg-theme-default .hg-row .hg-button-container,
|
||||
.hg-theme-default .hg-row .hg-button:not(:last-child) {
|
||||
@apply mr-[2px]! md:mr-[5px]!;
|
||||
|
|
|
@ -1,7 +1,18 @@
|
|||
export interface KeyStroke { modifier: number; keys: number[]; }
|
||||
export interface KeyInfo { key: string | number; shift?: boolean, altRight?: boolean }
|
||||
export interface KeyCombo extends KeyInfo { deadKey?: boolean, accentKey?: KeyInfo }
|
||||
export interface KeyboardLayout { isoCode: string, name: string, chars: Record<string, KeyCombo> }
|
||||
export interface KeyboardLayout {
|
||||
isoCode: string;
|
||||
name: string;
|
||||
chars: Record<string, KeyCombo>;
|
||||
modifierDisplayMap: Record<string, string>;
|
||||
keyDisplayMap: Record<string, string>;
|
||||
virtualKeyboard: {
|
||||
main: { default: string[], shift: string[] },
|
||||
control?: { default: string[], shift?: string[] },
|
||||
arrows?: { default: string[] }
|
||||
};
|
||||
}
|
||||
|
||||
// to add a new layout, create a file like the above and add it to the list
|
||||
import { cs_CZ } from "@/keyboardLayouts/cs_CZ"
|
||||
|
@ -15,13 +26,14 @@ import { fr_CH } from "@/keyboardLayouts/fr_CH"
|
|||
import { fr_FR } from "@/keyboardLayouts/fr_FR"
|
||||
import { it_IT } from "@/keyboardLayouts/it_IT"
|
||||
import { nb_NO } from "@/keyboardLayouts/nb_NO"
|
||||
import { pl_PL_t } from "@/keyboardLayouts/pl_PL_t"
|
||||
import { sv_SE } from "@/keyboardLayouts/sv_SE"
|
||||
|
||||
export const keyboards: KeyboardLayout[] = [ cs_CZ, de_CH, de_DE, en_UK, en_US, es_ES, fr_BE, fr_CH, fr_FR, it_IT, nb_NO, sv_SE ];
|
||||
export const keyboards: KeyboardLayout[] = [ cs_CZ, de_CH, de_DE, en_UK, en_US, es_ES, fr_BE, fr_CH, fr_FR, it_IT, nb_NO, pl_PL_t, sv_SE ];
|
||||
|
||||
export const selectedKeyboard = (isoCode: string): KeyboardLayout => {
|
||||
// fallback to original behaviour of en-US if no isoCode given
|
||||
return keyboards.find(keyboard => keyboard.isoCode == isoCode)
|
||||
// fallback to original behaviour of en-US if no isoCode given or matching layout not found
|
||||
return keyboards.find(keyboard => keyboard.isoCode == isoCode)
|
||||
?? keyboards.find(keyboard => keyboard.isoCode == "en-US")!;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
|
||||
|
||||
const name = "Čeština";
|
||||
import { en_US } from "./en_US" // for fallback of keyDisplayMap, modifierDisplayMap, and virtualKeyboard
|
||||
|
||||
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
|
||||
const name = "Čeština";
|
||||
const isoCode = "cs-CZ";
|
||||
|
||||
const keyTrema: KeyCombo = { key: "Backslash" } // tréma (umlaut), two dots placed above a vowel
|
||||
const keyAcute: KeyCombo = { key: "Equal" } // accent aigu (acute accent), mark ´ placed above the letter
|
||||
const keyHat: KeyCombo = { key: "Digit3", shift: true, altRight: true } // accent circonflexe (accent hat), mark ^ placed above the letter
|
||||
const keyCaron: KeyCombo = { key: "Equal", shift: true } // caron or haček (inverted hat), mark ˇ placed above the letter
|
||||
const keyGrave: KeyCombo = { key: "Digit7", shift: true, altRight: true } // accent grave, mark ` placed above the letter
|
||||
const keyTilde: KeyCombo = { key: "Digit1", shift: true, altRight: true } // tilde, mark ~ placed above the letter
|
||||
const keyRing: KeyCombo = { key: "Backquote", shift: true } // kroužek (little ring), mark ° placed above the letter
|
||||
const keyOverdot: KeyCombo = { key: "Digit8", shift: true, altRight: true } // overdot (dot above), mark ˙ placed above the letter
|
||||
const keyHook: KeyCombo = { key: "Digit6", shift: true, altRight: true } // ogonoek (little hook), mark ˛ placed beneath a letter
|
||||
const keyCedille: KeyCombo = { key: "Equal", shift: true, altRight: true } // accent cedille (cedilla), mark ¸ placed beneath a letter
|
||||
|
||||
const chars = {
|
||||
A: { key: "KeyA", shift: true },
|
||||
|
@ -244,7 +247,11 @@ const chars = {
|
|||
} as Record<string, KeyCombo>;
|
||||
|
||||
export const cs_CZ: KeyboardLayout = {
|
||||
isoCode: "cs-CZ",
|
||||
isoCode: isoCode,
|
||||
name: name,
|
||||
chars: chars
|
||||
chars: chars,
|
||||
// TODO need to localize these maps and layouts
|
||||
keyDisplayMap: en_US.keyDisplayMap,
|
||||
modifierDisplayMap: en_US.modifierDisplayMap,
|
||||
virtualKeyboard: en_US.virtualKeyboard
|
||||
};
|
|
@ -1,12 +1,15 @@
|
|||
import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
|
||||
|
||||
const name = "Schwiizerdütsch";
|
||||
import { en_US } from "./en_US" // for fallback of keyDisplayMap, modifierDisplayMap, and virtualKeyboard
|
||||
|
||||
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
|
||||
const name = "Schwiizerdütsch";
|
||||
const isoCode = "de-CH";
|
||||
|
||||
const keyTrema: KeyCombo = { key: "BracketRight" } // tréma (umlaut), two dots placed above a vowel
|
||||
const keyAcute: KeyCombo = { key: "Minus", altRight: true } // accent aigu (acute accent), mark ´ placed above the letter
|
||||
const keyHat: KeyCombo = { key: "Equal" } // accent circonflexe (accent hat), mark ^ placed above the letter
|
||||
const keyGrave: KeyCombo = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter
|
||||
const keyTilde: KeyCombo = { key: "Equal", altRight: true } // tilde, mark ~ placed above the letter
|
||||
|
||||
const chars = {
|
||||
A: { key: "KeyA", shift: true },
|
||||
|
@ -164,8 +167,22 @@ const chars = {
|
|||
Tab: { key: "Tab" },
|
||||
} as Record<string, KeyCombo>;
|
||||
|
||||
const keyDisplayMap = {
|
||||
...en_US.keyDisplayMap,
|
||||
BracketLeft: "è",
|
||||
"(BracketLeft)": "ü",
|
||||
Semicolon: "é",
|
||||
"(Semicolon)": "ö",
|
||||
Quote: "à",
|
||||
"(Quote)": "ä",
|
||||
} as Record<string, string>;
|
||||
|
||||
export const de_CH: KeyboardLayout = {
|
||||
isoCode: "de-CH",
|
||||
isoCode: isoCode,
|
||||
name: name,
|
||||
chars: chars
|
||||
chars: chars,
|
||||
keyDisplayMap: keyDisplayMap,
|
||||
// TODO need to localize these maps and layouts
|
||||
modifierDisplayMap: en_US.modifierDisplayMap,
|
||||
virtualKeyboard: en_US.virtualKeyboard
|
||||
};
|
|
@ -1,113 +1,146 @@
|
|||
import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
|
||||
|
||||
const name = "Deutsch";
|
||||
import { en_US } from "./en_US" // for fallback of keyDisplayMap, modifierDisplayMap, and virtualKeyboard
|
||||
|
||||
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
|
||||
const name = "Deutsch";
|
||||
const isoCode = "de-DE";
|
||||
|
||||
const keyAcute: KeyCombo = { key: "Equal" } // accent aigu (acute accent), mark ´ placed above the letter
|
||||
const keyHat: KeyCombo = { key: "Backquote" } // accent circonflexe (accent hat), mark ^ placed above the letter
|
||||
const keyGrave: KeyCombo = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter
|
||||
|
||||
const chars = {
|
||||
a: { key: "KeyA" },
|
||||
"á": { key: "KeyA", accentKey: keyAcute },
|
||||
"â": { key: "KeyA", accentKey: keyHat },
|
||||
"à": { key: "KeyA", accentKey: keyGrave },
|
||||
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", altRight: true }, // white smiling face ☺
|
||||
b: { key: "KeyB" },
|
||||
B: { key: "KeyB", shift: true },
|
||||
"‹": { key: "KeyB", altRight: true }, // single left-pointing angle quotation mark, ‹
|
||||
c: { key: "KeyC" },
|
||||
C: { key: "KeyC", shift: true },
|
||||
"\u202f": { key: "KeyC", altRight: true }, // narrow no-break space
|
||||
d: { key: "KeyD" },
|
||||
D: { key: "KeyD", shift: true },
|
||||
"′": { key: "KeyD", altRight: true }, // prime, mark ′ placed above the letter
|
||||
e: { key: "KeyE" },
|
||||
"é": { key: "KeyE", accentKey: keyAcute },
|
||||
"ê": { key: "KeyE", accentKey: keyHat },
|
||||
"è": { key: "KeyE", accentKey: keyGrave },
|
||||
"€": { key: "KeyE", altRight: 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" },
|
||||
F: { key: "KeyF", shift: true },
|
||||
"˟": { key: "KeyF", deadKey: true, altRight: true }, // modifier letter cross accent, ˟
|
||||
G: { key: "KeyG", shift: true },
|
||||
g: { key: "KeyG" },
|
||||
"ẞ": { key: "KeyG", altRight: true }, // capital sharp S, ẞ
|
||||
h: { key: "KeyH" },
|
||||
H: { key: "KeyH", shift: true },
|
||||
"ˍ": { key: "KeyH", deadKey: true, altRight: true }, // modifier letter low macron, ˍ
|
||||
i: { key: "KeyI" },
|
||||
"í": { key: "KeyI", accentKey: keyAcute },
|
||||
"î": { key: "KeyI", accentKey: keyHat },
|
||||
"ì": { key: "KeyI", accentKey: keyGrave },
|
||||
I: { key: "KeyI", shift: true },
|
||||
"Í": { key: "KeyI", shift: true, accentKey: keyAcute },
|
||||
"Î": { key: "KeyI", shift: true, accentKey: keyHat },
|
||||
"Ì": { key: "KeyI", shift: true, accentKey: keyGrave },
|
||||
"˜": { key: "KeyI", deadKey: true, altRight: true }, // tilde accent, mark ˜ placed above the letter
|
||||
j: { key: "KeyJ" },
|
||||
J: { key: "KeyJ", shift: true },
|
||||
"¸": { key: "KeyJ", deadKey: true, altRight: true }, // cedilla accent, mark ¸ placed below the letter
|
||||
k: { key: "KeyK" },
|
||||
K: { key: "KeyK", shift: true },
|
||||
l: { key: "KeyL" },
|
||||
L: { key: "KeyL", shift: true },
|
||||
"ˏ": { key: "KeyL", deadKey: true, altRight: true }, // modifier letter reversed comma, ˏ
|
||||
m: { key: "KeyM" },
|
||||
M: { key: "KeyM", shift: true },
|
||||
"µ": { key: "KeyM", altRight: true },
|
||||
n: { key: "KeyN" },
|
||||
N: { key: "KeyN", shift: true },
|
||||
"–": { key: "KeyN", altRight: true }, // en dash, –
|
||||
o: { key: "KeyO" },
|
||||
"ó": { key: "KeyO", accentKey: keyAcute },
|
||||
"ô": { key: "KeyO", accentKey: keyHat },
|
||||
"ò": { key: "KeyO", accentKey: keyGrave },
|
||||
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", deadKey: true, altRight: true }, // ring above, ˚
|
||||
p: { key: "KeyP" },
|
||||
P: { key: "KeyP", shift: true },
|
||||
"ˀ": { key: "KeyP", deadKey: true, altRight: true }, // modifier letter apostrophe, ʾ
|
||||
q: { key: "KeyQ" },
|
||||
Q: { key: "KeyQ", shift: true },
|
||||
"@": { key: "KeyQ", altRight: true },
|
||||
R: { key: "KeyR", shift: true },
|
||||
r: { key: "KeyR" },
|
||||
"˝": { key: "KeyR", deadKey: true, altRight: true }, // double acute accent, mark ˝ placed above the letter
|
||||
S: { key: "KeyS", shift: true },
|
||||
s: { key: "KeyS" },
|
||||
"″": { key: "KeyS", altRight: true }, // double prime, mark ″ placed above the letter
|
||||
T: { key: "KeyT", shift: true },
|
||||
t: { key: "KeyT" },
|
||||
"ˇ": { key: "KeyT", deadKey: true, altRight: true }, // caron/hacek accent, mark ˇ placed above the letter
|
||||
u: { key: "KeyU" },
|
||||
"ú": { key: "KeyU", accentKey: keyAcute },
|
||||
"û": { key: "KeyU", accentKey: keyHat },
|
||||
"ù": { key: "KeyU", accentKey: keyGrave },
|
||||
U: { key: "KeyU", shift: true },
|
||||
"Ú": { key: "KeyU", shift: true, accentKey: keyAcute },
|
||||
"Û": { key: "KeyU", shift: true, accentKey: keyHat },
|
||||
"Ù": { key: "KeyU", shift: true, accentKey: keyGrave },
|
||||
"˘": { key: "KeyU", deadKey: true, altRight: true }, // breve accent, ˘ placed above the letter
|
||||
v: { key: "KeyV" },
|
||||
V: { key: "KeyV", shift: true },
|
||||
"«": { key: "KeyV", altRight: true }, // left-pointing double angle quotation mark, «
|
||||
w: { key: "KeyW" },
|
||||
W: { key: "KeyW", shift: true },
|
||||
"¯": { key: "KeyW", deadKey: true, altRight: true }, // macron accent, mark ¯ placed above the letter
|
||||
x: { key: "KeyX" },
|
||||
X: { key: "KeyX", shift: true },
|
||||
"»": { key: "KeyX", altRight: true },
|
||||
// cross key between shift and y (aka OEM 102 key)
|
||||
y: { key: "KeyZ" },
|
||||
Y: { key: "KeyZ", shift: true },
|
||||
"›": { key: "KeyZ", altRight: true }, // single right-pointing angle quotation mark, ›
|
||||
z: { key: "KeyY" },
|
||||
Z: { key: "KeyY", shift: true },
|
||||
"¨": { key: "KeyY", deadKey: true, altRight: true }, // diaeresis accent, mark ¨ placed above the letter
|
||||
"°": { key: "Backquote", shift: true },
|
||||
"^": { key: "Backquote", deadKey: true },
|
||||
"|": { key: "Backquote", altRight: true },
|
||||
1: { key: "Digit1" },
|
||||
"!": { key: "Digit1", shift: true },
|
||||
"’": { key: "Digit1", altRight: true }, // single quote, mark ’ placed above the letter
|
||||
2: { key: "Digit2" },
|
||||
"\"": { key: "Digit2", shift: true },
|
||||
"²": { key: "Digit2", altRight: true },
|
||||
"<": { key: "Digit2", altRight: true }, // non-US < and >
|
||||
3: { key: "Digit3" },
|
||||
"§": { key: "Digit3", shift: true },
|
||||
"³": { key: "Digit3", altRight: true },
|
||||
">": { key: "Digit3", altRight: true }, // non-US < and >
|
||||
4: { key: "Digit4" },
|
||||
"$": { key: "Digit4", shift: true },
|
||||
"—": { key: "Digit4", altRight: true }, // em dash, —
|
||||
5: { key: "Digit5" },
|
||||
"%": { key: "Digit5", shift: true },
|
||||
"¡": { key: "Digit5", altRight: true }, // inverted exclamation mark, ¡
|
||||
6: { key: "Digit6" },
|
||||
"&": { key: "Digit6", shift: true },
|
||||
"¿": { key: "Digit6", altRight: true }, // inverted question mark, ¿
|
||||
7: { key: "Digit7" },
|
||||
"/": { key: "Digit7", shift: true },
|
||||
"{": { key: "Digit7", altRight: true },
|
||||
|
@ -123,36 +156,192 @@ const chars = {
|
|||
"ß": { key: "Minus" },
|
||||
"?": { key: "Minus", shift: true },
|
||||
"\\": { key: "Minus", altRight: true },
|
||||
"´": { key: "Equal", deadKey: true },
|
||||
"`": { key: "Equal", shift: true, deadKey: true },
|
||||
"´": { key: "Equal", deadKey: true }, // accent acute, mark ´ placed above the letter
|
||||
"`": { key: "Equal", shift: true, deadKey: true }, // accent grave, mark ` placed above the letter
|
||||
"˙": { key: "Equal", control: true, altRight: true, deadKey: true }, // acute accent, mark ˙ placed above the letter
|
||||
"ü": { key: "BracketLeft" },
|
||||
"Ü": { key: "BracketLeft", shift: true },
|
||||
Escape: { key: "BracketLeft", control: true },
|
||||
"ʼ": { key: "BracketLeft", altRight: true }, // modifier letter apostrophe, ʼ
|
||||
"+": { key: "BracketRight" },
|
||||
"*": { key: "BracketRight", shift: true },
|
||||
Control: { key: "BracketRight", control: true },
|
||||
"~": { key: "BracketRight", altRight: true },
|
||||
"ö": { key: "Semicolon" },
|
||||
"Ö": { key: "Semicolon", shift: true },
|
||||
"ˌ": { key: "Semicolon", deadkey: true, altRight: true }, // modifier letter low vertical line, ˌ
|
||||
"ä": { key: "Quote" },
|
||||
"Ä": { key: "Quote", shift: true },
|
||||
"˗": { key: "Quote", deadKey: true, altRight: true }, // modifier letter minus sign, ˗
|
||||
"#": { key: "Backslash" },
|
||||
"'": { key: "Backslash", shift: true },
|
||||
"−": { key: "Backslash", altRight: true }, // minus sign, −
|
||||
",": { key: "Comma" },
|
||||
";": { key: "Comma", shift: true },
|
||||
"\u2011": { key: "Comma", altRight: true }, // non-breaking hyphen, ‑
|
||||
".": { key: "Period" },
|
||||
":": { key: "Period", shift: true },
|
||||
"·": { key: "Period", altRight: true }, // middle dot, ·
|
||||
"-": { key: "Slash" },
|
||||
"_": { key: "Slash", shift: true },
|
||||
"<": { key: "IntlBackslash" },
|
||||
">": { key: "IntlBackslash", shift: true },
|
||||
"|": { key: "IntlBackslash", altRight: true },
|
||||
"\u00ad": { key: "Slash", altRight: true }, // soft hyphen,
|
||||
" ": { key: "Space" },
|
||||
"\n": { key: "Enter" },
|
||||
Enter: { key: "Enter" },
|
||||
Tab: { key: "Tab" },
|
||||
} as Record<string, KeyCombo>;
|
||||
|
||||
export const keyDisplayMap: Record<string, string> = {
|
||||
...en_US.keyDisplayMap,
|
||||
// now override the English keyDisplayMap with German specific keys
|
||||
|
||||
// Combination keys
|
||||
CtrlAltDelete: "Strg + Alt + Entf",
|
||||
CtrlAltBackspace: "Strg + Alt + ←",
|
||||
|
||||
// German action keys
|
||||
AltLeft: "Alt",
|
||||
AltRight: "AltGr",
|
||||
Backspace: "Rücktaste",
|
||||
"(Backspace)": "Rücktaste",
|
||||
CapsLock: "Feststelltaste",
|
||||
Clear: "Entf",
|
||||
ControlLeft: "Strg",
|
||||
ControlRight: "Strg",
|
||||
Delete: "Entf",
|
||||
End: "Ende",
|
||||
Enter: "Eingabe",
|
||||
Escape: "Esc",
|
||||
Home: "Pos1",
|
||||
Insert: "Einfg",
|
||||
Menu: "Menü",
|
||||
MetaLeft: "Meta",
|
||||
MetaRight: "Meta",
|
||||
PageDown: "Bild ↓",
|
||||
PageUp: "Bild ↑",
|
||||
ShiftLeft: "Umschalt",
|
||||
ShiftRight: "Umschalt",
|
||||
|
||||
// German umlauts and ß
|
||||
BracketLeft: "ü",
|
||||
"(BracketLeft)": "Ü",
|
||||
Semicolon: "ö",
|
||||
"(Semicolon)": "Ö",
|
||||
Quote: "ä",
|
||||
"(Quote)": "Ä",
|
||||
Minus: "ß",
|
||||
"(Minus)": "?",
|
||||
Equal: "´",
|
||||
"(Equal)": "`",
|
||||
Backslash: "#",
|
||||
"(Backslash)": "'",
|
||||
|
||||
// Shifted Numbers
|
||||
"(Digit2)": "\"",
|
||||
"(Digit3)": "§",
|
||||
"(Digit6)": "&",
|
||||
"(Digit7)": "/",
|
||||
"(Digit8)": "(",
|
||||
"(Digit9)": ")",
|
||||
"(Digit0)": "=",
|
||||
|
||||
// Additional German symbols
|
||||
Backquote: "^",
|
||||
"(Backquote)": "°",
|
||||
Comma: ",",
|
||||
"(Comma)": ";",
|
||||
Period: ".",
|
||||
"(Period)": ":",
|
||||
Slash: "-",
|
||||
"(Slash)": "_",
|
||||
|
||||
// Numpad
|
||||
NumpadDecimal: "Num ,",
|
||||
NumpadEnter: "Num Eingabe",
|
||||
NumpadInsert: "Einfg",
|
||||
NumpadDelete: "Entf",
|
||||
|
||||
// Modals
|
||||
PrintScreen: "Druck",
|
||||
ScrollLock: "Rollen",
|
||||
"(Pause)": "Unterbr",
|
||||
}
|
||||
|
||||
export const modifierDisplayMap: Record<string, string> = {
|
||||
ShiftLeft: "Umschalt (links)",
|
||||
ShiftRight: "Umschalt (rechts)",
|
||||
ControlLeft: "Strg (links)",
|
||||
ControlRight: "Strg (rechts)",
|
||||
AltLeft: "Alt",
|
||||
AltRight: "AltGr",
|
||||
MetaLeft: "Meta (links)",
|
||||
MetaRight: "Meta (rechts)",
|
||||
AltGr: "AltGr",
|
||||
} as Record<string, string>;
|
||||
|
||||
export const virtualKeyboard = {
|
||||
main: {
|
||||
default: [
|
||||
"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",
|
||||
"CapsLock KeyA KeyS KeyD KeyF KeyG KeyH KeyJ KeyK KeyL Semicolon Quote Backslash Enter",
|
||||
"ShiftLeft KeyZ KeyX KeyC KeyV KeyB KeyN KeyM Comma Period Slash ShiftRight",
|
||||
"ControlLeft MetaLeft AltLeft Space AltGr MetaRight Menu ControlRight",
|
||||
],
|
||||
shift: [
|
||||
"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)",
|
||||
"CapsLock (KeyA) (KeyS) (KeyD) (KeyF) (KeyG) (KeyH) (KeyJ) (KeyK) (KeyL) (Semicolon) (Quote) Enter",
|
||||
"ShiftLeft (KeyZ) (KeyX) (KeyC) (KeyV) (KeyB) (KeyN) (KeyM) (Comma) (Period) (Slash) ShiftRight",
|
||||
"ControlLeft MetaLeft AltLeft Space AltGr MetaRight Menu ControlRight",
|
||||
]
|
||||
},
|
||||
control: {
|
||||
default: [
|
||||
"PrintScreen ScrollLock Pause",
|
||||
"Insert Home PageUp",
|
||||
"Delete End PageDown"
|
||||
],
|
||||
shift: [
|
||||
"(PrintScreen) ScrollLock (Pause)",
|
||||
"Insert Home PageUp",
|
||||
"Delete End PageDown"
|
||||
],
|
||||
},
|
||||
|
||||
arrows: {
|
||||
default: [
|
||||
" ArrowUp ",
|
||||
"ArrowLeft ArrowDown ArrowRight"],
|
||||
},
|
||||
|
||||
numpad: {
|
||||
numlocked: [
|
||||
"NumLock NumpadDivide NumpadMultiply NumpadSubtract",
|
||||
"Numpad7 Numpad8 Numpad9 NumpadAdd",
|
||||
"Numpad4 Numpad5 Numpad6",
|
||||
"Numpad1 Numpad2 Numpad3 NumpadEnter",
|
||||
"Numpad0 NumpadDecimal",
|
||||
],
|
||||
default: [
|
||||
"NumLock NumpadDivide NumpadMultiply NumpadSubtract",
|
||||
"Home ArrowUp PageUp NumpadAdd",
|
||||
"ArrowLeft Clear ArrowRight",
|
||||
"End ArrowDown PageDown NumpadEnter",
|
||||
"NumpadInsert NumpadDelete",
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
export const de_DE: KeyboardLayout = {
|
||||
isoCode: "de-DE",
|
||||
isoCode: isoCode,
|
||||
name: name,
|
||||
chars: chars
|
||||
chars: chars,
|
||||
keyDisplayMap: keyDisplayMap,
|
||||
modifierDisplayMap: modifierDisplayMap,
|
||||
virtualKeyboard: virtualKeyboard
|
||||
};
|
|
@ -1,6 +1,9 @@
|
|||
import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
|
||||
|
||||
import { en_US } from "./en_US" // for fallback of keyDisplayMap, modifierDisplayMap, and virtualKeyboard
|
||||
|
||||
const name = "English (UK)";
|
||||
const isoCode = "en-UK";
|
||||
|
||||
const chars = {
|
||||
A: { key: "KeyA", shift: true },
|
||||
|
@ -107,7 +110,11 @@ const chars = {
|
|||
} as Record<string, KeyCombo>
|
||||
|
||||
export const en_UK: KeyboardLayout = {
|
||||
isoCode: "en-UK",
|
||||
isoCode: isoCode,
|
||||
name: name,
|
||||
chars: chars
|
||||
chars: chars,
|
||||
// TODO need to localize these maps and layouts
|
||||
keyDisplayMap: en_US.keyDisplayMap,
|
||||
modifierDisplayMap: en_US.modifierDisplayMap,
|
||||
virtualKeyboard: en_US.virtualKeyboard
|
||||
};
|
|
@ -1,8 +1,18 @@
|
|||
import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
|
||||
|
||||
const name = "English (US)";
|
||||
const isoCode = "en-US";
|
||||
|
||||
const chars = {
|
||||
// dead keys for "international" 101 keyboards TODO
|
||||
/*
|
||||
const keyAcute = { key: "Quote", control: true, menu: true, mark: "´" } // acute accent
|
||||
const keyCedilla = { key: ".", shift: true, alt: true, mark: "¸" } // cedilla accent
|
||||
const keyComma = { key: "BracketRight", shift: true, altRight: true, mark: "," } // comma accent
|
||||
const keyDiaeresis = { key: "Quote", shift: true, control: true, menu: true, mark: "¨" } // diaeresis accent
|
||||
const keyDegree = { key: "Semicolon", shift: true, control: true, menu: true, mark: "°" } // degree accent
|
||||
*/
|
||||
|
||||
export const chars = {
|
||||
A: { key: "KeyA", shift: true },
|
||||
B: { key: "KeyB", shift: true },
|
||||
C: { key: "KeyC", shift: true },
|
||||
|
@ -89,31 +99,213 @@ const chars = {
|
|||
">": { key: "Period", shift: true },
|
||||
";": { key: "Semicolon" },
|
||||
":": { key: "Semicolon", shift: true },
|
||||
"¶": { key: "Semicolon", altRight: true }, // pilcrow sign
|
||||
"[": { key: "BracketLeft" },
|
||||
"{": { key: "BracketLeft", shift: true },
|
||||
"«": { key: "BracketLeft", altRight: true }, // double left quote sign
|
||||
"]": { key: "BracketRight" },
|
||||
"}": { key: "BracketRight", shift: true },
|
||||
"»": { key: "BracketRight", altRight: true }, // double right quote sign
|
||||
"\\": { key: "Backslash" },
|
||||
"|": { key: "Backslash", shift: true },
|
||||
"¬": { key: "Backslash", altRight: true }, // not sign
|
||||
"`": { key: "Backquote" },
|
||||
"~": { key: "Backquote", shift: true },
|
||||
"§": { key: "IntlBackslash" },
|
||||
"±": { key: "IntlBackslash", shift: true },
|
||||
" ": { key: "Space", shift: false },
|
||||
"\n": { key: "Enter", shift: false },
|
||||
Enter: { key: "Enter", shift: false },
|
||||
Tab: { key: "Tab", shift: false },
|
||||
PrintScreen: { key: "Prt Sc", shift: false },
|
||||
" ": { key: "Space" },
|
||||
"\n": { key: "Enter" },
|
||||
Enter: { key: "Enter" },
|
||||
Escape: { key: "Escape" },
|
||||
Tab: { key: "Tab" },
|
||||
PrintScreen: { key: "Prt Sc" },
|
||||
SystemRequest: { key: "Prt Sc", shift: true },
|
||||
ScrollLock: { key: "ScrollLock", shift: false},
|
||||
Pause: { key: "Pause", shift: false },
|
||||
ScrollLock: { key: "ScrollLock" },
|
||||
Pause: { key: "Pause" },
|
||||
Break: { key: "Pause", shift: true },
|
||||
Insert: { key: "Insert", shift: false },
|
||||
Delete: { key: "Delete", shift: false },
|
||||
Insert: { key: "Insert" },
|
||||
Delete: { key: "Delete" },
|
||||
} as Record<string, KeyCombo>
|
||||
|
||||
export const modifierDisplayMap: Record<string, string> = {
|
||||
ControlLeft: "Left Ctrl",
|
||||
ControlRight: "Right Ctrl",
|
||||
ShiftLeft: "Left Shift",
|
||||
ShiftRight: "Right Shift",
|
||||
AltLeft: "Left Alt",
|
||||
AltRight: "Right Alt",
|
||||
MetaLeft: "Left Meta",
|
||||
MetaRight: "Right Meta",
|
||||
AltGr: "AltGr",
|
||||
} as Record<string, string>;
|
||||
|
||||
export const keyDisplayMap: Record<string, string> = {
|
||||
CtrlAltDelete: "Ctrl + Alt + Delete",
|
||||
AltMetaEscape: "Alt + Meta + Escape",
|
||||
CtrlAltBackspace: "Ctrl + Alt + Backspace",
|
||||
AltGr: "AltGr",
|
||||
AltLeft: "Alt",
|
||||
AltRight: "Alt",
|
||||
ArrowDown: "↓",
|
||||
ArrowLeft: "←",
|
||||
ArrowRight: "→",
|
||||
ArrowUp: "↑",
|
||||
Backspace: "Backspace",
|
||||
"(Backspace)": "Backspace",
|
||||
CapsLock: "Caps Lock",
|
||||
Clear: "Clear",
|
||||
ControlLeft: "Ctrl",
|
||||
ControlRight: "Ctrl",
|
||||
Delete: "Delete",
|
||||
End: "End",
|
||||
Enter: "Enter",
|
||||
Escape: "Esc",
|
||||
Home: "Home",
|
||||
Insert: "Insert",
|
||||
Menu: "Menu",
|
||||
MetaLeft: "Meta",
|
||||
MetaRight: "Meta",
|
||||
PageDown: "PgDn",
|
||||
PageUp: "PgUp",
|
||||
ShiftLeft: "Shift",
|
||||
ShiftRight: "Shift",
|
||||
Space: " ",
|
||||
Tab: "Tab",
|
||||
|
||||
// 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",
|
||||
|
||||
// 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
|
||||
F1: "F1", F2: "F2", F3: "F3", F4: "F4",
|
||||
F5: "F5", F6: "F6", F7: "F7", F8: "F8",
|
||||
F9: "F9", F10: "F10", F11: "F11", F12: "F12",
|
||||
|
||||
// Numpad
|
||||
Numpad0: "Num 0", Numpad1: "Num 1", Numpad2: "Num 2",
|
||||
Numpad3: "Num 3", Numpad4: "Num 4", Numpad5: "Num 5",
|
||||
Numpad6: "Num 6", Numpad7: "Num 7", Numpad8: "Num 8",
|
||||
Numpad9: "Num 9", NumpadAdd: "Num +", NumpadSubtract: "Num -",
|
||||
NumpadMultiply: "Num *", NumpadDivide: "Num /", NumpadDecimal: "Num .",
|
||||
NumpadEqual: "Num =", NumpadEnter: "Num Enter", NumpadInsert: "Ins",
|
||||
NumpadDelete: "Del", NumLock: "Num Lock",
|
||||
|
||||
// Modals
|
||||
PrintScreen: "Prt Sc", ScrollLock: "Scr Lk", Pause: "Pause",
|
||||
"(PrintScreen)": "Sys Rq", "(Pause)": "Break",
|
||||
SystemRequest: "Sys Rq", Break: "Break"
|
||||
};
|
||||
|
||||
export const virtualKeyboard = {
|
||||
main: {
|
||||
default: [
|
||||
"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",
|
||||
"CapsLock KeyA KeyS KeyD KeyF KeyG KeyH KeyJ KeyK KeyL Semicolon Quote Enter",
|
||||
"ShiftLeft KeyZ KeyX KeyC KeyV KeyB KeyN KeyM Comma Period Slash ShiftRight",
|
||||
"ControlLeft MetaLeft AltLeft Space AltGr MetaRight Menu ControlRight",
|
||||
],
|
||||
shift: [
|
||||
"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)",
|
||||
"CapsLock (KeyA) (KeyS) (KeyD) (KeyF) (KeyG) (KeyH) (KeyJ) (KeyK) (KeyL) (Semicolon) (Quote) Enter",
|
||||
"ShiftLeft (KeyZ) (KeyX) (KeyC) (KeyV) (KeyB) (KeyN) (KeyM) (Comma) (Period) (Slash) ShiftRight",
|
||||
"ControlLeft MetaLeft AltLeft Space AltGr MetaRight Menu ControlRight",
|
||||
]
|
||||
},
|
||||
control: {
|
||||
default: [
|
||||
"PrintScreen ScrollLock Pause",
|
||||
"Insert Home PageUp",
|
||||
"Delete End PageDown"
|
||||
],
|
||||
shift: [
|
||||
"(PrintScreen) ScrollLock (Pause)",
|
||||
"Insert Home PageUp",
|
||||
"Delete End PageDown"
|
||||
],
|
||||
},
|
||||
|
||||
arrows: {
|
||||
default: [
|
||||
"ArrowUp",
|
||||
"ArrowLeft ArrowDown ArrowRight"],
|
||||
},
|
||||
|
||||
numpad: {
|
||||
numlocked: [
|
||||
"NumLock NumpadDivide NumpadMultiply NumpadSubtract",
|
||||
"Numpad7 Numpad8 Numpad9 NumpadAdd",
|
||||
"Numpad4 Numpad5 Numpad6",
|
||||
"Numpad1 Numpad2 Numpad3 NumpadEnter",
|
||||
"Numpad0 NumpadDecimal",
|
||||
],
|
||||
default: [
|
||||
"NumLock NumpadDivide NumpadMultiply NumpadSubtract",
|
||||
"Home ArrowUp PageUp NumpadAdd",
|
||||
"ArrowLeft Clear ArrowRight",
|
||||
"End ArrowDown PageDown NumpadEnter",
|
||||
"NumpadInsert NumpadDelete",
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
export const en_US: KeyboardLayout = {
|
||||
isoCode: "en-US",
|
||||
name: name,
|
||||
chars: chars
|
||||
};
|
||||
isoCode,
|
||||
name,
|
||||
chars,
|
||||
keyDisplayMap,
|
||||
modifierDisplayMap,
|
||||
virtualKeyboard
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
|
||||
|
||||
const name = "Español";
|
||||
import { en_US } from "./en_US" // for fallback of keyDisplayMap, modifierDisplayMap, and virtualKeyboard
|
||||
|
||||
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
|
||||
const name = "Español";
|
||||
const isoCode = "es-ES";
|
||||
|
||||
const keyTrema: KeyCombo = { key: "Quote", shift: true } // tréma (umlaut), two dots placed above a vowel
|
||||
const keyAcute: KeyCombo = { key: "Quote" } // accent aigu (acute accent), mark ´ placed above the letter
|
||||
const keyHat: KeyCombo = { key: "BracketRight", shift: true } // accent circonflexe (accent hat), mark ^ placed above the letter
|
||||
const keyGrave: KeyCombo = { key: "BracketRight" } // accent grave, mark ` placed above the letter
|
||||
const keyTilde: KeyCombo = { key: "Key4", altRight: true } // tilde, mark ~ placed above the letter
|
||||
|
||||
const chars = {
|
||||
A: { key: "KeyA", shift: true },
|
||||
|
@ -168,7 +171,11 @@ const chars = {
|
|||
} as Record<string, KeyCombo>;
|
||||
|
||||
export const es_ES: KeyboardLayout = {
|
||||
isoCode: "es-ES",
|
||||
isoCode: isoCode,
|
||||
name: name,
|
||||
chars: chars
|
||||
chars: chars,
|
||||
// TODO need to localize these maps and layouts
|
||||
keyDisplayMap: en_US.keyDisplayMap,
|
||||
modifierDisplayMap: en_US.modifierDisplayMap,
|
||||
virtualKeyboard: en_US.virtualKeyboard
|
||||
};
|
|
@ -1,12 +1,15 @@
|
|||
import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
|
||||
|
||||
const name = "Belgisch Nederlands";
|
||||
import { en_US } from "./en_US" // for fallback of keyDisplayMap, modifierDisplayMap, and virtualKeyboard
|
||||
|
||||
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
|
||||
const keyAcute = { key: "Semicolon", altRight: true } // accent aigu (acute accent), mark ´ placed above the letter
|
||||
const keyGrave = { key: "Quote", shift: true } // accent grave, mark ` placed above the letter
|
||||
const keyTilde = { key: "Slash", altRight: true } // tilde, mark ~ placed above the letter
|
||||
const name = "Belgisch Nederlands";
|
||||
const isoCode = "nl-BE";
|
||||
|
||||
const keyTrema: KeyCombo = { key: "BracketLeft", shift: true } // tréma (umlaut), two dots placed above a vowel
|
||||
const keyHat: KeyCombo = { key: "BracketLeft" } // accent circonflexe (accent hat), mark ^ placed above the letter
|
||||
const keyAcute: KeyCombo = { key: "Semicolon", altRight: true } // accent aigu (acute accent), mark ´ placed above the letter
|
||||
const keyGrave: KeyCombo = { key: "Quote", shift: true } // accent grave, mark ` placed above the letter
|
||||
const keyTilde: KeyCombo = { key: "Slash", altRight: true } // tilde, mark ~ placed above the letter
|
||||
|
||||
const chars = {
|
||||
A: { key: "KeyQ", shift: true },
|
||||
|
@ -167,7 +170,11 @@ const chars = {
|
|||
} as Record<string, KeyCombo>;
|
||||
|
||||
export const fr_BE: KeyboardLayout = {
|
||||
isoCode: "fr-BE",
|
||||
isoCode: isoCode,
|
||||
name: name,
|
||||
chars: chars
|
||||
chars: chars,
|
||||
// TODO need to localize these maps and layouts
|
||||
keyDisplayMap: en_US.keyDisplayMap,
|
||||
modifierDisplayMap: en_US.modifierDisplayMap,
|
||||
virtualKeyboard: en_US.virtualKeyboard
|
||||
};
|
|
@ -3,6 +3,7 @@ import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
|
|||
import { de_CH } from "./de_CH"
|
||||
|
||||
const name = "Français de Suisse";
|
||||
const isoCode = "fr-CH";
|
||||
|
||||
const chars = {
|
||||
...de_CH.chars,
|
||||
|
@ -14,8 +15,22 @@ const chars = {
|
|||
"ä": { key: "Quote", shift: true },
|
||||
} as Record<string, KeyCombo>;
|
||||
|
||||
const keyDisplayMap = {
|
||||
...de_CH.keyDisplayMap,
|
||||
"BracketLeft": "è",
|
||||
"BracketLeftShift": "ü",
|
||||
"Semicolon": "é",
|
||||
"SemicolonShift": "ö",
|
||||
"Quote": "à",
|
||||
"QuoteShift": "ä",
|
||||
} as Record<string, string>;
|
||||
|
||||
export const fr_CH: KeyboardLayout = {
|
||||
isoCode: "fr-CH",
|
||||
isoCode: isoCode,
|
||||
name: name,
|
||||
chars: chars
|
||||
chars: chars,
|
||||
keyDisplayMap: keyDisplayMap,
|
||||
// TODO need to localize these maps and layouts
|
||||
modifierDisplayMap: de_CH.modifierDisplayMap,
|
||||
virtualKeyboard: de_CH.virtualKeyboard
|
||||
};
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
|
||||
|
||||
const name = "Français";
|
||||
import { en_US } from "./en_US" // for fallback of keyDisplayMap, modifierDisplayMap, and virtualKeyboard
|
||||
|
||||
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
|
||||
const name = "Français";
|
||||
const isoCode = "fr-FR";
|
||||
|
||||
const keyTrema: KeyCombo = { key: "BracketLeft", shift: true } // tréma (umlaut), two dots placed above a vowel
|
||||
const keyHat: KeyCombo = { key: "BracketLeft" } // accent circonflexe (accent hat), mark ^ placed above the letter
|
||||
|
||||
const chars = {
|
||||
A: { key: "KeyQ", shift: true },
|
||||
|
@ -139,7 +142,11 @@ const chars = {
|
|||
} as Record<string, KeyCombo>;
|
||||
|
||||
export const fr_FR: KeyboardLayout = {
|
||||
isoCode: "fr-FR",
|
||||
isoCode: isoCode,
|
||||
name: name,
|
||||
chars: chars
|
||||
chars: chars,
|
||||
// TODO need to localize these maps and layouts
|
||||
keyDisplayMap: en_US.keyDisplayMap,
|
||||
modifierDisplayMap: en_US.modifierDisplayMap,
|
||||
virtualKeyboard: en_US.virtualKeyboard
|
||||
};
|
|
@ -1,6 +1,9 @@
|
|||
import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
|
||||
|
||||
import { en_US } from "./en_US" // for fallback of keyDisplayMap, modifierDisplayMap, and virtualKeyboard
|
||||
|
||||
const name = "Italiano";
|
||||
const isoCode = "it-IT";
|
||||
|
||||
const chars = {
|
||||
A: { key: "KeyA", shift: true },
|
||||
|
@ -113,7 +116,11 @@ const chars = {
|
|||
} as Record<string, KeyCombo>;
|
||||
|
||||
export const it_IT: KeyboardLayout = {
|
||||
isoCode: "it-IT",
|
||||
isoCode: isoCode,
|
||||
name: name,
|
||||
chars: chars
|
||||
chars: chars,
|
||||
// TODO need to localize these maps and layouts
|
||||
keyDisplayMap: en_US.keyDisplayMap,
|
||||
modifierDisplayMap: en_US.modifierDisplayMap,
|
||||
virtualKeyboard: en_US.virtualKeyboard
|
||||
};
|
|
@ -1,12 +1,15 @@
|
|||
import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
|
||||
|
||||
const name = "Norsk bokmål";
|
||||
import { en_US } from "./en_US" // for fallback of keyDisplayMap, modifierDisplayMap, and virtualKeyboard
|
||||
|
||||
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
|
||||
const name = "Norsk bokmål";
|
||||
const isoCode = "nb-NO";
|
||||
|
||||
const keyTrema: KeyCombo = { key: "BracketRight" } // tréma (umlaut), two dots placed above a vowel
|
||||
const keyAcute: KeyCombo = { key: "Equal", altRight: true } // accent aigu (acute accent), mark ´ placed above the letter
|
||||
const keyHat: KeyCombo = { key: "BracketRight", shift: true } // accent circonflexe (accent hat), mark ^ placed above the letter
|
||||
const keyGrave: KeyCombo = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter
|
||||
const keyTilde: KeyCombo = { key: "BracketRight", altRight: true } // tilde, mark ~ placed above the letter
|
||||
|
||||
const chars = {
|
||||
A: { key: "KeyA", shift: true },
|
||||
|
@ -167,7 +170,11 @@ const chars = {
|
|||
} as Record<string, KeyCombo>;
|
||||
|
||||
export const nb_NO: KeyboardLayout = {
|
||||
isoCode: "nb-NO",
|
||||
isoCode: isoCode,
|
||||
name: name,
|
||||
chars: chars
|
||||
chars: chars,
|
||||
// TODO need to localize these maps and layouts
|
||||
keyDisplayMap: en_US.keyDisplayMap,
|
||||
modifierDisplayMap: en_US.modifierDisplayMap,
|
||||
virtualKeyboard: en_US.virtualKeyboard
|
||||
};
|
|
@ -0,0 +1,244 @@
|
|||
import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
|
||||
|
||||
import { en_US } from "./en_US" // for fallback of keyDisplayMap, modifierDisplayMap, and virtualKeyboard
|
||||
|
||||
const name = "Polski (Programista)";
|
||||
const isoCode = "pl-PL-t";
|
||||
|
||||
const keyAcute: KeyCombo = { key: "Quote" } // accent aigu (acute accent), mark ´ placed above the letter
|
||||
const keyCedilla: KeyCombo = { key: "OEM_2", altRight: true } // Cedilla mark ¸ placed below the letter in the center
|
||||
const keyDiaresis: KeyCombo = { key: "Plus", shift: true } // Diaresis (not umlaut!), two dots placed above a vowel to indicate each vowel should be pronounce
|
||||
const keyDotAbove: KeyCombo = { key: "", } // Dot above, single TODO!
|
||||
const keyDoubleAcute: KeyCombo = { key: "˝" } // Double acute mark ˝, placed above the letter in the center
|
||||
const keyGrave: KeyCombo = { key: "BracketRight" } // accent grave mark ` placed above the letter
|
||||
const keyHacek: KeyCombo = { key: "", } // TODO!
|
||||
const keyHat: KeyCombo = { key: "BracketRight", shift: true } // accent circonflexe (accent hat), mark ^ placed above the letter
|
||||
const keyOgonek: KeyCombo = { key: ""} // Ogonek mark ˛ placed below the letter on the right side
|
||||
const keyTylda: KeyCombo = { key: "Backquote", altRight: true } // Tilde mark ~ placed above the letter
|
||||
|
||||
const chars = {
|
||||
A: { key: "KeyA", shift: true },
|
||||
"Ä": { key: "KeyA", shift: true, accentKey: keyDiaresis },
|
||||
"Ą": { key: "KeyA", shift: true, ctrl: true, alt: true },
|
||||
"Á": { key: "KeyA", shift: true, accentKey: keyAcute },
|
||||
"Â": { key: "KeyA", shift: true, accentKey: keyHat },
|
||||
"À": { key: "KeyA", shift: true, accentKey: keyGrave },
|
||||
"Ã": { key: "KeyA", shift: true, accentKey: keyTylda },
|
||||
a: { key: "KeyA" },
|
||||
"ä": { key: "KeyA", accentKey: keyDiaresis },
|
||||
"ą": { key: "KeyA", accentKey: keyOgonek }, // "ą": { key: "KeyA", ctrl: true, alt: true },
|
||||
"á": { key: "KeyA", accentKey: keyAcute },
|
||||
"â": { key: "KeyA", accentKey: keyHat },
|
||||
"à": { key: "KeyA", accentKey: keyGrave },
|
||||
"ã": { key: "KeyA", accentKey: keyTylda },
|
||||
|
||||
B: { key: "KeyB", shift: true },
|
||||
b: { key: "KeyB" },
|
||||
|
||||
C: { key: "KeyC", shift: true },
|
||||
"Ć": { key: "KeyC", shift: true, accentKey: keyAcute },
|
||||
"Č": { key: "KeyC", shift: true, accentKey: keyHacek },
|
||||
"Ç": { key: "KeyC", shift: true, accentKey: keyCedilla }, // "Ç": { key: "Backslash", shift: true },
|
||||
c: { key: "KeyC" },
|
||||
"ć": { key: "KeyC", shift: false, accentKey: keyAcute },
|
||||
"č": { key: "KeyC", accentKey: keyHacek },
|
||||
"ç": { key: "KeyC", accentKey: keyCedilla }, // "ç": { key: "Backslash" },
|
||||
|
||||
D: { key: "KeyD", shift: true },
|
||||
"Ď": { key: "KeyD", shift: true, accentKey: keyHacek },
|
||||
d: { key: "KeyD" },
|
||||
"ď": { key: "KeyD", accentKey: keyHacek },
|
||||
|
||||
E: { key: "KeyE", shift: true },
|
||||
"Ë": { key: "KeyE", shift: true, accentKey: keyDiaresis },
|
||||
"Ę": { key: "KeyE", shift: true, ctrl: true, alt: true, accentKey: keyOgonek },
|
||||
"Ě": { key: "KeyE", shift: true, accentKey: keyHacek },
|
||||
"É": { key: "KeyE", shift: true, accentKey: keyAcute },
|
||||
"Ê": { key: "KeyE", shift: true, accentKey: keyHat },
|
||||
"È": { key: "KeyE", shift: true, accentKey: keyGrave },
|
||||
"Ẽ": { key: "KeyE", shift: true, accentKey: keyTylda },
|
||||
e: { key: "KeyE" },
|
||||
"ę": { key: "KeyE", ctrl: true, alt: true, accentKey: keyOgonek },
|
||||
"ë": { key: "KeyE", accentKey: keyDiaresis },
|
||||
"ě": { key: "KeyE", accentKey: keyHacek },
|
||||
"é": { key: "KeyE", accentKey: keyAcute },
|
||||
"ê": { key: "KeyE", accentKey: keyHat },
|
||||
"è": { key: "KeyE", accentKey: keyGrave },
|
||||
"ẽ": { key: "KeyE", accentKey: keyTylda },
|
||||
|
||||
F: { key: "KeyF", shift: true },
|
||||
f: { key: "KeyF" },
|
||||
|
||||
G: { key: "KeyG", shift: true },
|
||||
g: { key: "KeyG" },
|
||||
|
||||
H: { key: "KeyH", shift: true },
|
||||
h: { key: "KeyH" },
|
||||
|
||||
I: { key: "KeyI", shift: true },
|
||||
"Ï": { key: "KeyI", shift: true, accentKey: keyDiaresis },
|
||||
"Í": { key: "KeyI", shift: true, accentKey: keyAcute },
|
||||
"Î": { key: "KeyI", shift: true, accentKey: keyHat },
|
||||
"Ì": { key: "KeyI", shift: true, accentKey: keyGrave },
|
||||
"Ĩ": { key: "KeyI", shift: true, accentKey: keyTylda },
|
||||
i: { key: "KeyI" },
|
||||
"ï": { key: "KeyI", accentKey: keyDiaresis },
|
||||
"í": { key: "KeyI", accentKey: keyAcute },
|
||||
"î": { key: "KeyI", accentKey: keyHat },
|
||||
"ì": { key: "KeyI", accentKey: keyGrave },
|
||||
"ĩ": { key: "KeyI", accentKey: keyTylda },
|
||||
|
||||
J: { key: "KeyJ", shift: true },
|
||||
j: { key: "KeyJ" },
|
||||
|
||||
K: { key: "KeyK", shift: true },
|
||||
k: { key: "KeyK" },
|
||||
|
||||
L: { key: "KeyL", shift: true },
|
||||
l: { key: "KeyL" },
|
||||
|
||||
M: { key: "KeyM", shift: true },
|
||||
m: { key: "KeyM" },
|
||||
|
||||
N: { key: "KeyN", shift: true },
|
||||
"Ň": { key: "KeyN", shift: true, accentKey: keyHacek },
|
||||
n: { key: "KeyN" },
|
||||
"ň": { key: "KeyR", accentKey: keyHacek },
|
||||
|
||||
O: { key: "KeyO", shift: true },
|
||||
"Ö": { key: "KeyO", shift: true, accentKey: keyDiaresis },
|
||||
"Ő": { key: "KeyO", shift: true, accentKey: keyDoubleAcute },
|
||||
"Ó": { key: "KeyO", shift: true, accentKey: keyAcute }, // "Ó": { key: "KeyO", shift: true, ctrl: true, alt: true },
|
||||
"Ô": { key: "KeyO", shift: true, accentKey: keyHat },
|
||||
"Ò": { key: "KeyO", shift: true, accentKey: keyGrave },
|
||||
"Õ": { key: "KeyO", shift: true, accentKey: keyTylda },
|
||||
o: { key: "KeyO" },
|
||||
"ó": { key: "KeyO", ctrl: true, alt: true, accentKey: keyAcute },
|
||||
"ö": { key: "KeyO", accentKey: keyDiaresis },
|
||||
"ő": { key: "KeyO", accentKey: keyDoubleAcute },
|
||||
"ô": { key: "KeyO", accentKey: keyHat },
|
||||
"ò": { key: "KeyO", accentKey: keyGrave },
|
||||
"õ": { key: "KeyO", accentKey: keyTylda },
|
||||
|
||||
P: { key: "KeyP", shift: true },
|
||||
p: { key: "KeyP" },
|
||||
|
||||
Q: { key: "KeyQ", shift: true },
|
||||
q: { key: "KeyQ" },
|
||||
|
||||
R: { key: "KeyR", shift: true },
|
||||
"Ř": { key: "KeyR", shift: true, accentKey: keyHacek },
|
||||
r: { key: "KeyR" },
|
||||
"ř": { key: "KeyR", accentKey: keyHacek },
|
||||
|
||||
S: { key: "KeyS", shift: true },
|
||||
"Š": { key: "KeyS", shift: true, accentKey: keyHacek },
|
||||
"Ş": { key: "KeyS", shift: true, accentKey: keyCedilla },
|
||||
s: { key: "KeyS" },
|
||||
"š": { key: "KeyS", accentKey: keyHacek },
|
||||
"ş": { key: "KeyS", accentKey: keyCedilla },
|
||||
|
||||
T: { key: "KeyT", shift: true },
|
||||
"Ť": { key: "KeyT", shift: true, accentKey: keyHacek },
|
||||
"Ţ": { key: "KeyT", shift: true, accentKey: keyCedilla },
|
||||
t: { key: "KeyT" },
|
||||
"ť": { key: "KeyT", accentKey: keyHacek },
|
||||
"ţ": { key: "KeyS", accentKey: keyCedilla },
|
||||
|
||||
U: { key: "KeyU", shift: true },
|
||||
"Ü": { key: "KeyU", shift: true, accentKey: keyDiaresis },
|
||||
"Ű": { key: "KeyU", shift: true, accentKey: keyDoubleAcute },
|
||||
"Ú": { key: "KeyU", shift: true, accentKey: keyAcute },
|
||||
"Û": { key: "KeyU", shift: true, accentKey: keyHat },
|
||||
"Ù": { key: "KeyU", shift: true, accentKey: keyGrave },
|
||||
"Ũ": { key: "KeyU", shift: true, accentKey: keyTylda },
|
||||
u: { key: "KeyU" },
|
||||
"€": { key: "KeyU", ctrl: true, alt: true },
|
||||
"ü": { key: "KeyU", accentKey: keyDiaresis },
|
||||
"ű": { key: "KeyU", accentKey: keyDoubleAcute },
|
||||
"ú": { key: "KeyU", accentKey: keyAcute },
|
||||
"û": { key: "KeyU", accentKey: keyHat },
|
||||
"ù": { key: "KeyU", accentKey: keyGrave },
|
||||
"ũ": { key: "KeyU", accentKey: keyTylda },
|
||||
|
||||
V: { key: "KeyV", shift: true },
|
||||
v: { key: "KeyV" },
|
||||
|
||||
W: { key: "KeyW", shift: true },
|
||||
w: { key: "KeyW" },
|
||||
|
||||
X: { key: "KeyX", shift: true },
|
||||
x: { key: "KeyX" },
|
||||
|
||||
Y: { key: "KeyY", shift: true },
|
||||
y: { key: "KeyY" },
|
||||
|
||||
Z: { key: "KeyZ", shift: true },
|
||||
"Ž": { key: "KeyZ", shift: true, accentKey: keyHacek },
|
||||
"Ź": { key: "KeyZ", shift: true, ctrl: true, meta: true, accentKey: keyAcute },
|
||||
z: { key: "KeyZ" },
|
||||
"ž": { key: "KeyZ", accentKey: keyHacek },
|
||||
"ź": { key: "KeyX",ctrl: true, meta: true, accentKey: keyAcute }, // not a typo, it's on the X key
|
||||
"ż": { key: "KeyZ", ctrl: true, meta: true, accentKey: keyDotAbove },
|
||||
|
||||
"º": { 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 },
|
||||
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", 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" },
|
||||
"ˇ": { key: "Space", accentKey: keyHacek },
|
||||
"\n": { key: "Enter" },
|
||||
Enter: { key: "Enter" },
|
||||
Tab: { key: "Tab" },
|
||||
} as Record<string, KeyCombo>;
|
||||
|
||||
export const pl_PL_t: KeyboardLayout = {
|
||||
isoCode: isoCode,
|
||||
name: name,
|
||||
chars: chars,
|
||||
keyDisplayMap: en_US.keyDisplayMap,
|
||||
modifierDisplayMap: en_US.modifierDisplayMap,
|
||||
virtualKeyboard: en_US.virtualKeyboard
|
||||
};
|
|
@ -1,12 +1,15 @@
|
|||
import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
|
||||
|
||||
const name = "Svenska";
|
||||
import { en_US } from "./en_US" // for fallback of keyDisplayMap, modifierDisplayMap, and virtualKeyboard
|
||||
|
||||
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
|
||||
const name = "Svenska";
|
||||
const isoCode = "sv-SE";
|
||||
|
||||
const keyTrema: KeyCombo = { key: "BracketRight" } // tréma (umlaut), two dots placed above a vowel
|
||||
const keyAcute: KeyCombo = { key: "Equal" } // accent aigu (acute accent), mark ´ placed above the letter
|
||||
const keyHat: KeyCombo = { key: "BracketRight", shift: true } // accent circonflexe (accent hat), mark ^ placed above the letter
|
||||
const keyGrave: KeyCombo = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter
|
||||
const keyTilde: KeyCombo = { key: "BracketRight", altRight: true } // tilde, mark ~ placed above the letter
|
||||
|
||||
const chars = {
|
||||
A: { key: "KeyA", shift: true },
|
||||
|
@ -164,7 +167,11 @@ const chars = {
|
|||
} as Record<string, KeyCombo>;
|
||||
|
||||
export const sv_SE: KeyboardLayout = {
|
||||
isoCode: "sv-SE",
|
||||
isoCode: isoCode,
|
||||
name: name,
|
||||
chars: chars
|
||||
chars: chars,
|
||||
// TODO need to localize these maps and layouts
|
||||
keyDisplayMap: en_US.keyDisplayMap,
|
||||
modifierDisplayMap: en_US.modifierDisplayMap,
|
||||
virtualKeyboard: en_US.virtualKeyboard
|
||||
};
|
|
@ -1,20 +1,39 @@
|
|||
// Key codes and modifiers correspond to definitions in the
|
||||
// [Linux USB HID gadget driver](https://www.kernel.org/doc/Documentation/usb/gadget_hid.txt)
|
||||
// [Section 10. Keyboard/Keypad Page 0x07](https://usb.org/sites/default/files/hut1_21.pdf)
|
||||
// [Universal Serial Bus HID Usage Tables: Section 10](https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf)
|
||||
// These are all the key codes (not scan codes) that an 85/101/102 keyboard might have on it
|
||||
export const keys = {
|
||||
Again: 0x79,
|
||||
AlternateErase: 0x9d,
|
||||
AltGr: 0xe6, // aka AltRight
|
||||
AltLeft: 0xe2,
|
||||
AltRight: 0xe6,
|
||||
Application: 0x65,
|
||||
ArrowDown: 0x51,
|
||||
ArrowLeft: 0x50,
|
||||
ArrowRight: 0x4f,
|
||||
ArrowUp: 0x52,
|
||||
Attention: 0x9a,
|
||||
Backquote: 0x35, // aka Grave
|
||||
Backslash: 0x31,
|
||||
Backspace: 0x2a,
|
||||
BracketLeft: 0x2f, // aka LeftBrace
|
||||
BracketRight: 0x30, // aka RightBrace
|
||||
Cancel: 0x9b,
|
||||
CapsLock: 0x39,
|
||||
Clear: 0x9c,
|
||||
ClearAgain: 0xa2,
|
||||
Comma: 0x36,
|
||||
Compose: 0x65,
|
||||
ContextMenu: 0x65, // same as Compose
|
||||
Compose: 0xe3,
|
||||
ContextMenu: 0x65,
|
||||
ControlLeft: 0xe0,
|
||||
ControlRight: 0xe4,
|
||||
Copy: 0x7c,
|
||||
CrSel: 0xa3,
|
||||
CurrencySubunit: 0xb5,
|
||||
CurrencyUnit: 0xb4,
|
||||
Cut: 0x7b,
|
||||
DecimalSeparator: 0xb3,
|
||||
Delete: 0x4c,
|
||||
Digit0: 0x27,
|
||||
Digit1: 0x1e,
|
||||
|
@ -30,6 +49,8 @@ export const keys = {
|
|||
Enter: 0x28,
|
||||
Equal: 0x2e,
|
||||
Escape: 0x29,
|
||||
Execute: 0x74,
|
||||
ExSel: 0xa4,
|
||||
F1: 0x3a,
|
||||
F2: 0x3b,
|
||||
F3: 0x3c,
|
||||
|
@ -54,9 +75,21 @@ export const keys = {
|
|||
F22: 0x71,
|
||||
F23: 0x72,
|
||||
F24: 0x73,
|
||||
Home: 0x4a,
|
||||
Find: 0x7e,
|
||||
Grave: 0x35,
|
||||
HashTilde: 0x32, // non-US # and ~
|
||||
Help: 0x75,
|
||||
Home: 0x4a,
|
||||
Insert: 0x49,
|
||||
International1: 0x87,
|
||||
International2: 0x88,
|
||||
International3: 0x89,
|
||||
International4: 0x8a,
|
||||
International5: 0x8b,
|
||||
International6: 0x8c,
|
||||
International7: 0x8d,
|
||||
International8: 0x8e,
|
||||
International9: 0x8f,
|
||||
IntlBackslash: 0x64, // non-US \ and |
|
||||
KeyA: 0x04,
|
||||
KeyB: 0x05,
|
||||
|
@ -84,10 +117,27 @@ export const keys = {
|
|||
KeyX: 0x1b,
|
||||
KeyY: 0x1c,
|
||||
KeyZ: 0x1d,
|
||||
KeypadExclamation: 0xcf,
|
||||
LockingCapsLock: 0x82,
|
||||
LockingNumLock: 0x83,
|
||||
LockingScrollLock: 0x84,
|
||||
Lang1: 0x90, // Hangul/English toggle on Korean keyboards
|
||||
Lang2: 0x91, // Hanja conversion on Korean keyboards
|
||||
Lang3: 0x92, // Katakana on Japanese keyboards
|
||||
Lang4: 0x93, // Hiragana on Japanese keyboards
|
||||
Lang5: 0x94, // Zenkaku/Hankaku toggle on Japanese keyboards
|
||||
Lang6: 0x95,
|
||||
Lang7: 0x96,
|
||||
Lang8: 0x97,
|
||||
Lang9: 0x98,
|
||||
Menu: 0x76,
|
||||
MetaLeft: 0xe3,
|
||||
MetaRight: 0xe7,
|
||||
Minus: 0x2d,
|
||||
Mute: 0x7f,
|
||||
NumLock: 0x53, // and Clear
|
||||
Numpad0: 0x62, // and Insert
|
||||
Numpad00: 0xb0,
|
||||
Numpad000: 0xb1,
|
||||
Numpad1: 0x59, // and End
|
||||
Numpad2: 0x5a, // and Down Arrow
|
||||
Numpad3: 0x5b, // and Page Down
|
||||
|
@ -98,38 +148,111 @@ export const keys = {
|
|||
Numpad8: 0x60, // and Up Arrow
|
||||
Numpad9: 0x61, // and Page Up
|
||||
NumpadAdd: 0x57,
|
||||
NumpadAnd: 0xc7,
|
||||
NumpadAt: 0xce,
|
||||
NumpadBackspace: 0xbb,
|
||||
NumpadBinary: 0xda,
|
||||
NumpadCircumflex: 0xc3,
|
||||
NumpadClear: 0xd8,
|
||||
NumpadClearEntry: 0xd9,
|
||||
NumpadColon: 0xcb,
|
||||
NumpadComma: 0x85,
|
||||
NumpadDecimal: 0x63,
|
||||
NumpadDecimalBase: 0xdc,
|
||||
NumpadDelete: 0x63,
|
||||
NumpadDivide: 0x54,
|
||||
NumpadDownArrow: 0x5a,
|
||||
NumpadEnd: 0x59,
|
||||
NumpadEnter: 0x58,
|
||||
NumpadEqual: 0x67,
|
||||
NumpadExclamation: 0xcf,
|
||||
NumpadGreaterThan: 0xc6,
|
||||
NumpadHexadecimal: 0xdd,
|
||||
NumpadHome: 0x5f,
|
||||
NumpadKeyA: 0xbc,
|
||||
NumpadKeyB: 0xbd,
|
||||
NumpadKeyC: 0xbe,
|
||||
NumpadKeyD: 0xbf,
|
||||
NumpadKeyE: 0xc0,
|
||||
NumpadKeyF: 0xc1,
|
||||
NumpadLeftArrow: 0x5c,
|
||||
NumpadLeftBrace: 0xb8,
|
||||
NumpadLeftParen: 0xb6,
|
||||
NumpadLessThan: 0xc5,
|
||||
NumpadLogicalAnd: 0xc8,
|
||||
NumpadLogicalOr: 0xca,
|
||||
NumpadMemoryAdd: 0xd3,
|
||||
NumpadMemoryClear: 0xd2,
|
||||
NumpadMemoryDivide: 0xd6,
|
||||
NumpadMemoryMultiply: 0xd5,
|
||||
NumpadMemoryRecall: 0xd1,
|
||||
NumpadMemoryStore: 0xd0,
|
||||
NumpadMemorySubtract: 0xd4,
|
||||
NumpadMultiply: 0x55,
|
||||
NumpadOctal: 0xdb,
|
||||
NumpadOctathorpe: 0xcc,
|
||||
NumpadOr: 0xc9,
|
||||
NumpadPageDown: 0x5b,
|
||||
NumpadPageUp: 0x61,
|
||||
NumpadPercent: 0xc4,
|
||||
NumpadPlusMinus: 0xd7,
|
||||
NumpadRightArrow: 0x5e,
|
||||
NumpadRightBrace: 0xb9,
|
||||
NumpadRightParen: 0xb7,
|
||||
NumpadSpace: 0xcd,
|
||||
NumpadSubtract: 0x56,
|
||||
NumpadTab: 0xba,
|
||||
NumpadUpArrow: 0x60,
|
||||
NumpadXOR: 0xc2,
|
||||
Octothorpe: 0x32, // non-US # and ~
|
||||
Operation: 0xa1,
|
||||
Out: 0xa0,
|
||||
PageDown: 0x4e,
|
||||
PageUp: 0x4b,
|
||||
Period: 0x37,
|
||||
PrintScreen: 0x46,
|
||||
Paste: 0x7d,
|
||||
Pause: 0x48,
|
||||
Period: 0x37,
|
||||
Power: 0x66,
|
||||
PrintScreen: 0x46,
|
||||
Prior: 0x9d,
|
||||
Quote: 0x34, // aka Single Quote or Apostrophe
|
||||
Return: 0x9e,
|
||||
ScrollLock: 0x47,
|
||||
Select: 0x77,
|
||||
Semicolon: 0x33,
|
||||
Slash: 0x38,
|
||||
Space: 0x2c,
|
||||
SystemRequest: 0x9a,
|
||||
Tab: 0x2b,
|
||||
ControlLeft: 0xe0,
|
||||
ControlRight: 0xe4,
|
||||
Separator: 0x9f,
|
||||
ShiftLeft: 0xe1,
|
||||
ShiftRight: 0xe5,
|
||||
AltLeft: 0xe2,
|
||||
AltRight: 0xe6,
|
||||
MetaLeft: 0xe3,
|
||||
MetaRight: 0xe7,
|
||||
Slash: 0x38,
|
||||
Space: 0x2c,
|
||||
Stop: 0x78,
|
||||
SystemRequest: 0x9a,
|
||||
Tab: 0x2b,
|
||||
ThousandsSeparator: 0xb2,
|
||||
Tilde: 0x35,
|
||||
Undo: 0x7a,
|
||||
VolumeDown: 0x81,
|
||||
VolumeUp: 0x80,
|
||||
} as Record<string, number>;
|
||||
|
||||
export const deadKeys = {
|
||||
Acute: 0x00b4,
|
||||
Breve: 0x02d8,
|
||||
Caron: 0x02c7,
|
||||
Cedilla: 0x00b8,
|
||||
Circumflex: 0x005e, // or 0x02c6?
|
||||
Comma: 0x002c,
|
||||
Dot: 0x00b7,
|
||||
DoubleAcute: 0x02dd,
|
||||
Grave: 0x0060,
|
||||
Kreis: 0x00b0,
|
||||
Ogonek: 0x02db,
|
||||
Ring: 0x02da,
|
||||
Slash: 0x02f8,
|
||||
Tilde: 0x007e,
|
||||
Umlaut: 0x00a8,
|
||||
} as Record<string, number>
|
||||
|
||||
export const modifiers = {
|
||||
ControlLeft: 0x01,
|
||||
ControlRight: 0x10,
|
||||
|
@ -139,6 +262,7 @@ export const modifiers = {
|
|||
AltRight: 0x40,
|
||||
MetaLeft: 0x08,
|
||||
MetaRight: 0x80,
|
||||
AltGr: 0x40,
|
||||
} as Record<string, number>;
|
||||
|
||||
export const hidKeyToModifierMask = {
|
||||
|
@ -148,115 +272,18 @@ export const hidKeyToModifierMask = {
|
|||
0xe3: modifiers.MetaLeft,
|
||||
0xe4: modifiers.ControlRight,
|
||||
0xe5: modifiers.ShiftRight,
|
||||
0xe6: modifiers.AltRight,
|
||||
0xe6: modifiers.AltRight, // can also be AltGr
|
||||
0xe7: modifiers.MetaRight,
|
||||
} as Record<number, number>;
|
||||
|
||||
export const modifierDisplayMap: Record<string, string> = {
|
||||
ControlLeft: "Left Ctrl",
|
||||
ControlRight: "Right Ctrl",
|
||||
ShiftLeft: "Left Shift",
|
||||
ShiftRight: "Right Shift",
|
||||
AltLeft: "Left Alt",
|
||||
AltRight: "Right Alt",
|
||||
MetaLeft: "Left Meta",
|
||||
MetaRight: "Right Meta",
|
||||
} as Record<string, string>;
|
||||
export const latchingKeys = ["CapsLock", "ScrollLock", "NumLock", "Meta", "Compose", "Kana"];
|
||||
|
||||
export const keyDisplayMap: Record<string, string> = {
|
||||
CtrlAltDelete: "Ctrl + Alt + Delete",
|
||||
AltMetaEscape: "Alt + Meta + Escape",
|
||||
CtrlAltBackspace: "Ctrl + Alt + Backspace",
|
||||
Escape: "esc",
|
||||
Tab: "tab",
|
||||
Backspace: "backspace",
|
||||
"(Backspace)": "backspace",
|
||||
Enter: "enter",
|
||||
CapsLock: "caps lock",
|
||||
ShiftLeft: "shift",
|
||||
ShiftRight: "shift",
|
||||
ControlLeft: "ctrl",
|
||||
AltLeft: "alt",
|
||||
AltRight: "alt",
|
||||
MetaLeft: "meta",
|
||||
MetaRight: "meta",
|
||||
Space: " ",
|
||||
Insert: "insert",
|
||||
Home: "home",
|
||||
PageUp: "page up",
|
||||
Delete: "delete",
|
||||
End: "end",
|
||||
PageDown: "page down",
|
||||
ArrowLeft: "←",
|
||||
ArrowRight: "→",
|
||||
ArrowUp: "↑",
|
||||
ArrowDown: "↓",
|
||||
|
||||
// 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",
|
||||
|
||||
// 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
|
||||
F1: "F1", F2: "F2", F3: "F3", F4: "F4",
|
||||
F5: "F5", F6: "F6", F7: "F7", F8: "F8",
|
||||
F9: "F9", F10: "F10", F11: "F11", F12: "F12",
|
||||
|
||||
// Numpad
|
||||
Numpad0: "Num 0", Numpad1: "Num 1", Numpad2: "Num 2",
|
||||
Numpad3: "Num 3", Numpad4: "Num 4", Numpad5: "Num 5",
|
||||
Numpad6: "Num 6", Numpad7: "Num 7", Numpad8: "Num 8",
|
||||
Numpad9: "Num 9", NumpadAdd: "Num +", NumpadSubtract: "Num -",
|
||||
NumpadMultiply: "Num *", NumpadDivide: "Num /", NumpadDecimal: "Num .",
|
||||
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"
|
||||
};
|
||||
export function decodeModifiers(modifier: number) {
|
||||
return {
|
||||
isShiftActive: (modifier & (modifiers.ShiftLeft | modifiers.ShiftRight)) !== 0,
|
||||
isControlActive: (modifier & (modifiers.ControlLeft | modifiers.ControlRight)) !== 0,
|
||||
isAltActive: (modifier & (modifiers.AltLeft | modifiers.AltRight)) !== 0,
|
||||
isMetaActive: (modifier & (modifiers.MetaLeft | modifiers.MetaRight)) !== 0,
|
||||
isAltGrActive: (modifier & modifiers.AltGr) !== 0,
|
||||
};
|
||||
}
|
|
@ -1,28 +1,20 @@
|
|||
import { useCallback, useEffect, useMemo } from "react";
|
||||
import { useCallback, useEffect } from "react";
|
||||
|
||||
import { useSettingsStore } from "@/hooks/stores";
|
||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||
import notifications from "@/notifications";
|
||||
import { useKeyboardLayout } from "@/hooks/useKeyboardLayout";
|
||||
import { SettingsPageHeader } from "@components/SettingsPageheader";
|
||||
import { keyboardOptions } from "@/keyboardLayouts";
|
||||
import { Checkbox } from "@/components/Checkbox";
|
||||
|
||||
import { SelectMenuBasic } from "../components/SelectMenuBasic";
|
||||
import { SelectMenuBasic } from "@/components/SelectMenuBasic";
|
||||
import { keyboardOptions } from "@/keyboardLayouts";
|
||||
import notifications from "@/notifications";
|
||||
|
||||
import { SettingsItem } from "./devices.$id.settings";
|
||||
|
||||
export default function SettingsKeyboardRoute() {
|
||||
const { keyboardLayout, setKeyboardLayout } = useSettingsStore();
|
||||
const { setKeyboardLayout } = useSettingsStore();
|
||||
const { showPressedKeys, setShowPressedKeys } = useSettingsStore();
|
||||
|
||||
// this ensures we always get the en-US if it hasn't been set yet
|
||||
// and if we get en_US from the backend, we convert it to en-US
|
||||
const safeKeyboardLayout = useMemo(() => {
|
||||
if (keyboardLayout && keyboardLayout.length > 0)
|
||||
return keyboardLayout.replace("en_US", "en-US");
|
||||
return "en-US";
|
||||
}, [keyboardLayout]);
|
||||
|
||||
const { keyboard } = useKeyboardLayout();
|
||||
const layoutOptions = keyboardOptions();
|
||||
|
||||
const { send } = useJsonRpc();
|
||||
|
@ -30,21 +22,25 @@ export default function SettingsKeyboardRoute() {
|
|||
useEffect(() => {
|
||||
send("getKeyboardLayout", {}, resp => {
|
||||
if ("error" in resp) return;
|
||||
setKeyboardLayout(resp.result as string);
|
||||
const isoCode = resp.result as string;
|
||||
console.log("Fetched keyboard layout from backend:", isoCode);
|
||||
if (isoCode && isoCode.length > 0) {
|
||||
setKeyboardLayout(isoCode);
|
||||
}
|
||||
});
|
||||
}, [send, setKeyboardLayout]);
|
||||
|
||||
const onKeyboardLayoutChange = useCallback(
|
||||
(e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const layout = e.target.value;
|
||||
send("setKeyboardLayout", { layout }, resp => {
|
||||
const isoCode = e.target.value;
|
||||
send("setKeyboardLayout", { layout: isoCode }, 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);
|
||||
notifications.success("Keyboard layout set successfully to " + isoCode);
|
||||
setKeyboardLayout(isoCode);
|
||||
});
|
||||
},
|
||||
[send, setKeyboardLayout],
|
||||
|
@ -58,7 +54,6 @@ export default function SettingsKeyboardRoute() {
|
|||
/>
|
||||
|
||||
<div className="space-y-4">
|
||||
{ /* this menu item could be renamed to plain "Keyboard layout" in the future, when also the virtual keyboard layout mappings are being implemented */ }
|
||||
<SettingsItem
|
||||
title="Paste text"
|
||||
description="Keyboard layout of target operating system"
|
||||
|
@ -67,7 +62,7 @@ export default function SettingsKeyboardRoute() {
|
|||
size="SM"
|
||||
label=""
|
||||
fullWidth
|
||||
value={safeKeyboardLayout}
|
||||
value={keyboard.isoCode}
|
||||
onChange={onKeyboardLayoutChange}
|
||||
options={layoutOptions}
|
||||
/>
|
||||
|
|
|
@ -17,10 +17,10 @@ import { Button } from "@/components/Button";
|
|||
import EmptyCard from "@/components/EmptyCard";
|
||||
import Card from "@/components/Card";
|
||||
import { MAX_TOTAL_MACROS, COPY_SUFFIX, DEFAULT_DELAY } from "@/constants/macros";
|
||||
import { keyDisplayMap, modifierDisplayMap } from "@/keyboardMappings";
|
||||
import notifications from "@/notifications";
|
||||
import { ConfirmDialog } from "@/components/ConfirmDialog";
|
||||
import LoadingSpinner from "@/components/LoadingSpinner";
|
||||
import { useKeyboardLayout } from "@/hooks/useKeyboardLayout";
|
||||
|
||||
const normalizeSortOrders = (macros: KeySequence[]): KeySequence[] => {
|
||||
return macros.map((macro, index) => ({
|
||||
|
@ -35,6 +35,7 @@ export default function SettingsMacrosRoute() {
|
|||
const [actionLoadingId, setActionLoadingId] = useState<string | null>(null);
|
||||
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
|
||||
const [macroToDelete, setMacroToDelete] = useState<KeySequence | null>(null);
|
||||
const { keyboard } = useKeyboardLayout();
|
||||
|
||||
const isMaxMacrosReached = useMemo(
|
||||
() => macros.length >= MAX_TOTAL_MACROS,
|
||||
|
@ -185,7 +186,7 @@ export default function SettingsMacrosRoute() {
|
|||
step.modifiers.map((modifier, idx) => (
|
||||
<Fragment key={`mod-${idx}`}>
|
||||
<span className="font-medium text-slate-600 dark:text-slate-200">
|
||||
{modifierDisplayMap[modifier] || modifier}
|
||||
{keyboard.modifierDisplayMap[modifier] || modifier}
|
||||
</span>
|
||||
{idx < step.modifiers.length - 1 && (
|
||||
<span className="text-slate-400 dark:text-slate-600">
|
||||
|
@ -210,7 +211,7 @@ export default function SettingsMacrosRoute() {
|
|||
step.keys.map((key, idx) => (
|
||||
<Fragment key={`key-${idx}`}>
|
||||
<span className="font-medium text-blue-600 dark:text-blue-400">
|
||||
{keyDisplayMap[key] || key}
|
||||
{keyboard.keyDisplayMap[key] || key}
|
||||
</span>
|
||||
{idx < step.keys.length - 1 && (
|
||||
<span className="text-slate-400 dark:text-slate-600">
|
||||
|
@ -297,8 +298,10 @@ export default function SettingsMacrosRoute() {
|
|||
actionLoadingId,
|
||||
handleDeleteMacro,
|
||||
handleMoveMacro,
|
||||
keyboard.modifierDisplayMap,
|
||||
keyboard.keyDisplayMap,
|
||||
handleDuplicateMacro,
|
||||
navigate,
|
||||
navigate
|
||||
],
|
||||
);
|
||||
|
||||
|
|
|
@ -17,14 +17,13 @@ import { useResizeObserver } from "usehooks-ts";
|
|||
|
||||
import Card from "@/components/Card";
|
||||
import { LinkButton } from "@/components/Button";
|
||||
import { FeatureFlag } from "@/components/FeatureFlag";
|
||||
import LoadingSpinner from "@/components/LoadingSpinner";
|
||||
import { useUiStore } from "@/hooks/stores";
|
||||
import useKeyboard from "@/hooks/useKeyboard";
|
||||
|
||||
import { FeatureFlag } from "../components/FeatureFlag";
|
||||
import { cx } from "../cva.config";
|
||||
|
||||
|
||||
/* TODO: Migrate to using URLs instead of the global state. To simplify the refactoring, we'll keep the global state for now. */
|
||||
export default function SettingsRoute() {
|
||||
const location = useLocation();
|
||||
|
@ -65,16 +64,10 @@ export default function SettingsRoute() {
|
|||
}, [width]);
|
||||
|
||||
useEffect(() => {
|
||||
// disable focus trap
|
||||
setTimeout(() => {
|
||||
// Reset keyboard state. In case the user is pressing a key while enabling the sidebar
|
||||
resetKeyboardState();
|
||||
setDisableVideoFocusTrap(true);
|
||||
// For some reason, the focus trap is not disabled immediately
|
||||
// so we need to blur the active element
|
||||
(document.activeElement as HTMLElement)?.blur();
|
||||
console.debug("Just disabled focus trap");
|
||||
}, 300);
|
||||
resetKeyboardState();
|
||||
}, 500);
|
||||
|
||||
return () => {
|
||||
setDisableVideoFocusTrap(false);
|
||||
|
|
Loading…
Reference in New Issue