27

Is there a way to find the application name of the current active window at a given time on Mac OS X using Python?

Jason Coco
  • 77,985
  • 20
  • 184
  • 180
Moiz
  • 305
  • 1
  • 4
  • 8
  • Does this answer your question? [Obtain Active window using Python](https://stackoverflow.com/questions/10266281/obtain-active-window-using-python) – user202729 Jun 03 '23 at 02:54

4 Answers4

30

This should work:

#!/usr/bin/python

from AppKit import NSWorkspace
activeAppName = NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationName']
print activeAppName

Only works on Leopard, or on Tiger if you have PyObjC installed and happen to point at the right python binary in line one (not the case if you've installed universal MacPython, which you'd probably want to do on Tiger). But Peter's answer with the Carbon way of doing this will probably be quite a bit faster, since importing anything from AppKit in Python takes a while, or more accurately, importing something from AppKit for the first time in a Python process takes a while.

If you need this inside a PyObjC app, what I describe will work great and fast, since you only experience the lag of importing AppKit once. If you need this to work as a command-line tool, you'll notice the performance hit. If that's relevant to you, you're probably better off building a 10 line Foundation command line tool in Xcode using Peter's code as a starting point.

Dirk Stoop
  • 3,080
  • 21
  • 18
21

The method in the accepted answer was deprecated in OS X 10.7+. The current recommended version would be the following:

from AppKit import NSWorkspace
active_app_name = NSWorkspace.sharedWorkspace().frontmostApplication().localizedName()
print(active_app_name)
kenorb
  • 155,785
  • 88
  • 678
  • 743
  • 1
    This really helps! How can we get the active window title? – Jake W Jan 16 '15 at 07:10
  • I know it's possible to do it using AppleScript (calling it through osascript in Python), but up to my knowledge, there's no straightforward way to do it in Python. Here's a link to check the information you can retrieve using Cocoa: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSWorkspace_Class/index.html#//apple_ref/occ/instm/NSWorkspace/frontmostApplication –  Jan 17 '15 at 13:49
  • Originally we used AppleScript to get the current window title, which worked perfectly. But it didn't work if we signed the app. And then I found a native API in Quartz to do it, and that resolved our problem. – Jake W Jan 18 '15 at 01:48
  • 1
    For some reason this always gave me the name of my terminal. The accepted answer got it right. I'm running OS X 10.10. – erb Mar 05 '15 at 09:44
  • @JakeW - could you share how you did it? what's the api? – Yehosef May 20 '16 at 00:31
  • @Yehosef I've added a new answer so that it can display the sample code in a better format. I hope it would be helpful to you. – Jake W May 20 '16 at 02:23
  • @JakeW - thanks! But where's the answer? I don't see it. – Yehosef May 21 '16 at 22:35
  • 1
    @Yehosef As suggested by reviewers, I added the answer to this question: http://stackoverflow.com/questions/28815863/how-to-get-active-window-title-using-python-in-mac-os/37368813#37368813, which is more relevant. Basically the way to get app name is the same, the native part I found is for getting window title using Quartz. – Jake W May 21 '16 at 22:58
7

First off, do you want the window or the application name? This isn't Windows—an application process on Mac OS X can have multiple windows. (Furthermore, this has also been true of Windows for a few years now, although I have no idea what the API looks like for that.)

Second, Carbon or Cocoa?

To get the active window in Cocoa:

window = NSApp.mainWindow()

To get the name of your process in Cocoa:

appName = NSProcessInfo.processInfo().processName()

Edit: Oh, I think I know what you want. The name of the frontmost process, right?

I don't think there's a way to do it in Cocoa, but here's how to do it in Carbon in C:

ProcessSerialNumber psn = { 0L, 0L };
OSStatus err = GetFrontProcess(&psn);
/*error check*/

CFStringRef processName = NULL;
err = CopyProcessName(&psn, &processName);
/*error check*/

Remember to CFRelease(processName) when you're done with it.

I'm not sure what that will look like in Python, or if it's even possible. Python doesn't have pointers, which makes that tricky.

I know PyObjC would translate the latter argument to CopyProcessName into err, processName = CopyProcessName(…), but the Carbon bindings don't rely on PyObjC (they're part of core Python 2), and I'm not sure what you do about the PSN either way.

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
2

I needed the current frontmost application in a Python script that arranges the windows nicely on my screen (see move_window).

Of course, the complete credit goes to Peter! But here is the complete program:

#include <Carbon/Carbon.h>

int main(int, char) {
    ProcessSerialNumber psn = { 0L, 0L };
    OSStatus err = GetFrontProcess(&psn);

    CFStringRef processName = NULL;
    err = CopyProcessName(&psn, &processName);
    printf("%s\n", CFStringGetCStringPtr(processName, NULL));
    CFRelease(processName);
}

Build with gcc -framework Carbon filename.c

kenorb
  • 155,785
  • 88
  • 678
  • 743
SirVer
  • 1,397
  • 1
  • 16
  • 15
  • 2
    How is this an answer for python? – GreenAsJade Jan 26 '14 at 21:56
  • Also not for Python, but for the new Yosemite JavaScript automation you can use `$.NSWorkspace.sharedWorkspace.activeApplication.objectForKey('NSApplicationName').UTF8String;`. You need to import this first though: `ObjC.import('AppKit')`. – SirVer Feb 15 '15 at 08:49
  • 1
    As of now, 'CopyProcessName' has been explicitly marked deprecated. – Isilmë O. Apr 19 '18 at 17:42