背景
在之前那篇 Wayland 窗口管理器选型 里,我对 Wayfire 的评价是"方向不对"。原因之一是 工作区对大部分 bar(如 Waybar、DMS)都不兼容,需要自己写插件/脚本实现。
但吐槽归吐槽,实际需求摆在那里——手头确实有设备在跑 Wayfire,而 DMS(DankMaterialShell)又是我习惯的 bar/desktop shell。DMS 原生只内置了针对 Niri、Hyprland、Sway 和 dwl 的 WorkspaceSwitcher 控件,并不支持 Wayfire。
所以这篇文章就是填这个坑的完整记录——为 DMS 写一个 Wayfire 工作区插件。
关于 DMS 本身:它是一个基于 Quickshell 框架的 Wayland 桌面 Shell,支持插件扩展。如果你刚接触 DMS,可以参考之前的 DMS 配置笔记。
方案选型
要实现工作区显示,需要解决两个问题:
- 如何从 Wayfire 获取工作区信息?
- 如何让 DMS 显示这些信息?
Wayfire 端:IPC 协议
Wayfire 的 ipc 插件提供了一个 Unix Socket(位于 $XDG_RUNTIME_DIR/wayfire-*.socket),采用 JSON-RPC + 长度前缀的消息格式。搭配 wayfire-plugins-extra 里的 ipc-rules 插件后,可以获取完整的输出(output)/ 视图(view)信息,并订阅工作区切换、视图映射/取消映射等事件。
主要 IPC 方法:
| 方法 | 用途 |
|---|---|
window-rules/list-outputs | 列出所有输出(显示器)及当前工作区位置 |
window-rules/list-views | 列出所有视图(窗口) |
window-rules/events/watch | 订阅事件,实时推送变更 |
vswitch/set-workspace | 切换工作区 |
DMS 端:插件系统
DMS 的插件系统基于 PluginComponent,可以自定义 bar 上的 widget。核心属性:
horizontalBarPill/verticalBarPill— bar 上显示的组件popoutContent— 弹出菜单组件pluginData— 存储在plugin_settings.json中的用户配置
架构设计
| |
Python 守护进程作为中间层,订阅 Wayfire 事件,将视图与工作区的对应关系维护在内存中,实时写入 JSON 状态文件。DMS 插件通过定时轮询读取该文件更新显示。
实现细节
Python 守护进程
主要逻辑在 wayfire-workspace-state 脚本中:
- IPC 连接:通过环境变量
_WAYFIRE_SOCKET或扫描$XDG_RUNTIME_DIR寻找 socket - 事件订阅:监听
wset-workspace-changed、view-mapped、view-unmapped、view-workspace-changed等事件 - 视图跟踪:维护
views_per_workspace字典,每次事件更新后重建工作区列表 - 状态写入:原子写入(先写
.tmp再rename),避免 QML 读到半截数据
关键代码结构:
| |
DMS QML 插件
WayfireWorkspace.qml 的结构:
| |
这里有一个坑值得提:DMS 的 Proc.runCommand 是 qs.Common.Proc 单例提供的方法,签名是 runCommand(id, commandList, callback),其中 id 用于去重。一开始我按直觉传了 runCommand("cat", [path], callback),结果 id 占用了第一个参数,实际执行的命令变成了 [path] 漏掉了 cat。这个调试花了一些时间。
Wayfire 配置
需要在 wayfire.ini 中启用 IPC 插件:
| |
最终效果
- Bar 上显示所有工作区编号,活跃工作区高亮,有窗口的工作区显示指示点
- 点击编号直接切换到该工作区
- 点击空白区域弹出完整工作区网格视图
- 颜色、轮询间隔、显示模式均可通过 DMS 设置面板调整
项目地址
完整的插件源码已经开源在 GitHub:
👉 joyanhui/dms-ext-wayfire-workspace
包含:
WayfireWorkspace.qml/WayfireWorkspaceSettings.qml— DMS 插件wayfire-workspace-state— Python 守护进程/CLIREADME.md— 详细的使用说明(不依赖 NixOS)
总结
这个插件的开发过程典型地展示了 Wayland 生态中的"组合式创新"模式:
- Wayfire 提供了 IPC socket 和事件推送 — 这是基础设施
- Python 守护进程作为胶水层,将 IPC 事件转化为静态文件
- DMS 插件系统提供了 bar widget 的扩展点
- Quickshell 的
ProcAPI 让 QML 可以安全地执行外部命令
每个组件都在做自己擅长的事,没有谁被强行改造。这也是 Linux 桌面生态最吸引人的地方——当现成的工具不满足需求时,你可以把积木换一块,而不是换掉整个乐高套装。
至于 Wayfire 本身在 选型文章 里的评价,这个插件的存在并不会改变"方向不对"的结论——堆叠式管理器的天花板确实在那里。但它至少让 Wayfire 用户在使用 DMS 时少了一个痛点。