diff --git a/Application/AppController.h b/Application/AppController.h index 7372caa8d..bf5463038 100644 --- a/Application/AppController.h +++ b/Application/AppController.h @@ -2,7 +2,7 @@ #import -#import "NDHotKeyEvent.h" +#import #import "NowPlayingBarController.h" @class FileTreeViewController; diff --git a/Application/AppController.m b/Application/AppController.m index 8eb1ee318..f7c948a86 100644 --- a/Application/AppController.m +++ b/Application/AppController.m @@ -4,7 +4,7 @@ #import "PlaylistController.h" #import "PlaylistView.h" #import "PlaylistEntry.h" -#import "NDHotKeyEvent.h" +#import #import "AppleRemote.h" #import "PlaylistLoader.h" #import "OpenURLPanel.h" @@ -451,15 +451,15 @@ increase/decrease as long as the user holds the left/right, plus/minus button */ [userDefaultsValuesDict setObject:[NSNumber numberWithInt:35] forKey:@"hotKeyPlayKeyCode"]; [userDefaultsValuesDict setObject:[NSNumber numberWithInt:(NSControlKeyMask|NSCommandKeyMask)] forKey:@"hotKeyPlayModifiers"]; - [userDefaultsValuesDict setObject:[NSNumber numberWithInt:'P'] forKey:@"hotKeyPlayCharacter"]; [userDefaultsValuesDict setObject:[NSNumber numberWithInt:45] forKey:@"hotKeyNextKeyCode"]; [userDefaultsValuesDict setObject:[NSNumber numberWithInt:(NSControlKeyMask|NSCommandKeyMask)] forKey:@"hotKeyNextModifiers"]; - [userDefaultsValuesDict setObject:[NSNumber numberWithInt:'N'] forKey:@"hotKeyNextCharacter"]; [userDefaultsValuesDict setObject:[NSNumber numberWithInt:15] forKey:@"hotKeyPreviousKeyCode"]; [userDefaultsValuesDict setObject:[NSNumber numberWithInt:(NSControlKeyMask|NSCommandKeyMask)] forKey:@"hotKeyPreviousModifiers"]; - [userDefaultsValuesDict setObject:[NSNumber numberWithInt:'R'] forKey:@"hotKeyPreviousCharacter"]; + + [userDefaultsValuesDict setObject:[NSNumber numberWithInt:8] forKey:@"hotKeySpamKeyCode"]; + [userDefaultsValuesDict setObject:[NSNumber numberWithInt:(NSControlKeyMask|NSCommandKeyMask)] forKey:@"hotKeySpamModifiers"]; [userDefaultsValuesDict setObject:[NSNumber numberWithBool:YES] forKey:@"remoteEnabled"]; [userDefaultsValuesDict setObject:[NSNumber numberWithBool:YES] forKey:@"remoteOnlyOnActive"]; @@ -472,19 +472,6 @@ increase/decrease as long as the user holds the left/right, plus/minus button */ [userDefaultsValuesDict setObject:@"albumGainWithPeak" forKey:@"volumeScaling"]; - [userDefaultsValuesDict setObject:[NSNumber numberWithInt:0] forKey:@"hotKeyPlayKeyCode"]; - [userDefaultsValuesDict setObject:[NSNumber numberWithInt:0] forKey:@"hotKeyPlayCharacter"]; - [userDefaultsValuesDict setObject:[NSNumber numberWithInt:0] forKey:@"hotKeyPlayModifiers"]; - [userDefaultsValuesDict setObject:[NSNumber numberWithInt:0] forKey:@"hotKeyNextKeyCode"]; - [userDefaultsValuesDict setObject:[NSNumber numberWithInt:0] forKey:@"hotKeyNextCharacter"]; - [userDefaultsValuesDict setObject:[NSNumber numberWithInt:0] forKey:@"hotKeyNextModifiers"]; - [userDefaultsValuesDict setObject:[NSNumber numberWithInt:0] forKey:@"hotKeyPreviousKeyCode"]; - [userDefaultsValuesDict setObject:[NSNumber numberWithInt:0] forKey:@"hotKeyPreviousCharacter"]; - [userDefaultsValuesDict setObject:[NSNumber numberWithInt:0] forKey:@"hotKeyPreviousModifiers"]; - [userDefaultsValuesDict setObject:[NSNumber numberWithInt:0] forKey:@"hotKeySpamKeyCode"]; - [userDefaultsValuesDict setObject:[NSNumber numberWithInt:0] forKey:@"hotKeySpamCharacter"]; - [userDefaultsValuesDict setObject:[NSNumber numberWithInt:0] forKey:@"hotKeySpamModifiers"]; - [userDefaultsValuesDict setObject:[NSNumber numberWithInteger:kCogStatusStopped] forKey:@"lastPlaybackStatus"]; [userDefaultsValuesDict setObject:[NSNumber numberWithInteger:-1] forKey:@"lastTrackPlaying"]; [userDefaultsValuesDict setObject:[NSNumber numberWithDouble:0] forKey:@"lastTrackPosition"]; @@ -543,7 +530,6 @@ increase/decrease as long as the user holds the left/right, plus/minus button */ if ([[[[NSUserDefaultsController sharedUserDefaultsController] defaults] objectForKey:@"hotKeyPlayKeyCode"] intValue]) { playHotKey = [[NDHotKeyEvent alloc] initWithKeyCode: [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] objectForKey:@"hotKeyPlayKeyCode"] intValue] - character: [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] objectForKey:@"hotKeyPlayCharacter"] intValue] modifierFlags: [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] objectForKey:@"hotKeyPlayModifiers"] intValue] ]; [playHotKey setTarget:self selector:@selector(clickPlay)]; @@ -554,7 +540,6 @@ increase/decrease as long as the user holds the left/right, plus/minus button */ if ([[[[NSUserDefaultsController sharedUserDefaultsController] defaults] objectForKey:@"hotKeyPreviousKeyCode"] intValue]) { prevHotKey = [[NDHotKeyEvent alloc] initWithKeyCode: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeyPreviousKeyCode"] - character: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeyPreviousCharacter"] modifierFlags: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeyPreviousModifiers"] ]; [prevHotKey setTarget:self selector:@selector(clickPrev)]; @@ -565,7 +550,6 @@ increase/decrease as long as the user holds the left/right, plus/minus button */ if ([[[[NSUserDefaultsController sharedUserDefaultsController] defaults] objectForKey:@"hotKeyNextKeyCode"] intValue]) { nextHotKey = [[NDHotKeyEvent alloc] initWithKeyCode: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeyNextKeyCode"] - character: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeyNextCharacter"] modifierFlags: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeyNextModifiers"] ]; [nextHotKey setTarget:self selector:@selector(clickNext)]; @@ -576,7 +560,6 @@ increase/decrease as long as the user holds the left/right, plus/minus button */ if ([[[[NSUserDefaultsController sharedUserDefaultsController] defaults] objectForKey:@"hotKeySpamKeyCode"] intValue]) { spamHotKey = [[NDHotKeyEvent alloc] initWithKeyCode: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeySpamKeyCode"] - character: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeySpamCharacter"] modifierFlags: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeySpamModifiers"] ]; [spamHotKey setTarget:self selector:@selector(clickSpam)]; diff --git a/Cog.xcodeproj/project.pbxproj b/Cog.xcodeproj/project.pbxproj index 0a44ad50c..8e3fbc63b 100644 --- a/Cog.xcodeproj/project.pbxproj +++ b/Cog.xcodeproj/project.pbxproj @@ -45,8 +45,6 @@ 1778D3CA0F645BF00037E7A0 /* MissingAlbumArtTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1778D3C90F645BF00037E7A0 /* MissingAlbumArtTransformer.m */; }; 177EBFA20B8BC2A70000BC8C /* AppleRemote.m in Sources */ = {isa = PBXBuildFile; fileRef = 177EBF7F0B8BC2A70000BC8C /* AppleRemote.m */; }; 177EBFA70B8BC2A70000BC8C /* ImageTextCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 177EBF870B8BC2A70000BC8C /* ImageTextCell.m */; }; - 177EBFAB0B8BC2A70000BC8C /* NDHotKeyControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 177EBF8D0B8BC2A70000BC8C /* NDHotKeyControl.m */; }; - 177EBFAD0B8BC2A70000BC8C /* NDHotKeyEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 177EBF8F0B8BC2A70000BC8C /* NDHotKeyEvent.m */; }; 177EC0270B8BC2CF0000BC8C /* TrackingCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 177EC01B0B8BC2CF0000BC8C /* TrackingCell.m */; }; 177EC0290B8BC2CF0000BC8C /* TrackingSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = 177EC01D0B8BC2CF0000BC8C /* TrackingSlider.m */; }; 177EC04B0B8BC2FF0000BC8C /* next.png in Resources */ = {isa = PBXBuildFile; fileRef = 177EC0350B8BC2FF0000BC8C /* next.png */; }; @@ -177,6 +175,8 @@ 83849172180843B200E7332D /* pauseDockBadgeColorful.png in Resources */ = {isa = PBXBuildFile; fileRef = 8384916F180843B200E7332D /* pauseDockBadgeColorful.png */; }; 83849173180843B200E7332D /* playDockBadgeColorful.png in Resources */ = {isa = PBXBuildFile; fileRef = 83849170180843B200E7332D /* playDockBadgeColorful.png */; }; 83849174180843B200E7332D /* stopDockBadgeColorful.png in Resources */ = {isa = PBXBuildFile; fileRef = 83849171180843B200E7332D /* stopDockBadgeColorful.png */; }; + 838491871808591F00E7332D /* NDHotKey.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8384917E1808585D00E7332D /* NDHotKey.framework */; }; + 838491881808593200E7332D /* NDHotKey.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8384917E1808585D00E7332D /* NDHotKey.framework */; }; 8399D4E21805A55000B503B1 /* XmlContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 8399D4E01805A55000B503B1 /* XmlContainer.m */; }; 83BCB8DE17FC971300760340 /* FFMPEG.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = B09E94350D747F7B0064F138 /* FFMPEG.bundle */; }; 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; @@ -447,6 +447,20 @@ remoteGlobalIDString = 8375B03B17FFEA400092A79F; remoteInfo = Opus; }; + 8384917D1808585D00E7332D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 838491791808585C00E7332D /* NDHotKey.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 32F1615614E6BB3B00D6AB2F; + remoteInfo = NDHotKey; + }; + 838491851808591400E7332D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 838491791808585C00E7332D /* NDHotKey.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 32F1615514E6BB3B00D6AB2F; + remoteInfo = NDHotKey; + }; 83BCB8D817FC96F800760340 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 8360EF0017F92B23005208A4 /* HighlyComplete.xcodeproj */; @@ -542,6 +556,7 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( + 838491881808593200E7332D /* NDHotKey.framework in CopyFiles */, 17F561400C3BD4F30019975C /* CogAudio.framework in CopyFiles */, 170680840B950164006BA573 /* Growl.framework in CopyFiles */, ); @@ -611,10 +626,6 @@ 177EBF7F0B8BC2A70000BC8C /* AppleRemote.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = AppleRemote.m; sourceTree = ""; }; 177EBF860B8BC2A70000BC8C /* ImageTextCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ImageTextCell.h; sourceTree = ""; }; 177EBF870B8BC2A70000BC8C /* ImageTextCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = ImageTextCell.m; sourceTree = ""; }; - 177EBF8C0B8BC2A70000BC8C /* NDHotKeyControl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = NDHotKeyControl.h; sourceTree = ""; }; - 177EBF8D0B8BC2A70000BC8C /* NDHotKeyControl.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = NDHotKeyControl.m; sourceTree = ""; }; - 177EBF8E0B8BC2A70000BC8C /* NDHotKeyEvent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = NDHotKeyEvent.h; sourceTree = ""; }; - 177EBF8F0B8BC2A70000BC8C /* NDHotKeyEvent.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = NDHotKeyEvent.m; sourceTree = ""; }; 177EC01A0B8BC2CF0000BC8C /* TrackingCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrackingCell.h; sourceTree = ""; }; 177EC01B0B8BC2CF0000BC8C /* TrackingCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = TrackingCell.m; sourceTree = ""; }; 177EC01C0B8BC2CF0000BC8C /* TrackingSlider.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrackingSlider.h; sourceTree = ""; }; @@ -797,6 +808,7 @@ 8384916F180843B200E7332D /* pauseDockBadgeColorful.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = pauseDockBadgeColorful.png; path = Images/pauseDockBadgeColorful.png; sourceTree = ""; }; 83849170180843B200E7332D /* playDockBadgeColorful.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = playDockBadgeColorful.png; path = Images/playDockBadgeColorful.png; sourceTree = ""; }; 83849171180843B200E7332D /* stopDockBadgeColorful.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = stopDockBadgeColorful.png; path = Images/stopDockBadgeColorful.png; sourceTree = ""; }; + 838491791808585C00E7332D /* NDHotKey.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = NDHotKey.xcodeproj; path = Frameworks/NDHotKey/NDHotKey.xcodeproj; sourceTree = ""; }; 8399D4E01805A55000B503B1 /* XmlContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XmlContainer.m; sourceTree = ""; }; 8399D4E11805A55000B503B1 /* XmlContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XmlContainer.h; sourceTree = ""; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; @@ -836,6 +848,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 838491871808591F00E7332D /* NDHotKey.framework in Frameworks */, 8355D6B8180613FB00D05687 /* Security.framework in Frameworks */, 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, 8E6889240AAA403C00AD3950 /* Carbon.framework in Frameworks */, @@ -884,6 +897,7 @@ 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { isa = PBXGroup; children = ( + 838491791808585C00E7332D /* NDHotKey.xcodeproj */, 17F5612A0C3BD4DC0019975C /* CogAudio.xcodeproj */, 170680620B950158006BA573 /* Growl.framework */, 8E6889230AAA403C00AD3950 /* Carbon.framework */, @@ -951,7 +965,6 @@ 177EBF7D0B8BC2A70000BC8C /* AppleRemote */, 177EBF850B8BC2A70000BC8C /* ImageTextCell */, 179790DD0C087AB7001D6996 /* OpenURLPanel */, - 177EBF8B0B8BC2A70000BC8C /* NDHotKeys */, ); path = ThirdParty; sourceTree = ""; @@ -974,17 +987,6 @@ path = ImageTextCell; sourceTree = ""; }; - 177EBF8B0B8BC2A70000BC8C /* NDHotKeys */ = { - isa = PBXGroup; - children = ( - 177EBF8C0B8BC2A70000BC8C /* NDHotKeyControl.h */, - 177EBF8D0B8BC2A70000BC8C /* NDHotKeyControl.m */, - 177EBF8E0B8BC2A70000BC8C /* NDHotKeyEvent.h */, - 177EBF8F0B8BC2A70000BC8C /* NDHotKeyEvent.m */, - ); - path = NDHotKeys; - sourceTree = ""; - }; 177EC0110B8BC2CF0000BC8C /* Utils */ = { isa = PBXGroup; children = ( @@ -1445,6 +1447,14 @@ name = Products; sourceTree = ""; }; + 8384917A1808585C00E7332D /* Products */ = { + isa = PBXGroup; + children = ( + 8384917E1808585D00E7332D /* NDHotKey.framework */, + ); + name = Products; + sourceTree = ""; + }; 8E07AAEA0AAC90DC00A4B32F /* Preferences */ = { isa = PBXGroup; children = ( @@ -1579,6 +1589,7 @@ buildRules = ( ); dependencies = ( + 838491861808591400E7332D /* PBXTargetDependency */, 8375B36217FFEF010092A79F /* PBXTargetDependency */, 8375B36417FFEF010092A79F /* PBXTargetDependency */, 83BCB8DD17FC96FC00760340 /* PBXTargetDependency */, @@ -1692,6 +1703,10 @@ ProductGroup = 17C8089F0C3BD1AB005707C4 /* Products */; ProjectRef = 17C8089E0C3BD1AB005707C4 /* Musepack.xcodeproj */; }, + { + ProductGroup = 8384917A1808585C00E7332D /* Products */; + ProjectRef = 838491791808585C00E7332D /* NDHotKey.xcodeproj */; + }, { ProductGroup = 8375B05217FFEA400092A79F /* Products */; ProjectRef = 8375B05117FFEA400092A79F /* Opus.xcodeproj */; @@ -1851,6 +1866,13 @@ remoteRef = 8375B05617FFEA410092A79F /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 8384917E1808585D00E7332D /* NDHotKey.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = NDHotKey.framework; + remoteRef = 8384917D1808585D00E7332D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 8E8D40870CBB036600135C1B /* M3u.bundle */ = { isa = PBXReferenceProxy; fileType = wrapper.cfbundle; @@ -1997,8 +2019,6 @@ 8E07AB790AAC930B00A4B32F /* PreferencesController.m in Sources */, 177EBFA20B8BC2A70000BC8C /* AppleRemote.m in Sources */, 177EBFA70B8BC2A70000BC8C /* ImageTextCell.m in Sources */, - 177EBFAB0B8BC2A70000BC8C /* NDHotKeyControl.m in Sources */, - 177EBFAD0B8BC2A70000BC8C /* NDHotKeyEvent.m in Sources */, 177EC0270B8BC2CF0000BC8C /* TrackingCell.m in Sources */, 177EC0290B8BC2CF0000BC8C /* TrackingSlider.m in Sources */, 1770429C0B8BC53600B86321 /* AppController.m in Sources */, @@ -2158,6 +2178,11 @@ name = Opus; targetProxy = 8375B36317FFEF010092A79F /* PBXContainerItemProxy */; }; + 838491861808591400E7332D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = NDHotKey; + targetProxy = 838491851808591400E7332D /* PBXContainerItemProxy */; + }; 83BCB8D917FC96F800760340 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = HighlyComplete; diff --git a/Frameworks/NDHotKey/NDHotKey.xcodeproj/project.pbxproj b/Frameworks/NDHotKey/NDHotKey.xcodeproj/project.pbxproj new file mode 100644 index 000000000..b44d0301e --- /dev/null +++ b/Frameworks/NDHotKey/NDHotKey.xcodeproj/project.pbxproj @@ -0,0 +1,311 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 32F1615A14E6BB3B00D6AB2F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32F1615914E6BB3B00D6AB2F /* Cocoa.framework */; }; + 32F1616414E6BB3B00D6AB2F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 32F1616214E6BB3B00D6AB2F /* InfoPlist.strings */; }; + 32F1617A14E6BBFC00D6AB2F /* NDHotKeyControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F1617414E6BBFC00D6AB2F /* NDHotKeyControl.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 32F1617B14E6BBFC00D6AB2F /* NDHotKeyControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F1617514E6BBFC00D6AB2F /* NDHotKeyControl.m */; }; + 32F1617C14E6BBFC00D6AB2F /* NDHotKeyEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F1617614E6BBFC00D6AB2F /* NDHotKeyEvent.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 32F1617D14E6BBFC00D6AB2F /* NDHotKeyEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F1617714E6BBFC00D6AB2F /* NDHotKeyEvent.m */; }; + 32F1617E14E6BBFC00D6AB2F /* NDKeyboardLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F1617814E6BBFC00D6AB2F /* NDKeyboardLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 32F1617F14E6BBFC00D6AB2F /* NDKeyboardLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F1617914E6BBFC00D6AB2F /* NDKeyboardLayout.m */; }; + 32F1618E14E6BE7300D6AB2F /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32F1618D14E6BE7300D6AB2F /* Carbon.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 32F1615614E6BB3B00D6AB2F /* NDHotKey.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = NDHotKey.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 32F1615914E6BB3B00D6AB2F /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 32F1615C14E6BB3B00D6AB2F /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + 32F1615D14E6BB3B00D6AB2F /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + 32F1615E14E6BB3B00D6AB2F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 32F1616114E6BB3B00D6AB2F /* NDHotKey-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "NDHotKey-Info.plist"; sourceTree = ""; }; + 32F1616314E6BB3B00D6AB2F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 32F1616514E6BB3B00D6AB2F /* NDHotKey-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NDHotKey-Prefix.pch"; sourceTree = ""; }; + 32F1617414E6BBFC00D6AB2F /* NDHotKeyControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NDHotKeyControl.h; sourceTree = ""; }; + 32F1617514E6BBFC00D6AB2F /* NDHotKeyControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NDHotKeyControl.m; sourceTree = ""; }; + 32F1617614E6BBFC00D6AB2F /* NDHotKeyEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NDHotKeyEvent.h; sourceTree = ""; }; + 32F1617714E6BBFC00D6AB2F /* NDHotKeyEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NDHotKeyEvent.m; sourceTree = ""; }; + 32F1617814E6BBFC00D6AB2F /* NDKeyboardLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NDKeyboardLayout.h; sourceTree = ""; }; + 32F1617914E6BBFC00D6AB2F /* NDKeyboardLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NDKeyboardLayout.m; sourceTree = ""; }; + 32F1618D14E6BE7300D6AB2F /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 32F1615214E6BB3B00D6AB2F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 32F1618E14E6BE7300D6AB2F /* Carbon.framework in Frameworks */, + 32F1615A14E6BB3B00D6AB2F /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 32F1614A14E6BB3B00D6AB2F = { + isa = PBXGroup; + children = ( + 32F1618D14E6BE7300D6AB2F /* Carbon.framework */, + 32F1615F14E6BB3B00D6AB2F /* NDHotKey */, + 32F1615814E6BB3B00D6AB2F /* Frameworks */, + 32F1615714E6BB3B00D6AB2F /* Products */, + ); + sourceTree = ""; + }; + 32F1615714E6BB3B00D6AB2F /* Products */ = { + isa = PBXGroup; + children = ( + 32F1615614E6BB3B00D6AB2F /* NDHotKey.framework */, + ); + name = Products; + sourceTree = ""; + }; + 32F1615814E6BB3B00D6AB2F /* Frameworks */ = { + isa = PBXGroup; + children = ( + 32F1615914E6BB3B00D6AB2F /* Cocoa.framework */, + 32F1615B14E6BB3B00D6AB2F /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 32F1615B14E6BB3B00D6AB2F /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 32F1615C14E6BB3B00D6AB2F /* AppKit.framework */, + 32F1615D14E6BB3B00D6AB2F /* CoreData.framework */, + 32F1615E14E6BB3B00D6AB2F /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 32F1615F14E6BB3B00D6AB2F /* NDHotKey */ = { + isa = PBXGroup; + children = ( + 32F1617414E6BBFC00D6AB2F /* NDHotKeyControl.h */, + 32F1617514E6BBFC00D6AB2F /* NDHotKeyControl.m */, + 32F1617614E6BBFC00D6AB2F /* NDHotKeyEvent.h */, + 32F1617714E6BBFC00D6AB2F /* NDHotKeyEvent.m */, + 32F1617814E6BBFC00D6AB2F /* NDKeyboardLayout.h */, + 32F1617914E6BBFC00D6AB2F /* NDKeyboardLayout.m */, + 32F1616014E6BB3B00D6AB2F /* Supporting Files */, + ); + path = NDHotKey; + sourceTree = ""; + }; + 32F1616014E6BB3B00D6AB2F /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 32F1616114E6BB3B00D6AB2F /* NDHotKey-Info.plist */, + 32F1616214E6BB3B00D6AB2F /* InfoPlist.strings */, + 32F1616514E6BB3B00D6AB2F /* NDHotKey-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 32F1615314E6BB3B00D6AB2F /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 32F1617A14E6BBFC00D6AB2F /* NDHotKeyControl.h in Headers */, + 32F1617C14E6BBFC00D6AB2F /* NDHotKeyEvent.h in Headers */, + 32F1617E14E6BBFC00D6AB2F /* NDKeyboardLayout.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 32F1615514E6BB3B00D6AB2F /* NDHotKey */ = { + isa = PBXNativeTarget; + buildConfigurationList = 32F1616B14E6BB3B00D6AB2F /* Build configuration list for PBXNativeTarget "NDHotKey" */; + buildPhases = ( + 32F1615114E6BB3B00D6AB2F /* Sources */, + 32F1615214E6BB3B00D6AB2F /* Frameworks */, + 32F1615314E6BB3B00D6AB2F /* Headers */, + 32F1615414E6BB3B00D6AB2F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = NDHotKey; + productName = NDHotKey; + productReference = 32F1615614E6BB3B00D6AB2F /* NDHotKey.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 32F1614C14E6BB3B00D6AB2F /* Project object */ = { + isa = PBXProject; + attributes = { + ORGANIZATIONNAME = "dmitry.promsky@gmail.com"; + }; + buildConfigurationList = 32F1614F14E6BB3B00D6AB2F /* Build configuration list for PBXProject "NDHotKey" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 32F1614A14E6BB3B00D6AB2F; + productRefGroup = 32F1615714E6BB3B00D6AB2F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 32F1615514E6BB3B00D6AB2F /* NDHotKey */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 32F1615414E6BB3B00D6AB2F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 32F1616414E6BB3B00D6AB2F /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 32F1615114E6BB3B00D6AB2F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 32F1617B14E6BBFC00D6AB2F /* NDHotKeyControl.m in Sources */, + 32F1617D14E6BBFC00D6AB2F /* NDHotKeyEvent.m in Sources */, + 32F1617F14E6BBFC00D6AB2F /* NDKeyboardLayout.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 32F1616214E6BB3B00D6AB2F /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 32F1616314E6BB3B00D6AB2F /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 32F1616914E6BB3B00D6AB2F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx10.7; + SYMROOT = ../../build; + }; + name = Debug; + }; + 32F1616A14E6BB3B00D6AB2F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + SDKROOT = macosx10.7; + SYMROOT = ../../build; + }; + name = Release; + }; + 32F1616C14E6BB3B00D6AB2F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "NDHotKey/NDHotKey-Prefix.pch"; + INFOPLIST_FILE = "NDHotKey/NDHotKey-Info.plist"; + INSTALL_PATH = "@loader_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = framework; + }; + name = Debug; + }; + 32F1616D14E6BB3B00D6AB2F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "NDHotKey/NDHotKey-Prefix.pch"; + INFOPLIST_FILE = "NDHotKey/NDHotKey-Info.plist"; + INSTALL_PATH = "@loader_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = framework; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 32F1614F14E6BB3B00D6AB2F /* Build configuration list for PBXProject "NDHotKey" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 32F1616914E6BB3B00D6AB2F /* Debug */, + 32F1616A14E6BB3B00D6AB2F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 32F1616B14E6BB3B00D6AB2F /* Build configuration list for PBXNativeTarget "NDHotKey" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 32F1616C14E6BB3B00D6AB2F /* Debug */, + 32F1616D14E6BB3B00D6AB2F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 32F1614C14E6BB3B00D6AB2F /* Project object */; +} diff --git a/Frameworks/NDHotKey/NDHotKey/NDHotKey-Info.plist b/Frameworks/NDHotKey/NDHotKey/NDHotKey-Info.plist new file mode 100644 index 000000000..d781b0062 --- /dev/null +++ b/Frameworks/NDHotKey/NDHotKey/NDHotKey-Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + ND.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSHumanReadableCopyright + Copyright © 2012 dmitry.promsky@gmail.com. All rights reserved. + NSPrincipalClass + + + diff --git a/Frameworks/NDHotKey/NDHotKey/NDHotKey-Prefix.pch b/Frameworks/NDHotKey/NDHotKey/NDHotKey-Prefix.pch new file mode 100644 index 000000000..6fc9cc199 --- /dev/null +++ b/Frameworks/NDHotKey/NDHotKey/NDHotKey-Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'NDHotKey' target in the 'NDHotKey' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/Frameworks/NDHotKey/NDHotKey/NDHotKeyControl.h b/Frameworks/NDHotKey/NDHotKey/NDHotKeyControl.h new file mode 100644 index 000000000..976a2f6cf --- /dev/null +++ b/Frameworks/NDHotKey/NDHotKey/NDHotKeyControl.h @@ -0,0 +1,128 @@ +/* + NDHotKeyControl.h + + Created by Nathan Day on 29.03.08 under a MIT-style license. + Copyright (c) 2008 Nathan Day + + 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, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + 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. + */ + +/*! + @header NDHotKeyControl.h + @abstract Header file for a subclass of NSTextField for getting hot key combinations from the user. + @discussion The NDHotKeyControl can be used to get a NDHotKeyEvent for the last key combination pressed by the user. + @updated 2010-01-18 + */ + +#import + +@class NDHotKeyEvent; + +/*! + @class NDHotKeyControl + @abstract Subclass of NSTextField for getting hot key combinations from the user. + @discussion The NDHotKeyControl can be used to get a NDHotKeyEvent for the last key combination pressed by the user. + */ +@interface NDHotKeyControl : NSTextField +{ +@private + UInt16 keyCode; + NSUInteger modifierFlags; + BOOL requiresModifierKeys, + readyForEvent, + stayReadyForEvent; + id lastReadyForEventSender; +} + +- (IBAction)readyForHotKeyEventChanged:(id)sender; +/*! + @method keyCode + @abstract Get key code. + @discussion Returns the key code for the last key combination the user pressed while the reciever was active. + @result A UInt16 containing key code. + */ +- (UInt16)keyCode; + +/*! + @method keyCharacter + @abstract Get unicode character. + @discussion Returns the unicode character for the last key combination the user pressed while the reciever was active. + @result A unichar containing character. + */ +- (unichar)keyCharacter; + +/*! + @method modifierFlags + @abstract Get modifer flags. + @discussion Returns the modifer flags for the last key combination the user pressed while the reciever was active. + @result A unsigned long containing modifer flags. + */ +- (NSUInteger)modifierFlags; + +/*! + @method hotKeyEvent + @abstract Get NDHotKeyEvent + @discussion Returns the NDHotKeyEvent instance for the last key combination the user pressed while the reciever was active. The NDHotKeyEvent returned will either be one that has already been created or a newly created one otherwise. + @result A NDHotKeyEvent for the hot key event. + */ +- (NDHotKeyEvent *)hotKeyEvent; + +/*! + @method setRequiresModifierKeys: + @abstract Set whether hot keys entered need modifiers keys. + @discussion This does not include function key which do not require modifier keys no matter what the value you pass for the argument flag + @param flag If NO then the reciever only accepts hot keys combination containing modifer keys. + */ +- (void)setRequiresModifierKeys:(BOOL)flag; +/*! + @method requiresModifierKeys + @abstract Returns whether hot keys entered need modifiers keys. + @discussion This does not include key which do not require modifier keys no matter what the value is returned. + @result If NO then the reciever only accepts hot keys combination containing modifer keys. + */ +- (BOOL)requiresModifierKeys; + +/*! + @method setReadyForHotKeyEvent: + @abstract Set up the control to accept input + @discussion Setting readyForHotKeyEvent to YES will disable all Hot Key Events and then prepare NDHotKeyControl for keyboard input. Setting readyForHotKeyEvent to NO will re-enables all Hot Key Events and then stops NDHotKeyControl for accepting keyboard input. + @param flag <#description#> + */ +- (void)setReadyForHotKeyEvent:(BOOL)flag; +/*! + @method readyForHotKeyEvent + @abstract Is the control set up to accept input + @discussion Returns the current state of readyForHotKeyEvent as set by the method setReadyForHotKeyEvent:. + */ +- (BOOL)readyForHotKeyEvent; +/*! + @method setStayReadyForEvent: + @abstract Will the control remain continually active. + @discussion By default NDHotKeyControl will accept one key and then call [self setReadyForHotKeyEvent:NO], setStayReadyForEvent: allows you to change this behaviour so that NDHotKeyControl will continue accepting keys until it is manually deactivated. + */ +- (void)setStayReadyForEvent:(BOOL)flag; +/*! + @method stayReadyForEvent + @abstract Will the control remain continually active. + @discussion By default NDHotKeyControl will accept one key and then call [self setReadyForHotKeyEvent:NO], if stayReadyForEvent returns YES, NDHotKeyControl will continue accepting keys until it is manually deactivated. + */ +- (BOOL)stayReadyForEvent; + + +@end diff --git a/Frameworks/NDHotKey/NDHotKey/NDHotKeyControl.m b/Frameworks/NDHotKey/NDHotKey/NDHotKeyControl.m new file mode 100644 index 000000000..f5c780f4f --- /dev/null +++ b/Frameworks/NDHotKey/NDHotKey/NDHotKeyControl.m @@ -0,0 +1,145 @@ +/* + NDHotKeyControl.m + + Created by Nathan Day on 21.06.06 under a MIT-style license. + Copyright (c) 2008 Nathan Day + + 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, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + 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. + */ + +#import "NDHotKeyControl.h" +#import "NDHotKeyEvent.h" +#import "NDKeyboardLayout.h" + +@interface NDHotKeyControl () + +@end + +/* + * class implementation NDHotKeyControl + */ +@implementation NDHotKeyControl + +- (id)initWithFrame:(NSRect)aFrame +{ + if( (self = [super initWithFrame:aFrame]) != nil ) + { + [self setEditable:NO]; + requiresModifierKeys = YES; + readyForEvent = NO; + stayReadyForEvent = NO; + } + return self; +} + +- (id)initWithCoder:(NSCoder *)aCoder +{ + if( (self = [super initWithCoder:aCoder]) != nil ) + { + [self setEditable:NO]; + requiresModifierKeys = YES; + readyForEvent = NO; + stayReadyForEvent = NO; + } + return self; +} + +- (IBAction)readyForHotKeyEventChanged:(id)aSender +{ + if( [aSender isKindOfClass:[NSMatrix class]] ) + aSender = [aSender selectedCell]; + + if( [aSender isKindOfClass:[NSButton class]] || [aSender isKindOfClass:[NSButtonCell class]] ) + { + if( [aSender state] == NSOnState ) + { + [self setReadyForHotKeyEvent:YES]; + lastReadyForEventSender = aSender; + [self setStringValue:@""]; + } + else + { + [self setReadyForHotKeyEvent:NO]; + lastReadyForEventSender = nil; + } + } +} + +- (unsigned short)keyCode { return keyCode; } +- (unichar)keyCharacter { return [[NDKeyboardLayout keyboardLayout] characterForKeyCode:[self keyCode]]; } +- (NSUInteger)modifierFlags { return modifierFlags; } + +- (BOOL)performKeyEquivalent:(NSEvent*)anEvent +{ + BOOL theResult = NO; + if( [self readyForHotKeyEvent] ) + { + [self keyDown:anEvent]; + theResult = YES; + } + else + theResult = [super performKeyEquivalent:anEvent]; + return theResult; +} + +- (void)keyDown:(NSEvent *)anEvent +{ + NSUInteger theModifierFlags = [anEvent modifierFlags]; + unichar theChar = [[anEvent charactersIgnoringModifiers] characterAtIndex:0]; + theModifierFlags &= (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask|NSCommandKeyMask); + + if( (theModifierFlags != 0 || !requiresModifierKeys || theChar > 255) && theChar != 0 ) + { + NDKeyboardLayout * theKeyboardLayout = [NDKeyboardLayout keyboardLayout]; + + NSParameterAssert( theKeyboardLayout != nil ); + + keyCode = [anEvent keyCode]; + modifierFlags = theModifierFlags; + + [self setStringValue:[theKeyboardLayout stringForKeyCode:keyCode modifierFlags:modifierFlags]]; + [self performClick:self]; + if( ![self stayReadyForEvent] ) + [self setReadyForHotKeyEvent:NO]; + } +} + +- (NDHotKeyEvent *)hotKeyEvent { return [NDHotKeyEvent getHotKeyForKeyCode:[self keyCode] modifierFlags:[self modifierFlags]]; } +- (void)setRequiresModifierKeys:(BOOL)aFlag { requiresModifierKeys = aFlag; } +- (BOOL)requiresModifierKeys { return requiresModifierKeys; } + +- (void)setReadyForHotKeyEvent:(BOOL)aFlag +{ + readyForEvent = aFlag; + + [NDHotKeyEvent setAllEnabled:!readyForEvent]; + if( readyForEvent == NO && lastReadyForEventSender ) + { + [lastReadyForEventSender setState:NSOffState]; + lastReadyForEventSender = nil; + } +} + +- (BOOL)readyForHotKeyEvent { return readyForEvent; } +- (void)setStayReadyForEvent:(BOOL)aFlag { stayReadyForEvent = aFlag; } +- (BOOL)stayReadyForEvent { return stayReadyForEvent; } + + +@end + diff --git a/ThirdParty/NDHotKeys/NDHotKeyEvent.h b/Frameworks/NDHotKey/NDHotKey/NDHotKeyEvent.h old mode 100755 new mode 100644 similarity index 54% rename from ThirdParty/NDHotKeys/NDHotKeyEvent.h rename to Frameworks/NDHotKey/NDHotKey/NDHotKeyEvent.h index 1873c2b8f..85ea4835a --- a/ThirdParty/NDHotKeys/NDHotKeyEvent.h +++ b/Frameworks/NDHotKey/NDHotKey/NDHotKeyEvent.h @@ -1,3 +1,28 @@ +/* + NDHotKeyEvent.h + + Created by Nathan Day on 12.06.04 under a MIT-style license. + Copyright (c) 2008 Nathan Day + + 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, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + 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. + */ + /*! @header NDHotKeyEvent.h @abstract Header file for the class NDHotKeyEvent @@ -6,14 +31,22 @@

