如何在 Swift 应用程序启动后 post 一个 Quartz 事件?
How to post a Quartz Event after Swift application launch?
我正在编写一个简单的 Cocoa 应用程序,它将从 AppleScript 启动,只是为了 post 一个 Quartz Event 到另一个应用程序。
不需要用户界面,所以我从 Interface Builder 中删除了 window,并从 Application Delegate 中删除了它的出口。我从方法 applicationDidFinishLaunching(_:)
调用私有方法 postClickEvent()
。我在 mouseCursorPosition (x: 0, y: 0)
处使用 nil mouseEventSource 初始化 leftMouseDown
和 leftMouseUp
CGEvent,在 cghidEventTap
.
处使用 post 它们
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
postClickEvent()
}
func applicationWillTerminate(_ aNotification: Notification) {
}
private func postClickEvent() {
let point = CGPoint(x: 0, y: 0)
let leftMouseDownEvent = CGEvent(mouseEventSource: nil, mouseType: .leftMouseDown, mouseCursorPosition: point, mouseButton: .left)
let leftMouseUpEvent = CGEvent(mouseEventSource: nil, mouseType: .leftMouseUp, mouseCursorPosition: point, mouseButton: .left)
leftMouseDownEvent?.post(tap: .cghidEventTap)
leftMouseUpEvent?.post(tap: .cghidEventTap)
}
}
我希望应用程序在启动后立即单击左上角并打开 Apple 菜单,但它并没有发生。
我可以想到几种可能的解决方案。
- 在调试器中运行的应用程序可能需要 post
低级用户输入事件。应用程序是否需要 post 的权限
石英事件?
- 方法
applicationDidFinishLaunching(_:)
默认发送
应用程序启动后的通知中心和
初始化但在它收到第一个事件之前。也许
postClickEvent()
应该从另一个方法调用
申请代表?
- 事件在初始化时可能需要事件源。但路过
事件源用
init(stateID:)
为三个中的任何一个初始化
可能的事件源状态 ID 不会改变它。
- 事件可以在应用程序在全屏后获得焦点时 post 编辑 Xcode 所以点击 Apple 菜单项还为时过早。但是让线程休眠 10 秒不会改变它。
默认使用沙箱是 Swift Package Manager 在 Xcode 9.0 中的一项新功能。
Updated package manifest interpretation and package builds on macOS to use a sandbox, which prevents network access and file system modification. This helps mitigate the effect of maliciously crafted manifests. (31107213)
但是 Quartz Events 与 App Sandbox 不兼容。
You cannot sandbox an app that controls another app. Posting keyboard or mouse events using functions like CGEventPost offers a way to circumvent this restriction, and is therefore not allowed from a sandboxed app.
运行 该应用在控制台中留下沙盒违规日志消息,表明该应用被拒绝了人机界面设备控制。
Console
在 Xcode 目标编辑器中禁用 App Sandbox 允许 post Quartz 事件。
Xcode
我正在编写一个简单的 Cocoa 应用程序,它将从 AppleScript 启动,只是为了 post 一个 Quartz Event 到另一个应用程序。
不需要用户界面,所以我从 Interface Builder 中删除了 window,并从 Application Delegate 中删除了它的出口。我从方法 applicationDidFinishLaunching(_:)
调用私有方法 postClickEvent()
。我在 mouseCursorPosition (x: 0, y: 0)
处使用 nil mouseEventSource 初始化 leftMouseDown
和 leftMouseUp
CGEvent,在 cghidEventTap
.
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
postClickEvent()
}
func applicationWillTerminate(_ aNotification: Notification) {
}
private func postClickEvent() {
let point = CGPoint(x: 0, y: 0)
let leftMouseDownEvent = CGEvent(mouseEventSource: nil, mouseType: .leftMouseDown, mouseCursorPosition: point, mouseButton: .left)
let leftMouseUpEvent = CGEvent(mouseEventSource: nil, mouseType: .leftMouseUp, mouseCursorPosition: point, mouseButton: .left)
leftMouseDownEvent?.post(tap: .cghidEventTap)
leftMouseUpEvent?.post(tap: .cghidEventTap)
}
}
我希望应用程序在启动后立即单击左上角并打开 Apple 菜单,但它并没有发生。
我可以想到几种可能的解决方案。
- 在调试器中运行的应用程序可能需要 post 低级用户输入事件。应用程序是否需要 post 的权限 石英事件?
- 方法
applicationDidFinishLaunching(_:)
默认发送 应用程序启动后的通知中心和 初始化但在它收到第一个事件之前。也许postClickEvent()
应该从另一个方法调用 申请代表? - 事件在初始化时可能需要事件源。但路过
事件源用
init(stateID:)
为三个中的任何一个初始化 可能的事件源状态 ID 不会改变它。 - 事件可以在应用程序在全屏后获得焦点时 post 编辑 Xcode 所以点击 Apple 菜单项还为时过早。但是让线程休眠 10 秒不会改变它。
默认使用沙箱是 Swift Package Manager 在 Xcode 9.0 中的一项新功能。
Updated package manifest interpretation and package builds on macOS to use a sandbox, which prevents network access and file system modification. This helps mitigate the effect of maliciously crafted manifests. (31107213)
但是 Quartz Events 与 App Sandbox 不兼容。
You cannot sandbox an app that controls another app. Posting keyboard or mouse events using functions like CGEventPost offers a way to circumvent this restriction, and is therefore not allowed from a sandboxed app.
运行 该应用在控制台中留下沙盒违规日志消息,表明该应用被拒绝了人机界面设备控制。
Console
在 Xcode 目标编辑器中禁用 App Sandbox 允许 post Quartz 事件。
Xcode