Skip to content

Commit

Permalink
SRShortcutAction: Try to recover type of the NSEventTypeFlagsChanged …
Browse files Browse the repository at this point in the history
…event when keyCode is incorrect

SRAXGlobalShortcutMonitor intercepts all keyboard events which allows
to track changes of the modifier flags more or less reliably and thus
diff previous and current values.

Refs #129
  • Loading branch information
Kentzo committed Jun 25, 2020
1 parent 168e409 commit c0f6966
Showing 1 changed file with 31 additions and 8 deletions.
39 changes: 31 additions & 8 deletions Library/SRShortcutAction.m
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#import <Carbon/Carbon.h>
#import <os/trace.h>
#import <os/activity.h>
#import <stdatomic.h>

#import "SRShortcutAction.h"
#import "SRCommon.h"
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit c0f6966

Please sign in to comment.