Linux 窗口捕获
Linux 窗口捕获¶
仅限 Wayland。每次捕获都会在 LinuxSnapShot.ts 中选择一个后端(Hyprland 辅助程序、Niri IPC、KDE 辅助程序、带活动窗口目标的 Screenshot 门户、GNOME 扩展,然后是 Electron 选择器),并且在失败、取消或拒绝时绝不回退到另一个后端。过期的 NIRI_SOCKET 或可访问的 GNOME 扩展不得导致选择另一个桌面的后端;会话检测来自 linuxCaptureSession.ts 中的 XDG_CURRENT_DESKTOP。
模块边界¶
dbus-next 只能通过动态导入访问。linuxCaptureSession.ts 持有纯辅助函数(会话检测、Niri 绑定文本、门户键位映射、PNG 读取),使主进程能够回答“这是哪个桌面”,而无需在 macOS 或 Windows 上加载 D-Bus 客户端。
patches/dbus-next@0.10.2.patch 移除了 usocket(其可选的原生 Unix-FD 传输),并通过 Node 的 net 连接到 unix:path= 和 unix:abstract= 总线。我们从不传递 Unix 描述符,而 upstream 没有针对抽象套接字的 net 回退,dbus-launch 在 systemd 之外生成的就是这种套接字。升级 dbus-next 时请保留此补丁。
无障碍标识¶
Screenshot 门户返回 PNG URI,而不返回窗口标识,因此门户和选择器的捕获结果不携带无障碍数据。不要从随后获得焦点的窗口或猜测的标题来推断它。
原生后端提供 PID、标题和窗口框架。AT-SPI 匹配依据是 PID 加上唯一的标题和尺寸匹配。AT-SPI 在 Wayland 上会将窗口的屏幕位置报告为 (0, 0),即使合成器知道真实位置,因此只比较宽度和高度;只有当 AT-SPI 根节点与合成器的窗口框架一致,并且至少一个后代报告了不同的位置时,后代坐标才受信任。否则边界为 null,而不是以零为原点的矩形。
标题匹配会忽略单个前导 Braille CLI 旋转帧,因为终端会在捕获与查找之间改变它。KDE 同时提供 frameGeometry 和 clientGeometry;接受任一经过验证的尺寸,绝不要使用装饰高度容差。
在 GNOME 上,浏览器无障碍桥需要在浏览器启动前启用 org.gnome.desktop.interface toolkit-accessibility。捕获期间不要切换它。
KDE¶
KWin 通过对照其应用程序注册表解析调用方 PID 的可执行文件来授权 org.kde.KWin.ScreenShot2,因此辅助程序安装在 XDG 数据主目录下的稳定路径中,并带有隐藏桌面项,而不是从 AppImage 挂载点运行。两个陷阱:
X-KDE-DBUS-Restricted-Interfaces使用 KConfig 的逗号分隔列表语法。尾部加分号会成为接口名称的一部分,KWin 会拒绝它。- KService 的缓存键包含搜索路径和区域设置。请直接通过
kbuildsycoca6以及systemd-run --user刷新;仅刷新 AppImage 环境内部可能会让 KWin 读取过期的权限。
就绪状态通过使用无效 ID 调用 CaptureWindow 并期望得到 InvalidWindow 来检查,这发生在 KWin 的授权检查之后。仅凭磁盘上的文件绝不意味着已就绪。
Plasma 会消耗用于移位数字的 Shift,并产生标点符号 keysym,因此成功绑定的 Ctrl+Shift+2 在某些布局上可能永远不会触发。字母组合键可以规避此问题。通用修复需要布局感知的编码。
Hyprland¶
辅助程序在通过 hyprland-toplevel-export-v1 导出之前,使用 hyprland-toplevel-mapping-v1 将 foreign-toplevel 句柄映射到完整的 64 位窗口地址。绝不要截断地址或按标题选择窗口。
Hyprland 0.56.2 在同意被拒绝或 no_screen_share 规则生效时,会渲染 access-denied 纹理,而不是让导出帧失败。ready 不是权限授予,并且不得通过检查像素来猜测是否授予权限。参见 ScreenshareFrame。
Hyprland 的 GlobalShortcuts 门户注册的是动作,而不是按键组合。shortcutActionRegistered 与 shortcutRegistered 是不同的;UI 中不得声称这些按键已被保留。
捆绑的协议 XML 随辅助程序一起提供,因为其 BSD 许可证要求附带该声明。
Niri¶
Niri 不实现 global-shortcut 门户。捕获启用期间,应用在会话总线上拥有 <app-id>.SnapShot,并导出 com.t3tools.SnapShot.Capture;配置绑定会启动 gdbus 来调用它。开发版和打包版的应用 ID 使用不同的名称,这样开发构建不会抢占用户的绑定。
Niri 不提供全局截图原点,因此 AT-SPI 匹配仅使用逻辑尺寸和标题。
配置编辑¶
CaptureShortcutConfig 编辑用户 dotfiles。不变量:打开设置界面时绝不会读取该文件;审阅更改是读取同意;渲染器只能通过受信任的桌面 IPC 看到修改前/修改后的文本;保存会发送提议 ID,桌面端会在写入前根据其预览过的快照重新验证字节、inode、模式和包含项。写入通过暂存的临时文件进行,并以原子重命名的方式完成,同时在原文件旁保留备份。Niri 会先验证暂存文件。
修饰键序列化会显式写入 Linux 的 Ctrl,绝不使用跨平台的 mod 别名。
GNOME 扩展¶
源代码位于 apps/desktop/gnome-extension,UUID 为 snap-shot@t3.codes。GNOME 只在登录时发现新安装的扩展,因此 setup 会区分“已安装,需注销”和“已发现但已禁用”,并比较已加载版本和已安装版本。
扩展信任在同一连接上拥有 com.t3tools.T3Code.SnapShot(或 .Development 变体)的调用方。这是 GNOME 的受信任会话客户端模式,并不是对用户总线上的恶意进程进行认证。
Electron 不会在 Wayland 上定位覆盖窗口,因此闪光与飞行动画作为扩展内部的 Shell actor 运行,坐标相对于 T3 的内容区域。Electron 44 的恢复会话路径可能会跳过重新绑定,并在取消注册时遗留回调,这就是为什么 PortalCaptureShortcut 拥有自己的门户会话,而不是使用 Electron 的 global-shortcut API。
GNOME 50 移除了 Meta.is_wayland_compositor。Shell 内部实现会随主版本变化;在将某个版本加入 metadata.json 之前,请对每个版本进行验证。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 t3/t3code