(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;
}
Другие вопросы по тегам