Как отслеживать состояние ключа глобального модификатора (в любом приложении)?
Я использую код 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+, поэтому я буду использовать это сейчас, но было бы желательно использовать обратно совместимое решение.