Permalink
Browse files

Initial Repository Import

  • Loading branch information...
0 parents commit ab71653ae40f300a9cf381252f540cd21e7d6906 Justin Williams committed Jul 28, 2009
Showing with 6,255 additions and 0 deletions.
  1. +13 −0 .gitignore
  2. +2 −0 English.lproj/InfoPlist.strings
  3. +4,405 −0 English.lproj/MainMenu.xib
  4. +96 −0 English.lproj/SGKeyCodes.plist
  5. +1 −0 Frameworks/ShortcutRecorder.framework/Headers
  6. +1 −0 Frameworks/ShortcutRecorder.framework/Resources
  7. +1 −0 Frameworks/ShortcutRecorder.framework/ShortcutRecorder
  8. +185 −0 Frameworks/ShortcutRecorder.framework/Versions/A/Headers/SRCommon.h
  9. +16 −0 Frameworks/ShortcutRecorder.framework/Versions/A/Headers/SRKeyCodeTransformer.h
  10. +137 −0 Frameworks/ShortcutRecorder.framework/Versions/A/Headers/SRRecorderCell.h
  11. +74 −0 Frameworks/ShortcutRecorder.framework/Versions/A/Headers/SRRecorderControl.h
  12. +34 −0 Frameworks/ShortcutRecorder.framework/Versions/A/Headers/SRValidator.h
  13. +15 −0 Frameworks/ShortcutRecorder.framework/Versions/A/Headers/SR_LeopardView.h
  14. +17 −0 Frameworks/ShortcutRecorder.framework/Versions/A/Headers/ShortcutRecorder.h
  15. +20 −0 Frameworks/ShortcutRecorder.framework/Versions/A/Resources/Info.plist
  16. +26 −0 ...rks/ShortcutRecorder.framework/Versions/A/Resources/ShortcutRecorder.ibplugin/Contents/Info.plist
  17. BIN ...Recorder.framework/Versions/A/Resources/ShortcutRecorder.ibplugin/Contents/MacOS/ShortcutRecorder
  18. BIN ...Versions/A/Resources/ShortcutRecorder.ibplugin/Contents/Resources/English.lproj/InfoPlist.strings
  19. BIN ...ns/A/Resources/ShortcutRecorder.ibplugin/Contents/Resources/English.lproj/SR_LeopardInspector.nib
  20. BIN ...ions/A/Resources/ShortcutRecorder.ibplugin/Contents/Resources/English.lproj/SR_LeopardLibrary.nib
  21. +9 −0 ...sions/A/Resources/ShortcutRecorder.ibplugin/Contents/Resources/SRRecorderControl.classdescription
  22. BIN Frameworks/ShortcutRecorder.framework/Versions/A/ShortcutRecorder
  23. +1 −0 Frameworks/ShortcutRecorder.framework/Versions/Current
  24. +2 −0 LICENSE.txt
  25. +37 −0 README.markdown
  26. +32 −0 Resources/Info.plist
  27. +361 −0 SGHotKeyCenter.xcodeproj/project.pbxproj
  28. +35 −0 SGHotKeysLib/SGHotKey.h
  29. +59 −0 SGHotKeysLib/SGHotKey.m
  30. +26 −0 SGHotKeysLib/SGHotKeyCenter.h
  31. +208 −0 SGHotKeysLib/SGHotKeyCenter.m
  32. +28 −0 SGHotKeysLib/SGKeyCodeTranslator.h
  33. +56 −0 SGHotKeysLib/SGKeyCodeTranslator.m
  34. +38 −0 SGHotKeysLib/SGKeyCombo.h
  35. +209 −0 SGHotKeysLib/SGKeyCombo.m
  36. +7 −0 Source/Prefix.pch
  37. +28 −0 Source/SGHotKeyCenterAppDelegate.h
  38. +62 −0 Source/SGHotKeyCenterAppDelegate.m
  39. +14 −0 Source/main.m
