Reputation: 63
I am writing a simple Cocoa app that will be launched from AppleScript just to post a Quartz Event to another app.
There is no need for a user interface so I deleted the window from the Interface Builder and the outlet to it from the Application Delegate. I call a private method postClickEvent()
from the method applicationDidFinishLaunching(_:)
. I initialize leftMouseDown
and leftMouseUp
CGEvents with nil mouseEventSource at mouseCursorPosition (x: 0, y: 0)
and post them at location 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)
}
}
I would expect the app as soon as it is launched to click in the top left corner and open the Apple menu but it does not happen.
I can think of several possible solutions.
applicationDidFinishLaunching(_:)
is sent by the default
notification center after the application has been launched and
initialized but before it has received its first event. Maybe
postClickEvent()
should be called from another method of the
Application Delegate?init(stateID:)
for any of the three
possible Event Source State IDs does not change it.Upvotes: 1
Views: 2045
Reputation: 63
Using a sandbox by default is a new feature of Swift Package Manager in 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)
But Quartz Events are incompatible with 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.
Running the app leaves a Sandbox Violation log message in the Console that the app was denied Human Interface Device control.
Disabling App Sandbox in the Xcode target editor allows to post a Quartz Event.
Upvotes: 3