Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 224 lines (167 sloc) 5.093 kb
ab71653 @justin Initial Repository Import
justin authored
1 //
2 // SGHotKeyCenter.m
3 // SGHotKeyCenter
4 //
5 // Created by Justin Williams on 7/26/09.
6 // Copyright 2009 Second Gear. All rights reserved.
7 //
8
9 #import <Carbon/Carbon.h>
10 #import "SGHotKeyCenter.h"
11 #import "SGHotKey.h"
12 #import "SGKeyCombo.h"
13
14 OSType const kHotKeySignature = 'SGHk';
15
16 @interface SGHotKeyCenter ()
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
17
ab71653 @justin Initial Repository Import
justin authored
18 - (SGHotKey *)_hotKeyForCarbonHotKey:(EventHotKeyRef)carbonHotKey;
19 - (EventHotKeyRef)_carbonHotKeyForHotKey:(SGHotKey *)hotKey;
20
21 - (void)_updateEventHandler;
22 - (void)_hotKeyDown: (SGHotKey *)hotKey;
23
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
24 @end
ab71653 @justin Initial Repository Import
justin authored
25
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
26 static OSStatus hotKeyEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void* refCon );
376f1be @justin Reworked the SGHotKeyCenter sharedCenter to workaround an issue I fou…
justin authored
27 static SGHotKeyCenter *sharedCenter = nil;
28
ab71653 @justin Initial Repository Import
justin authored
29 @implementation SGHotKeyCenter
30
376f1be @justin Reworked the SGHotKeyCenter sharedCenter to workaround an issue I fou…
justin authored
31 + (void)initialize {
32 if (!sharedCenter) {
33 sharedCenter = [[self alloc] init];
34 }
35 }
36
45192c2 @justin Added support for traditioanl retain/release memory management
justin authored
37 - (void)dealloc {
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
38 [hotKeys release];
39 [super dealloc];
45192c2 @justin Added support for traditioanl retain/release memory management
justin authored
40 }
41
376f1be @justin Reworked the SGHotKeyCenter sharedCenter to workaround an issue I fou…
justin authored
42 + (SGHotKeyCenter *)sharedCenter {
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
43 return sharedCenter;
ab71653 @justin Initial Repository Import
justin authored
44 }
45
376f1be @justin Reworked the SGHotKeyCenter sharedCenter to workaround an issue I fou…
justin authored
46 + (id) allocWithZone:(NSZone *)zone {
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
47 //Usually already set by +initialize.
48 if (sharedCenter) {
49 //The caller expects to receive a new object, so implicitly retain it to balance out the caller's eventual release message.
50 return [sharedCenter retain];
51 } else {
52 //When not already set, +initialize is our caller—it's creating the shared instance. Let this go through.
53 return [super allocWithZone:zone];
54 }
376f1be @justin Reworked the SGHotKeyCenter sharedCenter to workaround an issue I fou…
justin authored
55 }
56
57 - (id) init {
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
58 if (!hasInited) {
59 if ((self = [super init])) {
60 //Initialize the instance here.
376f1be @justin Reworked the SGHotKeyCenter sharedCenter to workaround an issue I fou…
justin authored
61 hotKeys = [[NSMutableDictionary alloc] init];
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
62 hasInited = YES;
63 }
64 }
376f1be @justin Reworked the SGHotKeyCenter sharedCenter to workaround an issue I fou…
justin authored
65
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
66 return self;
ab71653 @justin Initial Repository Import
justin authored
67 }
68
69 - (BOOL)registerHotKey:(SGHotKey *)theHotKey {
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
70 OSStatus error;
71 EventHotKeyID hotKeyID;
72 EventHotKeyRef carbonHotKey;
73 NSValue *key = nil;
74
75 if ([[self allHotKeys] containsObject:theHotKey])
76 [self unregisterHotKey:theHotKey];
77
78 if (![[theHotKey keyCombo] isValidHotKeyCombo])
79 return YES;
80
81 static UInt32 currentId = 0;
82 hotKeyID.signature = kHotKeySignature;
83 hotKeyID.id = ++currentId;
84
85 theHotKey.hotKeyID = hotKeyID;
86
341f810 @roustem Fixing compile warnings.
roustem authored
87 error = RegisterEventHotKey((UInt32)theHotKey.keyCombo.keyCode,
88 (UInt32)theHotKey.keyCombo.modifiers,
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
89 hotKeyID,
90 GetEventMonitorTarget(),
91 // GetEventDispatcherTarget(),
92 0,
93 &carbonHotKey);
94
95 if (error)
96 return NO;
97
98 key = [NSValue valueWithPointer:carbonHotKey];
99
100 if (theHotKey && key)
101 [hotKeys setObject:theHotKey forKey:key];
102
103 [self _updateEventHandler];
104
105 return YES;
ab71653 @justin Initial Repository Import
justin authored
106 }
107
108
109 - (void)unregisterHotKey:(SGHotKey *)theHotKey {
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
110 EventHotKeyRef carbonHotKey;
111 NSValue *key = nil;
112
113 if (![[self allHotKeys] containsObject:theHotKey])
ab71653 @justin Initial Repository Import
justin authored
114 return;
115
116 carbonHotKey = [self _carbonHotKeyForHotKey:theHotKey];
117 NSAssert(carbonHotKey != nil, @"");
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
118
ab71653 @justin Initial Repository Import
justin authored
119 UnregisterEventHotKey(carbonHotKey);
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
120
ab71653 @justin Initial Repository Import
justin authored
121 key = [NSValue valueWithPointer:carbonHotKey];
122 [hotKeys removeObjectForKey:key];
123
124 [self _updateEventHandler];
125 }
126
127 - (NSArray *)allHotKeys {
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
128 return [hotKeys allValues];
ab71653 @justin Initial Repository Import
justin authored
129 }
130
131
132 - (SGHotKey *)hotKeyWithIdentifier:(id)theIdentifier {
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
133 if (!theIdentifier)
134 return nil;
135
136 for (SGHotKey *hotKey in [self allHotKeys]) {
137 if([[hotKey identifier] isEqual:theIdentifier] )
ab71653 @justin Initial Repository Import
justin authored
138 return hotKey;
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
139 }
140
141 return nil;
ab71653 @justin Initial Repository Import
justin authored
142 }
143
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
144 - (OSStatus)processCarbonEvent:(EventRef)event {
145 OSStatus error;
146 EventHotKeyID hotKeyID;
147 SGHotKey *hotKey = nil;
148
149 NSAssert(GetEventClass(event) == kEventClassKeyboard, @"Unknown event class");
150
151 error = GetEventParameter(event,
152 kEventParamDirectObject,
153 typeEventHotKeyID,
154 nil,
155 sizeof(EventHotKeyID),
156 nil,
157 &hotKeyID);
158 if (error)
159 return error;
160
161 NSAssert(hotKeyID.signature == kHotKeySignature, @"Invalid hot key id");
162 NSAssert(hotKeyID.id != 0, @"Invalid hot key id");
163
164 for (SGHotKey *thisHotKey in [self allHotKeys]) {
165 if ([thisHotKey matchesHotKeyID:hotKeyID]) {
166 hotKey = thisHotKey;
167 break;
168 }
169 }
170
171 switch (GetEventKind(event)) {
172 case kEventHotKeyPressed:
173 [self _hotKeyDown:hotKey];
174 break;
175
176 default:
177 NSAssert(0, @"Unknown event kind");
178 break;
179 }
180
181 return eventNotHandledErr;
ab71653 @justin Initial Repository Import
justin authored
182 }
183
184 - (SGHotKey *)_hotKeyForCarbonHotKey:(EventHotKeyRef)carbonHotKey {
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
185 NSValue *key = [NSValue valueWithPointer:carbonHotKey];
ab71653 @justin Initial Repository Import
justin authored
186 return [hotKeys objectForKey:key];
187 }
188
189 - (EventHotKeyRef)_carbonHotKeyForHotKey:(SGHotKey *)hotKey {
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
190 NSArray *values;
191 NSValue *value;
192
193 values = [hotKeys allKeysForObject:hotKey];
194 NSAssert([values count] == 1, @"Failed to find Carbon Hotkey for SGHotKey");
195
196 value = [values lastObject];
197
198 return (EventHotKeyRef)[value pointerValue];
ab71653 @justin Initial Repository Import
justin authored
199 }
200
201 - (void)_updateEventHandler {
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
202 static EventHandlerUPP handler = NewEventHandlerUPP(hotKeyEventHandler);
203
ab71653 @justin Initial Repository Import
justin authored
204 if ([hotKeys count] && eventHandlerInstalled == NO) {
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
205 EventTypeSpec eventSpec[1] = {
206 { kEventClassKeyboard, kEventHotKeyPressed }
ab71653 @justin Initial Repository Import
justin authored
207 };
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
208
209 InstallEventHandler(GetEventMonitorTarget(), handler, 1, eventSpec, NULL, NULL);
ab71653 @justin Initial Repository Import
justin authored
210 eventHandlerInstalled = YES;
211 }
212 }
213
214 - (void)_hotKeyDown:(SGHotKey *)hotKey {
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
215 [hotKey invoke];
ab71653 @justin Initial Repository Import
justin authored
216 }
217
218 static OSStatus hotKeyEventHandler(EventHandlerCallRef theHandlerRef, EventRef theEvent, void *userData ) {
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
219 OSStatus result = [[SGHotKeyCenter sharedCenter] processCarbonEvent:theEvent];
220 return result;
ab71653 @justin Initial Repository Import
justin authored
221 }
0eb42ad @roustem Simplifying, removing unused code.
roustem authored
222
ab71653 @justin Initial Repository Import
justin authored
223 @end
Something went wrong with that request. Please try again.