Как отслеживать состояние ключа глобального модификатора (в любом приложении)?

Я использую код Carbon в своем проекте Cocoa для обработки глобальных ключевых событий (ярлыков) из других приложений. В настоящее время я настроилkEventHotKeyReleased обработчик событий, и я могу успешно получить горячие клавиши, когда мое приложение не активно. Это вызывает некоторые операции в моем приложении.

Проблема у меня с поведениемkEventHotKeyReleased является:

Скажем, например, я нажимаю комбинацию клавиш Cmd-Shift-P. Как только я отпускаю клавишу «P», запускается событие горячей клавиши.Мне нужно иметь возможность вызвать событие (или вручную), когдавсе клавиши не нажаты (т.е. клавиши Cmd и Shift тоже отпускаются).

Легко отслеживать горячие клавиши, но я ничего не видел для отслеживания отдельных нажатий клавиш. Если бы я мог отслеживать состояния клавиш-модификаторов, я был бы в бизнесе.

Любые советы о том, как это сделать?

Заранее спасибо!

ОБНОВИТЬ:

Я пытался использоватьkEventRawKeyUp а такжеkEventRawKeyModifiersChanged но покаkEventHotKeyReleased работает эти двое, даже если я настроил их точно так же, какkEventHotKeyReleased.

EventTypeSpec eventTypes[] = {{kEventClassKeyboard, kEventHotKeyReleased}, {kEventClassKeyboard, kEventRawKeyUp}};
// Changing the order in the list does not help, nor does removing kEventHotKeyReleased
OSStatus err = InstallApplicationEventHandler(&globalHotkeyHandler, GetEventTypeCount(eventTypes), eventTypes, NULL, NULL);
// err == noErr after this line

globalHotKeyHandler метод вызывается дляkEventHotKeyReleased, но не дляkEventRawKeyUp по какой-то причине я не могу понять. Вот что мойglobalHotKeyHandler Метод выглядит так:

OSStatus globalHotkeyHandler(EventHandlerCallRef nextHandler, EventRef anEvent, void *userData) {
    NSLog(@"Something happened!");
}

Нужно ли сделать дополнительный звонок или что-то еще, что я забыл?

Н.Б .: На первый взгляд может показаться, что Access for Assistive Devices отключен, ноэто не так, Так что я довольно невежественен.

ОБНОВЛЕНИЕ 2:

Я немного исследовалCGEventTap Лейбовицн предложил, и я придумал эту установку:

CFMachPortRef keyUpEventTap = CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,kCGEventKeyUp,&keyUpCallback,NULL);
CFRunLoopSourceRef keyUpRunLoopSourceRef = CFMachPortCreateRunLoopSource(NULL, keyUpEventTap, 0);
CFRelease(keyUpEventTap);
CFRunLoopAddSource(CFRunLoopGetCurrent(), keyUpRunLoopSourceRef, kCFRunLoopDefaultMode);
CFRelease(keyUpRunLoopSourceRef);

... и обратный вызов:

CGEventRef keyUpCallback (CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
    NSLog(@"KeyUp event tapped!");
    return event;
}

Как вы можете видеть, я используюkCGEventKeyUp в качестве маски для события, но как-то я получаюсобытия мыши вниз ??! ??

ОБНОВЛЕНИЕ 3:

Хорошо, забудьте, что я пропустил строку в документе, в которой говорится, что для этого параметра используется CGEventMaskBit (kCGEventKeyUp), поэтому правильный вызов:

CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventKeyUp),&keyUpCallback,NULL);

У меня все еще есть проблема: клавиши-модификаторы не запускают kCGEventKeyUp ...

ОБНОВЛЕНИЕ 4:

Хорошо, забудь об этом еще раз ... Я обязательно отвечу на свои вопросы через 5 минут после того, как задаю их сегодня, да!

Чтобы перехватить клавиши-модификаторы, используйтеkCGEventFlagsChanged:

CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventFlagsChanged),&callbackFunction,NULL);

Итак, по сути, я получил определение состояния ключа и ключа модификатора, ноЯ все еще заинтересован в знанииПочему kEventRawKeyUp не работает...

Н.Б .: Также обратите внимание, что я работаю на Tiger с целью как можно большей поддержки новых и старых версий ОС. CGEventTap - только 10.4+, поэтому я буду использовать это сейчас, но было бы желательно использовать обратно совместимое решение.

Ответы на вопрос(2)

Ваш ответ на вопрос