Thread Saftey

By default the class object NDHotKeyEvent is not thread safe as the underlying functions that it relies on are not thread safe and the mechanism for keeping track of all of the NDHotKeyEvent instances is not thread safe either. Thread saftey can be enable be defining the flag NDHotKeyEventThreadSafe before compiling.

Even with the flag NDHotKeyEventThreadSafe defined instances of NDHotKeyEvent will still not be thread safe, that is, it is safe to invoke methods of different instance with different threads as well as class methods, but it is not safe to invoke methods of the same instance with different threads.

The functions stringForKeyCodeAndModifierFlags and unicharForKeyCode are never thread safe.

- -

Created by Nathan Day on Wed Feb 26 2003.
- Copyright © 2002 Nathan Day. All rights reserved.

+ @updated 2010-01-18 + @version 1.1.0 */ #import #import +/* + using NDHashTable clas instead of the NDHashTable functions that existed prior to 10.5 we can support garabage collection easier + */ +#if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED + #define NDMapTableClassDefined +#else + #warning Support for 10.4 and earily has been depreciated +#endif + /*! @defined NDHotKeyEventThreadSafe @abstract A flag to enable thread safety. @@ -48,6 +81,7 @@ enum */ extern const OSType NDHotKeyDefaultSignature; +@class NDHotKeyEvent; /*! @class NDHotKeyEvent @abstract Class to represent a HotKey @@ -58,13 +92,18 @@ extern const OSType NDHotKeyDefaultSignature; { @private EventHotKeyRef reference; - unsigned short keyCode; - unichar character; - unsigned int modifierFlags; + // UInt16 keyCode; + unichar keyCharacter; + BOOL keyPad; + NSUInteger modifierFlags; int currentEventType; - id target; + id target; SEL selectorReleased, - selectorPressed; + selectorPressed; +#ifdef NS_BLOCKS_AVAILABLE + void (^releasedBlock)(NDHotKeyEvent * e); + void (^pressedBlock)(NDHotKeyEvent * e); +#endif struct { unsigned individual : 1; @@ -80,6 +119,13 @@ extern const OSType NDHotKeyDefaultSignature; */ + (BOOL)install; +/*! + @method uninstall + @abstract Unistall the evenr key handler. + @discussion This method can be called if you want to remove all hot key permanently, without you application having to quit, you do not need to call this method if you application is about to quite. + */ ++ (void)uninstall; + /*! @method setSignature: @abstract Set the hot key signature for this application @@ -105,6 +151,15 @@ extern const OSType NDHotKeyDefaultSignature; */ + (BOOL)setAllEnabled:(BOOL)flag; +/*! + @method isEnabledKeyCharacter:modifierFlags: + @abstract Is hot key combination enabled. + @abstract Test to see if a key code and modifier flaf combination are enabled. + @param keyCharacter The key character used by the keyboard. + @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask, NSNumericPadKeyMask ). + @result Returns YES if enabled. + */ ++ (BOOL)isEnabledKeyCharacter:(unichar)keyCharacter modifierFlags:(NSUInteger)modifierFlags; /*! @method isEnabledKeyCode:modifierFlags: @abstract Is hot key combination enabled. @@ -113,18 +168,35 @@ extern const OSType NDHotKeyDefaultSignature; @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask ). @result Returns YES if enabled. */ -+ (BOOL)isEnabledKeyCode:(unsigned short)keyCode modifierFlags:(unsigned int)modifierFlags; ++ (BOOL)isEnabledKeyCode:(UInt16)keyCode modifierFlags:(NSUInteger)modifierFlags; +/*! + @method getHotKeyForKeyCharacter:modifierFlags: + @abstract Get an NDHotKeyEvent + @discussion Gets a NDHotKeyEvent for the supplied key code and modifer flags by either finding one that has already been created or by creating a new one.. + @param keyCharacter The key character used by the keyboard. + @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask, NSNumericPadKeyMask ). + @result The NDHotKeyEvent obejct or nil if failure. + */ ++ (NDHotKeyEvent *)getHotKeyForKeyCharacter:(unichar)keyCharacter modifierFlags:(NSUInteger)modifierFlags; /*! @method getHotKeyForKeyCode:modifierFlags: @abstract Get an NDHotKeyEvent @discussion Gets a NDHotKeyEvent for the supplied key code and modifer flags by either finding one that has already been created or by creating a new one.. @param keyCode The key code used by the keyboard, can vary across hardware. - @param aChar The character, used for display purposes only. @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask ). @result The NDHotKeyEvent obejct or nil if failure. */ -+ (NDHotKeyEvent *)getHotKeyForKeyCode:(unsigned short)keyCode character:(unichar)aChar modifierFlags:(unsigned int)modifierFlags; ++ (NDHotKeyEvent *)getHotKeyForKeyCode:(UInt16)keyCode modifierFlags:(NSUInteger)modifierFlags; +/*! + @method findHotKeyForKeyCharacter:modifierFlags: + @abstract Find an NDHotKeyEvent + @discussion Finds the NDHotKeyEvent for the supplied key code and modifer flags. + @param keyCharacter The key character used by the keyboard. + @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask, NSNumericPadKeyMask ). + @result The NDHotKeyEvent obejct or nil if none found. + */ ++ (NDHotKeyEvent *)findHotKeyForKeyCharacter:(unichar)keyCharacter modifierFlags:(NSUInteger)modifierFlags; /*! @method findHotKeyForKeyCode:modifierFlags: @abstract Find an NDHotKeyEvent @@ -133,31 +205,76 @@ extern const OSType NDHotKeyDefaultSignature; @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask ). @result The NDHotKeyEvent obejct or nil if none found. */ -+ (NDHotKeyEvent *)findHotKeyForKeyCode:(unsigned short)keyCode modifierFlags:(unsigned int)modifierFlags; ++ (NDHotKeyEvent *)findHotKeyForKeyCode:(UInt16)keyCode modifierFlags:(NSUInteger)modifierFlags; /*! - @method hotKeyWithKeyCode:character:modifierFlags: + @method findHotKeyForId: + @abstract Find an NDHotKeyEvent + @discussion Finds the NDHotKeyEvent for the with the given ID, you can find an already created NDHotKeyEvent but there is currently now way to create a new NDHotKeyEvent from a HotKey you create with Apple API's. + @param ID The hot key id as returned by hotKeyId + @result The NDHotKeyEvent obejct or nil if none found. + */ ++ (NDHotKeyEvent *)findHotKeyForId:(UInt32)ID; + +/*! + @method hotKeyWithEvent: + @abstract Get a NDHotKeyEvent object. + @discussion Returns a new hot key for the supplied event, if there is already a hot key for the supplied key code and modifer flags then nil is returned. + @param event The event generated from the user presssing the desired hot key combination. + @result An new NDHotKeyEvent or nil if failure. + */ ++ (id)hotKeyWithEvent:(NSEvent *)event; +/*! + @method hotKeyWithEvent:target:selector: + @abstract Get a NDHotKeyEvent object. + @discussion Returns a new hot key for the supplied event, if there is already a hot key for the supplied key code and modifer flags then nil is returned. + @param event The event generated from the user presssing the desired hot key combination. + @param target The target of hot key event. + @param selector The selector sent when hot key is released + @result An new NDHotKeyEvent or nil if failure. + */ ++ (id)hotKeyWithEvent:(NSEvent *)event target:(id)target selector:(SEL)selector; +/*! + @method hotKeyWithKeyCharacter:modifierFlags: + @abstract Get a NDHotKeyEvent object. + @discussion Returns a new hot key for the supplied hot key combination, if there is already a hot key for the supplied key code and modifer flags then nil is returned. + @param keyCharacter The key character used by the keyboard. + @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask, NSNumericPadKeyMask ). + @result An new NDHotKeyEvent or nil if failure. + */ ++ (id)hotKeyWithKeyCharacter:(unichar)keyCharacter modifierFlags:(NSUInteger)modifer; +/*! + @method hotKeyWithKeyCode:modifierFlags: @abstract Get a NDHotKeyEvent object. @discussion Returns a new hot key for the supplied hot key combination, if there is already a hot key for the supplied key code and modifer flags then nil is returned. @param keyCode The key code used by the keyboard, can vary across hardware. - @param aChar The character, used for display purposes only. @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask ). @result An new NDHotKeyEvent or nil if failure. */ -+ (id)hotKeyWithKeyCode:(unsigned short)keyCode character:(unichar)aChar modifierFlags:(unsigned int)modifer; ++ (id)hotKeyWithKeyCode:(UInt16)keyCode modifierFlags:(NSUInteger)modifer; /*! - @method hotKeyWithKeyCode:character:modifierFlags:target:selector: + @method hotKeyWithKeyCharacter:modifierFlags:target:selector: + @abstract Get a NDHotKeyEvent object. + @discussion Returns a new hot key for the supplied hot key combination and target object and selector, if there is already a hot key for the supplied key code and modifer flags then nil is returned. + @param keyCharacter The key character used by the keyboard. + @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask, NSNumericPadKeyMask ). + @param target The target of hot key event. + @param selector The selector sent when hot key is released + @result A new NDHotKeyEvent + */ ++ (id)hotKeyWithKeyCharacter:(unichar)keyCharacter modifierFlags:(NSUInteger)modifer target:(id)target selector:(SEL)selector; +/*! + @method hotKeyWithKeyCode:modifierFlags:target:selector: @abstract Get a NDHotKeyEvent object. @discussion Returns a new hot key for the supplied hot key combination and target object and selector, if there is already a hot key for the supplied key code and modifer flags then nil is returned. @param keyCode The key code used by the keyboard, can vary across hardware. - @param aChar The character, used for display purposes only. @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask ). @param target The target of hot key event. @param selector The selector sent when hot key is released @result A new NDHotKeyEvent */ -+ (id)hotKeyWithKeyCode:(unsigned short)keyCode character:(unichar)aChar modifierFlags:(unsigned int)modifer target:(id)target selector:(SEL)selector; ++ (id)hotKeyWithKeyCode:(UInt16)keyCode modifierFlags:(NSUInteger)modifer target:(id)target selector:(SEL)selector; /*! @method initWithPropertyList: @@ -167,29 +284,66 @@ extern const OSType NDHotKeyDefaultSignature; @result A initialized NDHotKeyEvent */ + (id)hotKeyWithWithPropertyList:(id)propertyList; +/*! + @method initWithEvent: + @abstract Initialize a NDHotKeyEvent object. + @discussion Initialize the reciever with the supplied hot key combination contained with the event event and target object and selector, if there is already a hot key for the supplied event then nil is returned. + @param event The key code used by the keyboard, can vary across hardware. + @result A initialized NDHotKeyEvent + */ +- (id)initWithEvent:(NSEvent *)event; +/*! + @method initWithEvent:target:selector: + @abstract Initialize a NDHotKeyEvent object. + @discussion Initialize the reciever with the supplied hot key combination contained with the event event and target object and selector, if there is already a hot key for the supplied event then nil is returned. + @param event An event used to create a hot key from. + @param target The target of hot key event. + @param selector The selector sent when hot key is released + @result A initialized NDHotKeyEvent + */ +- (id)initWithEvent:(NSEvent *)event target:(id)target selector:(SEL)selector; + +/*! + @method initWithKeyCode:character:modifierFlags:target:selector: + @abstract Initialize a NDHotKeyEvent object. + @discussion Initialize the reciever with the supplied hot key combination and target object and selector, if there is already a hot key for the supplied key code and modifer flags then nil is returned. + @param keyCharacter The key character used by the keyboard. + @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask, NSNumericPadKeyMask, NSNumericPadKeyMask ). + @param target The target of hot key event. + @param selector The selector sent when hot key is released + @result A initialized NDHotKeyEvent + */ +- (id)initWithKeyCharacter:(unichar)keyCharacter modifierFlags:(NSUInteger)modifer target:(id)target selector:(SEL)selector; /*! @method initWithKeyCode:character:modifierFlags:target:selector: @abstract Initialize a NDHotKeyEvent object. @discussion Initialize the reciever with the supplied hot key combination and target object and selector, if there is already a hot key for the supplied key code and modifer flags then nil is returned. @param keyCode The key code used by the keyboard, can vary across hardware. - @param aChar The character, used for display purposes only. @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask ). @param target The target of hot key event. @param selector The selector sent when hot key is released @result A initialized NDHotKeyEvent */ -- (id)initWithKeyCode:(unsigned short)keyCode character:(unichar)aChar modifierFlags:(unsigned int)modifer target:(id)target selector:(SEL)selector; +- (id)initWithKeyCode:(UInt16)keyCode modifierFlags:(NSUInteger)modifer target:(id)target selector:(SEL)selector; +/*! + @method initWithKeyCode:character:modifierFlags + @abstract Initialize a NDHotKeyEvent object. + @discussion Initialize the reciever with the supplied hot key combination, if there is already a hot key for the supplied key code and modifer flags then nil is returned. + @param keyCharacter The key character used by the keyboard. + @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask, NSNumericPadKeyMask ). + @result A initialized NDHotKeyEvent + */ +- (id)initWithKeyCharacter:(unichar)keyCharacter modifierFlags:(NSUInteger)modifer; /*! @method initWithKeyCode:character:modifierFlags @abstract Initialize a NDHotKeyEvent object. @discussion Initialize the reciever with the supplied hot key combination, if there is already a hot key for the supplied key code and modifer flags then nil is returned. @param keyCode The key code used by the keyboard, can vary across hardware. - @param aChar The character, used for display purposes only. @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask ). @result A initialized NDHotKeyEvent */ -- (id)initWithKeyCode:(unsigned short)keyCode character:(unichar)aChar modifierFlags:(unsigned int)modifer; +- (id)initWithKeyCode:(UInt16)keyCode modifierFlags:(NSUInteger)modifer; /*! @method initWithPropertyList: @@ -254,14 +408,14 @@ extern const OSType NDHotKeyDefaultSignature; */ - (void)encodeWithCoder:(NSCoder *)encoder; +- (BOOL)setEnabled:(BOOL)flag; /*! - @method setEnabled: + @method setIsEnabled: @abstract Set the hot key enabled or disable. @discussion setEnabled: registers or unregisters the recievers hot key combination. @param flag YES to enable, NO to disable. - @result Returns YES if successful */ -- (BOOL)setEnabled:(BOOL)flag; +- (void)setIsEnabled:(BOOL)flag; /*! @method isEnabled @@ -322,24 +476,45 @@ extern const OSType NDHotKeyDefaultSignature; /*! @method setTarget:selector: @abstract Set the hot key target. - @discussion Set the target object and selector to be sent when the hot key is released. - @param target The traget object. + @discussion Set the target object and selector to be sent when the hot key is released. The target needs to either respond to the method represented by the selector selector or to the method makeObjectsPerformSelector:withObject: in which case the method makeObjectsPerformSelector:withObject: is invoked with the selector selector, for example NSArray + @param target The traget object or a collection (for example NSArray) of target. @param selector The selector. @result returns YES if successful. */ - (BOOL)setTarget:(id)target selector:(SEL)selector; +#ifdef NS_BLOCKS_AVAILABLE +/*! + @method setBlock: + @abstract Set the hot key block called when the hot key is released. + @discussion Sets a block to be executed on hot key release. + @param block The block executed on key release, the block is passed the NDHotKeyEvent that represents the event. + @result returns YES if successful. + */ +- (BOOL)setBlock:(void(^)(NDHotKeyEvent*))block; +#endif /*! @method setTarget:selectorReleased:selectorPressed: @abstract Set the hot key target. - @discussion Set the target object and selector to be sent when the hot key is pressed and wehn it is released. - @param target The traget object. + @discussion Set the target object and selector to be sent when the hot key is pressed and wehn it is released. The target needs to either respond to the method represented by the selector selector or to the method makeObjectsPerformSelector:withObject: in which case the method makeObjectsPerformSelector:withObject: is invoked with the selector selector, for example NSArray + @param target The traget object or a collection (for example NSArray) of target. @param selectorReleased The key released selector. @param selectorPressed The key pressed selector. @result returns YES if successful. */ - (BOOL)setTarget:(id)target selectorReleased:(SEL)selectorReleased selectorPressed:(SEL)selectorPressed; +#ifdef NS_BLOCKS_AVAILABLE +/*! + @method setReleasedBlock:pressedBlock: + @abstract Set the hot key blocks called when the hot key is pressed and released. + @discussion Sets blocks to be executed on hot key released and pressed. + @param releasedBlock The block executed on key release, the block is passed the NDHotKeyEvent that represents the event. + @param pressedBlock The block executed on key pressed, the block is passed the NDHotKeyEvent that represents the event. + @result returns YES if successful. + */ +- (BOOL)setReleasedBlock:(void(^)(NDHotKeyEvent*))releasedBlock pressedBlock:(void(^)(NDHotKeyEvent*))pressedBlock; +#endif /*! @method performHotKeyReleased @abstract Invoke the target with the release selector. @@ -360,15 +535,15 @@ extern const OSType NDHotKeyDefaultSignature; @discussion The key code for the hot key, this is hardware specific. @result The key code. */ -- (unsigned short)keyCode; +- (UInt16)keyCode; /*! - @method character + @method keyCharacter @abstract Get the hot key character. @discussion This is the character for the key code, without modifier keys. The character is for display purposes only and dose not determine the key code. @result A uni code character. */ -- (unichar)character; +- (unichar)keyCharacter; /*! @method modifierFlags @@ -376,7 +551,14 @@ extern const OSType NDHotKeyDefaultSignature; @discussion The modifierFlags can be a bitwise and combination of NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask, and NSCommandKeyMask. @result The modifer key flags. */ -- (unsigned int)modifierFlags; +- (NSUInteger)modifierFlags; + +/*! + @method hotKeyId + @abstract Get the hot key id. + @discussion The id is how Apples 'Carbon Event Manager' keeps track of hot keys, if you want to use apples Hot Key function directly with NDHotKeyEvent then you can use the value returned from this method. + */ +- (UInt32)hotKeyId; /*! @method stringValue @@ -386,6 +568,16 @@ extern const OSType NDHotKeyDefaultSignature; */ - (NSString *)stringValue; +/*! + @methodgroup Deprecated Methods + */ + ++ (NDHotKeyEvent *)getHotKeyForKeyCode:(UInt16)keyCode character:(unichar)aChar modifierFlags:(NSUInteger)modifierFlags DEPRECATED_ATTRIBUTE; ++ (id)hotKeyWithKeyCode:(UInt16)keyCode character:(unichar)aChar modifierFlags:(NSUInteger)modifer DEPRECATED_ATTRIBUTE; ++ (id)hotKeyWithKeyCode:(UInt16)keyCode character:(unichar)aChar modifierFlags:(NSUInteger)modifer target:(id)target selector:(SEL)selector DEPRECATED_ATTRIBUTE; +- (id)initWithKeyCode:(UInt16)keyCode character:(unichar)aChar modifierFlags:(NSUInteger)modifer target:(id)target selector:(SEL)selector DEPRECATED_ATTRIBUTE; +- (id)initWithKeyCode:(UInt16)keyCode character:(unichar)aChar modifierFlags:(NSUInteger)modifer DEPRECATED_ATTRIBUTE; + @end /*! @@ -399,29 +591,10 @@ extern const OSType NDHotKeyDefaultSignature; @method targetWillChangeToObject:forHotKeyEvent: @abstract Message sent to a target object to inform it that the target is going to change. @discussion This method can be used to notify the receiver that it will no longer be the target for a NDHotKeyEvent or used to prevent the target from changing by returning NO - @param target The new target for the NDHotKeyEvent + @param target The new target for the NDHotKeyEvent or a collection (for example NSArray) of target. @param hotKeyEvent The NDHotKeyEvent for which the target is changing. @result Return NO to prevent the target from changing, otherwise return YES. */ - (BOOL)targetWillChangeToObject:(id)target forHotKeyEvent:(NDHotKeyEvent *)hotKeyEvent; @end - -/*! - @function stringForKeyCodeAndModifierFlags - @abstract Get a string for hot key parameters. - @discussion Returns a string representation of the passed in hot key values. - @param keyCode A key code. - @param aChar A character representation of the key code. - @param modifierFlags modifer flags, comman, option, shift and control. - @result A NSString representing the hot key combination. - */ -NSString * stringForKeyCodeAndModifierFlags( unsigned short keyCode, unichar aChar, unsigned int modifierFlags ); -/*! - @function unicharForKeyCode - @abstract Get a unicode charater for the key combination. - @discussion The uncode chararter for the key combination. - @param keyCode The key code used by the keyboard, can vary across hardware. - @result A unichar - */ -unichar unicharForKeyCode( unsigned short keyCode ); diff --git a/Frameworks/NDHotKey/NDHotKey/NDHotKeyEvent.m b/Frameworks/NDHotKey/NDHotKey/NDHotKeyEvent.m new file mode 100644 index 000000000..79f701f16 --- /dev/null +++ b/Frameworks/NDHotKey/NDHotKey/NDHotKeyEvent.m @@ -0,0 +1,924 @@ +/* + NDHotKeyEvent.m + + Created by Nathan Day on 21.06.06 under a MIT-style license. + Copyright (c) 2008 Nathan Day + + 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, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + 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. + */ + +#import "NDHotKeyEvent.h" +#import "NDKeyboardLayout.h" + +static const NSUInteger kNDHotKeyEventVersion = 2; + +@interface NDHotKeyEvent () +#ifdef NDMapTableClassDefined ++ (NSMapTable *)allHotKeyEvents; +#else ++ (NSHashTable *)allHotKeyEvents; +#endif +- (void)addHotKey; +- (void)removeHotKey; +- (BOOL)setCollectiveEnabled:(BOOL)aFlag; +- (BOOL)collectiveEnable; +@end + +static NSString * kArchivingKeyCodeKey = @"KeyCodeKey", + * kArchivingKeyCharacterKey = @"KeyCharacterKey", + * kArchivingModifierFlagsKey = @"ModifierFlagsKey", + * kArchivingSelectorReleasedCodeKey = @"SelectorReleasedCodeKey", + * kArchivingSelectorPressedCodeKey = @"SelectorPressedCodeKey"; +const OSType NDHotKeyDefaultSignature = 'NDHK'; + +static OSStatus switchHotKey( NDHotKeyEvent * self, BOOL aFlag ); + +@interface NDHotKeyEvent () +@end +/* + * class implementation NDHotKeyEvent + */ +@implementation NDHotKeyEvent + +#ifdef NDHotKeyEventThreadSafe + #warning Thread saftey has been enabled for NDHotKeyEvent class methods + #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4 + #define NDHotKeyEventLock @synchronized([self class]) { + #define NDHotKeyEventUnlock } + #else + static NSLock * hotKeysLock = nil; + #define NDHotKeyEventLock [hotKeysLock lock] + #define NDHotKeyEventUnlock [hotKeysLock unlock] + #endif +#else + #define NDHotKeyEventLock // lock + #define NDHotKeyEventUnlock // unlock +#endif + +#ifdef NDMapTableClassDefined +static NSMapTable * allHotKeyEvents = nil; +#else +static NSHashTable * allHotKeyEvents = NULL; +#endif +static EventHandlerRef hotKeysEventHandler = NULL; +static OSType signature = 0; + +static pascal OSErr eventHandlerCallback( EventHandlerCallRef anInHandlerCallRef, EventRef anInEvent, void * self ); + +#ifndef NDMapTableClassDefined +static NSUInteger hashValueHashFunction( NSHashTable * aTable, const void * aHotKeyEvent ); +static BOOL isEqualHashFunction( NSHashTable * aTable, const void * aFirstHotKeyEvent, const void * aSecondHotKeyEvent); +static NSString * describeHashFunction( NSHashTable * aTable, const void * aHotKeyEvent ); +#endif + +static UInt32 _idForCharacterAndModifer( unichar aCharacter, NSUInteger aModFlags ) { return (NSUInteger)aCharacter | (aModFlags<<16); } + +static void _getCharacterAndModiferForId( UInt32 anId, unichar *aCharacter, NSUInteger *aModFlags ) +{ + *aModFlags = anId>>16; + *aCharacter = anId&0xFFFF; +} + +struct HotKeyMappingEntry +{ + UInt32 hotKeyId; + NDHotKeyEvent * hotKeyEvent; +}; + ++ (BOOL)install +{ + if( hotKeysEventHandler == NULL ) + { + id theHotKeyEvents = [self allHotKeyEvents]; + EventTypeSpec theTypeSpec[] = + { + { kEventClassKeyboard, kEventHotKeyPressed }, + { kEventClassKeyboard, kEventHotKeyReleased } + }; + + NDHotKeyEventLock; + if( theHotKeyEvents != nil && hotKeysEventHandler == NULL ) + { + if( InstallEventHandler( GetEventDispatcherTarget(), NewEventHandlerUPP((EventHandlerProcPtr)eventHandlerCallback), 2, theTypeSpec, theHotKeyEvents, &hotKeysEventHandler ) != noErr ) + NSLog(@"Could not install Event handler"); + } + NDHotKeyEventUnlock; + } + + return hotKeysEventHandler != NULL; +} + ++ (void)uninstall +{ + if( hotKeysEventHandler != NULL ) + RemoveEventHandler( hotKeysEventHandler ); +} + ++ (void)initialize +{ + [NDHotKeyEvent setVersion:kNDHotKeyEventVersion]; // the character attribute has been removed +#ifdef NDHotKeyEventThreadSafe +#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4 + if( hotKeysLock == nil ) + { + NSLock * theInstance = [[NSLock alloc] init]; + + if( !CompareAndSwap( nil, (unsigned long int)theInstance, (unsigned long int*)&hotKeysLock) ) + [theInstance release]; // did not use instance + } +#endif +#endif +} + ++ (void)setSignature:(OSType)aSignature +{ + NSAssert( signature == 0 || aSignature == signature, @"The signature used by NDHotKeyEvent can only be set once safely" ); + signature = aSignature; +} + ++ (OSType)signature +{ + signature = signature ? signature : NDHotKeyDefaultSignature; + return signature; +} + ++ (BOOL)setAllEnabled:(BOOL)aFlag +{ + BOOL theAllSucceeded = YES; +#ifdef NDMapTableClassDefined + NSMapTable * theAllHotKeyEvents = [NDHotKeyEvent allHotKeyEvents]; +#else + NSHashTable * theAllHotKeyEvents = [NDHotKeyEvent allHotKeyEvents]; +#endif + + /* + * need to install before to make sure the method 'setCollectiveEnabled:' + * doesn't try install since install tries to aquire the lock 'hotKeysLock' + */ + if( theAllHotKeyEvents && [NDHotKeyEvent install] ) + { +#ifdef NDMapTableClassDefined + NDHotKeyEventLock; + for( NDHotKeyEvent * theHotEvent in [theAllHotKeyEvents objectEnumerator] ) + { + if( ![theHotEvent setCollectiveEnabled:aFlag] ) + theAllSucceeded = NO; + } + NDHotKeyEventUnlock; +#else + NSHashEnumerator theEnumerator; + struct HotKeyMappingEntry * theHotKeyMapEntry; + NDHotKeyEventLock; + theEnumerator = NSEnumerateHashTable( theAllHotKeyEvents ); + + while( (theHotKeyMapEntry = (struct HotKeyMappingEntry*)NSNextHashEnumeratorItem(&theEnumerator) ) ) + { + if( ![theHotKeyMapEntry->hotKeyEvent setCollectiveEnabled:aFlag] ) + theAllSucceeded = NO; + } + + NSEndHashTableEnumeration( &theEnumerator ); + NDHotKeyEventUnlock; +#endif + } + + return theAllSucceeded; +} + ++ (BOOL)isEnabledKeyCharacter:(unichar)aKeyCharacter modifierFlags:(NSUInteger)aModifierFlags +{ + return [[self findHotKeyForKeyCode:[[NDKeyboardLayout keyboardLayout] keyCodeForCharacter:aKeyCharacter numericPad:(aModifierFlags&NSNumericPadKeyMask) != 0] modifierFlags:aModifierFlags] isEnabled]; +} + ++ (BOOL)isEnabledKeyCode:(UInt16)aKeyCode modifierFlags:(NSUInteger)aModifierFlags +{ + return [[self findHotKeyForKeyCode:aKeyCode modifierFlags:aModifierFlags] isEnabled]; +} + ++ (NDHotKeyEvent *)getHotKeyForKeyCode:(UInt16)aKeyCode modifierFlags:(NSUInteger)aModifierFlags +{ + return [self getHotKeyForKeyCharacter:[[NDKeyboardLayout keyboardLayout] characterForKeyCode:aKeyCode] modifierFlags:aModifierFlags]; +} + +#pragma mark - finding hot key event objects ++ (NDHotKeyEvent *)getHotKeyForKeyCharacter:(unichar)aKeyCharacter modifierFlags:(NSUInteger)aModifierFlags +{ + NDHotKeyEvent * theHotKey = nil; + + theHotKey = [self findHotKeyForKeyCharacter:aKeyCharacter modifierFlags:aModifierFlags]; + return theHotKey ? theHotKey : [self hotKeyWithKeyCharacter:aKeyCharacter modifierFlags:aModifierFlags]; +} + ++ (NDHotKeyEvent *)findHotKeyForKeyCode:(UInt16)aKeyCode modifierFlags:(NSUInteger)aModifierFlags +{ + return [self findHotKeyForKeyCharacter:[[NDKeyboardLayout keyboardLayout] characterForKeyCode:aKeyCode] modifierFlags:aModifierFlags]; +} + ++ (NDHotKeyEvent *)findHotKeyForKeyCharacter:(unichar)aKeyCharacter modifierFlags:(NSUInteger)aModifierFlags +{ + return [self findHotKeyForId:_idForCharacterAndModifer(aKeyCharacter, aModifierFlags)]; +} + ++ (NDHotKeyEvent *)findHotKeyForId:(UInt32)anID +{ + NDHotKeyEvent * theResult = nil; +#ifdef NDMapTableClassDefined + NSMapTable * theAllHotKeyEvents = [NDHotKeyEvent allHotKeyEvents]; +#else + NSHashTable * theAllHotKeyEvents = [NDHotKeyEvent allHotKeyEvents]; +#endif + + if( theAllHotKeyEvents ) + { +#ifdef NDMapTableClassDefined + NDHotKeyEventLock; + theResult = [theAllHotKeyEvents objectForKey:[NSNumber numberWithUnsignedInt:anID]]; + NDHotKeyEventUnlock; +#else + struct HotKeyMappingEntry * theFoundEntry = NULL; + struct HotKeyMappingEntry theDummyEntry = {anID,nil}; + + NDHotKeyEventLock; + theFoundEntry = NSHashGet( theAllHotKeyEvents, (void*)&theDummyEntry); + if( theFoundEntry != NULL ) + [[theFoundEntry->hotKeyEvent retain] autorelease]; + NDHotKeyEventUnlock; + theResult = (theFoundEntry) ? theFoundEntry->hotKeyEvent : nil; +#endif + } + + return theResult; +} + ++ (id)hotKeyWithEvent:(NSEvent *)anEvent +{ + return [[[self alloc] initWithEvent:anEvent] autorelease]; +} + ++ (id)hotKeyWithEvent:(NSEvent *)anEvent target:(id)aTarget selector:(SEL)aSelector +{ + return [[[self alloc] initWithEvent:anEvent target:aTarget selector:aSelector] autorelease]; +} + ++ (id)hotKeyWithKeyCharacter:(unichar)aKeyCharacter modifierFlags:(NSUInteger)aModifierFlags +{ + return [[[self alloc] initWithKeyCharacter:aKeyCharacter modifierFlags:aModifierFlags target:nil selector:(SEL)0] autorelease]; +} + ++ (id)hotKeyWithKeyCode:(UInt16)aKeyCode modifierFlags:(NSUInteger)aModifierFlags +{ + return [[[self alloc] initWithKeyCode:aKeyCode modifierFlags:aModifierFlags target:nil selector:(SEL)0] autorelease]; +} + ++ (id)hotKeyWithKeyCharacter:(unichar)aKeyCharacter modifierFlags:(NSUInteger)aModifierFlags target:(id)aTarget selector:(SEL)aSelector +{ + return [[[self alloc] initWithKeyCharacter:aKeyCharacter modifierFlags:aModifierFlags target:aTarget selector:aSelector] autorelease]; +} + ++ (id)hotKeyWithKeyCode:(UInt16)aKeyCode modifierFlags:(NSUInteger)aModifierFlags target:(id)aTarget selector:(SEL)aSelector +{ + return [[[self alloc] initWithKeyCode:aKeyCode modifierFlags:aModifierFlags target:aTarget selector:aSelector] autorelease]; +} + ++ (id)hotKeyWithWithPropertyList:(id)aPropertyList +{ + return [[[self alloc] initWithPropertyList:aPropertyList] autorelease]; +} + ++ (NSString *)description +{ +#ifdef NDMapTableClassDefined + NSMapTable * theAllHotKeyEvents = [NDHotKeyEvent allHotKeyEvents]; +#else + NSHashTable * theAllHotKeyEvents = [NDHotKeyEvent allHotKeyEvents]; +#endif + NSString * theDescription = nil; + if( theAllHotKeyEvents ) + { + NDHotKeyEventLock; +#ifdef NDMapTableClassDefined + theDescription = [theAllHotKeyEvents description]; +#else + theDescription = NSStringFromHashTable(theAllHotKeyEvents); +#endif + NDHotKeyEventUnlock; + } + return theDescription; +} + +#pragma mark - creation and destruction +- (id)init +{ + [self release]; + NSAssert( NO, @"You can not initialize a Hot Key with the init method" ); + return nil; +} + +- (id)initWithEvent:(NSEvent *)anEvent +{ + return [self initWithEvent:anEvent target:nil selector:NULL]; +} + +- (id)initWithEvent:(NSEvent *)anEvent target:(id)aTarget selector:(SEL)aSelector +{ + unsigned long theModifierFlags = [anEvent modifierFlags] & (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask|NSCommandKeyMask); + + return [self initWithKeyCode:[anEvent keyCode] + modifierFlags:theModifierFlags + target:aTarget + selector:aSelector]; +} + +- (id)initWithKeyCharacter:(unichar)aKeyCharacter modifierFlags:(NSUInteger)aModifierFlags +{ + return [self initWithKeyCode:[[NDKeyboardLayout keyboardLayout] keyCodeForCharacter:aKeyCharacter numericPad:(aModifierFlags&NSNumericPadKeyMask) != 0] modifierFlags:aModifierFlags target:nil selector:NULL]; +} + +- (id)initWithKeyCode:(UInt16)aKeyCode modifierFlags:(NSUInteger)aModifierFlags +{ + return [self initWithKeyCode:aKeyCode modifierFlags:aModifierFlags target:nil selector:NULL]; +} + +- (id)initWithKeyCode:(UInt16)aKeyCode modifierFlags:(NSUInteger)aModifierFlags target:(id)aTarget selector:(SEL)aSelector +{ + return [self initWithKeyCharacter:[[NDKeyboardLayout keyboardLayout] characterForKeyCode:aKeyCode] modifierFlags:aModifierFlags target:aTarget selector:aSelector]; +} + +- (id)initWithKeyCharacter:(unichar)aKeyCharacter modifierFlags:(NSUInteger)aModifierFlags target:(id)aTarget selector:(SEL)aSelector +{ + if( (self = [super init]) != nil ) + { + keyCharacter = aKeyCharacter; + modifierFlags = aModifierFlags; + target = aTarget; + selectorReleased = aSelector; + currentEventType = NDHotKeyNoEvent; + isEnabled.collective = YES; + [self addHotKey]; + } + else + [self release], self = nil; + + return self; +} + +- (id)initWithCoder:(NSCoder *)aDecoder +{ + if( (self = [super init]) != nil) + { + if( [aDecoder allowsKeyedCoding] ) + { + NSNumber * theValue = [aDecoder decodeObjectForKey:kArchivingKeyCharacterKey]; + if( theValue == nil ) + { + theValue = [aDecoder decodeObjectForKey:kArchivingKeyCodeKey]; + keyCharacter = [[NDKeyboardLayout keyboardLayout] characterForKeyCode:[theValue unsignedShortValue]]; + } + else + keyCharacter = [theValue unsignedShortValue]; + modifierFlags = [[aDecoder decodeObjectForKey:kArchivingModifierFlagsKey] unsignedIntegerValue]; + + selectorReleased = NSSelectorFromString( [aDecoder decodeObjectForKey:kArchivingSelectorReleasedCodeKey] ); + selectorPressed = NSSelectorFromString( [aDecoder decodeObjectForKey:kArchivingSelectorPressedCodeKey] ); + } + else + { + if( [aDecoder versionForClassName:@"NDHotKeyNoEvent"] == 1 ) + { + unsigned short theKeyCode; + [aDecoder decodeValueOfObjCType:@encode(UInt16) at:&theKeyCode]; + keyCharacter = [[NDKeyboardLayout keyboardLayout] characterForKeyCode:theKeyCode]; + } + else + [aDecoder decodeValueOfObjCType:@encode(unichar) at:&keyCharacter]; + [aDecoder decodeValueOfObjCType:@encode(NSUInteger) at:&modifierFlags]; + + selectorReleased = NSSelectorFromString( [aDecoder decodeObject] ); + selectorPressed = NSSelectorFromString( [aDecoder decodeObject] ); + } + + [self addHotKey]; + } + + return self; +} + +- (void)encodeWithCoder:(NSCoder *)anEncoder +{ + if( [anEncoder allowsKeyedCoding] ) + { + [anEncoder encodeObject:[NSNumber numberWithUnsignedShort:keyCharacter] forKey:kArchivingKeyCharacterKey]; + [anEncoder encodeObject:[NSNumber numberWithUnsignedInteger:modifierFlags] forKey:kArchivingModifierFlagsKey]; + + [anEncoder encodeObject:NSStringFromSelector( selectorReleased ) forKey:kArchivingSelectorReleasedCodeKey]; + [anEncoder encodeObject:NSStringFromSelector( selectorPressed ) forKey:kArchivingSelectorPressedCodeKey]; + } + else + { + [anEncoder encodeValueOfObjCType:@encode(unichar) at:&keyCharacter]; + [anEncoder encodeValueOfObjCType:@encode(NSUInteger) at:&modifierFlags]; + + [anEncoder encodeObject:NSStringFromSelector( selectorReleased )]; + [anEncoder encodeObject:NSStringFromSelector( selectorPressed )]; + } +} + +- (id)initWithPropertyList:(id)aPropertyList +{ + if( aPropertyList ) + { + NSNumber * theKeyCode, + * theModiferFlag; + + theKeyCode = [aPropertyList objectForKey:kArchivingKeyCodeKey]; + theModiferFlag = [aPropertyList objectForKey:kArchivingModifierFlagsKey]; + + if( (self = [self initWithKeyCode:[theKeyCode unsignedShortValue] modifierFlags:[theModiferFlag unsignedIntValue]]) != nil ) + { + selectorPressed = NSSelectorFromString([aPropertyList objectForKey:kArchivingSelectorPressedCodeKey]); + selectorReleased = NSSelectorFromString([aPropertyList objectForKey:kArchivingSelectorReleasedCodeKey]); + } + } + else + [self release], self = nil; + + return self; +} + +- (id)propertyList +{ + return [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithUnsignedShort:[self keyCode]], kArchivingKeyCodeKey, + [NSNumber numberWithUnsignedInt:[self modifierFlags]], kArchivingModifierFlagsKey, + NSStringFromSelector( selectorPressed ), kArchivingSelectorPressedCodeKey, + NSStringFromSelector( selectorReleased ), kArchivingSelectorReleasedCodeKey, + nil]; +} + +- (oneway void)release +{ + /* + * We need to remove the hot key from the hash table before it's retain count reaches zero + */ + if( [self retainCount] == 1 ) + { +#ifdef NDMapTableClassDefined + NSMapTable * theAllHotKeyEvents = [NDHotKeyEvent allHotKeyEvents]; +#else + NSHashTable * theAllHotKeyEvents = [NDHotKeyEvent allHotKeyEvents]; +#endif + if( theAllHotKeyEvents ) + { +#ifndef NDMapTableClassDefined + struct HotKeyMappingEntry theDummyEntry = {[self hotKeyId],nil}; +#endif + NDHotKeyEventLock; + if( [self retainCount] == 1 ) // check again because it might have changed + { + switchHotKey( self, NO ); +#ifdef NDMapTableClassDefined + [theAllHotKeyEvents removeObjectForKey:[NSNumber numberWithUnsignedInt:[self hotKeyId]]]; +#else + id theHotKeyEvent = NSHashGet( theAllHotKeyEvents, (void*)&theDummyEntry ); + if( theHotKeyEvent ) + NSHashRemove( theAllHotKeyEvents, theHotKeyEvent ); +#endif + } + NDHotKeyEventUnlock; + } + } + [super release]; +} + +#if 0 +- (void)dealloc +{ + if( reference ) + { + if( UnregisterEventHotKey( reference ) != noErr ) // in lock from release + NSLog( @"Failed to unregister hot key %@", self ); + } + [super dealloc]; +} +#endif + +- (BOOL)setEnabled:(BOOL)aFlag +{ + BOOL theResult = YES; + + if( [NDHotKeyEvent install] ) + { + /* + * if individual and collective YES then currently ON, otherwise currently off + */ + NDHotKeyEventLock; + if( aFlag == YES && isEnabled.collective == YES && isEnabled.individual == NO ) + theResult = (switchHotKey( self, YES ) == noErr); + else if( aFlag == NO && isEnabled.collective == YES && isEnabled.individual == YES ) + theResult = (switchHotKey( self, NO ) == noErr); + NDHotKeyEventUnlock; + + if( theResult ) + isEnabled.individual = aFlag; + else + NSLog(@"%s failed ", aFlag ? "enable" : "disable" ); + } + else + theResult = NO; + + return theResult; +} + +- (void)setIsEnabled:(BOOL)aFlag { [self setEnabled:aFlag]; } + +- (BOOL)isEnabled { return isEnabled.individual && isEnabled.collective; } +- (id)target { return target; } +- (SEL)selector { return selectorReleased; } +- (SEL)selectorReleased { return selectorReleased; } +- (SEL)selectorPressed { return selectorPressed; } +- (int)currentEventType { return currentEventType; } // (NDHotKeyNoEvent | NDHotKeyPressedEvent | NDHotKeyReleasedEvent) +- (BOOL)setTarget:(id)aTarget selector:(SEL)aSelector { return [self setTarget:aTarget selectorReleased:aSelector selectorPressed:(SEL)0]; } + +#ifdef NS_BLOCKS_AVAILABLE +- (BOOL)setBlock:(void(^)(NDHotKeyEvent*))aBlock { return [self setReleasedBlock:aBlock pressedBlock:nil]; } +#endif + +- (BOOL)setTarget:(id)aTarget selectorReleased:(SEL)aSelectorReleased selectorPressed:(SEL)aSelectorPressed +{ + BOOL theResult = NO; + [self setEnabled:NO]; + if( target != nil && target != aTarget ) + { + if( ![target respondsToSelector:@selector(targetWillChangeToObject:forHotKeyEvent:)] || [target targetWillChangeToObject:aTarget forHotKeyEvent:self] ) + { + target = aTarget; + theResult = YES; + } + } + else + { + target = aTarget; + theResult = YES; + } + + selectorReleased = aSelectorReleased; + selectorPressed = aSelectorPressed; + +#ifdef NS_BLOCKS_AVAILABLE + [releasedBlock release], releasedBlock = nil; + [pressedBlock release], pressedBlock = nil; +#endif + + return theResult; // was change succesful +} + +#ifdef NS_BLOCKS_AVAILABLE +- (BOOL)setReleasedBlock:(void(^)(NDHotKeyEvent*))aReleasedBlock pressedBlock:(void(^)(NDHotKeyEvent*))aPressedBlock +{ + BOOL theResult = NO; + [self setEnabled:NO]; + if( ![target respondsToSelector:@selector(targetWillChangeToObject:forHotKeyEvent:)] || [target targetWillChangeToObject:nil forHotKeyEvent:self] ) + { + if( releasedBlock != aReleasedBlock ) + [releasedBlock release], releasedBlock = [aReleasedBlock copy]; + + if( pressedBlock != aPressedBlock ) + [pressedBlock release], pressedBlock = [aPressedBlock copy]; + + selectorReleased = (SEL)0; + selectorPressed = (SEL)0; + theResult = YES; + } + + return theResult; // was change succesful +} +#endif + +- (void)performHotKeyReleased +{ + NSAssert( target != nil || releasedBlock != nil, @"Release hot key fired without target or release block" ); + + currentEventType = NDHotKeyReleasedEvent; + if( selectorReleased ) + { + if([target respondsToSelector:selectorReleased]) + [target performSelector:selectorReleased withObject:self]; + else if( [target respondsToSelector:@selector(makeObjectsPerformSelector:withObject:)] ) + [target makeObjectsPerformSelector:selectorReleased withObject:self]; + } +#ifdef NS_BLOCKS_AVAILABLE + else if( releasedBlock ) + releasedBlock(self); +#endif + currentEventType = NDHotKeyNoEvent; +} + +- (void)performHotKeyPressed +{ + NSAssert( target != nil || pressedBlock != nil, @"Release hot key fired without target or pressed block" ); + + currentEventType = NDHotKeyPressedEvent; + if( selectorPressed ) + { + if([target respondsToSelector:selectorPressed]) + [target performSelector:selectorPressed withObject:self]; + else if( [target respondsToSelector:@selector(makeObjectsPerformSelector:withObject:)] ) + [target makeObjectsPerformSelector:selectorPressed withObject:self]; + } +#ifdef NS_BLOCKS_AVAILABLE + else if( pressedBlock ) + pressedBlock(self); +#endif + + currentEventType = NDHotKeyNoEvent; +} + +- (unichar)keyCharacter { return keyCharacter; } +- (BOOL)keyPad { return keyPad; } +- (UInt16)keyCode { return [[NDKeyboardLayout keyboardLayout] keyCodeForCharacter:self.keyCharacter numericPad:self.keyPad]; } +- (NSUInteger)modifierFlags { return modifierFlags; } +- (UInt32)hotKeyId { return _idForCharacterAndModifer( self.keyCharacter, self.modifierFlags ); } +- (NSString *)stringValue { return [[NDKeyboardLayout keyboardLayout] stringForKeyCode:[self keyCode] modifierFlags:[self modifierFlags]]; } + +- (BOOL)isEqual:(id)anObject +{ + return [super isEqual:anObject] || ([anObject isKindOfClass:[self class]] == YES && [self keyCode] == [(NDHotKeyEvent*)anObject keyCode] && [self modifierFlags] == [anObject modifierFlags]); +} + +- (NSUInteger)hash { return (NSUInteger)self.keyCharacter | (self.modifierFlags<<16); } + +- (NSString *)description +{ + return [NSString stringWithFormat:@"{\n\tKey Combination: %@,\n\tEnabled: %s\n\tKey Press Selector: %@\n\tKey Release Selector: %@\n}\n", + [self stringValue], + [self isEnabled] ? "yes" : "no", + NSStringFromSelector([self selectorPressed]), + NSStringFromSelector([self selectorReleased])]; +} + +pascal OSErr eventHandlerCallback( EventHandlerCallRef anInHandlerCallRef, EventRef anInEvent, void * anInUserData ) +{ +// NSHashTable * allHotKeyEvents = (NSHashTable *)anInUserData; + EventHotKeyID theHotKeyID; + OSStatus theError; + + NSCAssert( GetEventClass( anInEvent ) == kEventClassKeyboard, @"Got event that is not a hot key event" ); + + theError = GetEventParameter( anInEvent, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(EventHotKeyID), NULL, &theHotKeyID ); + + if( theError == noErr ) + { + NDHotKeyEvent * theHotKeyEvent; + UInt32 theEventKind; + + NSCAssert( [NDHotKeyEvent signature] == theHotKeyID.signature, @"Got hot key event with wrong signature" ); + + theHotKeyEvent = [NDHotKeyEvent findHotKeyForId:theHotKeyID.id]; + + theEventKind = GetEventKind( anInEvent ); + if( kEventHotKeyPressed == theEventKind ) + [theHotKeyEvent performHotKeyPressed]; + else if( kEventHotKeyReleased == theEventKind ) + [theHotKeyEvent performHotKeyReleased]; + } + + return theError; +} + +#ifndef NDMapTableClassDefined + +NSUInteger hashValueHashFunction( NSHashTable * aTable, const void * aHotKeyEntry ) +{ + struct HotKeyMappingEntry * theHotKeyEntry = (struct HotKeyMappingEntry*)aHotKeyEntry; + return theHotKeyEntry->hotKeyId; +} + +BOOL isEqualHashFunction( NSHashTable * aTable, const void * aFirstHotKeyEntry, const void * aSecondHotKeyEntry) +{ + struct HotKeyMappingEntry * theFirst = (struct HotKeyMappingEntry*)aFirstHotKeyEntry, + * theSecond = (struct HotKeyMappingEntry*)aSecondHotKeyEntry; + return theFirst->hotKeyId == theSecond->hotKeyId; +} + +NSString * describeHashFunction( NSHashTable * aTable, const void * aHotKeyEntry ) +{ + NDHotKeyEvent * theHotKey; + + theHotKey = ((struct HotKeyMappingEntry*)aHotKeyEntry)->hotKeyEvent; + return [theHotKey description]; +} +#endif + +#pragma mark Private methods + +#ifdef NDMapTableClassDefined ++ (NSMapTable *)allHotKeyEvents +{ + if( allHotKeyEvents == NULL ) + { + NDHotKeyEventLock; + if( allHotKeyEvents == NULL ) + allHotKeyEvents = [[NSMapTable alloc] initWithKeyOptions:NSMapTableStrongMemory valueOptions:NSMapTableZeroingWeakMemory capacity:0]; + NDHotKeyEventUnlock; + } + return allHotKeyEvents; +} +#else + ++ (NSHashTable *)allHotKeyEvents +{ + if( allHotKeyEvents == NULL ) + { + NSHashTableCallBacks theHashCallBacks; + + theHashCallBacks.hash = hashValueHashFunction; + theHashCallBacks.isEqual = isEqualHashFunction; + theHashCallBacks.retain = NULL; + theHashCallBacks.release = NULL; + theHashCallBacks.describe = describeHashFunction; + + NDHotKeyEventLock; + if( allHotKeyEvents == NULL ) + allHotKeyEvents = NSCreateHashTableWithZone( theHashCallBacks, 0, NULL); + NDHotKeyEventUnlock; + } + + return allHotKeyEvents; +} +#endif + +- (void)addHotKey +{ + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardLayoutSelectedKeyboardInputSourceChangedNotification:) name:NDKeyboardLayoutSelectedKeyboardInputSourceChangedNotification object:nil]; +#ifdef NDMapTableClassDefined + NSMapTable * theAllHotKeyEvents = [NDHotKeyEvent allHotKeyEvents]; +#else + NSHashTable * theAllHotKeyEvents = [NDHotKeyEvent allHotKeyEvents]; +#endif + if( theAllHotKeyEvents ) + { + NDHotKeyEventLock; +#ifdef NDMapTableClassDefined + [theAllHotKeyEvents setObject:self forKey:[NSNumber numberWithUnsignedInt:[self hotKeyId]]]; +#else + struct HotKeyMappingEntry * theEntry = (struct HotKeyMappingEntry *)malloc(sizeof(struct HotKeyMappingEntry)); + theEntry->hotKeyId = [self hotKeyId]; + theEntry->hotKeyEvent = self; + + NSParameterAssert( NSHashInsertIfAbsent( theAllHotKeyEvents, (void*)theEntry ) == NULL ); +#endif + NDHotKeyEventUnlock; + } +} + +- (void)keyboardLayoutSelectedKeyboardInputSourceChangedNotification:(NSNotification*)aNotification +{ + if( self.isEnabled ) // if enable re-eable using new keyCode + switchHotKey( self, YES ); +} + +- (void)removeHotKey +{ + [self setEnabled:NO]; + +#ifdef NDMapTableClassDefined + NSMapTable * theAllHotKeyEvents = [NDHotKeyEvent allHotKeyEvents]; +#else + NSHashTable * theAllHotKeyEvents = [NDHotKeyEvent allHotKeyEvents]; +#endif + + if( theAllHotKeyEvents ) + { +#ifndef NDMapTableClassDefined + struct HotKeyMappingEntry theDummyEntry = {[self hotKeyId],nil}; + struct HotKeyMappingEntry * theEntry = NULL; +#endif + NDHotKeyEventLock; +#ifdef NDMapTableClassDefined + [theAllHotKeyEvents removeObjectForKey:[NSNumber numberWithUnsignedInt:[self hotKeyId]]]; +#else + theEntry = (struct HotKeyMappingEntry*)NSHashGet( theAllHotKeyEvents, (void*)&theDummyEntry); + if( theEntry ) + { + NSParameterAssert( theEntry->hotKeyEvent == self ); + NSHashRemove( theAllHotKeyEvents, theEntry ); + } +#endif + NDHotKeyEventUnlock; + } +} + +- (BOOL)setCollectiveEnabled:(BOOL)aFlag +{ + BOOL theResult = YES; + + if( [NDHotKeyEvent install] ) + { + /* + * if individual and collective YES then currently ON, otherwise currently off + */ + NDHotKeyEventLock; + if( aFlag == YES && isEnabled.collective == NO && isEnabled.individual == YES ) + theResult = (switchHotKey( self, YES ) == noErr); + else if( aFlag == NO && isEnabled.collective == YES && isEnabled.individual == YES ) + theResult = (switchHotKey( self, NO ) == noErr); + NDHotKeyEventUnlock; + + if( theResult ) + isEnabled.collective = aFlag; + else + NSLog(@"%s failed", aFlag ? "enable" : "disable" ); + } + else + theResult = NO; + + return theResult; +} + +- (BOOL)collectiveEnable { return isEnabled.collective; } + +static OSStatus switchHotKey( NDHotKeyEvent * self, BOOL aFlag ) +{ + OSStatus theError = noErr; + if( aFlag ) + { + EventHotKeyID theHotKeyID; + + if( self->reference ) + theError = UnregisterEventHotKey( self->reference ); + if( theError == noErr ) + { + theHotKeyID.signature = [NDHotKeyEvent signature]; + theHotKeyID.id = [self hotKeyId]; + + NSCAssert( theHotKeyID.signature, @"HotKeyEvent signature has not been set yet" ); + NSCParameterAssert(sizeof(unsigned long) >= sizeof(id) ); + + theError = RegisterEventHotKey( self.keyCode, NDCarbonModifierFlagsForCocoaModifierFlags(self->modifierFlags), theHotKeyID, GetEventDispatcherTarget(), 0, &self->reference ); + } + } + else + { + theError = UnregisterEventHotKey( self->reference ); + self->reference = 0; + } + + return theError; +} + +#pragma mark - Deprecated Methods + ++ (NDHotKeyEvent *)getHotKeyForKeyCode:(UInt16)aKeyCode character:(unichar)aChar modifierFlags:(NSUInteger)aModifierFlags +{ + return [self getHotKeyForKeyCode:aKeyCode modifierFlags:aModifierFlags]; +} + +/* + * +hotKeyWithKeyCode:character:modifierFlags: + */ ++ (id)hotKeyWithKeyCode:(UInt16)aKeyCode character:(unichar)aChar modifierFlags:(NSUInteger)aModifierFlags +{ + return [self hotKeyWithKeyCode:aKeyCode modifierFlags:aModifierFlags target:nil selector:NULL]; +} + +/* + * +hotKeyWithKeyCode:character:modifierFlags:target:selector: + */ ++ (id)hotKeyWithKeyCode:(UInt16)aKeyCode character:(unichar)aChar modifierFlags:(NSUInteger)aModifierFlags target:(id)aTarget selector:(SEL)aSelector +{ + return [[[self alloc] initWithKeyCode:aKeyCode modifierFlags:aModifierFlags target:aTarget selector:aSelector] autorelease]; +} + +/* + * -initWithKeyCode:character:modifierFlags: + */ +- (id)initWithKeyCode:(UInt16)aKeyCode character:(unichar)aChar modifierFlags:(NSUInteger)aModifierFlags +{ + return [self initWithKeyCode:aKeyCode modifierFlags:aModifierFlags target:nil selector:NULL]; +} + +/* + * -initWithKeyCode:character:modifierFlags:target:selector: + */ +- (id)initWithKeyCode:(UInt16)aKeyCode character:(unichar)aChar modifierFlags:(NSUInteger)aModifierFlags target:(id)aTarget selector:(SEL)aSelector +{ + return [self initWithKeyCode:aKeyCode modifierFlags:aModifierFlags target:aTarget selector:aSelector]; +} + +@end diff --git a/Frameworks/NDHotKey/NDHotKey/NDKeyboardLayout.h b/Frameworks/NDHotKey/NDHotKey/NDKeyboardLayout.h new file mode 100644 index 000000000..31c6101b2 --- /dev/null +++ b/Frameworks/NDHotKey/NDHotKey/NDKeyboardLayout.h @@ -0,0 +1,135 @@ +/* + NDKeyboardLayout.h + + Created by Nathan Day on 01.18.10 under a MIT-style license. + Copyright (c) 2010 Nathan Day + + 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, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + 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. + */ + +/*! + @header NDKeyboardLayout.h + @abstract Header file for NDKeyboardLayout + @author Nathan Day + */ + +#import +#import +#import + +struct ReverseMappingEntry; + +extern NSString * const NDKeyboardLayoutSelectedKeyboardInputSourceChangedNotification; +extern NSString * const NDKeyboardLayoutPreviousKeyboardLayoutUserInfoKey; + +/*! + @function NDCocoaModifierFlagsForCarbonModifierFlags + Convert Carbon modifer flags to Cocoa modifier flags. + @param modifierFlags one or more of the flags shiftKey, controlKey, optionKey, cmdKey + */ +NSUInteger NDCocoaModifierFlagsForCarbonModifierFlags( NSUInteger modifierFlags ); +/*! + @function NDCarbonModifierFlagsForCocoaModifierFlags + Convert Cocoa modifer flags to Carbon modifier flags. + @param modifierFlags one or more of the flags NSShiftKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSCommandKeyMask + */ +NSUInteger NDCarbonModifierFlagsForCocoaModifierFlags( NSUInteger modifierFlags ); + +/*! + @class NDKeyboardLayout + @abstract Class for translating between key codes and key characters. + @discussion The key code for each key character can change between hardware and with localisation, NDKeyboardLayout handles translation between key codes and key characters as well as for generating strings for display purposes. + @helps Used by NDHotKeyEvent. + */ +@interface NDKeyboardLayout : NSObject +{ +@private + CFDataRef keyboardLayoutData; + struct ReverseMappingEntry * mappings; + NSUInteger numberOfMappings; +} + +/*! + @method keyboardLayout + Get a keyboard layout for the current keyboard + */ ++ (id)keyboardLayout; + +/*! + @method init + initialise a keyboard layout for the current keyboard, if that fails a keyboard layout for one of the languages + returned from [NSLocale preferredLanguages] is attempted and if finally if that fails a keyboard layout + for the most recently used ASCII-capable keyboard is created. If that fails then this method returns nil. + */ +- (id)init; +/*! + @method initWithLanguage: + @abstract initialise a keyboard layout. + @discussion Initialises a KeyboardLayout with an TISInputSourceRef for the supplied language. + */ +- (id)initWithLanguage:(NSString *)langauge; +/*! + @method initWithInputSource: + @abstract initialise a keyboard layout. + @discussion Initialises a KeyboardLayout with an TISInputSourceRef, this method is called with the result from initWithInputSource:TISCopyCurrentKeyboardInputSource(). + */ +- (id)initWithInputSource:(TISInputSourceRef)source; + +/*! + @method stringForCharacter:modifierFlags: + @abstract Get a string for display purposes. + @discussion stringForCharacter:modifierFlags: returns a string that can be displayed to the user, For example command-z would produce ⌘Z, shift-T would produce ⇧T. + @param character The unmodified character on the keyboard. + @param modifierFlags Modifier flags NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask, NSCommandKeyMask and NSNumericPadKeyMask. + */ +- (NSString*)stringForCharacter:(unichar)character modifierFlags:(UInt32)modifierFlags; +/*! + @method stringForKeyCode:modifierFlags: + @abstract Get a string for display purposes. + @discussion stringForKeyCode:modifierFlags: returns a string that can be displayed to the user. This method is called by stringForCharacter::modifierFlags and is problem more useful most of the time. + @param keyCode A value specifying the virtual key code that is to be translated. For ADB keyboards, virtual key codes are in the range from 0 to 127. + @param modifierFlags Modifier flags NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask, NSCommandKeyMask and NSNumericPadKeyMask. + */ +- (NSString*)stringForKeyCode:(UInt16)keyCode modifierFlags:(UInt32)modifierFlags; +/*! + @method characterForKeyCode: + @abstract Get the key character for a given key code. + @discussion The character returned is the unmodified version on the keyboard. + @param keyCode A value specifying the virtual key code that is to be translated. For ADB keyboards, virtual key codes are in the range from 0 to 127. + @result The character for the unmodified version of the key. + */ +- (unichar)characterForKeyCode:(UInt16)keyCode; +/*! + @method keyCodeForCharacter:numericPad: + @abstract Get the key code for a given key character. + @discussion The character pass in must be the unshifter character for the key, for example to get the key code for the '?' on keyboards where you type shift-/ to get '?' you should pass in the character '/" + @param character The unmodified character on the keyboard. + @param numericPad For the keycode of a key on the keypad where the same character is also on the main keyboard this flag needs to be YES. + */ +- (UInt16)keyCodeForCharacter:(unichar)character numericPad:(BOOL)numericPad; +/*! + @method keyCodeForCharacter: + @abstract Get the key code for a given key character. + @discussion Calls keyCodeForCharacter:numericPad: with the keypad flag set to NO + @param character The unmodified character on the keyboard. + @result A value specifying the virtual key code that is to be translated. For ADB keyboards, virtual key codes are in the range from 0 to 127. + */ +- (UInt16)keyCodeForCharacter:(unichar)character; + +@end diff --git a/Frameworks/NDHotKey/NDHotKey/NDKeyboardLayout.m b/Frameworks/NDHotKey/NDHotKey/NDKeyboardLayout.m new file mode 100644 index 000000000..ee46ec8a6 --- /dev/null +++ b/Frameworks/NDHotKey/NDHotKey/NDKeyboardLayout.m @@ -0,0 +1,485 @@ +/* + NDKeyboardLayout.m + + Created by Nathan Day on 01.18.10 under a MIT-style license. + Copyright (c) 2010 Nathan Day + + 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, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + 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. + */ + +#import "NDKeyboardLayout.h" +#include + +NSString * const NDKeyboardLayoutSelectedKeyboardInputSourceChangedNotification = @"NDKeyboardLayoutSelectedKeyboardInputSourceChanged"; +NSString * const NDKeyboardLayoutPreviousKeyboardLayoutUserInfoKey = @"NDKeyboardLayoutPreviousKeyboardLayout"; + +struct ReverseMappingEntry +{ + UniChar character; + BOOL keypad; + UInt16 keyCode; +}; + +struct UnmappedEntry +{ + UniChar character; + UInt16 keyCode; + unichar description[4]; +}; + +struct UnmappedEntry unmappedKeys[] = +{ + {NSDeleteFunctionKey, 0x33, {0x232B,'\0','\0','\0'}}, + {NSF17FunctionKey, 0x40, {'F','1','7','\0'}}, + {NSClearDisplayFunctionKey, 0x47, {0x2327,'\0','\0','\0'}}, + {NSF18FunctionKey, 0x4F, {'F','1','8','\0'}}, + {NSF19FunctionKey, 0x50, {'F','1','9','\0'}}, + {NSF5FunctionKey, 0x60, {'F','5','\0','\0'}}, + {NSF6FunctionKey, 0x61, {'F','6','\0','\0'}}, + {NSF7FunctionKey, 0x62, {'F','7','\0','\0'}}, + {NSF3FunctionKey, 0x63, {'F','3','\0','\0'}}, + {NSF8FunctionKey, 0x64, {'F','8','\0','\0'}}, + {NSF9FunctionKey, 0x65, {'F','9','\0','\0'}}, + {NSF11FunctionKey, 0x67, {'F','1','1','\0'}}, + {NSF14FunctionKey, 0x68, {'F','1','4','\0'}}, + {NSF13FunctionKey, 0x69, {'F','1','3','\0'}}, + {NSF16FunctionKey, 0x6A, {'F','1','6','\0'}}, + {NSF10FunctionKey, 0x6D, {'F','1','0','\0'}}, + {NSF12FunctionKey, 0x6F, {'F','1','2','\0'}}, + {NSF15FunctionKey, 0x71, {'F','1','5','\0'}}, + {NSHomeFunctionKey, 0x73, {0x21F1,'\0','\0','\0'}}, + {NSPageUpFunctionKey, 0x74, {0x21DE,'\0','\0','\0'}}, + {NSDeleteCharFunctionKey, 0x75, {0x2326,'\0','\0','\0'}}, + {NSF4FunctionKey, 0x76, {'F','4','\0','\0'}}, + {NSEndFunctionKey, 0x77, {0x21F2,'\0','\0','\0'}}, + {NSF2FunctionKey, 0x78, {'F','2','\0','\0'}}, + {NSPageDownFunctionKey, 0x79, {0x21DF,'\0','\0','\0'}}, + {NSF1FunctionKey, 0x7A, {'F','1','\0','\0'}}, + {NSLeftArrowFunctionKey, 0x7B, {0x2190,'\0','\0','\0'}}, + {NSRightArrowFunctionKey, 0x7C, {0x2192,'\0','\0','\0'}}, + {NSDownArrowFunctionKey, 0x7D, {0x2193,'\0','\0','\0'}}, + {NSUpArrowFunctionKey, 0x7E, {0x2191,'\0','\0','\0'}} +// {NSF20FunctionKey, 0xXXXX}, +// {NSF21FunctionKey, 0xXXXX}, +// {NSF22FunctionKey, 0xXXXX}, +// {NSF23FunctionKey, 0xXXXX}, +// {NSF24FunctionKey, 0xXXXX}, +// {NSF25FunctionKey, 0xXXXX}, +// {NSF26FunctionKey, 0xXXXX}, +// {NSF27FunctionKey, 0xXXXX}, +// {NSF28FunctionKey, 0xXXXX}, +// {NSF29FunctionKey, 0xXXXX}, +// {NSF30FunctionKey, 0xXXXX}, +// {NSF31FunctionKey, 0xXXXX}, +// {NSF32FunctionKey, 0xXXXX}, +// {NSF33FunctionKey, 0xXXXX}, +// {NSF34FunctionKey, 0xXXXX}, +// {NSF35FunctionKey, 0xXXXX}, +// {NSInsertFunctionKey, 0xXXXX}, +// {NSBeginFunctionKey, 0xXXXX}, +// {NSPrintScreenFunctionKey, 0xXXXX}, +// {NSScrollLockFunctionKey, 0xXXXX}, +// {NSPauseFunctionKey, 0xXXXX}, +// {NSSysReqFunctionKey, 0xXXXX}, +// {NSBreakFunctionKey, 0xXXXX}, +// {NSResetFunctionKey, 0xXXXX}, +// {NSStopFunctionKey, 0xXXXX}, +// {NSMenuFunctionKey, 0xXXXX}, +// {NSUserFunctionKey, 0xXXXX}, +// {NSSystemFunctionKey, 0xXXXX}, +// {NSPrintFunctionKey, 0xXXXX}, +// {NSClearLineFunctionKey, 0xXXXX}, +// {NSInsertLineFunctionKey, 0xXXXX}, +// {NSDeleteLineFunctionKey, 0xXXXX}, +// {NSInsertCharFunctionKey, 0xXXXX}, +// {NSPrevFunctionKey, 0xXXXX}, +// {NSNextFunctionKey, 0xXXXX}, +// {NSSelectFunctionKey, 0xXXXX}, +// {NSExecuteFunctionKey, 0xXXXX}, +// {NSUndoFunctionKey, 0xXXXX}, +// {NSRedoFunctionKey, 0xXXXX}, +// {NSFindFunctionKey, 0xXXXX}, +// {NSHelpFunctionKey, 0xXXXX}, +// {NSModeSwitchFunctionKey, 0xXXXX} +}; + +@interface NDKeyboardLayout () + +@property(readonly,nonatomic) const UCKeyboardLayout * keyboardLayoutPtr; + +@end + +static int _reverseMappingEntryCmpFunc( const void * a, const void * b ) +{ + struct ReverseMappingEntry * theA = (struct ReverseMappingEntry*)a, + * theB = (struct ReverseMappingEntry*)b; + return theA->character != theB->character ? theA->character - theB->character : theA->keypad - theB->keypad; +} + +static struct ReverseMappingEntry * _searchreverseMapping( struct ReverseMappingEntry * aMapping, NSUInteger aLength, struct ReverseMappingEntry * aSearchValue ) +{ + NSInteger low = 0, + high = aLength - 1, + mid, + result; + + while( low <= high ) + { + mid = (low + high)>>1; + result = _reverseMappingEntryCmpFunc( &aMapping[mid], aSearchValue ); + if( result > 0 ) + high = mid - 1; + else if( result < 0 ) + low = mid + 1; + else + return &aMapping[mid]; + } + return NULL; +} + +static struct UnmappedEntry * _unmappedEntryForKeyCode( UInt16 aKeyCode ) +{ + NSInteger low = 0, + high = sizeof(unmappedKeys)/sizeof(*unmappedKeys) - 1, + mid, + result; + + while( low <= high ) + { + mid = (low + high)>>1; + result = unmappedKeys[mid].keyCode - aKeyCode; + if( result > 0 ) + high = mid - 1; + else if( result < 0 ) + low = mid + 1; + else + return &unmappedKeys[mid]; + } + return '\0'; +} + +static const size_t kBufferSize = 4; +static NSUInteger _characterForModifierFlags( unichar aBuff[kBufferSize], UInt32 aModifierFlags ) +{ + NSUInteger thePos = 0; + memset( aBuff, 0, kBufferSize ); + if(aModifierFlags & NSControlKeyMask) + aBuff[thePos++] = kControlUnicode; + + if(aModifierFlags & NSAlternateKeyMask) + aBuff[thePos++] = kOptionUnicode; + + if(aModifierFlags & NSShiftKeyMask) + aBuff[thePos++] = kShiftUnicode; + + if(aModifierFlags & NSCommandKeyMask) + aBuff[thePos++] = kCommandUnicode; + return thePos; +} + +/* + * NDCocoaModifierFlagsForCarbonModifierFlags() + */ +NSUInteger NDCocoaModifierFlagsForCarbonModifierFlags( NSUInteger aModifierFlags ) +{ + NSUInteger theCocoaModifierFlags = 0; + + if(aModifierFlags & shiftKey) + theCocoaModifierFlags |= NSShiftKeyMask; + + if(aModifierFlags & controlKey) + theCocoaModifierFlags |= NSControlKeyMask; + + if(aModifierFlags & optionKey) + theCocoaModifierFlags |= NSAlternateKeyMask; + + if(aModifierFlags & cmdKey) + theCocoaModifierFlags |= NSCommandKeyMask; + + return theCocoaModifierFlags; +} + +/* + * NDCarbonModifierFlagsForCocoaModifierFlags() + */ +NSUInteger NDCarbonModifierFlagsForCocoaModifierFlags( NSUInteger aModifierFlags ) +{ + NSUInteger theCarbonModifierFlags = 0; + + if(aModifierFlags & NSShiftKeyMask) + theCarbonModifierFlags |= shiftKey; + + if(aModifierFlags & NSControlKeyMask) + theCarbonModifierFlags |= controlKey; + + if(aModifierFlags & NSAlternateKeyMask) + theCarbonModifierFlags |= optionKey; + + if(aModifierFlags & NSCommandKeyMask) + theCarbonModifierFlags |= cmdKey; + + return theCarbonModifierFlags; +} + +@implementation NDKeyboardLayout + +#pragma mark Utility Methods + +- (void)generateMappings +{ + mappings = (struct ReverseMappingEntry*)calloc( 128 + sizeof(unmappedKeys)/sizeof(*unmappedKeys), sizeof(struct ReverseMappingEntry) ); + + numberOfMappings = 0; + + for( NSUInteger i = 0; i < 128; i++ ) + { + UInt32 theDeadKeyState = 0; + UniCharCount theLength = 0; + + if( UCKeyTranslate( self.keyboardLayoutPtr, + i, + kUCKeyActionDisplay, + 0, + LMGetKbdType(), + kUCKeyTranslateNoDeadKeysBit, + &theDeadKeyState, + 1, + &theLength, + &mappings[numberOfMappings].character ) == noErr && theLength > 0 && isprint(mappings[numberOfMappings].character) ) + { + mappings[numberOfMappings].keyCode = i; + numberOfMappings++; + } + } + + /* add unmapped keys */ + for( NSUInteger i = 0; i < sizeof(unmappedKeys)/sizeof(*unmappedKeys); i++ ) + { + mappings[numberOfMappings].character = unmappedKeys[i].character; + mappings[numberOfMappings].keyCode = unmappedKeys[i].keyCode; + numberOfMappings++; + } + + mappings = (struct ReverseMappingEntry*)realloc( (void*)mappings, numberOfMappings*sizeof(struct ReverseMappingEntry) ); + + // sort so we can perform binary searches + qsort( (void *)mappings, numberOfMappings, sizeof(struct ReverseMappingEntry), _reverseMappingEntryCmpFunc ); + + /* find keypad keys and set the keypad flag */ + for( NSUInteger i = 1; i < numberOfMappings; i++ ) + { + NSParameterAssert( mappings[i-1].keyCode != mappings[i].keyCode ); + if( mappings[i-1].character == mappings[i].character ) // assume large keycode is a keypad + { + if( mappings[i-1].keyCode > mappings[i].keyCode ) // make the keypad entry is second + { + UInt16 theTemp = mappings[i-1].keyCode; + mappings[i-1].keyCode = mappings[i].keyCode; + mappings[i].keyCode = theTemp; + } + mappings[i].keypad = YES; + } + } + +#ifdef DEBUGGING_CODE + for( NSUInteger i = 1; i < numberOfMappings; i++ ) + { + fprintf( stderr, "%d -> %c[%d]%s\n", + mappings[i].keyCode, + (char)mappings[i].character, + mappings[i].character, + mappings[i].keypad ? " keypad" : "" + ); + NSAssert3( mappings[i-1].character <= mappings[i].character, @"[%d] %d <= %d", i, mappings[i-1].character, mappings[i].character ); + } +#endif +} + +#pragma mark Constructor Methods + +static volatile NDKeyboardLayout * kCurrentKeyboardLayout = nil; + +void NDKeyboardLayoutNotificationCallback( CFNotificationCenterRef aCenter, void * self, CFStringRef aName, const void * anObj, CFDictionaryRef aUserInfo ) +{ + NSDictionary * theUserInfo = [NSDictionary dictionaryWithObject:kCurrentKeyboardLayout forKey:NDKeyboardLayoutPreviousKeyboardLayoutUserInfoKey]; + @synchronized(self) { [kCurrentKeyboardLayout release], kCurrentKeyboardLayout = nil; } + [[NSNotificationCenter defaultCenter] postNotificationName:NDKeyboardLayoutSelectedKeyboardInputSourceChangedNotification object:self userInfo:theUserInfo]; +} + ++ (void)initialize +{ + CFNotificationCenterAddObserver( CFNotificationCenterGetLocalCenter(), + (const void *)self, + NDKeyboardLayoutNotificationCallback, + kTISNotifySelectedKeyboardInputSourceChanged, + NULL, + CFNotificationSuspensionBehaviorDeliverImmediately + ); +} + ++ (id)keyboardLayout +{ + if( kCurrentKeyboardLayout == nil ) + { + @synchronized(self) + { /* + Try different method until we succeed. + */ + TISInputSourceRef (*theInputSourceFunctions[])() = { + TISCopyInputMethodKeyboardLayoutOverride, + TISCopyCurrentKeyboardLayoutInputSource, + TISCopyCurrentASCIICapableKeyboardLayoutInputSource + }; + + for( NSUInteger i = 0; i < sizeof(theInputSourceFunctions)/sizeof(*theInputSourceFunctions) && kCurrentKeyboardLayout == nil; i++ ) + { + TISInputSourceRef theInputSource = theInputSourceFunctions[i](); + if( theInputSource != NULL ) + { + kCurrentKeyboardLayout = [[self alloc] initWithInputSource:theInputSource]; + CFRelease(theInputSource); + } + } + } + } + + return kCurrentKeyboardLayout; +} + +- (id)init +{ + [self release]; + return [[NDKeyboardLayout keyboardLayout] retain]; +} + +- (id)initWithLanguage:(NSString *)aLangauge { return [self initWithInputSource:TISCopyInputSourceForLanguage((CFStringRef)aLangauge)]; } + +- (id)initWithInputSource:(TISInputSourceRef)aSource +{ + if( (self = [super init]) != nil ) + { + if( aSource != NULL && (keyboardLayoutData = (CFDataRef)CFMakeCollectable(TISGetInputSourceProperty(aSource, kTISPropertyUnicodeKeyLayoutData))) != nil ) + { + CFRetain( keyboardLayoutData ); + } + else + self = nil, [self release]; + } + return self; +} + +- (void)dealloc +{ + if( mappings != NULL ) + free( (void*)mappings ); + if( keyboardLayoutData != NULL ) + CFRelease( keyboardLayoutData ); + [super dealloc]; +} + +- (NSString*)stringForCharacter:(unichar)aCharacter modifierFlags:(UInt32)aModifierFlags +{ + return [self stringForKeyCode:[self keyCodeForCharacter:aCharacter numericPad:(aModifierFlags&NSNumericPadKeyMask) != 0] modifierFlags:aModifierFlags]; +} + +- (NSString*)stringForKeyCode:(UInt16)aKeyCode modifierFlags:(UInt32)aModifierFlags +{ + NSString * theResult = nil; + struct UnmappedEntry * theEntry = _unmappedEntryForKeyCode( aKeyCode ); // is it one of the unmapped values + + if( theEntry != NULL ) + { + unichar theCharacter[sizeof(theEntry->description)/sizeof(*theEntry->description)+4+1]; + memset( theCharacter, 0, sizeof(theCharacter) ); + NSUInteger thePos = _characterForModifierFlags(theCharacter,aModifierFlags); + memcpy( theCharacter+thePos, theEntry->description, sizeof(theEntry->description) ); + theResult = [NSString stringWithCharacters:theCharacter length:sizeof(theEntry->description)/sizeof(*theEntry->description)+thePos]; + } + else + { + UInt32 theDeadKeyState = 0; + UniCharCount theLength = 0; + UniChar theCharacter[260]; + + NSUInteger thePos = _characterForModifierFlags(theCharacter,aModifierFlags); + + if( UCKeyTranslate( self.keyboardLayoutPtr, aKeyCode, + kUCKeyActionDisplay, + NDCarbonModifierFlagsForCocoaModifierFlags(aModifierFlags), + LMGetKbdType(), + kUCKeyTranslateNoDeadKeysBit, + &theDeadKeyState, + sizeof(theCharacter)/sizeof(*theCharacter)-thePos, + &theLength, + theCharacter+thePos ) == noErr ) + { + + theResult = [[NSString stringWithCharacters:theCharacter length:theLength+thePos] uppercaseString]; + } + } + return theResult; +} + +- (unichar)characterForKeyCode:(UInt16)aKeyCode +{ + unichar theChar = 0; + struct UnmappedEntry * theEntry = _unmappedEntryForKeyCode( aKeyCode ); + + if( theEntry == NULL ) // is it one of the unmapped values + { + UInt32 theDeadKeyState = 0; + UniCharCount theLength = 0; + UniChar theCharacter[256]; + + if( UCKeyTranslate( self.keyboardLayoutPtr, aKeyCode, + kUCKeyActionDisplay, + 0, + LMGetKbdType(), + kUCKeyTranslateNoDeadKeysBit, + &theDeadKeyState, + sizeof(theCharacter)/sizeof(*theCharacter), + &theLength, + theCharacter ) == noErr ) + { + theChar = theCharacter[0]; + } + } + else + theChar = theEntry->character; + return toupper(theChar); +} + +- (UInt16)keyCodeForCharacter:(unichar)aCharacter { return [self keyCodeForCharacter:aCharacter numericPad:NO]; } + +- (UInt16)keyCodeForCharacter:(unichar)aCharacter numericPad:(BOOL)aNumericPad +{ + struct ReverseMappingEntry theSearchValue = { tolower(aCharacter), aNumericPad, 0 }; + struct ReverseMappingEntry * theEntry = NULL; + if( mappings == NULL ) + [self generateMappings]; + theEntry = _searchreverseMapping( mappings, numberOfMappings, &theSearchValue ); + return theEntry ? theEntry->keyCode : '\0'; +} + +#pragma mark - private + +- (const UCKeyboardLayout *)keyboardLayoutPtr { return (const UCKeyboardLayout *)CFDataGetBytePtr(keyboardLayoutData); } + +@end + diff --git a/Frameworks/NDHotKey/NDHotKey/en.lproj/InfoPlist.strings b/Frameworks/NDHotKey/NDHotKey/en.lproj/InfoPlist.strings new file mode 100644 index 000000000..477b28ff8 --- /dev/null +++ b/Frameworks/NDHotKey/NDHotKey/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/Preferences/General/English.lproj/Preferences.xib b/Preferences/General/English.lproj/Preferences.xib index c40407990..fbb5f04a6 100644 --- a/Preferences/General/English.lproj/Preferences.xib +++ b/Preferences/General/English.lproj/Preferences.xib @@ -32,39 +32,6 @@ - - - @@ -128,18 +95,6 @@ - @@ -150,7 +105,6 @@ - diff --git a/Preferences/General/General.xcodeproj/project.pbxproj b/Preferences/General/General.xcodeproj/project.pbxproj index f5b77e3b4..005c90740 100644 --- a/Preferences/General/General.xcodeproj/project.pbxproj +++ b/Preferences/General/General.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ 17E78B6A0D68C1E3005C5A59 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = 17E78B680D68C1E3005C5A59 /* Preferences.xib */; }; 8384917718084D9F00E7332D /* appearance.png in Resources */ = {isa = PBXBuildFile; fileRef = 8384917518084D9F00E7332D /* appearance.png */; }; 8384917818084D9F00E7332D /* growl.png in Resources */ = {isa = PBXBuildFile; fileRef = 8384917618084D9F00E7332D /* growl.png */; }; + 8384918C1808596A00E7332D /* NDHotKey.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 838491841808588D00E7332D /* NDHotKey.framework */; }; 83EF495F17FBC96A00642E3C /* VolumeBehaviorArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = 83EF495E17FBC96A00642E3C /* VolumeBehaviorArrayController.m */; }; 8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; }; 8E07AA880AAC8EA200A4B32F /* HotKeyPane.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E07AA810AAC8EA200A4B32F /* HotKeyPane.m */; }; @@ -28,13 +29,41 @@ 8E07AA8A0AAC8EA200A4B32F /* GeneralPreferencesPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E07AA850AAC8EA200A4B32F /* GeneralPreferencesPlugin.m */; }; 8E07ABDD0AAC95BC00A4B32F /* hot_keys.png in Resources */ = {isa = PBXBuildFile; fileRef = 8E07ABDB0AAC95BC00A4B32F /* hot_keys.png */; }; 8E15A86C0B894768006DC802 /* updates.png in Resources */ = {isa = PBXBuildFile; fileRef = 8E15A86B0B894768006DC802 /* updates.png */; }; - 8E6C12160AACAE4100819171 /* NDHotKeyControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E6C12130AACAE4100819171 /* NDHotKeyControl.m */; }; - 8E6C12170AACAE4100819171 /* NDHotKeyEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E6C12150AACAE4100819171 /* NDHotKeyEvent.m */; }; 8E6C123A0AACAEF200819171 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E6C12390AACAEF200819171 /* Carbon.framework */; }; 8E6C13A00AACBAB500819171 /* HotKeyControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E6C139F0AACBAB500819171 /* HotKeyControl.m */; }; 99F1813F0DE01D7A00FD5FFB /* PlaylistBehaviorArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = 99F1813E0DE01D7A00FD5FFB /* PlaylistBehaviorArrayController.m */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 838491831808588D00E7332D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8384917F1808588D00E7332D /* NDHotKey.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 32F1615614E6BB3B00D6AB2F; + remoteInfo = NDHotKey; + }; + 838491891808594800E7332D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8384917F1808588D00E7332D /* NDHotKey.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 32F1615514E6BB3B00D6AB2F; + remoteInfo = NDHotKey; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8384918B1808595500E7332D /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 8384918C1808596A00E7332D /* NDHotKey.framework in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; 089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -59,6 +88,7 @@ 8384913618081ECB00E7332D /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../Utils/Logging.h; sourceTree = ""; }; 8384917518084D9F00E7332D /* appearance.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = appearance.png; path = Icons/appearance.png; sourceTree = ""; }; 8384917618084D9F00E7332D /* growl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = growl.png; path = Icons/growl.png; sourceTree = ""; }; + 8384917F1808588D00E7332D /* NDHotKey.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = NDHotKey.xcodeproj; path = ../../Frameworks/NDHotKey/NDHotKey.xcodeproj; sourceTree = ""; }; 83EF495D17FBC96A00642E3C /* VolumeBehaviorArrayController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VolumeBehaviorArrayController.h; sourceTree = ""; }; 83EF495E17FBC96A00642E3C /* VolumeBehaviorArrayController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VolumeBehaviorArrayController.m; sourceTree = ""; }; 8D5B49B6048680CD000E48DA /* General.preferencePane */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = General.preferencePane; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -71,10 +101,6 @@ 8E07AA850AAC8EA200A4B32F /* GeneralPreferencesPlugin.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = GeneralPreferencesPlugin.m; sourceTree = ""; }; 8E07ABDB0AAC95BC00A4B32F /* hot_keys.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = hot_keys.png; path = Icons/hot_keys.png; sourceTree = ""; }; 8E15A86B0B894768006DC802 /* updates.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = updates.png; path = Icons/updates.png; sourceTree = ""; }; - 8E6C12120AACAE4100819171 /* NDHotKeyControl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = NDHotKeyControl.h; sourceTree = ""; }; - 8E6C12130AACAE4100819171 /* NDHotKeyControl.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = NDHotKeyControl.m; sourceTree = ""; }; - 8E6C12140AACAE4100819171 /* NDHotKeyEvent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = NDHotKeyEvent.h; sourceTree = ""; }; - 8E6C12150AACAE4100819171 /* NDHotKeyEvent.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = NDHotKeyEvent.m; sourceTree = ""; }; 8E6C12390AACAEF200819171 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; 8E6C139E0AACBAB500819171 /* HotKeyControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HotKeyControl.h; sourceTree = ""; }; 8E6C139F0AACBAB500819171 /* HotKeyControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HotKeyControl.m; sourceTree = ""; }; @@ -145,6 +171,7 @@ 1058C7ACFEA557BF11CA2CBB /* Linked Frameworks */ = { isa = PBXGroup; children = ( + 8384917F1808588D00E7332D /* NDHotKey.xcodeproj */, 8E6C12390AACAEF200819171 /* Carbon.framework */, 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */, ); @@ -179,10 +206,6 @@ children = ( 170744AB0BFF3938002475C9 /* AppcastArrayController.h */, 170744AC0BFF3938002475C9 /* AppcastArrayController.m */, - 8E6C12120AACAE4100819171 /* NDHotKeyControl.h */, - 8E6C12130AACAE4100819171 /* NDHotKeyControl.m */, - 8E6C12140AACAE4100819171 /* NDHotKeyEvent.h */, - 8E6C12150AACAE4100819171 /* NDHotKeyEvent.m */, 8E6C139E0AACBAB500819171 /* HotKeyControl.h */, 8E6C139F0AACBAB500819171 /* HotKeyControl.m */, 17C643370B8A77CC00C53518 /* OutputsArrayController.h */, @@ -211,6 +234,14 @@ name = "Other Sources"; sourceTree = ""; }; + 838491801808588D00E7332D /* Products */ = { + isa = PBXGroup; + children = ( + 838491841808588D00E7332D /* NDHotKey.framework */, + ); + name = Products; + sourceTree = ""; + }; 8E07ABD90AAC95AF00A4B32F /* Icons */ = { isa = PBXGroup; children = ( @@ -237,10 +268,12 @@ 8D5B49AF048680CD000E48DA /* Resources */, 8D5B49B1048680CD000E48DA /* Sources */, 8D5B49B3048680CD000E48DA /* Frameworks */, + 8384918B1808595500E7332D /* CopyFiles */, ); buildRules = ( ); dependencies = ( + 8384918A1808594800E7332D /* PBXTargetDependency */, ); name = General; productInstallPath = "$(HOME)/Library/Bundles"; @@ -272,6 +305,12 @@ ); mainGroup = 089C166AFE841209C02AAC07 /* General */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 838491801808588D00E7332D /* Products */; + ProjectRef = 8384917F1808588D00E7332D /* NDHotKey.xcodeproj */; + }, + ); projectRoot = ""; targets = ( 8D5B49AC048680CD000E48DA /* General */, @@ -279,6 +318,16 @@ }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + 838491841808588D00E7332D /* NDHotKey.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = NDHotKey.framework; + remoteRef = 838491831808588D00E7332D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXResourcesBuildPhase section */ 8D5B49AF048680CD000E48DA /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -309,8 +358,6 @@ 8E07AA880AAC8EA200A4B32F /* HotKeyPane.m in Sources */, 8E07AA890AAC8EA200A4B32F /* GeneralPreferencePane.m in Sources */, 8E07AA8A0AAC8EA200A4B32F /* GeneralPreferencesPlugin.m in Sources */, - 8E6C12160AACAE4100819171 /* NDHotKeyControl.m in Sources */, - 8E6C12170AACAE4100819171 /* NDHotKeyEvent.m in Sources */, 8E6C13A00AACBAB500819171 /* HotKeyControl.m in Sources */, 83EF495F17FBC96A00642E3C /* VolumeBehaviorArrayController.m in Sources */, 17C643380B8A77CC00C53518 /* OutputsArrayController.m in Sources */, @@ -322,6 +369,14 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 8384918A1808594800E7332D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = NDHotKey; + targetProxy = 838491891808594800E7332D /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin PBXVariantGroup section */ 178E386D0C3DA64500EE6711 /* InfoPlist.strings */ = { isa = PBXVariantGroup; diff --git a/Preferences/General/HotKeyControl.h b/Preferences/General/HotKeyControl.h index 2143afab0..9c5a77ad5 100644 --- a/Preferences/General/HotKeyControl.h +++ b/Preferences/General/HotKeyControl.h @@ -7,22 +7,9 @@ // #import -#import "NDHotKeyControl.h" +#import @interface HotKeyControl : NDHotKeyControl { - BOOL observing; } -- (void)enableAllHotKeys; -- (void)disableAllHotKeys; - -- (void)startObserving; -- (void)stopObserving; - -- (void)setKeyCode: (unsigned short)k; -- (void)setCharacter: (unichar)c; -- (void)setModifierFlags: (unsigned long)m; - -- (void)updateStringValue; - @end diff --git a/Preferences/General/HotKeyControl.m b/Preferences/General/HotKeyControl.m index 93ac047d6..0b54d40ff 100644 --- a/Preferences/General/HotKeyControl.m +++ b/Preferences/General/HotKeyControl.m @@ -7,113 +7,15 @@ // #import "HotKeyControl.h" -#import "NDHotKeyEvent.h" - -typedef int CGSConnection; -typedef enum { - CGSGlobalHotKeyEnable = 0, - CGSGlobalHotKeyDisable = 1, -} CGSGlobalHotKeyOperatingMode; - -extern CGSConnection _CGSDefaultConnection(void); - -extern CGError CGSGetGlobalHotKeyOperatingMode( - CGSConnection connection, CGSGlobalHotKeyOperatingMode *mode); - -extern CGError CGSSetGlobalHotKeyOperatingMode(CGSConnection connection, - CGSGlobalHotKeyOperatingMode mode); +#import @implementation HotKeyControl -- (void)awakeFromNib -{ - observing = NO; -} - -- (void)disableAllHotKeys -{ - CGSConnection conn = _CGSDefaultConnection(); - CGSSetGlobalHotKeyOperatingMode(conn, CGSGlobalHotKeyDisable); -} - -- (void)enableAllHotKeys -{ - CGSConnection conn = _CGSDefaultConnection(); - CGSSetGlobalHotKeyOperatingMode(conn, CGSGlobalHotKeyEnable); -} - -- (void)startObserving -{ - [self disableAllHotKeys]; - - observing = YES; - [self setStringValue:NSLocalizedStringFromTableInBundle(@"Press Key...", nil, [NSBundle bundleForClass:[self class]], @"")]; -} - -- (void)stopObserving -{ - [self enableAllHotKeys]; - observing = NO; - - [self updateStringValue]; -} - -- (BOOL)becomeFirstResponder -{ - [self startObserving]; - - return YES; -} - -- (BOOL)resignFirstResponder -{ - [self stopObserving]; - - return YES; -} - -- (BOOL)performKeyEquivalent:(NSEvent*)anEvent -{ - if (observing == YES) - { - return [super performKeyEquivalent:anEvent]; - } - else - { - return NO; - } -} - -- (void)keyDown:(NSEvent *)theEvent -{ - if (observing == YES) - { - [super keyDown:theEvent]; - } -} - - (void)mouseDown:(NSEvent *)theEvent { - [self startObserving]; + [self setStringValue:NSLocalizedStringFromTableInBundle(@"Press Key...", nil, [NSBundle bundleForClass:[self class]], @"")]; + [self setRequiresModifierKeys:YES]; + [self setReadyForHotKeyEvent:YES]; } -- (void)setKeyCode: (unsigned short)k -{ - keyCode = k; -} - -- (void)setCharacter: (unichar)c -{ - character = c; -} - -- (void)setModifierFlags: (unsigned long)m -{ - modifierFlags = m; -} - -- (void)updateStringValue -{ - [self setStringValue:stringForKeyCodeAndModifierFlags( keyCode, character, modifierFlags )]; -} @end diff --git a/Preferences/General/HotKeyPane.h b/Preferences/General/HotKeyPane.h index bd131235c..7fca954ec 100644 --- a/Preferences/General/HotKeyPane.h +++ b/Preferences/General/HotKeyPane.h @@ -17,11 +17,6 @@ IBOutlet HotKeyControl *spamHotKeyControl; } -- (IBAction) grabPlayHotKey:(id)sender; -- (IBAction) grabPrevHotKey:(id)sender; -- (IBAction) grabNextHotKey:(id)sender; -- (IBAction) grabSpamHotKey:(id)sender; - - (IBAction) hotKeyChanged:(id)sender; @end diff --git a/Preferences/General/HotKeyPane.m b/Preferences/General/HotKeyPane.m index 818ae8c74..76facfc78 100644 --- a/Preferences/General/HotKeyPane.m +++ b/Preferences/General/HotKeyPane.m @@ -7,113 +7,56 @@ // #import "HotKeyPane.h" -#import "NDHotKeyEvent.h" +#import "NDHotKey/NDHotKeyEvent.h" +#import "NDHotKey/NDKeyboardLayout.h" +#import "HotKeyControl.h" @implementation HotKeyPane +static void setControlText(HotKeyControl* control, NSString* kcprop, NSString* mprop) +{ + UInt16 keyCode = [[NSUserDefaults standardUserDefaults] integerForKey:kcprop]; + NSUInteger modifiers = [[NSUserDefaults standardUserDefaults] integerForKey:mprop]; + NSString *str = [[NDKeyboardLayout keyboardLayout] stringForKeyCode:keyCode modifierFlags:modifiers]; + [control setStringValue:str]; +} + - (void)awakeFromNib { -// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object: [view window]]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidResignKey:) name:NSWindowDidResignKeyNotification object: [view window]]; - - [prevHotKeyControl setKeyCode: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeyPreviousKeyCode"] ]; - [prevHotKeyControl setCharacter: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeyPreviousCharacter"] ]; - [prevHotKeyControl setModifierFlags: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeyPreviousModifiers"] ]; - - [prevHotKeyControl updateStringValue]; - - [nextHotKeyControl setKeyCode: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeyNextKeyCode"] ]; - [nextHotKeyControl setCharacter: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeyNextCharacter"] ]; - [nextHotKeyControl setModifierFlags: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeyNextModifiers"] ]; - - [nextHotKeyControl updateStringValue]; - - [playHotKeyControl setKeyCode: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeyPlayKeyCode"] ]; - [playHotKeyControl setCharacter: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeyPlayCharacter"] ]; - [playHotKeyControl setModifierFlags: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeyPlayModifiers"] ]; - - [playHotKeyControl updateStringValue]; - - [spamHotKeyControl setKeyCode: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeySpamKeyCode"] ]; - [spamHotKeyControl setCharacter: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeySpamCharacter"] ]; - [spamHotKeyControl setModifierFlags: [[NSUserDefaults standardUserDefaults] integerForKey:@"hotKeySpamModifiers"] ]; - - [spamHotKeyControl updateStringValue]; + setControlText(prevHotKeyControl, @"hotKeyPreviousKeyCode", @"hotKeyPreviousModifiers"); + setControlText(nextHotKeyControl, @"hotKeyNextKeyCode", @"hotKeyNextModifiers"); + setControlText(playHotKeyControl, @"hotKeyPlayKeyCode", @"hotKeyPlayModifiers"); + setControlText(spamHotKeyControl, @"hotKeySpamKeyCode", @"hotKeySpamModifiers"); } - (NSString *)title { - return NSLocalizedStringFromTableInBundle(@"Hot Keys", nil, [NSBundle bundleForClass:[self class]], @""); + return NSLocalizedStringFromTableInBundle(@"Hot Keys", nil, [NSBundle bundleForClass:[self class]], @""); } - (NSImage *)icon { - return [[[NSImage alloc] initWithContentsOfFile:[[NSBundle bundleForClass:[self class]] pathForImageResource:@"hot_keys"]] autorelease]; -} - -/*- (void)windowDidBecomeKey:(id)notification -{ - if ([notification object] == [view window]) { - [playHotKeyControl startObserving]; - [prevHotKeyControl startObserving]; - [nextHotKeyControl startObserving]; - } -} -*/ -- (void)windowDidResignKey:(id)notification -{ - if ([notification object] == [view window]) { - [playHotKeyControl stopObserving]; - [prevHotKeyControl stopObserving]; - [nextHotKeyControl stopObserving]; - [spamHotKeyControl stopObserving]; - } -} - -- (IBAction) grabPlayHotKey:(id)sender -{ - [playHotKeyControl startObserving]; -} - -- (IBAction) grabPrevHotKey:(id)sender -{ - [prevHotKeyControl startObserving]; -} - -- (IBAction) grabNextHotKey:(id)sender -{ - [nextHotKeyControl startObserving]; -} - -- (IBAction) grabSpamHotKey:(id)sender -{ - [spamHotKeyControl startObserving]; + return [[[NSImage alloc] initWithContentsOfFile:[[NSBundle bundleForClass:[self class]] pathForImageResource:@"hot_keys"]] autorelease]; } - (IBAction) hotKeyChanged:(id)sender { - if (sender == playHotKeyControl) { - [[NSUserDefaults standardUserDefaults] setInteger:[playHotKeyControl character] forKey:@"hotKeyPlayCharacter"]; - [[NSUserDefaults standardUserDefaults] setInteger:[playHotKeyControl modifierFlags] forKey:@"hotKeyPlayModifiers"]; - [[NSUserDefaults standardUserDefaults] setInteger:[playHotKeyControl keyCode] forKey:@"hotKeyPlayKeyCode"]; - } - else if (sender == prevHotKeyControl) { - [[NSUserDefaults standardUserDefaults] setInteger:[prevHotKeyControl character] forKey:@"hotKeyPreviousCharacter"]; - [[NSUserDefaults standardUserDefaults] setInteger:[prevHotKeyControl modifierFlags] forKey:@"hotKeyPreviousModifiers"]; - [[NSUserDefaults standardUserDefaults] setInteger:[prevHotKeyControl keyCode] forKey:@"hotKeyPreviousKeyCode"]; - } - else if (sender == nextHotKeyControl) { - [[NSUserDefaults standardUserDefaults] setInteger:[nextHotKeyControl character] forKey:@"hotKeyNextCharacter"]; - [[NSUserDefaults standardUserDefaults] setInteger:[nextHotKeyControl modifierFlags] forKey:@"hotKeyNextModifiers"]; - [[NSUserDefaults standardUserDefaults] setInteger:[nextHotKeyControl keyCode] forKey:@"hotKeyNextKeyCode"]; - } - else if (sender == spamHotKeyControl) { - [[NSUserDefaults standardUserDefaults] setInteger:[spamHotKeyControl character] forKey:@"hotKeySpamCharacter"]; - [[NSUserDefaults standardUserDefaults] setInteger:[spamHotKeyControl modifierFlags] forKey:@"hotKeySpamModifiers"]; - [[NSUserDefaults standardUserDefaults] setInteger:[spamHotKeyControl keyCode] forKey:@"hotKeySpamKeyCode"]; - } - - [sender stopObserving]; + if (sender == playHotKeyControl) { + [[NSUserDefaults standardUserDefaults] setInteger:[playHotKeyControl modifierFlags] forKey:@"hotKeyPlayModifiers"]; + [[NSUserDefaults standardUserDefaults] setInteger:[playHotKeyControl keyCode] forKey:@"hotKeyPlayKeyCode"]; + } + else if (sender == prevHotKeyControl) { + [[NSUserDefaults standardUserDefaults] setInteger:[prevHotKeyControl modifierFlags] forKey:@"hotKeyPreviousModifiers"]; + [[NSUserDefaults standardUserDefaults] setInteger:[prevHotKeyControl keyCode] forKey:@"hotKeyPreviousKeyCode"]; + } + else if (sender == nextHotKeyControl) { + [[NSUserDefaults standardUserDefaults] setInteger:[nextHotKeyControl modifierFlags] forKey:@"hotKeyNextModifiers"]; + [[NSUserDefaults standardUserDefaults] setInteger:[nextHotKeyControl keyCode] forKey:@"hotKeyNextKeyCode"]; + } + else if (sender == spamHotKeyControl) { + [[NSUserDefaults standardUserDefaults] setInteger:[nextHotKeyControl modifierFlags] forKey:@"hotKeySpamModifiers"]; + [[NSUserDefaults standardUserDefaults] setInteger:[nextHotKeyControl keyCode] forKey:@"hotKeySpamKeyCode"]; + } } @end diff --git a/Preferences/General/NDHotKeyControl.h b/Preferences/General/NDHotKeyControl.h deleted file mode 100755 index e07021dcc..000000000 --- a/Preferences/General/NDHotKeyControl.h +++ /dev/null @@ -1,76 +0,0 @@ -/*! - @header NDHotKeyControl.h - @abstract Header file for a subclass of NSTextField for getting hot key combinations from the user. - @discussion The NDHotKeyControl can be used to get a NDHotKeyEvent for the last key combination pressed by the user. - - Created by Nathan Day on Wed Mar 05 2003. - Copyright (c) 2002 Nathan Day. All rights reserved. - */ - -#import - -@class NDHotKeyEvent; - -/* - @class NDHotKeyControl - @abstract Subclass of NSTextField for getting hot key combinations from the user. - @discussion The NDHotKeyControl can be used to get a NDHotKeyEvent for the last key combination pressed by the user. - */ -@interface NDHotKeyControl : NSTextField -{ -@protected - unsigned short keyCode; - unichar character; - unsigned long modifierFlags; - BOOL requiresModifierKeys; -} - -/*! - @method keyCode - @abstract Get key code. - @discussion Returns the key code for the last key combination the user pressed while the reciever was active. - @result A unsigned short containing key code. - */ -- (unsigned short)keyCode; - -/*! - @method character - @abstract Get unicode character. - @discussion Returns the unicode character for the last key combination the user pressed while the reciever was active. - @result A unichar containing character. - */ -- (unichar)character; - -/*! - @method modifierFlags - @abstract Get modifer flags. - @discussion Returns the modifer flags for the last key combination the user pressed while the reciever was active. - @result A unsigned long containing modifer flags. - */ -- (unsigned long)modifierFlags; - -/*! - @method hotKeyEvent - @abstract Get NDHotKeyEvent - @discussion Returns the NDHotKeyEvent instance for the last key combination the user pressed while the reciever was active. The NDHotKeyEvent returned will either be one that has already been created or a newly created one otherwise. - @result A NDHotKeyEvent for the hot key event. - */ -- (NDHotKeyEvent *)hotKeyEvent; - -/*! - @method setRequiresModifierKeys: - @abstract Set whether hot keys entered need modifiers keys. - @discussion This does not include function key which do not require modifier keys no matter what the value you pass for the argument flag - @param flag If NO then the reciever only accepts hot keys combination containing modifer keys. - */ -- (void)setRequiresModifierKeys:(BOOL)flag; - -/*! - @method requiresModifierKeys - @abstract Returns whether hot keys entered need modifiers keys. - @discussion This does not include key which do not require modifier keys no matter what the value is returned. - @result If NO then the reciever only accepts hot keys combination containing modifer keys. - */ -- (BOOL)requiresModifierKeys; - -@end diff --git a/Preferences/General/NDHotKeyControl.m b/Preferences/General/NDHotKeyControl.m deleted file mode 100755 index 5bdd78d76..000000000 --- a/Preferences/General/NDHotKeyControl.m +++ /dev/null @@ -1,116 +0,0 @@ -/* - * NDHotKeyControl.m - * NDHotKeyEvent - * - * Created by Nathan Day on Wed Mar 05 2003. - * Copyright (c) 2002 Nathan Day. All rights reserved. - */ - -#import "NDHotKeyControl.h" -#import "NDHotKeyEvent.h" - -/* - * class implementation NDHotKeyControl - */ -@implementation NDHotKeyControl - -/* - * -initWithFrame: - */ -- (id)initWithFrame:(NSRect)aFrame -{ - if ( self = [super initWithFrame:aFrame] ) - { - [self setEditable:NO]; - requiresModifierKeys = YES; - } - return self; -} - -/* - * -initWithCoder: - */ -- (id)initWithCoder:(NSCoder *)aCoder -{ - if ( self = [super initWithCoder:aCoder] ) - { - [self setEditable:NO]; - requiresModifierKeys = YES; - } - return self; -} - -/* - * -keyCode - */ -- (unsigned short)keyCode -{ - return keyCode; -} - -/* - * -character - */ -- (unichar)character -{ - return character; -} - -/* - * -modifierFlags - */ -- (unsigned long)modifierFlags -{ - return modifierFlags; -} - -/* - * -performKeyEquivalent: - */ -- (BOOL)performKeyEquivalent:(NSEvent*)anEvent -{ - [self keyDown:anEvent]; - return YES; -} - -/* - * -keyDown: - */ -- (void)keyDown:(NSEvent *)theEvent -{ - unsigned long theModifierFlags = [theEvent modifierFlags]; - unichar theChar = [[theEvent charactersIgnoringModifiers] characterAtIndex:0]; - theModifierFlags &= (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask|NSCommandKeyMask); - - if( (theModifierFlags != 0 || !requiresModifierKeys || theChar > 255) && theChar != 0 ) - { - keyCode = [theEvent keyCode]; - modifierFlags = theModifierFlags; - character = theChar; - - [self setStringValue:stringForKeyCodeAndModifierFlags( keyCode, character, modifierFlags )]; - [self performClick:self]; - } -} - -/* - * -hotKeyEvent - */ -- (NDHotKeyEvent *)hotKeyEvent -{ - return [NDHotKeyEvent getHotKeyForKeyCode:[self keyCode] character:[self character] modifierFlags:[self modifierFlags]]; - -} - -- (void)setRequiresModifierKeys:(BOOL)aFlag -{ - requiresModifierKeys = aFlag; -} - -- (BOOL)requiresModifierKeys -{ - return requiresModifierKeys; -} - -@end - diff --git a/Preferences/General/NDHotKeyEvent.h b/Preferences/General/NDHotKeyEvent.h deleted file mode 100755 index 1873c2b8f..000000000 --- a/Preferences/General/NDHotKeyEvent.h +++ /dev/null @@ -1,427 +0,0 @@ -/*! - @header NDHotKeyEvent.h - @abstract Header file for the class NDHotKeyEvent - @discussion

