need help implementing Global Keyboard Shortcuts

Yeah, it’s true that ASOC would have more to handle with my method, but the checking of the keyDown could easily be moved to the objective C method if performance were an issue. I don’t know then how the two approaches would differ in their cpu usage since I don’t know anything about those Carbon methods. I also don’t know whether Carbon will continue to be a viable technology — I thought I read something lately indicating that it might be phased out (or no longer supported), but I can’t find where I saw that.

This is probably a better example that behaves more like your Carbon method and moves the checking of the key presses to the block in the objective C method. Like your method, it uses notifications, so any class in the project could process the hot keys. It registers an array of hot keys, and the userInfo of the notification that is sent contains the name of the hot key.

#import "NSEvent+HotKeys.h"

@implementation NSEvent (HotKeys)

+(void)registerHotKeys:(NSArray *) hotKeys notificationName:(NSString *) name {
    id center = [NSNotificationCenter defaultCenter];
    [NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask handler:^(NSEvent *event) {
        for (id aKey in hotKeys){
           NSUInteger theKey = [[aKey valueForKey:@"keyCode"] integerValue];
           NSUInteger modifier = [[aKey valueForKey:@"modifier"] integerValue];
            if ([event keyCode] == theKey && [NSEvent modifierFlags] == modifier) {
                [center postNotificationName:name object:self userInfo:[aKey valueForKey:@"keyName"]];
            } 
        }
    }]; 
}
@end

And it is used like this:

script HotKeysAppDelegate
	property parent : class "NSObject"
	
	on applicationWillFinishLaunching_(aNotification)
		current application's NSEvent's registerHotKeys_notificationName_({{keyName:"hotKey1", keyCode:44, modifier:786432}, {keyName:"hotKey2", keyCode:47, modifier:786432}}, "RDKeyDownNotification")
		set Noter to current application's NSNotificationCenter's defaultCenter()
		Noter's addObserver_selector_name_object_(me, "hotKeyDetected:", "RDKeyDownNotification", missing value)
	end applicationWillFinishLaunching_
	
	on hotKeyDetected_(aNotification)
		log aNotification's userInfo()
	end hotKeyDetected_
	
end script

Ric

Ric,

I was thinking Apple could obsolete Carbon. I read somewhere that the non-UI portions are 64-bit which should include the Carbon Event Manager. It is definitely possible for that to get axed down the road.

You’re second Hot Key example looks great. I will give it a shot. NSNotifications are wonderful. :slight_smile:

Appreciate it!

Todd

Relax – the non-UI Carbon stuff is safe. Especially those parts where there is no Cocoa equivalent.

Hello,

I have made separate posts relating to this post, but since none of them helped me, I decided to post directed to this post. The problem I am having is when I build this application, I get the following error:

Undefined symbols for architecture x86_64:
“_main”, referenced from:
start in crt1.10.6.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

StefanK told me this meant that a framework was missing. Could someone post the steps? I have an ObjC category for NSEvent and the .m part is the right script. I am also calling it from AppDelegate using the script above. What did I miss?

Have you added the Carbon framework to the project?

What application?

Ric

I added the Carbon framework and it still didn’t work…

Sorry rdelmar, I meant my application, the one I’m building :P.

“didn’t work” isn’t much use to anyone. Did you get the same error message, a new one, or what?

If you’re using the code I posted above, then you don’t need the carbon framework. You should post the code so we can see what you are doing.

Ric

Here is my AppDelegate. The purpose of my app is to “lock” the screen.

script AppDelegate
	property parent : class "NSObject"
    
    on lockScreen() 
    do shell script "'/System/Library/CoreServices/Menu Extras/User.menu/Contents/Resources/CGSession' -suspend"
    end lockScreen    
    
    on hotKeyDetected_(aNotification)
        lockScreen()
    end hotKeyDetected_
	
	on applicationWillFinishLaunching_(aNotification)
        current application's NSEvent's registerHotKeys_notificationName_({{keyName:"hotKey1", keyCode:44, modifier:786432}, {keyName:"hotKey2", keyCode:47, modifier:786432}}, "RDKeyDownNotification")
        set Noter to current application's NSNotificationCenter's defaultCenter()
        Noter's addObserver_selector_name_object_(me, "hotKeyDetected:", "RDKeyDownNotification", missing value)
	end applicationWillFinishLaunching_
	
	on applicationShouldTerminate_(sender)
		-- Insert code here to do any housekeeping before your application quits 
		return current application's NSTerminateNow
	end applicationShouldTerminate_
	
end script

Here is the .m file of my ObjC category

#import "NSEvent+HotKeys.h"

@implementation NSEvent (HotKeys)

+(void)registerHotKeys:(NSArray *) hotKeys notificationName:(NSString *) name {
    id center = [NSNotificationCenter defaultCenter];
    [NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask handler:^(NSEvent *event) {
        for (id aKey in hotKeys){
            NSUInteger theKey = [[aKey valueForKey:@"keyCode"] integerValue];
            NSUInteger modifier = [[aKey valueForKey:@"modifier"] integerValue];
            if ([event keyCode] == theKey && [NSEvent modifierFlags] == modifier) {
                [center postNotificationName:name object:self userInfo:[aKey valueForKey:@"keyName"]];
            } 
        }
    }]; 
}
@end

I cut and pasted that code into a new project, and it worked fine to get to the lockScreen() method (I just have a log statement in there). Try putting a log statement in as the first line in lockScreen() and see if it gets executed. If it does, then the problem is with your do shell script.

Ric

I still get the same error…

But when do you get the error? Does the log statement in lockScreen() get executed?

Ric

Okay, I kinda sound stupid… but I don’t know how to activate the console in Xcode 4 :/. Sorry, could you tell me how to do that…

Also, I’m assuming that lockScreen() didn’t work because the build failed anyways, it wouldn’t run.

EDIT: Sorry, it DID run, it just wouldn’t work.

In the upper right hand corner of the Xcode window, there are three buttons with “View” written under them. The middle one toggles the display of the console window. But that’s probably not going to help if your build is failing. I didn’t realize you app wasn’t even running.

Ric

Could I send you my project? I am not explaining enough so maybe it would be more helpful to directly send you the project…

Sure. PM me.

Ric

Gosh… you know I’m a beginner when I can’t even find out how to attach an item to a PM. :stuck_out_tongue:

I don’t know that you can. Just PM me, I 'll respond and then you can attach it to my email

Ric

I am using TechExpertHD´s code in my app. Basically it works but in input or text fields the char that is part of the hotkey combination appears in those input fields. How can I avoid this annoying behavior. E.g. the hotkey alt + cmd + ‘A’ produces an ‘A’. Any hint is appreciated.