MacOS Quartz Event Tap прослушивание неверных событий - PullRequest
1 голос
/ 05 февраля 2020

Я пытаюсь перехватить события перемещения мыши с помощью метода CGEvent.tapCreate(tap:place:options:eventsOfInterest:callback:userInfo:), как показано ниже:

let cfMachPort = CGEvent.tapCreate(tap: CGEventTapLocation.cghidEventTap, 
                                   place: CGEventTapPlacement.headInsertEventTap, 
                                   options: CGEventTapOptions.defaultTap, 
                                   eventsOfInterest:CGEventMask(CGEventType.mouseMoved.rawValue), 
                                   callback: {(eventTapProxy, eventType, event, mutablePointer) -> Unmanaged<CGEvent>? in event
    print(event.type.rawValue)   //Breakpoint
    return nil
}, userInfo: nil)

let runloopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, cfMachPort!, 0)

let runLoop = RunLoop.current
let cfRunLoop = runLoop.getCFRunLoop()
CFRunLoopAddSource(cfRunLoop, runloopSource, CFRunLoopMode.defaultMode)

Я передаю как тип события eventsOfInterest mouseMoved события с необработанным значением 5 как видно из документации . Но по какой-то причине мой print() не выполняется, пока я не щелкну мышью. Проверка события отправки мыши в отладчике дает мне необработанное значение 2, которое согласно документации является событием leftMouseUp.

В документации для CGEvent.tapCreate(tap:place:options:eventsOfInterest:callback:userInfo:) там написано:

Отводы событий получают события нажатия клавиш «вверх» и «ключ вниз» [...]

Так что кажется, что метод игнорирует mouseMoved события в генеральный?! Но как мне слушать 1025 событий? Я пытаюсь предотвратить замену моего курсора (пользовательского курсора) (например, при наведении курсора на панель приложения в нижней части экрана).

Ответы [ 2 ]

2 голосов
/ 05 февраля 2020

Вам необходимо сдвинуть бит CGEventType значение, используемое для создания параметра CGEventMask. В Objective- C есть макрос для этого: CGEventMaskBit .

Из документации CGEventMask:

для формирования битовой маски используйте макрос CGEventMaskBit для преобразования каждой константы в маску события, а затем ИЛИ отдельные маски вместе

Я не знаю эквивалентного механизма в swift; но сам макрос выглядит так:

*/ #define CGEventMaskBit(eventType) ((CGEventMask)1 << (eventType))

В вашем примере достаточно просто вручную сдвинуть аргумент; например,

eventsOfInterest:CGEventMask(1 << CGEventType.mouseMoved.rawValue),

Я хотел бы отметить, что приведенный в вопросе пример кода немного опасен; поскольку он создает событие по умолчанию, а затем отбрасывает события, а не позволяет их обрабатывать. Это портит обработку щелчка мышью, и было действительно сложно завершить приложение с помощью мыши. Любой, кто запускает пример, может установить тип касания события на CGEventTapOptions.listenOnly, чтобы предотвратить это.

0 голосов
/ 05 февраля 2020

Вот способ прослушивания mouseMove глобальных событий (протестировано с Xcode 11.2+, macOS 10.15)

// ... say in AppDelegate

var globalObserver: Any!
var localObserver: Any!

func applicationDidFinishLaunching(_ aNotification: Notification) {

    globalObserver = NSEvent.addGlobalMonitorForEvents(matching: .mouseMoved) { event in
        let location = event.locationInWindow
        print("in background: {\(location.x), \(location.y)}")
    }

    localObserver = NSEvent.addLocalMonitorForEvents(matching: .mouseMoved) { event in
        let location = event.locationInWindow
        print("active: {\(location.x), \(location.y)}")
        return event
    }
    ...
...