如何使用ScriptingBridge(或AppleScript)确定具有活动键盘焦点的窗口



从我能找到的所有API文档中,似乎正确的做法是检查System Events返回的"最前面"窗口或API的可访问性,就像这样(这里是Python中的示例,但这在ObjC或swift或ruby中是相同的):

#!/usr/bin/env python
from ScriptingBridge import SBApplication
events = SBApplication.applicationWithBundleIdentifier_(
    "com.apple.systemevents")
for proc in events.applicationProcesses():
    if proc.frontmost():
        print(proc.name())

我从中得到的值与从NSWorkspace.sharedWorkspace().frontmostApplication()得到的值相同。它通常是正确的。除非提示对话框,尤其是来自系统的对话框,实际上是键盘焦点所在的。例如,如果Messages.app想要我的Jabber帐户的密码,或者如果我的iCloud密码更改;这些对话框似乎来自UserNotificationCenter进程,它并没有以某种方式报告自己是最前端的应用程序,尽管它确实有键盘焦点。

"UserNotificationCenter"one_answers"UserNotificationCenter"是后台应用程序(info.plist中的NSUIElement键为1)。

proc.frontmost()在后台进程中始终为false(无菜单且不在Dock中)。

NSWorkspace.sharedWorkspace().frontmostApplication()不适用于后台应用程序。


要获得活动应用程序,请使用NSWorkspace类中的activeApplication方法

这是AppleScript:

set pyScript to "from AppKit import NSWorkspace
activeApp = NSWorkspace.sharedWorkspace().activeApplication()
print activeApp['NSApplicationName'].encode('utf-8')
print activeApp['NSApplicationProcessIdentifier']"
set r to do shell script "/usr/bin/python -c " & quoted form of pyScript
set {localizedAppName, procID} to paragraphs of r -- procID is the unix id

使用不推荐使用的方法更新

set pyScript to "from AppKit import NSWorkspace
for app in NSWorkspace.sharedWorkspace().runningApplications():
        if app.isActive(): 
                print app.localizedName().encode('utf-8')
                print app.processIdentifier()
                break"
set r to do shell script "/usr/bin/python -c " & quoted form of pyScript
set {localizedAppName, procID} to paragraphs of r -- procID is the unix id

要从进程ID获取前窗口,请使用procID变量,如下所示:

tell application "System Events"
    tell (first process whose unix id = procID)
        log (get properties) -- properties of this process
        tell window 1 to if exists then log (get properties) -- properties of the front window of this process
    end tell
end tell

最新更新