mirror of https://github.com/jetkvm/kvm.git
Move keyboardmapping store to stores.ts, simplified some things, updated settings.tsx to set the keyboard layout properly.
This commit is contained in:
parent
0e855adc35
commit
7c40e2e011
|
@ -5,18 +5,18 @@ import {
|
||||||
useRTCStore,
|
useRTCStore,
|
||||||
useSettingsStore,
|
useSettingsStore,
|
||||||
useVideoStore,
|
useVideoStore,
|
||||||
|
useKeyboardMappingsStore,
|
||||||
} from "@/hooks/stores";
|
} from "@/hooks/stores";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { keyboardMappingsStore } from "@/keyboardMappings/KeyboardMappingStore";
|
|
||||||
|
|
||||||
export default function InfoBar() {
|
export default function InfoBar() {
|
||||||
const [keys, setKeys] = useState(keyboardMappingsStore.keys);
|
const [keys, setKeys] = useState(useKeyboardMappingsStore.keys);
|
||||||
const [modifiers, setModifiers] = useState(keyboardMappingsStore.modifiers);
|
const [modifiers, setModifiers] = useState(useKeyboardMappingsStore.modifiers);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribeKeyboardStore = keyboardMappingsStore.subscribe(() => {
|
const unsubscribeKeyboardStore = useKeyboardMappingsStore.subscribe(() => {
|
||||||
setKeys(keyboardMappingsStore.keys);
|
setKeys(useKeyboardMappingsStore.keys);
|
||||||
setModifiers(keyboardMappingsStore.modifiers);
|
setModifiers(useKeyboardMappingsStore.modifiers);
|
||||||
});
|
});
|
||||||
return unsubscribeKeyboardStore; // Cleanup on unmount
|
return unsubscribeKeyboardStore; // Cleanup on unmount
|
||||||
}, []);
|
}, []);
|
||||||
|
|
|
@ -4,11 +4,9 @@ import { Button } from "@components/Button";
|
||||||
import Card from "@components/Card";
|
import Card from "@components/Card";
|
||||||
import { ChevronDownIcon } from "@heroicons/react/16/solid";
|
import { ChevronDownIcon } from "@heroicons/react/16/solid";
|
||||||
import "react-simple-keyboard/build/css/index.css";
|
import "react-simple-keyboard/build/css/index.css";
|
||||||
import { useHidStore, useUiStore } from "@/hooks/stores";
|
import { useHidStore, useUiStore, useKeyboardMappingsStore } from "@/hooks/stores";
|
||||||
import { Transition } from "@headlessui/react";
|
import { Transition } from "@headlessui/react";
|
||||||
import { cx } from "@/cva.config";
|
import { cx } from "@/cva.config";
|
||||||
//import { keys, modifiers } from "@/keyboardMappings/KeyboardMappingStore";
|
|
||||||
import { keyboardMappingsStore } from "@/keyboardMappings/KeyboardMappingStore";
|
|
||||||
import useKeyboard from "@/hooks/useKeyboard";
|
import useKeyboard from "@/hooks/useKeyboard";
|
||||||
import DetachIconRaw from "@/assets/detach-icon.svg";
|
import DetachIconRaw from "@/assets/detach-icon.svg";
|
||||||
import AttachIconRaw from "@/assets/attach-icon.svg";
|
import AttachIconRaw from "@/assets/attach-icon.svg";
|
||||||
|
@ -22,13 +20,13 @@ const AttachIcon = ({ className }: { className?: string }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
function KeyboardWrapper() {
|
function KeyboardWrapper() {
|
||||||
const [keys, setKeys] = useState(keyboardMappingsStore.keys);
|
const [keys, setKeys] = useState(useKeyboardMappingsStore.keys);
|
||||||
const [modifiers, setModifiers] = useState(keyboardMappingsStore.modifiers);
|
const [modifiers, setModifiers] = useState(useKeyboardMappingsStore.modifiers);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribeKeyboardStore = keyboardMappingsStore.subscribe(() => {
|
const unsubscribeKeyboardStore = useKeyboardMappingsStore.subscribe(() => {
|
||||||
setKeys(keyboardMappingsStore.keys);
|
setKeys(useKeyboardMappingsStore.keys);
|
||||||
setModifiers(keyboardMappingsStore.modifiers);
|
setModifiers(useKeyboardMappingsStore.modifiers);
|
||||||
});
|
});
|
||||||
return unsubscribeKeyboardStore; // Cleanup on unmount
|
return unsubscribeKeyboardStore; // Cleanup on unmount
|
||||||
}, []);
|
}, []);
|
||||||
|
|
|
@ -6,8 +6,8 @@ import {
|
||||||
useSettingsStore,
|
useSettingsStore,
|
||||||
useUiStore,
|
useUiStore,
|
||||||
useVideoStore,
|
useVideoStore,
|
||||||
|
useKeyboardMappingsStore,
|
||||||
} from "@/hooks/stores";
|
} from "@/hooks/stores";
|
||||||
import { keyboardMappingsStore } from "@/keyboardMappings/KeyboardMappingStore";
|
|
||||||
import { useResizeObserver } from "@/hooks/useResizeObserver";
|
import { useResizeObserver } from "@/hooks/useResizeObserver";
|
||||||
import { cx } from "@/cva.config";
|
import { cx } from "@/cva.config";
|
||||||
import VirtualKeyboard from "@components/VirtualKeyboard";
|
import VirtualKeyboard from "@components/VirtualKeyboard";
|
||||||
|
@ -18,13 +18,13 @@ import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import { ConnectionErrorOverlay, HDMIErrorOverlay, LoadingOverlay } from "./VideoOverlay";
|
import { ConnectionErrorOverlay, HDMIErrorOverlay, LoadingOverlay } from "./VideoOverlay";
|
||||||
|
|
||||||
export default function WebRTCVideo() {
|
export default function WebRTCVideo() {
|
||||||
const [keys, setKeys] = useState(keyboardMappingsStore.keys);
|
const [keys, setKeys] = useState(useKeyboardMappingsStore.keys);
|
||||||
const [modifiers, setModifiers] = useState(keyboardMappingsStore.modifiers);
|
const [modifiers, setModifiers] = useState(useKeyboardMappingsStore.modifiers);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribeKeyboardStore = keyboardMappingsStore.subscribe(() => {
|
const unsubscribeKeyboardStore = useKeyboardMappingsStore.subscribe(() => {
|
||||||
setKeys(keyboardMappingsStore.keys);
|
setKeys(useKeyboardMappingsStore.keys);
|
||||||
setModifiers(keyboardMappingsStore.modifiers);
|
setModifiers(useKeyboardMappingsStore.modifiers);
|
||||||
});
|
});
|
||||||
return unsubscribeKeyboardStore; // Cleanup on unmount
|
return unsubscribeKeyboardStore; // Cleanup on unmount
|
||||||
}, []);
|
}, []);
|
||||||
|
@ -218,12 +218,15 @@ export default function WebRTCVideo() {
|
||||||
const prev = useHidStore.getState();
|
const prev = useHidStore.getState();
|
||||||
let code = e.code;
|
let code = e.code;
|
||||||
const key = e.key;
|
const key = e.key;
|
||||||
|
console.log(e);
|
||||||
|
console.log(key);
|
||||||
|
|
||||||
// if (document.activeElement?.id !== "videoFocusTrap") {
|
// if (document.activeElement?.id !== "videoFocusTrap") {hH
|
||||||
// console.log("KEYUP: Not focusing on the video", document.activeElement);
|
// console.log("KEYUP: Not focusing on the video", document.activeElement);
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
console.log(document.activeElement);
|
//
|
||||||
|
// console.log(document.activeElement);
|
||||||
|
|
||||||
setIsNumLockActive(e.getModifierState("NumLock"));
|
setIsNumLockActive(e.getModifierState("NumLock"));
|
||||||
setIsCapsLockActive(e.getModifierState("CapsLock"));
|
setIsCapsLockActive(e.getModifierState("CapsLock"));
|
||||||
|
@ -289,6 +292,7 @@ export default function WebRTCVideo() {
|
||||||
prev.activeModifiers.filter(k => k !== modifiers[e.code]),
|
prev.activeModifiers.filter(k => k !== modifiers[e.code]),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.log(e.key);
|
||||||
sendKeyboardEvent([...new Set(newKeys)], [...new Set(newModifiers)]);
|
sendKeyboardEvent([...new Set(newKeys)], [...new Set(newModifiers)]);
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
|
|
|
@ -3,28 +3,27 @@ import { GridCard } from "@components/Card";
|
||||||
import { TextAreaWithLabel } from "@components/TextArea";
|
import { TextAreaWithLabel } from "@components/TextArea";
|
||||||
import { SectionHeader } from "@components/SectionHeader";
|
import { SectionHeader } from "@components/SectionHeader";
|
||||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import { useHidStore, useRTCStore, useUiStore } from "@/hooks/stores";
|
import { useHidStore, useRTCStore, useUiStore, useKeyboardMappingsStore } from "@/hooks/stores";
|
||||||
import notifications from "../../notifications";
|
import notifications from "../../notifications";
|
||||||
import { useCallback, useEffect, useRef, useState } from "react";
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
import { LuCornerDownLeft } from "react-icons/lu";
|
import { LuCornerDownLeft } from "react-icons/lu";
|
||||||
import { ExclamationCircleIcon } from "@heroicons/react/16/solid";
|
import { ExclamationCircleIcon } from "@heroicons/react/16/solid";
|
||||||
import { useClose } from "@headlessui/react";
|
import { useClose } from "@headlessui/react";
|
||||||
import { keyboardMappingsStore } from "@/keyboardMappings/KeyboardMappingStore";
|
|
||||||
|
|
||||||
const hidKeyboardPayload = (keys: number[], modifier: number) => {
|
const hidKeyboardPayload = (keys: number[], modifier: number) => {
|
||||||
return { keys, modifier };
|
return { keys, modifier };
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function PasteModal() {
|
export default function PasteModal() {
|
||||||
const [keys, setKeys] = useState(keyboardMappingsStore.keys);
|
const [keys, setKeys] = useState(useKeyboardMappingsStore.keys);
|
||||||
const [chars, setChars] = useState(keyboardMappingsStore.chars);
|
const [chars, setChars] = useState(useKeyboardMappingsStore.chars);
|
||||||
const [modifiers, setModifiers] = useState(keyboardMappingsStore.modifiers);
|
const [modifiers, setModifiers] = useState(useKeyboardMappingsStore.modifiers);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribeKeyboardStore = keyboardMappingsStore.subscribe(() => {
|
const unsubscribeKeyboardStore = useKeyboardMappingsStore.subscribe(() => {
|
||||||
setKeys(keyboardMappingsStore.keys);
|
setKeys(useKeyboardMappingsStore.keys);
|
||||||
setChars(keyboardMappingsStore.chars);
|
setChars(useKeyboardMappingsStore.chars);
|
||||||
setModifiers(keyboardMappingsStore.modifiers);
|
setModifiers(useKeyboardMappingsStore.modifiers);
|
||||||
});
|
});
|
||||||
return unsubscribeKeyboardStore; // Cleanup on unmount
|
return unsubscribeKeyboardStore; // Cleanup on unmount
|
||||||
}, []);
|
}, []);
|
||||||
|
@ -54,13 +53,14 @@ export default function PasteModal() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (const char of text) {
|
for (const char of text) {
|
||||||
const { key, shift, alt } = chars[char] ?? {};
|
const { key, shift, altLeft, altRight } = chars[char] ?? {};
|
||||||
if (!key) continue;
|
if (!key) continue;
|
||||||
|
|
||||||
// Build the modifier bitmask
|
// Build the modifier bitmask
|
||||||
const modifier =
|
const modifier =
|
||||||
(shift ? modifiers["ShiftLeft"] : 0) |
|
(shift ? modifiers["ShiftLeft"] : 0) |
|
||||||
(alt ? modifiers["AltLeft"] : 0);
|
(altLeft ? modifiers["AltLeft"] : 0) |
|
||||||
|
(altRight ? modifiers["AltRight"] : 0); // This is important for a lot of keyboard layouts, right and left alt have different functions
|
||||||
|
|
||||||
await new Promise<void>((resolve, reject) => {
|
await new Promise<void>((resolve, reject) => {
|
||||||
send(
|
send(
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {
|
||||||
useSettingsStore,
|
useSettingsStore,
|
||||||
useUiStore,
|
useUiStore,
|
||||||
useUpdateStore,
|
useUpdateStore,
|
||||||
|
useKeyboardMappingsStore,
|
||||||
} from "@/hooks/stores";
|
} from "@/hooks/stores";
|
||||||
import { Checkbox } from "@components/Checkbox";
|
import { Checkbox } from "@components/Checkbox";
|
||||||
import { Button, LinkButton } from "@components/Button";
|
import { Button, LinkButton } from "@components/Button";
|
||||||
|
@ -25,8 +26,6 @@ import LocalAuthPasswordDialog from "@/components/LocalAuthPasswordDialog";
|
||||||
import { LocalDevice } from "@routes/devices.$id";
|
import { LocalDevice } from "@routes/devices.$id";
|
||||||
import { useRevalidator } from "react-router-dom";
|
import { useRevalidator } from "react-router-dom";
|
||||||
import { ShieldCheckIcon } from "@heroicons/react/20/solid";
|
import { ShieldCheckIcon } from "@heroicons/react/20/solid";
|
||||||
import { keyboardMappingsStore } from "@/keyboardMappings/KeyboardMappingStore";
|
|
||||||
import { KeyboardLayout } from "@/keyboardMappings/KeyboardLayouts";
|
|
||||||
|
|
||||||
export function SettingsItem({
|
export function SettingsItem({
|
||||||
title,
|
title,
|
||||||
|
@ -157,8 +156,7 @@ export default function SettingsSidebar() {
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO set this to update to the actual layout chosen
|
useKeyboardMappingsStore.setLayout(keyboardLayout)
|
||||||
keyboardMappingsStore.setLayout(KeyboardLayout.UKApple)
|
|
||||||
setKeyboardLayout(keyboardLayout);
|
setKeyboardLayout(keyboardLayout);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -294,6 +292,7 @@ export default function SettingsSidebar() {
|
||||||
send("getKeyboardLayout", {}, resp => {
|
send("getKeyboardLayout", {}, resp => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
setKeyboardLayout(String(resp.result));
|
setKeyboardLayout(String(resp.result));
|
||||||
|
useKeyboardMappingsStore.setLayout(String(resp.result))
|
||||||
});
|
});
|
||||||
|
|
||||||
send("getStreamQualityFactor", {}, resp => {
|
send("getStreamQualityFactor", {}, resp => {
|
||||||
|
@ -545,7 +544,7 @@ export default function SettingsSidebar() {
|
||||||
size="SM"
|
size="SM"
|
||||||
label=""
|
label=""
|
||||||
// TODO figure out how to make this selector wider like the EDID one?
|
// TODO figure out how to make this selector wider like the EDID one?
|
||||||
//fullWidth
|
//fullWidthƒ
|
||||||
value={keyboardLayout}
|
value={keyboardLayout}
|
||||||
options={[
|
options={[
|
||||||
{ value: "uk", label: "GB" },
|
{ value: "uk", label: "GB" },
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { createJSONStorage, persist } from "zustand/middleware";
|
import { createJSONStorage, persist } from "zustand/middleware";
|
||||||
|
import { getKeyboardMappings } from "@/keyboardMappings/KeyboardLayouts";
|
||||||
|
|
||||||
// Utility function to append stats to a Map
|
// Utility function to append stats to a Map
|
||||||
const appendStatToMap = <T extends { timestamp: number }>(
|
const appendStatToMap = <T extends { timestamp: number }>(
|
||||||
|
@ -528,3 +529,39 @@ export const useLocalAuthModalStore = create<LocalAuthModalState>(set => ({
|
||||||
setModalView: view => set({ modalView: view }),
|
setModalView: view => set({ modalView: view }),
|
||||||
setErrorMessage: message => set({ errorMessage: message }),
|
setErrorMessage: message => set({ errorMessage: message }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
class KeyboardMappingsStore {
|
||||||
|
private _layout: string = 'us';
|
||||||
|
private _subscribers: (() => void)[] = [];
|
||||||
|
|
||||||
|
public keys = getKeyboardMappings(this._layout).keys;
|
||||||
|
public chars = getKeyboardMappings(this._layout).chars;
|
||||||
|
public modifiers = getKeyboardMappings(this._layout).modifiers;
|
||||||
|
|
||||||
|
setLayout(newLayout: string) {
|
||||||
|
if (this._layout === newLayout) return;
|
||||||
|
this._layout = newLayout;
|
||||||
|
const updatedMappings = getKeyboardMappings(newLayout);
|
||||||
|
this.keys = updatedMappings.keys;
|
||||||
|
this.chars = updatedMappings.chars;
|
||||||
|
this.modifiers = updatedMappings.modifiers;
|
||||||
|
this._notifySubscribers();
|
||||||
|
}
|
||||||
|
|
||||||
|
getLayout() {
|
||||||
|
return this._layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribe(callback: () => void) {
|
||||||
|
this._subscribers.push(callback);
|
||||||
|
return () => {
|
||||||
|
this._subscribers = this._subscribers.filter(sub => sub !== callback); // Cleanup
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private _notifySubscribers() {
|
||||||
|
this._subscribers.forEach(callback => callback());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useKeyboardMappingsStore = new KeyboardMappingsStore();
|
|
@ -1,20 +1,15 @@
|
||||||
import {keysUKApple, charsUKApple, modifiersUKApple } from './layouts/uk_apple';
|
import {keysUKApple, charsUKApple, modifiersUKApple } from './layouts/uk_apple';
|
||||||
import {keysUS, charsUS, modifiersUS } from './layouts/us';
|
import {keysUS, charsUS, modifiersUS } from './layouts/us';
|
||||||
|
|
||||||
export enum KeyboardLayout {
|
export function getKeyboardMappings(layout: string) {
|
||||||
US = "us",
|
switch (layout) {
|
||||||
UKApple = "uk_apple",
|
case "uk_apple":
|
||||||
}
|
return {
|
||||||
|
keys: keysUKApple,
|
||||||
export function getKeyboardMappings(layout: KeyboardLayout) {
|
chars: charsUKApple,
|
||||||
switch (layout) {
|
modifiers: modifiersUKApple,
|
||||||
case KeyboardLayout.UKApple:
|
};
|
||||||
return {
|
case "us":
|
||||||
keys: keysUKApple,
|
|
||||||
chars: charsUKApple,
|
|
||||||
modifiers: modifiersUKApple,
|
|
||||||
};
|
|
||||||
case KeyboardLayout.US:
|
|
||||||
default:
|
default:
|
||||||
return {
|
return {
|
||||||
keys: keysUS,
|
keys: keysUS,
|
||||||
|
@ -22,4 +17,4 @@ export function getKeyboardMappings(layout: KeyboardLayout) {
|
||||||
modifiers: modifiersUS,
|
modifiers: modifiersUS,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,39 +0,0 @@
|
||||||
import { getKeyboardMappings, KeyboardLayout } from "@/keyboardMappings/KeyboardLayouts";
|
|
||||||
|
|
||||||
// TODO Move this in with all the other stores?
|
|
||||||
|
|
||||||
class KeyboardMappingsStore {
|
|
||||||
private _layout: KeyboardLayout = KeyboardLayout.US;
|
|
||||||
private _subscribers: (() => void)[] = [];
|
|
||||||
|
|
||||||
public keys = getKeyboardMappings(this._layout).keys;
|
|
||||||
public chars = getKeyboardMappings(this._layout).chars;
|
|
||||||
public modifiers = getKeyboardMappings(this._layout).modifiers;
|
|
||||||
|
|
||||||
setLayout(newLayout: KeyboardLayout) {
|
|
||||||
if (this._layout === newLayout) return;
|
|
||||||
this._layout = newLayout;
|
|
||||||
const updatedMappings = getKeyboardMappings(newLayout);
|
|
||||||
this.keys = updatedMappings.keys;
|
|
||||||
this.chars = updatedMappings.chars;
|
|
||||||
this.modifiers = updatedMappings.modifiers;
|
|
||||||
this._notifySubscribers();
|
|
||||||
}
|
|
||||||
|
|
||||||
getLayout() {
|
|
||||||
return this._layout;
|
|
||||||
}
|
|
||||||
|
|
||||||
subscribe(callback: () => void) {
|
|
||||||
this._subscribers.push(callback);
|
|
||||||
return () => {
|
|
||||||
this._subscribers = this._subscribers.filter(sub => sub !== callback); // Cleanup
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private _notifySubscribers() {
|
|
||||||
this._subscribers.forEach(callback => callback());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const keyboardMappingsStore = new KeyboardMappingsStore();
|
|
|
@ -12,11 +12,11 @@ export const charsUKApple = {
|
||||||
"~": { key: "Backquote", shift: true },
|
"~": { key: "Backquote", shift: true },
|
||||||
"\\" : { key: "Backslash", shift: false },
|
"\\" : { key: "Backslash", shift: false },
|
||||||
"|": { key: "Backslash", shift: true },
|
"|": { key: "Backslash", shift: true },
|
||||||
"#": { key: "Digit3", shift: false, alt: true },
|
"#": { key: "Digit3", shift: false, altLeft: true },
|
||||||
"£": { key: "Digit3", shift: true },
|
"£": { key: "Digit3", shift: true },
|
||||||
"@": { key: "Digit2", shift: true },
|
"@": { key: "Digit2", shift: true },
|
||||||
"\"": { key: "Quote", shift: true },
|
"\"": { key: "Quote", shift: true },
|
||||||
} as Record<string, { key: string | number; shift: boolean; alt?: boolean; }>;
|
} as Record<string, { key: string | number; shift: boolean; altLeft?: boolean; altRight?: boolean; }>;
|
||||||
|
|
||||||
// Modifiers are typically the same between UK and US layouts
|
// Modifiers are typically the same between UK and US layouts
|
||||||
export const modifiersUKApple = {
|
export const modifiersUKApple = {
|
||||||
|
|
|
@ -200,8 +200,8 @@ export const charsUS = {
|
||||||
"\n": { key: "Enter", shift: false },
|
"\n": { key: "Enter", shift: false },
|
||||||
Enter: { key: "Enter", shift: false },
|
Enter: { key: "Enter", shift: false },
|
||||||
Tab: { key: "Tab", shift: false },
|
Tab: { key: "Tab", shift: false },
|
||||||
} as Record<string, { key: string | number; shift: boolean; alt?: boolean; }>;
|
} as Record<string, { key: string | number; shift: boolean; altLeft?: boolean; altRight?: boolean; }>;
|
||||||
|
|
||||||
export const modifiersUS = {
|
export const modifiersUS = {
|
||||||
ControlLeft: 0x01,
|
ControlLeft: 0x01,
|
||||||
ControlRight: 0x10,
|
ControlRight: 0x10,
|
||||||
|
|
Loading…
Reference in New Issue