Как определить разницу между событием с нажатой клавиатурой и сгенерированным?
Я установил клавиатуру крюк:
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