Skip to content

Commit 3382623

Browse files
committed
SRAXGlobalShortcutMonitor: Avoid using NSEvent from the CGEventTap handler
NSEvent seems to depend on being used from the main thread, which is unncessary limiting for the monitor. Refs #129
1 parent 7d0a692 commit 3382623

File tree

3 files changed

+65
-26
lines changed

3 files changed

+65
-26
lines changed

Sources/ShortcutRecorder/SRShortcutAction.m

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -369,11 +369,13 @@ - (void)observeValueForKeyPath:(NSString *)aKeyPath
369369

370370
@implementation NSEvent (SRShortcutAction)
371371

372-
- (SRKeyEventType)SR_keyEventType
372+
+ (SRKeyEventType)SR_keyEventTypeForEventType:(NSEventType)anEventType
373+
keyCode:(unsigned short)aKeyCode
374+
modifierFlags:(NSEventModifierFlags)aModifierFlags
373375
{
374376
SRKeyEventType eventType = SRKeyEventTypeDown;
375377

376-
switch (self.type)
378+
switch (anEventType)
377379
{
378380
case NSEventTypeKeyDown:
379381
eventType = SRKeyEventTypeDown;
@@ -383,8 +385,8 @@ - (SRKeyEventType)SR_keyEventType
383385
break;
384386
case NSEventTypeFlagsChanged:
385387
{
386-
__auto_type keyCode = self.keyCode;
387-
__auto_type modifierFlags = self.modifierFlags;
388+
__auto_type keyCode = aKeyCode;
389+
__auto_type modifierFlags = aModifierFlags;
388390

389391
if (keyCode == kVK_Command || keyCode == kVK_RightCommand)
390392
eventType = modifierFlags & NSEventModifierFlagCommand ? SRKeyEventTypeDown : SRKeyEventTypeUp;
@@ -399,13 +401,18 @@ - (SRKeyEventType)SR_keyEventType
399401
break;
400402
}
401403
default:
402-
[NSException raise:NSInternalInconsistencyException format:@"Expected a key event, got %lu", self.type];
404+
[NSException raise:NSInternalInconsistencyException format:@"Expected a key event, got %lu", anEventType];
403405
break;
404406
}
405407

406408
return eventType;
407409
}
408410

411+
- (SRKeyEventType)SR_keyEventType
412+
{
413+
return [self.class SR_keyEventTypeForEventType:self.type keyCode:self.keyCode modifierFlags:self.modifierFlags];
414+
}
415+
409416
@end
410417

411418

@@ -1343,25 +1350,34 @@ - (CGEventRef)handleEvent:(CGEventRef)anEvent
13431350
__block __auto_type result = anEvent;
13441351

