Использование событий мыши и трекпада OSX с помощью события - PullRequest
6 голосов
/ 23 декабря 2010

Я пытаюсь добавить ловушку событий, чтобы включить / отключить событие с моего волшебного трекпада.Я думал, что это будет прямо вперед, то есть зарегистрировать ловушку события и, при необходимости, отменить событие, возвращая NULL.Идея состоит в том, чтобы использовать панель для какого-то конкретного, трудоемкого ввода данных, приложения для ввода данных являются сторонними, поэтому я не могу просто добавить код, который я хочу, там, где я хочу.Поэтому я решил, что я буду отслеживать системные события, а затем отправлять желаемые данные через группу CGEventCreateKeyboardEvent s.

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

Мой код указан ниже.С тем, что ниже, я ожидал бы, что не смогу двигать мышь, если я изменю (A) на kCGEventScrollWheel или kCGEventLeftMouseDragged, тогда событие сработает, т.е. прокрутка или перетаскивание влево не произойдет.Значит ли это, что не все события могут быть отброшены?Надеюсь, я просто упускаю что-то очевидное здесь

  #define case_print(a) case a: printf("%s - %d\n",#a,a); break;


  CGEventRef eventOccurred(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void* refcon) {
    int subType =  CGEventGetIntegerValueField(event, kCGMouseEventSubtype);
    if (type == NSEventTypeGesture || subType == NX_SUBTYPE_MOUSE_TOUCH) {
        printf("touchpad\n");

        switch(type) {
                case_print(kCGEventNull)
                case_print(kCGEventLeftMouseDown)
                case_print(kCGEventLeftMouseUp)
                case_print(kCGEventRightMouseDown)
                case_print(kCGEventRightMouseUp)
                case_print(kCGEventMouseMoved)
                case_print(kCGEventLeftMouseDragged)
                case_print(kCGEventRightMouseDragged)
                case_print(kCGEventScrollWheel)
                case_print(kCGEventOtherMouseDown)
                case_print(kCGEventOtherMouseUp)
                case_print(kCGEventOtherMouseDragged)
                case_print(kCGEventTapDisabledByTimeout)
                case_print(kCGEventTapDisabledByUserInput)
                case_print(NSEventTypeGesture)
                case_print(NSEventTypeMagnify)
                case_print(NSEventTypeSwipe)
                case_print(NSEventTypeRotate)
                case_print(NSEventTypeBeginGesture)
                case_print(NSEventTypeEndGesture)
            default:
                printf("default: %d\n",type);
                break;    
        }

        event = NULL;
    }  else {
        if (type == kCGEventMouseMoved) {  // (A)
            printf("discarding mouse event");
            event = NULL;
        }
    }

    return event;
}


CFMachPortRef createEventTap() {  
    CGEventMask eventMask = NSAnyEventMask;

    if (!AXAPIEnabled() && !AXIsProcessTrusted()) { 
        printf("axapi not enabled");
    } 

    return CGEventTapCreate(kCGHIDEventTap, 
                            kCGHeadInsertEventTap, 
                            kCGEventTapOptionDefault, 
                            eventMask, 
                            eventOccurred, 
                            NULL); 
}

int main (int argc, const char * argv[]) {
    CFMachPortRef tap = createEventTap();

    if (tap) {
        CFRunLoopSourceRef rl = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, tap, 0);
        CFRunLoopAddSource(CFRunLoopGetMain(), rl, kCFRunLoopCommonModes);
        CGEventTapEnable(tap, true);
        CFRunLoopRun();

        printf("Tap created.\n");
        sleep(-1);
    } else {
        printf("failed!\n");
    }

    return 0;
}

Обратите внимание, «axapi not enabled» не выводится, хотя я не думаю, что опция доступности влияет на что-либо, кроме событий клавиатуры.

Кстати, я видел несколько похожих постов о том, как получить события с сенсорной панели, просто ничего не применимо к их удалению (кроме возврата нуля должно работать).

Ответы [ 4 ]

4 голосов
/ 15 апреля 2011

Я думаю, что невозможно просто отбросить эти события. Из заголовочного файла CGEventTypes.h:

"Событие, переданное обратному вызову, удерживается вызывающим кодом и является освобождается после возврата и данные передаются обратно в система событий. Если другое событие возвращается функцией обратного вызова, тогда это событие будет выпущено вызывающий код вместе с исходное событие, после данных события был передан обратно на мероприятие система. "

Я немного поигрался с этим, и кажется, что после обратного вызова, оконный сервер снова активно проверяет, что вы сделали с событием. Он позволяет только удалять ключевые события и события мыши вверх / вниз, но так же, как он игнорирует удаление событий перемещения мыши (я думаю, что рендеринг мыши обрабатывается в другом месте в любом случае), он, кажется, игнорирует удаление (т. Е. Ваш обратный вызов, возвращающий NULL) для жестов мыши.

Цифры, учитывающие касание для жестов, специально не объясняются в документации (на этом уровне не определен тип).

Я попытался вернуть другое событие (нажатие клавиши), и это событие затем обрабатывается дополнительно к исходному жесту. Выпуск события в вашем обратном вызове тоже не делает этого (конечно), просто приводит к исключению.

Единственное, что я не пробовал, - это непосредственно манипулировать внутренними данными переданного CGEvent, чтобы, по крайней мере, заставить жест ничего не делать (удаляя все движения и тому подобное), но это довольно сложно, потому что нет определенных методов, определенных для этого , Я почти уверен, что необходимая информация находится где-то в различных полях, доступных через методы CGEventSet *.

Я посмотрел вниз до IOLLEvent.h, чтобы выяснить их структуру данных, но это было слишком уродливо, чтобы я мог вникнуть гораздо дальше. Будем надеяться, что Lion предложит немного больше о типе событий на уровне CF.

3 голосов
/ 29 апреля 2011

Я могу подтвердить, что на 10.6 ни один из следующих методов не был успешным для этой цели.

1-возвращающий NULL

2 - возвращение нового события мыши с предыдущей позицией курсора

3 - возвращение пройденного события с его kCGMouseEventDelta, измененным на 0

Я не могу говорить о 10.7, но давайте просто скажем, что мои надежды не оправдаются.

Однако есть одна вещь, которую вы могли бы сделать вместо того, чтобы отбросить движение, переместить его обратно в предыдущее местоположение с помощью CGWarpMouseCursorPosition, в результате курсор перестанет двигаться с небольшим изменением первого.

1 голос
/ 24 марта 2012
CGAssociateMouseAndMouseCursorPosition(FALSE);

Запретит работу мыши, когда ваше приложение активно.

Все еще изучаю, могу ли я распространить это на глобальные приложения ...

http://lists.apple.com/archives/quartz-dev/2007/May/msg00112.html

1 голос
/ 19 января 2011

Если ваш тап пассивный, возврат NULL оставит поток событий без изменений. Из справочной документации CGEventTapCallBack :

"Если событие является пассивным слушатель, ваша функция обратного вызова может вернуть событие, которое передано, или НОЛЬ. В любом случае поток событий не затрагивается. "

Тем не менее, похоже, что ваш кран активен. Таким образом, ваше возвращаемое значение NULL должно удалить событие. Рассматривали ли вы изменение события для отмены действия?

Также обратите внимание, что для вызова CGEventTapCreate требуются права пользователя root для перехвата всех событий. Ваш процесс работает как root?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...