13 .gitignore
@@ -0,0 +1,13 @@
+# xcode noise
+build/*
+*.pbxuser
+*.mode1v3
+*.mode2v3
+*.perspectivev3
+
+# old skool
+.svn
+
+# osx noise
+.DS_Store
+profile
2 English.lproj/InfoPlist.strings
@@ -0,0 +1,2 @@
+/* Localized versions of Info.plist keys */
+
4,405 English.lproj/MainMenu.xib
4,405 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
96 English.lproj/SGKeyCodes.plist
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>padKeyString</key>
+ <string>Pad</string>
+ <key>padKeys</key>
+ <array>
+ <string>65</string>
+ <string>67</string>
+ <string>69</string>
+ <string>75</string>
+ <string>78</string>
+ <string>81</string>
+ <string>82</string>
+ <string>83</string>
+ <string>84</string>
+ <string>85</string>
+ <string>86</string>
+ <string>87</string>
+ <string>88</string>
+ <string>89</string>
+ <string>91</string>
+ <string>92</string>
+ </array>
+ <key>unmappedKeys</key>
+ <dict>
+ <key>100</key>
+ <string>F8</string>
+ <key>101</key>
+ <string>F9</string>
+ <key>103</key>
+ <string>F11</string>
+ <key>105</key>
+ <string>F13</string>
+ <key>107</key>
+ <string>F14</string>
+ <key>109</key>
+ <string>F10</string>
+ <key>111</key>
+ <string>F12</string>
+ <key>113</key>
+ <string>F15</string>
+ <key>114</key>
+ <string>Ins</string>
+ <key>115</key>
+ <string>Home</string>
+ <key>116</key>
+ <string>Page Up</string>
+ <key>117</key>
+ <string>Del</string>
+ <key>118</key>
+ <string>F4</string>
+ <key>119</key>
+ <string>End</string>
+ <key>120</key>
+ <string>F2</string>
+ <key>121</key>
+ <string>Page Down</string>
+ <key>122</key>
+ <string>F1</string>
+ <key>123</key>
+ <string>Left Arrow</string>
+ <key>124</key>
+ <string>Right Arrow</string>
+ <key>125</key>
+ <string>Down Arrow</string>
+ <key>126</key>
+ <string>Up Arrow</string>
+ <key>36</key>
+ <string>Return</string>
+ <key>48</key>
+ <string>Tab</string>
+ <key>49</key>
+ <string>Space</string>
+ <key>51</key>
+ <string>Backspace</string>
+ <key>53</key>
+ <string>ESC</string>
+ <key>71</key>
+ <string>Clear</string>
+ <key>76</key>
+ <string>Pad Enter</string>
+ <key>96</key>
+ <string>F5</string>
+ <key>97</key>
+ <string>F6</string>
+ <key>98</key>
+ <string>F7</string>
+ <key>99</key>
+ <string>F3</string>
+ </dict>
+ <key>version</key>
+ <integer>1</integer>
+</dict>
+</plist>
1 Frameworks/ShortcutRecorder.framework/Headers
1 Frameworks/ShortcutRecorder.framework/Resources
1 Frameworks/ShortcutRecorder.framework/ShortcutRecorder
185 Frameworks/ShortcutRecorder.framework/Versions/A/Headers/SRCommon.h
@@ -0,0 +1,185 @@
+//
+// SRCommon.h
+// ShortcutRecorder
+//
+// Copyright 2006-2007 Contributors. All rights reserved.
+//
+// License: BSD
+//
+// Contributors:
+// David Dauer
+// Jesper
+// Jamie Kirkpatrick
+
+#import <Cocoa/Cocoa.h>
+#import <Carbon/Carbon.h>
+#import <CoreServices/CoreServices.h>
+
+#pragma mark Dummy class
+
+@interface SRDummyClass : NSObject {} @end
+
+#pragma mark -
+#pragma mark Typedefs
+
+typedef struct _KeyCombo {
+ NSUInteger flags; // 0 for no flags
+ NSInteger code; // -1 for no code
+} KeyCombo;
+
+#pragma mark -
+#pragma mark Enums
+
+// Unicode values of some keyboard glyphs
+enum {
+ KeyboardTabRightGlyph = 0x21E5,
+ KeyboardTabLeftGlyph = 0x21E4,
+ KeyboardCommandGlyph = kCommandUnicode,
+ KeyboardOptionGlyph = kOptionUnicode,
+ KeyboardShiftGlyph = kShiftUnicode,
+ KeyboardControlGlyph = kControlUnicode,
+ KeyboardReturnGlyph = 0x2305,
+ KeyboardReturnR2LGlyph = 0x21A9,
+ KeyboardDeleteLeftGlyph = 0x232B,
+ KeyboardDeleteRightGlyph = 0x2326,
+ KeyboardPadClearGlyph = 0x2327,
+ KeyboardLeftArrowGlyph = 0x2190,
+ KeyboardRightArrowGlyph = 0x2192,
+ KeyboardUpArrowGlyph = 0x2191,
+ KeyboardDownArrowGlyph = 0x2193,
+ KeyboardPageDownGlyph = 0x21DF,
+ KeyboardPageUpGlyph = 0x21DE,
+ KeyboardNorthwestArrowGlyph = 0x2196,
+ KeyboardSoutheastArrowGlyph = 0x2198,
+ KeyboardEscapeGlyph = 0x238B,
+ KeyboardHelpGlyph = 0x003F,
+ KeyboardUpArrowheadGlyph = 0x2303,
+};
+
+// Special keys
+enum {
+ kSRKeysF1 = 122,
+ kSRKeysF2 = 120,
+ kSRKeysF3 = 99,
+ kSRKeysF4 = 118,
+ kSRKeysF5 = 96,
+ kSRKeysF6 = 97,
+ kSRKeysF7 = 98,
+ kSRKeysF8 = 100,
+ kSRKeysF9 = 101,
+ kSRKeysF10 = 109,
+ kSRKeysF11 = 103,
+ kSRKeysF12 = 111,
+ kSRKeysF13 = 105,
+ kSRKeysF14 = 107,
+ kSRKeysF15 = 113,
+ kSRKeysF16 = 106,
+ kSRKeysF17 = 64,
+ kSRKeysF18 = 79,
+ kSRKeysF19 = 80,
+ kSRKeysSpace = 49,
+ kSRKeysDeleteLeft = 51,
+ kSRKeysDeleteRight = 117,
+ kSRKeysPadClear = 71,
+ kSRKeysLeftArrow = 123,
+ kSRKeysRightArrow = 124,
+ kSRKeysUpArrow = 126,
+ kSRKeysDownArrow = 125,
+ kSRKeysSoutheastArrow = 119,
+ kSRKeysNorthwestArrow = 115,
+ kSRKeysEscape = 53,
+ kSRKeysPageDown = 121,
+ kSRKeysPageUp = 116,
+ kSRKeysReturnR2L = 36,
+ kSRKeysReturn = 76,
+ kSRKeysTabRight = 48,
+ kSRKeysHelp = 114
+};
+
+#pragma mark -
+#pragma mark Macros
+
+// Localization macros, for use in any bundle
+#define SRLoc(key) SRLocalizedString(key, nil)
+#define SRLocalizedString(key, comment) NSLocalizedStringFromTableInBundle(key, @"ShortcutRecorder", [NSBundle bundleForClass: [SRDummyClass class]], comment)
+
+// Image macros, for use in any bundle
+//#define SRImage(name) [[[NSImage alloc] initWithContentsOfFile: [[NSBundle bundleForClass: [self class]] pathForImageResource: name]] autorelease]
+#define SRResIndImage(name) [SRSharedImageProvider supportingImageWithName:name]
+#define SRImage(name) SRResIndImage(name)
+
+//#define SRCommonWriteDebugImagery
+
+// Macros for glyps
+#define SRInt(x) [NSNumber numberWithInteger:x]
+#define SRChar(x) [NSString stringWithFormat: @"%C", x]
+
+// Some default values
+#define ShortcutRecorderEmptyFlags 0
+#define ShortcutRecorderAllFlags ShortcutRecorderEmptyFlags | (NSCommandKeyMask | NSAlternateKeyMask | NSControlKeyMask | NSShiftKeyMask | NSFunctionKeyMask)
+#define ShortcutRecorderEmptyCode -1
+
+// These keys will cancel the recoding mode if not pressed with any modifier
+#define ShortcutRecorderEscapeKey 53
+#define ShortcutRecorderBackspaceKey 51
+#define ShortcutRecorderDeleteKey 117
+
+#pragma mark -
+#pragma mark Getting a string of the key combination
+
+//
+// ################### +- Returns string from keyCode like NSEvent's -characters
+// # EXPLANATORY # | +- Returns string from keyCode like NSEvent's -charactersUsingModifiers
+// # CHART # | | +- Returns fully readable and localized name of modifier (if modifier given)
+// ################### | | | +- Returns glyph of modifier (if modifier given)
+// SRString... X - - X
+// SRReadableString... X - X -
+// SRCharacter... - X - -
+//
+NSString * SRStringForKeyCode( NSInteger keyCode );
+NSString * SRStringForCarbonModifierFlags( NSUInteger flags );
+NSString * SRStringForCarbonModifierFlagsAndKeyCode( NSUInteger flags, NSInteger keyCode );
+NSString * SRStringForCocoaModifierFlags( NSUInteger flags );
+NSString * SRStringForCocoaModifierFlagsAndKeyCode( NSUInteger flags, NSInteger keyCode );
+NSString * SRReadableStringForCarbonModifierFlagsAndKeyCode( NSUInteger flags, NSInteger keyCode );
+NSString * SRReadableStringForCocoaModifierFlagsAndKeyCode( NSUInteger flags, NSInteger keyCode );
+NSString *SRCharacterForKeyCodeAndCarbonFlags(NSInteger keyCode, NSUInteger carbonFlags);
+NSString *SRCharacterForKeyCodeAndCocoaFlags(NSInteger keyCode, NSUInteger cocoaFlags);
+
+#pragma mark Converting between Cocoa and Carbon modifier flags
+
+NSUInteger SRCarbonToCocoaFlags( NSUInteger carbonFlags );
+NSUInteger SRCocoaToCarbonFlags( NSUInteger cocoaFlags );
+
+#pragma mark -
+#pragma mark Animation pace function
+
+CGFloat SRAnimationEaseInOut(CGFloat t);
+
+#pragma mark -
+#pragma mark Inlines
+
+FOUNDATION_STATIC_INLINE KeyCombo SRMakeKeyCombo(NSInteger code, NSUInteger flags) {
+ KeyCombo kc;
+ kc.code = code;
+ kc.flags = flags;
+ return kc;
+}
+
+FOUNDATION_STATIC_INLINE BOOL SRIsSpecialKey(NSInteger keyCode) {
+ return (keyCode == kSRKeysF1 || keyCode == kSRKeysF2 || keyCode == kSRKeysF3 || keyCode == kSRKeysF4 || keyCode == kSRKeysF5 || keyCode == kSRKeysF6 || keyCode == kSRKeysF7 || keyCode == kSRKeysF8 || keyCode == kSRKeysF9 || keyCode == kSRKeysF10 || keyCode == kSRKeysF11 || keyCode == kSRKeysF12 || keyCode == kSRKeysF13 || keyCode == kSRKeysF14 || keyCode == kSRKeysF15 || keyCode == kSRKeysF16 || keyCode == kSRKeysSpace || keyCode == kSRKeysDeleteLeft || keyCode == kSRKeysDeleteRight || keyCode == kSRKeysPadClear || keyCode == kSRKeysLeftArrow || keyCode == kSRKeysRightArrow || keyCode == kSRKeysUpArrow || keyCode == kSRKeysDownArrow || keyCode == kSRKeysSoutheastArrow || keyCode == kSRKeysNorthwestArrow || keyCode == kSRKeysEscape || keyCode == kSRKeysPageDown || keyCode == kSRKeysPageUp || keyCode == kSRKeysReturnR2L || keyCode == kSRKeysReturn || keyCode == kSRKeysTabRight || keyCode == kSRKeysHelp);
+}
+
+#pragma mark -
+#pragma mark Additions
+
+@interface NSAlert( SRAdditions )
++ (NSAlert *) alertWithNonRecoverableError:(NSError *)error;
+@end
+
+#pragma mark -
+#pragma mark Image provider
+
+@interface SRSharedImageProvider : NSObject
++ (NSImage *)supportingImageWithName:(NSString *)name;
+@end
16 Frameworks/ShortcutRecorder.framework/Versions/A/Headers/SRKeyCodeTransformer.h
@@ -0,0 +1,16 @@
+//
+// SRKeyCodeTransformer.h
+// ShortcutRecorder
+//
+// Copyright 2006-2007 Contributors. All rights reserved.
+//
+// License: BSD
+//
+// Contributors:
+// David Dauer
+// Jesper
+// Jamie Kirkpatrick
+
+#import <Cocoa/Cocoa.h>
+
+@interface SRKeyCodeTransformer : NSValueTransformer {} @end
137 Frameworks/ShortcutRecorder.framework/Versions/A/Headers/SRRecorderCell.h
@@ -0,0 +1,137 @@
+//
+// SRRecorderCell.h
+// ShortcutRecorder
+//
+// Copyright 2006-2007 Contributors. All rights reserved.
+//
+// License: BSD
+//
+// Contributors:
+// David Dauer
+// Jesper
+// Jamie Kirkpatrick
+
+#import <Cocoa/Cocoa.h>
+#import "SRCommon.h"
+
+#define SRMinWidth 50
+#define SRMaxHeight 22
+
+#define SRTransitionFPS 30.0f
+#define SRTransitionDuration 0.35f
+//#define SRTransitionDuration 2.35
+#define SRTransitionFrames (SRTransitionFPS*SRTransitionDuration)
+#define SRAnimationAxisIsY YES
+#define ShortcutRecorderNewStyleDrawing
+
+#define SRAnimationOffsetRect(X,Y) (SRAnimationAxisIsY ? NSOffsetRect(X,0.0f,-NSHeight(Y)) : NSOffsetRect(X,NSWidth(Y),0.0f))
+
+@class SRRecorderControl, SRValidator;
+
+enum SRRecorderStyle {
+ SRGradientBorderStyle = 0,
+ SRGreyStyle = 1
+};
+typedef enum SRRecorderStyle SRRecorderStyle;
+
+@interface SRRecorderCell : NSActionCell <NSCoding>
+{
+ NSGradient *recordingGradient;
+ NSString *autosaveName;
+
+ BOOL isRecording;
+ BOOL mouseInsideTrackingArea;
+ BOOL mouseDown;
+
+ SRRecorderStyle style;
+
+ BOOL isAnimating;
+ CGFloat transitionProgress;
+ BOOL isAnimatingNow;
+ BOOL isAnimatingTowardsRecording;
+ BOOL comboJustChanged;
+
+ NSTrackingRectTag removeTrackingRectTag;
+ NSTrackingRectTag snapbackTrackingRectTag;
+
+ KeyCombo keyCombo;
+ BOOL hasKeyChars;
+ NSString *keyChars;
+ NSString *keyCharsIgnoringModifiers;
+
+ NSUInteger allowedFlags;
+ NSUInteger requiredFlags;
+ NSUInteger recordingFlags;
+
+ BOOL allowsKeyOnly;
+ BOOL escapeKeysRecord;
+
+ NSSet *cancelCharacterSet;
+
+ SRValidator *validator;
+
+ IBOutlet id delegate;
+ BOOL globalHotKeys;
+ void *hotKeyModeToken;
+}
+
+- (void)resetTrackingRects;
+
+#pragma mark *** Aesthetics ***
+
++ (BOOL)styleSupportsAnimation:(SRRecorderStyle)style;
+
+- (BOOL)animates;
+- (void)setAnimates:(BOOL)an;
+- (SRRecorderStyle)style;
+- (void)setStyle:(SRRecorderStyle)nStyle;
+
+#pragma mark *** Delegate ***
+
+- (id)delegate;
+- (void)setDelegate:(id)aDelegate;
+
+#pragma mark *** Responder Control ***
+
+- (BOOL)becomeFirstResponder;
+- (BOOL)resignFirstResponder;
+
+#pragma mark *** Key Combination Control ***
+
+- (BOOL)performKeyEquivalent:(NSEvent *)theEvent;
+- (void)flagsChanged:(NSEvent *)theEvent;
+
+- (NSUInteger)allowedFlags;
+- (void)setAllowedFlags:(NSUInteger)flags;
+
+- (NSUInteger)requiredFlags;
+- (void)setRequiredFlags:(NSUInteger)flags;
+
+- (BOOL)allowsKeyOnly;
+- (void)setAllowsKeyOnly:(BOOL)nAllowsKeyOnly escapeKeysRecord:(BOOL)nEscapeKeysRecord;
+- (BOOL)escapeKeysRecord;
+
+- (BOOL)canCaptureGlobalHotKeys;
+- (void)setCanCaptureGlobalHotKeys:(BOOL)inState;
+
+- (KeyCombo)keyCombo;
+- (void)setKeyCombo:(KeyCombo)aKeyCombo;
+
+#pragma mark *** Autosave Control ***
+
+- (NSString *)autosaveName;
+- (void)setAutosaveName:(NSString *)aName;
+
+// Returns the displayed key combination if set
+- (NSString *)keyComboString;
+
+- (NSString *)keyChars;
+- (NSString *)keyCharsIgnoringModifiers;
+
+@end
+
+// Delegate Methods
+@interface NSObject (SRRecorderCellDelegate)
+- (BOOL)shortcutRecorderCell:(SRRecorderCell *)aRecorderCell isKeyCode:(NSInteger)keyCode andFlagsTaken:(NSUInteger)flags reason:(NSString **)aReason;
+- (void)shortcutRecorderCell:(SRRecorderCell *)aRecorderCell keyComboDidChange:(KeyCombo)newCombo;
+@end
74 Frameworks/ShortcutRecorder.framework/Versions/A/Headers/SRRecorderControl.h
@@ -0,0 +1,74 @@
+//
+// SRRecorderControl.h
+// ShortcutRecorder
+//
+// Copyright 2006-2007 Contributors. All rights reserved.
+//
+// License: BSD
+//
+// Contributors:
+// David Dauer
+// Jesper
+// Jamie Kirkpatrick
+
+#import <Cocoa/Cocoa.h>
+#import "SRRecorderCell.h"
+
+@interface SRRecorderControl : NSControl
+{
+ IBOutlet id delegate;
+}
+
+#pragma mark *** Aesthetics ***
+- (BOOL)animates;
+- (void)setAnimates:(BOOL)an;
+- (SRRecorderStyle)style;
+- (void)setStyle:(SRRecorderStyle)nStyle;
+
+#pragma mark *** Delegate ***
+- (id)delegate;
+- (void)setDelegate:(id)aDelegate;
+
+#pragma mark *** Key Combination Control ***
+
+- (NSUInteger)allowedFlags;
+- (void)setAllowedFlags:(NSUInteger)flags;
+
+- (BOOL)allowsKeyOnly;
+- (void)setAllowsKeyOnly:(BOOL)nAllowsKeyOnly escapeKeysRecord:(BOOL)nEscapeKeysRecord;
+- (BOOL)escapeKeysRecord;
+
+- (BOOL)canCaptureGlobalHotKeys;
+- (void)setCanCaptureGlobalHotKeys:(BOOL)inState;
+
+- (NSUInteger)requiredFlags;
+- (void)setRequiredFlags:(NSUInteger)flags;
+
+- (KeyCombo)keyCombo;
+- (void)setKeyCombo:(KeyCombo)aKeyCombo;
+
+- (NSString *)keyChars;
+- (NSString *)keyCharsIgnoringModifiers;
+
+#pragma mark *** Autosave Control ***
+
+- (NSString *)autosaveName;
+- (void)setAutosaveName:(NSString *)aName;
+
+#pragma mark -
+
+// Returns the displayed key combination if set
+- (NSString *)keyComboString;
+
+#pragma mark *** Conversion Methods ***
+
+- (NSUInteger)cocoaToCarbonFlags:(NSUInteger)cocoaFlags;
+- (NSUInteger)carbonToCocoaFlags:(NSUInteger)carbonFlags;
+
+@end
+
+// Delegate Methods
+@interface NSObject (SRRecorderDelegate)
+- (BOOL)shortcutRecorder:(SRRecorderControl *)aRecorder isKeyCode:(NSInteger)keyCode andFlagsTaken:(NSUInteger)flags reason:(NSString **)aReason;
+- (void)shortcutRecorder:(SRRecorderControl *)aRecorder keyComboDidChange:(KeyCombo)newKeyCombo;
+@end
34 Frameworks/ShortcutRecorder.framework/Versions/A/Headers/SRValidator.h
@@ -0,0 +1,34 @@
+//
+// SRValidator.h
+// ShortcutRecorder
+//
+// Copyright 2006-2007 Contributors. All rights reserved.
+//
+// License: BSD
+//
+// Contributors:
+// David Dauer
+// Jesper
+// Jamie Kirkpatrick
+
+#import <Cocoa/Cocoa.h>
+
+@interface SRValidator : NSObject {
+ id delegate;
+}
+
+- (id) initWithDelegate:(id)theDelegate;
+
+- (BOOL) isKeyCode:(NSInteger)keyCode andFlagsTaken:(NSUInteger)flags error:(NSError **)error;
+- (BOOL) isKeyCode:(NSInteger)keyCode andFlags:(NSUInteger)flags takenInMenu:(NSMenu *)menu error:(NSError **)error;
+
+- (id) delegate;
+- (void) setDelegate: (id) theDelegate;
+
+@end
+
+#pragma mark -
+
+@interface NSObject( SRValidation )
+- (BOOL) shortcutValidator:(SRValidator *)validator isKeyCode:(NSInteger)keyCode andFlagsTaken:(NSUInteger)flags reason:(NSString **)aReason;
+@end
15 Frameworks/ShortcutRecorder.framework/Versions/A/Headers/SR_LeopardView.h
@@ -0,0 +1,15 @@
+//
+// SR_LeopardView.h
+// SR Leopard
+//
+// Created by Jesper on 2007-10-19.
+// Copyright 2007 __MyCompanyName__. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+@interface SR_LeopardView : NSView {
+
+}
+
+@end
17 Frameworks/ShortcutRecorder.framework/Versions/A/Headers/ShortcutRecorder.h
@@ -0,0 +1,17 @@
+//
+// ShortcutRecorder.h
+// ShortcutRecorder
+// - 10.5 version only; master framework header
+//
+// Copyright 2007 Contributors. All rights reserved.
+//
+// License: BSD
+//
+// Contributors to this file:
+// Jesper
+
+#import <ShortcutRecorder/SRCommon.h>
+#import <ShortcutRecorder/SRKeyCodeTransformer.h>
+#import <ShortcutRecorder/SRValidator.h>
+#import <ShortcutRecorder/SRRecorderCell.h>
+#import <ShortcutRecorder/SRRecorderControl.h>
20 Frameworks/ShortcutRecorder.framework/Versions/A/Resources/Info.plist
@@ -0,0 +1,20 @@
+<?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>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>ShortcutRecorder</string>
+ <key>CFBundleIdentifier</key>
+ <string>net.wafflesoftware.ShortcutRecorder.framework.Leopard</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+</dict>
+</plist>
26 ...tcutRecorder.framework/Versions/A/Resources/ShortcutRecorder.ibplugin/Contents/Info.plist
@@ -0,0 +1,26 @@
+<?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>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>ShortcutRecorder</string>
+ <key>CFBundleIdentifier</key>
+ <string>net.wafflesoftware.ShortcutRecorder.IB.Leopard</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>ShortcutRecorder</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>NSPrincipalClass</key>
+ <string>SR_Leopard</string>
+</dict>
+</plist>
BIN ....framework/Versions/A/Resources/ShortcutRecorder.ibplugin/Contents/MacOS/ShortcutRecorder
Binary file not shown.
BIN .../A/Resources/ShortcutRecorder.ibplugin/Contents/Resources/English.lproj/InfoPlist.strings
Binary file not shown.
BIN ...ources/ShortcutRecorder.ibplugin/Contents/Resources/English.lproj/SR_LeopardInspector.nib
Binary file not shown.
BIN ...esources/ShortcutRecorder.ibplugin/Contents/Resources/English.lproj/SR_LeopardLibrary.nib
Binary file not shown.
9 ...Resources/ShortcutRecorder.ibplugin/Contents/Resources/SRRecorderControl.classdescription
@@ -0,0 +1,9 @@
+{
+ Actions = {
+ };
+ Outlets = {
+ delegate = id;
+ };
+ ClassName = SRRecorderControl;
+ SuperClass = NSControl;
+}
BIN Frameworks/ShortcutRecorder.framework/Versions/A/ShortcutRecorder
Binary file not shown.
1 Frameworks/ShortcutRecorder.framework/Versions/Current
2 LICENSE.txt
@@ -0,0 +1,2 @@
+SGHotKeyCenter Copyright (c) 2009 Second Gear LLC, Justin Williams Based on PTHotKeyCenter. Copyright (c) 2003-2004 Rogue Amoeba Software LLC, Quentin D. Carnicelli, Finlay Dobbie, Vincent Pottier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so.
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 README.markdown
@@ -0,0 +1,37 @@
+SGHotKeyLib - Hot Keys For Mac OS X Leopard and beyond
+=========================
+
+* Maintained by [Justin Williams](http://carpeaqua.com)
+* Originally by Quentin D. Carnicelli
+
+What is SGHotKeyLib?
+==================
+
+SGHotKeysLib is a fork of Quentin D. Carnicelli's excellent [PTHotKeysLib](http://rogueamoeba.com/sources/) library for registering shortcut keys on Mac OS X.
+
+PTHotKeysLib has served us well for many years, but as I was working on upgrading my applications to run natively in 64 bit I was running into issues. The original code itself used many deprecated methods, used 32 bit intger types, etc. As I fixed those issues, my OCD started to get the best of me and I started reformatting and rewriting portions of the code using modern Objective-C practices and paradigms.
+
+SGHotKeysLib does the following:
+
+* Adopts Objective-C 2.0 syntax, properties and other language features (suck it dot syntax haters)
+* Uses Leopard's Text Input Sources (no patching required)
+* Runs natively in 64 bit
+* Requires Garbage Collection
+* Removes legacy code support (no more checking for 10.1, no more Project Builder)
+* Cleans up the code formatting & variable declarations
+* Puts the code on Github for hot forking action
+
+What's in the box?
+==================
+
+SGHotKeysLib includes:
+
+* The SGHotKeySLib itself
+* A sample application that demonstrates how it works.
+
+The sample uses a custom-built version of the [ShortcutRecorder](http://code.google.com/p/shortcutrecorder/) framework to demonstrate setting a hot key.
+
+Help Me!
+==================
+
+SGHotKeysLib is a modernization of a piece of code many of us have been using for several years, and I'm sure it could be improved even more. If you have ideas for how to do that, please fork away.
32 Resources/Info.plist
@@ -0,0 +1,32 @@
+<?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>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.secondgear.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>${MACOSX_DEPLOYMENT_TARGET}</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
361 SGHotKeyCenter.xcodeproj/project.pbxproj
@@ -0,0 +1,361 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1DDD58140DA1D0A300B32029 /* MainMenu.xib */; };
+ 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
+ 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+ D03756F6101D675B007A7D40 /* SGKeyCodes.plist in Resources */ = {isa = PBXBuildFile; fileRef = D03756F4101D675B007A7D40 /* SGKeyCodes.plist */; };
+ D03757D8101D6FD0007A7D40 /* ShortcutRecorder.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03757D7101D6FD0007A7D40 /* ShortcutRecorder.framework */; };
+ D03757DC101D6FE8007A7D40 /* ShortcutRecorder.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = D03757D7101D6FD0007A7D40 /* ShortcutRecorder.framework */; };
+ D0764512101E79F500DAE20D /* SGHotKeyCenterAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D0764511101E79F500DAE20D /* SGHotKeyCenterAppDelegate.m */; };
+ D0764532101E7A6100DAE20D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D0764530101E7A6100DAE20D /* main.m */; };
+ D0764638101E843900DAE20D /* SGHotKey.m in Sources */ = {isa = PBXBuildFile; fileRef = D0764631101E843900DAE20D /* SGHotKey.m */; };
+ D0764639101E843900DAE20D /* SGHotKeyCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = D0764633101E843900DAE20D /* SGHotKeyCenter.m */; };
+ D076463A101E843900DAE20D /* SGKeyCodeTranslator.m in Sources */ = {isa = PBXBuildFile; fileRef = D0764635101E843900DAE20D /* SGKeyCodeTranslator.m */; };
+ D076463B101E843900DAE20D /* SGKeyCombo.m in Sources */ = {isa = PBXBuildFile; fileRef = D0764637101E843900DAE20D /* SGKeyCombo.m */; };
+ D0ABD262101D374900E5F733 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0ABD261101D374900E5F733 /* Carbon.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ D03757E3101D6FF2007A7D40 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ D03757DC101D6FE8007A7D40 /* ShortcutRecorder.framework in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+ 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
+ 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
+ 1DDD58150DA1D0A300B32029 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainMenu.xib; sourceTree = "<group>"; };
+ 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
+ 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
+ 8D1107320486CEB800E47090 /* SGHotKeyCenter.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SGHotKeyCenter.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ D03756F5101D675B007A7D40 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = English; path = English.lproj/SGKeyCodes.plist; sourceTree = "<group>"; };
+ D03757D7101D6FD0007A7D40 /* ShortcutRecorder.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ShortcutRecorder.framework; path = Frameworks/ShortcutRecorder.framework; sourceTree = "<group>"; };
+ D0764510101E79F500DAE20D /* SGHotKeyCenterAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SGHotKeyCenterAppDelegate.h; path = Source/SGHotKeyCenterAppDelegate.h; sourceTree = "<group>"; };
+ D0764511101E79F500DAE20D /* SGHotKeyCenterAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SGHotKeyCenterAppDelegate.m; path = Source/SGHotKeyCenterAppDelegate.m; sourceTree = "<group>"; };
+ D0764520101E7A3300DAE20D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Resources/Info.plist; sourceTree = "<group>"; };
+ D0764530101E7A6100DAE20D /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Source/main.m; sourceTree = "<group>"; };
+ D0764531101E7A6100DAE20D /* Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Prefix.pch; path = Source/Prefix.pch; sourceTree = "<group>"; };
+ D0764630101E843900DAE20D /* SGHotKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SGHotKey.h; path = SGHotKeysLib/SGHotKey.h; sourceTree = "<group>"; };
+ D0764631101E843900DAE20D /* SGHotKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SGHotKey.m; path = SGHotKeysLib/SGHotKey.m; sourceTree = "<group>"; };
+ D0764632101E843900DAE20D /* SGHotKeyCenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SGHotKeyCenter.h; path = SGHotKeysLib/SGHotKeyCenter.h; sourceTree = "<group>"; };
+ D0764633101E843900DAE20D /* SGHotKeyCenter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SGHotKeyCenter.m; path = SGHotKeysLib/SGHotKeyCenter.m; sourceTree = "<group>"; };
+ D0764634101E843900DAE20D /* SGKeyCodeTranslator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SGKeyCodeTranslator.h; path = SGHotKeysLib/SGKeyCodeTranslator.h; sourceTree = "<group>"; };
+ D0764635101E843900DAE20D /* SGKeyCodeTranslator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SGKeyCodeTranslator.m; path = SGHotKeysLib/SGKeyCodeTranslator.m; sourceTree = "<group>"; };
+ D0764636101E843900DAE20D /* SGKeyCombo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SGKeyCombo.h; path = SGHotKeysLib/SGKeyCombo.h; sourceTree = "<group>"; };
+ D0764637101E843900DAE20D /* SGKeyCombo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SGKeyCombo.m; path = SGHotKeysLib/SGKeyCombo.m; sourceTree = "<group>"; };
+ D0ABD261101D374900E5F733 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8D11072E0486CEB800E47090 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D03757D8101D6FD0007A7D40 /* ShortcutRecorder.framework in Frameworks */,
+ 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
+ D0ABD262101D374900E5F733 /* Carbon.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 080E96DDFE201D6D7F000001 /* Classes */ = {
+ isa = PBXGroup;
+ children = (
+ D0764510101E79F500DAE20D /* SGHotKeyCenterAppDelegate.h */,
+ D0764511101E79F500DAE20D /* SGHotKeyCenterAppDelegate.m */,
+ D0ABD1B2101D28E300E5F733 /* SGHotKeyLib */,
+ );
+ name = Classes;
+ sourceTree = "<group>";
+ };
+ 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ D03757D7101D6FD0007A7D40 /* ShortcutRecorder.framework */,
+ 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */,
+ );
+ name = "Linked Frameworks";
+ sourceTree = "<group>";
+ };
+ 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 29B97324FDCFA39411CA2CEA /* AppKit.framework */,
+ 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */,
+ 29B97325FDCFA39411CA2CEA /* Foundation.framework */,
+ );
+ name = "Other Frameworks";
+ sourceTree = "<group>";
+ };
+ 19C28FACFE9D520D11CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8D1107320486CEB800E47090 /* SGHotKeyCenter.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 29B97314FDCFA39411CA2CEA /* SGHotKeyCenter */ = {
+ isa = PBXGroup;
+ children = (
+ 080E96DDFE201D6D7F000001 /* Classes */,
+ 29B97315FDCFA39411CA2CEA /* Other Sources */,
+ 29B97317FDCFA39411CA2CEA /* Resources */,
+ 29B97323FDCFA39411CA2CEA /* Frameworks */,
+ 19C28FACFE9D520D11CA2CBB /* Products */,
+ D0ABD261101D374900E5F733 /* Carbon.framework */,
+ );
+ name = SGHotKeyCenter;
+ sourceTree = "<group>";
+ };
+ 29B97315FDCFA39411CA2CEA /* Other Sources */ = {
+ isa = PBXGroup;
+ children = (
+ D0764530101E7A6100DAE20D /* main.m */,
+ D0764531101E7A6100DAE20D /* Prefix.pch */,
+ );
+ name = "Other Sources";
+ sourceTree = "<group>";
+ };
+ 29B97317FDCFA39411CA2CEA /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ D0764520101E7A3300DAE20D /* Info.plist */,
+ 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
+ 1DDD58140DA1D0A300B32029 /* MainMenu.xib */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ 29B97323FDCFA39411CA2CEA /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */,
+ 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ D0ABD1B2101D28E300E5F733 /* SGHotKeyLib */ = {
+ isa = PBXGroup;
+ children = (
+ D0764630101E843900DAE20D /* SGHotKey.h */,
+ D0764631101E843900DAE20D /* SGHotKey.m */,
+ D0764632101E843900DAE20D /* SGHotKeyCenter.h */,
+ D0764633101E843900DAE20D /* SGHotKeyCenter.m */,
+ D0764634101E843900DAE20D /* SGKeyCodeTranslator.h */,
+ D0764635101E843900DAE20D /* SGKeyCodeTranslator.m */,
+ D0764636101E843900DAE20D /* SGKeyCombo.h */,
+ D0764637101E843900DAE20D /* SGKeyCombo.m */,
+ D03756F4101D675B007A7D40 /* SGKeyCodes.plist */,
+ );
+ name = SGHotKeyLib;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8D1107260486CEB800E47090 /* SGHotKeyCenter */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "SGHotKeyCenter" */;
+ buildPhases = (
+ 8D1107290486CEB800E47090 /* Resources */,
+ 8D11072C0486CEB800E47090 /* Sources */,
+ 8D11072E0486CEB800E47090 /* Frameworks */,
+ D03757E3101D6FF2007A7D40 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = SGHotKeyCenter;
+ productInstallPath = "$(HOME)/Applications";
+ productName = SGHotKeyCenter;
+ productReference = 8D1107320486CEB800E47090 /* SGHotKeyCenter.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 29B97313FDCFA39411CA2CEA /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "SGHotKeyCenter" */;
+ compatibilityVersion = "Xcode 3.1";
+ hasScannedForEncodings = 1;
+ mainGroup = 29B97314FDCFA39411CA2CEA /* SGHotKeyCenter */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 8D1107260486CEB800E47090 /* SGHotKeyCenter */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 8D1107290486CEB800E47090 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */,
+ 1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */,
+ D03756F6101D675B007A7D40 /* SGKeyCodes.plist in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8D11072C0486CEB800E47090 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D0764512101E79F500DAE20D /* SGHotKeyCenterAppDelegate.m in Sources */,
+ D0764532101E7A6100DAE20D /* main.m in Sources */,
+ D0764638101E843900DAE20D /* SGHotKey.m in Sources */,
+ D0764639101E843900DAE20D /* SGHotKeyCenter.m in Sources */,
+ D076463A101E843900DAE20D /* SGKeyCodeTranslator.m in Sources */,
+ D076463B101E843900DAE20D /* SGKeyCombo.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 089C165DFE840E0CC02AAC07 /* English */,
+ );
+ name = InfoPlist.strings;
+ sourceTree = "<group>";
+ };
+ 1DDD58140DA1D0A300B32029 /* MainMenu.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 1DDD58150DA1D0A300B32029 /* English */,
+ );
+ name = MainMenu.xib;
+ sourceTree = "<group>";
+ };
+ D03756F4101D675B007A7D40 /* SGKeyCodes.plist */ = {
+ isa = PBXVariantGroup;
+ children = (
+ D03756F5101D675B007A7D40 /* English */,
+ );
+ name = SGKeyCodes.plist;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ C01FCF4B08A954540054247B /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/Frameworks\"",
+ );
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = Source/Prefix.pch;
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ INFOPLIST_FILE = Resources/Info.plist;
+ INSTALL_PATH = "$(HOME)/Applications";
+ PRODUCT_NAME = SGHotKeyCenter;
+ };
+ name = Debug;
+ };
+ C01FCF4C08A954540054247B /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/Frameworks\"",
+ );
+ GCC_MODEL_TUNING = G5;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = Source/Prefix.pch;
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ INFOPLIST_FILE = Resources/Info.plist;
+ INSTALL_PATH = "$(HOME)/Applications";
+ PRODUCT_NAME = SGHotKeyCenter;
+ };
+ name = Release;
+ };
+ C01FCF4F08A954540054247B /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = required;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ };
+ name = Debug;
+ };
+ C01FCF5008A954540054247B /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_GC = required;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ PREBINDING = NO;
+ SDKROOT = macosx10.5;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "SGHotKeyCenter" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C01FCF4B08A954540054247B /* Debug */,
+ C01FCF4C08A954540054247B /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ C01FCF4E08A954540054247B /* Build configuration list for PBXProject "SGHotKeyCenter" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C01FCF4F08A954540054247B /* Debug */,
+ C01FCF5008A954540054247B /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
+}
35 SGHotKeysLib/SGHotKey.h
@@ -0,0 +1,35 @@
+//
+// SGHotKey.h
+// SGHotKeyCenter
+//
+// Created by Justin Williams on 7/26/09.
+// Copyright 2009 Second Gear. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import <Carbon/Carbon.h>
+#import "SGKeyCombo.h"
+
+@interface SGHotKey : NSObject {
+ NSString *identifier;
+ NSString *name;
+
+ SGKeyCombo *keyCombo;
+ id target;
+ SEL action;
+
+ EventHotKeyID hotKeyID;
+}
+
+@property (nonatomic, copy) NSString *identifier;
+@property (nonatomic, copy) NSString *name;
+@property (nonatomic, retain) SGKeyCombo *keyCombo;
+@property (nonatomic, assign) id target;
+@property (nonatomic, assign) SEL action;
+@property (nonatomic, assign) EventHotKeyID hotKeyID;
+
+- (id)initWithIdentifier:(id)theIdentifier keyCombo:(SGKeyCombo *)theCombo target:(id)theTarget action:(SEL)theAction;
+- (BOOL)matchesHotKeyID:(EventHotKeyID)theKeyID;
+- (void)invoke;
+
+@end
59 SGHotKeysLib/SGHotKey.m
@@ -0,0 +1,59 @@
+//
+// SGHotKey.m
+// SGHotKeyCenter
+//
+// Created by Justin Williams on 7/26/09.
+// Copyright 2009 Second Gear. All rights reserved.
+//
+
+#import "SGHotKey.h"
+#import "SGKeyCombo.h"
+
+@implementation SGHotKey
+
+@synthesize identifier;
+@synthesize name;
+@synthesize keyCombo;
+@synthesize target;
+@synthesize action;
+@synthesize hotKeyID;
+
+- (id)init {
+ return [self initWithIdentifier:nil keyCombo:nil target:nil action:nil];
+}
+
+- (id)initWithIdentifier:(id)theIdentifier keyCombo:(SGKeyCombo *)theCombo target:(id)theTarget action:(SEL)theAction {
+ if (self = [super init]) {
+ self.identifier = theIdentifier;
+ self.keyCombo = theCombo;
+ self.target = theTarget;
+ self.action = theAction;
+ }
+
+ return self;
+}
+
+- (BOOL)matchesHotKeyID:(EventHotKeyID)theKeyID {
+ return (hotKeyID.id == theKeyID.id) && (hotKeyID.signature == theKeyID.signature);
+}
+
+- (void)invoke {
+ [self.target performSelector:self.action withObject:self];
+}
+
+- (void)setKeyCombo:(SGKeyCombo *)theKeyCombo {
+ if (theKeyCombo == nil)
+ theKeyCombo = [SGKeyCombo clearKeyCombo];
+
+ keyCombo = theKeyCombo;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat: @"<%@: %@, %@>",
+ NSStringFromClass([self class]),
+ self.identifier,
+ self.keyCombo];
+}
+
+
+@end
26 SGHotKeysLib/SGHotKeyCenter.h
@@ -0,0 +1,26 @@
+//
+// SGHotKeyCenter.h
+// SGHotKeyCenter
+//
+// Created by Justin Williams on 7/26/09.
+// Copyright 2009 Second Gear. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+@class SGHotKey;
+
+@interface SGHotKeyCenter : NSObject {
+ NSMutableDictionary *hotKeys; // Keys are NSValue of EventHotKeyRef
+ BOOL eventHandlerInstalled;
+}
+
++ (SGHotKeyCenter *)sharedCenter;
+
+- (BOOL)registerHotKey:(SGHotKey *)theHotKey;
+- (void)unregisterHotKey:(SGHotKey *)theHotKey;
+
+- (NSArray *)allHotKeys;
+- (SGHotKey *)hotKeyWithIdentifier:(id)theIdentifier;
+
+@end
208 SGHotKeysLib/SGHotKeyCenter.m
@@ -0,0 +1,208 @@
+//
+// SGHotKeyCenter.m
+// SGHotKeyCenter
+//
+// Created by Justin Williams on 7/26/09.
+// Copyright 2009 Second Gear. All rights reserved.
+//
+
+#import <Carbon/Carbon.h>
+#import "SGHotKeyCenter.h"
+#import "SGHotKey.h"
+#import "SGKeyCombo.h"
+
+OSType const kHotKeySignature = 'SGHk';
+
+@interface SGHotKeyCenter ()
+- (SGHotKey *)_hotKeyForCarbonHotKey:(EventHotKeyRef)carbonHotKey;
+- (EventHotKeyRef)_carbonHotKeyForHotKey:(SGHotKey *)hotKey;
+
+- (void)_updateEventHandler;
+- (void)_hotKeyDown: (SGHotKey *)hotKey;
+- (void)_hotKeyUp: (SGHotKey *)hotKey;
+static OSStatus hotKeyEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void* refCon );
+@end
+
+
+@implementation SGHotKeyCenter
+
++ (SGHotKeyCenter *)sharedCenter {
+ static SGHotKeyCenter *sharedCenter = nil;
+
+ if (sharedCenter == nil) {
+ sharedCenter = [[self alloc] init];
+ }
+
+ return sharedCenter;
+}
+
+- (id)init {
+ if (self = [super init]) {
+ hotKeys = [[NSMutableDictionary alloc] init];
+ }
+
+ return self;
+}
+
+- (BOOL)registerHotKey:(SGHotKey *)theHotKey {
+ OSStatus error;
+ EventHotKeyID hotKeyID;
+ EventHotKeyRef carbonHotKey;
+ NSValue *key = nil;
+
+ if ([[self allHotKeys] containsObject:theHotKey])
+ [self unregisterHotKey:theHotKey];
+
+ if (![[theHotKey keyCombo] isValidHotKeyCombo])
+ return YES;
+
+ static UInt32 currentId = 0;
+ hotKeyID.signature = kHotKeySignature;
+ hotKeyID.id = ++currentId;
+
+ theHotKey.hotKeyID = hotKeyID;
+
+ error = RegisterEventHotKey(theHotKey.keyCombo.keyCode,
+ theHotKey.keyCombo.modifiers,
+ hotKeyID,
+ GetEventDispatcherTarget(),
+ 0,
+ &carbonHotKey);
+
+ if (error)
+ return NO;
+
+ key = [NSValue valueWithPointer:carbonHotKey];
+
+ if (theHotKey && key)
+ [hotKeys setObject:theHotKey forKey:key];
+
+ [self _updateEventHandler];
+
+ return YES;
+}
+
+
+- (void)unregisterHotKey:(SGHotKey *)theHotKey {
+ EventHotKeyRef carbonHotKey;
+ NSValue *key = nil;
+
+ if (![[self allHotKeys] containsObject:theHotKey])
+ return;
+
+ carbonHotKey = [self _carbonHotKeyForHotKey:theHotKey];
+ NSAssert(carbonHotKey != nil, @"");
+
+ UnregisterEventHotKey(carbonHotKey);
+
+ key = [NSValue valueWithPointer:carbonHotKey];
+ [hotKeys removeObjectForKey:key];
+
+ [self _updateEventHandler];
+}
+
+- (NSArray *)allHotKeys {
+ return [hotKeys allValues];
+}
+
+
+- (SGHotKey *)hotKeyWithIdentifier:(id)theIdentifier {
+ if (!theIdentifier)
+ return nil;
+
+ for (SGHotKey *hotKey in [self allHotKeys]) {
+ if([[hotKey identifier] isEqual:theIdentifier] )
+ return hotKey;
+ }
+
+ return nil;
+}
+
+- (OSStatus)sendCarbonEvent:(EventRef)event {
+ OSStatus error;
+ EventHotKeyID hotKeyID;
+ SGHotKey *hotKey = nil;
+
+ NSAssert(GetEventClass(event) == kEventClassKeyboard, @"Unknown event class");
+
+ error = GetEventParameter(event,
+ kEventParamDirectObject,
+ typeEventHotKeyID,
+ nil,
+ sizeof(EventHotKeyID),
+ nil,
+ &hotKeyID);
+ if (error)
+ return error;
+
+ NSAssert(hotKeyID.signature == kHotKeySignature, @"Invalid hot key id");
+ NSAssert(hotKeyID.id != 0, @"Invalid hot key id");
+
+ for (SGHotKey *thisHotKey in [self allHotKeys]) {
+ if ([thisHotKey matchesHotKeyID:hotKeyID]) {
+ hotKey = thisHotKey;
+ break;
+ }
+ }
+
+ switch (GetEventKind(event)) {
+ case kEventHotKeyPressed:
+ [self _hotKeyDown:hotKey];
+ break;
+
+ case kEventHotKeyReleased:
+ [self _hotKeyUp:hotKey];
+ break;
+
+ default:
+ NSAssert(0, @"Unknown event kind");
+ break;
+ }
+
+ return noErr;
+}
+
+- (SGHotKey *)_hotKeyForCarbonHotKey:(EventHotKeyRef)carbonHotKey {
+ NSValue *key = [NSValue valueWithPointer:carbonHotKey];
+ return [hotKeys objectForKey:key];
+}
+
+- (EventHotKeyRef)_carbonHotKeyForHotKey:(SGHotKey *)hotKey {
+ NSArray *values;
+ NSValue *value;
+
+ values = [hotKeys allKeysForObject:hotKey];
+ NSAssert([values count] == 1, @"Failed to find Carbon Hotkey for SGHotKey");
+
+ value = [values lastObject];
+
+ return (EventHotKeyRef)[value pointerValue];
+}
+
+- (void)_updateEventHandler {
+ if ([hotKeys count] && eventHandlerInstalled == NO) {
+ EventTypeSpec eventSpec[2] = {
+ { kEventClassKeyboard, kEventHotKeyPressed },
+ { kEventClassKeyboard, kEventHotKeyReleased }
+ };
+
+ InstallEventHandler(GetEventDispatcherTarget(),
+ (EventHandlerProcPtr)hotKeyEventHandler,
+ 2, eventSpec, nil, nil);
+
+ eventHandlerInstalled = YES;
+ }
+}
+
+- (void)_hotKeyDown:(SGHotKey *)hotKey {
+ [hotKey invoke];
+}
+
+- (void)_hotKeyUp:(SGHotKey *)hotKey {
+ // Nothing!
+}
+
+static OSStatus hotKeyEventHandler(EventHandlerCallRef theHandlerRef, EventRef theEvent, void *userData ) {
+ return [[SGHotKeyCenter sharedCenter] sendCarbonEvent:theEvent];
+}
+@end
28 SGHotKeysLib/SGKeyCodeTranslator.h
@@ -0,0 +1,28 @@
+//
+// SGKeyCodeTranslator.h
+// SGHotKeyCenter
+//
+// Created by Justin Williams on 7/26/09.
+// Copyright 2009 Second Gear. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#include <Carbon/Carbon.h>
+#include <CoreServices/CoreServices.h>
+
+
+@interface SGKeyCodeTranslator : NSObject {
+ TISInputSourceRef keyboardLayout;
+ const UCKeyboardLayout *keyboardLayoutData;
+ NSUInteger keyTranslateState;
+ UInt32 deadKeyState;
+}
+
+@property (nonatomic, assign) TISInputSourceRef keyboardLayout;
+
++ (id)currentTranslator;
+
+- (id)initWithKeyboardLayout:(TISInputSourceRef)theLayout;
+- (NSString *)translateKeyCode:(short)theKeyCode;
+
+@end
56 SGHotKeysLib/SGKeyCodeTranslator.m
@@ -0,0 +1,56 @@
+//
+// SGKeyCodeTranslator.m
+// SGHotKeyCenter
+//
+// Created by Justin Williams on 7/26/09.
+// Copyright 2009 Second Gear. All rights reserved.
+//
+
+#import "SGKeyCodeTranslator.h"
+
+
+@implementation SGKeyCodeTranslator
+
+@synthesize keyboardLayout;
+
++ (id)currentTranslator {
+ static SGKeyCodeTranslator *currentTranslator = nil;
+ TISInputSourceRef currentKeyboardLayout = TISCopyCurrentKeyboardInputSource();
+
+ if (currentTranslator == nil || [currentTranslator keyboardLayout] != currentKeyboardLayout) {
+ currentTranslator = [[SGKeyCodeTranslator alloc] initWithKeyboardLayout:currentKeyboardLayout];
+ }
+
+ return currentTranslator;
+}
+
+- (id)initWithKeyboardLayout:(TISInputSourceRef)theLayout {
+ if ((self = [super init]) != nil) {
+ keyboardLayout = theLayout;
+ CFDataRef uchr = TISGetInputSourceProperty(keyboardLayout, kTISPropertyUnicodeKeyLayoutData);
+ keyboardLayoutData = (const UCKeyboardLayout *)CFDataGetBytePtr(uchr);
+ }
+
+ return self;
+}
+
+
+- (NSString *)translateKeyCode:(short)keyCode {
+ UniCharCount maxStringLength = 4, actualStringLength;
+ UniChar unicodeString[4];
+
+ UCKeyTranslate(keyboardLayoutData,
+ keyCode,
+ kUCKeyActionDisplay,
+ 0,
+ LMGetKbdType(),
+ kUCKeyTranslateNoDeadKeysBit,
+ &deadKeyState,
+ maxStringLength,
+ &actualStringLength,
+ unicodeString);
+
+ return [NSString stringWithCharacters:unicodeString length:1];
+}
+
+@end
38 SGHotKeysLib/SGKeyCombo.h
@@ -0,0 +1,38 @@
+//
+// SGKeyCombo.h
+// SGHotKeyCenter
+//
+// Created by Justin Williams on 7/26/09.
+// Copyright 2009 Second Gear. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+@interface SGKeyCombo : NSObject {
+ NSInteger keyCode;
+ NSInteger modifiers;
+}
+
+@property (nonatomic, assign) NSInteger keyCode;
+@property (nonatomic, assign) NSInteger modifiers;
+
++ (id)clearKeyCombo;
++ (id)keyComboWithKeyCode:(NSInteger)theKeyCode modifiers:(NSInteger)theModifiers;
+- (id)initWithKeyCode:(NSInteger)theKeyCode modifiers:(NSInteger)theModifiers;
+
+- (id)initWithPlistRepresentation:(id)thePlist;
+- (id)plistRepresentation;
+
+- (BOOL)isEqual:(SGKeyCombo *)theCombo;
+
+- (BOOL)isClearCombo;
+- (BOOL)isValidHotKeyCombo;
+
+@end
+
+@interface SGKeyCombo (UserDisplayAdditions)
+- (NSString *)description;
+- (NSString *)keyCodeString;
+- (NSUInteger)modifierMask;
+@end
+
209 SGHotKeysLib/SGKeyCombo.m
@@ -0,0 +1,209 @@
+//
+// SGKeyCombo.m
+// SGHotKeyCenter
+//
+// Created by Justin Williams on 7/26/09.
+// Copyright 2009 Second Gear. All rights reserved.
+//
+
+#import <Carbon/Carbon.h>
+#import "SGKeyCombo.h"
+#import "SGKeyCodeTranslator.h"
+
+NSString * const kKeyCodeDictionaryKey = @"keyCode";
+NSString * const kModifiersDictionaryKey = @"modifiers";
+
+@implementation SGKeyCombo
+
+@synthesize keyCode;
+@synthesize modifiers;
+
++ (id)clearKeyCombo {
+ return [self keyComboWithKeyCode:-1 modifiers:-1];
+}
+
++ (id)keyComboWithKeyCode:(NSInteger)theKeyCode modifiers:(NSInteger)theModifiers {
+ return [[self alloc] initWithKeyCode:theKeyCode modifiers:theModifiers];
+}
+
+
+- (id)initWithKeyCode:(NSInteger)theKeyCode modifiers:(NSInteger)theModifiers {
+ if (self = [super init]) {
+ keyCode = theKeyCode;
+ modifiers = theModifiers;
+ }
+
+ return self;
+}
+
+- (id)initWithPlistRepresentation:(id)thePlist {
+ NSInteger theKeyCode;
+ NSInteger theModifiers;
+
+ if (!thePlist || ![thePlist count]) {
+ theKeyCode = -1;
+ theModifiers = -1;
+ } else {
+ theKeyCode = [[thePlist objectForKey:kKeyCodeDictionaryKey] integerValue];
+ if (theKeyCode <= 0) theKeyCode = -1;
+
+ theModifiers = [[thePlist objectForKey:kModifiersDictionaryKey] integerValue];
+ if (theModifiers <= 0) theModifiers = -1;
+ }
+
+ return [self initWithKeyCode:theKeyCode modifiers:theModifiers];
+}
+
+
+- (id)plistRepresentation {
+ return [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithInteger:self.keyCode], kKeyCodeDictionaryKey,
+ [NSNumber numberWithInteger:self.modifiers], kModifiersDictionaryKey,
+ nil];
+}
+
+- (BOOL)isEqual:(SGKeyCombo *)theCombo {
+ return self.keyCode == theCombo.keyCode && self.modifiers == theCombo.modifiers;
+
+}
+
+- (BOOL)isClearCombo {
+ return keyCode == -1 && modifiers == -1;
+}
+
+
+- (BOOL)isValidHotKeyCombo {
+ return keyCode >= 0 && modifiers > 0;
+}
+
++ (NSString*)_stringForModifiers:(NSInteger)theModifiers {
+ static unichar modToChar[4][2] =
+ {
+ { cmdKey, kCommandUnicode },
+ { optionKey, kOptionUnicode },
+ { controlKey, kControlUnicode },
+ { shiftKey, kShiftUnicode }
+ };
+
+ NSString *string = [NSString string];
+ long i;
+
+ for( i = 0; i < 4; i++ ) {
+ if (theModifiers & modToChar[i][0] )
+ string = [string stringByAppendingString: [NSString stringWithCharacters: &modToChar[i][1] length: 1]];
+ }
+
+ return string;
+}
+
++ (NSDictionary *)_keyCodesDictionary {
+ static NSDictionary* keyCodes = nil;
+
+ if(keyCodes == nil) {
+ NSString *path;
+ NSString *contents;
+ NSError *error;
+
+ path = [[NSBundle bundleForClass:self] pathForResource:@"SGKeyCodes" ofType:@"plist"];
+ contents = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
+ NSAssert(contents != nil, @"Contents of SGKeyCodes is nil");
+ keyCodes = [contents propertyList];
+ }
+
+ return keyCodes;
+}
+
++ (NSString*)_stringForKeyCode: (short)theKeyCode legacyKeyCodeMap: (NSDictionary*)theDictionary {
+ id key;
+ NSString *string;
+
+ key = [NSString stringWithFormat:@"%d", theKeyCode];
+ string = [theDictionary objectForKey:key];
+
+ if( !string )
+ string = [NSString stringWithFormat:@"%X", theKeyCode];
+
+ return string;
+}
+
++ (NSString*)_stringForKeyCode:(short)theKeyCode newKeyCodeMap:(NSDictionary*)theDictionary {
+ NSString *result;
+ NSString *keyCodeString;
+ NSDictionary *unmappedKeys;
+ NSArray *padKeys;
+
+ keyCodeString = [NSString stringWithFormat: @"%d", theKeyCode];
+
+ //Handled if its not handled by translator
+ unmappedKeys = [theDictionary objectForKey:@"unmappedKeys"];
+ result = [unmappedKeys objectForKey:keyCodeString];
+ if( result )
+ return result;
+
+ //Translate it
+ result = [[[SGKeyCodeTranslator currentTranslator] translateKeyCode:theKeyCode] uppercaseString];
+
+ //Handle if its a key-pad key
+ padKeys = [theDictionary objectForKey:@"padKeys"];
+ if([padKeys indexOfObject:keyCodeString] != NSNotFound) {
+ result = [NSString stringWithFormat:@"%@ %@", [theDictionary objectForKey:@"padKeyString"], result];
+ }
+
+ return result;
+}
+
++ (NSString *)_stringForKeyCode:(short)theKeyCode {
+ NSDictionary *dict;
+
+ dict = [self _keyCodesDictionary];
+ if([[dict objectForKey:@"version"] integerValue] <= 0)
+ return [self _stringForKeyCode:theKeyCode legacyKeyCodeMap:dict];
+
+ return [self _stringForKeyCode:theKeyCode newKeyCodeMap:dict];
+}
+
+- (NSString*)keyCodeString {
+ // special case: the modifiers for the "clear" key are 0x0
+ if ( [self isClearCombo] ) return @"";
+
+ return [[self class] _stringForKeyCode:self.keyCode];
+}
+
+- (NSUInteger)modifierMask {
+ // special case: the modifiers for the "clear" key are 0x0
+ if ([self isClearCombo]) return 0;
+
+ static NSUInteger modToChar[4][2] =
+ {
+ { cmdKey, NSCommandKeyMask },
+ { optionKey, NSAlternateKeyMask },
+ { controlKey, NSControlKeyMask },
+ { shiftKey, NSShiftKeyMask }
+ };
+
+ NSUInteger i, ret = 0;
+
+ for (i = 0; i < 4; i++) {
+ if (self.modifiers & modToChar[i][0]) {
+ ret |= modToChar[i][1];
+ }
+ }
+
+ return ret;
+}
+
+- (NSString *)description {
+ NSString *desc;
+
+ if ([self isValidHotKeyCombo]) {
+ desc = [NSString stringWithFormat: @"%@%@",
+ [[self class] _stringForModifiers:self.modifiers],
+ [[self class] _stringForKeyCode:self.keyCode]];
+ }
+ else {
+ desc = NSLocalizedString(@"(None)", @"Hot Keys: Key Combo text for 'empty' combo" );
+ }
+
+ return desc;
+}
+@end
7 Source/Prefix.pch
@@ -0,0 +1,7 @@
+//
+// Prefix header for all source files of the 'SGHotKeyCenter' target in the 'SGHotKeyCenter' project
+//
+
+#ifdef __OBJC__
+ #import <Cocoa/Cocoa.h>
+#endif
28 Source/SGHotKeyCenterAppDelegate.h
@@ -0,0 +1,28 @@
+//
+// SGHotKeyCenterAppDelegate.h
+// SGHotKeyCenter
+//
+// Created by Justin Williams on 7/26/09.
+// Copyright 2009 Second Gear. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import <ShortcutRecorder/ShortcutRecorder.h>
+#import "SGHotKey.h"
+
+extern NSString *kGlobalHotKey;
+
+@interface SGHotKeyCenterAppDelegate : NSObject {
+ NSWindow *window;
+ SRRecorderControl *hotKeyControl;
+ NSTextField *resultsTextField;
+
+ SGHotKey *hotKey;
+}
+
+@property (nonatomic, retain) IBOutlet NSWindow *window;
+@property (nonatomic, retain) IBOutlet SRRecorderControl *hotKeyControl;
+@property (nonatomic, retain) IBOutlet NSTextField *resultsTextField;
+@property (nonatomic, retain) SGHotKey *hotKey;
+
+@end
62 Source/SGHotKeyCenterAppDelegate.m
@@ -0,0 +1,62 @@
+//
+// SGHotKeyCenterAppDelegate.m
+// SGHotKeyCenter
+//
+// Created by Justin Williams on 7/26/09.
+// Copyright 2009 Second Gear. All rights reserved.
+//
+
+#import "SGHotKeyCenterAppDelegate.h"
+#import "SGHotKeyCenter.h"
+
+NSString *kGlobalHotKey = @"Global Hot Key";
+
+@implementation SGHotKeyCenterAppDelegate
+
+@synthesize window;
+@synthesize hotKeyControl;
+@synthesize resultsTextField;
+@synthesize hotKey;
+
+- (void)applicationDidFinishLaunching:(NSNotification *)theNotification {
+ [[SGHotKeyCenter sharedCenter] unregisterHotKey:hotKey];
+ id keyComboPlist = [[NSUserDefaults standardUserDefaults] objectForKey:kGlobalHotKey];
+ SGKeyCombo *keyCombo = [[SGKeyCombo alloc] initWithPlistRepresentation:keyComboPlist];
+ hotKey = [[SGHotKey alloc] initWithIdentifier:kGlobalHotKey keyCombo:keyCombo target:self action:@selector(hotKeyPressed:)];
+ [[SGHotKeyCenter sharedCenter] registerHotKey:hotKey];
+ [hotKeyControl setKeyCombo:SRMakeKeyCombo(hotKey.keyCombo.keyCode, [hotKeyControl carbonToCocoaFlags:hotKey.keyCombo.modifiers])];
+}
+
+- (void)applicationWillTerminate:(NSNotification *)theNotification {
+ [[NSUserDefaults standardUserDefaults] setObject:[self.hotKey.keyCombo plistRepresentation] forKey:kGlobalHotKey];
+}
+
+- (void)hotKeyPressed:(id)sender {
+ [resultsTextField setStringValue:[NSString stringWithFormat: @"%@\n%@", sender, [NSCalendarDate calendarDate]]];
+}
+
+#pragma mark -
+#pragma mark ShortcutRecorder Delegate Methods
+
+- (BOOL)shortcutRecorder:(SRRecorderControl *)aRecorder isKeyCode:(NSInteger)keyCode andFlagsTaken:(NSUInteger)flags reason:(NSString **)aReason {
+ return NO;
+}
+
+- (void)shortcutRecorder:(SRRecorderControl *)aRecorder keyComboDidChange:(KeyCombo)newKeyCombo {
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+
+ SGKeyCombo *keyCombo = [SGKeyCombo keyComboWithKeyCode:[aRecorder keyCombo].code
+ modifiers:[aRecorder cocoaToCarbonFlags:[aRecorder keyCombo].flags]];
+
+ if (aRecorder == hotKeyControl) {
+ self.hotKey.keyCombo = keyCombo;
+
+ // Re-register the new hot key
+ [[SGHotKeyCenter sharedCenter] registerHotKey:self.hotKey];
+ [defaults setObject:[keyCombo plistRepresentation] forKey:kGlobalHotKey];
+ }
+
+ [defaults synchronize];
+}
+
+@end
14 Source/main.m
@@ -0,0 +1,14 @@
+//
+// main.m
+// SGHotKeyCenter
+//
+// Created by Justin Williams on 7/26/09.
+// Copyright 2009 Second Gear. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+int main(int argc, char *argv[])
+{
+ return NSApplicationMain(argc, (const char **) argv);
+}

0 comments on commit ab71653

Please sign in to comment.