NDHotKeyEvent provides a thread safe Objective-C interface to HotKey events as well as some additional feature to key track of all the hot keys in your application.

- -

Thread Saftey

By default the class object NDHotKeyEvent is not thread safe as the underlying functions that it relies on are not thread safe and the mechanism for keeping track of all of the NDHotKeyEvent instances is not thread safe either. Thread saftey can be enable be defining the flag NDHotKeyEventThreadSafe before compiling.

-

Even with the flag NDHotKeyEventThreadSafe defined instances of NDHotKeyEvent will still not be thread safe, that is, it is safe to invoke methods of different instance with different threads as well as class methods, but it is not safe to invoke methods of the same instance with different threads.

-

The functions stringForKeyCodeAndModifierFlags and unicharForKeyCode are never thread safe.

- -

Created by Nathan Day on Wed Feb 26 2003.
- Copyright © 2002 Nathan Day. All rights reserved.

- */ - -#import -#import - -/*! - @defined NDHotKeyEventThreadSafe - @abstract A flag to enable thread safety. - @discussion By default the class object NDHotKeyEvent is not thread safe. Defining the this flag will make th class methods of NDHotKeyEvent thread safe, see introduction for more details.. - */ -enum -{ -/*! - @const NDHotKeyNoEvent - @abstract A value returned from the method -[NDHotKeyEvent currentEventType] - @discussion This value is returned if the hot key has not been pressed yet. - */ - NDHotKeyNoEvent = 0, -/*! - @const NDHotKeyPressedEvent - @abstract A value returned from the method -[NDHotKeyEvent currentEventType] - @discussion This value is returned if hot key was pressed last. - */ - NDHotKeyPressedEvent, -/*! - @const NDHotKeyReleasedEvent - @abstract A value returned from the method -[NDHotKeyEvent currentEventType] - @discussion This value is returned if hot key was released last. - */ - NDHotKeyReleasedEvent -}; - -/*! - @const NDHotKeyDefaultSignature - @abstract The default signature - @discussion This is the default signature that will be used if you start using NDHotKeyEvent without setting the signature first. - */ -extern const OSType NDHotKeyDefaultSignature; - -/*! - @class NDHotKeyEvent - @abstract Class to represent a HotKey - @discussion

