app.window - 窗口管理 API

列出、查询、移动、调整大小及控制 macOS 应用窗口。

权限: L2 敏感级,需要系统辅助功能(Accessibility)权限。首次调用时系统会提示授权。

方法

app.window.list(opts?)

获取所有可见窗口列表。

参数:

  • opts (table, 可选):
    • app (string) - 按应用名称过滤(支持部分匹配)

返回值: array<table> - 每项包含:

  • title (string) - 窗口标题
  • app (string) - 应用名称
  • bundleId (string) - 应用 Bundle ID
  • pid (number) - 进程 ID
  • x (number) - 窗口左上角 X 坐标(点)
  • y (number) - 窗口左上角 Y 坐标(点)
  • width (number) - 窗口宽度(点)
  • height (number) - 窗口高度(点)
  • isMinimized (boolean) - 是否已最小化
  • isFullscreen (boolean) - 是否全屏
-- 获取所有窗口
local windows = app.window.list()
for _, w in ipairs(windows) do
    app.log.info(w.app .. ": " .. w.title)
end

-- 仅获取 Safari 的窗口
local safariWindows = app.window.list({app = "Safari"})

app.window.focused()

获取当前聚焦(最前端)的窗口。

返回值: table|nil - 窗口信息(字段同 list() 返回项),无焦点窗口时返回 nil

local win = app.window.focused()
if win then
    app.log.info("当前窗口: " .. win.title .. " (" .. win.app .. ")")
end

app.window.move(window, x, y)

移动窗口到指定位置。

参数:

  • window - 窗口标识,支持以下三种形式:
    • {app = "Safari", title = "窗口标题"} - 按应用名和标题匹配
    • {pid = 1234, title = "窗口标题"} - 按进程 ID 和标题匹配
    • "窗口标题" - 仅按标题匹配(取第一个匹配项)
  • x (number) - 目标 X 坐标(点)
  • y (number) - 目标 Y 坐标(点)

返回值: boolean, error

local ok, err = app.window.move({app = "Safari"}, 0, 0)
if not ok then
    app.log.error("移动失败: " .. (err or ""))
end

-- 使用进程 ID
app.window.move({pid = 1234, title = "index.html"}, 100, 100)

-- 仅按标题匹配
app.window.move("Untitled", 200, 200)

app.window.resize(window, w, h)

调整窗口大小。

