Shortcut key support
10
README.md
@@ -10,15 +10,19 @@ macOS 10.10 Yosemite or higher version.
|
||||
|
||||
## Installation
|
||||
|
||||
Download the [latest stable version](https://github.com/CocoaHeadsBrasil/MuteUnmuteMic/releases/download/1.4.2/Un.MuteMic.zip) or clone this repo and build & run.
|
||||
Download or clone this repo and build & run.
|
||||
|
||||
To build as a macos app: In XCode: choose _Product_ -> _Archive_ -> Click _Distribute App_ button -> Choose _Copy App_ -> Choose the export folder and click _Export_
|
||||
|
||||
## Usage
|
||||
|
||||
![[Un]MuteMic usage](https://cloud.githubusercontent.com/assets/235208/10419593/143171fc-704a-11e5-8270-374ca898685b.gif)
|
||||
Use the shortcut key, click the icon, or open the menu and click _Toggle Mute_.
|
||||
|
||||
## Authors
|
||||
|
||||
CocoaHeads Brasil: [http://www.cocoaheads.com.br/](http://www.cocoaheads.com.br/)
|
||||
* CocoaHeads Brasil: [http://www.cocoaheads.com.br/](http://www.cocoaheads.com.br/)
|
||||
* [racecarparts](https://github.com/racecarparts)
|
||||
* Shoutout to: [https://github.com/jaz303/JFHotkeyManager](https://github.com/jaz303/JFHotkeyManager)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
D9A9F66F1BC35EDC004395E8 /* AudioMixer.c in Sources */ = {isa = PBXBuildFile; fileRef = D9A9F66D1BC35EDC004395E8 /* AudioMixer.c */; };
|
||||
ECD9888D2448C7B2000626C4 /* JFHotkeyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = ECD9888C2448C7B2000626C4 /* JFHotkeyManager.m */; };
|
||||
ECF208BE1BAF2DE6000D3C2C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = ECF208BD1BAF2DE6000D3C2C /* AppDelegate.m */; };
|
||||
ECF208C11BAF2DE6000D3C2C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = ECF208C01BAF2DE6000D3C2C /* main.m */; };
|
||||
ECF208C31BAF2DE6000D3C2C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = ECF208C21BAF2DE6000D3C2C /* Assets.xcassets */; };
|
||||
@@ -17,6 +18,8 @@
|
||||
/* Begin PBXFileReference section */
|
||||
D9A9F66D1BC35EDC004395E8 /* AudioMixer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = AudioMixer.c; path = "[Un]MuteMic/AudioMixer.c"; sourceTree = "<group>"; };
|
||||
D9A9F66E1BC35EDC004395E8 /* AudioMixer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioMixer.h; path = "[Un]MuteMic/AudioMixer.h"; sourceTree = "<group>"; };
|
||||
ECD9888B2448C785000626C4 /* JFHotkeyManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JFHotkeyManager.h; sourceTree = "<group>"; };
|
||||
ECD9888C2448C7B2000626C4 /* JFHotkeyManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JFHotkeyManager.m; sourceTree = "<group>"; };
|
||||
ECF208B91BAF2DE6000D3C2C /* [Un]MuteMic.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "[Un]MuteMic.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
ECF208BC1BAF2DE6000D3C2C /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
ECF208BD1BAF2DE6000D3C2C /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
@@ -73,6 +76,8 @@
|
||||
ECF208C71BAF2DE6000D3C2C /* Info.plist */,
|
||||
ECF208BF1BAF2DE6000D3C2C /* Supporting Files */,
|
||||
D9A9F6701BC5830F004395E8 /* AudioMixer */,
|
||||
ECD9888B2448C785000626C4 /* JFHotkeyManager.h */,
|
||||
ECD9888C2448C7B2000626C4 /* JFHotkeyManager.m */,
|
||||
);
|
||||
path = "[Un]MuteMic";
|
||||
sourceTree = "<group>";
|
||||
@@ -116,6 +121,7 @@
|
||||
TargetAttributes = {
|
||||
ECF208B81BAF2DE6000D3C2C = {
|
||||
CreatedOnToolsVersion = 7.0;
|
||||
LastSwiftMigration = 1140;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -124,6 +130,7 @@
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
English,
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
@@ -157,6 +164,7 @@
|
||||
ECF208C11BAF2DE6000D3C2C /* main.m in Sources */,
|
||||
ECF208BE1BAF2DE6000D3C2C /* AppDelegate.m in Sources */,
|
||||
D9A9F66F1BC35EDC004395E8 /* AudioMixer.c in Sources */,
|
||||
ECD9888D2448C7B2000626C4 /* JFHotkeyManager.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -257,11 +265,15 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
INFOPLIST_FILE = "[Un]MuteMic/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = br.com.cocoaheads.MuteUnmuteMic;
|
||||
PRODUCT_NAME = "[Un]MuteMic";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "[Un]MuteMic-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -269,11 +281,14 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
INFOPLIST_FILE = "[Un]MuteMic/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = br.com.cocoaheads.MuteUnmuteMic;
|
||||
PRODUCT_NAME = "[Un]MuteMic";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "[Un]MuteMic-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:[Un]MuteMic.xcodeproj">
|
||||
location = "self:/Users/tom.wheeler/dev/MuteUnmuteMic/[Un]MuteMic.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PreviewsEnabled</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -7,14 +7,18 @@
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "AudioMixer.h"
|
||||
#import <Carbon/Carbon.h>
|
||||
#import "JFHotkeyManager.h"
|
||||
|
||||
static NSInteger const kDefaultVolume = 70;
|
||||
static NSInteger const kDefaultVolume = 80;
|
||||
|
||||
@interface AppDelegate ()
|
||||
|
||||
@property (nonatomic) NSStatusItem *menuItem;
|
||||
@property (nonatomic) BOOL muted;
|
||||
@property (nonatomic) NSInteger inputVolumeToUnmute;
|
||||
@property JFHotkeyManager *hkm;
|
||||
//@property __JFHotkey *shortcut;
|
||||
|
||||
@end
|
||||
|
||||
@@ -25,6 +29,13 @@ static NSInteger const kDefaultVolume = 70;
|
||||
[self initDefaults];
|
||||
[self configureStatusBar];
|
||||
[self updateInputVolume];
|
||||
|
||||
// Initialise a new hotkey manager
|
||||
_hkm = [[JFHotkeyManager alloc] init];
|
||||
|
||||
// Bind the hotkey by key code reference number and modifiers:
|
||||
// want modifiers? use `withModifiers:cmdKey + optionKey + shiftKey`
|
||||
JFHotKeyRef hk = [_hkm bindKeyRef:80 withModifiers:0 target:self action:@selector(toggleMute)];
|
||||
}
|
||||
|
||||
- (void)initDefaults
|
||||
@@ -39,7 +50,7 @@ static NSInteger const kDefaultVolume = 70;
|
||||
|
||||
NSStatusItem *menuItem =
|
||||
[statusBar statusItemWithLength:NSVariableStatusItemLength];
|
||||
[menuItem setToolTip:@"[Un]MuteMic by CocoaHeads Brazil"];
|
||||
[menuItem setToolTip:@"i haz teh mutez"];
|
||||
[menuItem setImage:[NSImage imageNamed:@"mic_on"]];
|
||||
[menuItem setHighlightMode:YES];
|
||||
|
||||
@@ -61,6 +72,11 @@ static NSInteger const kDefaultVolume = 70;
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)didToggleMute:(NSMenuItem *)sender
|
||||
{
|
||||
[self toggleMute];
|
||||
}
|
||||
|
||||
- (void)toggleMute
|
||||
{
|
||||
self.muted = !self.muted;
|
||||
@@ -96,11 +112,14 @@ static NSInteger const kDefaultVolume = 70;
|
||||
SetHardwareMute(muted);
|
||||
|
||||
// set image
|
||||
self.menuItem.image = [NSImage imageNamed:imageName];
|
||||
self.menuItem.button.image = [NSImage imageNamed:imageName];
|
||||
}
|
||||
|
||||
- (void)showMenu
|
||||
{
|
||||
// NSMenuItem *mi = [self.menu itemWithTitle:@"Shortcut"];
|
||||
|
||||
|
||||
[self.menuItem popUpStatusItemMenu:self.menu];
|
||||
}
|
||||
|
||||
@@ -115,4 +134,15 @@ static NSInteger const kDefaultVolume = 70;
|
||||
[self updateInputVolume];
|
||||
}
|
||||
|
||||
- (IBAction)didCallSetShortcut:(NSMenuItem *)sender
|
||||
{
|
||||
NSMenuItem *menuItem = (NSMenuItem*) sender;
|
||||
NSString *menuString = menuItem.title;
|
||||
|
||||
if ([menuString isEqualToString:@"Shortcut"])
|
||||
{
|
||||
NSLog(@"%@", menuString);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"filename" : "mic_off.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"filename" : "mic_off@2x.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
"template-rendering-intent" : "original"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 351 B After Width: | Height: | Size: 718 B |
|
Before Width: | Height: | Size: 643 B After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 302 B After Width: | Height: | Size: 461 B |
|
Before Width: | Height: | Size: 500 B After Width: | Height: | Size: 729 B |
@@ -1,7 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="9046" systemVersion="14E46" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="16096" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9046"/>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16096"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
@@ -19,6 +20,12 @@
|
||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||
<menu id="d1i-xa-wlo">
|
||||
<items>
|
||||
<menuItem title="Toggle Mute [F19]" id="jbg-be-dZJ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="didToggleMute:" target="Voe-Tx-rLC" id="mqy-oo-eJP"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Input Volume" id="w4W-DI-DEg">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Input Volume" autoenablesItems="NO" id="iVL-f8-mAL">
|
||||
@@ -35,13 +42,13 @@
|
||||
<action selector="didSetVolumeInput:" target="Voe-Tx-rLC" id="b1z-78-Fgk"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="80" tag="5" id="OoN-lP-2Ll">
|
||||
<menuItem title="80" state="on" tag="5" id="OoN-lP-2Ll">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="didSetVolumeInput:" target="Voe-Tx-rLC" id="itM-AQ-plW"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="70" state="on" id="ZNu-ZY-zwa">
|
||||
<menuItem title="70" id="ZNu-ZY-zwa">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="didSetVolumeInput:" target="Voe-Tx-rLC" id="Ykp-jU-4Cw"/>
|
||||
@@ -73,7 +80,7 @@
|
||||
<connections>
|
||||
<outlet property="delegate" destination="Voe-Tx-rLC" id="30G-NN-Naz"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="-268" y="-315.5"/>
|
||||
<point key="canvasLocation" x="-269" y="-276"/>
|
||||
</menu>
|
||||
</objects>
|
||||
</document>
|
||||
|
||||
50
[Un]MuteMic/JFHotkeyManager.h
Normal file
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// JFHotkeyManager.h
|
||||
// JFHotkeyManager
|
||||
//
|
||||
// Created by Jason Frame on 23/02/2010.
|
||||
// Copyright 2010 Jason Frame. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <Carbon/Carbon.h>
|
||||
|
||||
typedef NSUInteger JFHotKeyRef;
|
||||
|
||||
@interface JFHotkeyManager : NSObject {
|
||||
|
||||
NSMutableDictionary *_hotkeys;
|
||||
UInt32 _nextId;
|
||||
|
||||
}
|
||||
|
||||
- (JFHotKeyRef)bind:(NSString *)commandString
|
||||
target:(id)target
|
||||
action:(SEL)selector;
|
||||
|
||||
- (JFHotKeyRef)bindKeyRef:(UInt32)keyRef
|
||||
withModifiers:(UInt32)modifiers
|
||||
target:(id)target
|
||||
action:(SEL)selector;
|
||||
|
||||
- (void)unbind:(JFHotKeyRef)keyRef;
|
||||
|
||||
- (void)_dispatch:(NSUInteger)hotkeyId;
|
||||
|
||||
@end
|
||||
|
||||
@interface __JFHotkey : NSObject {
|
||||
id _target;
|
||||
SEL _action;
|
||||
EventHotKeyRef _ref;
|
||||
}
|
||||
|
||||
- (id)initWithHotkeyID:(UInt32)hotkeyID
|
||||
keyRef:(UInt32)keyRef
|
||||
modifiers:(UInt32)modifiers
|
||||
target:(id)target
|
||||
action:(SEL)selector;
|
||||
|
||||
- (void)invoke;
|
||||
|
||||
@end
|
||||
252
[Un]MuteMic/JFHotkeyManager.m
Normal file
@@ -0,0 +1,252 @@
|
||||
//
|
||||
// JFHotkeyManager.m
|
||||
// JFHotkeyManager
|
||||
//
|
||||
// Created by Jason Frame on 23/02/2010.
|
||||
// Copyright 2010 Jason Frame. All rights reserved.
|
||||
//
|
||||
|
||||
#import "JFHotkeyManager.h"
|
||||
|
||||
static OSStatus hotkeyHandler(EventHandlerCallRef hnd,
|
||||
EventRef evt,
|
||||
void *data) {
|
||||
|
||||
EventHotKeyID hkID;
|
||||
GetEventParameter(evt, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(hkID), NULL, &hkID);
|
||||
|
||||
JFHotkeyManager *hkm = (__bridge JFHotkeyManager *)data;
|
||||
[hkm _dispatch:hkID.id];
|
||||
|
||||
return noErr;
|
||||
|
||||
}
|
||||
|
||||
static NSMutableDictionary *keyMap;
|
||||
static NSMutableDictionary *modMap;
|
||||
|
||||
static void mapKey(NSString *s, NSUInteger key) {
|
||||
keyMap[s] = @(key);
|
||||
}
|
||||
|
||||
static void mapMod(NSString *s, NSUInteger mod) {
|
||||
modMap[s] = @(mod);
|
||||
}
|
||||
|
||||
|
||||
@implementation __JFHotkey
|
||||
- (id)initWithHotkeyID:(UInt32)hotkeyID
|
||||
keyRef:(UInt32)keyRef
|
||||
modifiers:(UInt32)modifiers
|
||||
target:(id)target
|
||||
action:(SEL)selector {
|
||||
if (self = [super init]) {
|
||||
|
||||
EventHotKeyID kID;
|
||||
kID.id = kID.signature = hotkeyID;
|
||||
|
||||
RegisterEventHotKey(keyRef, modifiers, kID, GetApplicationEventTarget(), 0, &_ref);
|
||||
|
||||
_target = target;
|
||||
_action = selector;
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
UnregisterEventHotKey(_ref);
|
||||
}
|
||||
|
||||
- (void)invoke {
|
||||
IMP imp = [_target methodForSelector:_action];
|
||||
void (*func)(id, SEL) = (void *)imp;
|
||||
func(_target, _action);
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@implementation JFHotkeyManager
|
||||
|
||||
+ (void)initialize {
|
||||
|
||||
modMap = [[NSMutableDictionary alloc] init];
|
||||
keyMap = [[NSMutableDictionary alloc] init];
|
||||
|
||||
// Is this guaranteed to be the same across systems/keyboards?
|
||||
// Probably not.
|
||||
|
||||
//
|
||||
// Keys
|
||||
|
||||
mapKey(@"a", 0x00);
|
||||
mapKey(@"b", 0x0B);
|
||||
mapKey(@"c", 0x09);
|
||||
mapKey(@"d", 0x02);
|
||||
mapKey(@"e", 0x0E);
|
||||
mapKey(@"f", 0x03);
|
||||
mapKey(@"g", 0x05);
|
||||
mapKey(@"h", 0x04);
|
||||
mapKey(@"i", 0x22);
|
||||
mapKey(@"j", 0x26);
|
||||
mapKey(@"k", 0x29);
|
||||
mapKey(@"l", 0x25);
|
||||
mapKey(@"m", 0x2E);
|
||||
mapKey(@"n", 0x2D);
|
||||
mapKey(@"o", 0x1F);
|
||||
mapKey(@"p", 0x23);
|
||||
mapKey(@"q", 0x0C);
|
||||
mapKey(@"r", 0x0F);
|
||||
mapKey(@"s", 0x01);
|
||||
mapKey(@"t", 0x11);
|
||||
mapKey(@"u", 0x20);
|
||||
mapKey(@"v", 0x09);
|
||||
mapKey(@"w", 0x0D);
|
||||
mapKey(@"x", 0x07);
|
||||
mapKey(@"y", 0x10);
|
||||
mapKey(@"z", 0x06);
|
||||
|
||||
mapKey(@"0", 0x1D);
|
||||
mapKey(@"1", 0x12);
|
||||
mapKey(@"2", 0x13);
|
||||
mapKey(@"3", 0x14);
|
||||
mapKey(@"4", 0x15);
|
||||
mapKey(@"5", 0x17);
|
||||
mapKey(@"6", 0x16);
|
||||
mapKey(@"7", 0x1A);
|
||||
mapKey(@"8", 0x1C);
|
||||
mapKey(@"9", 0x19);
|
||||
|
||||
mapKey(@",", 0x2B);
|
||||
mapKey(@".", 0x2F);
|
||||
mapKey(@"/", 0x2C);
|
||||
|
||||
mapKey(@"f1", 0x7A);
|
||||
mapKey(@"f2", 0x79);
|
||||
mapKey(@"f3", 0x63);
|
||||
mapKey(@"f4", 0x76);
|
||||
mapKey(@"f5", 0x60);
|
||||
mapKey(@"f6", 0x61);
|
||||
mapKey(@"f7", 0x62);
|
||||
mapKey(@"f8", 0x64);
|
||||
mapKey(@"f9", 0x65);
|
||||
mapKey(@"f10", 0x6D);
|
||||
mapKey(@"f11", 0x67);
|
||||
mapKey(@"f12", 0x6F);
|
||||
mapKey(@"f13", 0x69);
|
||||
mapKey(@"f14", 0x6B);
|
||||
mapKey(@"f15", 0x71);
|
||||
|
||||
mapKey(@"escape", 0x35);
|
||||
mapKey(@"esc", 0x35);
|
||||
mapKey(@"space", 0x31);
|
||||
mapKey(@"enter", 0x24);
|
||||
mapKey(@"tab", 0x30);
|
||||
mapKey(@"backspace",0x33);
|
||||
mapKey(@"bkspc", 0x33);
|
||||
|
||||
mapKey(@"left", 0x7B);
|
||||
mapKey(@"right", 0x7C);
|
||||
mapKey(@"down", 0x7D);
|
||||
mapKey(@"up", 0x7E);
|
||||
|
||||
//
|
||||
// Modifiers
|
||||
|
||||
mapMod(@"apple", cmdKey);
|
||||
|
||||
mapMod(@"ctrl", controlKey);
|
||||
mapMod(@"ctl", controlKey);
|
||||
mapMod(@"control", controlKey);
|
||||
|
||||
mapMod(@"opt", optionKey);
|
||||
mapMod(@"option", optionKey);
|
||||
mapMod(@"alt", optionKey);
|
||||
|
||||
mapMod(@"cmd", cmdKey);
|
||||
mapMod(@"command", cmdKey);
|
||||
mapMod(@"apple", cmdKey);
|
||||
|
||||
mapMod(@"shift", shiftKey);
|
||||
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
if (self = [super init]) {
|
||||
|
||||
_hotkeys = [[NSMutableDictionary alloc] init];
|
||||
_nextId = 1;
|
||||
|
||||
EventTypeSpec evtType;
|
||||
evtType.eventClass = kEventClassKeyboard;
|
||||
evtType.eventKind = kEventHotKeyPressed;
|
||||
InstallApplicationEventHandler(&hotkeyHandler,
|
||||
1,
|
||||
&evtType,
|
||||
(__bridge void*)self,
|
||||
NULL);
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (JFHotKeyRef)bind:(NSString *)commandString
|
||||
target:(id)target
|
||||
action:(SEL)selector {
|
||||
|
||||
UInt32 keyRef = 0;
|
||||
UInt32 modifiers = 0;
|
||||
|
||||
NSArray *bits = [[commandString lowercaseString] componentsSeparatedByString:@" "];
|
||||
for (NSString *bit in bits) {
|
||||
|
||||
NSNumber *code = modMap[bit];
|
||||
if (code != nil) {
|
||||
modifiers += [code unsignedIntValue];
|
||||
continue;
|
||||
}
|
||||
|
||||
code = keyMap[bit];
|
||||
if (code != nil) {
|
||||
keyRef = [code unsignedIntValue];
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return [self bindKeyRef:keyRef
|
||||
withModifiers:modifiers
|
||||
target:target
|
||||
action:selector];
|
||||
|
||||
}
|
||||
|
||||
- (JFHotKeyRef)bindKeyRef:(UInt32)keyRef
|
||||
withModifiers:(UInt32)modifiers
|
||||
target:(id)target
|
||||
action:(SEL)selector {
|
||||
|
||||
UInt32 keyID = _nextId;
|
||||
_nextId++;
|
||||
|
||||
__JFHotkey *hk = [[__JFHotkey alloc] initWithHotkeyID:keyID
|
||||
keyRef:keyRef
|
||||
modifiers:modifiers
|
||||
target:target
|
||||
action:selector];
|
||||
|
||||
_hotkeys[@(keyID)] = hk;
|
||||
|
||||
return keyID;
|
||||
|
||||
}
|
||||
|
||||
- (void)unbind:(JFHotKeyRef)keyRef {
|
||||
[_hotkeys removeObjectForKey:@(keyRef)];
|
||||
}
|
||||
|
||||
- (void)_dispatch:(NSUInteger)hotkeyId {
|
||||
[_hotkeys[@(hotkeyId)] invoke];
|
||||
}
|
||||
|
||||
@end
|
||||