13451352
os_activity_initiate("-[SRAXGlobalShortcutMonitor handleEvent:]", OS_ACTIVITY_FLAG_DETACHED, ^{
1346-
__auto_type nsEvent = [NSEvent eventWithCGEvent:anEvent];
1347-
if (!nsEvent)
1348-
{
1349-
os_trace_error("#Error Unexpected event");
1350-
return;
1351-
}
1352-
1353-
__auto_type shortcut = [SRShortcut shortcutWithEvent:nsEvent ignoringCharacters:YES];
1354-
if (!shortcut)
1353+
__auto_type eventKeyCode = CGEventGetIntegerValueField(anEvent, kCGKeyboardEventKeycode);
1354+
__auto_type eventType = CGEventGetType(anEvent);
1355+
__auto_type cocoaModifierFlags = SRCoreGraphicsToCocoaFlags(CGEventGetFlags(anEvent));
1356+
NSEventType cocoaEventType;
1357+
switch (eventType)
13551358
{
1356-
os_trace_error("#Error Not a keyboard event");
1357-
return;
1359+
case kCGEventKeyDown:
1360+
cocoaEventType = NSEventTypeKeyDown;
1361+
break;
1362+
case kCGEventKeyUp:
1363+
cocoaEventType = NSEventTypeKeyUp;
1364+
break;
1365+
case kCGEventFlagsChanged:
1366+
cocoaEventType = NSEventTypeFlagsChanged;
1367+
break;
1368+
default:
1369+
cocoaEventType = 0;
1370+
break;
13581371
}
13591372

1360-
SRKeyEventType eventType = nsEvent.SR_keyEventType;
1361-
if (eventType == 0)
1362-
return;
1363-
1364-
__auto_type actions = [self enabledActionsForShortcut:shortcut keyEvent:eventType];
1373+
__auto_type shortcut = [SRShortcut shortcutWithCode:eventType != kCGEventFlagsChanged ? (SRKeyCode)eventKeyCode : SRKeyCodeNone
1374+
modifierFlags:cocoaModifierFlags
1375+
characters:nil
1376+
charactersIgnoringModifiers:nil];
1377+
__auto_type keyEventType = [NSEvent SR_keyEventTypeForEventType:cocoaEventType
1378+
keyCode:(unsigned short)eventKeyCode
1379+
modifierFlags:cocoaModifierFlags];
1380+
__auto_type actions = [self enabledActionsForShortcut:shortcut keyEvent:keyEventType];
13651381
__block BOOL isHandled = NO;
13661382
[actions enumerateObjectsWithOptions:NSEnumerationReverse
13671383
usingBlock:^(SRShortcutAction *obj, NSUInteger idx, BOOL *stop)
@@ -1578,11 +1594,7 @@ - (BOOL)handleEvent:(NSEvent *)anEvent withTarget:(nullable id)aTarget
15781594
return NO;
15791595
}
15801596

1581-
SRKeyEventType eventType = anEvent.SR_keyEventType;
1582-
if (eventType == 0)
1583-
return NO;
1584-
1585-
__auto_type actions = [self enabledActionsForShortcut:shortcut keyEvent:eventType];
1597+
__auto_type actions = [self enabledActionsForShortcut:shortcut keyEvent:anEvent.SR_keyEventType];
15861598
__block BOOL isHandled = NO;
15871599
[actions enumerateObjectsWithOptions:NSEnumerationReverse
15881600
usingBlock:^(SRShortcutAction *obj, NSUInteger idx, BOOL *stop)

Sources/ShortcutRecorder/include/ShortcutRecorder/SRCommon.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ NS_SWIFT_NAME(CarbonModifierFlagsMask)
2424
static const UInt32 SRCarbonModifierFlagsMask = cmdKey | optionKey | shiftKey | controlKey;
2525

2626

27+
NS_SWIFT_NAME(CoreGraphicsModifierFlagsMask)
28+
static const CGEventFlags SRCoreGraphicsModifierFlagsMask = kCGEventFlagMaskCommand | kCGEventFlagMaskAlternate | kCGEventFlagMaskShift | kCGEventFlagMaskControl;
29+
2730
/*!
2831
Dawable unicode characters for key codes that do not have appropriate constants in Carbon and Cocoa.
2932
@@ -301,6 +304,26 @@ NS_INLINE UInt32 SRCocoaToCarbonFlags(NSEventModifierFlags aCocoaFlags)
301304
return carbonFlags;
302305
}
303306

307+
NS_SWIFT_NAME(coreGraphicsToCocoaFlags(_:))
308+
NS_INLINE NSEventModifierFlags SRCoreGraphicsToCocoaFlags(CGEventFlags aCoreGraphicsFlags)
309+
{
310+
NSEventModifierFlags cocoaFlags = 0;
311+
312+
if (aCoreGraphicsFlags & kCGEventFlagMaskCommand)
313+
cocoaFlags |= NSEventModifierFlagCommand;
314+
315+
if (aCoreGraphicsFlags & kCGEventFlagMaskAlternate)
316+
cocoaFlags |= NSEventModifierFlagOption;
317+
318+
if (aCoreGraphicsFlags & kCGEventFlagMaskControl)
319+
cocoaFlags |= NSEventModifierFlagControl;
320+
321+
if (aCoreGraphicsFlags & kCGEventFlagMaskShift)
322+
cocoaFlags |= NSEventModifierFlagShift;
323+
324+
return cocoaFlags;
325+
}
326+
304327

305328
/*!
306329
Return Bundle where resources can be found.

Sources/ShortcutRecorder/include/ShortcutRecorder/SRShortcutAction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,10 @@ typedef NS_CLOSED_ENUM(NSUInteger, SRKeyEventType)
198198

199199
@interface NSEvent (SRShortcutAction)
200200

201+
+ (SRKeyEventType)SR_keyEventTypeForEventType:(NSEventType)anEventType
202+
keyCode:(unsigned short)aKeyCode
203+
modifierFlags:(NSEventModifierFlags)aModifierFlags;
204+
201205
/*!
202206
Keyboard event type as recognized by the shortcut recorder.
203207

0 commit comments

Comments
 (0)