CGEventTap接收自定义发送CGEvent时CGEventFlags异常如何解决
问题原因
- 你手动创建
CGEvent时传入的keyboardEventSource为nil,系统会为这类无真实HID设备关联的模拟事件自动添加私有标记位:你看到的537001984换算为十六进制是0x20040000,其中包含系统自动附加的CGEventFlags.maskNonCoalesced(非合并事件标记)、模拟事件专属私有位,这些位是物理按键事件不会携带的。 - 直接给
event.flags赋值只会覆盖你显式指定的修饰键位,系统保留的私有标记位不会被覆盖,依然会被追加到最终的flags数值中,所以和物理按键触发的flags数值不一致。 - 物理按键触发的事件flags除了修饰键位,还会携带HID设备相关的低阶状态位,手动创建的事件默认不会携带这部分内容。
解决方法
提供两种可行方案,按需选择:
方案1:优化模拟事件创建逻辑,尽可能匹配真实事件特征
创建事件时指定和系统硬件事件一致的事件源,避免系统添加多余的私有标记,同时在回调中只过滤业务需要关心的修饰键位,忽略系统私有位即可得到和物理按键一致的输出,修改后的代码如下:
import Cocoa import Carbon func createEventTap() { func callback(proxy: CGEventTapProxy, type: CGEventType, event: CGEvent, refcon: UnsafeMutableRawPointer?) -> Unmanaged<CGEvent>? { // 仅保留业务关心的修饰键位,忽略系统私有标记位 let validFlagMask: CGEventFlags = [.maskShift, .maskControl, .maskAlternate, .maskCommand, .maskAlphaShift] let validFlags = event.flags.intersection(validFlagMask) print(validFlags.rawValue) return Unmanaged.passUnretained(event) } let eventMask = (1 << CGEventType.keyDown.rawValue) let eventTap = CGEvent.tapCreate(tap: .cghidEventTap, place: .tailAppendEventTap, options: .defaultTap , eventsOfInterest: CGEventMask(eventMask), callback: callback, userInfo: nil)! let runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0) CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, .commonModes) CGEvent.tapEnable(tap: eventTap, enable: true) } createEventTap() DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2), execute: { // 指定和系统HID状态一致的事件源,减少系统附加标记 guard let eventSource = CGEventSource(stateID: .hidSystemState) else { return } eventSource.flags = .maskShift let event = CGEvent(keyboardEventSource: eventSource, virtualKey: CGKeyCode(kVK_Space), keyDown: true)! event.post(tap: .cghidEventTap) })
方案2:回调里手动修正模拟事件的flags
如果需要flags数值完全和物理事件一致,可以在生成模拟事件时给事件添加自定义标识,回调里识别到是自身发送的事件后直接修改flags为目标值:
// 发送事件时添加自定义标记 event.setIntegerValueField(.eventSourceUserData, value: 999) // 回调中识别并修正flag if event.getIntegerValueField(.eventSourceUserData) == 999 { event.flags = CGEventFlags(rawValue: 131330) }
内容的提问来源于stack exchange,提问作者Dexter Leng
相关产品推荐
相关产品推荐