This class is a wrapper for Carbon Event HotKeys and provides some feature to key track of all the hot keys in your application. It can be used to be notified of key down as well as key up evernts and when a hot key is being taken by another object (see the protocol NDHotKeyEventTragetWillChange)

- - */ -@interface NDHotKeyEvent : NSObject -{ -@private - EventHotKeyRef reference; - unsigned short keyCode; - unichar character; - unsigned int modifierFlags; - int currentEventType; - id target; - SEL selectorReleased, - selectorPressed; - struct - { - unsigned individual : 1; - unsigned collective : 1; - } isEnabled; -} - -/*! - @method install - @abstract Install the event key handler - @discussion install is called before hot keys can be used. You normally don't need to invoke this method your self but in a multithreaded you might want to invoke this method before creating any threads. install is designed to be thread safe but the effects of calling Apples InstallEventHandler() funtion from anything other than the main thread is unknown. - @result Returns true if install succeeded. - */ -+ (BOOL)install; - - /*! - @method setSignature: - @abstract Set the hot key signature for this application - @discussion This should only be called once, before trying to enable any hot keys. - @param signature The four char code signature to identify all hot keys for this application, could your applications signature. - */ -+ (void)setSignature:(OSType)signature; - -/*! - @method signature - @abstract Get the hot key signature for this application - @discussion Used to identify the hot key handler for this application. - @result The four char code signature. - */ -+ (OSType)signature; - -/*! - @method setAllEnabled: - @abstract Set enabled for all instances of NDHotKeyEvent - @discussion Used to enable or disable all hot keys. This method is not the same as sending the message setEnabled: to every single NDHotKeyEvent instance. Enabling with this method only enables the hot keys that where enable prior to using this method to disable all hot keys. - @param flag YES to enable, NO to disable. - @result Returns YES if succesful. - */ -+ (BOOL)setAllEnabled:(BOOL)flag; - -/*! - @method isEnabledKeyCode:modifierFlags: - @abstract Is hot key combination enabled. - @abstract Test to see if a key code and modifier flaf combination are enabled. - @param keyCode The key code used by the keyboard, can vary across hardware. - @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask ). - @result Returns YES if enabled. - */ -+ (BOOL)isEnabledKeyCode:(unsigned short)keyCode modifierFlags:(unsigned int)modifierFlags; - -/*! - @method getHotKeyForKeyCode:modifierFlags: - @abstract Get an NDHotKeyEvent - @discussion Gets a NDHotKeyEvent for the supplied key code and modifer flags by either finding one that has already been created or by creating a new one.. - @param keyCode The key code used by the keyboard, can vary across hardware. - @param aChar The character, used for display purposes only. - @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask ). - @result The NDHotKeyEvent obejct or nil if failure. - */ -+ (NDHotKeyEvent *)getHotKeyForKeyCode:(unsigned short)keyCode character:(unichar)aChar modifierFlags:(unsigned int)modifierFlags; -/*! - @method findHotKeyForKeyCode:modifierFlags: - @abstract Find an NDHotKeyEvent - @discussion Finds the NDHotKeyEvent for the supplied key code and modifer flags. - @param keyCode The key code used by the keyboard, can vary across hardware. - @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask ). - @result The NDHotKeyEvent obejct or nil if none found. - */ -+ (NDHotKeyEvent *)findHotKeyForKeyCode:(unsigned short)keyCode modifierFlags:(unsigned int)modifierFlags; - -/*! - @method hotKeyWithKeyCode:character:modifierFlags: - @abstract Get a NDHotKeyEvent object. - @discussion Returns a new hot key for the supplied hot key combination, if there is already a hot key for the supplied key code and modifer flags then nil is returned. - @param keyCode The key code used by the keyboard, can vary across hardware. - @param aChar The character, used for display purposes only. - @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask ). - @result An new NDHotKeyEvent or nil if failure. - */ -+ (id)hotKeyWithKeyCode:(unsigned short)keyCode character:(unichar)aChar modifierFlags:(unsigned int)modifer; - -/*! - @method hotKeyWithKeyCode:character:modifierFlags:target:selector: - @abstract Get a NDHotKeyEvent object. - @discussion Returns a new hot key for the supplied hot key combination and target object and selector, if there is already a hot key for the supplied key code and modifer flags then nil is returned. - @param keyCode The key code used by the keyboard, can vary across hardware. - @param aChar The character, used for display purposes only. - @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask ). - @param target The target of hot key event. - @param selector The selector sent when hot key is released - @result A new NDHotKeyEvent - */ -+ (id)hotKeyWithKeyCode:(unsigned short)keyCode character:(unichar)aChar modifierFlags:(unsigned int)modifer target:(id)target selector:(SEL)selector; - -/*! - @method initWithPropertyList: - @abstract creates a NDHotKeyEvent with a property list. - @discussion This can be used for archiving purposes, but it is possible that it will not work if the users keyboard is changed, ie between machines. - @param propertyList A property list object - @result A initialized NDHotKeyEvent - */ -+ (id)hotKeyWithWithPropertyList:(id)propertyList; -/*! - @method initWithKeyCode:character:modifierFlags:target:selector: - @abstract Initialize a NDHotKeyEvent object. - @discussion Initialize the reciever with the supplied hot key combination and target object and selector, if there is already a hot key for the supplied key code and modifer flags then nil is returned. - @param keyCode The key code used by the keyboard, can vary across hardware. - @param aChar The character, used for display purposes only. - @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask ). - @param target The target of hot key event. - @param selector The selector sent when hot key is released - @result A initialized NDHotKeyEvent - */ -- (id)initWithKeyCode:(unsigned short)keyCode character:(unichar)aChar modifierFlags:(unsigned int)modifer target:(id)target selector:(SEL)selector; - -/*! - @method initWithKeyCode:character:modifierFlags - @abstract Initialize a NDHotKeyEvent object. - @discussion Initialize the reciever with the supplied hot key combination, if there is already a hot key for the supplied key code and modifer flags then nil is returned. - @param keyCode The key code used by the keyboard, can vary across hardware. - @param aChar The character, used for display purposes only. - @param modifierFlags The modifer flags, ( NSCommandKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask ). - @result A initialized NDHotKeyEvent - */ -- (id)initWithKeyCode:(unsigned short)keyCode character:(unichar)aChar modifierFlags:(unsigned int)modifer; - -/*! - @method initWithPropertyList: - @abstract Initializes the reciever with a property list. - @discussion This can be used for archiving purposes, but it is possible that it will not work if the users keyboard is changed, ie between machines. The following properties are initialised -
    -
  • Key Code
  • -
  • Character
  • -
  • Modifier Flags
  • -
  • Selector Pressed
  • -
  • Selector Released
  • -
- @param propertyList A property list object - @result A initialized NDHotKeyEvent - */ -- (id)initWithPropertyList:(id)propertyList; -/*! - @method propertyList - @abstract Returns a property list for the reciever. - @discussion This can be used for archiving purposes, but it is possible that it will not work if the users keyboard is changed, ie between machines. The property list returned contains the following properties; -
    -
  • Key Code
  • -
  • Character
  • -
  • Modifier Flags
  • -
  • Selector Pressed
  • -
  • Selector Released
  • -
- @result The property list object. - */ -- (id)propertyList; - -/*! - @method initWithCoder: - @abstract Initializes a newly allocated instance from data in decoder. - @discussion Decodes the following properties of a NDHotKeyEvent; -
    -
  • Key Code
  • -
  • Character
  • -
  • Modifier Flags
  • -
  • Selector Pressed
  • -
  • Selector Released
  • -
- Will use Keyed Coding if [decoder allowsKeyedCoding] == YES. - @param decoder A subclass of NSCoder - @result A initialized NDHotKeyEvent - */ -- (id)initWithCoder:(NSCoder *)decoder; - -/*! - @method encodeWithCoder: - @abstract Encodes the receiver using encoder - @discussion Encodes the following properties of a NDHotKeyEvent; -
    -
  • Key Code
  • -
  • Character
  • -
  • Modifier Flags
  • -
  • Selector Pressed
  • -
  • Selector Released
  • -
- Will use Keyed Coding if [encoder allowsKeyedCoding] == YES. - @param encoder A subclass of NSCoder. - */ -- (void)encodeWithCoder:(NSCoder *)encoder; - -/*! - @method setEnabled: - @abstract Set the hot key enabled or disable. - @discussion setEnabled: registers or unregisters the recievers hot key combination. - @param flag YES to enable, NO to disable. - @result Returns YES if successful - */ -- (BOOL)setEnabled:(BOOL)flag; - -/*! - @method isEnabled - @abstract Find out if a hot key is enabled. - @discussion Returns YES if the hot key is registered. - @result YES if enabled. - */ -- (BOOL)isEnabled; - -/*! - @method target - @abstract Get the hot key event target. - @discussion Returns the object that is sent the key pressed and key released hot key events, see the methods -selector, -selectorReleased and selectorPressed. - @result The target object. - */ -- (id)target; - -/*! - @method selector - @abstract The selector for a key released event. - @discussion This is the selector sent when the hot key combination for the reciever is released. This is the same selector has returned from the method [NDHotKeyEvent selectorReleased] - @result The method selector. - */ -- (SEL)selector; - -/*! - @method selectorReleased - @abstract The selector for a key released event. - @discussion This is the selector sent when the hot key combination for the reciever is released. This is the same selector has returned from the method [NDHotKeyEvent selector] - @result The method selector. - */ -- (SEL)selectorReleased; - -/*! - @method selectorPressed - @abstract The selector for a key pressed event. - @discussion This is the selector sent when the hot key combination for the reciever is pressed. - @result The method selector. - */ -- (SEL)selectorPressed; - -/*! - @method currentEventType - @abstract Get the current hot key event type. - @discussion This value returns what event last occured. Can be used in your target when it is sent a event message to find out what event occured, possible values are -
- - - - - -
ValueDescription
NDHotKeyNoEventThe hot key has not been pressed yet.
NDHotKeyPressedEventThe hot key was pressed last.
NDHotKeyReleasedEventThe hot key was released last.
-
- @result The last event type. - */ -- (int)currentEventType; - -/*! - @method setTarget:selector: - @abstract Set the hot key target. - @discussion Set the target object and selector to be sent when the hot key is released. - @param target The traget object. - @param selector The selector. - @result returns YES if successful. - */ -- (BOOL)setTarget:(id)target selector:(SEL)selector; - -/*! - @method setTarget:selectorReleased:selectorPressed: - @abstract Set the hot key target. - @discussion Set the target object and selector to be sent when the hot key is pressed and wehn it is released. - @param target The traget object. - @param selectorReleased The key released selector. - @param selectorPressed The key pressed selector. - @result returns YES if successful. - */ -- (BOOL)setTarget:(id)target selectorReleased:(SEL)selectorReleased selectorPressed:(SEL)selectorPressed; - -/*! - @method performHotKeyReleased - @abstract Invoke the target with the release selector. - @discussion Use to send the selector for a release event, though this method can be called by you. - */ -- (void)performHotKeyReleased; - -/*! - @method performHotKeyPressed - @abstract Invoke the target with the press selector. - @discussion Use to send the selector for a presse event, though this method can be called by you. - */ -- (void)performHotKeyPressed; - -/*! - @method keyCode - @abstract Get the hot key key code. - @discussion The key code for the hot key, this is hardware specific. - @result The key code. - */ -- (unsigned short)keyCode; - -/*! - @method character - @abstract Get the hot key character. - @discussion This is the character for the key code, without modifier keys. The character is for display purposes only and dose not determine the key code. - @result A uni code character. - */ -- (unichar)character; - -/*! - @method modifierFlags - @abstract Get the hot key modifer key flags. - @discussion The modifierFlags can be a bitwise and combination of NSControlKeyMask, NSAlternateKeyMask, NSShiftKeyMask, and NSCommandKeyMask. - @result The modifer key flags. - */ -- (unsigned int)modifierFlags; - -/*! - @method stringValue - @abstract Get a string got the hot keys. - @discussion This is a string that can be used for display purposes. - @result A NSString - */ -- (NSString *)stringValue; - -@end - -/*! - @protocol NSObject(NDHotKeyEventTragetWillChange) - @abstract Informal protocol used to inform a NDHotKeyEvent target of events. - @discussion The informal protocol NDHotKeyEventTragetWillChange defines a method used to notify a NDHotKeyEvent target that the target will change. - */ -@interface NSObject (NDHotKeyEventTragetWillChange) - -/*! - @method targetWillChangeToObject:forHotKeyEvent: - @abstract Message sent to a target object to inform it that the target is going to change. - @discussion This method can be used to notify the receiver that it will no longer be the target for a NDHotKeyEvent or used to prevent the target from changing by returning NO - @param target The new target for the NDHotKeyEvent - @param hotKeyEvent The NDHotKeyEvent for which the target is changing. - @result Return NO to prevent the target from changing, otherwise return YES. - */ -- (BOOL)targetWillChangeToObject:(id)target forHotKeyEvent:(NDHotKeyEvent *)hotKeyEvent; - -@end - -/*! - @function stringForKeyCodeAndModifierFlags - @abstract Get a string for hot key parameters. - @discussion Returns a string representation of the passed in hot key values. - @param keyCode A key code. - @param aChar A character representation of the key code. - @param modifierFlags modifer flags, comman, option, shift and control. - @result A NSString representing the hot key combination. - */ -NSString * stringForKeyCodeAndModifierFlags( unsigned short keyCode, unichar aChar, unsigned int modifierFlags ); -/*! - @function unicharForKeyCode - @abstract Get a unicode charater for the key combination. - @discussion The uncode chararter for the key combination. - @param keyCode The key code used by the keyboard, can vary across hardware. - @result A unichar - */ -unichar unicharForKeyCode( unsigned short keyCode ); diff --git a/Preferences/General/NDHotKeyEvent.m b/Preferences/General/NDHotKeyEvent.m deleted file mode 100755 index 8805df1ea..000000000 --- a/Preferences/General/NDHotKeyEvent.m +++ /dev/null @@ -1,1155 +0,0 @@ -/* - * NDHotKeyEvent.m - * NDHotKeyEvent - * - * Created by Nathan Day on Wed Feb 26 2003. - * Copyright (c) 2002 Nathan Day. All rights reserved. - */ - -#import "NDHotKeyEvent.h" - -#import - -#import "Logging.h" - -@interface NDHotKeyEvent (Private) -+ (NSMapTable *)allHotKeyEvents; -- (BOOL)addHotKey; -- (void)removeHotKey; -- (BOOL)setCollectiveEnabled:(BOOL)aFlag; -- (BOOL)collectiveEnable; -@end - -static NSString * kArchivingKeyCodeKey = @"KeyCodeKey", - * kArchivingCharacterKey = @"CharacterKey", - * kArchivingModifierFlagsKey = @"ModifierFlagsKey", - * kArchivingSelectorReleasedCodeKey = @"SelectorReleasedCodeKey", - * kArchivingSelectorPressedCodeKey = @"SelectorPressedCodeKey"; -const OSType NDHotKeyDefaultSignature = 'NDHK'; - -static OSStatus switchHotKey( NDHotKeyEvent * self, BOOL aFlag ); - -unichar unicodeForFunctionKey( UInt32 aKeyCode ); - -/* - * class implementation NDHotKeyEvent - */ -@implementation NDHotKeyEvent - -#ifdef NDHotKeyEventThreadSafe - static NSLock * hotKeysLock = NULL; - #warning Thread saftey has been enabled for NDHotKeyEvent class methods - #define NDHotKeyEventLock [hotKeysLock lock] - #define NDHotKeyEventUnlock [hotKeysLock unlock] -#else - #warning The NDHotKeyEvent class methods are NOT thread safe - #define NDHotKeyEventLock // lock - #define NDHotKeyEventUnlock // unlock -#endif - -static NSMapTable * allHotKeyEvents = NULL; -static BOOL isInstalled = NO; -static OSType signature = 0; - -unsigned int cocoaModifierFlagsToCarbonModifierFlags( unsigned int aModifierFlags ); - -pascal OSErr eventHandlerCallback( EventHandlerCallRef anInHandlerCallRef, EventRef anInEvent, void * self ); - -NSUInteger hashValueHashFunction( NSMapTable * aTable, const void * aHotKeyEntry ); -BOOL isEqualHashFunction( NSMapTable * aTable, const void * aFirstHotKeyEvent, const void * aSecondHotKeyEvent ); -NSString * describeHashFunction( NSMapTable * aTable, const void * aHotKeyEvent ); - -NSUInteger hashKeyHashFunction( NSMapTable * aTable, const void * aNumber ); -BOOL isEqualKeyHashFunction( NSMapTable * aTable, const void * aFirstNumber, const void * aSecondNumber ); -void hashKeyRetainFunction( NSMapTable * aTable, const void * aNumber ); -void hashKeyReleaseFunction( NSMapTable * aTable, void * aNumber ); - -struct HotKeyMappingEntry -{ - unsigned short keyCode; - unsigned int modifierFlags; - NDHotKeyEvent * hotKeyEvent; -}; - -/* - * +install - */ -+ (BOOL)install -{ - if( isInstalled == NO ) - { - NSMapTable * theHotKeyEvents = [self allHotKeyEvents]; - EventTypeSpec theTypeSpec[] = - { - { kEventClassKeyboard, kEventHotKeyPressed }, - { kEventClassKeyboard, kEventHotKeyReleased } - }; - - NDHotKeyEventLock; - if( theHotKeyEvents != nil && isInstalled == NO ) - { - if( InstallEventHandler( GetEventDispatcherTarget(), NewEventHandlerUPP((EventHandlerProcPtr)eventHandlerCallback), 2, theTypeSpec, theHotKeyEvents, nil ) == noErr ) - { - isInstalled = YES; - } - else - { - DLog(@"Could not install Event handler"); - } - } - NDHotKeyEventUnlock; - } - - return isInstalled; -} - -#ifdef NDHotKeyEventThreadSafe -/* - * +initialize: - */ -+ (void)initialize -{ - while( hotKeysLock == nil ) - { - NSLock * theInstance = [[NSLock alloc] init]; - - if( !CompareAndSwap( nil, (unsigned long int)theInstance, (unsigned long int*)&hotKeysLock) ) - [theInstance release]; // did not use instance - } -} -#endif - -/* - * +setSignature: - */ -+ (void)setSignature:(OSType)aSignature -{ - NSAssert( signature == 0 || aSignature == signature, @"The signature used by NDHotKeyEvent can only be set once safely" ); - signature = aSignature; -} - -/* - * +signature - */ -+ (OSType)signature -{ - signature = signature ? signature : NDHotKeyDefaultSignature; - return signature; -} - -/* - * +setAllEnabled: - */ -+ (BOOL)setAllEnabled:(BOOL)aFlag -{ - BOOL theAllSucceeded = YES; - NSMapTable * theMapTable = [NDHotKeyEvent allHotKeyEvents]; - - /* - * need to install before to make sure the method 'setCollectiveEnabled:' - * doesn't try install since install tries to aquire the lock 'hotKeysLock' - */ - if( theMapTable && [NDHotKeyEvent install] ) - { - NSMapEnumerator theEnumerator; - NSUInteger theKey; - struct HotKeyMappingEntry * theHotKeyMapEntry; - NDHotKeyEventLock; - theEnumerator = NSEnumerateMapTable(theMapTable); - - while ( NSNextMapEnumeratorPair(&theEnumerator, (void**)&theKey, (void**)&theHotKeyMapEntry) ) - { - if( ![theHotKeyMapEntry->hotKeyEvent setCollectiveEnabled:aFlag] ) - theAllSucceeded = NO; - } - NDHotKeyEventUnlock; - } - - return theAllSucceeded; -} - -/* - * +isEnabledKeyCode:modifierFlags: - */ -+ (BOOL)isEnabledKeyCode:(unsigned short)aKeyCode modifierFlags:(unsigned int)aModifierFlags -{ - return [[self findHotKeyForKeyCode:aKeyCode modifierFlags:aModifierFlags] isEnabled]; -} - -/* - * +getHotKeyForKeyCode:character:modifierFlags: - */ -+ (NDHotKeyEvent *)getHotKeyForKeyCode:(unsigned short)aKeyCode character:(unichar)aChar modifierFlags:(unsigned int)aModifierFlags -{ - NDHotKeyEvent * theHotKey = nil; - - theHotKey = [self findHotKeyForKeyCode:aKeyCode modifierFlags:aModifierFlags]; - return theHotKey ? theHotKey : [self hotKeyWithKeyCode:aKeyCode character:aChar modifierFlags:aModifierFlags]; -} - -/* - * +findHotKeyForKeyCode:modifierFlags: - */ -+ (NDHotKeyEvent *)findHotKeyForKeyCode:(unsigned short)aKeyCode modifierFlags:(unsigned int)aModifierFlags -{ - struct HotKeyMappingEntry * theFoundEntry = NULL; - NSMapTable * theMapTable = [NDHotKeyEvent allHotKeyEvents]; - - if( theMapTable ) - { - NDHotKeyEventLock; - theFoundEntry = (struct HotKeyMappingEntry *) NSMapGet( theMapTable, (void*)(NSUInteger)(aKeyCode ^ aModifierFlags) ); - if( theFoundEntry != NULL ) - [[theFoundEntry->hotKeyEvent retain] autorelease]; - NDHotKeyEventUnlock; - } - - return (theFoundEntry) ? theFoundEntry->hotKeyEvent : nil; -} - -/* - * +hotKeyWithKeyCode:character:modifierFlags: - */ -+ (id)hotKeyWithKeyCode:(unsigned short)aKeyCode character:(unichar)aChar modifierFlags:(unsigned int)aModifierFlags -{ - return [self hotKeyWithKeyCode:aKeyCode character:aChar modifierFlags:aModifierFlags target:nil selector:NULL]; -} - -/* - * +hotKeyWithKeyCode:character:modifierFlags:target:selector: - */ -+ (id)hotKeyWithKeyCode:(unsigned short)aKeyCode character:(unichar)aChar modifierFlags:(unsigned int)aModifierFlags target:(id)aTarget selector:(SEL)aSelector -{ - return [[[self alloc] initWithKeyCode:aKeyCode character:aChar modifierFlags:aModifierFlags target:aTarget selector:aSelector] autorelease]; -} - -+ (id)hotKeyWithWithPropertyList:(id)aPropertyList -{ - return [[[self alloc] initWithPropertyList:aPropertyList] autorelease]; -} - -+ (NSString *)description -{ - NSMapTable * theMapTable = [NDHotKeyEvent allHotKeyEvents]; - NSString * theDescription = nil; - if( theMapTable ) - { - NDHotKeyEventLock; - theDescription = @""; - NDHotKeyEventUnlock; - } - return theDescription; -} - -/* - * -init - */ -- (id)init -{ - [self release]; - NSAssert( NO, @"You can not initialize a Hot Key with the init method" ); - return nil; -} - -/* - * -initWithKeyCode:character:modifierFlags: - */ -- (id)initWithKeyCode:(unsigned short)aKeyCode character:(unichar)aChar modifierFlags:(unsigned int)aModifierFlags -{ - return [self initWithKeyCode:aKeyCode character:aChar modifierFlags:aModifierFlags target:nil selector:NULL]; -} - -/* - * -initWithKeyCode:character:modifierFlags:target:selector: - */ -- (id)initWithKeyCode:(unsigned short)aKeyCode character:(unichar)aChar modifierFlags:(unsigned int)aModifierFlags target:(id)aTarget selector:(SEL)aSelector -{ - if( (self = [super init]) != nil ) - { - keyCode = aKeyCode; - character = aChar; - modifierFlags = aModifierFlags; - target = aTarget; - selectorReleased = aSelector; - currentEventType = NDHotKeyNoEvent; - isEnabled.collective = YES; - - if( ![self addHotKey] ) - { - [self release]; - self = nil; - } - } - else - { - [self release]; - self = nil; - } - - return self; -} - -- (id)initWithCoder:(NSCoder *)aDecoder -{ - if( (self = [super init]) != nil) - { - if( [aDecoder allowsKeyedCoding] ) - { - keyCode = [[aDecoder decodeObjectForKey:kArchivingKeyCodeKey] unsignedShortValue]; - character = [[aDecoder decodeObjectForKey:kArchivingCharacterKey] unsignedShortValue]; - modifierFlags = [[aDecoder decodeObjectForKey:kArchivingModifierFlagsKey] unsignedIntValue]; - - selectorReleased = NSSelectorFromString( [aDecoder decodeObjectForKey:kArchivingSelectorReleasedCodeKey] ); - selectorPressed = NSSelectorFromString( [aDecoder decodeObjectForKey:kArchivingSelectorPressedCodeKey] ); - } - else - { - [aDecoder decodeValueOfObjCType:@encode(unsigned short) at:&keyCode]; - [aDecoder decodeValueOfObjCType:@encode(unichar) at:&character]; - [aDecoder decodeValueOfObjCType:@encode(unsigned int) at:&modifierFlags]; - - selectorReleased = NSSelectorFromString( [aDecoder decodeObject] ); - selectorPressed = NSSelectorFromString( [aDecoder decodeObject] ); - } - - if( ![self addHotKey] ) - { - [self release]; - self = nil; - } - } - - return self; -} - -- (void)encodeWithCoder:(NSCoder *)anEncoder -{ - if( [anEncoder allowsKeyedCoding] ) - { - [anEncoder encodeObject:[NSNumber numberWithUnsignedShort:keyCode] forKey:kArchivingKeyCodeKey]; - [anEncoder encodeObject:[NSNumber numberWithUnsignedShort:character] forKey:kArchivingCharacterKey]; - [anEncoder encodeObject:[NSNumber numberWithUnsignedInt:modifierFlags] forKey:kArchivingModifierFlagsKey]; - - [anEncoder encodeObject:NSStringFromSelector( selectorReleased ) forKey:kArchivingSelectorReleasedCodeKey]; - [anEncoder encodeObject:NSStringFromSelector( selectorPressed ) forKey:kArchivingSelectorPressedCodeKey]; - } - else - { - [anEncoder encodeValueOfObjCType:@encode(unsigned short) at:&keyCode]; - [anEncoder encodeValueOfObjCType:@encode(unichar) at:&character]; - [anEncoder encodeValueOfObjCType:@encode(unsigned int) at:&modifierFlags]; - - [anEncoder encodeObject:NSStringFromSelector( selectorReleased )]; - [anEncoder encodeObject:NSStringFromSelector( selectorPressed )]; - } -} - -- (id)initWithPropertyList:(id)aPropertyList -{ - if( aPropertyList ) - { - NSString * theCharacter; - NSNumber * theKeyCode, - * theModiferFlag; - SEL theKeyPressedSelector, - theKeyReleasedSelector; - - theKeyCode = [aPropertyList objectForKey:kArchivingKeyCodeKey]; - theCharacter = [aPropertyList objectForKey:kArchivingCharacterKey]; - theModiferFlag = [aPropertyList objectForKey:kArchivingModifierFlagsKey]; - theKeyPressedSelector = NSSelectorFromString([aPropertyList objectForKey:kArchivingSelectorPressedCodeKey]); - theKeyReleasedSelector = NSSelectorFromString([aPropertyList objectForKey:kArchivingSelectorReleasedCodeKey]); - - self = [self initWithKeyCode:[theKeyCode unsignedShortValue] character:[theCharacter characterAtIndex:0] modifierFlags:[theModiferFlag unsignedIntValue]]; - } - else - { - [self release]; - self = nil; - } - - return self; -} - -- (id)propertyList -{ - return [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithUnsignedShort:[self keyCode]], kArchivingKeyCodeKey, - [NSString stringWithCharacters:&character length:1] , kArchivingCharacterKey, - [NSNumber numberWithUnsignedInt:[self modifierFlags]], kArchivingModifierFlagsKey, - NSStringFromSelector( selectorPressed ), kArchivingSelectorPressedCodeKey, - NSStringFromSelector( selectorReleased ), kArchivingSelectorReleasedCodeKey, - nil]; -} - -/* - * -release - */ -- (oneway void)release -{ - /* - * We need to remove the hot key from the hash table before it's retain count reaches zero - */ - if( [self retainCount] == 1 ) - { - NSMapTable * theMapTable = [NDHotKeyEvent allHotKeyEvents]; - if( theMapTable ) - { - NDHotKeyEventLock; - switchHotKey( self, NO ); - if( [self retainCount] == 1 ) // check again because it might have changed - { - [theMapTable removeObjectForKey:[NSNumber numberWithInteger:[self hash]]]; - } - NDHotKeyEventUnlock; - } - } -// else - [super release]; -} - -- (void)dealloc -{ - if( UnregisterEventHotKey( reference ) != noErr ) // in lock from release - DLog( @"Failed to unregister hot key %@", self ); - [super dealloc]; -} - -/* - * -setEnabled: - */ -- (BOOL)setEnabled:(BOOL)aFlag -{ - BOOL theResult = YES; - - if( [NDHotKeyEvent install] ) - { - /* - * if individual and collective YES then currently ON, otherwise currently off - */ - NDHotKeyEventLock; - if( aFlag == YES && isEnabled.collective == YES && isEnabled.individual == NO ) - { - theResult = (switchHotKey( self, YES ) == noErr); - } - else if( aFlag == NO && isEnabled.collective == YES && isEnabled.individual == YES ) - { - theResult = (switchHotKey( self, NO ) == noErr); - } - NDHotKeyEventUnlock; - - if( theResult ) - isEnabled.individual = aFlag; - else - DLog(@"%s failed ", aFlag ? "enable" : "disable" ); - } - else - theResult = NO; - - return theResult; -} - -/* - * -isEnabled - */ -- (BOOL)isEnabled -{ - return isEnabled.individual && isEnabled.collective; -} - -/* - * -target - */ -- (id)target -{ - return target; -} - -/* -* -selector -*/ -- (SEL)selector -{ - return selectorReleased; -} - -/* - * -selectorReleased - */ -- (SEL)selectorReleased -{ - return selectorReleased; -} - -/* -* -selectorPressed -*/ -- (SEL)selectorPressed -{ - return selectorPressed; -} - -/* - * -currentEventType - * (NDHotKeyNoEvent | NDHotKeyPressedEvent | NDHotKeyReleasedEvent) - */ -- (int)currentEventType -{ - return currentEventType; -} - -/* - * -setTarget:selector: - */ -- (BOOL)setTarget:(id)aTarget selector:(SEL)aSelector -{ - return [self setTarget:aTarget selectorReleased:aSelector selectorPressed:(SEL)0]; -} - -/* - * -setTarget:selectorReleased:selectorPressed: - */ -- (BOOL)setTarget:(id)aTarget selectorReleased:(SEL)aSelectorReleased selectorPressed:(SEL)aSelectorPressed -{ - [self setEnabled:NO]; - if( target && target != aTarget ) - { - [self setEnabled:NO]; - if( ![target respondsToSelector:@selector(targetWillChangeToObject:forHotKeyEvent:)] || [target targetWillChangeToObject:aTarget forHotKeyEvent:self] ) - { - target = aTarget; - selectorReleased = aSelectorReleased; - selectorPressed = aSelectorPressed; - } - } - else - { - target = aTarget; - selectorReleased = aSelectorReleased; - selectorPressed = aSelectorPressed; - } - - return target == aTarget; // was change succesful -} - -/* - * -performHotKeyReleased - */ -- (void)performHotKeyReleased -{ - NSAssert( target, @"NDHotKeyEvent tried to perfrom release with no target" ); - - if( selectorReleased && [target respondsToSelector:selectorReleased]) - { - currentEventType = NDHotKeyReleasedEvent; - [target performSelector:selectorReleased withObject:self]; - currentEventType = NDHotKeyNoEvent; - } -} - -/* - * -performHotKeyPressed - */ -- (void)performHotKeyPressed -{ - NSAssert( target, @"NDHotKeyEvent tried to perfrom press with no target" ); - - if( selectorPressed && [target respondsToSelector:selectorPressed]) - { - currentEventType = NDHotKeyPressedEvent; - [target performSelector:selectorPressed withObject:self]; - currentEventType = NDHotKeyNoEvent; - } -} - -/* - * -keyCode - */ -- (unsigned short)keyCode -{ - return keyCode; -} - -/* - * -character - */ -- (unichar)character -{ - return character; -} - -/* - * -modifierFlags - */ -- (unsigned int)modifierFlags -{ - return modifierFlags; -} - -/* - * -stringValue - */ -- (NSString *)stringValue -{ - NSString * theStringValue = nil; - NDHotKeyEventLock; - theStringValue = stringForKeyCodeAndModifierFlags( [self keyCode], [self character], [self modifierFlags] ); - NDHotKeyEventUnlock; - - return theStringValue; -} - - -/* - * -isEqual: - */ -- (BOOL)isEqual:(id)anObject -{ - return [super isEqual:anObject] || ([anObject isKindOfClass:[self class]] == YES && [self keyCode] == [(NDHotKeyEvent*)anObject keyCode] && [self modifierFlags] == [(NDHotKeyEvent*)anObject modifierFlags]); -} - -/* - * -hash - */ -- (NSUInteger)hash -{ - return (unsigned int)keyCode ^ modifierFlags; // xor -} - -/* - * -description - */ -- (NSString *)description -{ - return [NSString stringWithFormat:@"{\n\tKey Combination: %@,\n\tEnabled: %s\n\tKey Press Selector: %@\n\tKey Release Selector: %@\n}\n", [self stringValue], - [self isEnabled] ? "yes" : "no", - NSStringFromSelector([self selectorPressed]), - NSStringFromSelector([self selectorReleased])]; -} - -/* - * cocoaModifierFlagsToCarbonModifierFlags() - */ -unsigned int cocoaModifierFlagsToCarbonModifierFlags( unsigned int aModifierFlags ) -{ - unsigned int theCarbonModifierFlags = 0; - - if(aModifierFlags & NSShiftKeyMask) - theCarbonModifierFlags |= shiftKey; - - if(aModifierFlags & NSControlKeyMask) - theCarbonModifierFlags |= controlKey; - - if(aModifierFlags & NSAlternateKeyMask) - theCarbonModifierFlags |= optionKey; - - if(aModifierFlags & NSCommandKeyMask) - theCarbonModifierFlags |= cmdKey; - - return theCarbonModifierFlags; -} - -/* - * eventHandlerCallback() - */ -pascal OSErr eventHandlerCallback( EventHandlerCallRef anInHandlerCallRef, EventRef anInEvent, void * anInUserData ) -{ - NSMapTable * allHotKeyEvents = (NSMapTable *)anInUserData; - EventHotKeyID theHotKeyID; - OSStatus theError; - - NSCAssert( GetEventClass( anInEvent ) == kEventClassKeyboard, @"Got event that is not a hot key event" ); - - theError = GetEventParameter( anInEvent, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(EventHotKeyID), NULL, &theHotKeyID ); - - if( theError == noErr ) - { - struct HotKeyMappingEntry * theHotKeyMappingEntry; - NDHotKeyEvent * theHotKeyEvent; - UInt32 theEventKind; - - NSCAssert( [NDHotKeyEvent signature] == theHotKeyID.signature, @"Got hot key event with wrong signature" ); - - theHotKeyMappingEntry = (struct HotKeyMappingEntry *) NSMapGet(allHotKeyEvents, (void *)(NSUInteger)theHotKeyID.id); - - if ( theHotKeyMappingEntry ) { - theHotKeyEvent = theHotKeyMappingEntry->hotKeyEvent; - theEventKind = GetEventKind( anInEvent ); - if( kEventHotKeyPressed == theEventKind ) - { - [theHotKeyEvent performHotKeyPressed]; - } - else if( kEventHotKeyReleased == theEventKind ) - { - [theHotKeyEvent performHotKeyReleased]; - } - } - } - - return theError; -} - -/* - * hashValueHashFunction() - */ -NSUInteger hashValueHashFunction( NSMapTable * aTable, const void * aHotKeyEntry ) -{ - struct HotKeyMappingEntry * theHotKeyEntry; - unsigned int theKeyCode, - theModifiers; - - theHotKeyEntry = (struct HotKeyMappingEntry*)aHotKeyEntry; - theKeyCode = (unsigned int)theHotKeyEntry->keyCode; - theModifiers = (unsigned int)theHotKeyEntry->modifierFlags; - return theKeyCode ^ theModifiers; // xor -} - -/* - * isEqualHashFunction() - */ -BOOL isEqualHashFunction( NSMapTable * aTable, const void * aFirstHotKeyEntry, const void * aSecondHotKeyEntry ) -{ - struct HotKeyMappingEntry * theFirst, - * theSecond; - - theFirst = (struct HotKeyMappingEntry*)aFirstHotKeyEntry; - theSecond = (struct HotKeyMappingEntry*)aSecondHotKeyEntry; - return theFirst->keyCode == theSecond->keyCode && theFirst->modifierFlags == theSecond->modifierFlags; -} - -/* - * describeHashFunction() - */ -NSString * describeHashFunction( NSMapTable * aTable, const void * aHotKeyEntry ) -{ - NDHotKeyEvent * theHotKey; - - theHotKey = ((struct HotKeyMappingEntry*)aHotKeyEntry)->hotKeyEvent; - return [theHotKey description]; -} - -NSUInteger hashKeyHashFunction( NSMapTable * aTable, const void * aNumber ) -{ - NSNumber * theNumber = (NSNumber *) aNumber; - return [theNumber integerValue]; -} - -BOOL isEqualKeyHashFunction( NSMapTable * aTable, const void * aFirstNumber, const void * aSecondNumber ) -{ - NSNumber * theFirstNumber = (NSNumber *) aFirstNumber; - NSNumber * theSecondNumber = (NSNumber *) aSecondNumber; - return [theFirstNumber isEqual:theSecondNumber]; -} - -void hashKeyRetainFunction( NSMapTable * aTable, const void * aNumber ) -{ - const NSNumber * theNumber = (const NSNumber *) aNumber; - [theNumber retain]; -} - -void hashKeyReleaseFunction( NSMapTable * aTable, void * aNumber ) -{ - NSNumber * theNumber = (NSNumber *) aNumber; - [theNumber release]; -} - -@end - -@implementation NDHotKeyEvent (Private) - -/* - * +allHotKeyEvents - */ -+ (NSMapTable *)allHotKeyEvents -{ - if( allHotKeyEvents == NULL ) - { - NDHotKeyEventLock; - if( allHotKeyEvents == NULL ) - allHotKeyEvents = NSCreateMapTable(NSIntegerMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 0); - NDHotKeyEventUnlock; - } - - return allHotKeyEvents; -} - -/* - * -addHotKey - */ -- (BOOL)addHotKey -{ - NSMapTable * theMapTable = [NDHotKeyEvent allHotKeyEvents]; - if( theMapTable ) - { - struct HotKeyMappingEntry * theEntry; - - theEntry = (struct HotKeyMappingEntry *)malloc(sizeof(struct HotKeyMappingEntry)); - - theEntry->keyCode = [self keyCode]; - theEntry->modifierFlags = [self modifierFlags]; - theEntry->hotKeyEvent = self; - - NDHotKeyEventLock; - NSMapInsert(theMapTable, (void*)[self hash], theEntry); - NDHotKeyEventUnlock; - } - - return YES; -} - -/* - * -removeHotKey - */ -- (void)removeHotKey -{ - [self setEnabled:NO]; - - NSMapTable * theMapTable = [NDHotKeyEvent allHotKeyEvents]; - if( theMapTable ) - { - NDHotKeyEventLock; - free(NSMapGet(theMapTable, (void *)[self hash])); - NSMapRemove(theMapTable, (void*)[self hash]); - NDHotKeyEventUnlock; - } -} - -/* - * setCollectiveEnabled: - */ -- (BOOL)setCollectiveEnabled:(BOOL)aFlag -{ - BOOL theResult = YES; - - if( [NDHotKeyEvent install] ) - { - /* - * if individual and collective YES then currently ON, otherwise currently off - */ - NDHotKeyEventLock; - if( aFlag == YES && isEnabled.collective == NO && isEnabled.individual == YES ) - { - theResult = (switchHotKey( self, YES ) == noErr); - } - else if( aFlag == NO && isEnabled.collective == YES && isEnabled.individual == YES ) - { - theResult = (switchHotKey( self, NO ) == noErr); - } - NDHotKeyEventUnlock; - - if( theResult ) - isEnabled.collective = aFlag; - else - DLog(@"%s failed", aFlag ? "enable" : "disable" ); - } - else - theResult = NO; - - return theResult; -} - -/* - * collectiveEnable() - */ -- (BOOL)collectiveEnable -{ - return isEnabled.collective; -} - -/* - * switchHotKey() - */ -static OSStatus switchHotKey( NDHotKeyEvent * self, BOOL aFlag ) -{ - OSStatus theError; - if( aFlag ) - { - struct HotKeyMappingEntry theDummyEntry; - - theDummyEntry.keyCode = [self keyCode]; - theDummyEntry.modifierFlags = [self modifierFlags]; - theDummyEntry.hotKeyEvent = nil; - - EventHotKeyID theHotKeyID; - - theHotKeyID.signature = [NDHotKeyEvent signature]; - theHotKeyID.id = hashValueHashFunction( nil, (const void *)&theDummyEntry ); - - NSCAssert( theHotKeyID.signature, @"HotKeyEvent signature has not been set yet" ); - NSCParameterAssert(sizeof(unsigned long) >= sizeof(id) ); - - theError = RegisterEventHotKey( self->keyCode, cocoaModifierFlagsToCarbonModifierFlags(self->modifierFlags), theHotKeyID, GetEventDispatcherTarget(), 0, &self->reference ); - } - else - { - theError = UnregisterEventHotKey( self->reference ); - } - - return theError; -} - -@end - - -/* - * stringForKeyCodeAndModifierFlags() - */ -NSString * stringForKeyCodeAndModifierFlags( unsigned short aKeyCode, unichar aChar, unsigned int aModifierFlags ) -{ - NSString * stringForCharacter( const unsigned short aKeyCode, unichar aCharacter ); - NSString * stringForModifiers( unsigned int aModifierFlags ); - - return [stringForModifiers(aModifierFlags) stringByAppendingString:stringForCharacter( aKeyCode, aChar )]; -} - -/* - * unicharForKeyCode() - */ -unichar unicharForKeyCode( unsigned short aKeyCode ) -{ - UInt32 theChar = kNullCharCode; - - TISInputSourceRef theCurrentKeyBoardLayout = TISCopyCurrentKeyboardLayoutInputSource(); - UCKeyboardLayout *uchr = (UCKeyboardLayout *) TISGetInputSourceProperty(theCurrentKeyBoardLayout, kTISPropertyUnicodeKeyLayoutData); - if ( uchr != nil ) - { - UInt32 deadKeyState = 0; - UInt32 flags = 0; - UniCharCount maxStringLength = 255; - UniCharCount actualStringLength = 0; - UniChar unicodeString[maxStringLength]; - - UCKeyTranslate(uchr, aKeyCode, kUCKeyActionDown, flags, LMGetKbdType(), 1, &deadKeyState, maxStringLength, &actualStringLength, unicodeString); - - if ( actualStringLength == 1 ) - theChar = unicodeString[ 0 ]; - - switch( theChar ) - { - case kHomeCharCode: theChar = NSHomeFunctionKey; break; -// case kEnterCharCode: theChar = ; break; - case kEndCharCode: theChar = NSEndFunctionKey; break; - case kHelpCharCode: theChar = NSHelpFunctionKey; break; -// case kBellCharCode: theChar = ; break; -// case kBackspaceCharCode: theChar = ; break; -// case kTabCharCode: theChar = ; break; -// case kLineFeedCharCode: theChar = ; break; - case kPageUpCharCode: theChar = NSPageUpFunctionKey; break; - case kPageDownCharCode: theChar = NSPageDownFunctionKey; break; -// case kReturnCharCode: theChar = ; break; - case kFunctionKeyCharCode: theChar = unicodeForFunctionKey( aKeyCode ); break; -// case kCommandCharCode: theChar = ; break; -// case kCheckCharCode: theChar = ; break; -// case kDiamondCharCode : theChar = ; break; -// case kAppleLogoCharCode: theChar = ; break; -// case kEscapeCharCode: theChar = ; break; - case kClearCharCode: - theChar = (aKeyCode==0x47) ? NSInsertFunctionKey : theChar; - break; - case kLeftArrowCharCode: theChar = NSLeftArrowFunctionKey; break; - case kRightArrowCharCode: theChar = NSRightArrowFunctionKey; break; - case kUpArrowCharCode: theChar = NSUpArrowFunctionKey; break; - case kDownArrowCharCode: theChar = NSDownArrowFunctionKey; break; -// case kSpaceCharCode: theChar = ; break; - case kDeleteCharCode: theChar = NSDeleteCharFunctionKey; break; -// case kBulletCharCode: theChar = ; break; -// case kNonBreakingSpaceCharCode: theChar = ; break; - } - } - - return theChar; -} - -unichar unicodeForFunctionKey( UInt32 aKeyCode ) -{ - switch( aKeyCode ) - { - case 0x7A: return NSF1FunctionKey; - case 0x78: return NSF2FunctionKey; - case 0x63: return NSF3FunctionKey; - case 0x76: return NSF4FunctionKey; - case 0x60: return NSF5FunctionKey; - case 0x61: return NSF6FunctionKey; - case 0x62: return NSF7FunctionKey; - case 0x64: return NSF8FunctionKey; - case 0x65: return NSF9FunctionKey; - case 0x6D: return NSF10FunctionKey; - case 0x67: return NSF11FunctionKey; - case 0x6F: return NSF12FunctionKey; - default: return 0x00; - } -} - -NSString * stringForCharacter( const unsigned short aKeyCode, unichar aCharacter ) -{ - NSString * theString = nil; - switch( aCharacter ) - { - case NSUpArrowFunctionKey: - aCharacter = 0x2191; - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - case NSDownArrowFunctionKey: - aCharacter = 0x2193; - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - case NSLeftArrowFunctionKey: - aCharacter = 0x2190; - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - case NSRightArrowFunctionKey: - aCharacter = 0x2192; - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - case NSF1FunctionKey: theString = @"F1"; break; - case NSF2FunctionKey: theString = @"F2"; break; - case NSF3FunctionKey: theString = @"F3"; break; - case NSF4FunctionKey: theString = @"F4"; break; - case NSF5FunctionKey: theString = @"F5"; break; - case NSF6FunctionKey: theString = @"F6"; break; - case NSF7FunctionKey: theString = @"F7"; break; - case NSF8FunctionKey: theString = @"F8"; break; - case NSF9FunctionKey: theString = @"F9"; break; - case NSF10FunctionKey: theString = @"F10"; break; - case NSF11FunctionKey: theString = @"F11"; break; - case NSF12FunctionKey: theString = @"F12"; break; - case NSF13FunctionKey: theString = @"F13"; break; - case NSF14FunctionKey: theString = @"F14"; break; - case NSF15FunctionKey: theString = @"F15"; break; - case NSF16FunctionKey: theString = @"F16"; break; - case NSF17FunctionKey: theString = @"F17"; break; - case NSF18FunctionKey: theString = @"F18"; break; - case NSF19FunctionKey: theString = @"F19"; break; - case NSF20FunctionKey: theString = @"F20"; break; - case NSF21FunctionKey: theString = @"F21"; break; - case NSF22FunctionKey: theString = @"F22"; break; - case NSF23FunctionKey: theString = @"F23"; break; - case NSF24FunctionKey: theString = @"F24"; break; - case NSF25FunctionKey: theString = @"F25"; break; - case NSF26FunctionKey: theString = @"F26"; break; - case NSF27FunctionKey: theString = @"F27"; break; - case NSF28FunctionKey: theString = @"F28"; break; - case NSF29FunctionKey: theString = @"F29"; break; - case NSF30FunctionKey: theString = @"F30"; break; - case NSF31FunctionKey: theString = @"F31"; break; - case NSF32FunctionKey: theString = @"F32"; break; - case NSF33FunctionKey: theString = @"F33"; break; - case NSF34FunctionKey: theString = @"F34"; break; - case NSF35FunctionKey: theString = @"F35"; break; - case NSInsertFunctionKey: theString = @"Ins"; break; - case NSDeleteFunctionKey: theString = @"Delete"; break; - case NSHomeFunctionKey: - aCharacter = 0x2196; - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - case NSBeginFunctionKey: theString = @"Begin"; break; - case NSEndFunctionKey: theString = @"End"; break; - case NSPageUpFunctionKey: - // aCharacter = 0x21DE; - // theString = [NSString stringWithCharacters:&aCharacter length:1]; - theString = @"PgUp"; - break; - case NSPageDownFunctionKey: -// aCharacter = 0x21DF; -// theString = [NSString stringWithCharacters:&aCharacter length:1]; - theString = @"PgDn"; - break; - case NSPrintScreenFunctionKey: theString = @"Print"; break; - case NSScrollLockFunctionKey: theString = @"ScrollLock"; break; - case NSPauseFunctionKey: theString = @"Pause"; break; - case NSSysReqFunctionKey: theString = @"SysReq"; break; - case NSBreakFunctionKey: theString = @"Break"; break; - case NSResetFunctionKey: theString = @"Reset"; break; - case NSStopFunctionKey: theString = @"Stop"; break; - case NSMenuFunctionKey: theString = @"Menu"; break; - case NSUserFunctionKey: theString = @"User"; break; - case NSSystemFunctionKey: theString = @"System"; break; - case NSPrintFunctionKey: theString = @"Print"; break; - case NSClearLineFunctionKey: theString = @"ClearLine"; break; - case NSClearDisplayFunctionKey: theString = @"ClearDisplay"; break; - case NSInsertLineFunctionKey: theString = @"InsertLine"; break; - case NSDeleteLineFunctionKey: theString = @"DeleteLine"; break; - case NSInsertCharFunctionKey: theString = @"InsertChar"; break; - case NSDeleteCharFunctionKey: - aCharacter = 0x2326; - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - case NSPrevFunctionKey: theString = @"Prev"; break; - case NSNextFunctionKey: theString = @"Next"; break; - case NSSelectFunctionKey: theString = @"Select"; break; - case NSExecuteFunctionKey: theString = @"Exec"; break; - case NSUndoFunctionKey: theString = @"Undo"; break; - case NSRedoFunctionKey: theString = @"Redo"; break; - case NSFindFunctionKey: theString = @"Find"; break; - case NSHelpFunctionKey: theString = @"Help"; break; - case NSModeSwitchFunctionKey: theString = @"ModeSwitch"; break; - case kEscapeCharCode: theString = @"Esc"; break; - case kTabCharCode: - aCharacter = 0x21E5; - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - case kSpaceCharCode: theString = @"Space"; break; - case kEnterCharCode: - aCharacter = 0x21B5; - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - case kReturnCharCode: - aCharacter = 0x21A9; - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - case kDeleteCharCode: theString = @"Del"; break; - case '0'...'9': - case '=': - case '/': - case '*': - case '-': - case '+': - case '.': - theString = [NSString stringWithCharacters:&aCharacter length:1]; - if( aKeyCode > 60 ) - theString = [NSString stringWithFormat:@"[%@]", theString]; - break; - default: - aCharacter = unicharForKeyCode(aKeyCode); - - if( aCharacter >= 'a' && aCharacter <= 'z' ) // convert to uppercase - aCharacter = aCharacter + 'A' - 'a'; - - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - } - return theString; -} - -NSString * stringForModifiers( unsigned int aModifierFlags ) -{ - NSMutableString * theString; - unichar theCharacter; - - theString = [NSMutableString string]; - if( aModifierFlags & NSControlKeyMask) - { - theCharacter = kControlUnicode; - [theString appendString:[NSString stringWithCharacters:&theCharacter length:1]]; - } - - if( aModifierFlags & NSAlternateKeyMask) - { - theCharacter = kOptionUnicode; - [theString appendString:[NSString stringWithCharacters:&theCharacter length:1]]; - } - - if( aModifierFlags & NSShiftKeyMask) - { - theCharacter = kShiftUnicode; - [theString appendString:[NSString stringWithCharacters:&theCharacter length:1]]; - } - - if( aModifierFlags & NSCommandKeyMask) - { - theCharacter = kCommandUnicode; - [theString appendString:[NSString stringWithCharacters:&theCharacter length:1]]; - } - - return theString; -} diff --git a/ThirdParty/NDHotKeys/NDHotKeyControl.h b/ThirdParty/NDHotKeys/NDHotKeyControl.h deleted file mode 100755 index aa9874c9c..000000000 --- a/ThirdParty/NDHotKeys/NDHotKeyControl.h +++ /dev/null @@ -1,76 +0,0 @@ -/*! - @header NDHotKeyControl.h - @abstract Header file for a subclass of NSTextField for getting hot key combinations from the user. - @discussion The NDHotKeyControl can be used to get a NDHotKeyEvent for the last key combination pressed by the user. - - Created by Nathan Day on Wed Mar 05 2003. - Copyright (c) 2002 Nathan Day. All rights reserved. - */ - -#import - -@class NDHotKeyEvent; - -/*! - @class NDHotKeyControl - @abstract Subclass of NSTextField for getting hot key combinations from the user. - @discussion The NDHotKeyControl can be used to get a NDHotKeyEvent for the last key combination pressed by the user. - */ -@interface NDHotKeyControl : NSTextField -{ -@private - unsigned short keyCode; - unichar character; - unsigned long modifierFlags; - BOOL requiresModifierKeys; -} - -/*! - @method keyCode - @abstract Get key code. - @discussion Returns the key code for the last key combination the user pressed while the reciever was active. - @result A unsigned short containing key code. - */ -- (unsigned short)keyCode; - -/*! - @method character - @abstract Get unicode character. - @discussion Returns the unicode character for the last key combination the user pressed while the reciever was active. - @result A unichar containing character. - */ -- (unichar)character; - -/*! - @method modifierFlags - @abstract Get modifer flags. - @discussion Returns the modifer flags for the last key combination the user pressed while the reciever was active. - @result A unsigned long containing modifer flags. - */ -- (unsigned long)modifierFlags; - -/*! - @method hotKeyEvent - @abstract Get NDHotKeyEvent - @discussion Returns the NDHotKeyEvent instance for the last key combination the user pressed while the reciever was active. The NDHotKeyEvent returned will either be one that has already been created or a newly created one otherwise. - @result A NDHotKeyEvent for the hot key event. - */ -- (NDHotKeyEvent *)hotKeyEvent; - -/*! - @method setRequiresModifierKeys: - @abstract Set whether hot keys entered need modifiers keys. - @discussion This does not include function key which do not require modifier keys no matter what the value you pass for the argument flag - @param flag If NO then the reciever only accepts hot keys combination containing modifer keys. - */ -- (void)setRequiresModifierKeys:(BOOL)flag; - -/*! - @method requiresModifierKeys - @abstract Returns whether hot keys entered need modifiers keys. - @discussion This does not include key which do not require modifier keys no matter what the value is returned. - @result If NO then the reciever only accepts hot keys combination containing modifer keys. - */ -- (BOOL)requiresModifierKeys; - -@end diff --git a/ThirdParty/NDHotKeys/NDHotKeyControl.m b/ThirdParty/NDHotKeys/NDHotKeyControl.m deleted file mode 100755 index 5bdd78d76..000000000 --- a/ThirdParty/NDHotKeys/NDHotKeyControl.m +++ /dev/null @@ -1,116 +0,0 @@ -/* - * NDHotKeyControl.m - * NDHotKeyEvent - * - * Created by Nathan Day on Wed Mar 05 2003. - * Copyright (c) 2002 Nathan Day. All rights reserved. - */ - -#import "NDHotKeyControl.h" -#import "NDHotKeyEvent.h" - -/* - * class implementation NDHotKeyControl - */ -@implementation NDHotKeyControl - -/* - * -initWithFrame: - */ -- (id)initWithFrame:(NSRect)aFrame -{ - if ( self = [super initWithFrame:aFrame] ) - { - [self setEditable:NO]; - requiresModifierKeys = YES; - } - return self; -} - -/* - * -initWithCoder: - */ -- (id)initWithCoder:(NSCoder *)aCoder -{ - if ( self = [super initWithCoder:aCoder] ) - { - [self setEditable:NO]; - requiresModifierKeys = YES; - } - return self; -} - -/* - * -keyCode - */ -- (unsigned short)keyCode -{ - return keyCode; -} - -/* - * -character - */ -- (unichar)character -{ - return character; -} - -/* - * -modifierFlags - */ -- (unsigned long)modifierFlags -{ - return modifierFlags; -} - -/* - * -performKeyEquivalent: - */ -- (BOOL)performKeyEquivalent:(NSEvent*)anEvent -{ - [self keyDown:anEvent]; - return YES; -} - -/* - * -keyDown: - */ -- (void)keyDown:(NSEvent *)theEvent -{ - unsigned long theModifierFlags = [theEvent modifierFlags]; - unichar theChar = [[theEvent charactersIgnoringModifiers] characterAtIndex:0]; - theModifierFlags &= (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask|NSCommandKeyMask); - - if( (theModifierFlags != 0 || !requiresModifierKeys || theChar > 255) && theChar != 0 ) - { - keyCode = [theEvent keyCode]; - modifierFlags = theModifierFlags; - character = theChar; - - [self setStringValue:stringForKeyCodeAndModifierFlags( keyCode, character, modifierFlags )]; - [self performClick:self]; - } -} - -/* - * -hotKeyEvent - */ -- (NDHotKeyEvent *)hotKeyEvent -{ - return [NDHotKeyEvent getHotKeyForKeyCode:[self keyCode] character:[self character] modifierFlags:[self modifierFlags]]; - -} - -- (void)setRequiresModifierKeys:(BOOL)aFlag -{ - requiresModifierKeys = aFlag; -} - -- (BOOL)requiresModifierKeys -{ - return requiresModifierKeys; -} - -@end - diff --git a/ThirdParty/NDHotKeys/NDHotKeyEvent.m b/ThirdParty/NDHotKeys/NDHotKeyEvent.m deleted file mode 100755 index 8805df1ea..000000000 --- a/ThirdParty/NDHotKeys/NDHotKeyEvent.m +++ /dev/null @@ -1,1155 +0,0 @@ -/* - * NDHotKeyEvent.m - * NDHotKeyEvent - * - * Created by Nathan Day on Wed Feb 26 2003. - * Copyright (c) 2002 Nathan Day. All rights reserved. - */ - -#import "NDHotKeyEvent.h" - -#import - -#import "Logging.h" - -@interface NDHotKeyEvent (Private) -+ (NSMapTable *)allHotKeyEvents; -- (BOOL)addHotKey; -- (void)removeHotKey; -- (BOOL)setCollectiveEnabled:(BOOL)aFlag; -- (BOOL)collectiveEnable; -@end - -static NSString * kArchivingKeyCodeKey = @"KeyCodeKey", - * kArchivingCharacterKey = @"CharacterKey", - * kArchivingModifierFlagsKey = @"ModifierFlagsKey", - * kArchivingSelectorReleasedCodeKey = @"SelectorReleasedCodeKey", - * kArchivingSelectorPressedCodeKey = @"SelectorPressedCodeKey"; -const OSType NDHotKeyDefaultSignature = 'NDHK'; - -static OSStatus switchHotKey( NDHotKeyEvent * self, BOOL aFlag ); - -unichar unicodeForFunctionKey( UInt32 aKeyCode ); - -/* - * class implementation NDHotKeyEvent - */ -@implementation NDHotKeyEvent - -#ifdef NDHotKeyEventThreadSafe - static NSLock * hotKeysLock = NULL; - #warning Thread saftey has been enabled for NDHotKeyEvent class methods - #define NDHotKeyEventLock [hotKeysLock lock] - #define NDHotKeyEventUnlock [hotKeysLock unlock] -#else - #warning The NDHotKeyEvent class methods are NOT thread safe - #define NDHotKeyEventLock // lock - #define NDHotKeyEventUnlock // unlock -#endif - -static NSMapTable * allHotKeyEvents = NULL; -static BOOL isInstalled = NO; -static OSType signature = 0; - -unsigned int cocoaModifierFlagsToCarbonModifierFlags( unsigned int aModifierFlags ); - -pascal OSErr eventHandlerCallback( EventHandlerCallRef anInHandlerCallRef, EventRef anInEvent, void * self ); - -NSUInteger hashValueHashFunction( NSMapTable * aTable, const void * aHotKeyEntry ); -BOOL isEqualHashFunction( NSMapTable * aTable, const void * aFirstHotKeyEvent, const void * aSecondHotKeyEvent ); -NSString * describeHashFunction( NSMapTable * aTable, const void * aHotKeyEvent ); - -NSUInteger hashKeyHashFunction( NSMapTable * aTable, const void * aNumber ); -BOOL isEqualKeyHashFunction( NSMapTable * aTable, const void * aFirstNumber, const void * aSecondNumber ); -void hashKeyRetainFunction( NSMapTable * aTable, const void * aNumber ); -void hashKeyReleaseFunction( NSMapTable * aTable, void * aNumber ); - -struct HotKeyMappingEntry -{ - unsigned short keyCode; - unsigned int modifierFlags; - NDHotKeyEvent * hotKeyEvent; -}; - -/* - * +install - */ -+ (BOOL)install -{ - if( isInstalled == NO ) - { - NSMapTable * theHotKeyEvents = [self allHotKeyEvents]; - EventTypeSpec theTypeSpec[] = - { - { kEventClassKeyboard, kEventHotKeyPressed }, - { kEventClassKeyboard, kEventHotKeyReleased } - }; - - NDHotKeyEventLock; - if( theHotKeyEvents != nil && isInstalled == NO ) - { - if( InstallEventHandler( GetEventDispatcherTarget(), NewEventHandlerUPP((EventHandlerProcPtr)eventHandlerCallback), 2, theTypeSpec, theHotKeyEvents, nil ) == noErr ) - { - isInstalled = YES; - } - else - { - DLog(@"Could not install Event handler"); - } - } - NDHotKeyEventUnlock; - } - - return isInstalled; -} - -#ifdef NDHotKeyEventThreadSafe -/* - * +initialize: - */ -+ (void)initialize -{ - while( hotKeysLock == nil ) - { - NSLock * theInstance = [[NSLock alloc] init]; - - if( !CompareAndSwap( nil, (unsigned long int)theInstance, (unsigned long int*)&hotKeysLock) ) - [theInstance release]; // did not use instance - } -} -#endif - -/* - * +setSignature: - */ -+ (void)setSignature:(OSType)aSignature -{ - NSAssert( signature == 0 || aSignature == signature, @"The signature used by NDHotKeyEvent can only be set once safely" ); - signature = aSignature; -} - -/* - * +signature - */ -+ (OSType)signature -{ - signature = signature ? signature : NDHotKeyDefaultSignature; - return signature; -} - -/* - * +setAllEnabled: - */ -+ (BOOL)setAllEnabled:(BOOL)aFlag -{ - BOOL theAllSucceeded = YES; - NSMapTable * theMapTable = [NDHotKeyEvent allHotKeyEvents]; - - /* - * need to install before to make sure the method 'setCollectiveEnabled:' - * doesn't try install since install tries to aquire the lock 'hotKeysLock' - */ - if( theMapTable && [NDHotKeyEvent install] ) - { - NSMapEnumerator theEnumerator; - NSUInteger theKey; - struct HotKeyMappingEntry * theHotKeyMapEntry; - NDHotKeyEventLock; - theEnumerator = NSEnumerateMapTable(theMapTable); - - while ( NSNextMapEnumeratorPair(&theEnumerator, (void**)&theKey, (void**)&theHotKeyMapEntry) ) - { - if( ![theHotKeyMapEntry->hotKeyEvent setCollectiveEnabled:aFlag] ) - theAllSucceeded = NO; - } - NDHotKeyEventUnlock; - } - - return theAllSucceeded; -} - -/* - * +isEnabledKeyCode:modifierFlags: - */ -+ (BOOL)isEnabledKeyCode:(unsigned short)aKeyCode modifierFlags:(unsigned int)aModifierFlags -{ - return [[self findHotKeyForKeyCode:aKeyCode modifierFlags:aModifierFlags] isEnabled]; -} - -/* - * +getHotKeyForKeyCode:character:modifierFlags: - */ -+ (NDHotKeyEvent *)getHotKeyForKeyCode:(unsigned short)aKeyCode character:(unichar)aChar modifierFlags:(unsigned int)aModifierFlags -{ - NDHotKeyEvent * theHotKey = nil; - - theHotKey = [self findHotKeyForKeyCode:aKeyCode modifierFlags:aModifierFlags]; - return theHotKey ? theHotKey : [self hotKeyWithKeyCode:aKeyCode character:aChar modifierFlags:aModifierFlags]; -} - -/* - * +findHotKeyForKeyCode:modifierFlags: - */ -+ (NDHotKeyEvent *)findHotKeyForKeyCode:(unsigned short)aKeyCode modifierFlags:(unsigned int)aModifierFlags -{ - struct HotKeyMappingEntry * theFoundEntry = NULL; - NSMapTable * theMapTable = [NDHotKeyEvent allHotKeyEvents]; - - if( theMapTable ) - { - NDHotKeyEventLock; - theFoundEntry = (struct HotKeyMappingEntry *) NSMapGet( theMapTable, (void*)(NSUInteger)(aKeyCode ^ aModifierFlags) ); - if( theFoundEntry != NULL ) - [[theFoundEntry->hotKeyEvent retain] autorelease]; - NDHotKeyEventUnlock; - } - - return (theFoundEntry) ? theFoundEntry->hotKeyEvent : nil; -} - -/* - * +hotKeyWithKeyCode:character:modifierFlags: - */ -+ (id)hotKeyWithKeyCode:(unsigned short)aKeyCode character:(unichar)aChar modifierFlags:(unsigned int)aModifierFlags -{ - return [self hotKeyWithKeyCode:aKeyCode character:aChar modifierFlags:aModifierFlags target:nil selector:NULL]; -} - -/* - * +hotKeyWithKeyCode:character:modifierFlags:target:selector: - */ -+ (id)hotKeyWithKeyCode:(unsigned short)aKeyCode character:(unichar)aChar modifierFlags:(unsigned int)aModifierFlags target:(id)aTarget selector:(SEL)aSelector -{ - return [[[self alloc] initWithKeyCode:aKeyCode character:aChar modifierFlags:aModifierFlags target:aTarget selector:aSelector] autorelease]; -} - -+ (id)hotKeyWithWithPropertyList:(id)aPropertyList -{ - return [[[self alloc] initWithPropertyList:aPropertyList] autorelease]; -} - -+ (NSString *)description -{ - NSMapTable * theMapTable = [NDHotKeyEvent allHotKeyEvents]; - NSString * theDescription = nil; - if( theMapTable ) - { - NDHotKeyEventLock; - theDescription = @""; - NDHotKeyEventUnlock; - } - return theDescription; -} - -/* - * -init - */ -- (id)init -{ - [self release]; - NSAssert( NO, @"You can not initialize a Hot Key with the init method" ); - return nil; -} - -/* - * -initWithKeyCode:character:modifierFlags: - */ -- (id)initWithKeyCode:(unsigned short)aKeyCode character:(unichar)aChar modifierFlags:(unsigned int)aModifierFlags -{ - return [self initWithKeyCode:aKeyCode character:aChar modifierFlags:aModifierFlags target:nil selector:NULL]; -} - -/* - * -initWithKeyCode:character:modifierFlags:target:selector: - */ -- (id)initWithKeyCode:(unsigned short)aKeyCode character:(unichar)aChar modifierFlags:(unsigned int)aModifierFlags target:(id)aTarget selector:(SEL)aSelector -{ - if( (self = [super init]) != nil ) - { - keyCode = aKeyCode; - character = aChar; - modifierFlags = aModifierFlags; - target = aTarget; - selectorReleased = aSelector; - currentEventType = NDHotKeyNoEvent; - isEnabled.collective = YES; - - if( ![self addHotKey] ) - { - [self release]; - self = nil; - } - } - else - { - [self release]; - self = nil; - } - - return self; -} - -- (id)initWithCoder:(NSCoder *)aDecoder -{ - if( (self = [super init]) != nil) - { - if( [aDecoder allowsKeyedCoding] ) - { - keyCode = [[aDecoder decodeObjectForKey:kArchivingKeyCodeKey] unsignedShortValue]; - character = [[aDecoder decodeObjectForKey:kArchivingCharacterKey] unsignedShortValue]; - modifierFlags = [[aDecoder decodeObjectForKey:kArchivingModifierFlagsKey] unsignedIntValue]; - - selectorReleased = NSSelectorFromString( [aDecoder decodeObjectForKey:kArchivingSelectorReleasedCodeKey] ); - selectorPressed = NSSelectorFromString( [aDecoder decodeObjectForKey:kArchivingSelectorPressedCodeKey] ); - } - else - { - [aDecoder decodeValueOfObjCType:@encode(unsigned short) at:&keyCode]; - [aDecoder decodeValueOfObjCType:@encode(unichar) at:&character]; - [aDecoder decodeValueOfObjCType:@encode(unsigned int) at:&modifierFlags]; - - selectorReleased = NSSelectorFromString( [aDecoder decodeObject] ); - selectorPressed = NSSelectorFromString( [aDecoder decodeObject] ); - } - - if( ![self addHotKey] ) - { - [self release]; - self = nil; - } - } - - return self; -} - -- (void)encodeWithCoder:(NSCoder *)anEncoder -{ - if( [anEncoder allowsKeyedCoding] ) - { - [anEncoder encodeObject:[NSNumber numberWithUnsignedShort:keyCode] forKey:kArchivingKeyCodeKey]; - [anEncoder encodeObject:[NSNumber numberWithUnsignedShort:character] forKey:kArchivingCharacterKey]; - [anEncoder encodeObject:[NSNumber numberWithUnsignedInt:modifierFlags] forKey:kArchivingModifierFlagsKey]; - - [anEncoder encodeObject:NSStringFromSelector( selectorReleased ) forKey:kArchivingSelectorReleasedCodeKey]; - [anEncoder encodeObject:NSStringFromSelector( selectorPressed ) forKey:kArchivingSelectorPressedCodeKey]; - } - else - { - [anEncoder encodeValueOfObjCType:@encode(unsigned short) at:&keyCode]; - [anEncoder encodeValueOfObjCType:@encode(unichar) at:&character]; - [anEncoder encodeValueOfObjCType:@encode(unsigned int) at:&modifierFlags]; - - [anEncoder encodeObject:NSStringFromSelector( selectorReleased )]; - [anEncoder encodeObject:NSStringFromSelector( selectorPressed )]; - } -} - -- (id)initWithPropertyList:(id)aPropertyList -{ - if( aPropertyList ) - { - NSString * theCharacter; - NSNumber * theKeyCode, - * theModiferFlag; - SEL theKeyPressedSelector, - theKeyReleasedSelector; - - theKeyCode = [aPropertyList objectForKey:kArchivingKeyCodeKey]; - theCharacter = [aPropertyList objectForKey:kArchivingCharacterKey]; - theModiferFlag = [aPropertyList objectForKey:kArchivingModifierFlagsKey]; - theKeyPressedSelector = NSSelectorFromString([aPropertyList objectForKey:kArchivingSelectorPressedCodeKey]); - theKeyReleasedSelector = NSSelectorFromString([aPropertyList objectForKey:kArchivingSelectorReleasedCodeKey]); - - self = [self initWithKeyCode:[theKeyCode unsignedShortValue] character:[theCharacter characterAtIndex:0] modifierFlags:[theModiferFlag unsignedIntValue]]; - } - else - { - [self release]; - self = nil; - } - - return self; -} - -- (id)propertyList -{ - return [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithUnsignedShort:[self keyCode]], kArchivingKeyCodeKey, - [NSString stringWithCharacters:&character length:1] , kArchivingCharacterKey, - [NSNumber numberWithUnsignedInt:[self modifierFlags]], kArchivingModifierFlagsKey, - NSStringFromSelector( selectorPressed ), kArchivingSelectorPressedCodeKey, - NSStringFromSelector( selectorReleased ), kArchivingSelectorReleasedCodeKey, - nil]; -} - -/* - * -release - */ -- (oneway void)release -{ - /* - * We need to remove the hot key from the hash table before it's retain count reaches zero - */ - if( [self retainCount] == 1 ) - { - NSMapTable * theMapTable = [NDHotKeyEvent allHotKeyEvents]; - if( theMapTable ) - { - NDHotKeyEventLock; - switchHotKey( self, NO ); - if( [self retainCount] == 1 ) // check again because it might have changed - { - [theMapTable removeObjectForKey:[NSNumber numberWithInteger:[self hash]]]; - } - NDHotKeyEventUnlock; - } - } -// else - [super release]; -} - -- (void)dealloc -{ - if( UnregisterEventHotKey( reference ) != noErr ) // in lock from release - DLog( @"Failed to unregister hot key %@", self ); - [super dealloc]; -} - -/* - * -setEnabled: - */ -- (BOOL)setEnabled:(BOOL)aFlag -{ - BOOL theResult = YES; - - if( [NDHotKeyEvent install] ) - { - /* - * if individual and collective YES then currently ON, otherwise currently off - */ - NDHotKeyEventLock; - if( aFlag == YES && isEnabled.collective == YES && isEnabled.individual == NO ) - { - theResult = (switchHotKey( self, YES ) == noErr); - } - else if( aFlag == NO && isEnabled.collective == YES && isEnabled.individual == YES ) - { - theResult = (switchHotKey( self, NO ) == noErr); - } - NDHotKeyEventUnlock; - - if( theResult ) - isEnabled.individual = aFlag; - else - DLog(@"%s failed ", aFlag ? "enable" : "disable" ); - } - else - theResult = NO; - - return theResult; -} - -/* - * -isEnabled - */ -- (BOOL)isEnabled -{ - return isEnabled.individual && isEnabled.collective; -} - -/* - * -target - */ -- (id)target -{ - return target; -} - -/* -* -selector -*/ -- (SEL)selector -{ - return selectorReleased; -} - -/* - * -selectorReleased - */ -- (SEL)selectorReleased -{ - return selectorReleased; -} - -/* -* -selectorPressed -*/ -- (SEL)selectorPressed -{ - return selectorPressed; -} - -/* - * -currentEventType - * (NDHotKeyNoEvent | NDHotKeyPressedEvent | NDHotKeyReleasedEvent) - */ -- (int)currentEventType -{ - return currentEventType; -} - -/* - * -setTarget:selector: - */ -- (BOOL)setTarget:(id)aTarget selector:(SEL)aSelector -{ - return [self setTarget:aTarget selectorReleased:aSelector selectorPressed:(SEL)0]; -} - -/* - * -setTarget:selectorReleased:selectorPressed: - */ -- (BOOL)setTarget:(id)aTarget selectorReleased:(SEL)aSelectorReleased selectorPressed:(SEL)aSelectorPressed -{ - [self setEnabled:NO]; - if( target && target != aTarget ) - { - [self setEnabled:NO]; - if( ![target respondsToSelector:@selector(targetWillChangeToObject:forHotKeyEvent:)] || [target targetWillChangeToObject:aTarget forHotKeyEvent:self] ) - { - target = aTarget; - selectorReleased = aSelectorReleased; - selectorPressed = aSelectorPressed; - } - } - else - { - target = aTarget; - selectorReleased = aSelectorReleased; - selectorPressed = aSelectorPressed; - } - - return target == aTarget; // was change succesful -} - -/* - * -performHotKeyReleased - */ -- (void)performHotKeyReleased -{ - NSAssert( target, @"NDHotKeyEvent tried to perfrom release with no target" ); - - if( selectorReleased && [target respondsToSelector:selectorReleased]) - { - currentEventType = NDHotKeyReleasedEvent; - [target performSelector:selectorReleased withObject:self]; - currentEventType = NDHotKeyNoEvent; - } -} - -/* - * -performHotKeyPressed - */ -- (void)performHotKeyPressed -{ - NSAssert( target, @"NDHotKeyEvent tried to perfrom press with no target" ); - - if( selectorPressed && [target respondsToSelector:selectorPressed]) - { - currentEventType = NDHotKeyPressedEvent; - [target performSelector:selectorPressed withObject:self]; - currentEventType = NDHotKeyNoEvent; - } -} - -/* - * -keyCode - */ -- (unsigned short)keyCode -{ - return keyCode; -} - -/* - * -character - */ -- (unichar)character -{ - return character; -} - -/* - * -modifierFlags - */ -- (unsigned int)modifierFlags -{ - return modifierFlags; -} - -/* - * -stringValue - */ -- (NSString *)stringValue -{ - NSString * theStringValue = nil; - NDHotKeyEventLock; - theStringValue = stringForKeyCodeAndModifierFlags( [self keyCode], [self character], [self modifierFlags] ); - NDHotKeyEventUnlock; - - return theStringValue; -} - - -/* - * -isEqual: - */ -- (BOOL)isEqual:(id)anObject -{ - return [super isEqual:anObject] || ([anObject isKindOfClass:[self class]] == YES && [self keyCode] == [(NDHotKeyEvent*)anObject keyCode] && [self modifierFlags] == [(NDHotKeyEvent*)anObject modifierFlags]); -} - -/* - * -hash - */ -- (NSUInteger)hash -{ - return (unsigned int)keyCode ^ modifierFlags; // xor -} - -/* - * -description - */ -- (NSString *)description -{ - return [NSString stringWithFormat:@"{\n\tKey Combination: %@,\n\tEnabled: %s\n\tKey Press Selector: %@\n\tKey Release Selector: %@\n}\n", [self stringValue], - [self isEnabled] ? "yes" : "no", - NSStringFromSelector([self selectorPressed]), - NSStringFromSelector([self selectorReleased])]; -} - -/* - * cocoaModifierFlagsToCarbonModifierFlags() - */ -unsigned int cocoaModifierFlagsToCarbonModifierFlags( unsigned int aModifierFlags ) -{ - unsigned int theCarbonModifierFlags = 0; - - if(aModifierFlags & NSShiftKeyMask) - theCarbonModifierFlags |= shiftKey; - - if(aModifierFlags & NSControlKeyMask) - theCarbonModifierFlags |= controlKey; - - if(aModifierFlags & NSAlternateKeyMask) - theCarbonModifierFlags |= optionKey; - - if(aModifierFlags & NSCommandKeyMask) - theCarbonModifierFlags |= cmdKey; - - return theCarbonModifierFlags; -} - -/* - * eventHandlerCallback() - */ -pascal OSErr eventHandlerCallback( EventHandlerCallRef anInHandlerCallRef, EventRef anInEvent, void * anInUserData ) -{ - NSMapTable * allHotKeyEvents = (NSMapTable *)anInUserData; - EventHotKeyID theHotKeyID; - OSStatus theError; - - NSCAssert( GetEventClass( anInEvent ) == kEventClassKeyboard, @"Got event that is not a hot key event" ); - - theError = GetEventParameter( anInEvent, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(EventHotKeyID), NULL, &theHotKeyID ); - - if( theError == noErr ) - { - struct HotKeyMappingEntry * theHotKeyMappingEntry; - NDHotKeyEvent * theHotKeyEvent; - UInt32 theEventKind; - - NSCAssert( [NDHotKeyEvent signature] == theHotKeyID.signature, @"Got hot key event with wrong signature" ); - - theHotKeyMappingEntry = (struct HotKeyMappingEntry *) NSMapGet(allHotKeyEvents, (void *)(NSUInteger)theHotKeyID.id); - - if ( theHotKeyMappingEntry ) { - theHotKeyEvent = theHotKeyMappingEntry->hotKeyEvent; - theEventKind = GetEventKind( anInEvent ); - if( kEventHotKeyPressed == theEventKind ) - { - [theHotKeyEvent performHotKeyPressed]; - } - else if( kEventHotKeyReleased == theEventKind ) - { - [theHotKeyEvent performHotKeyReleased]; - } - } - } - - return theError; -} - -/* - * hashValueHashFunction() - */ -NSUInteger hashValueHashFunction( NSMapTable * aTable, const void * aHotKeyEntry ) -{ - struct HotKeyMappingEntry * theHotKeyEntry; - unsigned int theKeyCode, - theModifiers; - - theHotKeyEntry = (struct HotKeyMappingEntry*)aHotKeyEntry; - theKeyCode = (unsigned int)theHotKeyEntry->keyCode; - theModifiers = (unsigned int)theHotKeyEntry->modifierFlags; - return theKeyCode ^ theModifiers; // xor -} - -/* - * isEqualHashFunction() - */ -BOOL isEqualHashFunction( NSMapTable * aTable, const void * aFirstHotKeyEntry, const void * aSecondHotKeyEntry ) -{ - struct HotKeyMappingEntry * theFirst, - * theSecond; - - theFirst = (struct HotKeyMappingEntry*)aFirstHotKeyEntry; - theSecond = (struct HotKeyMappingEntry*)aSecondHotKeyEntry; - return theFirst->keyCode == theSecond->keyCode && theFirst->modifierFlags == theSecond->modifierFlags; -} - -/* - * describeHashFunction() - */ -NSString * describeHashFunction( NSMapTable * aTable, const void * aHotKeyEntry ) -{ - NDHotKeyEvent * theHotKey; - - theHotKey = ((struct HotKeyMappingEntry*)aHotKeyEntry)->hotKeyEvent; - return [theHotKey description]; -} - -NSUInteger hashKeyHashFunction( NSMapTable * aTable, const void * aNumber ) -{ - NSNumber * theNumber = (NSNumber *) aNumber; - return [theNumber integerValue]; -} - -BOOL isEqualKeyHashFunction( NSMapTable * aTable, const void * aFirstNumber, const void * aSecondNumber ) -{ - NSNumber * theFirstNumber = (NSNumber *) aFirstNumber; - NSNumber * theSecondNumber = (NSNumber *) aSecondNumber; - return [theFirstNumber isEqual:theSecondNumber]; -} - -void hashKeyRetainFunction( NSMapTable * aTable, const void * aNumber ) -{ - const NSNumber * theNumber = (const NSNumber *) aNumber; - [theNumber retain]; -} - -void hashKeyReleaseFunction( NSMapTable * aTable, void * aNumber ) -{ - NSNumber * theNumber = (NSNumber *) aNumber; - [theNumber release]; -} - -@end - -@implementation NDHotKeyEvent (Private) - -/* - * +allHotKeyEvents - */ -+ (NSMapTable *)allHotKeyEvents -{ - if( allHotKeyEvents == NULL ) - { - NDHotKeyEventLock; - if( allHotKeyEvents == NULL ) - allHotKeyEvents = NSCreateMapTable(NSIntegerMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 0); - NDHotKeyEventUnlock; - } - - return allHotKeyEvents; -} - -/* - * -addHotKey - */ -- (BOOL)addHotKey -{ - NSMapTable * theMapTable = [NDHotKeyEvent allHotKeyEvents]; - if( theMapTable ) - { - struct HotKeyMappingEntry * theEntry; - - theEntry = (struct HotKeyMappingEntry *)malloc(sizeof(struct HotKeyMappingEntry)); - - theEntry->keyCode = [self keyCode]; - theEntry->modifierFlags = [self modifierFlags]; - theEntry->hotKeyEvent = self; - - NDHotKeyEventLock; - NSMapInsert(theMapTable, (void*)[self hash], theEntry); - NDHotKeyEventUnlock; - } - - return YES; -} - -/* - * -removeHotKey - */ -- (void)removeHotKey -{ - [self setEnabled:NO]; - - NSMapTable * theMapTable = [NDHotKeyEvent allHotKeyEvents]; - if( theMapTable ) - { - NDHotKeyEventLock; - free(NSMapGet(theMapTable, (void *)[self hash])); - NSMapRemove(theMapTable, (void*)[self hash]); - NDHotKeyEventUnlock; - } -} - -/* - * setCollectiveEnabled: - */ -- (BOOL)setCollectiveEnabled:(BOOL)aFlag -{ - BOOL theResult = YES; - - if( [NDHotKeyEvent install] ) - { - /* - * if individual and collective YES then currently ON, otherwise currently off - */ - NDHotKeyEventLock; - if( aFlag == YES && isEnabled.collective == NO && isEnabled.individual == YES ) - { - theResult = (switchHotKey( self, YES ) == noErr); - } - else if( aFlag == NO && isEnabled.collective == YES && isEnabled.individual == YES ) - { - theResult = (switchHotKey( self, NO ) == noErr); - } - NDHotKeyEventUnlock; - - if( theResult ) - isEnabled.collective = aFlag; - else - DLog(@"%s failed", aFlag ? "enable" : "disable" ); - } - else - theResult = NO; - - return theResult; -} - -/* - * collectiveEnable() - */ -- (BOOL)collectiveEnable -{ - return isEnabled.collective; -} - -/* - * switchHotKey() - */ -static OSStatus switchHotKey( NDHotKeyEvent * self, BOOL aFlag ) -{ - OSStatus theError; - if( aFlag ) - { - struct HotKeyMappingEntry theDummyEntry; - - theDummyEntry.keyCode = [self keyCode]; - theDummyEntry.modifierFlags = [self modifierFlags]; - theDummyEntry.hotKeyEvent = nil; - - EventHotKeyID theHotKeyID; - - theHotKeyID.signature = [NDHotKeyEvent signature]; - theHotKeyID.id = hashValueHashFunction( nil, (const void *)&theDummyEntry ); - - NSCAssert( theHotKeyID.signature, @"HotKeyEvent signature has not been set yet" ); - NSCParameterAssert(sizeof(unsigned long) >= sizeof(id) ); - - theError = RegisterEventHotKey( self->keyCode, cocoaModifierFlagsToCarbonModifierFlags(self->modifierFlags), theHotKeyID, GetEventDispatcherTarget(), 0, &self->reference ); - } - else - { - theError = UnregisterEventHotKey( self->reference ); - } - - return theError; -} - -@end - - -/* - * stringForKeyCodeAndModifierFlags() - */ -NSString * stringForKeyCodeAndModifierFlags( unsigned short aKeyCode, unichar aChar, unsigned int aModifierFlags ) -{ - NSString * stringForCharacter( const unsigned short aKeyCode, unichar aCharacter ); - NSString * stringForModifiers( unsigned int aModifierFlags ); - - return [stringForModifiers(aModifierFlags) stringByAppendingString:stringForCharacter( aKeyCode, aChar )]; -} - -/* - * unicharForKeyCode() - */ -unichar unicharForKeyCode( unsigned short aKeyCode ) -{ - UInt32 theChar = kNullCharCode; - - TISInputSourceRef theCurrentKeyBoardLayout = TISCopyCurrentKeyboardLayoutInputSource(); - UCKeyboardLayout *uchr = (UCKeyboardLayout *) TISGetInputSourceProperty(theCurrentKeyBoardLayout, kTISPropertyUnicodeKeyLayoutData); - if ( uchr != nil ) - { - UInt32 deadKeyState = 0; - UInt32 flags = 0; - UniCharCount maxStringLength = 255; - UniCharCount actualStringLength = 0; - UniChar unicodeString[maxStringLength]; - - UCKeyTranslate(uchr, aKeyCode, kUCKeyActionDown, flags, LMGetKbdType(), 1, &deadKeyState, maxStringLength, &actualStringLength, unicodeString); - - if ( actualStringLength == 1 ) - theChar = unicodeString[ 0 ]; - - switch( theChar ) - { - case kHomeCharCode: theChar = NSHomeFunctionKey; break; -// case kEnterCharCode: theChar = ; break; - case kEndCharCode: theChar = NSEndFunctionKey; break; - case kHelpCharCode: theChar = NSHelpFunctionKey; break; -// case kBellCharCode: theChar = ; break; -// case kBackspaceCharCode: theChar = ; break; -// case kTabCharCode: theChar = ; break; -// case kLineFeedCharCode: theChar = ; break; - case kPageUpCharCode: theChar = NSPageUpFunctionKey; break; - case kPageDownCharCode: theChar = NSPageDownFunctionKey; break; -// case kReturnCharCode: theChar = ; break; - case kFunctionKeyCharCode: theChar = unicodeForFunctionKey( aKeyCode ); break; -// case kCommandCharCode: theChar = ; break; -// case kCheckCharCode: theChar = ; break; -// case kDiamondCharCode : theChar = ; break; -// case kAppleLogoCharCode: theChar = ; break; -// case kEscapeCharCode: theChar = ; break; - case kClearCharCode: - theChar = (aKeyCode==0x47) ? NSInsertFunctionKey : theChar; - break; - case kLeftArrowCharCode: theChar = NSLeftArrowFunctionKey; break; - case kRightArrowCharCode: theChar = NSRightArrowFunctionKey; break; - case kUpArrowCharCode: theChar = NSUpArrowFunctionKey; break; - case kDownArrowCharCode: theChar = NSDownArrowFunctionKey; break; -// case kSpaceCharCode: theChar = ; break; - case kDeleteCharCode: theChar = NSDeleteCharFunctionKey; break; -// case kBulletCharCode: theChar = ; break; -// case kNonBreakingSpaceCharCode: theChar = ; break; - } - } - - return theChar; -} - -unichar unicodeForFunctionKey( UInt32 aKeyCode ) -{ - switch( aKeyCode ) - { - case 0x7A: return NSF1FunctionKey; - case 0x78: return NSF2FunctionKey; - case 0x63: return NSF3FunctionKey; - case 0x76: return NSF4FunctionKey; - case 0x60: return NSF5FunctionKey; - case 0x61: return NSF6FunctionKey; - case 0x62: return NSF7FunctionKey; - case 0x64: return NSF8FunctionKey; - case 0x65: return NSF9FunctionKey; - case 0x6D: return NSF10FunctionKey; - case 0x67: return NSF11FunctionKey; - case 0x6F: return NSF12FunctionKey; - default: return 0x00; - } -} - -NSString * stringForCharacter( const unsigned short aKeyCode, unichar aCharacter ) -{ - NSString * theString = nil; - switch( aCharacter ) - { - case NSUpArrowFunctionKey: - aCharacter = 0x2191; - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - case NSDownArrowFunctionKey: - aCharacter = 0x2193; - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - case NSLeftArrowFunctionKey: - aCharacter = 0x2190; - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - case NSRightArrowFunctionKey: - aCharacter = 0x2192; - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - case NSF1FunctionKey: theString = @"F1"; break; - case NSF2FunctionKey: theString = @"F2"; break; - case NSF3FunctionKey: theString = @"F3"; break; - case NSF4FunctionKey: theString = @"F4"; break; - case NSF5FunctionKey: theString = @"F5"; break; - case NSF6FunctionKey: theString = @"F6"; break; - case NSF7FunctionKey: theString = @"F7"; break; - case NSF8FunctionKey: theString = @"F8"; break; - case NSF9FunctionKey: theString = @"F9"; break; - case NSF10FunctionKey: theString = @"F10"; break; - case NSF11FunctionKey: theString = @"F11"; break; - case NSF12FunctionKey: theString = @"F12"; break; - case NSF13FunctionKey: theString = @"F13"; break; - case NSF14FunctionKey: theString = @"F14"; break; - case NSF15FunctionKey: theString = @"F15"; break; - case NSF16FunctionKey: theString = @"F16"; break; - case NSF17FunctionKey: theString = @"F17"; break; - case NSF18FunctionKey: theString = @"F18"; break; - case NSF19FunctionKey: theString = @"F19"; break; - case NSF20FunctionKey: theString = @"F20"; break; - case NSF21FunctionKey: theString = @"F21"; break; - case NSF22FunctionKey: theString = @"F22"; break; - case NSF23FunctionKey: theString = @"F23"; break; - case NSF24FunctionKey: theString = @"F24"; break; - case NSF25FunctionKey: theString = @"F25"; break; - case NSF26FunctionKey: theString = @"F26"; break; - case NSF27FunctionKey: theString = @"F27"; break; - case NSF28FunctionKey: theString = @"F28"; break; - case NSF29FunctionKey: theString = @"F29"; break; - case NSF30FunctionKey: theString = @"F30"; break; - case NSF31FunctionKey: theString = @"F31"; break; - case NSF32FunctionKey: theString = @"F32"; break; - case NSF33FunctionKey: theString = @"F33"; break; - case NSF34FunctionKey: theString = @"F34"; break; - case NSF35FunctionKey: theString = @"F35"; break; - case NSInsertFunctionKey: theString = @"Ins"; break; - case NSDeleteFunctionKey: theString = @"Delete"; break; - case NSHomeFunctionKey: - aCharacter = 0x2196; - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - case NSBeginFunctionKey: theString = @"Begin"; break; - case NSEndFunctionKey: theString = @"End"; break; - case NSPageUpFunctionKey: - // aCharacter = 0x21DE; - // theString = [NSString stringWithCharacters:&aCharacter length:1]; - theString = @"PgUp"; - break; - case NSPageDownFunctionKey: -// aCharacter = 0x21DF; -// theString = [NSString stringWithCharacters:&aCharacter length:1]; - theString = @"PgDn"; - break; - case NSPrintScreenFunctionKey: theString = @"Print"; break; - case NSScrollLockFunctionKey: theString = @"ScrollLock"; break; - case NSPauseFunctionKey: theString = @"Pause"; break; - case NSSysReqFunctionKey: theString = @"SysReq"; break; - case NSBreakFunctionKey: theString = @"Break"; break; - case NSResetFunctionKey: theString = @"Reset"; break; - case NSStopFunctionKey: theString = @"Stop"; break; - case NSMenuFunctionKey: theString = @"Menu"; break; - case NSUserFunctionKey: theString = @"User"; break; - case NSSystemFunctionKey: theString = @"System"; break; - case NSPrintFunctionKey: theString = @"Print"; break; - case NSClearLineFunctionKey: theString = @"ClearLine"; break; - case NSClearDisplayFunctionKey: theString = @"ClearDisplay"; break; - case NSInsertLineFunctionKey: theString = @"InsertLine"; break; - case NSDeleteLineFunctionKey: theString = @"DeleteLine"; break; - case NSInsertCharFunctionKey: theString = @"InsertChar"; break; - case NSDeleteCharFunctionKey: - aCharacter = 0x2326; - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - case NSPrevFunctionKey: theString = @"Prev"; break; - case NSNextFunctionKey: theString = @"Next"; break; - case NSSelectFunctionKey: theString = @"Select"; break; - case NSExecuteFunctionKey: theString = @"Exec"; break; - case NSUndoFunctionKey: theString = @"Undo"; break; - case NSRedoFunctionKey: theString = @"Redo"; break; - case NSFindFunctionKey: theString = @"Find"; break; - case NSHelpFunctionKey: theString = @"Help"; break; - case NSModeSwitchFunctionKey: theString = @"ModeSwitch"; break; - case kEscapeCharCode: theString = @"Esc"; break; - case kTabCharCode: - aCharacter = 0x21E5; - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - case kSpaceCharCode: theString = @"Space"; break; - case kEnterCharCode: - aCharacter = 0x21B5; - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - case kReturnCharCode: - aCharacter = 0x21A9; - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - case kDeleteCharCode: theString = @"Del"; break; - case '0'...'9': - case '=': - case '/': - case '*': - case '-': - case '+': - case '.': - theString = [NSString stringWithCharacters:&aCharacter length:1]; - if( aKeyCode > 60 ) - theString = [NSString stringWithFormat:@"[%@]", theString]; - break; - default: - aCharacter = unicharForKeyCode(aKeyCode); - - if( aCharacter >= 'a' && aCharacter <= 'z' ) // convert to uppercase - aCharacter = aCharacter + 'A' - 'a'; - - theString = [NSString stringWithCharacters:&aCharacter length:1]; - break; - } - return theString; -} - -NSString * stringForModifiers( unsigned int aModifierFlags ) -{ - NSMutableString * theString; - unichar theCharacter; - - theString = [NSMutableString string]; - if( aModifierFlags & NSControlKeyMask) - { - theCharacter = kControlUnicode; - [theString appendString:[NSString stringWithCharacters:&theCharacter length:1]]; - } - - if( aModifierFlags & NSAlternateKeyMask) - { - theCharacter = kOptionUnicode; - [theString appendString:[NSString stringWithCharacters:&theCharacter length:1]]; - } - - if( aModifierFlags & NSShiftKeyMask) - { - theCharacter = kShiftUnicode; - [theString appendString:[NSString stringWithCharacters:&theCharacter length:1]]; - } - - if( aModifierFlags & NSCommandKeyMask) - { - theCharacter = kCommandUnicode; - [theString appendString:[NSString stringWithCharacters:&theCharacter length:1]]; - } - - return theString; -}