【问题标题】:How to post a Quartz Event after Swift application launch?Swift 应用程序启动后如何发布 Quartz 事件?
【发布时间】:2018-04-15 15:08:40
【问题描述】:

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

不需要用户界面,因此我从 Interface Builder 中删除了窗口,并从 Application Delegate 中删除了它的出口。我从方法applicationDidFinishLaunching(_:) 中调用了一个私有方法postClickEvent()。我在mouseCursorPosition (x: 0, y: 0) 使用nil mouseEventSource 初始化leftMouseDownleftMouseUp 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 菜单,但它没有发生。

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

  • 在调试器中运行的应用程序可能需要权限才能发布 低级用户输入事件。应用是否需要获得权限才能发布 石英事件?
  • 默认发送applicationDidFinishLaunching(_:)方法 应用程序启动后的通知中心和 初始化但在它收到第一个事件之前。可能是 postClickEvent() 应该从另一个方法调用 申请代表?
  • 事件在初始化时可能需要一个事件源。但是路过 对于这三个中的任何一个,使用 init(stateID:) 初始化的事件源 可能的事件源状态 ID 不会改变它。
  • 可以在应用程序在全屏 Xcode 后获得焦点时发布事件,这样太早了,无法单击 Apple 菜单项。但是让线程休眠 10 秒并不会改变它。

【问题讨论】:

  • 您的代码可以在我的 Mac (macOS 10.12) 上运行。您不能从 AppleScript 发布活动吗?
  • 我的 macOS 版本是 10.13.1。 AppleScript 无法发布拖放事件,因此我想调用 Swift 子例程。您是从标准 macOS Cocoa App 模板的 applicationDidFinishLaunching(_:) 还是从其他地方调用 postClickEvent() ?您是否对应用权限或输入辅助功能设置进行了任何更改?

标签: swift xcode cocoa macos-high-sierra cgeventtap


【解决方案1】:

默认使用沙盒是 Xcode 9.0 中 Swift 包管理器的一项新功能。

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

Xcode Release Notes

但 Quartz Events 与 App Sandbox 不兼容。

您不能对控制另一个应用的应用进行沙盒处理。使用 CGEventPost 之类的函数发布键盘或鼠标事件提供了一种规避此限制的方法,因此不允许在沙盒应用中使用。

App Sandbox Design Guide

运行应用程序会在控制台中留下沙盒违规日志消息,表明应用程序被拒绝人机接口设备控制。

Console

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

Xcode

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-03
    • 2017-03-07
    • 2010-10-18
    • 1970-01-01
    相关资源
    最近更新 更多