From 377b44220f2a4a8b7ffc3eda9e93cf073e8a74da Mon Sep 17 00:00:00 2001 From: Tomáš Znamenáček Date: Tue, 5 Aug 2014 11:13:13 +0200 Subject: Repackaged the code as a framework and included the demo. Packaging the code as a framework is mostly just a formality. It doesn’t really change much, it just turns the code into a regular component. What it does change is that the code now has its own Xcode settings, which could make compatibility easier in the long run. Including the demo in the main repository makes it easier to hack on the library, since you can try the changes immediately. It also shows how to bundle the framework into an app that uses it. --- Framework/MASShortcut.h | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 Framework/MASShortcut.h (limited to 'Framework/MASShortcut.h') diff --git a/Framework/MASShortcut.h b/Framework/MASShortcut.h new file mode 100644 index 0000000..c9081a2 --- /dev/null +++ b/Framework/MASShortcut.h @@ -0,0 +1,60 @@ +#import +#import + +#define MASShortcutChar(char) [NSString stringWithFormat:@"%C", (unsigned short)(char)] +#define MASShortcutClear(flags) (flags & (NSControlKeyMask | NSShiftKeyMask | NSAlternateKeyMask | NSCommandKeyMask)) +#define MASShortcutCarbonFlags(cocoaFlags) (\ + (cocoaFlags & NSCommandKeyMask ? cmdKey : 0) | \ + (cocoaFlags & NSAlternateKeyMask ? optionKey : 0) | \ + (cocoaFlags & NSControlKeyMask ? controlKey : 0) | \ + (cocoaFlags & NSShiftKeyMask ? shiftKey : 0)) + +// These glyphs are missed in Carbon.h +enum { + kMASShortcutGlyphEject = 0x23CF, + kMASShortcutGlyphClear = 0x2715, + kMASShortcutGlyphDeleteLeft = 0x232B, + kMASShortcutGlyphDeleteRight = 0x2326, + kMASShortcutGlyphLeftArrow = 0x2190, + kMASShortcutGlyphRightArrow = 0x2192, + kMASShortcutGlyphUpArrow = 0x2191, + kMASShortcutGlyphDownArrow = 0x2193, + kMASShortcutGlyphEscape = 0x238B, + kMASShortcutGlyphHelp = 0x003F, + kMASShortcutGlyphPageDown = 0x21DF, + kMASShortcutGlyphPageUp = 0x21DE, + kMASShortcutGlyphTabRight = 0x21E5, + kMASShortcutGlyphReturn = 0x2305, + kMASShortcutGlyphReturnR2L = 0x21A9, + kMASShortcutGlyphPadClear = 0x2327, + kMASShortcutGlyphNorthwestArrow = 0x2196, + kMASShortcutGlyphSoutheastArrow = 0x2198, +} MASShortcutGlyph; + +@interface MASShortcut : NSObject + +@property (nonatomic) NSUInteger keyCode; +@property (nonatomic) NSUInteger modifierFlags; +@property (nonatomic, readonly) UInt32 carbonKeyCode; +@property (nonatomic, readonly) UInt32 carbonFlags; +@property (nonatomic, readonly) NSString *keyCodeString; +@property (nonatomic, readonly) NSString *keyCodeStringForKeyEquivalent; +@property (nonatomic, readonly) NSString *modifierFlagsString; +@property (nonatomic, readonly) NSData *data; +@property (nonatomic, readonly) BOOL shouldBypass; +@property (nonatomic, readonly, getter = isValid) BOOL valid; + +- (id)initWithKeyCode:(NSUInteger)code modifierFlags:(NSUInteger)flags; + ++ (MASShortcut *)shortcutWithKeyCode:(NSUInteger)code modifierFlags:(NSUInteger)flags; ++ (MASShortcut *)shortcutWithEvent:(NSEvent *)anEvent; ++ (MASShortcut *)shortcutWithData:(NSData *)aData; + +- (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 -- cgit v1.2.3 From 88392d1a6963cca5009b9b0c20b054ad9e911b6c Mon Sep 17 00:00:00 2001 From: Tomáš Znamenáček Date: Tue, 5 Aug 2014 15:16:59 +0200 Subject: Introduced a separate header file for keycode definitions. --- Framework/MASShortcut.h | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) (limited to 'Framework/MASShortcut.h') diff --git a/Framework/MASShortcut.h b/Framework/MASShortcut.h index c9081a2..f1e489c 100644 --- a/Framework/MASShortcut.h +++ b/Framework/MASShortcut.h @@ -1,4 +1,4 @@ -#import +#import "MASKeyCodes.h" #import #define MASShortcutChar(char) [NSString stringWithFormat:@"%C", (unsigned short)(char)] @@ -9,27 +9,6 @@ (cocoaFlags & NSControlKeyMask ? controlKey : 0) | \ (cocoaFlags & NSShiftKeyMask ? shiftKey : 0)) -// These glyphs are missed in Carbon.h -enum { - kMASShortcutGlyphEject = 0x23CF, - kMASShortcutGlyphClear = 0x2715, - kMASShortcutGlyphDeleteLeft = 0x232B, - kMASShortcutGlyphDeleteRight = 0x2326, - kMASShortcutGlyphLeftArrow = 0x2190, - kMASShortcutGlyphRightArrow = 0x2192, - kMASShortcutGlyphUpArrow = 0x2191, - kMASShortcutGlyphDownArrow = 0x2193, - kMASShortcutGlyphEscape = 0x238B, - kMASShortcutGlyphHelp = 0x003F, - kMASShortcutGlyphPageDown = 0x21DF, - kMASShortcutGlyphPageUp = 0x21DE, - kMASShortcutGlyphTabRight = 0x21E5, - kMASShortcutGlyphReturn = 0x2305, - kMASShortcutGlyphReturnR2L = 0x21A9, - kMASShortcutGlyphPadClear = 0x2327, - kMASShortcutGlyphNorthwestArrow = 0x2196, - kMASShortcutGlyphSoutheastArrow = 0x2198, -} MASShortcutGlyph; @interface MASShortcut : NSObject -- cgit v1.2.3 From 1c801726d35e56d3bbf4a33279213bc60935c244 Mon Sep 17 00:00:00 2001 From: Tomáš Znamenáček Date: Tue, 5 Aug 2014 15:34:46 +0200 Subject: Converted keycode macros to plain functions. Plain functions are less prone to bugs, the compiler understands them better and can offer better error messages, and plain functions can be refactored more easily. --- Framework/MASShortcut.h | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'Framework/MASShortcut.h') diff --git a/Framework/MASShortcut.h b/Framework/MASShortcut.h index f1e489c..b7ed55c 100644 --- a/Framework/MASShortcut.h +++ b/Framework/MASShortcut.h @@ -1,14 +1,4 @@ #import "MASKeyCodes.h" -#import - -#define MASShortcutChar(char) [NSString stringWithFormat:@"%C", (unsigned short)(char)] -#define MASShortcutClear(flags) (flags & (NSControlKeyMask | NSShiftKeyMask | NSAlternateKeyMask | NSCommandKeyMask)) -#define MASShortcutCarbonFlags(cocoaFlags) (\ - (cocoaFlags & NSCommandKeyMask ? cmdKey : 0) | \ - (cocoaFlags & NSAlternateKeyMask ? optionKey : 0) | \ - (cocoaFlags & NSControlKeyMask ? controlKey : 0) | \ - (cocoaFlags & NSShiftKeyMask ? shiftKey : 0)) - @interface MASShortcut : NSObject -- cgit v1.2.3 From 6383b054190d8bc4b7e059718cded0119d25d98c Mon Sep 17 00:00:00 2001 From: Tomáš Znamenáček Date: Tue, 5 Aug 2014 16:24:15 +0200 Subject: Introduced a standalone MASShortcutValidator class to validate shortcuts. It’s a natural simplification of the MASShortcut class. All MASShortcutView objects use a shared validator by default, but can be reconfigured to use a different validator if needed through the shortcutValidator property. --- Framework/MASShortcut.h | 8 -------- 1 file changed, 8 deletions(-) (limited to 'Framework/MASShortcut.h') diff --git a/Framework/MASShortcut.h b/Framework/MASShortcut.h index b7ed55c..123e25e 100644 --- a/Framework/MASShortcut.h +++ b/Framework/MASShortcut.h @@ -11,7 +11,6 @@ @property (nonatomic, readonly) NSString *modifierFlagsString; @property (nonatomic, readonly) NSData *data; @property (nonatomic, readonly) BOOL shouldBypass; -@property (nonatomic, readonly, getter = isValid) BOOL valid; - (id)initWithKeyCode:(NSUInteger)code modifierFlags:(NSUInteger)flags; @@ -19,11 +18,4 @@ + (MASShortcut *)shortcutWithEvent:(NSEvent *)anEvent; + (MASShortcut *)shortcutWithData:(NSData *)aData; -- (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 -- cgit v1.2.3 From 5d06f0070626608847d5a4089ad2f7244e280a1a Mon Sep 17 00:00:00 2001 From: Tomáš Znamenáček Date: Tue, 5 Aug 2014 16:29:39 +0200 Subject: Introduced `instancetype` return type where appropriate. --- Framework/MASShortcut.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Framework/MASShortcut.h') diff --git a/Framework/MASShortcut.h b/Framework/MASShortcut.h index 123e25e..24bd125 100644 --- a/Framework/MASShortcut.h +++ b/Framework/MASShortcut.h @@ -12,10 +12,10 @@ @property (nonatomic, readonly) NSData *data; @property (nonatomic, readonly) BOOL shouldBypass; -- (id)initWithKeyCode:(NSUInteger)code modifierFlags:(NSUInteger)flags; +- (instancetype)initWithKeyCode:(NSUInteger)code modifierFlags:(NSUInteger)flags; -+ (MASShortcut *)shortcutWithKeyCode:(NSUInteger)code modifierFlags:(NSUInteger)flags; -+ (MASShortcut *)shortcutWithEvent:(NSEvent *)anEvent; -+ (MASShortcut *)shortcutWithData:(NSData *)aData; ++ (instancetype)shortcutWithKeyCode:(NSUInteger)code modifierFlags:(NSUInteger)flags; ++ (instancetype)shortcutWithEvent:(NSEvent *)anEvent; ++ (instancetype)shortcutWithData:(NSData *)aData; @end -- cgit v1.2.3 From 344d22988f567890a201d58f96c9a2fcde9ce0b0 Mon Sep 17 00:00:00 2001 From: Tomáš Znamenáček Date: Tue, 5 Aug 2014 16:32:30 +0200 Subject: Removed [MASShortcut shouldBypass]. It was never used and the recording can already be cancelled by Esc. --- Framework/MASShortcut.h | 1 - 1 file changed, 1 deletion(-) (limited to 'Framework/MASShortcut.h') diff --git a/Framework/MASShortcut.h b/Framework/MASShortcut.h index 24bd125..6873dd9 100644 --- a/Framework/MASShortcut.h +++ b/Framework/MASShortcut.h @@ -10,7 +10,6 @@ @property (nonatomic, readonly) NSString *keyCodeStringForKeyEquivalent; @property (nonatomic, readonly) NSString *modifierFlagsString; @property (nonatomic, readonly) NSData *data; -@property (nonatomic, readonly) BOOL shouldBypass; - (instancetype)initWithKeyCode:(NSUInteger)code modifierFlags:(NSUInteger)flags; -- cgit v1.2.3 From 1cebcd3acf013b2b09087750e79dda7b90e93b5f Mon Sep 17 00:00:00 2001 From: Tomáš Znamenáček Date: Tue, 5 Aug 2014 16:42:31 +0200 Subject: Removed -data and shortcutWithData: from MASShortcut. Using NSKeyedUnarchiver and NSKeyedArchiver directly is almost the same amount of typing and it’s much clearer what goes on. --- Framework/MASShortcut.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'Framework/MASShortcut.h') diff --git a/Framework/MASShortcut.h b/Framework/MASShortcut.h index 6873dd9..aa3dfb0 100644 --- a/Framework/MASShortcut.h +++ b/Framework/MASShortcut.h @@ -9,12 +9,10 @@ @property (nonatomic, readonly) NSString *keyCodeString; @property (nonatomic, readonly) NSString *keyCodeStringForKeyEquivalent; @property (nonatomic, readonly) NSString *modifierFlagsString; -@property (nonatomic, readonly) NSData *data; - (instancetype)initWithKeyCode:(NSUInteger)code modifierFlags:(NSUInteger)flags; + (instancetype)shortcutWithKeyCode:(NSUInteger)code modifierFlags:(NSUInteger)flags; + (instancetype)shortcutWithEvent:(NSEvent *)anEvent; -+ (instancetype)shortcutWithData:(NSData *)aData; @end -- cgit v1.2.3 From 1bdadb166d7ac60a9ea8947e110146bf39a7fb9b Mon Sep 17 00:00:00 2001 From: Tomáš Znamenáček Date: Wed, 6 Aug 2014 10:19:11 +0200 Subject: Made the keyCode and modifierFlags properties read-only. A shortcut is a good value type, it makes good sense to represent it using an immutable object like NSNumber or NSString. --- Framework/MASShortcut.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Framework/MASShortcut.h') diff --git a/Framework/MASShortcut.h b/Framework/MASShortcut.h index aa3dfb0..2168952 100644 --- a/Framework/MASShortcut.h +++ b/Framework/MASShortcut.h @@ -2,8 +2,8 @@ @interface MASShortcut : NSObject -@property (nonatomic) NSUInteger keyCode; -@property (nonatomic) NSUInteger modifierFlags; +@property (nonatomic, readonly) NSUInteger keyCode; +@property (nonatomic, readonly) NSUInteger modifierFlags; @property (nonatomic, readonly) UInt32 carbonKeyCode; @property (nonatomic, readonly) UInt32 carbonFlags; @property (nonatomic, readonly) NSString *keyCodeString; -- cgit v1.2.3 From 1094fd9a612a3d02109b04346ee17da75c701449 Mon Sep 17 00:00:00 2001 From: Tomáš Znamenáček Date: Thu, 7 Aug 2014 18:20:37 +0200 Subject: Added header documentation. --- Framework/MASShortcut.h | 56 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) (limited to 'Framework/MASShortcut.h') diff --git a/Framework/MASShortcut.h b/Framework/MASShortcut.h index 2168952..3e1bedf 100644 --- a/Framework/MASShortcut.h +++ b/Framework/MASShortcut.h @@ -1,18 +1,70 @@ #import "MASKeyCodes.h" -@interface MASShortcut : NSObject +/** + @brief A model class to hold a key combination. + This class just represents a combination of keys. It does not care if + the combination is valid or can be used as a hotkey, it doesn’t watch + the input system for the shortcut appearance, nor it does access user + defaults. +*/ +@interface MASShortcut : NSObject + +/** + @brief The virtual key code for the keyboard key. + + @Hardware independent, same as in NSEvent. Events.h in the HIToolbox + framework for a complete list, or Command-click this symbol: kVK_ANSI_A. +*/ @property (nonatomic, readonly) NSUInteger keyCode; + +/** + @brief Cocoa keyboard modifier flags. + + Same as in NSEvent: NSCommandKeyMask, NSAlternateKeyMask, etc. +*/ @property (nonatomic, readonly) NSUInteger modifierFlags; + +/** + @brief Same as @p keyCode, just a different type. +*/ @property (nonatomic, readonly) UInt32 carbonKeyCode; + +/** + @brief Carbon modifier flags. + + A bit sum of @p cmdKey, @p optionKey, etc. +*/ @property (nonatomic, readonly) UInt32 carbonFlags; + +/** + @brief A string representing the “key” part of a shortcut, like the “5” in “⌘5”. +*/ @property (nonatomic, readonly) NSString *keyCodeString; + +/** + @brief A key-code string used in key equivalent matching. + + For precise meaning of “key equivalents” see the @p keyEquivalent + property of @p NSMenuItem. Here the string is used to support shortcut + validation (“is the shortcut already taken in this menu?”) and + for display in @p NSMenu. +*/ @property (nonatomic, readonly) NSString *keyCodeStringForKeyEquivalent; + +/** + @brief A string representing the shortcut modifiers, like the “⌘” in “⌘5”. +*/ @property (nonatomic, readonly) NSString *modifierFlagsString; - (instancetype)initWithKeyCode:(NSUInteger)code modifierFlags:(NSUInteger)flags; - + (instancetype)shortcutWithKeyCode:(NSUInteger)code modifierFlags:(NSUInteger)flags; + +/** + @brief Creates a new shortcut from an NSEvent object. + + This is just a convenience initializer that reads the key code and modifiers from an NSEvent. +*/ + (instancetype)shortcutWithEvent:(NSEvent *)anEvent; @end -- cgit v1.2.3