Global Hotkeys - Trouble with sizeof EventHotKeyRef
Global Hotkeys - Trouble with sizeof EventHotKeyRef
- Subject: Global Hotkeys - Trouble with sizeof EventHotKeyRef
- From: Tobias Zimmerman <email@hidden>
- Date: Thu, 24 Sep 2009 19:50:08 -0400
- Thread-topic: Global Hotkeys - Trouble with sizeof EventHotKeyRef
Hi all. I have a menu-bar background app that relies on global hotkeys. I
have been using Carbon¹s RegisterEventHotKey to register callbacks for my
hotkeys in Leopard. Is this still the preferred/only method for global
hotkeys in Snow Leopard?
Presuming it is, here is my problem, which relates to making my code 64-bit
clean:
I am using the Carbon/Cocoa hybrid approach described in this somewhat dated
blog post: http://unsanity.org/archives/000045.php
I call ³RegisterEventHotKey² from CarbonEvents.h to register the hotkeys,
and then listen for them in my app delegate¹s ³sendEvent:² method, checking
for event subtype 6¹ (hotkey pressed). The RegisterEventHotKey function is
passed the address of an ³EventHotKeyRef² variable, and returns a unique
reference to the hotkey. In the NSEvent received by ³sendEvent:², the
data1¹ attribute contains the same EventHotKeyRef, allowing one to
correlate the hotkey event with a specific hot key.
After registering the hotkeys, I convert the EventHotKeyRef to an NSValue
using ³valueFromPointer² and then use those values as keys to an
NSMutableDictionary which I then reference in sendEvent to figure out which
action goes with the hotkey that was pressed. Later on, I can unregister
all of the hotkeys by iterating through the dictionary keys, reconverting
the NSValues to pointers (and casting as EventHotKeyRef), and passing to
UnregisterEventHotKey¹.
All this worked fine in 32-bit mode. However, in 64-bit mode, the
EventHotKeyRef passed by CarbonEvents as data1¹ of the NSEvent object does
not match up with the values I am getting back from the RegisterEventHotKey
function. When I register the hotkeys and convert the EventHotKeyRef to an
NSValue, they typically look something like this: ³<20ed1200 01000000>².
However, when I take the data1¹ field from NSEvent on the same hotkey and
convert that to an NSValue, it will look like this: ³<20ed1200 00000000>².
Thus, I can¹t look up the right hotkey in my dictionary. It appears that
whatever mechanism converts the Carbon Event to an NSEvent is munging the
EventHotKeyRef it passes as data1¹ of the NSEvent by truncating the size.
I clearly don¹t have a good grasp of precisely what the EventHotKeyRef¹
type is (it is typedef¹d to an opaque type). I think that I messing things
up when I convert the EventHotKeyRef to an NSValue using valueFromPointer¹,
but I am not really clear what the better/correct method would be.
So, I need a way to (1) record the EventHotKeyRef returned by
RegisterEventHotKey and correlate it to the desired action; (2) unpack the
EventHotKeyRef returned by data1¹ of the NSEvent and look up the desired
action; and (3) iterate through the stored EventHotKeyRefs for the purpose
of calling UnregisterEventHotKey¹.
One approach would be to find the right combination of typecasts/conversions
to store the EventHotKeyRef in a dictionary and have consistent results
between the RegisterEventHotKey and data1 of the NSEvent. Another approach
would be to store the ³good² EventHotKeyRefs in a primitive array for use in
the unregister calls, and then create my lookup dictionary with a shortened
version of the ref that chops off the padding bytes that are getting munged
so that the results are the same when looking up the data1¹ field.
I have not tried going the pure-Carbon route (e.g., as described here
http://dbachrach.com/blog/2005/11/program-global-hotkeys-in-cocoa-easily/ ),
as I am hoping to find a workaround that lets me stay with the (in my
opinion) simpler Cocoa ³sendEvent² method.
(I am also not sure why my NSDictionary lookup works in 32-bit mode if the
NSValue created from the NSEvent data1¹ is a different (but numerically
equivalent) object from the one originally stored in the dictionary key (I
gather NSDictionary¹s objectForKey¹ will return the entry for any NSValue
that returns true from isEqualToValue¹ of the comparator?)
Any and all advice on this would be appreciated. Relevant code is below.
Thanks in advance
Tobias Zimmerman
/* Method to register hotkeys /*
> - (void)assignHotKey: (UInt32)keyEquiv
> modifiers: (UInt32)mods
> hotKeyNumber: (NSInteger)menuIndex //the menu item index of the
> associated action
> {
> EventHotKeyID hotKeyID;
> EventHotKeyRef theRef;
>
> hotKeyID.signature = 'SWMN';
> hotKeyID.id = keyEquiv;
>
> RegisterEventHotKey(
> keyEquiv,
> mods,
> hotKeyID,
> GetApplicationEventTarget(),
> 0,
> &theRef
> );
>
> NSValue *HKValue = [NSValue valueWithPointer:(EventHotKeyRef)theRef];
>
> NSLog(@"Storing HKValue: %@", HKValue); // in 64-bit, e.g.,
> ³<20ed1200 01000000>²
>
> [hotKeys setObject: [NSNumber numberWithInteger: menuIndex] forKey:
> HKValue]; //hotkeys is an NSMutableDictionary
> }
>
>
/*method that processes hotkey events */
> - (void)sendEvent: (NSEvent *)theEvent
> {
> if ( ([theEvent type] == NSSystemDefined) && ([theEvent subtype] ==
> kEventHotKeyPressedSubtype) ) { // kEventHotKeyPressedSubtype == 6
>
> NSValue *HKValue = [NSValue valueWithPointer:(EventHotKeyRef)[theEvent
> data1]];
>
> NSLog(@"Received Hot Key: %@", HKValue); // in 64-bit, e.g.,
> ³<20ed1200 00000000>²
>
> NSInteger menuIndex = [ [hotKeys objectForKey:HKValue] integerValue];
> // Not really sure why this works in 32-bit
>
> // if NSValue objects aren¹t identical
>
> // (but are numerically equal)
>
> [statusMenu performActionForItemAtIndex: menuIndex]; // Calls the
> appropriate menu item for the desired action
> }
> [super sendEvent:theEvent];
> }
>
>
/* method to unregister hotkeys */
> - (void)unregisterHotKeys
> {
> for ( NSValue *key in hotKeys ) {
> UnregisterEventHotKey( (EventHotKeyRef)[key pointerValue] );
> }
> hotKeys = [NSMutableDictionary dictionary];
> }
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden