From 8e6d020a3f213c5ffe3316471bcbd69e411b8065 Mon Sep 17 00:00:00 2001 From: Raphael Schweikert Date: Wed, 20 Feb 2013 16:14:06 +0100 Subject: [PATCH 1/3] Add modifiers for keys in modal mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A key bound like key:modal;modifier Behaves the way it always has: the modifier is applied to the key that enters modal mode. A key bound like key:modifier;modal Now behaves as follows: the modifier has to be pressed with the key that triggers the action while in modal mode. Of course, the two can also be combined: key:modifier1;modal;modifier2 behaves as you’d expect: modal mode is activated when `modal` is pressed along with `modifier2` and the command is executed if `key` is pressed along with `modifier1` while in modal mode. combinations followed by `:toggle` also work --- Slate/Binding.h | 2 ++ Slate/Binding.m | 16 ++++++++++++---- Slate/SlateAppDelegate.m | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Slate/Binding.h b/Slate/Binding.h index b51fe4cc..9e4cd8cd 100644 --- a/Slate/Binding.h +++ b/Slate/Binding.h @@ -29,6 +29,7 @@ UInt32 keyCode; UInt32 modifiers; NSNumber *modalKey; + UInt32 modalModifiers; EventHotKeyRef hotKeyRef; BOOL repeat; BOOL toggle; @@ -38,6 +39,7 @@ @property (assign) UInt32 keyCode; @property (assign) UInt32 modifiers; @property NSNumber *modalKey; +@property (assign) UInt32 modalModifiers; @property (assign) EventHotKeyRef hotKeyRef; @property (assign) BOOL repeat; @property (assign) BOOL toggle; diff --git a/Slate/Binding.m b/Slate/Binding.m index b8442fc6..18c33a66 100644 --- a/Slate/Binding.m +++ b/Slate/Binding.m @@ -34,6 +34,7 @@ @implementation Binding @synthesize keyCode; @synthesize modifiers; @synthesize modalKey; +@synthesize modalModifiers; @synthesize hotKeyRef; @synthesize repeat; @synthesize toggle; @@ -113,6 +114,7 @@ + (UInt32)modifierFromString:(NSString *)mod { + (NSArray *)getKeystrokeFromString:(NSString *)keystroke { NSNumber *theKeyCode = [NSNumber numberWithUnsignedInt:0]; UInt32 theModifiers = 0; + UInt32 theModalModifiers = 0; NSNumber *theModalKey = nil; NSArray *keyAndModifiers = [keystroke componentsSeparatedByString:COLON]; if ([keyAndModifiers count] >= 1) { @@ -132,7 +134,12 @@ + (NSArray *)getKeystrokeFromString:(NSString *)keystroke { while (mod) { NSNumber *_theModalKey = [[Binding asciiToCodeDict] objectForKey:mod]; if (_theModalKey != nil) { - theModalKey = _theModalKey; + if(theModalKey == nil) { + theModalKey = _theModalKey; + } + } else if(theModalKey != nil) { + //Assume every modifier defined after a modal key to be a modifier for the modal key (to be pressed when entering modal mode) as opposed to the actual key + theModalModifiers = [Binding modifierFromString:mod]; } else { theModifiers += [Binding modifierFromString:mod]; } @@ -141,7 +148,7 @@ + (NSArray *)getKeystrokeFromString:(NSString *)keystroke { } } } - return [NSArray arrayWithObjects:theKeyCode, [NSNumber numberWithInteger:theModifiers], theModalKey, nil]; + return [NSArray arrayWithObjects:theKeyCode, [NSNumber numberWithInteger:theModifiers], theModalKey, [NSNumber numberWithInteger:theModalModifiers], nil]; } - (void)setKeystrokeFromString:(NSString*)keystroke { @@ -151,7 +158,8 @@ - (void)setKeystrokeFromString:(NSString*)keystroke { keyCode = [[keyarr objectAtIndex:0] unsignedIntValue]; modifiers = [[keyarr objectAtIndex:1] unsignedIntValue]; if ([keyarr count] >= 3 ) { - [self setModalKey:[keyarr objectAtIndex:2]]; + self.modalKey = [keyarr objectAtIndex:2]; + modalModifiers = [[keyarr objectAtIndex:3] unsignedIntValue]; } } if ([modalAndKey count] >= 3){ // modal toggle @@ -211,7 +219,7 @@ - (NSString *)modalHashKey { if ([self modalKey] == nil) { return nil; } - return [NSString stringWithFormat:@"%@%@%u", [self modalKey], PLUS, [self modifiers]]; + return [NSString stringWithFormat:@"%@%@%u", [self modalKey], PLUS, [self modalModifiers]]; } + (NSArray *)modalHashKeyToKeyAndModifiers:(NSString *)modalHashKey { diff --git a/Slate/SlateAppDelegate.m b/Slate/SlateAppDelegate.m index 8ab4dd45..2c39aeed 100644 --- a/Slate/SlateAppDelegate.m +++ b/Slate/SlateAppDelegate.m @@ -232,7 +232,7 @@ - (OSStatus)activateBinding:(EventHotKeyID)hkCom isRepeat:(BOOL)isRepeat { EventHotKeyRef myHotKeyRef; myHotKeyID.signature = *[[NSString stringWithFormat:@"hotkey%li",i] cStringUsingEncoding:NSASCIIStringEncoding]; myHotKeyID.id = (UInt32)i; - RegisterEventHotKey([binding keyCode], 0, myHotKeyID, GetEventMonitorTarget(), 0, &myHotKeyRef); + RegisterEventHotKey([binding keyCode], [binding modifiers], myHotKeyID, GetEventMonitorTarget(), 0, &myHotKeyRef); [binding setHotKeyRef:myHotKeyRef]; [[self currentModalHotKeyRefs] addObject:[NSValue valueWithPointer:myHotKeyRef]]; i++; From e63360ac20141137540f1f257fc86d49017618cd Mon Sep 17 00:00:00 2001 From: Raphael Schweikert Date: Wed, 20 Feb 2013 16:17:26 +0100 Subject: [PATCH 2/3] Meaningful error when binding multiple modal keys --- Slate/Binding.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Slate/Binding.m b/Slate/Binding.m index 18c33a66..b68a3105 100644 --- a/Slate/Binding.m +++ b/Slate/Binding.m @@ -136,6 +136,9 @@ + (NSArray *)getKeystrokeFromString:(NSString *)keystroke { if (_theModalKey != nil) { if(theModalKey == nil) { theModalKey = _theModalKey; + } else { + SlateLogger(@"Fatal: Two modal keys (codes %@ and %@) found in binding \"%@\"", theModalKey, _theModalKey, keystroke); + @throw([NSException exceptionWithName:@"Two Modal Keys" reason:[NSString stringWithFormat:@"Duplicate modal keys (%@ and %@) found in binding \"%@\"", theModalKey, _theModalKey, keystroke] userInfo:nil]); } } else if(theModalKey != nil) { //Assume every modifier defined after a modal key to be a modifier for the modal key (to be pressed when entering modal mode) as opposed to the actual key From 42a81c3bcb21780294eff921f96ffc915108c21a Mon Sep 17 00:00:00 2001 From: Raphael Schweikert Date: Wed, 20 Feb 2013 17:53:20 +0100 Subject: [PATCH 3/3] Describe changed `modal-key` modifiers behaviour Update README.md --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 94b7cbbc..7604faf2 100644 --- a/README.md +++ b/README.md @@ -218,11 +218,17 @@ The `bind` directive follows one of the following formats (tokens may be separat #### Modal Key #### -`modal-key` is any one of the Allowed Keys. If using a `modal-key`, pressing that key will cause the Slate menu bar icon to change indicating modal mode is activated. then clicking `key` will activate the binding. Modal mode will remain active until `key` has been pressed or `modal-key` is pressed again. You may specify multiple bindings with the same `modal-key` as long as `key` is different. Also, `modal-key` can accompany a comma or semicolon separated list of modifier keys listed above. This will cause that entire keystroke to be considered the modal activation binding. For example: `bind 1:f4,ctrl,alt` will result in the modal keystroke being `ctrl+alt+f4`. After pressing that keystroke, modal mode will be activated and pressing `1` after that will activate the binding. +`modal-key` is any one of the Allowed Keys. If using a `modal-key`, pressing that key will cause the Slate menu bar icon to change indicating modal mode is activated. then clicking `key` will activate the binding. Modal mode will remain active until `key` has been pressed or `modal-key` is pressed again. + +You may specify multiple bindings with the same `modal-key` as long as `key` is different. + +Also, `modal-key` can accompany a comma or semicolon separated list of modifier keys (listed above). These modifier keys can either precede the `modal-key` (in which case they will apply to the `key` itself, in modal mode) or they can follow the `modal-key` (which will cause the entire keystroke, including modifiers, to be the modal activation binding). + +For example: `bind 1:f4,ctrl,alt` will result in the modal keystroke being `ctrl+alt+f4`. After pressing that keystroke, modal mode will be activated and pressing `1` after that will activate the binding, whereas `bind 1:ctrl,f4,alt` will result in the modal mode being activated with `alt+f4` and the action being triggered with `ctrl+1` (while modal mode is active). ##### Modal Toggle Behavior ##### -If you add `:toggle` to the end of a modal binding it will cause that binding to not end the modal mode. For example with the binding `1:ctrl,f4`, you press `ctrl+f4` and then press `1` to activate the binding. Once that binding is activated, modal mode will end and you have to press `ctrl+f4` again to activate it. However, with the binding `1:ctrl,f4:toggle` pressing `ctrl+f4` will toggle modal mode. pressing `1` will activate the binding but not end modal mode. To end modal mode, press `ctrl+f4` again or use the config `modalEscapeKey`. +If you add `:toggle` to the end of a modal binding it will cause that binding to not end the modal mode. For example with the binding `1:ctrl,f4`, you press `f4` and then press `ctrl+1` to activate the binding. Once that binding is activated, modal mode will end and you have to press `f4` again to activate it. However, with the binding `1:ctrl,f4:toggle` pressing `f4` will toggle modal mode. pressing `ctrl+1` will activate the binding but not end modal mode. To end modal mode, press `f4` again or use the config `modalEscapeKey`. #### Operation ####