是否可以在 macOS 应用程序中观察模拟(非物理)键盘/鼠标事件?
我编写了不同的代码来模拟键盘按钮按下。
1 示例:斯威夫特
let keyDownEvent = CGEvent(keyboardEventSource: CGEventSource(stateID: CGEventSourceStateID.hidSystemState), virtualKey: virtualKey, keyDown: true)
keyDownEvent?.post(tap: CGEventTapLocation.cghidEventTap)
2 示例:Obj-c / C++
-(void)HIDPostAuxKey:(const UInt8)auxKeyCode {
__block NXEventData event;
__block kern_return_t kr;
__block IOGPoint loc = { 0, 0 };
// Key press event
__block UInt32 evtInfo = auxKeyCode << 16 | NX_KEYDOWN << 8;
bzero(&event, sizeof(NXEventData));
event.key.origCharSet = event.key.charSet = NX_ASCIISET;
event.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS;
event.compound.misc.L[0] = evtInfo;
// event.key.repeat = true;
kr = IOHIDPostEvent( get_event_driver(), NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE );
assert( KERN_SUCCESS == kr );
// Key release event
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 100);
dispatch_after(delay, dispatch_get_main_queue(), ^(void){
evtInfo = auxKeyCode << 16 | NX_KEYUP << 8;
bzero(&event, sizeof(NXEventData));
event.key.origCharSet = event.key.charSet = NX_ASCIISET;
event.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS;
event.compound.misc.L[0] = evtInfo;
kr = IOHIDPostEvent( get_event_driver(), NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE );
assert( KERN_SUCCESS == kr );
}); }
由于 Apple 删除了处理键盘按下的访问权限,因此如果 macOS 应用程序在后台,则没有在设置中启用可访问性,例如这样的 api:
NSEvent.addGlobalMonitorForEvents(matching: [.keyDown, .keyUp]) { (event) in
debugPrint("any key button tapped")
}
现在不起作用。
我发现唯一可行的解决方案是 IOKit,低级 api https://stackoverflow.com/a/39834889/7141905,即使没有启用应用程序的可访问性,它也会监听键盘/鼠标事件。
但是这两种方法都不能观察/捕捉模拟键盘按下。它只能观察来自用户输入的物理事件。Carbon Framework 也不适合我的情况。
有关可访问性要求的更多信息:https ://github.com/KonsomeJona/OctoMouse#why-is-the-keystrokes-counter-not-working