refactor(common): introduce modifier-key-constants

Refactor the `getModifierState` and `getStateFromLayer` functions into a
cleaner `modifierStringToState` function, and move from web into common.

Marks existing functions as deprecated but does not update usage at this
time.
This commit is contained in:
Marc Durdin 2026-04-07 06:55:38 +02:00
parent 4be89fef1f
commit d15f410d14
4 changed files with 73 additions and 0 deletions

View file

@ -189,3 +189,42 @@ export function visualKeyboardShiftToLayerName(shift: VisualKeyboardShiftState):
}
return result.substring(0, result.length - 1);
}
/**
* Get modifier key state from a hyphen-separated modifier string, such as
* found in layer ids or key "layer" properties. Ignores unrecognized
* components. Order of components is not significant.
*
* @param modifierString a modifier string such as 'ctrl-shift'
* @return Keyman modifier state bitmask
*/
export function modifierStringToState(modifierString: string): ModifierKeyConstant {
const map = new Map<string,ModifierKeyConstant>([
['shift', ModifierKeyConstant.K_SHIFTFLAG],
['leftctrl', ModifierKeyConstant.LCTRLFLAG],
['rightctrl', ModifierKeyConstant.RCTRLFLAG],
['ctrl', ModifierKeyConstant.K_CTRLFLAG],
['leftalt', ModifierKeyConstant.LALTFLAG],
['rightalt', ModifierKeyConstant.RALTFLAG],
['alt', ModifierKeyConstant.K_ALTFLAG],
['caps', ModifierKeyConstant.CAPITALFLAG],
// legacy mappings: these were deprecated when we introduced chiral
// modifiers in KeymanWeb in ~v14.0; typically these would have been used
// without other components, but for the purposes of this function, we can
// treat them as components without harm
['altshift', ModifierKeyConstant.K_ALTFLAG | ModifierKeyConstant.K_SHIFTFLAG],
['ctrlalt', ModifierKeyConstant.K_CTRLFLAG | ModifierKeyConstant.K_ALTFLAG],
['ctrlaltshift', ModifierKeyConstant.K_CTRLFLAG | ModifierKeyConstant.K_ALTFLAG | ModifierKeyConstant.K_SHIFTFLAG],
['ctrlshift', ModifierKeyConstant.K_CTRLFLAG | ModifierKeyConstant.K_SHIFTFLAG],
]);
let modifier = 0;
const components = modifierString.split('-');
for(const component of components) {
if(map.has(component)) {
modifier |= map.get(component);
}
}
return modifier;
}

View file

@ -20,6 +20,7 @@ export {
ModifierKeyConstant, ModifierKeyConstants, LDML_MODIFIER_TO_KVK_MODIFIER, KVK_MODIFIER_TO_LDML_MODIFIER,
translateLdmlModifiersToVisualKeyboardShift, translateVisualKeyboardShiftToLdmlModifiers,
visualKeyboardShiftToLayerName,
modifierStringToState,
} from './consts/modifier-key-constants.js';
export * as TouchLayout from './keyman-touch-layout/keyman-touch-layout-file.js';

View file

@ -0,0 +1,31 @@
/*
* Keyman is copyright (C) SIL Global. MIT License.
*/
import 'mocha';
import { assert } from 'chai';
import { ModifierKeyConstant, modifierStringToState } from '../../src/consts/modifier-key-constants.js';
describe('modifierStringToState', function() {
it('should map modifiers correctly', function() {
assert.equal(modifierStringToState(''), 0);
assert.equal(modifierStringToState('shift'), ModifierKeyConstant.K_SHIFTFLAG);
assert.equal(modifierStringToState('ctrl'), ModifierKeyConstant.K_CTRLFLAG);
assert.equal(modifierStringToState('rightctrl'), ModifierKeyConstant.RCTRLFLAG);
assert.equal(modifierStringToState('ctrl-shift'), ModifierKeyConstant.K_CTRLFLAG | ModifierKeyConstant.K_SHIFTFLAG);
assert.equal(modifierStringToState('ctrl-shift-alt'), ModifierKeyConstant.K_CTRLFLAG | ModifierKeyConstant.K_SHIFTFLAG | ModifierKeyConstant.K_ALTFLAG);
assert.equal(modifierStringToState('ctrl-shift-alt-caps'), ModifierKeyConstant.K_CTRLFLAG | ModifierKeyConstant.K_SHIFTFLAG | ModifierKeyConstant.K_ALTFLAG | ModifierKeyConstant.CAPITALFLAG);
assert.equal(modifierStringToState('caps-alt-ctrl-shift'), ModifierKeyConstant.K_CTRLFLAG | ModifierKeyConstant.K_SHIFTFLAG | ModifierKeyConstant.K_ALTFLAG | ModifierKeyConstant.CAPITALFLAG);
});
it('should map legacy modifiers correctly', function() {
assert.equal(modifierStringToState('altshift'), ModifierKeyConstant.K_ALTFLAG | ModifierKeyConstant.K_SHIFTFLAG);
assert.equal(modifierStringToState('ctrlaltshift'), ModifierKeyConstant.K_CTRLFLAG | ModifierKeyConstant.K_SHIFTFLAG | ModifierKeyConstant.K_ALTFLAG);
});
it('should ignore unknown modifiers', function() {
assert.equal(modifierStringToState('ctrl-shift-none'), ModifierKeyConstant.K_CTRLFLAG | ModifierKeyConstant.K_SHIFTFLAG);
assert.equal(modifierStringToState('ctrlraltshift'), 0);
assert.equal(modifierStringToState('ncaps'), 0);
});
});

View file

@ -86,6 +86,7 @@ const Codes = {
/**
* Get modifier key state from layer id
*
* @deprecated Use `modifierStringToState` from `@keymanapp/common-types`; note that 'caps' is also matched
* @param {string} layerId layer id (e.g. ctrlshift)
* @return {number} modifier key state (desktop keyboards)
*/
@ -128,6 +129,7 @@ const Codes = {
/**
* Get state key state from layer id
*
* @deprecated Use `modifierStringToState` from `@keymanapp/common-types`; note that modifiers are also matched
* @param {string} layerId layer id (e.g. caps)
* @return {number} modifier key state (desktop keyboards)
*/