Add a temporary solution to non-Latin keyboards being unusable
This commit is contained in:
parent
720a04b501
commit
05737202fa
|
|
@ -37,37 +37,41 @@ export function createInputManager(editor: EditorState, container: HTMLElement,
|
|||
// Don't redirect when a modal is covering the workspace
|
||||
if (dialog.dialogIsVisible()) return false;
|
||||
|
||||
const key = getLatinKey(e);
|
||||
|
||||
// Don't redirect a fullscreen request
|
||||
if (e.key.toLowerCase() === "f11" && e.type === "keydown" && !e.repeat) {
|
||||
if (key === "f11" && e.type === "keydown" && !e.repeat) {
|
||||
e.preventDefault();
|
||||
fullscreen.toggleFullscreen();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't redirect a reload request
|
||||
if (e.key.toLowerCase() === "f5") return false;
|
||||
if (key === "f5") return false;
|
||||
|
||||
// Don't redirect debugging tools
|
||||
if (e.key.toLowerCase() === "f12") return false;
|
||||
if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === "c") return false;
|
||||
if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === "i") return false;
|
||||
if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === "j") return false;
|
||||
if (key === "f12") return false;
|
||||
if (e.ctrlKey && e.shiftKey && key === "c") return false;
|
||||
if (e.ctrlKey && e.shiftKey && key === "i") return false;
|
||||
if (e.ctrlKey && e.shiftKey && key === "j") return false;
|
||||
|
||||
// Redirect to the backend
|
||||
return true;
|
||||
};
|
||||
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
const key = getLatinKey(e);
|
||||
|
||||
if (shouldRedirectKeyboardEventToBackend(e)) {
|
||||
e.preventDefault();
|
||||
const modifiers = makeModifiersBitfield(e);
|
||||
editor.instance.on_key_down(e.key, modifiers);
|
||||
editor.instance.on_key_down(key, modifiers);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dialog.dialogIsVisible()) {
|
||||
if (e.key === "Escape") dialog.dismissDialog();
|
||||
if (e.key === "Enter") {
|
||||
if (key === "escape") dialog.dismissDialog();
|
||||
if (key === "enter") {
|
||||
dialog.submitDialog();
|
||||
|
||||
// Prevent the Enter key from acting like a click on the last clicked button, which might reopen the dialog
|
||||
|
|
@ -77,10 +81,12 @@ export function createInputManager(editor: EditorState, container: HTMLElement,
|
|||
};
|
||||
|
||||
const onKeyUp = (e: KeyboardEvent) => {
|
||||
const key = getLatinKey(e);
|
||||
|
||||
if (shouldRedirectKeyboardEventToBackend(e)) {
|
||||
e.preventDefault();
|
||||
const modifiers = makeModifiersBitfield(e);
|
||||
editor.instance.on_key_up(e.key, modifiers);
|
||||
editor.instance.on_key_up(key, modifiers);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -196,3 +202,329 @@ export type InputManager = ReturnType<typeof createInputManager>;
|
|||
export function makeModifiersBitfield(e: WheelEvent | PointerEvent | KeyboardEvent): number {
|
||||
return Number(e.ctrlKey) | (Number(e.shiftKey) << 1) | (Number(e.altKey) << 2);
|
||||
}
|
||||
|
||||
// This function is a naive, temporary solution to allow non-Latin keyboards to fall back on the physical QWERTY layout
|
||||
function getLatinKey(e: KeyboardEvent): string {
|
||||
const key = e.key.toLowerCase();
|
||||
const isPrintable = isKeyPrintable(e.key);
|
||||
|
||||
// Control (non-printable) characters are handled normally
|
||||
if (!isPrintable) return key;
|
||||
|
||||
// These non-Latin characters should fall back to the Latin equivalent at the key location
|
||||
const LAST_LATIN_UNICODE_CHAR = 0x024f;
|
||||
if (key.length > 1 || key.charCodeAt(0) > LAST_LATIN_UNICODE_CHAR) return e.code.toLowerCase();
|
||||
|
||||
// Otherwise, ths is a printable Latin character
|
||||
return e.key.toLowerCase();
|
||||
}
|
||||
|
||||
function isKeyPrintable(key: string): boolean {
|
||||
const allPrintableKeys: string[] = [
|
||||
// Modifier
|
||||
"Alt",
|
||||
"AltGraph",
|
||||
"CapsLock",
|
||||
"Control",
|
||||
"Fn",
|
||||
"FnLock",
|
||||
"Meta",
|
||||
"NumLock",
|
||||
"ScrollLock",
|
||||
"Shift",
|
||||
"Symbol",
|
||||
"SymbolLock",
|
||||
// Legacy modifier
|
||||
"Hyper",
|
||||
"Super",
|
||||
// White space
|
||||
"Enter",
|
||||
"Tab",
|
||||
// Navigation
|
||||
"ArrowDown",
|
||||
"ArrowLeft",
|
||||
"ArrowRight",
|
||||
"ArrowUp",
|
||||
"End",
|
||||
"Home",
|
||||
"PageDown",
|
||||
"PageUp",
|
||||
// Editing
|
||||
"Backspace",
|
||||
"Clear",
|
||||
"Copy",
|
||||
"CrSel",
|
||||
"Cut",
|
||||
"Delete",
|
||||
"EraseEof",
|
||||
"ExSel",
|
||||
"Insert",
|
||||
"Paste",
|
||||
"Redo",
|
||||
"Undo",
|
||||
// UI
|
||||
"Accept",
|
||||
"Again",
|
||||
"Attn",
|
||||
"Cancel",
|
||||
"ContextMenu",
|
||||
"Escape",
|
||||
"Execute",
|
||||
"Find",
|
||||
"Help",
|
||||
"Pause",
|
||||
"Play",
|
||||
"Props",
|
||||
"Select",
|
||||
"ZoomIn",
|
||||
"ZoomOut",
|
||||
// Device
|
||||
"BrightnessDown",
|
||||
"BrightnessUp",
|
||||
"Eject",
|
||||
"LogOff",
|
||||
"Power",
|
||||
"PowerOff",
|
||||
"PrintScreen",
|
||||
"Hibernate",
|
||||
"Standby",
|
||||
"WakeUp",
|
||||
// IME composition keys
|
||||
"AllCandidates",
|
||||
"Alphanumeric",
|
||||
"CodeInput",
|
||||
"Compose",
|
||||
"Convert",
|
||||
"Dead",
|
||||
"FinalMode",
|
||||
"GroupFirst",
|
||||
"GroupLast",
|
||||
"GroupNext",
|
||||
"GroupPrevious",
|
||||
"ModeChange",
|
||||
"NextCandidate",
|
||||
"NonConvert",
|
||||
"PreviousCandidate",
|
||||
"Process",
|
||||
"SingleCandidate",
|
||||
// Korean-specific
|
||||
"HangulMode",
|
||||
"HanjaMode",
|
||||
"JunjaMode",
|
||||
// Japanese-specific
|
||||
"Eisu",
|
||||
"Hankaku",
|
||||
"Hiragana",
|
||||
"HiraganaKatakana",
|
||||
"KanaMode",
|
||||
"KanjiMode",
|
||||
"Katakana",
|
||||
"Romaji",
|
||||
"Zenkaku",
|
||||
"ZenkakuHankaku",
|
||||
// Common function
|
||||
"F1",
|
||||
"F2",
|
||||
"F3",
|
||||
"F4",
|
||||
"F5",
|
||||
"F6",
|
||||
"F7",
|
||||
"F8",
|
||||
"F9",
|
||||
"F10",
|
||||
"F11",
|
||||
"F12",
|
||||
"Soft1",
|
||||
"Soft2",
|
||||
"Soft3",
|
||||
"Soft4",
|
||||
// Multimedia
|
||||
"ChannelDown",
|
||||
"ChannelUp",
|
||||
"Close",
|
||||
"MailForward",
|
||||
"MailReply",
|
||||
"MailSend",
|
||||
"MediaClose",
|
||||
"MediaFastForward",
|
||||
"MediaPause",
|
||||
"MediaPlay",
|
||||
"MediaPlayPause",
|
||||
"MediaRecord",
|
||||
"MediaRewind",
|
||||
"MediaStop",
|
||||
"MediaTrackNext",
|
||||
"MediaTrackPrevious",
|
||||
"New",
|
||||
"Open",
|
||||
"Print",
|
||||
"Save",
|
||||
"SpellCheck",
|
||||
// Multimedia numpad
|
||||
"Key11",
|
||||
"Key12",
|
||||
// Audio
|
||||
"AudioBalanceLeft",
|
||||
"AudioBalanceRight",
|
||||
"AudioBassBoostDown",
|
||||
"AudioBassBoostToggle",
|
||||
"AudioBassBoostUp",
|
||||
"AudioFaderFront",
|
||||
"AudioFaderRear",
|
||||
"AudioSurroundModeNext",
|
||||
"AudioTrebleDown",
|
||||
"AudioTrebleUp",
|
||||
"AudioVolumeDown",
|
||||
"AudioVolumeUp",
|
||||
"AudioVolumeMute",
|
||||
"MicrophoneToggle",
|
||||
"MicrophoneVolumeDown",
|
||||
"MicrophoneVolumeUp",
|
||||
"MicrophoneVolumeMute",
|
||||
// Speech
|
||||
"SpeechCorrectionList",
|
||||
"SpeechInputToggle",
|
||||
// Application
|
||||
"LaunchApplication1",
|
||||
"LaunchApplication2",
|
||||
"LaunchCalendar",
|
||||
"LaunchContacts",
|
||||
"LaunchMail",
|
||||
"LaunchMediaPlayer",
|
||||
"LaunchMusicPlayer",
|
||||
"LaunchPhone",
|
||||
"LaunchScreenSaver",
|
||||
"LaunchSpreadsheet",
|
||||
"LaunchWebBrowser",
|
||||
"LaunchWebCam",
|
||||
"LaunchWordProcessor",
|
||||
// Browser
|
||||
"BrowserBack",
|
||||
"BrowserFavorites",
|
||||
"BrowserForward",
|
||||
"BrowserHome",
|
||||
"BrowserRefresh",
|
||||
"BrowserSearch",
|
||||
"BrowserStop",
|
||||
// Mobile phone
|
||||
"AppSwitch",
|
||||
"Call",
|
||||
"Camera",
|
||||
"CameraFocus",
|
||||
"EndCall",
|
||||
"GoBack",
|
||||
"GoHome",
|
||||
"HeadsetHook",
|
||||
"LastNumberRedial",
|
||||
"Notification",
|
||||
"MannerMode",
|
||||
"VoiceDial",
|
||||
// TV
|
||||
"TV",
|
||||
"TV3DMode",
|
||||
"TVAntennaCable",
|
||||
"TVAudioDescription",
|
||||
"TVAudioDescriptionMixDown",
|
||||
"TVAudioDescriptionMixUp",
|
||||
"TVContentsMenu",
|
||||
"TVDataService",
|
||||
"TVInput",
|
||||
"TVInputComponent1",
|
||||
"TVInputComponent2",
|
||||
"TVInputComposite1",
|
||||
"TVInputComposite2",
|
||||
"TVInputHDMI1",
|
||||
"TVInputHDMI2",
|
||||
"TVInputHDMI3",
|
||||
"TVInputHDMI4",
|
||||
"TVInputVGA1",
|
||||
"TVMediaContext",
|
||||
"TVNetwork",
|
||||
"TVNumberEntry",
|
||||
"TVPower",
|
||||
"TVRadioService",
|
||||
"TVSatellite",
|
||||
"TVSatelliteBS",
|
||||
"TVSatelliteCS",
|
||||
"TVSatelliteToggle",
|
||||
"TVTerrestrialAnalog",
|
||||
"TVTerrestrialDigital",
|
||||
"TVTimer",
|
||||
// Media controls
|
||||
"AVRInput",
|
||||
"AVRPower",
|
||||
"ColorF0Red",
|
||||
"ColorF1Green",
|
||||
"ColorF2Yellow",
|
||||
"ColorF3Blue",
|
||||
"ColorF4Grey",
|
||||
"ColorF5Brown",
|
||||
"ClosedCaptionToggle",
|
||||
"Dimmer",
|
||||
"DisplaySwap",
|
||||
"DVR",
|
||||
"Exit",
|
||||
"FavoriteClear0",
|
||||
"FavoriteClear1",
|
||||
"FavoriteClear2",
|
||||
"FavoriteClear3",
|
||||
"FavoriteRecall0",
|
||||
"FavoriteRecall1",
|
||||
"FavoriteRecall2",
|
||||
"FavoriteRecall3",
|
||||
"FavoriteStore0",
|
||||
"FavoriteStore1",
|
||||
"FavoriteStore2",
|
||||
"FavoriteStore3",
|
||||
"Guide",
|
||||
"GuideNextDay",
|
||||
"GuidePreviousDay",
|
||||
"Info",
|
||||
"InstantReplay",
|
||||
"Link",
|
||||
"ListProgram",
|
||||
"LiveContent",
|
||||
"Lock",
|
||||
"MediaApps",
|
||||
"MediaAudioTrack",
|
||||
"MediaLast",
|
||||
"MediaSkipBackward",
|
||||
"MediaSkipForward",
|
||||
"MediaStepBackward",
|
||||
"MediaStepForward",
|
||||
"MediaTopMenu",
|
||||
"NavigateIn",
|
||||
"NavigateNext",
|
||||
"NavigateOut",
|
||||
"NavigatePrevious",
|
||||
"NextFavoriteChannel",
|
||||
"NextUserProfile",
|
||||
"OnDemand",
|
||||
"Pairing",
|
||||
"PinPDown",
|
||||
"PinPMove",
|
||||
"PinPToggle",
|
||||
"PinPUp",
|
||||
"PlaySpeedDown",
|
||||
"PlaySpeedReset",
|
||||
"PlaySpeedUp",
|
||||
"RandomToggle",
|
||||
"RcLowBattery",
|
||||
"RecordSpeedNext",
|
||||
"RfBypass",
|
||||
"ScanChannelsToggle",
|
||||
"ScreenModeNext",
|
||||
"Settings",
|
||||
"SplitScreenToggle",
|
||||
"STBInput",
|
||||
"STBPower",
|
||||
"Subtitle",
|
||||
"Teletext",
|
||||
"VideoModeNext",
|
||||
"Wink",
|
||||
"ZoomToggle",
|
||||
];
|
||||
|
||||
return !allPrintableKeys.includes(key);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue