aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Shpakovski2012-11-23 23:46:04 +0300
committerVadim Shpakovski2012-11-23 23:46:04 +0300
commita89afec679f5ce42e73f085ce13f115fcae8afb9 (patch)
treeede5ce4dc5f1e4c6be1e28a46f373f0f8a9370f6
parentbc56cdc907541cb633e8787424e0112ed856a5e9 (diff)
downloadMASShortcut-a89afec679f5ce42e73f085ce13f115fcae8afb9.tar.bz2
Enables support for exlusive Option modifier.
-rw-r--r--MASShortcut.h5
-rw-r--r--MASShortcut.m65
2 files changed, 53 insertions, 17 deletions
diff --git a/MASShortcut.h b/MASShortcut.h
index 3c6c109..06507f6 100644
--- a/MASShortcut.h
+++ b/MASShortcut.h
@@ -51,4 +51,9 @@ enum {
- (BOOL)isTakenError:(NSError **)error;
+// The following API enable hotkeys with the Option key as the only modifier
+// For example, Option-G will not generate © and Option-R will not paste ®
++ (void)setAllowsAnyHotkeyWithOptionModifier:(BOOL)allow;
++ (BOOL)allowsAnyHotkeyWithOptionModifier;
+
@end
diff --git a/MASShortcut.m b/MASShortcut.m
index ca5a1ae..b004e48 100644
--- a/MASShortcut.m
+++ b/MASShortcut.m
@@ -1,7 +1,7 @@
#import "MASShortcut.h"
-NSString *const kMASShortcutKeyCode = @"KeyCode";
-NSString *const kMASShortcutModifierFlags = @"ModifierFlags";
+NSString *const MASShortcutKeyCode = @"KeyCode";
+NSString *const MASShortcutModifierFlags = @"ModifierFlags";
@implementation MASShortcut {
NSUInteger _keyCode; // NSNotFound if empty
@@ -15,17 +15,17 @@ NSString *const kMASShortcutModifierFlags = @"ModifierFlags";
- (void)encodeWithCoder:(NSCoder *)coder
{
- [coder encodeInteger:(self.keyCode != NSNotFound ? (NSInteger)self.keyCode : - 1) forKey:kMASShortcutKeyCode];
- [coder encodeInteger:(NSInteger)self.modifierFlags forKey:kMASShortcutModifierFlags];
+ [coder encodeInteger:(self.keyCode != NSNotFound ? (NSInteger)self.keyCode : - 1) forKey:MASShortcutKeyCode];
+ [coder encodeInteger:(NSInteger)self.modifierFlags forKey:MASShortcutModifierFlags];
}
- (id)initWithCoder:(NSCoder *)decoder
{
self = [super init];
if (self) {
- NSInteger code = [decoder decodeIntegerForKey:kMASShortcutKeyCode];
+ NSInteger code = [decoder decodeIntegerForKey:MASShortcutKeyCode];
self.keyCode = (code < 0 ? NSNotFound : (NSUInteger)code);
- self.modifierFlags = [decoder decodeIntegerForKey:kMASShortcutModifierFlags];
+ self.modifierFlags = [decoder decodeIntegerForKey:MASShortcutModifierFlags];
}
return self;
}
@@ -232,19 +232,50 @@ NSString *const kMASShortcutModifierFlags = @"ModifierFlags";
return (self.modifierFlags == NSCommandKeyMask) && ([codeString isEqualToString:@"W"] || [codeString isEqualToString:@"Q"]);
}
+BOOL MASShortcutAllowsAnyHotkeyWithOptionModifier = NO;
+
++ (void)setAllowsAnyHotkeyWithOptionModifier:(BOOL)allow
+{
+ MASShortcutAllowsAnyHotkeyWithOptionModifier = allow;
+}
+
++ (BOOL)allowsAnyHotkeyWithOptionModifier
+{
+ return MASShortcutAllowsAnyHotkeyWithOptionModifier;
+}
+
- (BOOL)isValid
{
- BOOL hasFlags = (_modifierFlags > 0);
- BOOL hasCommand = ((_modifierFlags & NSCommandKeyMask) > 0);
- BOOL hasControl = ((_modifierFlags & NSControlKeyMask) > 0);
- BOOL hasOption = ((_modifierFlags & NSAlternateKeyMask) > 0);
- BOOL isFunction = ((_keyCode == kVK_F1) || (_keyCode == kVK_F2) || (_keyCode == kVK_F3) || (_keyCode == kVK_F4) ||
- (_keyCode == kVK_F5) || (_keyCode == kVK_F6) || (_keyCode == kVK_F7) || (_keyCode == kVK_F8) ||
- (_keyCode == kVK_F9) || (_keyCode == kVK_F10) || (_keyCode == kVK_F11) || (_keyCode == kVK_F12) ||
- (_keyCode == kVK_F13) || (_keyCode == kVK_F14) || (_keyCode == kVK_F15) || (_keyCode == kVK_F16) ||
- (_keyCode == kVK_F17) || (_keyCode == kVK_F18) || (_keyCode == kVK_F19) || (_keyCode == kVK_F20));
- BOOL isSpecial = ((_keyCode == kVK_Space) || (_keyCode == kVK_Escape) || (_keyCode == kVK_Return));
- return ((hasFlags && (hasCommand || hasControl || (hasOption && isSpecial))) || isFunction);
+ // Allow any function key with any combination of modifiers
+ BOOL includesFunctionKey = ((_keyCode == kVK_F1) || (_keyCode == kVK_F2) || (_keyCode == kVK_F3) || (_keyCode == kVK_F4) ||
+ (_keyCode == kVK_F5) || (_keyCode == kVK_F6) || (_keyCode == kVK_F7) || (_keyCode == kVK_F8) ||
+ (_keyCode == kVK_F9) || (_keyCode == kVK_F10) || (_keyCode == kVK_F11) || (_keyCode == kVK_F12) ||
+ (_keyCode == kVK_F13) || (_keyCode == kVK_F14) || (_keyCode == kVK_F15) || (_keyCode == kVK_F16) ||
+ (_keyCode == kVK_F17) || (_keyCode == kVK_F18) || (_keyCode == kVK_F19) || (_keyCode == kVK_F20));
+ if (includesFunctionKey) return YES;
+
+ // Do not allow any other key without modifiers
+ BOOL hasModifierFlags = (_modifierFlags > 0);
+ if (!hasModifierFlags) return NO;
+
+ // Allow any hotkey containing Control or Command modifier
+ BOOL includesCommand = ((_modifierFlags & NSCommandKeyMask) > 0);
+ BOOL includesControl = ((_modifierFlags & NSControlKeyMask) > 0);
+ if (includesCommand || includesControl) return YES;
+
+ // Allow Option key only in selected cases
+ BOOL includesOption = ((_modifierFlags & NSAlternateKeyMask) > 0);
+ if (includesOption) {
+
+ // Always allow Option-Space and Option-Escape because they do not have any bind system commands
+ if ((_keyCode == kVK_Space) || (_keyCode == kVK_Escape)) return YES;
+
+ // Allow Option modifier with any key even if it will break the system binding
+ if ([[self class] allowsAnyHotkeyWithOptionModifier]) return YES;
+ }
+
+ // The hotkey does not have any modifiers or violates system bindings
+ return NO;
}
- (BOOL)isKeyEquivalent:(NSString *)keyEquivalent flags:(NSUInteger)flags takenInMenu:(NSMenu *)menu error:(NSError **)outError