Skip to content
Browse files

Isolates monitoring code from data.

  • Loading branch information...
1 parent 243aee3 commit 4099b62587959708bd02d1c49ec1c8fa39448cf4 @shpakovski committed Sep 19, 2012
Showing with 167 additions and 158 deletions.
  1. +8 −0 MASShortcut+Monitoring.h
  2. +158 −0 MASShortcut+Monitoring.m
  3. +1 −0 MASShortcut+UserDefaults.m
  4. +0 −3 MASShortcut.h
  5. +0 −155 MASShortcut.m
View
8 MASShortcut+Monitoring.h
@@ -0,0 +1,8 @@
+#import "MASShortcut.h"
+
+@interface MASShortcut (Monitoring)
+
++ (id)addGlobalHotkeyMonitorWithShortcut:(MASShortcut *)shortcut handler:(void (^)())handler;
++ (void)removeGlobalHotkeyMonitor:(id)monitor;
+
+@end
View
158 MASShortcut+Monitoring.m
@@ -0,0 +1,158 @@
+#import "MASShortcut+Monitoring.h"
+
+NSMutableDictionary *MASRegisteredHotKeys();
+BOOL InstallCommonEventHandler();
+void UninstallEventHandler();
+void InstallHotkeyWithShortcut(MASShortcut *shortcut, UInt32 *outCarbonHotKeyID, EventHotKeyRef *outCarbonHotKey);
+
+#pragma mark -
+
+@interface MASShortcutHotKey : NSObject
+
+@property (nonatomic, readonly) MASShortcut *shortcut;
+@property (nonatomic, readonly, copy) void (^handler)();
+@property (nonatomic, readonly) EventHotKeyRef carbonHotKey;
+@property (nonatomic, readonly) UInt32 carbonHotKeyID;
+
+- (id)initWithShortcut:(MASShortcut *)shortcut handler:(void (^)())handler;
+
+@end
+
+#pragma mark -
+
+@implementation MASShortcut (Monitoring)
+
++ (id)addGlobalHotkeyMonitorWithShortcut:(MASShortcut *)shortcut handler:(void (^)())handler
+{
+ NSString *monitor = [NSString stringWithFormat:@"%p: %@", shortcut, shortcut.description];
+ MASShortcutHotKey *hotKey = [[MASShortcutHotKey alloc] initWithShortcut:shortcut handler:handler];
+ [MASRegisteredHotKeys() setObject:hotKey forKey:monitor];
+ return monitor;
+}
+
++ (void)removeGlobalHotkeyMonitor:(id)monitor
+{
+ if (monitor == nil) return;
+ NSMutableDictionary *registeredHotKeys = MASRegisteredHotKeys();
+ [registeredHotKeys removeObjectForKey:monitor];
+ if (registeredHotKeys.count == 0) {
+ UninstallEventHandler();
+ }
+}
+
+@end
+
+#pragma mark -
+
+@implementation MASShortcutHotKey
+
+@synthesize carbonHotKeyID = _carbonHotKeyID;
+@synthesize handler = _handler;
+@synthesize shortcut = _shortcut;
+@synthesize carbonHotKey = _carbonHotKey;
+
+#pragma mark -
+
+- (id)initWithShortcut:(MASShortcut *)shortcut handler:(void (^)())handler
+{
+ self = [super init];
+ if (self) {
+ _shortcut = shortcut;
+ _handler = [handler copy];
+ InstallHotkeyWithShortcut(shortcut, &_carbonHotKeyID, &_carbonHotKey);
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ [self uninstallExisitingHotKey];
+}
+
+- (void)uninstallExisitingHotKey
+{
+ if (_carbonHotKey) {
+ UnregisterEventHotKey(_carbonHotKey);
+ _carbonHotKey = NULL;
+ }
+}
+
+@end
+
+#pragma mark - Carbon magic
+
+NSMutableDictionary *MASRegisteredHotKeys()
+{
+ static NSMutableDictionary *shared = nil;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ shared = [NSMutableDictionary dictionary];
+ });
+ return shared;
+}
+
+#pragma mark -
+
+FourCharCode const kMASShortcutSignature = 'MASS';
+
+void InstallHotkeyWithShortcut(MASShortcut *shortcut, UInt32 *outCarbonHotKeyID, EventHotKeyRef *outCarbonHotKey)
+{
+ if ((shortcut == nil) || !InstallCommonEventHandler()) return;
+
+ static UInt32 sCarbonHotKeyID = 0;
+ EventHotKeyID hotKeyID = { .signature = kMASShortcutSignature, .id = ++ sCarbonHotKeyID };
+ EventHotKeyRef carbonHotKey = NULL;
+ if (RegisterEventHotKey(shortcut.carbonKeyCode, shortcut.carbonFlags, hotKeyID, GetEventDispatcherTarget(), kEventHotKeyExclusive, &carbonHotKey) != noErr) {
+ carbonHotKey = NULL;
+ }
+
+ if (outCarbonHotKeyID) *outCarbonHotKeyID = hotKeyID.id;
+ if (outCarbonHotKey) *outCarbonHotKey = carbonHotKey;
+}
+
+static OSStatus CarbonCallback(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
+{
+ if (GetEventClass(inEvent) != kEventClassKeyboard) return noErr;
+
+ EventHotKeyID hotKeyID;
+ OSStatus status = GetEventParameter(inEvent, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(hotKeyID), NULL, &hotKeyID);
+ if (status != noErr) return status;
+
+ if (hotKeyID.signature != kMASShortcutSignature) return noErr;
+
+ [MASRegisteredHotKeys() enumerateKeysAndObjectsUsingBlock:^(id key, MASShortcutHotKey *hotKey, BOOL *stop) {
+ if (hotKeyID.id == hotKey.carbonHotKeyID) {
+ if (hotKey.handler) {
+ hotKey.handler();
+ }
+ *stop = YES;
+ }
+ }];
+
+ return noErr;
+}
+
+#pragma mark -
+
+static EventHandlerRef sEventHandler = NULL;
+
+BOOL InstallCommonEventHandler()
+{
+ if (sEventHandler == NULL) {
+ EventTypeSpec hotKeyPressedSpec = { .eventClass = kEventClassKeyboard, .eventKind = kEventHotKeyPressed };
+ OSStatus status = InstallEventHandler(GetEventDispatcherTarget(), CarbonCallback, 1, &hotKeyPressedSpec, NULL, &sEventHandler);
+ if (status != noErr) {
+ sEventHandler = NULL;
+ return NO;
+ }
+ }
+ return YES;
+}
+
+void UninstallEventHandler()
+{
+ if (sEventHandler) {
+ RemoveEventHandler(sEventHandler);
+ sEventHandler = NULL;
+ }
+}
View
1 MASShortcut+UserDefaults.m
@@ -1,4 +1,5 @@
#import "MASShortcut+UserDefaults.h"
+#import "MASShortcut+Monitoring.h"
@interface MASShortcutUserDefaultsHotKey : NSObject
View
3 MASShortcut.h
@@ -51,7 +51,4 @@ enum {
- (BOOL)isTakenError:(NSError **)error;
-+ (id)addGlobalHotkeyMonitorWithShortcut:(MASShortcut *)shortcut handler:(void (^)())handler;
-+ (void)removeGlobalHotkeyMonitor:(id)monitor;
-
@end
View
155 MASShortcut.m
@@ -3,26 +3,6 @@
NSString *const kMASShortcutKeyCode = @"KeyCode";
NSString *const kMASShortcutModifierFlags = @"ModifierFlags";
-NSMutableDictionary *MASRegisteredHotKeys();
-BOOL InstallCommonEventHandler();
-void UninstallEventHandler();
-void InstallHotkeyWithShortcut(MASShortcut *shortcut, UInt32 *outCarbonHotKeyID, EventHotKeyRef *outCarbonHotKey);
-
-#pragma mark -
-
-@interface MASShortcutHotKey : NSObject
-
-@property (nonatomic, readonly) MASShortcut *shortcut;
-@property (nonatomic, readonly, copy) void (^handler)();
-@property (nonatomic, readonly) EventHotKeyRef carbonHotKey;
-@property (nonatomic, readonly) UInt32 carbonHotKeyID;
-
-- (id)initWithShortcut:(MASShortcut *)shortcut handler:(void (^)())handler;
-
-@end
-
-#pragma mark -
-
@implementation MASShortcut {
NSUInteger _keyCode; // NSNotFound if empty
NSUInteger _modifierFlags; // 0 if empty
@@ -325,139 +305,4 @@ - (BOOL)isTakenError:(NSError **)outError
return [self isKeyEquivalent:self.keyCodeStringForKeyEquivalent flags:self.modifierFlags takenInMenu:[NSApp mainMenu] error:outError];
}
-#pragma mark - Global monitoring
-
-+ (id)addGlobalHotkeyMonitorWithShortcut:(MASShortcut *)shortcut handler:(void (^)())handler
-{
- NSString *monitor = [NSString stringWithFormat:@"%p: %@", shortcut, shortcut.description];
- MASShortcutHotKey *hotKey = [[MASShortcutHotKey alloc] initWithShortcut:shortcut handler:handler];
- [MASRegisteredHotKeys() setObject:hotKey forKey:monitor];
- return monitor;
-}
-
-+ (void)removeGlobalHotkeyMonitor:(id)monitor
-{
- if (monitor == nil) return;
- NSMutableDictionary *registeredHotKeys = MASRegisteredHotKeys();
- [registeredHotKeys removeObjectForKey:monitor];
- if (registeredHotKeys.count == 0) {
- UninstallEventHandler();
- }
-}
-
-@end
-
-#pragma mark -
-
-@implementation MASShortcutHotKey
-
-@synthesize carbonHotKeyID = _carbonHotKeyID;
-@synthesize handler = _handler;
-@synthesize shortcut = _shortcut;
-@synthesize carbonHotKey = _carbonHotKey;
-
-#pragma mark -
-
-- (id)initWithShortcut:(MASShortcut *)shortcut handler:(void (^)())handler
-{
- self = [super init];
- if (self) {
- _shortcut = shortcut;
- _handler = [handler copy];
- InstallHotkeyWithShortcut(shortcut, &_carbonHotKeyID, &_carbonHotKey);
- }
- return self;
-}
-
-- (void)dealloc
-{
- [self uninstallExisitingHotKey];
-}
-
-- (void)uninstallExisitingHotKey
-{
- if (_carbonHotKey) {
- UnregisterEventHotKey(_carbonHotKey);
- _carbonHotKey = NULL;
- }
-}
-
@end
-
-#pragma mark - Carbon magic
-
-NSMutableDictionary *MASRegisteredHotKeys()
-{
- static NSMutableDictionary *shared = nil;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- shared = [NSMutableDictionary dictionary];
- });
- return shared;
-}
-
-#pragma mark -
-
-FourCharCode const kMASShortcutSignature = 'MASS';
-
-void InstallHotkeyWithShortcut(MASShortcut *shortcut, UInt32 *outCarbonHotKeyID, EventHotKeyRef *outCarbonHotKey)
-{
- if ((shortcut == nil) || !InstallCommonEventHandler()) return;
-
- static UInt32 sCarbonHotKeyID = 0;
- EventHotKeyID hotKeyID = { .signature = kMASShortcutSignature, .id = ++ sCarbonHotKeyID };
- EventHotKeyRef carbonHotKey = NULL;
- if (RegisterEventHotKey(shortcut.carbonKeyCode, shortcut.carbonFlags, hotKeyID, GetEventDispatcherTarget(), kEventHotKeyExclusive, &carbonHotKey) != noErr) {
- carbonHotKey = NULL;
- }
-
- if (outCarbonHotKeyID) *outCarbonHotKeyID = hotKeyID.id;
- if (outCarbonHotKey) *outCarbonHotKey = carbonHotKey;
-}
-
-static OSStatus CarbonCallback(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
-{
- if (GetEventClass(inEvent) != kEventClassKeyboard) return noErr;
-
- EventHotKeyID hotKeyID;
- OSStatus status = GetEventParameter(inEvent, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(hotKeyID), NULL, &hotKeyID);
- if (status != noErr) return status;
-
- if (hotKeyID.signature != kMASShortcutSignature) return noErr;
-
- [MASRegisteredHotKeys() enumerateKeysAndObjectsUsingBlock:^(id key, MASShortcutHotKey *hotKey, BOOL *stop) {
- if (hotKeyID.id == hotKey.carbonHotKeyID) {
- if (hotKey.handler) {
- hotKey.handler();
- }
- *stop = YES;
- }
- }];
-
- return noErr;
-}
-
-#pragma mark -
-
-static EventHandlerRef sEventHandler = NULL;
-
-BOOL InstallCommonEventHandler()
-{
- if (sEventHandler == NULL) {
- EventTypeSpec hotKeyPressedSpec = { .eventClass = kEventClassKeyboard, .eventKind = kEventHotKeyPressed };
- OSStatus status = InstallEventHandler(GetEventDispatcherTarget(), CarbonCallback, 1, &hotKeyPressedSpec, NULL, &sEventHandler);
- if (status != noErr) {
- sEventHandler = NULL;
- return NO;
- }
- }
- return YES;
-}
-
-void UninstallEventHandler()
-{
- if (sEventHandler) {
- RemoveEventHandler(sEventHandler);
- sEventHandler = NULL;
- }
-}

0 comments on commit 4099b62

Please sign in to comment.
Something went wrong with that request. Please try again.