在 macOS Sierra 中使用 Quartz 事件模拟击键
Posted
技术标签:
【中文标题】在 macOS Sierra 中使用 Quartz 事件模拟击键【英文标题】:Simulate keystrokes with Quartz events in macOS Sierra 【发布时间】:2016-09-22 19:30:55 【问题描述】:我在 macOS 中模拟击键,并将它们发送到活动应用程序。我正在按照https://***.com/a/27487493/5600424 的方式进行操作,但在 Swift 3 中。例如,发送一个“a”:
let eventSource = CGEventSource(stateID: CGEventSourceStateID.hidSystemState)
let key: CGKeyCode = 0 // virtual key for 'a'
let eventDown = CGEvent(keyboardEventSource: eventSource, virtualKey: key, keyDown: true)
let eventUp = CGEvent(keyboardEventSource: eventSource, virtualKey: key, keyDown: false)
let location = CGEventTapLocation.cghidEventTap
eventDown.post(tap: location)
eventUp.post(tap: location)
这在 OSX El Capitan(Swift 3,Xcode 8.0)上运行良好,但在更新到 macOS Sierra 后停止运行。应用程序本身在其处于活动状态时仍会收到击键,但是当另一个应用程序处于活动状态时,事件似乎会丢失。我试图弄清楚发生了什么但没有成功,并且文档没有帮助。任何帮助将不胜感激,谢谢!
【问题讨论】:
您是否尝试过发布到不同的点击位置,例如CGEventTapLocation.cgSessionEventTap
?或者,如果您针对特定应用程序,请使用 postToPSN()
?
嗨@Ken,我不是针对特定应用程序,我希望前台应用程序的活动窗口接收事件(用户正在与之交互的那个)。它按照我在塞拉之前的预期工作。我也试过CGEventTapLocation.cgSessionEventTap
,但行为没有改变:如果我切换到另一个应用程序,这些事件将被忽略。也许正确的方法是使用NSWorkspace.shared().runningApplications.first(where: $0.isActive )
跟踪前台应用程序并使用postToPSN()
?
嗯,使用NSWorkspace.shared().frontmostApplication
会更合适。 ;) 你当然可以试试。也可能是 Sierra 加强了事件发布的安全性,您需要像点击关键事件一样拥有辅助访问权限。
嗨,Ken,事实证明,由于另一个问题,根本没有发送击键。它们的行为仍与升级前相同,无需辅助访问。非常感谢您的帮助!
请不要在您的问题中包含答案。如果您自己解决了问题,您可以发布自己的答案。谢谢。
【参考方案1】:
问题中引用的代码可以正常工作,并且在从 El Capitan 升级到 Sierra 时,其行为没有改变,与声称的相反。
其他应用程序没有收到的击键,因为一旦应用程序在后台,负责发送带有上述代码的键盘事件的函数不再被调用,原因是独立的。
【讨论】:
以上是关于在 macOS Sierra 中使用 Quartz 事件模拟击键的主要内容,如果未能解决你的问题,请参考以下文章
macOS Sierra是啥 macOS Sierra有啥新功能
使用 AppleScript 在 macOS Sierra 中启用 VoiceOver 不起作用
如何在多用户 MacOS Sierra 设置中使用 Homebrew