(OS X) Предотвращение клавиатуры во время программного щелчка мыши
Я пытаюсь перенести keynav на OS X. В основном это работает, но я столкнулся с проблемой из-за невозможности изменить (глобальные) отслеживаемые события.
Можно ли подавить модификатор клавиатуры во время события щелчка мышью? Может быть, использовать последовательность, например, создание события клавиатуры с помощью "клавиши управления вверх" + щелчок мыши?
Это мой метод щелчка мышью:
- (void)clickMouseAtPoint:(CGPoint)point
{
CGEventRef move = CGEventCreateMouseEvent(
NULL, kCGEventMouseMoved,
point,
kCGMouseButtonLeft // ignored
);
CGEventRef click1_down = CGEventCreateMouseEvent(
NULL, kCGEventLeftMouseDown,
point,
kCGMouseButtonLeft
);
CGEventRef click1_up = CGEventCreateMouseEvent(
NULL, kCGEventLeftMouseUp,
point,
kCGMouseButtonLeft
);
CGEventPost(kCGHIDEventTap, move);
CGEventPost(kCGHIDEventTap, click1_down);
CGEventPost(kCGHIDEventTap, click1_up);
CFRelease(click1_up);
CFRelease(click1_down);
CFRelease(move1);
}
1 ответ
Это то, чем я закончил. В частности, предыстория того, что здесь делается: при нажатии ctrl + запятая клавиатура накладывается на весь рабочий стол, пользователь может перемещаться по перекрестию, удерживая клавиши ctrl+SomeKeys, и имитировать щелчок мыши в положении перекрестного удара. second ctrl+ запятая (awaitClick устанавливается, когда в приведенном ниже фрагменте кода ожидается второй щелчок).
Теперь, прежде чем щелкнуть мышью, модификатор управляющей клавиши удаляется из события клавиатуры. Кроме того, в то время как keynav показывается, весь ввод с клавиатуры заменяется кодом клавиши -1. Я нашел это, экспериментируя, что это подавляет нажатие клавиши.
Хорошо это или нет, я не могу сказать. Но это работает надежно до сих пор.
CGEventRef
myCGEventCallback(CGEventTapProxy proxy, CGEventType type,
CGEventRef event, void *refcon)
{
if ((type != kCGEventKeyDown) && (type != kCGEventKeyUp))
return event;
CGKeyCode keycode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);
EWAppDelegate *appInstance = [NSApplication sharedApplication].delegate;
CGEventFlags flags = CGEventGetFlags(event);
if (_awaitClick && keycode == (CGKeyCode)43 && type == kCGEventKeyDown)
{
flags = flags & ~kCGEventFlagMaskControl;
CGEventSetFlags(event, flags);
NSLog(@"suppressed control key");
}
BOOL didHandle = NO;
if (type == kCGEventKeyDown)
{
didHandle = [appInstance handleNavKey:keycode flags:flags];
}
NSLog(@"pressed keycode %d", keycode);
if (didHandle || _navIsSHowing) {
CGEventSetIntegerValueField(event, kCGKeyboardEventKeycode, (int64_t)-1);
NSLog(@"nav");
}
return event;
}
- (BOOL)registerGlobalKeyBoardModifier
{
CFMachPortRef eventTap;
CGEventMask eventMask;
CFRunLoopSourceRef runLoopSource;
eventMask = ((1 << kCGEventKeyDown) | (1 << kCGEventKeyUp));
eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, 0,
eventMask, myCGEventCallback, NULL);
if (!eventTap) {
fprintf(stderr, "failed to create event tap\n");
return NO;
}
runLoopSource = CFMachPortCreateRunLoopSource(
kCFAllocatorDefault, eventTap, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource,
kCFRunLoopCommonModes);
CGEventTapEnable(eventTap, true);
return YES;
}