07 · Quickshell 运行时¶
Omarchy Shell 不是一组每次点击才启动的 QML 小程序,而是一个长时间运行的 Quickshell 进程。bar、panel、overlay、menu、通知和后台 service 都是它内部的插件。
为什么需要常驻宿主¶
桌面 UI 有大量需要共享的状态:应用索引、插件注册表、主题 token、当前 panel、通知历史、托盘和媒体状态。如果每个界面都独立启动,会重复扫描、出现多个 D-Bus owner,并很难保持互斥关系。
flowchart TD
Root[shell.qml / ShellRoot]
Root --> PR[PluginRegistry]
Root --> BR[BarWidgetRegistry]
Root --> AL[AppLibrary]
Root --> Bar[Active Bar]
Root --> Service[Service Loaders]
Root --> Surface[Panel / Overlay / Menu Loaders]
CLI[omarchy-shell IPC] --> Root
PR --> Bar
PR --> Service
PR --> Surface
AL --> Bar
AL --> Surface
shell.qml 显式创建共享 registry 和 AppLibrary,再通过 property 注入下游。这样可避免 QML 相对 import 造成“看似 singleton、实际不同实例”的问题。
启动与重启¶
Hyprland autostart 调用 omarchy-launch-shell,后者启动 Quickshell 主文件。omarchy-restart-shell 使用锁和等待逻辑,避免旧进程未退出就拉起第二个实例。
IPC wrapper omarchy-shell 只向已运行实例转发调用,并受超时控制。它不会自动启动 Shell:
- 正常调用失败能真实反映桌面运行时缺失;
-q可用于 quiet best-effort 场景;- 启动责任仍集中在会话 autostart,而不是散到任意命令。
这防止一个 headless SSH 命令意外启动整套图形桌面。
配置加载链¶
Shell 有三层配置输入:
shell.qml内置一个可启动的 fallback 对象;- 读取
$OMARCHY_PATH/config/omarchy/shell.json的发行初始配置; - 若
~/.config/omarchy/shell.json存在且合法,则整体替换。
default 和 user 文件都由 FileView 监视,改动触发重新解析。用户配置是 canonical object,不做 deep merge;这避免新默认字段在用户不知情时改变已定制桌面。
插件何时加载¶
| 类型 | 时机 | 理由 |
|---|---|---|
| active full bar | 启动时 | 桌面持续可见 |
| first-party service | 启动时 | 通知、锁屏等基础设施 |
| third-party service | 被 shell.json 启用时 | 不默认执行外部代码 |
| panel / overlay / menu | summon 时 | 降低常驻开销 |
keepLoaded surface |
首次 summon 后保留 | 插件声明保留状态/性能 |
若选中的第三方 full bar 加载失败,宿主回退到内置 omarchy.bar,保证桌面仍有基本控制面。
延迟 surface 的两次召唤问题¶
panel 第一次 summon 时 Loader 还没完成。如果第二个 payload 很快到达,简单实现会覆盖或丢失事件。Shell 保存 pending payload,待组件 ready 后再调用 open(payloadJson)。
sequenceDiagram
participant C as CLI
participant H as Shell host
participant L as Loader
participant P as Plugin panel
C->>H: summon(id, payload A)
H->>L: active = true
C->>H: summon(id, payload B)
H->>H: 保存 pending payload
L-->>H: item ready
H->>P: 注入依赖
H->>P: open(latest queued payload)
宿主还维护当前 open panel ID,使常规 panel 互斥;bar widget 对应的 panel 则路由给正在使用的 bar 实例,因为位置和 anchor 由 bar 掌握。
IPC 是稳定边界¶
Shell 暴露一个 shell target,并允许插件注册自己的 target。核心方法包括:
ping:健康检查;summon/hide/toggle:surface 生命周期;call:调用已加载插件方法;rescanPlugins:重新发现与热加载;reloadConfig:重读 shell.json;applyTheme:推送颜色和 shell token;- bar widget 的 put/move/set 与调试接口。
命令行、Hyprland binding 和其他脚本都走 IPC,而不是直接操作 QML 对象。这让 UI 内部可以重构,只要 IPC 契约保持。
主题如何进入常驻进程¶
主题切换先在文件系统生成 colors.toml / shell.toml,随后把 base64 编码的 payload 经 applyTheme 推入 Shell。机器级 ~/.config/omarchy/shell.toml 另由 FileView 实时监视,并覆盖活动主题的对应 token,使文字大小等本机偏好跨主题保留。
QML 通过共享 singleton 使用:
Color:基础 palette 与各 surface 角色;Style:间距、字号、圆角与 bar 尺寸;Border:支持渐变/分边宽度的边框规范。
故障隔离策略¶
| 故障 | 宿主行为 |
|---|---|
| 用户 shell.json 无效 | 保持可启动 fallback/default |
| 自定义 bar 加载失败 | 回退内置 bar |
| panel 尚未实例化 | 排队 payload 后延迟 open |
| Shell 不在运行 | IPC 明确失败,不偷偷启动 |
| 插件目录变化 | rescan / inotify 热加载用户代码 |
| 主题切换 | 先原子更新文件,再向运行时推送 |
关键源码索引¶
shell/shell.qml根对象与共享实例shell/shell.qml配置监视shell/shell.qmlservice loadersshell/shell.qml延迟 surface 加载bin/omarchy-shell— IPC wrapper 与超时bin/omarchy-launch-shell— 会话启动docs/omarchy-shell.md— manifest、IPC 和配置契约
下一章专门拆常驻宿主最重要的扩展边界:08 · 插件系统。