From a45145ae3d8c0b6522ee2bc8f2e16564ea396cce Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 23 Nov 2022 09:25:11 +1100 Subject: [PATCH] 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. --- .../KeymanEngine4Mac/KME/KMBinaryFileFormat.h | 1 + mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMBinaryFileFormat.h b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMBinaryFileFormat.h index 60d394be71..17483dabd2 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMBinaryFileFormat.h +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMBinaryFileFormat.h @@ -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) diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m index 293799915a..40ad2678f2 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m @@ -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;