Skip to content

Commit

Permalink
Created Frameworks folder, added MASShortcut framework and moved Sparkle
Browse files Browse the repository at this point in the history
  • Loading branch information
sveinbjornt committed Apr 16, 2019
1 parent 123548f commit c559e02
Show file tree
Hide file tree
Showing 39 changed files with 448 additions and 27 deletions.
1 change: 1 addition & 0 deletions Frameworks/MASShortcut.framework/Headers
1 change: 1 addition & 0 deletions Frameworks/MASShortcut.framework/MASShortcut
1 change: 1 addition & 0 deletions Frameworks/MASShortcut.framework/Modules
File renamed without changes.
@@ -0,0 +1,19 @@
extern NSString *const MASDictionaryTransformerName;

/**
Converts shortcuts for storage in user defaults.
User defaults can’t stored custom types directly, they have to
be serialized to `NSData` or some other supported type like an
`NSDictionary`. In Cocoa Bindings, the conversion can be done
using value transformers like this one.
There’s a built-in transformer (`NSKeyedUnarchiveFromDataTransformerName`)
that converts any `NSCoding` types to `NSData`, but with shortcuts
it makes sense to use a dictionary instead – the defaults look better
when inspected with the `defaults` command-line utility and the
format is compatible with an older sortcut library called Shortcut
Recorder.
*/
@interface MASDictionaryTransformer : NSValueTransformer
@end
44 changes: 44 additions & 0 deletions Frameworks/MASShortcut.framework/Versions/A/Headers/MASKeyCodes.h
@@ -0,0 +1,44 @@
#import <Carbon/Carbon.h>
#import <AppKit/AppKit.h>
#import "MASKeyMasks.h"

// 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,
};

NS_INLINE NSString* NSStringFromMASKeyCode(unsigned short ch)
{
return [NSString stringWithFormat:@"%C", ch];
}

NS_INLINE NSUInteger MASPickCocoaModifiers(NSUInteger flags)
{
return (flags & (NSEventModifierFlagControl | NSEventModifierFlagShift | NSEventModifierFlagOption | NSEventModifierFlagCommand));
}

NS_INLINE UInt32 MASCarbonModifiersFromCocoaModifiers(NSUInteger cocoaFlags)
{
return
(cocoaFlags & NSEventModifierFlagCommand ? cmdKey : 0)
| (cocoaFlags & NSEventModifierFlagOption ? optionKey : 0)
| (cocoaFlags & NSEventModifierFlagControl ? controlKey : 0)
| (cocoaFlags & NSEventModifierFlagShift ? shiftKey : 0);
}
18 changes: 18 additions & 0 deletions Frameworks/MASShortcut.framework/Versions/A/Headers/MASKeyMasks.h
@@ -0,0 +1,18 @@
#import <Availability.h>

// https://github.com/shpakovski/MASShortcut/issues/99
//
// Long story short: NSControlKeyMask and friends were replaced with NSEventModifierFlagControl
// and similar in macOS Sierra. The project builds fine & clean, but including MASShortcut in
// a project with deployment target set to 10.12 results in several deprecation warnings because
// of the control masks. Simply replacing the old symbols with the new ones isn’t an option,
// since it breaks the build on older SDKs – in Travis, for example.
//
// It should be safe to remove this whole thing once the 10.12 SDK is ubiquitous.

#if __MAC_OS_X_VERSION_MAX_ALLOWED < 101200
#define NSEventModifierFlagCommand NSCommandKeyMask
#define NSEventModifierFlagControl NSControlKeyMask
#define NSEventModifierFlagOption NSAlternateKeyMask
#define NSEventModifierFlagShift NSShiftKeyMask
#endif
81 changes: 81 additions & 0 deletions Frameworks/MASShortcut.framework/Versions/A/Headers/MASShortcut.h
@@ -0,0 +1,81 @@
#import "MASKeyCodes.h"

/**
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 <NSSecureCoding, NSCopying>

/**
The virtual key code for the keyboard key.
Hardware independent, same as in `NSEvent`. See `Events.h` in the HIToolbox
framework for a complete list, or Command-click this symbol: `kVK_ANSI_A`.
*/
@property (nonatomic, readonly) NSUInteger keyCode;

