如何使用 ScriptingBridge(或 AppleScript)确定具有活动键盘焦点的 window?
How do I determine the window with the active keyboard focus using ScriptingBridge (or AppleScript)?
从我能找到的所有 API 文档中,似乎正确的做法是检查系统事件返回的 "frontmost" window 或可访问性 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" 和 "UserNotificationCenter" 是后台应用程序(NSUIElement
键在 info.plist).
proc.frontmost()
在后台进程(无菜单且不在 Dock 中)上始终为 false。
并且 NSWorkspace.sharedWorkspace().frontmostApplication()
不适用于后台应用程序。
要获取活动应用程序,请使用 NSWorkspace
class
中的 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 中获取前面的 window,请使用 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
从我能找到的所有 API 文档中,似乎正确的做法是检查系统事件返回的 "frontmost" window 或可访问性 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" 和 "UserNotificationCenter" 是后台应用程序(NSUIElement
键在 info.plist).
proc.frontmost()
在后台进程(无菜单且不在 Dock 中)上始终为 false。
并且 NSWorkspace.sharedWorkspace().frontmostApplication()
不适用于后台应用程序。
要获取活动应用程序,请使用 NSWorkspace
class
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 中获取前面的 window,请使用 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