Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(web): refactor and harmonize constants 🏗️ #12072

Merged
merged 2 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
modifierCodes: {
// 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.
modifierCodes: {

Optionally, we could also emit the same values under their new name:

Suggested change
modifierCodes: {
// 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.
modifierCodes: {
...ModifierKeyConstants,

so that at some point in the distant future, we could drop the old names entirely... maybe.

"RCTRL":0x0002, // RCTRLFLAG
"LALT":0x0004, // LALTFLAG
"RALT":0x0008, // RALTFLAG
"SHIFT":0x0010, // K_SHIFTFLAG
"CTRL":0x0020, // K_CTRLFLAG
"ALT":0x0040, // K_ALTFLAG
...ModifierKeyConstants,

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should include this here -- we should maintain this as a legacy interface only. Mixing the names in a published interface doesn't buy us anything -- we have to maintain the old names anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

// 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
Loading