/**
Cocoa keyboard modifier flags.
Same as in `NSEvent`: `NSCommandKeyMask`, `NSAlternateKeyMask`, etc.
*/
@property (nonatomic, readonly) NSUInteger modifierFlags;

/**
Same as `keyCode`, just a different type.
*/
@property (nonatomic, readonly) UInt32 carbonKeyCode;

/**
Carbon modifier flags.
A bit sum of `cmdKey`, `optionKey`, etc.
*/
@property (nonatomic, readonly) UInt32 carbonFlags;

/**
A string representing the “key” part of a shortcut, like the `5` in `⌘5`.
@warning The value may change depending on the active keyboard layout.
For example for the `^2` keyboard shortcut (`kVK_ANSI_2+NSControlKeyMask`
to be precise) the `keyCodeString` is `2` on the US keyboard, but `ě` when
the Czech keyboard layout is active. See the spec for details.
*/
@property (nonatomic, readonly) NSString *keyCodeString;

/**
A key-code string used in key equivalent matching.
For precise meaning of “key equivalents” see the `keyEquivalent`
property of `NSMenuItem`. Here the string is used to support shortcut
validation (“is the shortcut already taken in this menu?”) and
for display in `NSMenu`.
The value of this property may differ from `keyCodeString`. For example
the Russian keyboard has a `Г` (Ge) Cyrillic character in place of the
latin `U` key. This means you can create a `^Г` shortcut, but in menus
that’s always displayed as `^U`. So the `keyCodeString` returns `Г`
and `keyCodeStringForKeyEquivalent` returns `U`.
*/
@property (nonatomic, readonly) NSString *keyCodeStringForKeyEquivalent;

/**
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;

/**
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
@@ -0,0 +1,67 @@
#import "MASShortcutMonitor.h"

/**
Binds actions to user defaults keys.
If you store shortcuts in user defaults (for example by binding
a `MASShortcutView` to user defaults), you can use this class to
connect an action directly to a user defaults key. If the shortcut
stored under the key changes, the action will get automatically
updated to the new one.
This class is mostly a wrapper around a `MASShortcutMonitor`. It
watches the changes in user defaults and updates the shortcut monitor
accordingly with the new shortcuts.
*/
@interface MASShortcutBinder : NSObject

/**
A convenience shared instance.
You may use it so that you don’t have to manage an instance by hand,
but it’s perfectly fine to allocate and use a separate instance instead.
*/
+ (instancetype) sharedBinder;

/**
The underlying shortcut monitor.
*/
@property(strong) MASShortcutMonitor *shortcutMonitor;

/**
Binding options customizing the access to user defaults.
As an example, you can use `NSValueTransformerNameBindingOption` to customize
the storage format used for the shortcuts. By default the shortcuts are converted
from `NSData` (`NSKeyedUnarchiveFromDataTransformerName`). Note that if the
binder is to work with `MASShortcutView`, both object have to use the same storage
format.
*/
@property(copy) NSDictionary *bindingOptions;

/**
Binds given action to a shortcut stored under the given defaults key.
In other words, no matter what shortcut you store under the given key,
pressing it will always trigger the given action.
*/
- (void) bindShortcutWithDefaultsKey: (NSString*) defaultsKeyName toAction: (dispatch_block_t) action;

/**
Disconnect the binding between user defaults and action.
In other words, the shortcut stored under the given key will no longer trigger an action.
*/
- (void) breakBindingWithDefaultsKey: (NSString*) defaultsKeyName;

/**
Register default shortcuts in user defaults.
This is a convenience frontent to `[NSUserDefaults registerDefaults]`.
The dictionary should contain a map of user defaults’ keys to appropriate
keyboard shortcuts. The shortcuts will be transformed according to
`bindingOptions` and registered using `registerDefaults`.
*/
- (void) registerDefaultShortcuts: (NSDictionary*) defaultShortcuts;

@end
@@ -0,0 +1,27 @@
#import "MASShortcut.h"

/**
Executes action when a shortcut is pressed.
There can only be one instance of this class, otherwise things
will probably not work. (There’s a Carbon event handler inside
and there can only be one Carbon event handler of a given type.)
*/
@interface MASShortcutMonitor : NSObject

- (instancetype) init __unavailable;
+ (instancetype) sharedMonitor;

