首页 文章

如何在Swift应用程序启动后发布Quartz事件?

提问于
浏览
0

我正在编写一个简单的Cocoa应用程序,它将从AppleScript启动,只是为了将Quartz事件发布到另一个应用程序 .

不需要用户界面,因此我从Interface Builder中删除了窗口,并从Application Delegate中删除了它的出口 . 我从方法applicationDidFinishLaunching(_ :)中调用了一个私有方法postClickEvent() . 我使用mouseCursorPosition(x:0,y:0)中的nil mouseEventSource初始化leftMouseDown和leftMouseUp CGEvents,并将它们发布到位置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菜单但不会发生 .

我可以想到几种可能的解决方案 .

  • 在调试器中运行的应用程序可能需要具有发布低级用户输入事件的权限 . 应用是否需要获得发布Quartz事件的权限?

  • 方法applicationDidFinishLaunching(_ :)是在应用程序启动并初始化之后但在收到第一个事件之前由默认通知中心发送的 . 也许应该从Application Delegate的另一个方法调用postClickEvent()?

  • 事件初始化时可能需要事件源 . 但是,对于三个可能的事件源状态ID中的任何一个,使用init(stateID :)初始化的事件源不会更改它 .

  • 事件可以在应用程序在全屏Xcode之后获得焦点时发布,因此太早点击Apple菜单项 . 但是让线程休眠10秒并不会改变它 .

1 回答

  • 0

    默认情况下使用沙箱是Xcode 9.0中Swift Package Manager的一项新功能 .

    在macOS上更新了软件包清单解释和软件包构建,以使用沙箱,防止网络访问和文件系统修改 . 这有助于减轻恶意制作的清单的影响 . (31107213)

    Xcode Release Notes

    但Quartz Events与App Sandbox不兼容 .

    您无法对控制其他应用的应用进行沙盒处理 . 使用CGEventPost等函数发布键盘或鼠标事件提供了一种规避此限制的方法,因此不允许从沙盒应用程序中进行 .

    App Sandbox Design Guide

    运行应用程序会在控制台中留下Sandbox Violation日志消息,表明应用程序被拒绝人工接口设备控制 .

    Console

    在Xcode目标编辑器中禁用App Sandbox允许发布Quartz事件 .

    Xcode

相关问题