Как определить разницу между событием с нажатой клавиатурой и сгенерированным?

Я установил клавиатуру крюк:

CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {

По сути, я хочу взять нажатие клавиш на клавиатуре пользователя, съесть ввод и вместо этого опубликовать свой собственный ввод.

Так что, если он нажмет "g", я могу добавить "foo" в текстовое поле.

Я пишу в текстовое поле с CGEventPost а также CGEventSetUnicodeString как найдено здесь: http://www.mail-archive.com/cocoa-dev@lists.apple.com/msg23343.html

Проблема в том, что каждый из моих программно введенных символов попадает в зацепку клавиатуры. Так я не могу return NULL в хуке клавиатуры, чтобы заблокировать пользовательский ввод... который также блокирует весь ввод программы!

Я дифференцировал их на стороне Windows в C# с помощью флага "injected", см. Мой вопрос год назад здесь: как использовать низкоуровневые 8-битные флаги в качестве условных выражений?

Ищете что-то похожее в Objective-C.

1 ответ

Решение

Посмотрите на комментарии в CGEventSource.h. Немного проще собрать информацию вместе, чем использовать справочник по службам событий. Длинный, но более правильный путь выглядит как создание источника событий (который подчиняется правилам управления памятью; вам нужно CFRelease это, если вы закончили использовать его до завершения программы):

myEventSource = CGEventSourceCreate(kCGEventSourceStatePrivate);

Это создаст ваш собственный источник событий с уникальным идентификатором; Затем вы указываете, что события, которые вы создаете, пришли оттуда:

CGEventRef myKeyboardEvent = CGEventCreateKeyboardEvent(myEventSource, 
                                                        keyCode, true);

Когда приходит событие, проверьте, не от вас ли оно:

 if( (CGEventGetType(newEvent) == kCGEventKeyDown) &&
     (CGEventGetIntegerValueField(newEvent, kCGEventSourceStateID) == CGEventSourceGetSourceStateID(myEventSource) ) {

Есть также поле пользовательских данных для источника, которое позволяет вам передавать произвольные 64 бита, если вам нужно.

Быстрый и грязный способ - попытаться выбрать поле события, которое вряд ли будет значимым значением для события клавиатуры, например kCGMouseEventPressure и превратить это в подпись:

CGEventSetIntegerValueField(myKeyboardEvent, 
                            kCGMouseEventPressure, 
                            0xFEEDFACE);
// The field is an int_64 so you could make the sig longer
Другие вопросы по тегам