/**
Register a shortcut along with an action.
Attempting to insert an already registered shortcut probably won’t work.
It may burn your house or cut your fingers. You have been warned.
*/
- (BOOL) registerShortcut: (MASShortcut*) shortcut withAction: (dispatch_block_t) action;
- (BOOL) isShortcutRegistered: (MASShortcut*) shortcut;

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

@end
@@ -0,0 +1,29 @@
#import "MASShortcut.h"

/**
This class is used by the recording control to tell which shortcuts are acceptable.
There are two kinds of shortcuts that are not considered acceptable: shortcuts that
are too simple (like single letter keys) and shortcuts that are already used by the
operating system.
*/
@interface MASShortcutValidator : NSObject

/**
Set to `YES` if you want to accept Option-something shortcuts.
`NO` by default, since Option-something shortcuts are often used by system,
for example Option-G will type the © sign. This also applies to Option-Shift
shortcuts – in other words, shortcut recorder will not accept shortcuts like
Option-Shift-K by default. (Again, since Option-Shift-K inserts the Apple
logo sign by default.)
*/
@property(assign) BOOL allowAnyShortcutWithOptionModifier;

+ (instancetype) sharedValidator;

- (BOOL) isShortcutValid: (MASShortcut*) shortcut;
- (BOOL) isShortcut: (MASShortcut*) shortcut alreadyTakenInMenu: (NSMenu*) menu explanation: (NSString**) explanation;
- (BOOL) isShortcutAlreadyTakenBySystem: (MASShortcut*) shortcut explanation: (NSString**) explanation;

@end
@@ -0,0 +1,25 @@
#import "MASShortcutView.h"

/**
A simplified interface to bind the recorder value to user defaults.
You can bind the `shortcutValue` to user defaults using the standard
`bind:toObject:withKeyPath:options:` call, but since that’s a lot to type
and read, here’s a simpler option.
Setting the `associatedUserDefaultsKey` binds the view’s shortcut value
to the given user defaults key. You can supply a value transformer to convert
values between user defaults and `MASShortcut`. If you don’t supply
a transformer, the `NSUnarchiveFromDataTransformerName` will be used
automatically.
Set `associatedUserDefaultsKey` to `nil` to disconnect the binding.
*/
@interface MASShortcutView (Bindings)

@property(copy) NSString *associatedUserDefaultsKey;

- (void) setAssociatedUserDefaultsKey: (NSString*) newKey withTransformer: (NSValueTransformer*) transformer;
- (void) setAssociatedUserDefaultsKey: (NSString*) newKey withTransformerName: (NSString*) transformerName;

@end
@@ -0,0 +1,26 @@
@class MASShortcut, MASShortcutValidator;

extern NSString *const MASShortcutBinding;

typedef enum {
MASShortcutViewStyleDefault = 0, // Height = 19 px
MASShortcutViewStyleTexturedRect, // Height = 25 px
MASShortcutViewStyleRounded, // Height = 43 px
MASShortcutViewStyleFlat
} MASShortcutViewStyle;

@interface MASShortcutView : NSView

@property (nonatomic, strong) MASShortcut *shortcutValue;
@property (nonatomic, strong) MASShortcutValidator *shortcutValidator;
@property (nonatomic, getter = isRecording) BOOL recording;
@property (nonatomic, getter = isEnabled) BOOL enabled;
@property (nonatomic, copy) void (^shortcutValueChange)(MASShortcutView *sender);
@property (nonatomic, assign) MASShortcutViewStyle style;

/// Returns custom class for drawing control.
+ (Class)shortcutCellClass;

- (void)setAcceptsFirstResponder:(BOOL)value;

@end
@@ -0,0 +1,8 @@
#import "MASKeyMasks.h"
#import "MASShortcut.h"
#import "MASShortcutValidator.h"
#import "MASShortcutMonitor.h"
#import "MASShortcutBinder.h"
#import "MASDictionaryTransformer.h"
#import "MASShortcutView.h"
#import "MASShortcutView+Bindings.h"
Binary file not shown.
@@ -0,0 +1,6 @@
framework module MASShortcut {
umbrella header "Shortcut.h"

export *
module * { export * }
}

0 comments on commit c559e02

Please sign in to comment.