-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathHotKeyService.m
More file actions
147 lines (110 loc) · 3.92 KB
/
HotKeyService.m
File metadata and controls
147 lines (110 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#import "HotKeyService.h"
#import <Carbon/Carbon.h>
#import "HotKey.h"
NSString * const HotKeyHandlerDidTriggerHotKey = @"HotKeyHandlerDidTriggerHotKey";
@interface HotKeyService ()
@property (nonatomic, strong) NSMutableDictionary *hotKeys;
@end
@implementation HotKeyService
static id this;
+ (HotKeyService *)sharedService {
static HotKeyService *sharedService = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedService = [[self alloc] init];
});
return sharedService;
}
- (id)init {
self = [super init];
if (self) {
[self setup];
}
return self;
}
- (void)setup {
this = self;
self.hotKeys = [NSMutableDictionary dictionary];
[self installHotKeyHandler];
}
- (void)installHotKeyHandler {
EventTypeSpec eventType;
eventType.eventClass = kEventClassKeyboard;
eventType.eventKind = kEventHotKeyPressed;
InstallApplicationEventHandler(&hotKeyHandler,
1,
&eventType,
NULL,
NULL);
}
- (HotKey *)registerHotKey:(HotKey *)hotKey {
hotKey.keyID = (int)[self.hotKeys count] + 1;
EventHotKeyID hotKeyID;
hotKeyID.signature = 'cdk1';
hotKeyID.id = hotKey.keyID;
EventHotKeyRef hotKeyRef;
OSStatus err = RegisterEventHotKey(hotKey.keyCode,
hotKey.carbonModifiers,
hotKeyID,
GetApplicationEventTarget(),
0,
&hotKeyRef);
if (err != 0) {
return nil;
}
hotKey.value = [NSValue valueWithPointer:hotKeyRef];
self.hotKeys[@(hotKey.keyID)] = hotKey;
return hotKey;
}
- (HotKey *)findHotKeyByID:(int)keyID {
return self.hotKeys[@(keyID)];
}
static OSStatus hotKeyHandler(EventHandlerCallRef nextHandler,
EventRef theEvent,
void *userData) {
EventHotKeyID hotKeyID;
GetEventParameter(theEvent,
kEventParamDirectObject,
typeEventHotKeyID,
NULL,
sizeof(hotKeyID),
NULL,
&hotKeyID);
UInt32 keyID = hotKeyID.id;
HotKey *hotKey = [this findHotKeyByID:keyID];
[this dispatchNotificationForHotKey:hotKey];
return noErr;
}
- (void)dispatchNotificationForHotKey:(HotKey *)hotKey {
NSNotification *notification = [NSNotification notificationWithName:HotKeyHandlerDidTriggerHotKey
object:nil
userInfo:@{@"hotKey":hotKey}];
[[NSNotificationCenter defaultCenter] postNotification:notification];
}
- (void)unregisterAllHotKeys {
NSDictionary *hotKeys = [self.hotKeys copy];
for (id keyID in hotKeys) {
[self unregisterHotKey:hotKeys[keyID]];
}
}
- (void)unregisterHotKey:(HotKey *)hotKey {
EventHotKeyRef hotKeyRef = (EventHotKeyRef)[hotKey.value pointerValue];
UnregisterEventHotKey(hotKeyRef);
hotKey.value = nil;
[self.hotKeys removeObjectForKey:@(hotKey.keyID)];
}
- (void)dispatchKeyEventsForHotKeys:(NSArray *)hotKeys {
ProcessSerialNumber processSerialNumber;
GetFrontProcess(&processSerialNumber);
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
for (int i = 0; i < [hotKeys count]; i++) {
HotKey *hotKey = hotKeys[i];
CGEventRef ev;
ev = CGEventCreateKeyboardEvent(source, (CGKeyCode)hotKey.keyCode, true);
CGEventSetFlags(ev, hotKey.modifiers);
CGEventPostToPSN(&processSerialNumber, ev);
CFRelease(ev);
}
CFRelease(source);
}
@end