使用 JXA 获取所有正在运行的全屏应用程序(或空间)的列表

问题描述 投票:0回答:3

考虑到有一些应用程序在全屏模式下运行,我想知道是否有一种方法可以使用 JXA 列出它们。类似于下面的内容,但适用于所有正在运行的全屏应用程序。

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

用例:我正在尝试创建一个 Alfred 工作流程来按名称导航全屏应用程序。

谢谢!

javascript-automation
3个回答
1
投票

给你:

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);
})();

0
投票

下面是上述答案的更详细版本。

#!/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))

0
投票

对于那些现在发现这一点的人来说,自上述以来,JXA 桥中的某些内容可能已经发生了变化,在 Sonoma 版本 14.4.1 (23E224) 上,我需要一个额外的步骤(摘自 https://stackoverflow.com/a/ 35007108/24051718)以避免 CFDictionaryRef 被损坏:

#!/usr/bin/osascript -lJavaScript

ObjC.import('CoreGraphics');
ObjC.bindFunction('CFMakeCollectable', [ 'id', [ 'void *' ] ]);

const windows = ObjC.deepUnwrap(
  $.CFMakeCollectable(
    $.CGWindowListCopyWindowInfo(
      $.kCGWindowListOptionAll,
      $.kCGNullWindowID)));
JSON.stringify(windows, null, 2);

结果

[
  {
    "kCGWindowLayer": 0,
    "kCGWindowMemoryUsage": 2176,
    "kCGWindowSharingState": 0,
    "kCGWindowOwnerPID": 49478,
    "kCGWindowNumber": 16739,
    "kCGWindowOwnerName": "System Settings",
    "kCGWindowStoreType": 1,
    "kCGWindowBounds": {
...
© www.soinside.com 2019 - 2024. All rights reserved.