tags:

views:

669

answers:

2

I'm working with an application that allows the customer to customize what shortcut keys are assigned. One thing I want to do is warn if a shortcut key is chosen that is already in use by Mac OS X.

I'm trying to work with CopySymbolicHotKeys, but I'm not sure that I'm using it correctly as it lists commands as being reserved even though I do not see it listed in the "Keyboard Shortcuts" tab-pane of the "Keyboard & Mouse" System Preferences. I would like to be able to get those shortcuts that are "reserved" for system use, is this the API to use?

I've included a sample of my code below, please look at it an offer any suggestion that may come to your mind.

CFArrayRef hotkeyArray = NULL;
OSStatus status = CopySymbolicHotKeys(&hotkeyArray);

if (noErr == status && NULL != hotkeyArray) {

 CFIndex hotKeyCount = CFArrayGetCount(hotkeyArray);

 for (CFIndex i = 0; i < hotKeyCount; i++) {
  CFDictionaryRef hotKeyDict = (CFDictionaryRef) CFArrayGetValueAtIndex(hotkeyArray, i);
  if (hotKeyDict && CFGetTypeID(hotKeyDict) == CFDictionaryGetTypeID()) {
   if (kCFBooleanTrue == (CFBooleanRef) CFDictionaryGetValue(hotKeyDict, kHISymbolicHotKeyEnabled)) {

    SInt32 keyModifiers = 0;

    CFNumberRef cfkeyModifers = (CFNumberRef) CFDictionaryGetValue(hotKeyDict, kHISymbolicHotKeyModifiers);
    CFNumberGetValue(cfkeyModifers, kCFNumberSInt32Type, &keyModifiers);

    bool keyIsCommandOnly = (keyModifiers == (keyModifiers & cmdKey));
    bool keyIsCommandAndOption = (keyModifiers == (keyModifiers & (cmdKey | optionKey)));

    CFNumberRef cfKeyCode = (CFNumberRef) CFDictionaryGetValue(hotKeyDict, kHISymbolicHotKeyCode);

    short keyCode = 0;
    CFNumberGetValue(cfKeyCode, kCFNumberShortType, &keyCode);

    CFStringRef keyString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%C"), keyCode);

    const char* commandOnlyStr = "Command";
    const char* commandAndOptionStr = "Command-Option";
    const char* otherStr = "Other Modifier Key";

    char* modifierStr = otherStr;

    if (keyIsCommandOnly) {
     modifierStr = commandOnlyStr;
    }
    else if (keyIsCommandAndOption) {
     modifierStr = commandAndOptionStr;
    }

    CFStringRef debugString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("Mac OS X Reserved Key: %s %@"), modifierStr, keyString);
    CFShow(debugString); // Command-O, Command-W and other apparently non-reserved keys are output
    CFRelease(debugString);
    CFRelease(keyString);
   }
  }
 }
}
CFRelease(hotkeyArray);
A: 

I wouldn't know how to do it programmically but if hard-coding is an option you'll find a list of MacOSX shortcuts here: http://support.apple.com/kb/HT1343 . I'd use a regex to suck out the key-combinations then programmically convert to keysyms/keycodes. The page appears to be updated by Apple for each OSX release so you should be able to easily repeat the process with each OSX update.

SpliFF
No, hard coding isn't an option as the user can change the values in the System Preferences and then the hard-code values are invalid.
Lyndsey Ferguson
I was thinking that but if the user changed the system preference themselves then it's arguable they would be aware they are clobbering it. I'd argue that in nearly all cases overriding their system preference was actually their desired goal (to reuse a favoured shortcut under a new context). Still I accept it isn't the ideal answer.
SpliFF
A: 
Lyndsey Ferguson