Как определить разницу между событием с нажатой клавиатурой и сгенерированным? - PullRequest
9 голосов
/ 30 апреля 2011

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

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 Ответ

6 голосов
/ 30 апреля 2011

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

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
...