首页 > 解决方案 > MacOS Quartz Event Tap 监听错误事件

问题描述

我正在尝试使用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 的事件类型事件作为事件类型传递。但由于某种原因,除非我用鼠标单击,否则 my 不会执行。在调试器中检查发送鼠标事件会给我一个原始值 2,根据文档,这是一个事件。print()leftMouseUp

在它的文档CGEvent.tapCreate(tap:place:options:eventsOfInterest:callback:userInfo:)说:

事件点击接收按键向上和按键向下事件 [...]

所以看起来该方法mouseMoved通常会忽略事件?!但是我应该如何收听mouseMoved事件呢?我试图阻止我的光标(自定义光标)被替换(例如,当我将鼠标悬停在屏幕底部的应用程序坞上时)。

标签: swiftmacoscore-graphics

解决方案


您需要对CGEventType用于创建CGEventMask参数的值进行位移。在 Objective-C 中,有一个宏可以做到这一点:CGEventMaskBit

CGEventMask文档中:

要形成位掩码,请使用 CGEventMaskBit 宏将每个常量转换为事件掩码,然后将各个掩码 OR 在一起

我不知道 swift 中的等效机制;但宏本身看起来像这样:

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

在您的示例中,只需手动移动参数就足够了;例如

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

我要指出,问题中给出的代码示例有点危险;因为它创建了一个默认事件点击,然后删除事件而不是允许它们被处理。这会打乱鼠标单击处理,并且使用鼠标实际终止应用程序很棘手。运行该示例的任何人都可以将事件点击类型设置为CGEventTapOptions.listenOnly以防止这种情况发生。


推荐阅读