参数:

  • window - 窗口标识(同 move()
  • w (number) - 目标宽度(点)
  • h (number) - 目标高度(点)

返回值: boolean, error

local ok, err = app.window.resize({app = "Finder"}, 800, 600)

app.window.setFrame(window, x, y, w, h)

同时设置窗口位置和大小。

参数:

  • window - 窗口标识(同 move()
  • x (number) - X 坐标
  • y (number) - Y 坐标
  • w (number) - 宽度
  • h (number) - 高度

返回值: boolean, error

-- 将 Safari 设为左半屏
local screen = app.screen.mainScreen()
local ok, err = app.window.setFrame(
    {app = "Safari"},
    0, 0,
    screen.width / 2, screen.height
)

app.window.minimize(window)

最小化窗口。

参数:

  • window - 窗口标识(同 move()

返回值: boolean, error

app.window.minimize({app = "Safari"})

app.window.maximize(window)

最大化窗口(缩放到填充屏幕可用区域)。

参数:

  • window - 窗口标识(同 move()

返回值: boolean, error

app.window.maximize({app = "Safari"})

app.window.close(window)

关闭窗口。

参数:

  • window - 窗口标识(同 move()

返回值: boolean, error

app.window.close({app = "TextEdit", title = "Untitled"})

app.window.focus(window)

将窗口置于最前并聚焦。

参数:

  • window - 窗口标识(同 move()

返回值: boolean, error

app.window.focus({app = "Finder"})

AX 元素(1.3.0)

app.window.element.* 子模块暴露辅助功能元素树,可用于读取控件状态、定位按钮/输入框、模拟点击与写入。所有函数共用 window 权限和辅助功能授权。

元素句柄(handle)形如 {__ax_element_id, __type = "AXElement", role, title, identifier, value, children},Lua 侧当作普通 table 读取即可,但必须原封不动地传给 click/value/setValue

app.window.element.tree(window, opts?)

递归读取窗口下的 AX 元素树(since 1.3.0)。

参数:

  • window - 窗口描述(同 app.window.move()
  • opts (table, 可选)
    • maxDepth (number) - 递归深度(默认 10)
    • maxChildren (number) - 每层子元素上限(默认 200)

返回值: handle - 根节点,包含 children 嵌套数组

local tree = app.window.element.tree({app = "Calculator"})
for _, btn in ipairs(tree.children) do
    app.log.info(btn.role .. " / " .. btn.title)
end

app.window.element.find(window, filter)

按条件在元素树中搜索,返回匹配的句柄数组(since 1.3.0)。

参数:

  • window - 窗口描述
  • filter (table)
    • role (string, 可选) - 精确匹配 AXRole(如 "AXButton"
    • title (string, 可选) - title 包含指定子串(不区分大小写)
    • identifier (string, 可选) - 精确匹配 AXIdentifier
    • limit (number, 可选) - 最多返回项数(默认 50)
    • maxDepth (number, 可选) - 搜索深度(默认 15)

返回值: array<handle>, err

local buttons = app.window.element.find({app = "Calculator"}, {
    role = "AXButton", title = "1"
})

app.window.element.click(handle)

触发元素的 AXPress 动作(since 1.3.0)。

local ok = app.window.element.click(buttons[1])

app.window.element.value(handle)

读取元素的 AXValue(since 1.3.0)。CGPoint/CGSize/CGRect/CFRange 会被转换成 table;其它保持字符串或数字。

local v = app.window.element.value(handle)

app.window.element.setValue(handle, value)

设置元素的 AXValue(since 1.3.0)。主要用于输入框、滑块等可写控件。

app.window.element.setValue(inputField, "hello")

说明

  • 所有窗口操作均需要系统辅助功能权限,可在「系统设置 → 隐私与安全性 → 辅助功能」中授权
  • 窗口标识中 title 支持部分匹配;若多个窗口匹配,操作第一个匹配项
  • maximize() 等同于双击标题栏的缩放按钮,不同于全屏模式
  • 坐标系以主显示器左上角为原点,向右向下为正方向(点单位,非像素)
  • 最小化的窗口无法通过 move()/resize() 操作,需先调用 focus() 恢复

示例

整理窗口布局

function MyPlugin:handleOrganizeWindows(context)
    local screen = app.screen.mainScreen()
    local w = screen.width / 2
    local h = screen.height

    -- Safari 放左半屏
    app.window.setFrame({app = "Safari"}, 0, 0, w, h)

    -- VS Code 放右半屏
    app.window.setFrame({app = "Code"}, w, 0, w, h)

    app.notification.show("窗口整理完成", "左: Safari,右: VS Code")
end

列出所有窗口信息

function MyPlugin:handleListWindows(context)
    local windows = app.window.list()

    local lines = {}
    for _, win in ipairs(windows) do
        local size = string.format("%dx%d @ (%d,%d)", win.width, win.height, win.x, win.y)
        table.insert(lines, string.format("[%s] %s — %s", win.app, win.title, size))
    end

    local result = table.concat(lines, "\n")
    app.dialog.alert("当前窗口 (" .. #windows .. ")", result)
end
开发者文档
使用帮助
使用说明 脚本菜单 常见问题
脚本开发
开发指南
插件开发
快速开始 开发指南 示例插件
API 参考
概览 API 查询 插件信息 日志 Finder 上下文 插件设置 国际化
UI 与交互
对话框 进度条 系统通知 选择器 WebView 状态栏 Dock
文件与路径
文件操作 路径工具 Finder 操作 废纸篓 扩展属性 元数据 文件监听
数据格式
JSON Plist CSV XML PDF 图片
文本与编码
字符串 正则表达式 日期时间 颜色 加密编码
系统
Shell 命令 进程管理 应用管理 系统信息 AppleScript 快捷指令
系统信息
网络信息 电源/电池 屏幕/外观 音频控制 蓝牙设备 位置服务
网络
HTTP 请求 WebSocket URL 工具
输入与剪贴板
键盘模拟 鼠标模拟 全局热键 剪贴板 窗口管理
存储
SQLite Keychain UserDefaults
媒体
文字识别 二维码
工具
归档 类型标识 分享 定时器 防休眠 并发/协程