Friday, October 24, 2014

#1 2010-03-01 05:54:36 pm

elspub
Member
Registered: 2009-11-15
Posts: 39

need help implementing Global Keyboard Shortcuts

I'm trying to set up a couple Global Keyboard Shortcuts for my application so I can activate a quick entry mode from any application. It looks like the Snow Leopard answer is

addGlobalMonitorForEventsMatchingMask

The documentation is here:

http://developer.apple.com/mac/library/ … k:handler:

There's even a short tutorial here:
http://cocoakids.net/14-global-hotkeys- … ow-leopard


My problem is I go cross-eyed trying to convert Obj-C to ASOC, not to mention how to go about using it once converted. Looks like it could just be a few lines in my applicationDidFinishLaunching_(Notification) handler.

Anyone who can help me figure this out will win my praise and gratitude (not to mention I would think I'm not alone in wanting to do this and it would be a useful but of knowledge to have here)


An alternative would be to make my application applescriptable. But that looks more complicated.

Last edited by elspub (2010-03-01 05:58:34 pm)

Offline

 

#2 2010-03-01 06:51:15 pm

Shane Stanley
Member
From: Australia
Registered: 2002-12-07
Posts: 3702

Re: need help implementing Global Keyboard Shortcuts

That method uses blocks, which can't be implemented in ASObjC -- even if it could, you may well run into problems given the amount of processing it would have to do. Your only hope is to use a separate Objective-C class.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#3 2010-03-01 07:32:11 pm

elspub
Member
Registered: 2009-11-15
Posts: 39

Re: need help implementing Global Keyboard Shortcuts

Your only hope is to use a separate Objective-C class.

How do I do that?

Offline

 

#4 2010-03-01 08:04:05 pm

Shane Stanley
Member
From: Australia
Registered: 2002-12-07
Posts: 3702

Re: need help implementing Global Keyboard Shortcuts

You'll need to know some Objective-C. Basically, you'd add an Objective-C class that does something like the stuff in the tutorial you pointed to, and call it from your AS.

Last edited by Shane Stanley (2010-03-01 08:05:51 pm)


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#5 2010-03-01 08:27:29 pm

Craig Williams
Administrator
From: Ft. Smith, AR
Registered: 2006-12-06
Posts: 887

Re: need help implementing Global Keyboard Shortcuts

Are you just wanting the hot key to toggle the active state of your application?

Offline

 

#6 2010-03-01 08:37:47 pm

elspub
Member
Registered: 2009-11-15
Posts: 39

Re: need help implementing Global Keyboard Shortcuts

Are you just wanting the hot key to toggle the active state of your application?

No, I know I can just use applescript and/or a service for that. There's different functions, in a statusbar menu, that I want to activate with the global shortcuts.

If its easier to make my application applescriptable than I could do that too.

Offline

 

#7 2010-03-01 09:23:29 pm

Craig Williams
Administrator
From: Ft. Smith, AR
Registered: 2006-12-06
Posts: 887

Re: need help implementing Global Keyboard Shortcuts

The reason I asked that question is that I have class files that set up the toggle action. You would need to know some Objective-C to manipulate them to your needs though.

Here is the site that I gathered the information from. It uses Carbon but that code requires very little change to work in your app.

http://dbachrach.com/blog/2005/11/progr … oa-easily/

Offline

 

#8 2011-07-31 01:56:22 pm

goodtime
Member
From: Charlotte, NC
Registered: 2009-08-02
Posts: 40
Website

Re: need help implementing Global Keyboard Shortcuts

Found an example on Google code called CocoaHotKeys.  The NSNotifications are in AppleScriptObjC. Changed the CocoaHotKey handler to register the ASCII keycodes in ASOC. The Modifier keys are still in Objective-C; this might be inconvenient for some, but shouldn't be hard to change. Feel free to make and post your own enhancements.

ASOCHotKey 1.0 example adapted by Todd Bruss
Requires Carbon Framework
created with Xcode 4.1
uses code from CocoaHotKeys by Matthias Plappert
Download: http://starplayr.com/downloads/ASOCHotKey.zip
Provided as is without warranty.

PWHotKey's Carbon code is original and remains unchanged; there are a couple 64 to 32-bit integer conversion alerts. Tested in Lion, 64-bit. Should work in Snow Leopard, uses 10.6 SDK. See notes on ASOCHotKeyAppDelegate.applescript. Goal: help ASOC users add Global HotKeys to their AppleScriptObjC Projects with minimal effort.

Last edited by goodtime (2011-07-31 03:43:51 pm)


Developer of StarPlayr and StarLight
http://StarPlayr.com

Offline

 

#9 2011-07-31 11:07:26 pm

rdelmar
Member
From: Sonoma County, CA
Registered: 2010-03-05
Posts: 1008

Re: need help implementing Global Keyboard Shortcuts

I'm not sure why that app you posted is so long and involved, a simple subclass or category on NSEvent would do the job as Shane mentioned earlier in this topic.

I did it this way by creating a category on NSEvent that allows me to use global monitors in ASOC.  The category's .m file  is :

Applescript:

#import "NSEvent+HotKeys.h"

@implementation NSEvent (HotKeys)

+(id) globalMonitorForEventsMatchingMask:(NSEventMask) mask withSelector: (SEL) aSelector target: (id) target {
id theMonitor = [NSEvent addGlobalMonitorForEventsMatchingMask:mask handler:^(NSEvent *event) {
[target performSelector: aSelector withObject: event];
}];
return theMonitor;
}
@end

I can then call it in ASOC like any other NSEvent class method.  Here is an example app that responds to option-control-/ when pressed in another app:

Applescript:

script HotKeysAppDelegate
   property parent : class "NSObject"
   property keyMontitor : missing value
   
   on applicationWillFinishLaunching_(aNotification)
       set keyMontitor to current application's NSEvent's globalMonitorForEventsMatchingMask_withSelector_target_(current application's NSKeyDownMask, "check:", me)
   end applicationWillFinishLaunching_
   
   on check_(theEvent)
       if theEvent's type() is current application's NSKeyDown then
           -- keyCode 44 is "/" and modifierFlag 786432 is Control+Option
           if (theEvent's keyCode() as integer is 44) and (current application's NSEvent's modifierFlags() as integer is 786432) then
               activate
               log "key pressed"
               --current application's NSEvent's removeMonitor_(keyMontitor)
           end if
       else
           log "Not a key press"
       end if
   end check_
   
end script

Ric

Offline

 

#10 2011-08-01 05:39:35 am

goodtime
Member
From: Charlotte, NC
Registered: 2009-08-02
Posts: 40
Website

Re: need help implementing Global Keyboard Shortcuts

You're example is shorter, but it doesn't look like the hot keys are registered and ASOC is stuck having to check every keydown event for a match.  That could be more CPU intensive.  My adaptation from CocoaHotKeys only triggers the ASOC code after the registered hot key has been pressed. It's less work for ASOC to handle.

Thank you for your example.  One nice thing about NSEvents however is I think they will work gestures.

Last edited by goodtime (2011-08-01 05:47:36 am)


Developer of StarPlayr and StarLight
http://StarPlayr.com

Offline

 

#11 2011-08-01 10:35:19 am

rdelmar
Member
From: Sonoma County, CA
Registered: 2010-03-05
Posts: 1008

Re: 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.

Applescript:

#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:

Applescript:

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

Last edited by rdelmar (2011-08-01 12:32:02 pm)

Offline

 

#12 2011-08-01 02:18:07 pm

goodtime
Member
From: Charlotte, NC
Registered: 2009-08-02
Posts: 40
Website

Re: need help implementing Global Keyboard Shortcuts

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. smile

Appreciate it!

Todd

Last edited by goodtime (2011-08-01 03:44:36 pm)


Developer of StarPlayr and StarLight
http://StarPlayr.com

Offline

 

#13 2011-08-01 06:09:49 pm

Shane Stanley
Member
From: Australia
Registered: 2002-12-07
Posts: 3702

Re: need help implementing Global Keyboard Shortcuts

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


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#14 2012-02-15 01:07:38 pm

TechExpertHD
Member
Registered: 2011-12-11
Posts: 82
Website

Re: need help implementing Global Keyboard Shortcuts

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?

Offline

 

#15 2012-02-15 04:21:43 pm

Shane Stanley
Member
From: Australia
Registered: 2002-12-07
Posts: 3702

Re: need help implementing Global Keyboard Shortcuts

Have you added the Carbon framework to the project?


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#16 2012-02-15 05:07:31 pm

rdelmar
Member
From: Sonoma County, CA
Registered: 2010-03-05
Posts: 1008

Re: need help implementing Global Keyboard Shortcuts

The problem I am having is when I build this application

What application?

Ric

Offline

 

#17 2012-02-15 05:49:47 pm

TechExpertHD
Member
Registered: 2011-12-11
Posts: 82
Website

Re: need help implementing Global Keyboard Shortcuts

I added the Carbon framework and it still didn't work...

Sorry rdelmar, I meant my application, the one I'm building tongue.

Offline

 

#18 2012-02-15 05:59:48 pm

Shane Stanley
Member
From: Australia
Registered: 2002-12-07
Posts: 3702

Re: need help implementing Global Keyboard Shortcuts

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


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#19 2012-02-15 06:08:30 pm

rdelmar
Member
From: Sonoma County, CA
Registered: 2010-03-05
Posts: 1008

Re: need help implementing Global Keyboard Shortcuts

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

Offline

 

#20 2012-02-15 06:27:08 pm

TechExpertHD
Member
Registered: 2011-12-11
Posts: 82
Website

Re: need help implementing Global Keyboard Shortcuts

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

Applescript:

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

Applescript:

#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

Offline

 

#21 2012-02-15 06:39:25 pm

rdelmar
Member
From: Sonoma County, CA
Registered: 2010-03-05
Posts: 1008

Re: need help implementing Global Keyboard Shortcuts

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

Offline

 

#22 2012-02-15 06:48:29 pm

TechExpertHD
Member
Registered: 2011-12-11
Posts: 82
Website

Re: need help implementing Global Keyboard Shortcuts

I still get the same error...

Offline

 

#23 2012-02-15 06:59:52 pm

rdelmar
Member
From: Sonoma County, CA
Registered: 2010-03-05
Posts: 1008

Re: need help implementing Global Keyboard Shortcuts

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

Ric

Offline

 

#24 2012-02-15 07:05:57 pm

TechExpertHD
Member
Registered: 2011-12-11
Posts: 82
Website

Re: need help implementing Global Keyboard Shortcuts

Okay, I kinda sound stupid... but I don't know how to activate the console in Xcode 4 hmm. 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.

Last edited by TechExpertHD (2012-02-15 07:08:37 pm)

Offline

 

#25 2012-02-15 07:10:49 pm

rdelmar
Member
From: Sonoma County, CA
Registered: 2010-03-05
Posts: 1008

Re: need help implementing Global Keyboard Shortcuts

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

Offline

 

Board footer

Powered by FluxBB

[ Generated in 0.324 seconds, 11 queries executed ]

RSS (new topics) RSS (active topics)