9

I am trying to write the Python script which prints the title of the active window using python in Mac OS.

Here is my code:

from AppKit import NSWorkspace
active_app_name = NSWorkspace.sharedWorkspace().frontmostApplication().localizedName()
print active_app_name

This code just prints name of the app like Google chrome or firefox, but not title. How to get title of the window?

kenorb
  • 137,499
  • 74
  • 643
  • 694
Bharath
  • 321
  • 1
  • 3
  • 5
  • 1
    Possible duplicate of [Finding the Current Active Window in Mac OS X using Python](https://stackoverflow.com/questions/373020/finding-the-current-active-window-in-mac-os-x-using-python) – kenorb May 28 '17 at 13:40

3 Answers3

8

Here is what I used to find both the active application name and window title on Mac OS X using Python by using Quartz API.

First of all, we need to add imports as required:

if sys.platform == "darwin":
    import applescript
    from AppKit import NSWorkspace
    from Quartz import (
        CGWindowListCopyWindowInfo,
        kCGWindowListOptionOnScreenOnly,
        kCGNullWindowID
    )

And then we can get the active app name and window title via the code below:

def getActiveInfo(event_window_num):
    try:
        if sys.platform == "darwin":
            app = NSWorkspace.sharedWorkspace().frontmostApplication()
            active_app_name = app.localizedName()

            options = kCGWindowListOptionOnScreenOnly
            windowList = CGWindowListCopyWindowInfo(options, kCGNullWindowID)
            windowTitle = 'Unknown'
            for window in windowList:
                windowNumber = window['kCGWindowNumber']
                ownerName = window['kCGWindowOwnerName']
                # geometry = window['kCGWindowBounds']
                windowTitle = window.get('kCGWindowName', u'Unknown')
                if windowTitle and (
                                event_window_num == windowNumber
                        or ownerName == active_app_name
                ):
                    # log.debug(
                    #     'ownerName=%s, windowName=%s, x=%s, y=%s, '
                    #     'width=%s, height=%s'
                    #     % (window['kCGWindowOwnerName'],
                    #        window.get('kCGWindowName', u'Unknown'),
                    #        geometry['X'],
                    #        geometry['Y'],
                    #        geometry['Width'],
                    #        geometry['Height']))
                    break

            return _review_active_info(active_app_name, windowTitle)
        if sys.platform == "win32":
            (active_app_name, windowTitle) = _getActiveInfo_Win32()
            return _review_active_info(active_app_name, windowTitle)
    except:
        log.error('Unexpected error: %s' % sys.exc_info()[0])
        log.error('error line number: %s' % sys.exc_traceback.tb_lineno)
    return 'Unknown', 'Unknown'
Jake W
  • 2,699
  • 33
  • 38
  • Could you give a complete shell example? I don't understand what the event_window_num arg is for. Or the _review_active_info(). – Yehosef May 22 '16 at 08:36
  • @Yehosef the event_window_num is from a mouse event or keyboard event captured, I think you can ignore this parameter safely. _review_active_info is also a custom function in my app to just verify app_name and window_title we get, you can also ignore this method. The core part of getting active app_name and window_title is shown in the sample code. – Jake W May 22 '16 at 12:40
  • Unfortunately, I just get an error straight away with `import applescript` : `ImportError: No module named applescript`. – mivk Jan 03 '21 at 10:25
3

There is no access to app title from NSWorkspace.sharedWorkspace().activeApplication().

But you can find the current window title by its PID:

For example:

from AppKit import NSWorkspace
pid = NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationProcessIdentifier']

Then find the right window using below code (it's stored in kCGWindowOwnerPID) as shown in below code:

Here is a complete shell example based on @JakeW's script:

#!/usr/bin/python
# Prints list of windows in the current workspace.
import sys
if sys.platform == "darwin":
    from AppKit import NSWorkspace
    from Quartz import (
        CGWindowListCopyWindowInfo,
        kCGWindowListOptionOnScreenOnly,
        kCGNullWindowID
    )

if sys.platform == "darwin":
    curr_app = NSWorkspace.sharedWorkspace().frontmostApplication()
    curr_pid = NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationProcessIdentifier']
    curr_app_name = curr_app.localizedName()
    options = kCGWindowListOptionOnScreenOnly
    windowList = CGWindowListCopyWindowInfo(options, kCGNullWindowID)
    for window in windowList:
        pid = window['kCGWindowOwnerPID']
        windowNumber = window['kCGWindowNumber']
        ownerName = window['kCGWindowOwnerName']
        geometry = window['kCGWindowBounds']
        windowTitle = window.get('kCGWindowName', u'Unknown')
        if curr_pid == pid:
            print("%s - %s (PID: %d, WID: %d): %s" % (ownerName, windowTitle.encode('ascii','ignore'), pid, windowNumber, geometry))
elif sys.platform == "win32":
    (active_app_name, windowTitle) = _getActiveInfo_Win32()

It will list details of the current active window including its title.

kenorb
  • 137,499
  • 74
  • 643
  • 694
  • This lists all windows of active application, not just the active window. E.g. in chrome open the developer tools on a separate window, you cannot distinguish which is active. – sivann May 31 '17 at 13:32
  • You need to add a break after curr_pid == pid:, and also check for existence of windowTitle – sivann May 31 '17 at 13:52
  • This worked, the higher voted answer by Jake W didn't work. – jason Aug 25 '20 at 05:39
1

As of macOS 10.6 and later it is better to use: frontmostApplication and if you want to get all of the applications listed you can call runningApplications method.

You can see more details at https://developer.apple.com/documentation/appkit/nsworkspace#overview

For example:

from AppKit import NSWorkspace
NSWorkspace.sharedWorkspace().runningApplications() // for getting all applications
NSWorkspace.sharedWorkspace().frontmostApplication() // for active window
Shay Dahan
  • 101
  • 1
  • 3
  • 3
    This answer is written well but doesn't address the OP's question about window title. Could you update your answer with how to get this title? – Samuel Jaeschke Jan 17 '21 at 23:16