From all the API documentation I can find, it seems that the right thing to do is to check the "frontmost" window as returned by System Events or the accessibility API, like so (example in Python here, but this is the same in ObjC or swift or ruby or whatever):
#!/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())
The value I get back from this is the same as from NSWorkspace.sharedWorkspace().frontmostApplication()
. And it's usually correct. Except when a prompt dialog, especially one from the system, is actually what has the keyboard focus. For example, if Messages.app wants a password to my Jabber account, or if my iCloud password changes; these dialogs appear to be coming from the UserNotificationCenter
process, which does not report itself as the frontmost application somehow, even though it definitely has keyboard focus.
"UserNotificationCenter" and "UserNotificationCenter" are background applications (the NSUIElement
key is 1 in the info.plist).
proc.frontmost()
is always false on process which is in background (no menu and not in the Dock).
And NSWorkspace.sharedWorkspace().frontmostApplication()
doesn't work on background application.
To get the active application, use the activeApplication
method from the NSWorkspace
class
Here's the 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
Update with a not deprecated method:
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
To get the front window from a process ID, use the procID
variable, like this:
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