diff --git a/Library/SRShortcutAction.m b/Library/SRShortcutAction.m index 6de4b5ea..62a474a5 100644 --- a/Library/SRShortcutAction.m +++ b/Library/SRShortcutAction.m @@ -6,6 +6,7 @@ #import #import #import +#import #import "SRShortcutAction.h" #import "SRCommon.h" @@ -1265,6 +1266,7 @@ - (void)willRemoveShortcut:(SRShortcut *)aShortcut @implementation SRAXGlobalShortcutMonitor { BOOL _canActivelyFilterEvents; + _Atomic(NSEventModifierFlags) _lastSeenModifierFlags; } CGEventRef _Nullable _SRQuartzEventHandler(CGEventTapProxy aProxy, CGEventType aType, CGEventRef anEvent, void * _Nullable aUserInfo) @@ -1298,6 +1300,8 @@ - (instancetype)initWithRunLoop:(NSRunLoop *)aRunLoop - (instancetype)initWithRunLoop:(NSRunLoop *)aRunLoop tapOptions:(CGEventTapOptions)aTapOptions { + _lastSeenModifierFlags = ATOMIC_VAR_INIT(0); + static const CGEventMask Mask = (CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(kCGEventKeyUp) | CGEventMaskBit(kCGEventFlagsChanged)); @@ -1356,9 +1360,32 @@ - (CGEventRef)handleEvent:(CGEventRef)anEvent return; } - SRKeyEventType eventType = nsEvent.SR_keyEventType; - if (eventType == 0) - return; + SRKeyEventType eventType = 0; + + if (nsEvent.type == NSEventTypeFlagsChanged && nsEvent.keyCode == 0) + { + os_trace("#Error Flags changed event without a key code"); + __auto_type currentModifierFlags = nsEvent.modifierFlags & SRCocoaModifierFlagsMask; + __auto_type addedModifierFlags = currentModifierFlags & ~_lastSeenModifierFlags; + __auto_type removedModifierFlags = _lastSeenModifierFlags & ~currentModifierFlags; + + // Each modifier flag is "1" in the binary representation. + __auto_type numberOfChangedFlags = __builtin_popcountll(addedModifierFlags) + __builtin_popcountll(removedModifierFlags); + + if (numberOfChangedFlags != 1) + { + os_trace("#Error Ambigious flags changed event: default to SRKeyEventTypeDown"); + eventType = addedModifierFlags != 0 ? SRKeyEventTypeDown : SRKeyEventTypeUp; + } + else if (addedModifierFlags) + eventType = SRKeyEventTypeDown; + else if (removedModifierFlags) + eventType = SRKeyEventTypeUp; + } + else + eventType = nsEvent.SR_keyEventType; + + _lastSeenModifierFlags = nsEvent.modifierFlags & SRCocoaModifierFlagsMask; __auto_type actions = [self enabledActionsForShortcut:shortcut keyEvent:eventType]; __block BOOL isHandled = NO; @@ -1577,11 +1604,7 @@ - (BOOL)handleEvent:(NSEvent *)anEvent withTarget:(nullable id)aTarget return NO; } - SRKeyEventType eventType = anEvent.SR_keyEventType; - if (eventType == 0) - return NO; - - __auto_type actions = [self enabledActionsForShortcut:shortcut keyEvent:eventType]; + __auto_type actions = [self enabledActionsForShortcut:shortcut keyEvent:anEvent.SR_keyEventType]; __block BOOL isHandled = NO; [actions enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(SRShortcutAction *obj, NSUInteger idx, BOOL *stop)