Skip to content

Commit bea1692

Browse files
committed
Merge feature to allow responding to keyUp events.
cocoabits#114
1 parent 3f8080d commit bea1692

File tree

6 files changed

+54
-11
lines changed

6 files changed

+54
-11
lines changed

Framework/Monitoring/MASHotKey.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ extern FourCharCode const MASHotKeySignature;
66

77
@property(readonly) UInt32 carbonID;
88
@property(copy) dispatch_block_t action;
9+
@property(copy) dispatch_block_t actionUp;
910

1011
+ (instancetype) registeredHotKeyWithShortcut: (MASShortcut*) shortcut;
1112

Framework/Monitoring/MASShortcutMonitor.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,21 @@
1212
- (instancetype) init __unavailable;
1313
+ (instancetype) sharedMonitor;
1414

15+
/**
16+
Register a shortcut along with an action.
17+
18+
Attempting to insert an already registered shortcut probably won’t work.
19+
It may burn your house or cut your fingers. You have been warned.
20+
*/
21+
- (BOOL) registerShortcut: (MASShortcut*) shortcut withAction: (dispatch_block_t) action;
22+
1523
/**
1624
Register a shortcut along with an action.
1725
1826
Attempting to insert an already registered shortcut probably won’t work.
1927
It may burn your house or cut your fingers. You have been warned.
2028
*/
21-
- (BOOL) registerShortcut: (MASShortcut*) shortcut withAction: (dispatch_block_t) action;
29+
- (BOOL) registerShortcut: (MASShortcut*) shortcut withAction: (dispatch_block_t) action onKeyUp: (dispatch_block_t) actionUp;
2230
- (BOOL) isShortcutRegistered: (MASShortcut*) shortcut;
2331

2432
- (void) unregisterShortcut: (MASShortcut*) shortcut;

Framework/Monitoring/MASShortcutMonitor.m

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,13 @@ - (instancetype) init
1616
{
1717
self = [super init];
1818
[self setHotKeys:[NSMutableDictionary dictionary]];
19-
EventTypeSpec hotKeyPressedSpec = { .eventClass = kEventClassKeyboard, .eventKind = kEventHotKeyPressed };
19+
EventTypeSpec eventTypeSpecs[2] = {
20+
{ .eventClass = kEventClassKeyboard, .eventKind = kEventHotKeyPressed },
21+
{ .eventClass = kEventClassKeyboard, .eventKind = kEventHotKeyReleased }
22+
};
2023
OSStatus status = InstallEventHandler(GetEventDispatcherTarget(), MASCarbonEventCallback,
21-
1, &hotKeyPressedSpec, (__bridge void*)self, &_eventHandlerRef);
24+
2, eventTypeSpecs,
25+
(__bridge void*)self, &_eventHandlerRef);
2226
if (status != noErr) {
2327
return nil;
2428
}
@@ -46,10 +50,16 @@ + (instancetype) sharedMonitor
4650
#pragma mark Registration
4751

