title: How to monitor global modifier key state (in any application)?
body: <p>I'm using some Carbon code in my Cocoa project for handling global key events (shortcuts) from other applications. Currently I have setup a <code>kEventHotKeyReleased</code> event handler and I can successfully obtain hot keys when my application is not active. That triggers some operation in my application.</p>
  
  <p>The problem I have with the behavior of <code>kEventHotKeyReleased</code> is:</p>
  
  <p>Say for example I press the Cmd-Shift-P key combination. As soon as I release the "P" key the hot key event is triggered. <strong>I need to be able to trigger the event (or manually trigger it) when <em>all</em> of the keys are unpressed</strong> (i.e: the Cmd and Shift keys are released too).</p>
  
  <p>It is easy to monitor for hot keys but I have seen nothing for monitoring individual keystrokes. If I could monitor the modifier key states I would be in business.</p>
  
  <p>Any hints on how to do this?</p>
  
  <p>Thanks in advance!</p>
  
  <hr>
  
  <p><strong>UPDATE:</strong></p>
  
  <p>I've tried using <code>kEventRawKeyUp</code> and <code>kEventRawKeyModifiersChanged</code> but while <code>kEventHotKeyReleased</code> works those two don't even though I set them up in the exact same way as <code>kEventHotKeyReleased</code>.</p>
  
  <pre><code>EventTypeSpec eventTypes[] = {{kEventClassKeyboard, kEventHotKeyReleased}, {kEventClassKeyboard, kEventRawKeyUp}};
  // Changing the order in the list does not help, nor does removing kEventHotKeyReleased
  OSStatus err = InstallApplicationEventHandler(&amp;globalHotkeyHandler, GetEventTypeCount(eventTypes), eventTypes, NULL, NULL);
  // err == noErr after this line
  </code></pre>
  
  <p>The <code>globalHotKeyHandler</code> method is called for <code>kEventHotKeyReleased</code>, but not for <code>kEventRawKeyUp</code> for some reason I can't seem to grasp. Here's what my <code>globalHotKeyHandler</code> method looks like:</p>
  
  <pre><code>OSStatus globalHotkeyHandler(EventHandlerCallRef nextHandler, EventRef anEvent, void *userData) {
      NSLog(@"Something happened!");
  }
  </code></pre>
  
  <p>Is there an additional call that needs to be made or something else I forgot?</p>
  
  <p>N.B: At first glance, it seems like it could be that Access for Assistive Devices is disabled but <strong><em>it is not</em></strong>. So I'm pretty clueless.</p>
  
  <hr>
  
  <p><strong>UPDATE 2:</strong></p>
  
  <p>I investigated a bit on the <code>CGEventTap</code> Leibowitzn suggested and I came up with this setup:</p>
  
  <pre><code>CFMachPortRef keyUpEventTap = CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,kCGEventKeyUp,&amp;keyUpCallback,NULL);
  CFRunLoopSourceRef keyUpRunLoopSourceRef = CFMachPortCreateRunLoopSource(NULL, keyUpEventTap, 0);
  CFRelease(keyUpEventTap);
  CFRunLoopAddSource(CFRunLoopGetCurrent(), keyUpRunLoopSourceRef, kCFRunLoopDefaultMode);
  CFRelease(keyUpRunLoopSourceRef);
  </code></pre>
  
  <p>... and the callback:</p>
  
  <pre><code>CGEventRef keyUpCallback (CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
      NSLog(@"KeyUp event tapped!");
      return event;
  }
  </code></pre>
  
  <p>As you can see I'm using <code>kCGEventKeyUp</code> as the mask for the event tap but somehow I'm receiving <strong><em>mouse down events</em></strong> ??!??</p>
  
  <hr>
  
  <p><strong>UPDATE 3:</strong></p>
  
  <p>Ok forget that, I overlooked the line in the doc that said to use CGEventMaskBit(kCGEventKeyUp) for this parameter, so the correct call is:</p>
  
  <pre><code>CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventKeyUp),&amp;keyUpCallback,NULL);
  </code></pre>
  
  <p>I'm still having a problem though: modifier keys do not trigger the kCGEventKeyUp...</p>
  
  <hr>
  
  <p><strong>UPDATE 4:</strong></p>
  
  <p>Ok forget that again... I'm bound to answer to my own questions 5 minutes after asking them today huh!</p>
  
  <p>To intercept modifier keys, use <code>kCGEventFlagsChanged</code>:</p>
  
  <pre><code>CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventFlagsChanged),&amp;callbackFunction,NULL);
  </code></pre>
  
  <p>So in essence I got the key and modifier key state detection working, but <strong>I'm still interested in knowing <em>why</em> <code>kEventRawKeyUp</code> doesn't work</strong>...</p>
  
  <hr>
  
  <p>N.B: Also note that I'm developing on Tiger with the goal of having support for new and older versions of the OS as much as possible. CGEventTap is 10.4+ only so I'll be using this for now but a backwards-compatible solution would be welcome.</p>