summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave DeLong2012-12-25 10:16:27 -0800
committerDave DeLong2012-12-25 10:16:27 -0800
commit4ed465f39afdd215a21e2c7b651c4599dccd693a (patch)
tree5f7e46fff0ac2636288edd61c62c0ef559f0d0f0
parent8c2ee2148e6f35674b0b0c7701f0ae306ec230d5 (diff)
downloadDDHotKey-4ed465f39afdd215a21e2c7b651c4599dccd693a.tar.bz2
Updates
Made DDHotKeyCenter a true singleton, updated for ARC
-rw-r--r--DDHotKey.xcodeproj/project.pbxproj18
-rw-r--r--DDHotKey.xcodeproj/project.xcworkspace/contents.xcworkspacedata7
-rw-r--r--DDHotKeyCenter.h39
-rw-r--r--DDHotKeyCenter.m480
-rw-r--r--README.markdown69
5 files changed, 308 insertions, 305 deletions
diff --git a/DDHotKey.xcodeproj/project.pbxproj b/DDHotKey.xcodeproj/project.pbxproj
index 2b47832..05bc2cd 100644
--- a/DDHotKey.xcodeproj/project.pbxproj
+++ b/DDHotKey.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 45;
+ objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
@@ -151,8 +151,11 @@
/* Begin PBXProject section */
29B97313FDCFA39411CA2CEA /* Project object */ = {
isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0450;
+ };
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "DDHotKey" */;
- compatibilityVersion = "Xcode 3.1";
+ compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
@@ -219,9 +222,9 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
- GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
@@ -236,6 +239,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ COMBINE_HIDPI_IMAGES = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_MODEL_TUNING = G5;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
@@ -249,13 +253,13 @@
C01FCF4F08A954540054247B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ ARCHS = "$(ARCHS_STANDARD_64_BIT)";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
ONLY_ACTIVE_ARCH = YES;
- PREBINDING = NO;
SDKROOT = macosx;
};
name = Debug;
@@ -263,11 +267,11 @@
C01FCF5008A954540054247B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ ARCHS = "$(ARCHS_STANDARD_64_BIT)";
GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- PREBINDING = NO;
SDKROOT = macosx;
};
name = Release;
diff --git a/DDHotKey.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/DDHotKey.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..2bd2ea5
--- /dev/null
+++ b/DDHotKey.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "self:DDHotKey.xcodeproj">
+ </FileRef>
+</Workspace>
diff --git a/DDHotKeyCenter.h b/DDHotKeyCenter.h
index 6274b36..58dc9d2 100644
--- a/DDHotKeyCenter.h
+++ b/DDHotKeyCenter.h
@@ -1,7 +1,7 @@
/*
DDHotKey -- DDHotKeyCenter.h
- Copyright (c) 2010, Dave DeLong <http://www.davedelong.com>
+ Copyright (c) 2012, Dave DeLong <http://www.davedelong.com>
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
@@ -10,19 +10,15 @@
#import <Cocoa/Cocoa.h>
-#if NS_BLOCKS_AVAILABLE
//a convenient typedef for the required signature of a hotkey block callback
typedef void (^DDHotKeyTask)(NSEvent*);
-#endif
@interface DDHotKey : NSObject
-@property (nonatomic, readonly, retain) id target;
+@property (nonatomic, readonly) id target;
@property (nonatomic, readonly) SEL action;
-@property (nonatomic, readonly, retain) id object;
-#if NS_BLOCKS_AVAILABLE
-@property (nonatomic, readonly, copy) DDHotKeyTask task;
-#endif
+@property (nonatomic, readonly) id object;
+@property (nonatomic, readonly) DDHotKeyTask task;
@property (nonatomic, readonly) unsigned short keyCode;
@property (nonatomic, readonly) NSUInteger modifierFlags;
@@ -31,56 +27,59 @@ typedef void (^DDHotKeyTask)(NSEvent*);
#pragma mark -
-@interface DDHotKeyCenter : NSObject {
+@interface DDHotKeyCenter : NSObject
-}
++ (id)sharedHotKeyCenter;
/**
Register a target/action hotkey.
The modifierFlags must be a bitwise OR of NSCommandKeyMask, NSAlternateKeyMask, NSControlKeyMask, or NSShiftKeyMask;
Returns YES if the hotkey was registered; NO otherwise.
*/
-- (BOOL) registerHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags target:(id)target action:(SEL)action object:(id)object;
+- (BOOL)registerHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags target:(id)target action:(SEL)action object:(id)object;
-#if NS_BLOCKS_AVAILABLE
/**
Register a block callback hotkey.
The modifierFlags must be a bitwise OR of NSCommandKeyMask, NSAlternateKeyMask, NSControlKeyMask, or NSShiftKeyMask;
Returns YES if the hotkey was registered; NO otherwise.
*/
-- (BOOL) registerHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags task:(DDHotKeyTask)task;
-#endif
+- (BOOL)registerHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags task:(DDHotKeyTask)task;
/**
See if a hotkey exists with the specified keycode and modifier flags.
NOTE: this will only check among hotkeys you have explicitly registered with DDHotKeyCenter. This does not check all globally registered hotkeys.
*/
-- (BOOL) hasRegisteredHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags;
+- (BOOL)hasRegisteredHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags;
/**
Unregister a specific hotkey
*/
-- (void) unregisterHotKey:(DDHotKey *)hotKey;
+- (void)unregisterHotKey:(DDHotKey *)hotKey;
+
+/**
+ Unregister all hotkeys
+ */
+- (void)unregisterAllHotKeys;
/**
Unregister all hotkeys with a specific target
*/
-- (void) unregisterHotKeysWithTarget:(id)target;
+- (void)unregisterHotKeysWithTarget:(id)target;
/**
Unregister all hotkeys with a specific target and action
*/
-- (void) unregisterHotKeysWithTarget:(id)target action:(SEL)action;
+- (void)unregisterHotKeysWithTarget:(id)target action:(SEL)action;
/**
Unregister a hotkey with a specific keycode and modifier flags
*/
-- (void) unregisterHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags;
+- (void)unregisterHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags;
/**
Returns a set of currently registered hotkeys
**/
-- (NSSet *) registeredHotKeys;
+- (NSSet *)registeredHotKeys;
@end
diff --git a/DDHotKeyCenter.m b/DDHotKeyCenter.m
index 465baac..a5ae678 100644
--- a/DDHotKeyCenter.m
+++ b/DDHotKeyCenter.m
@@ -1,7 +1,7 @@
/*
DDHotKey -- DDHotKeyCenter.m
- Copyright (c) 2010, Dave DeLong <http://www.davedelong.com>
+ Copyright (c) 2012, Dave DeLong <http://www.davedelong.com>
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
@@ -12,302 +12,310 @@
#import <Carbon/Carbon.h>
#import <objc/runtime.h>
+#if __has_feature(objc_arc)
+
+#define DDHK_HAS_ARC 1
+#define DDHK_RETAIN(_o) (_o)
+#define DDHK_RELEASE(_o)
+#define DDHK_AUTORELEASE(_o) (_o)
+
+#else
+
+#define DDHK_HAS_ARC 0
+#define DDHK_RETAIN(_o) [(_o) retain]
+#define DDHK_RELEASE(_o) [(_o) release]
+#define DDHK_AUTORELEASE(_o) [(_o) autorelease]
+
+#endif
+
#pragma mark Private Global Declarations
-static NSMutableSet * _registeredHotKeys = nil;
-static UInt32 _nextHotKeyID = 1;
-OSStatus dd_hotKeyHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void * userData);
+OSStatus dd_hotKeyHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData);
UInt32 dd_translateModifierFlags(NSUInteger flags);
-NSString* dd_stringifyModifierFlags(NSUInteger flags);
#pragma mark DDHotKey
-@implementation DDHotKey
+@interface DDHotKey ()
-- (id) target { return nil; }
-- (SEL) action { return nil; }
-- (id) object { return nil; }
-- (unsigned short) keyCode { return 0; }
-- (NSUInteger) modifierFlags { return 0; }
+@property (nonatomic, retain) NSValue *hotKeyRef;
+@property (nonatomic) UInt32 hotKeyID;
-#if NS_BLOCKS_AVAILABLE
-- (DDHotKeyTask) task { return nil; }
-#endif
+@end
-- (NSUInteger) hash {
- return [self keyCode] + [self modifierFlags];
+@implementation DDHotKey {
+ id _target;
+ SEL _action;
+ id _object;
+
+ unsigned short _keyCode;
+ NSUInteger _modifierFlags;
+ DDHotKeyTask _task;
}
-- (BOOL) isEqual:(id)object {
- BOOL equal = NO;
- if ([object isKindOfClass:[DDHotKey class]]) {
- equal = ([object keyCode] == [self keyCode]);
- equal &= ([object modifierFlags] == [self modifierFlags]);
- }
- return equal;
+- (void) dealloc {
+ [[DDHotKeyCenter sharedHotKeyCenter] unregisterHotKey:self];
+#if !DDHK_HAS_ARC
+ DDHK_RELEASE(_target); _target = nil;
+ DDHK_RELEASE(_object); _object = nil;
+ DDHK_RELEASE(_hotKeyRef); _hotKeyRef = nil;
+ DDHK_RELEASE(_task); _task = nil;
+ [super dealloc];
+#endif
}
-- (NSString *) description {
- NSString * flags = dd_stringifyModifierFlags([self modifierFlags]);
- NSString * invokes = @"(block)";
- if ([self target] != nil && [self action] != nil) {
- invokes = [NSString stringWithFormat:@"[%@ %@]", [self target], NSStringFromSelector([self action])];
- }
- return [NSString stringWithFormat:@"%@\n\t(key: %hu\n\tflags: %@\n\tinvokes: %@)", [super description], [self keyCode], flags, invokes];
+- (void)_setTarget:(id)target {
+ if (target != _target) {
+ DDHK_RELEASE(_target);
+ _target = DDHK_RETAIN(target);
+ }
}
-@end
-
-@interface _DDHotKey : DDHotKey {
- @private
- id target;
- SEL action;
- id object;
-
-#if NS_BLOCKS_AVAILABLE
- DDHotKeyTask task;
-#endif
-
- unsigned short keyCode;
- NSUInteger modifierFlags;
- UInt32 hotKeyID;
- NSValue * hotKeyRef;
+- (void)_setAction:(SEL)action {
+ _action = action;
}
-@property (nonatomic, retain) id target;
-@property (nonatomic) SEL action;
-@property (nonatomic, retain) id object;
-@property (nonatomic) unsigned short keyCode;
-@property (nonatomic) NSUInteger modifierFlags;
-@property (nonatomic) UInt32 hotKeyID;
-@property (nonatomic, retain) NSValue * hotKeyRef;
+- (void)_setObject:(id)object {
+ if (object != _object) {
+ DDHK_RELEASE(_object);
+ _object = DDHK_RETAIN(object);
+ }
+}
-#if NS_BLOCKS_AVAILABLE
-@property (nonatomic, copy) DDHotKeyTask task;
-#endif
+- (void)_setKeyCode:(unsigned short)keyCode {
+ _keyCode = keyCode;
+}
-- (void) invokeWithEvent:(NSEvent *)event;
-- (BOOL) registerHotKey;
-- (void) unregisterHotKey;
+- (void)_setModifierFlags:(NSUInteger)modifierFlags {
+ _modifierFlags = modifierFlags;
+}
-@end
+- (void)_setTask:(DDHotKeyTask)task {
+ DDHK_RELEASE(_task);
+ _task = [task copy];
+}
-@implementation _DDHotKey
+- (NSUInteger)hash {
+ return [self keyCode] ^ [self modifierFlags];
+}
-@synthesize target, action, object, keyCode, modifierFlags, hotKeyID, hotKeyRef;
-#if NS_BLOCKS_AVAILABLE
-@synthesize task;
-#endif
+- (BOOL)isEqual:(id)object {
+ BOOL equal = NO;
+ if ([object isKindOfClass:[DDHotKey class]]) {
+ equal = ([object keyCode] == [self keyCode]);
+ equal &= ([object modifierFlags] == [self modifierFlags]);
+ }
+ return equal;
+}
-- (Class) class { return [DDHotKey class]; }
+- (NSString *)description {
+ NSMutableArray *bits = [NSMutableArray array];
+ if ((_modifierFlags & NSControlKeyMask) > 0) { [bits addObject:@"NSControlKeyMask"]; }
+ if ((_modifierFlags & NSCommandKeyMask) > 0) { [bits addObject:@"NSCommandKeyMask"]; }
+ if ((_modifierFlags & NSShiftKeyMask) > 0) { [bits addObject:@"NSShiftKeyMask"]; }
+ if ((_modifierFlags & NSAlternateKeyMask) > 0) { [bits addObject:@"NSAlternateKeyMask"]; }
+
+ NSString *flags = [NSString stringWithFormat:@"(%@)", [bits componentsJoinedByString:@" | "]];
+ NSString *invokes = @"(block)";
+ if ([self target] != nil && [self action] != nil) {
+ invokes = [NSString stringWithFormat:@"[%@ %@]", [self target], NSStringFromSelector([self action])];
+ }
+ return [NSString stringWithFormat:@"%@\n\t(key: %hu\n\tflags: %@\n\tinvokes: %@)", [super description], [self keyCode], flags, invokes];
+}
-- (void) invokeWithEvent:(NSEvent *)event {
- if (target != nil && action != nil && [target respondsToSelector:action]) {
- [target performSelector:action withObject:event withObject:object];
- }
-#if NS_BLOCKS_AVAILABLE
- else if (task != nil) {
- task(event);
- }
-#endif
+- (void)invokeWithEvent:(NSEvent *)event {
+ if (_target != nil && _action != nil && [_target respondsToSelector:_action]) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+ [_target performSelector:_action withObject:event withObject:_object];
+#pragma clang diagnostic pop
+ } else if (_task != nil) {
+ _task(event);
+ }
}
-- (NSString *) actionString {
- return NSStringFromSelector(action);
+- (NSString *)actionString {
+ return NSStringFromSelector(_action);
}
-- (BOOL) registerHotKey {
- EventHotKeyID keyID;
- keyID.signature = 'htk1';
- keyID.id = _nextHotKeyID;
-
- EventHotKeyRef carbonHotKey;
- UInt32 flags = dd_translateModifierFlags(modifierFlags);
- OSStatus err = RegisterEventHotKey(keyCode, flags, keyID, GetEventDispatcherTarget(), 0, &carbonHotKey);
-
- //error registering hot key
- if (err != 0) { return NO; }
-
- NSValue * refValue = [NSValue valueWithPointer:carbonHotKey];
- [self setHotKeyRef:refValue];
- [self setHotKeyID:_nextHotKeyID];
-
- _nextHotKeyID++;
-
- return YES;
+@end
+
+#pragma mark DDHotKeyCenter
+
+static DDHotKeyCenter *center = nil;
+
+@implementation DDHotKeyCenter {
+ NSMutableSet *_registeredHotKeys;
+ UInt32 _nextHotKeyID;
}
-- (void) unregisterHotKey {
- EventHotKeyRef carbonHotKey = (EventHotKeyRef)[hotKeyRef pointerValue];
- UnregisterEventHotKey(carbonHotKey);
- [self setHotKeyRef:nil];
++ (id)sharedHotKeyCenter {
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ center = [[DDHotKeyCenter alloc] _init];
+ });
+ return center;
}
-- (void) dealloc {
- [target release], target = nil;
- [object release], object = nil;
- if (hotKeyRef != nil) {
- [self unregisterHotKey];
- [hotKeyRef release], hotKeyRef = nil;
- }
- [super dealloc];
++ (id)allocWithZone:(NSZone *)zone {
+ if (center == nil) {
+ return [super allocWithZone:zone];
+ }
+ return DDHK_RETAIN(center);
}
-@end
+- (id)_init {
+ self = [super init];
+ if (self) {
+ _registeredHotKeys = [[NSMutableSet alloc] init];
+ _nextHotKeyID = 1;
+ }
+ return self;
+}
-#pragma mark DDHotKeyCenter
+- (NSSet *)hotKeysMatchingPredicate:(NSPredicate *)predicate {
+ return [_registeredHotKeys filteredSetUsingPredicate:predicate];
+}
-@implementation DDHotKeyCenter
-
-+ (void) initialize {
- if (self == [DDHotKeyCenter class] && _registeredHotKeys == nil) {
- _registeredHotKeys = [[NSMutableSet alloc] init];
- _nextHotKeyID = 1;
- EventTypeSpec eventSpec;
- eventSpec.eventClass = kEventClassKeyboard;
- eventSpec.eventKind = kEventHotKeyReleased;
- InstallApplicationEventHandler(&dd_hotKeyHandler, 1, &eventSpec, NULL, NULL);
- }
+- (BOOL)hasRegisteredHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"keyCode = %hu AND modifierFlags = %lu", keyCode, flags];
+ return ([[self hotKeysMatchingPredicate:predicate] count] > 0);
}
-- (NSSet *) hotKeysMatchingPredicate:(NSPredicate *)predicate {
- return [_registeredHotKeys filteredSetUsingPredicate:predicate];
+- (BOOL)_registerHotKey:(DDHotKey *)hotKey {
+ BOOL success = NO;
+
+ EventHotKeyID keyID;
+ keyID.signature = 'htk1';
+ keyID.id = _nextHotKeyID;
+
+ EventHotKeyRef carbonHotKey;
+ UInt32 flags = dd_translateModifierFlags([hotKey modifierFlags]);
+ OSStatus err = RegisterEventHotKey([hotKey keyCode], flags, keyID, GetEventDispatcherTarget(), 0, &carbonHotKey);
+
+ //error registering hot key
+ if (err != 0) { return NO; }
+
+ NSValue *refValue = [NSValue valueWithPointer:carbonHotKey];
+ [hotKey setHotKeyRef:refValue];
+ [hotKey setHotKeyID:_nextHotKeyID];
+
+ _nextHotKeyID++;
+ [_registeredHotKeys addObject:hotKey];
+
+ return success;
}
-- (BOOL) hasRegisteredHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags {
- NSPredicate * predicate = [NSPredicate predicateWithFormat:@"keyCode = %hu AND modifierFlags = %lu", keyCode, flags];
- return ([[self hotKeysMatchingPredicate:predicate] count] > 0);
+- (void)unregisterHotKey:(DDHotKey *)hotKey {
+ NSValue *hotKeyRef = [hotKey hotKeyRef];
+ if (hotKeyRef) {
+ EventHotKeyRef carbonHotKey = (EventHotKeyRef)[hotKeyRef pointerValue];
+ UnregisterEventHotKey(carbonHotKey);
+ [hotKey setHotKeyRef:nil];
+
+ [_registeredHotKeys removeObject:hotKey];
+ }
}
-#if NS_BLOCKS_AVAILABLE
-- (BOOL) registerHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags task:(DDHotKeyTask)task {
- //we can't add a new hotkey if something already has this combo
- if ([self hasRegisteredHotKeyWithKeyCode:keyCode modifierFlags:flags]) { return NO; }
-
- _DDHotKey * newHotKey = [[_DDHotKey alloc] init];
- [newHotKey setTask:task];
- [newHotKey setKeyCode:keyCode];
- [newHotKey setModifierFlags:flags];
-
- BOOL success = [newHotKey registerHotKey];
- if (success) {
- [_registeredHotKeys addObject:newHotKey];
- }
-
- [newHotKey release];
- return success;
+- (BOOL)registerHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags task:(DDHotKeyTask)task {
+ //we can't add a new hotkey if something already has this combo
+ if ([self hasRegisteredHotKeyWithKeyCode:keyCode modifierFlags:flags]) { return NO; }
+
+ DDHotKey *newHotKey = DDHK_AUTORELEASE([[DDHotKey alloc] init]);
+ [newHotKey _setTask:task];
+ [newHotKey _setKeyCode:keyCode];
+ [newHotKey _setModifierFlags:flags];
+
+ return [self _registerHotKey:newHotKey];
}
-#endif
-- (BOOL) registerHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags target:(id)target action:(SEL)action object:(id)object {
- //we can't add a new hotkey if something already has this combo
- if ([self hasRegisteredHotKeyWithKeyCode:keyCode modifierFlags:flags]) { return NO; }
-
- //build the hotkey object:
- _DDHotKey * newHotKey = [[_DDHotKey alloc] init];
- [newHotKey setTarget:target];
- [newHotKey setAction:action];
- [newHotKey setObject:object];
- [newHotKey setKeyCode:keyCode];
- [newHotKey setModifierFlags:flags];
-
- BOOL success = [newHotKey registerHotKey];
- if (success) {
- [_registeredHotKeys addObject:newHotKey];
- }
-
- [newHotKey release];
- return success;
+- (BOOL)registerHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags target:(id)target action:(SEL)action object:(id)object {
+ //we can't add a new hotkey if something already has this combo
+ if ([self hasRegisteredHotKeyWithKeyCode:keyCode modifierFlags:flags]) { return NO; }
+
+ //build the hotkey object:
+ DDHotKey *newHotKey = DDHK_AUTORELEASE([[DDHotKey alloc] init]);
+ [newHotKey _setTarget:target];
+ [newHotKey _setAction:action];
+ [newHotKey _setObject:object];
+ [newHotKey _setKeyCode:keyCode];
+ [newHotKey _setModifierFlags:flags];
+ return [self _registerHotKey:newHotKey];
}
-- (void) unregisterHotKeysMatchingPredicate:(NSPredicate *)predicate {
- //explicitly unregister the hotkey, since relying on the unregistration in -dealloc can be problematic
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- NSSet * matches = [self hotKeysMatchingPredicate:predicate];
- [_registeredHotKeys minusSet:matches];
- [matches makeObjectsPerformSelector:@selector(unregisterHotKey)];
- [pool release];
+- (void)unregisterHotKeysMatchingPredicate:(NSPredicate *)predicate {
+ //explicitly unregister the hotkey, since relying on the unregistration in -dealloc can be problematic
+ @autoreleasepool {
+ NSSet *matches = [self hotKeysMatchingPredicate:predicate];
+ for (DDHotKey *hotKey in matches) {
+ [self unregisterHotKey:hotKey];
+ }
+ }
}
-- (void) unregisterHotKey:(DDHotKey *)hotKey {
- if (object_getClass(hotKey) == [_DDHotKey class]) {
- _DDHotKey * key = (_DDHotKey *)hotKey;
- [_registeredHotKeys removeObject:key];
- [key unregisterHotKey];
- } else {
- [NSException raise:NSInvalidArgumentException format:@"Invalid hotkey"];
- }
+- (void)unregisterHotKeysWithTarget:(id)target {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"target = %@", target];
+ [self unregisterHotKeysMatchingPredicate:predicate];
}
-- (void) unregisterHotKeysWithTarget:(id)target {
- NSPredicate * predicate = [NSPredicate predicateWithFormat:@"target = %@", target];
- [self unregisterHotKeysMatchingPredicate:predicate];
+- (void)unregisterHotKeysWithTarget:(id)target action:(SEL)action {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"target = %@ AND actionString = %@", target, NSStringFromSelector(action)];
+ [self unregisterHotKeysMatchingPredicate:predicate];
}
-- (void) unregisterHotKeysWithTarget:(id)target action:(SEL)action {
- NSPredicate * predicate = [NSPredicate predicateWithFormat:@"target = %@ AND actionString = %@", target, NSStringFromSelector(action)];
- [self unregisterHotKeysMatchingPredicate:predicate];
+- (void)unregisterHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"keyCode = %hu AND modifierFlags = %lu", keyCode, flags];
+ [self unregisterHotKeysMatchingPredicate:predicate];
}
-- (void) unregisterHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags {
- NSPredicate * predicate = [NSPredicate predicateWithFormat:@"keyCode = %hu AND modifierFlags = %lu", keyCode, flags];
- [self unregisterHotKeysMatchingPredicate:predicate];
+- (void)unregisterAllHotKeys {
+ NSSet *keys = [_registeredHotKeys copy];
+ for (DDHotKey *key in keys) {
+ [self unregisterHotKey:key];
+ }
+ DDHK_RELEASE(keys);
}
-- (NSSet *) registeredHotKeys {
- return [self hotKeysMatchingPredicate:[NSPredicate predicateWithFormat:@"hotKeyRef != NULL"]];
+- (NSSet *)registeredHotKeys {
+ return [self hotKeysMatchingPredicate:[NSPredicate predicateWithFormat:@"hotKeyRef != NULL"]];
}
@end
-OSStatus dd_hotKeyHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void * userData) {
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
-
- EventHotKeyID hotKeyID;
- GetEventParameter(theEvent, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(hotKeyID),NULL,&hotKeyID);
-
- UInt32 keyID = hotKeyID.id;
-
- NSSet * matchingHotKeys = [_registeredHotKeys filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"hotKeyID = %u", keyID]];
- if ([matchingHotKeys count] > 1) { NSLog(@"ERROR!"); }
- _DDHotKey * matchingHotKey = [matchingHotKeys anyObject];
-
- NSEvent * event = [NSEvent eventWithEventRef:theEvent];
- NSEvent * keyEvent = [NSEvent keyEventWithType:NSKeyUp
- location:[event locationInWindow]
- modifierFlags:[event modifierFlags]
- timestamp:[event timestamp]
- windowNumber:-1
- context:nil
- characters:@""
- charactersIgnoringModifiers:@""
- isARepeat:NO
- keyCode:[matchingHotKey keyCode]];
-
- [matchingHotKey invokeWithEvent:keyEvent];
-
- [pool release];
-
- return noErr;
+OSStatus dd_hotKeyHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData) {
+ @autoreleasepool {
+ EventHotKeyID hotKeyID;
+ GetEventParameter(theEvent, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(hotKeyID),NULL,&hotKeyID);
+
+ UInt32 keyID = hotKeyID.id;
+
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"hotKeyID = %u", keyID];
+ NSSet *matchingHotKeys = [[DDHotKeyCenter sharedHotKeyCenter] hotKeysMatchingPredicate:predicate];
+ if ([matchingHotKeys count] > 1) { NSLog(@"ERROR!"); }
+ DDHotKey *matchingHotKey = [matchingHotKeys anyObject];
+
+ NSEvent *event = [NSEvent eventWithEventRef:theEvent];
+ NSEvent *keyEvent = [NSEvent keyEventWithType:NSKeyUp
+ location:[event locationInWindow]
+ modifierFlags:[event modifierFlags]
+ timestamp:[event timestamp]
+ windowNumber:-1
+ context:nil
+ characters:@""
+ charactersIgnoringModifiers:@""
+ isARepeat:NO
+ keyCode:[matchingHotKey keyCode]];
+
+ [matchingHotKey invokeWithEvent:keyEvent];
+ }
+
+ return noErr;
}
UInt32 dd_translateModifierFlags(NSUInteger flags) {
- UInt32 newFlags = 0;
- if ((flags & NSControlKeyMask) > 0) { newFlags |= controlKey; }
- if ((flags & NSCommandKeyMask) > 0) { newFlags |= cmdKey; }
- if ((flags & NSShiftKeyMask) > 0) { newFlags |= shiftKey; }
- if ((flags & NSAlternateKeyMask) > 0) { newFlags |= optionKey; }
- return newFlags;
-}
-
-NSString* dd_stringifyModifierFlags(NSUInteger flags) {
- NSMutableArray * bits = [NSMutableArray array];
- if ((flags & NSControlKeyMask) > 0) { [bits addObject:@"NSControlKeyMask"]; }
- if ((flags & NSCommandKeyMask) > 0) { [bits addObject:@"NSCommandKeyMask"]; }
- if ((flags & NSShiftKeyMask) > 0) { [bits addObject:@"NSShiftKeyMask"]; }
- if ((flags & NSAlternateKeyMask) > 0) { [bits addObject:@"NSAlternateKeyMask"]; }
- if ([bits count] > 0) {
- return [NSString stringWithFormat:@"(%@)", [bits componentsJoinedByString:@" | "]];
- }
- return @"ERROR: No valid flags";
+ UInt32 newFlags = 0;
+ if ((flags & NSControlKeyMask) > 0) { newFlags |= controlKey; }
+ if ((flags & NSCommandKeyMask) > 0) { newFlags |= cmdKey; }
+ if ((flags & NSShiftKeyMask) > 0) { newFlags |= shiftKey; }
+ if ((flags & NSAlternateKeyMask) > 0) { newFlags |= optionKey; }
+ return newFlags;
}
diff --git a/README.markdown b/README.markdown
index c0c90eb..767885f 100644
--- a/README.markdown
+++ b/README.markdown
@@ -1,38 +1,26 @@
-DDHotKey
-Copyright (c) 2010, Dave DeLong <http://www.davedelong.com>
-
-##About
-DDHotKey is an easy-to-use Cocoa class for registering an application to respond to system key
-events, or "hotkeys".
-
-A global hotkey is a key combination that always executes a specific action, regardless of
-which app is frontmost. For example, the Mac OS X default hotkey of "command-space" shows the
-Spotlight search bar, even if Finder is not the frontmost application.
-
-##License
-The license for this framework is included in every source file, and is repoduced in its entirety
-here:
-
-Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee
-is hereby granted, provided that the above copyright notice and this permission notice appear in all
-copies. The software is provided "as is", without warranty of any kind, including all implied
-warranties of merchantability and fitness. In no event shall the authors or copyright holders be
-liable for any claim, damages, or other liability, whether in an action of contract, tort, or
-otherwise, arising from, out of, or in connection with the software or the use or other dealings
-in the software.
-
-##How to use
-First, your application will need to link against `Carbon.framework`.
-
-When you wish to create a hotkey, you'll need to do so via a `DDHotKeyCenter` object. You may
-alloc/init and release a `DDHotKeyCenter` object at anytime; it is merely an accessor to a static
-`NSSet`, which holds the hotkeys in global memory.
-
-You can register a hotkey in one of two ways: via a target/action mechanism, or with a block. The
-target/action mechanism can take a single extra "object" parameter, which it will pass into the
-action when the hotkey is fired. Both the `target` and the `object` parameters are retained by the
-`DDHotKeyCenter`. In addition, an `NSEvent` object is passed, which contains information regarding
-the hotkey event (such as the location, the keyCode, the modifierFlags, etc).
+# DDHotKey
+
+Copyright &copy; 2012, Dave DeLong <http://www.davedelong.com>
+
+## About
+
+DDHotKey is an easy-to-use Cocoa class for registering an application to respond to system key events, or "hotkeys".
+
+A global hotkey is a key combination that always executes a specific action, regardless of which app is frontmost. For example, the Mac OS X default hotkey of "command-space" shows the Spotlight search bar, even if Finder is not the frontmost application.
+
+## License
+
+The license for this framework is included in every source file, and is repoduced in its entirety here:
+
+Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. The software is provided "as is", without warranty of any kind, including all implied warranties of merchantability and fitness. In no event shall the authors or copyright holders be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the software or the use or other dealings in the software.
+
+## How to use
+
+Your application will need to link against `Carbon.framework`, and you will need to compile your application with the Clang compiler.
+
+When you wish to create a hotkey, you'll need to do so via the `DDHotKeyCenter` singleton.
+
+You can register a hotkey in one of two ways: via a target/action mechanism, or with a block. The target/action mechanism can take a single extra "object" parameter, which it will pass into the action when the hotkey is fired. Both the `target` and the `object` parameters are retained by the `DDHotKeyCenter`. In addition, an `NSEvent` object is passed, which contains information regarding the hotkey event (such as the location, the keyCode, the modifierFlags, etc).
Hotkey actions must have one of two method signatures (the actual selector is irrelevant):
@@ -44,13 +32,10 @@ Hotkey actions must have one of two method signatures (the actual selector is ir
//a method with an NSEvent parameter and an object parameter
- (void) hotkeyAction:(NSEvent*)hotKeyEvent withObject:(id)anObject;
-The other way to register a hotkey is with a block callback. The block must have the following
-signature:
+The other way to register a hotkey is with a block callback. The block must have the following signature:
-`void (^)(NSEvent *);`
+ void (^)(NSEvent *);
-`DDHotKeyCenter.h` contains a typedef statement to typedef this signature as a `DDHotKeyTask`, for
-convenience.
+`DDHotKeyCenter.h` contains a typedef statement to typedef this signature as a `DDHotKeyTask`, for convenience.
-Finally, you can unregister a hotkey based on its target, its target and action, or its keycode and
-modifier flags. \ No newline at end of file
+Finally, you can unregister a hotkey based on its target, its target and action, or its keycode and modifier flags. \ No newline at end of file