fix(mac): Caps processing was not consistent with core

Fixes #7632.

If Caps Lock was on, rules that did not specify Caps Lock state were
not matched, for example:

```
+ [K_SLASH] > 'foo'
```

The truth table for matches is:

Event    |    Rule     | Result
---------|-------------|-----------
NCAPS    |    0        | match
NCAPS    |    CAPS     | no match
NCAPS    |    NCAPS    | match
CAPS     |    0        | match
CAPS     |    CAPS     | match
CAPS     |    NCAPS    | no match

(Internally, Keyman for Mac currently maps 0 to NCAPS on the event for
simplicity.)

The fix is to ignore the Event Caps Lock state if the rule specifies
neither `CAPS` nor `NCAPS`. If the rule specifies either of these
state masks, then the Caps component of the state mask must match.
This commit is contained in:
Marc Durdin 2022-11-23 09:25:11 +11:00
parent a70d25839b
commit a45145ae3d
2 changed files with 7 additions and 3 deletions

View file

@ -144,6 +144,7 @@ struct COMP_STORE {
#define ISVIRTUALKEY 0x4000 // It is a Virtual Key Sequence
#define VIRTUALCHARKEY 0x8000 // Keyman 6.0: Virtual Key Cap Sequence
#define K_MODIFIERFLAG 0x007F
#define K_CAPITALMASK (CAPITALFLAG|NOTCAPITALFLAG)
struct COMP_KEY {
WORD Key; // Windows VK code or character value (VIRTUALCHARKEY, ISVIRTUALKEY)

View file

@ -278,8 +278,7 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx";
DWORD kMask = mask;
if (self.debugMode)
NSLog(@"Has shift flags: %X", key.shiftFlags);
//DWORD flags = key.shiftFlags & 0x0FFF;
if ((key.shiftFlags & NOTCAPITALFLAG) && !(kMask & CAPITALFLAG))
if ((kMask & CAPITALFLAG) == 0)
kMask |= NOTCAPITALFLAG;
if ((key.shiftFlags & K_CTRLFLAG) && (kMask & LCTRLFLAG)) {
kMask |= K_CTRLFLAG;
@ -305,7 +304,11 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx";
NSLog(@"mFlag = %X", mFlag);
NSLog(@"mMask = %X", mMask);
}
if ((kMask & CAPITALFLAG && key.shiftFlags & CAPITALFLAG) || (!(kMask & CAPITALFLAG) && !(key.shiftFlags & CAPITALFLAG))) {
// If key.shiftFlags has neither CAPITALMASK nor NOTCAPITALMASK,
// we ignore Caps state, otherwise Caps state must match
// precisely
if ((key.shiftFlags & K_CAPITALMASK) == 0 ||
(key.shiftFlags & K_CAPITALMASK) == (kMask & K_CAPITALMASK)) {
if (mMask == mFlag) {
if (!key.context.length) {
mKey = key;