0

Given there are apps running in fullscreen mode, I'm wondering if there's a way to list them using JXA. Something similar to below but for all running fullscreen apps.

var list = Application('System Events').applicationProcesses.where({ backgroundOnly: false }).windows.name();

Use case: I'm trying to create a Alfred workflow to navigate fullscreen apps by name.

Thanks!

Chanaka
  • 954
  • 1
  • 8
  • 17
  • I don't think you can do it using _System Events_, which seems only to be aware of the windows in the current space. To demonstrate this, make a few windows of a few apps fullscreen; switch back to your main desktop, and run: `Applications('com.apple.systemevents').processes.windows.attributes['AXFullScreen'].value();` What version of macOS are you using ? It probably possible to obtain the list using JSObjC, but in versions later than High Sierra, it's pretty broken. – CJK Dec 28 '19 at 04:10

2 Answers2

1

Here you go:

ObjC.import('CoreGraphics');

unwrap = ObjC.deepUnwrap.bind(ObjC);

(function run() {
        const bounds = x => ['X', 'Y', 'Width', 'Height'].map(k => x.kCGWindowBounds[k]);

        const windowInfo = unwrap($.CGWindowListCopyWindowInfo(
                                        $.kCGWindowListOptionAll,
                                        $.kCGNullWindowID)),
              applicationWindows = windowInfo.filter(x => x.kCGWindowLayer==0),
              menubar = windowInfo.filter(x => x.kCGWindowName=='Menubar')[0],
              desktop = windowInfo.filter(x => x.kCGWindowName=='Desktop')[0],
              fullframe = bounds(desktop);

        return applicationWindows.filter(x => {
                return bounds(x).reduce((ξ, y, i) => {
                        return ξ && (y==fullframe[i]);
                }, true);
        }).map(x => x.kCGWindowOwnerName);
})();
CJK
  • 5,732
  • 1
  • 8
  • 26
  • Thank you very much, this approach is not mentioned in other places about JXA. I saw and used your answer some time ago. But didn't find time to reply here. I came up with a solution using your version, I'll post it below. – Chanaka May 16 '20 at 03:13
0

Below is a little bit more verbose version of the above answer.

#!/usr/bin/env osascript -l JavaScript

/**
 * A JXA script to list all the fullscreen windows.
 * Note: In macOS Mojave this method lists all the maximized windows as well.
 * So we don't know which ones are fullscreen.
 */

ObjC.import('CoreGraphics');

const unwrap = ObjC.deepUnwrap.bind(ObjC);
const getBounds = x => ['X', 'Y', 'Width', 'Height'].map(k => x.kCGWindowBounds[k]);

const windowInfo = unwrap($.CGWindowListCopyWindowInfo($.kCGWindowListOptionAll, $.kCGNullWindowID))
const applicationWindows = windowInfo.filter(x => x.kCGWindowLayer === 0 && x.kCGWindowName)
const menubar = windowInfo.filter(x => x.kCGWindowName === 'Menubar')[0]
const desktop = windowInfo.filter(x => x.kCGWindowName === 'Desktop')[0]

const fullFrameSize = getBounds(desktop);
const results = applicationWindows.filter(x => {
  const windowSize = getBounds(x)
  if (JSON.stringify(windowSize) === JSON.stringify(fullFrameSize)) {
    return true
  }
  return false
}).map(x => ({
  app: x.kCGWindowOwnerName,
  pid: x.kCGWindowOwnerPID,
  winTitle: x.kCGWindowName,
  winInfo: x,
}))

console.log("[DEBUG] results =", JSON.stringify(results, null, 2))
Chanaka
  • 954
  • 1
  • 8
  • 17