Skip to content

Commit

Permalink
refactor(web): refactor and harmonize constants
Browse files Browse the repository at this point in the history
Note that this adds the keyCodes > 50000 to `USVirtualKeyCodes`.

Fixes: #8146
  • Loading branch information
ermshiperete committed Aug 1, 2024
1 parent dd12e73 commit 2c2acbe
Show file tree
Hide file tree
Showing 17 changed files with 189 additions and 179 deletions.
18 changes: 8 additions & 10 deletions common/web/keyboard-processor/src/keyboards/defaultLayouts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
***/

import { Version, deepCopy } from "@keymanapp/web-utils";
import { TouchLayout } from "@keymanapp/common-types";
import { ModifierKeyConstants, TouchLayout } from "@keymanapp/common-types";

import LayoutFormFactorSpec = TouchLayout.TouchLayoutPlatform;
import LayoutLayerBase = TouchLayout.TouchLayoutLayer;
Expand Down Expand Up @@ -349,31 +349,29 @@ export class Layouts {
* Description Get name of layer from code, where the modifer order is determined by ascending bit-flag value.
*/
static getLayerId(m: number): string {
let modifierCodes = Codes.modifierCodes;

var s='';
if(m == 0) {
return 'default';
} else {
if(m & modifierCodes['LCTRL']) {
if(m & ModifierKeyConstants.LCTRLFLAG) {
s = (s.length > 0 ? s + '-' : '') + 'leftctrl';
}
if(m & modifierCodes['RCTRL']) {
if(m & ModifierKeyConstants.RCTRLFLAG) {
s = (s.length > 0 ? s + '-' : '') + 'rightctrl';
}
if(m & modifierCodes['LALT']) {
if(m & ModifierKeyConstants.LALTFLAG) {
s = (s.length > 0 ? s + '-' : '') + 'leftalt';
}
if(m & modifierCodes['RALT']) {
if(m & ModifierKeyConstants.RALTFLAG) {
s = (s.length > 0 ? s + '-' : '') + 'rightalt';
}
if(m & modifierCodes['SHIFT']) {
if(m & ModifierKeyConstants.K_SHIFTFLAG) {
s = (s.length > 0 ? s + '-' : '') + 'shift';
}
if(m & modifierCodes['CTRL']) {
if(m & ModifierKeyConstants.K_CTRLFLAG) {
s = (s.length > 0 ? s + '-' : '') + 'ctrl';
}
if(m & modifierCodes['ALT']) {
if(m & ModifierKeyConstants.K_ALTFLAG) {
s = (s.length > 0 ? s + '-' : '') + 'alt';
}
return s;
Expand Down
24 changes: 11 additions & 13 deletions common/web/keyboard-processor/src/keyboards/keyboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { EncodedVisualKeyboard, LayoutSpec, Layouts } from "./defaultLayouts.js"
import { ActiveKey, ActiveLayout, ActiveSubKey } from "./activeLayout.js";
import KeyEvent from "../text/keyEvent.js";
import type OutputTarget from "../text/outputTarget.js";
import { TouchLayout } from "@keymanapp/common-types";
import { ModifierKeyConstants, TouchLayout } from "@keymanapp/common-types";
type TouchLayoutSpec = TouchLayout.TouchLayoutPlatform & { isDefault?: boolean};

import type { ComplexKeyboardStore } from "../text/kbdInterface.js";
Expand Down Expand Up @@ -108,7 +108,7 @@ export type KeyboardObject = {
KRTL?: boolean;
/**
* Keyboard Modifier BitMask: a set of bitflags indicating which modifiers
* the keyboard's rules utilize. See also: `Codes.modifierCodes`.
* the keyboard's rules utilize. See also: `ModifierKeyConstants`.
*/
KMBM?: number;
/**
Expand Down Expand Up @@ -420,8 +420,6 @@ export default class Keyboard {
* @return {boolean}
*/
get emulatesAltGr(): boolean {
let modifierCodes = Codes.modifierCodes;

// If we're not chiral, we're not emulating.
if(!this.isChiral) {
return false;
Expand All @@ -437,22 +435,22 @@ export default class Keyboard {
return false;
}

var emulationMask = modifierCodes['LCTRL'] | modifierCodes['LALT'];
var emulationMask = ModifierKeyConstants.LCTRLFLAG | ModifierKeyConstants.LALTFLAG;
var unshiftedEmulationLayer = layers[Layouts.getLayerId(emulationMask)];
var shiftedEmulationLayer = layers[Layouts.getLayerId(modifierCodes['SHIFT'] | emulationMask)];
var shiftedEmulationLayer = layers[Layouts.getLayerId(ModifierKeyConstants.K_SHIFTFLAG | emulationMask)];

// buildDefaultLayout ensures that these are aliased to the original modifier set being emulated.
// As a result, we can directly test for reference equality.
//
// This allows us to still return `true` after creating the layers for emulation; during keyboard
// construction, the two layers should be null for AltGr emulation to succeed.
if(unshiftedEmulationLayer != null &&
unshiftedEmulationLayer != layers[Layouts.getLayerId(modifierCodes['RALT'])]) {
unshiftedEmulationLayer != layers[Layouts.getLayerId(ModifierKeyConstants.RALTFLAG)]) {
return false;
}

if(shiftedEmulationLayer != null &&
shiftedEmulationLayer != layers[Layouts.getLayerId(modifierCodes['RALT'] | modifierCodes['SHIFT'])]) {
shiftedEmulationLayer != layers[Layouts.getLayerId(ModifierKeyConstants.RALTFLAG | ModifierKeyConstants.K_SHIFTFLAG)]) {
return false;
}

Expand Down Expand Up @@ -665,9 +663,9 @@ export default class Keyboard {
* same for the other modifiers.
*/
Lkc.Lstates = 0;
Lkc.Lstates |= stateKeys['K_CAPS'] ? Codes.modifierCodes['CAPS'] : Codes.modifierCodes['NO_CAPS'];
Lkc.Lstates |= stateKeys['K_NUMLOCK'] ? Codes.modifierCodes['NUM_LOCK'] : Codes.modifierCodes['NO_NUM_LOCK'];
Lkc.Lstates |= stateKeys['K_SCROLL'] ? Codes.modifierCodes['SCROLL_LOCK'] : Codes.modifierCodes['NO_SCROLL_LOCK'];
Lkc.Lstates |= stateKeys['K_CAPS'] ? ModifierKeyConstants.CAPITALFLAG : ModifierKeyConstants.NOTCAPITALFLAG;
Lkc.Lstates |= stateKeys['K_NUMLOCK'] ? ModifierKeyConstants.NUMLOCKFLAG : ModifierKeyConstants.NOTNUMLOCKFLAG;
Lkc.Lstates |= stateKeys['K_SCROLL'] ? ModifierKeyConstants.SCROLLFLAG : ModifierKeyConstants.NOTSCROLLFLAG;
}

// Set LisVirtualKey to false to ensure that nomatch rule does fire for U_xxxx keys
Expand All @@ -689,7 +687,7 @@ export default class Keyboard {
// Handles modifier states when the OSK is emulating rightalt through the leftctrl-leftalt layer.
if((Lkc.Lmodifiers & Codes.modifierBitmasks['ALT_GR_SIM']) == Codes.modifierBitmasks['ALT_GR_SIM'] && this.emulatesAltGr) {
Lkc.Lmodifiers &= ~Codes.modifierBitmasks['ALT_GR_SIM'];
Lkc.Lmodifiers |= Codes.modifierCodes['RALT'];
Lkc.Lmodifiers |= ModifierKeyConstants.RALTFLAG;
}
}

Expand Down Expand Up @@ -729,4 +727,4 @@ export default class Keyboard {
const res=dict[keyName.toUpperCase()];
return res ? res : 0;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ export interface KeyboardKeymanGlobal {
* Defines any public API points used by debug-compiled keyboards for human-readable
* nomenclature in rules within a Keyman keyboard's script for keyboard rules.
*
* Refer to C:\keymanapp\keyman\developer\src\tike\compile\CompileKeymanWeb.pas,
* TCompileKeymanWeb.JavaScript_SetupDebug.
* Refer to TCompileKeymanWeb.JavaScript_SetupDebug.
*/
export interface MinimalCodesInterface {
readonly modifierCodes: typeof Codes.modifierCodes;
Expand Down
97 changes: 37 additions & 60 deletions common/web/keyboard-processor/src/text/codes.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,36 @@
// TODO: Move to separate folder: 'codes'
// We should start splitting off code needed by keyboards even without a KeyboardProcessor active.
/*
* Keyman is copyright (C) SIL International. MIT License.
*
* Keyboard key codes and modifier bitmasks.
*/

// see also: common/web/types/src/kmx/kmx.ts
import { ModifierKeyConstants, USVirtualKeyCodes } from '@keymanapp/common-types';

const Codes = {
// Define Keyman Developer modifier bit-flags (exposed for use by other modules)
// Compare against /common/include/kmx_file.h. CTRL+F "#define LCTRLFLAG" to find the secton.
modifierCodes: {
"LCTRL":0x0001, // LCTRLFLAG
"RCTRL":0x0002, // RCTRLFLAG
"LALT":0x0004, // LALTFLAG
"RALT":0x0008, // RALTFLAG
"SHIFT":0x0010, // K_SHIFTFLAG
"CTRL":0x0020, // K_CTRLFLAG
"ALT":0x0040, // K_ALTFLAG
...ModifierKeyConstants,

// Debug-mode keyboards compiled before Keyman 18.0 referenced the `ModifierKeyConstants`
// constants via the names established below. We must continue to support them, as they're
// essentially part of the keyboard API now.
"LCTRL": ModifierKeyConstants.LCTRLFLAG,
"RCTRL": ModifierKeyConstants.RCTRLFLAG,
"LALT": ModifierKeyConstants.LALTFLAG,
"RALT": ModifierKeyConstants.RALTFLAG,
"SHIFT": ModifierKeyConstants.K_SHIFTFLAG,
"CTRL": ModifierKeyConstants.K_CTRLFLAG,
"ALT": ModifierKeyConstants.K_ALTFLAG,
// TENTATIVE: Represents command keys, which some OSes use for shortcuts we don't
// want to block. No rule will ever target a modifier set with this bit set to 1.
"META":0x0080, // K_METAFLAG
"CAPS":0x0100, // CAPITALFLAG
"NO_CAPS":0x0200, // NOTCAPITALFLAG
"NUM_LOCK":0x0400, // NUMLOCKFLAG
"NO_NUM_LOCK":0x0800, // NOTNUMLOCKFLAG
"SCROLL_LOCK":0x1000, // SCROLLFLAG
"NO_SCROLL_LOCK":0x2000, // NOTSCROLLFLAG
"VIRTUAL_KEY":0x4000, // ISVIRTUALKEY
"VIRTUAL_CHAR_KEY":0x8000 // VIRTUALCHARKEY // Unused by KMW, but reserved for use by other Keyman engines.

"META": ModifierKeyConstants.K_METAFLAG,
"CAPS": ModifierKeyConstants.CAPITALFLAG,
"NO_CAPS": ModifierKeyConstants.NOTCAPITALFLAG,
"NUM_LOCK": ModifierKeyConstants.NUMLOCKFLAG,
"NO_NUM_LOCK": ModifierKeyConstants.NOTNUMLOCKFLAG,
"SCROLL_LOCK": ModifierKeyConstants.SCROLLFLAG,
"NO_SCROLL_LOCK": ModifierKeyConstants.NOTSCROLLFLAG,
"VIRTUAL_KEY": ModifierKeyConstants.ISVIRTUALKEY,
"VIRTUAL_CHAR_KEY": ModifierKeyConstants.VIRTUALCHARKEY // Unused by KMW, but reserved for use by other Keyman engines.
// Note: keys_mod_other = 0x10000, used by KMX+ for the
// other modifier flag in layers, > 16 bit so not available here.
// See keys_mod_other in keyman_core_ldml.ts
Expand All @@ -50,35 +55,7 @@ const Codes = {

// Define standard keycode numbers (exposed for use by other modules)
keyCodes: {
"K_BKSP":8,"K_TAB":9,"K_ENTER":13,
"K_SHIFT":16,"K_CONTROL":17,"K_ALT":18,"K_PAUSE":19,"K_CAPS":20,
"K_ESC":27,"K_SPACE":32,"K_PGUP":33,
"K_PGDN":34,"K_END":35,"K_HOME":36,"K_LEFT":37,"K_UP":38,
"K_RIGHT":39,"K_DOWN":40,"K_SEL":41,"K_PRINT":42,"K_EXEC":43,
"K_INS":45,"K_DEL":46,"K_HELP":47,"K_0":48,
"K_1":49,"K_2":50,"K_3":51,"K_4":52,"K_5":53,"K_6":54,"K_7":55,
"K_8":56,"K_9":57,"K_A":65,"K_B":66,"K_C":67,"K_D":68,"K_E":69,
"K_F":70,"K_G":71,"K_H":72,"K_I":73,"K_J":74,"K_K":75,"K_L":76,
"K_M":77,"K_N":78,"K_O":79,"K_P":80,"K_Q":81,"K_R":82,"K_S":83,
"K_T":84,"K_U":85,"K_V":86,"K_W":87,"K_X":88,"K_Y":89,"K_Z":90,
"K_NP0":96,"K_NP1":97,"K_NP2":98,
"K_NP3":99,"K_NP4":100,"K_NP5":101,"K_NP6":102,
"K_NP7":103,"K_NP8":104,"K_NP9":105,"K_NPSTAR":106,
"K_NPPLUS":107,"K_SEPARATOR":108,"K_NPMINUS":109,"K_NPDOT":110,
"K_NPSLASH":111,"K_F1":112,"K_F2":113,"K_F3":114,"K_F4":115,
"K_F5":116,"K_F6":117,"K_F7":118,"K_F8":119,"K_F9":120,
"K_F10":121,"K_F11":122,"K_F12":123,"K_NUMLOCK":144,"K_SCROLL":145,
"K_LSHIFT":160,"K_RSHIFT":161,"K_LCONTROL":162,"K_RCONTROL":163,
"K_LALT":164,"K_RALT":165,
"K_COLON":186,"K_EQUAL":187,"K_COMMA":188,"K_HYPHEN":189,
"K_PERIOD":190,"K_SLASH":191,"K_BKQUOTE":192,
"K_LBRKT":219,"K_BKSLASH":220,"K_RBRKT":221,
"K_QUOTE":222,"K_oE2":226,"K_OE2":226,
"K_LOPT":50001,"K_ROPT":50002,
"K_NUMERALS":50003,"K_SYMBOLS":50004,"K_CURRENCIES":50005,
"K_UPPER":50006,"K_LOWER":50007,"K_ALPHA":50008,
"K_SHIFTED":50009,"K_ALTGR":50010,
"K_TABBACK":50011,"K_TABFWD":50012
...USVirtualKeyCodes,
} as {[name: string]: number},

codesUS: [
Expand Down Expand Up @@ -117,34 +94,34 @@ const Codes = {
getModifierState(layerId: string): number {
var modifier=0;
if(layerId.indexOf('shift') >= 0) {
modifier |= Codes.modifierCodes['SHIFT'];
modifier |= ModifierKeyConstants.K_SHIFTFLAG;
}

// The chiral checks must not be directly exclusive due each other to visual OSK feedback.
var ctrlMatched=false;
if(layerId.indexOf('leftctrl') >= 0) {
modifier |= Codes.modifierCodes['LCTRL'];
modifier |= ModifierKeyConstants.LCTRLFLAG;
ctrlMatched=true;
}
if(layerId.indexOf('rightctrl') >= 0) {
modifier |= Codes.modifierCodes['RCTRL'];
modifier |= ModifierKeyConstants.RCTRLFLAG;
ctrlMatched=true;
}
if(layerId.indexOf('ctrl') >= 0 && !ctrlMatched) {
modifier |= Codes.modifierCodes['CTRL'];
modifier |= ModifierKeyConstants.K_CTRLFLAG;
}

var altMatched=false;
if(layerId.indexOf('leftalt') >= 0) {
modifier |= Codes.modifierCodes['LALT'];
modifier |= ModifierKeyConstants.LALTFLAG;
altMatched=true;
}
if(layerId.indexOf('rightalt') >= 0) {
modifier |= Codes.modifierCodes['RALT'];
modifier |= ModifierKeyConstants.RALTFLAG;
altMatched=true;
}
if(layerId.indexOf('alt') >= 0 && !altMatched) {
modifier |= Codes.modifierCodes['ALT'];
modifier |= ModifierKeyConstants.K_ALTFLAG;
}

return modifier;
Expand All @@ -160,9 +137,9 @@ const Codes = {
var modifier=0;

if(layerId.indexOf('caps') >= 0) {
modifier |= Codes.modifierCodes['CAPS'];
modifier |= ModifierKeyConstants.CAPITALFLAG;
} else {
modifier |= Codes.modifierCodes['NO_CAPS'];
modifier |= ModifierKeyConstants.NOTCAPITALFLAG;
}

return modifier;
Expand Down
3 changes: 2 additions & 1 deletion common/web/keyboard-processor/src/text/defaultRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// We should start splitting off code needed by keyboards even without a KeyboardProcessor active.
// There's an upcoming `/common/web/types` package that 'codes' and 'keyboards' may fit well within.

import { ModifierKeyConstants} from '@keymanapp/common-types';
import Codes from "./codes.js";
import type KeyEvent from "./keyEvent.js";
import type OutputTarget from "./outputTarget.js";
Expand Down Expand Up @@ -190,7 +191,7 @@ export default class DefaultRules {

// check if exact match to SHIFT's code. Only the 'default' and 'shift' layers should have default key outputs.
// TODO: Extend to allow AltGr as well - better mnemonic support.
if(keyShiftState == Codes.modifierCodes['SHIFT']) {
if(keyShiftState == ModifierKeyConstants.K_SHIFTFLAG) {
keyShiftState = 1;
} else if(keyShiftState != 0) {
if(ruleBehavior) {
Expand Down
13 changes: 7 additions & 6 deletions common/web/keyboard-processor/src/text/kbdInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//#region Imports

import { type DeviceSpec } from "@keymanapp/web-utils";
import { ModifierKeyConstants } from '@keymanapp/common-types';

import Codes from "./codes.js";
import type KeyEvent from "./keyEvent.js";
Expand Down Expand Up @@ -552,8 +553,8 @@ export default class KeyboardInterface extends KeyboardHarness {
* @returns
*/
private static matchModifiersToRuleChirality(eventModifiers: number, targetModifierMask: number): number {
const CHIRAL_ALT = Codes.modifierCodes["LALT"] | Codes.modifierCodes["RALT"];
const CHIRAL_CTRL = Codes.modifierCodes["LCTRL"] | Codes.modifierCodes["RCTRL"];
const CHIRAL_ALT = ModifierKeyConstants.LALTFLAG | ModifierKeyConstants.RALTFLAG;
const CHIRAL_CTRL = ModifierKeyConstants.LCTRLFLAG | ModifierKeyConstants.RCTRLFLAG;

let modifiers = eventModifiers;

Expand All @@ -563,7 +564,7 @@ export default class KeyboardInterface extends KeyboardHarness {

if(altIntersection) {
// Undo the chiral part and replace with non-chiral.
modifiers ^= altIntersection | Codes.modifierCodes["ALT"];
modifiers ^= altIntersection | ModifierKeyConstants.K_ALTFLAG;
}
}

Expand All @@ -573,7 +574,7 @@ export default class KeyboardInterface extends KeyboardHarness {

if(ctrlIntersection) {
// Undo the chiral part and replace with non-chiral.
modifiers ^= ctrlIntersection | Codes.modifierCodes["CTRL"];
modifiers ^= ctrlIntersection | ModifierKeyConstants.K_CTRLFLAG;
}
}

Expand Down Expand Up @@ -939,7 +940,7 @@ export default class KeyboardInterface extends KeyboardHarness {
// Denote the changed store as part of the matched rule's behavior.
this.ruleBehavior.setStore[systemId] = strValue;
return true;
}
}
return false;
}

Expand Down Expand Up @@ -1178,4 +1179,4 @@ export default class KeyboardInterface extends KeyboardHarness {
(function() {
// This will be the only call within the keyboard-processor module.
KeyboardInterface.__publishShorthandAPI();
}());
}());
Loading

0 comments on commit 2c2acbe

Please sign in to comment.