4852
- (BOOL) registerShortcut: (MASShortcut*) shortcut withAction: (dispatch_block_t) action
53+
{
54+
return [self registerShortcut:shortcut withAction:action onKeyUp:nil];
55+
}
56+
57+
- (BOOL) registerShortcut: (MASShortcut*) shortcut withAction: (dispatch_block_t) action onKeyUp: (dispatch_block_t) actionUp
4958
{
5059
MASHotKey *hotKey = [MASHotKey registeredHotKeyWithShortcut:shortcut];
5160
if (hotKey) {
5261
[hotKey setAction:action];
62+
[hotKey setActionUp:actionUp];
5363
[_hotKeys setObject:hotKey forKey:shortcut];
5464
return YES;
5565
} else {
@@ -91,7 +101,10 @@ - (void) handleEvent: (EventRef) event
91101
[_hotKeys enumerateKeysAndObjectsUsingBlock:^(MASShortcut *shortcut, MASHotKey *hotKey, BOOL *stop) {
92102
if (hotKeyID.id == [hotKey carbonID]) {
93103
if ([hotKey action]) {
94-
dispatch_async(dispatch_get_main_queue(), [hotKey action]);
104+
dispatch_block_t action = (GetEventKind(event) == kEventHotKeyReleased) ? [hotKey actionUp] : [hotKey action];
105+
if (action) {
106+
dispatch_async(dispatch_get_main_queue(), action);
107+
}
95108
}
96109
*stop = YES;
97110
}

Framework/User Defaults Storage/MASShortcutBinder.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@
4747
*/
4848
- (void) bindShortcutWithDefaultsKey: (NSString*) defaultsKeyName toAction: (dispatch_block_t) action;
4949

50+
51+
/**
52+
Binds given actions to a shortcut stored under the given defaults key.
53+
54+
In other words, no matter what shortcut you store under the given key,
55+
pressing it will always trigger the given action.
56+
*/
57+
- (void) bindShortcutWithDefaultsKey: (NSString*) defaultsKeyName toAction: (dispatch_block_t) action onKeyUp: (dispatch_block_t) actionUp;
58+
5059
/**
5160
Disconnect the binding between user defaults and action.
5261

Framework/User Defaults Storage/MASShortcutBinder.m

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
@interface MASShortcutBinder ()
55
@property(strong) NSMutableDictionary *actions;
6+
@property(strong) NSMutableDictionary *actionsUp;
67
@property(strong) NSMutableDictionary *shortcuts;
78
@end
89

@@ -14,6 +15,7 @@ - (id) init
1415
{
1516
self = [super init];
1617
[self setActions:[NSMutableDictionary dictionary]];
18+
[self setActionsUp:[NSMutableDictionary dictionaryWithCapacity:0]];
1719
[self setShortcuts:[NSMutableDictionary dictionary]];
1820
[self setShortcutMonitor:[MASShortcutMonitor sharedMonitor]];
1921
[self setBindingOptions:@{NSValueTransformerNameBindingOption: NSKeyedUnarchiveFromDataTransformerName}];
@@ -40,23 +42,33 @@ + (instancetype) sharedBinder
4042
#pragma mark Registration
4143

4244
- (void) bindShortcutWithDefaultsKey: (NSString*) defaultsKeyName toAction: (dispatch_block_t) action
45+
{
46+
[self bindShortcutWithDefaultsKey:defaultsKeyName toAction:action onKeyUp:nil];
47+
}
48+
49+
- (void) bindShortcutWithDefaultsKey: (NSString*) defaultsKeyName toAction: (dispatch_block_t) action onKeyUp: (dispatch_block_t) actionUp
4350
{
4451
NSAssert([defaultsKeyName rangeOfString:@"."].location == NSNotFound,
45-
@"Illegal character in binding name (“.”), please see http://git.io/x5YS.");
52+
@"Illegal character in binding name (“.”), please see http://git.io/x5YS.");
4653
NSAssert([defaultsKeyName rangeOfString:@" "].location == NSNotFound,
47-
@"Illegal character in binding name (“ ”), please see http://git.io/x5YS.");
54+
@"Illegal character in binding name (“ ”), please see http://git.io/x5YS.");
4855
[_actions setObject:[action copy] forKey:defaultsKeyName];
56+
if (actionUp)
57+
[_actionsUp setObject:[actionUp copy] forKey:defaultsKeyName];
58+
else
59+
[_actionsUp removeObjectForKey:defaultsKeyName];
4960
[self bind:defaultsKeyName
50-
toObject:[NSUserDefaultsController sharedUserDefaultsController]
51-
withKeyPath:[@"values." stringByAppendingString:defaultsKeyName]
52-
options:_bindingOptions];
61+
toObject:[NSUserDefaultsController sharedUserDefaultsController]
62+
withKeyPath:[@"values." stringByAppendingString:defaultsKeyName]
63+
options:_bindingOptions];
5364
}
5465

5566
- (void) breakBindingWithDefaultsKey: (NSString*) defaultsKeyName
5667
{
5768
[_shortcutMonitor unregisterShortcut:[_shortcuts objectForKey:defaultsKeyName]];
5869
[_shortcuts removeObjectForKey:defaultsKeyName];
5970
[_actions removeObjectForKey:defaultsKeyName];
71+
[_actionsUp removeObjectForKey:defaultsKeyName];
6072
[self unbind:defaultsKeyName];
6173
}
6274

@@ -115,7 +127,7 @@ - (void) setValue: (id) value forUndefinedKey: (NSString*) key
115127

116128
// Bind new shortcut
117129
[_shortcuts setObject:newShortcut forKey:key];
118-
[_shortcutMonitor registerShortcut:newShortcut withAction:[_actions objectForKey:key]];
130+
[_shortcutMonitor registerShortcut:newShortcut withAction:[_actions objectForKey:key] onKeyUp:[_actionsUp objectForKey:key]];
119131
}
120132

121133
@end

MASShortcut.xcodeproj/xcshareddata/xcschemes/MASShortcut.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
</AdditionalOptions>
6767
</TestAction>
6868
<LaunchAction
69-
buildConfiguration = "Debug"
69+
buildConfiguration = "Release"
7070
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
7171
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
7272
launchStyle = "0"

0 commit comments

Comments
 (0)