From 0566280bc4de8cf28bc31b0ca220edb7921d9142 Mon Sep 17 00:00:00 2001 From: farkon00 <59134591+farkon00@users.noreply.github.com> Date: Wed, 10 Jan 2024 16:48:16 +0200 Subject: [PATCH] impr(layout emulator): add support for alt layer emulation (farkon00) (#4817) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * impr: add AltGr support to the keyboard emulator * Added a polish layout * fix: fix caps lock and punctuation behavior for layout emulator * Add AltGr version of Ґ to the Ukrainian layout * Fixed the backquote key not working for the layout emulator * Renamed polish layout to polish programmers * Made layout emulator use both alts for modifications on mac --- frontend/scripts/json-validation.js | 16 ++--- frontend/src/ts/test/layout-emulator.ts | 77 ++++++++++--------------- frontend/static/layouts/_list.json | 13 ++++- 3 files changed, 51 insertions(+), 55 deletions(-) diff --git a/frontend/scripts/json-validation.js b/frontend/scripts/json-validation.js index 06d7c3ef3..4903c4272 100644 --- a/frontend/scripts/json-validation.js +++ b/frontend/scripts/json-validation.js @@ -219,25 +219,25 @@ function validateOthers() { properties: { row1: { type: "array", - items: { type: "string", minLength: 1, maxLength: 2 }, + items: { type: "string", minLength: 1, maxLength: 4 }, minItems: 13, maxItems: 13, }, row2: { type: "array", - items: { type: "string", minLength: 1, maxLength: 2 }, + items: { type: "string", minLength: 1, maxLength: 4 }, minItems: 13, maxItems: 13, }, row3: { type: "array", - items: { type: "string", minLength: 1, maxLength: 2 }, + items: { type: "string", minLength: 1, maxLength: 4 }, minItems: 11, maxItems: 11, }, row4: { type: "array", - items: { type: "string", minLength: 1, maxLength: 2 }, + items: { type: "string", minLength: 1, maxLength: 4 }, minItems: 10, maxItems: 10, }, @@ -263,25 +263,25 @@ function validateOthers() { properties: { row1: { type: "array", - items: { type: "string", minLength: 1, maxLength: 2 }, + items: { type: "string", minLength: 1, maxLength: 4 }, minItems: 13, maxItems: 13, }, row2: { type: "array", - items: { type: "string", minLength: 1, maxLength: 2 }, + items: { type: "string", minLength: 1, maxLength: 4 }, minItems: 12, maxItems: 12, }, row3: { type: "array", - items: { type: "string", minLength: 1, maxLength: 2 }, + items: { type: "string", minLength: 1, maxLength: 4 }, minItems: 12, maxItems: 12, }, row4: { type: "array", - items: { type: "string", minLength: 1, maxLength: 2 }, + items: { type: "string", minLength: 1, maxLength: 4 }, minItems: 11, maxItems: 11, }, diff --git a/frontend/src/ts/test/layout-emulator.ts b/frontend/src/ts/test/layout-emulator.ts index 2bcc1fe50..63c4d060f 100644 --- a/frontend/src/ts/test/layout-emulator.ts +++ b/frontend/src/ts/test/layout-emulator.ts @@ -3,40 +3,26 @@ import * as Misc from "../utils/misc"; import { capsState } from "./caps-warning"; import * as Notifications from "../elements/notifications"; -function shouldCapslockUseSecondCharLocation(keyLocation: string): boolean { - return [ - "KeyQ", - "KeyW", - "KeyE", - "KeyR", - "KeyT", - "KeyY", - "KeyU", - "KeyI", - "KeyO", - "KeyP", - "KeyA", - "KeyS", - "KeyD", - "KeyF", - "KeyG", - "KeyH", - "KeyJ", - "KeyK", - "KeyL", - "KeyZ", - "KeyX", - "KeyC", - "KeyV", - "KeyB", - "KeyN", - "KeyM", - ].includes(keyLocation); -} +let isAltGrPressed = false; +const isPunctuationPattern = /\p{P}/u; export async function getCharFromEvent( event: JQuery.KeyDownEvent ): Promise { + function emulatedLayoutGetVariantIndex( + event: JQuery.KeyDownEvent, + keyVariants: string + ): number { + let isCapitalized = event.shiftKey; + const altGrIndex = isAltGrPressed && keyVariants.length > 2 ? 2 : 0; + const isNotPunctuation = !isPunctuationPattern.test( + keyVariants.slice(altGrIndex, altGrIndex + 2) + ); + if (capsState && isNotPunctuation) { + isCapitalized = !event.shiftKey; + } + return (isCapitalized ? 1 : 0) + altGrIndex; + } let layout; try { @@ -215,31 +201,30 @@ export async function getCharFromEvent( .concat(layoutKeys["row4"]) .concat(layoutKeys["row5"]); - let mapIndex: number | null = null; - for (let i = 0; i < keyEventCodes.length; i++) { - if (event.code === keyEventCodes[i]) { - mapIndex = i; - } - } - if (mapIndex === null) { + const mapIndex = keyEventCodes.indexOf(event.code); + if (mapIndex === -1) { if (event.code.includes("Numpad")) { return event.key; } else { return null; } } - - const capsSwap = shouldCapslockUseSecondCharLocation(event.code); - const charIndex = - (capsState && !event.shiftKey && capsSwap) || - (capsState && event.shiftKey && !capsSwap) || - (!capsState && event.shiftKey) - ? 1 - : 0; - const char = layoutMap[mapIndex][charIndex]; + const variant = emulatedLayoutGetVariantIndex(event, layoutMap[mapIndex]); + const char = layoutMap[mapIndex][variant]; if (char) { return char; } else { return event.key; } } + +function updateAltGrState(event: JQuery.KeyboardEventBase): void { + const shouldHandleLeftAlt = + event.code === "AltLeft" && navigator.userAgent.includes("Mac"); + if (event.code !== "AltRight" && !shouldHandleLeftAlt) return; + if (event.type === "keydown") isAltGrPressed = true; + if (event.type === "keyup") isAltGrPressed = false; +} + +$(document).on("keydown", updateAltGrState); +$(document).on("keyup", updateAltGrState); diff --git a/frontend/static/layouts/_list.json b/frontend/static/layouts/_list.json index c514b4908..4bda3f524 100644 --- a/frontend/static/layouts/_list.json +++ b/frontend/static/layouts/_list.json @@ -1264,6 +1264,17 @@ "row5": [" "] } }, + "polish_programmers": { + "keymapShowTopRow": false, + "type": "ansi", + "keys": { + "row1": ["`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+"], + "row2": ["qQ", "wW", "eEęĘ", "rR", "tT", "yY", "uU", "iI", "oOóÓ", "pP", "[{", "]}", "\\|"], + "row3": ["aAąĄ", "sSśŚ", "dD", "fF", "gG", "hH", "jJ", "kK", "lLłŁ", ";:", "'\""], + "row4": ["zZżŻ", "xXźŹ", "cCćĆ", "vV", "bB", "nNńŃ", "mM", ",<", ".>", "/?"], + "row5": [" "] + } + }, "bulgarian": { "keymapShowTopRow": false, "type": "iso", @@ -1291,7 +1302,7 @@ "type": "ansi", "keys": { "row1": ["'₴", "1!", "2\"", "3№", "4;", "5%", "6:", "7?", "8*", "9(", "0)", "-_", "=+"], - "row2": ["йЙ", "цЦ", "уУ", "кК", "еЕ", "нН", "гГ", "шШ", "щЩ", "зЗ", "хХ", "їЇ", "ґҐ"], + "row2": ["йЙ", "цЦ", "уУ", "кК", "еЕ", "нН", "гГґҐ", "шШ", "щЩ", "зЗ", "хХ", "їЇ", "ґҐ"], "row3": ["фФ", "іІ", "вВ", "аА", "пП", "рР", "оО", "лЛ", "дД", "жЖ", "єЄ"], "row4": ["яЯ", "чЧ", "сС", "мМ", "иИ", "тТ", "ьЬ", "бБ", "юЮ", ".,"], "row5": [" "]