11 · 桌面服务适配层¶
通知、提醒、截图、录屏、OCR 和音频都不是单纯 UI。它们把 D-Bus、systemd、Hyprland、PipeWire 与命令行工具包装成可从菜单、快捷键和终端复用的桌面动作。
共同模式:系统能力 + 薄命令 + Shell 表面¶
flowchart LR
Input[快捷键/菜单/CLI] --> Adapter[omarchy-* 适配命令]
Adapter --> OS[D-Bus/systemd/Hyprland/PipeWire]
Adapter --> IPC[Quickshell IPC]
IPC --> UI[toast/panel/overlay]
OS --> State[文件/设备/进程状态]
State --> UI
这样做把“执行动作”和“显示反馈”拆开。headless 场景仍可以完成核心动作;图形会话存在时再提供实时反馈。
通知:Shell 自己拥有服务¶
Quickshell notification 插件注册 freedesktop NotificationServer,因此系统不再需要 dunst/mako。omarchy-notification-send 是 notify-send 的产品化 wrapper,把 glyph、点击 exec、图片等信息编码到 hints。
持久化模型¶
每个 popup 有独立 JSON 文件;归档后进入 history,保留最新 10 条,并复制需要持久化的图片。replace_id 更新同一通知身份,而不是留下重复条目。
stateDiagram-v2
[*] --> Incoming
Incoming --> Popup: 未静音/允许显示
Incoming --> History: 静音但非 ephemeral
Popup --> Replaced: replace_id 命中
Popup --> History: dismiss/timeout
Replaced --> History
History --> Trimmed: 超过 10 条
Do Not Disturb 并非绝对吞掉:Omarchy action 与 critical notification 有例外,保证系统确认和严重状态仍可达。被静音但值得保留的通知进入 history,用户稍后能看到。
--exec 数据放在通知自身而不是保持发送进程阻塞,所以即使 sender 已退出、Shell 中途重启,点击动作仍有机会恢复。
提醒:用 systemd 表达未来¶
omarchy-reminder 不维持一个常驻 shell sleep。它创建 transient user timer,并把消息存到 runtime 文件;到时由 systemd 触发 Shell reminder flow。
这让提醒:
- 不依赖原终端继续运行;
- 可由 systemd 管理定时与取消;
- UI 只在触发时加载;
- 消息传递仍是明确文件/IPC 契约。
Capture:组合 Wayland 工具¶
区域捕获入口统一处理 Hyprland geometry、slurp 选择和冻结画面,再被不同命令复用:
| 功能 | 额外阶段 |
|---|---|
| screenshot | 保存图片、剪贴板/通知 |
| OCR | 图片交给 OCR,再复制文本 |
| QR | 识别二维码并处理结果 |
| screen recording | 选择输出、音频、停止信号与后处理 |
录屏会在 KMS capture 与显式 opt-in portal 之间选择,并可叠加 webcam、合并音频。停止不是粗暴 kill:脚本维护录制进程/overlay 状态,通过 signal 收尾并在后处理中产出最终文件。
flowchart TD
Start[screenrecord 命令] --> Source{KMS 或 portal}
Source --> Region[显示器/区域]
Region --> Audio[可选系统/麦克风]
Audio --> Webcam[可选摄像头 overlay]
Webcam --> Record[录制进程]
Stop[stop action] --> Signal[发送结束信号]
Signal --> Record
Record --> Post[合并/转码/通知]
这里的复杂度不在 ffmpeg 参数本身,而在“开始、显示状态、停止、清理、产出反馈”必须形成一条不会遗留进程的生命周期。
音频:状态读取与安全调优¶
普通 volume/default sink 命令包装 PipeWire/WirePlumber 工具,给 bar、keybinding 和菜单提供一致接口。硬件 speaker tuning 更谨慎:
- 依据硬件匹配数据决定是否适用;
- 使用单独 PipeWire client,避免调优进程失败拖垮主音频图;
- 切换而不重启整个 PipeWire;
- 验证结果,失败时回滚;
- 从 physical sink 读取音量,避免逻辑节点误导 UI。
这是“适配器”应有的边界:只把下游系统可靠支持的状态暴露给 UI,不伪造一个内部真相。
为什么大多保留 CLI¶
即使有漂亮 panel,Omarchy 仍为动作保留命令入口:
- Hyprland binding 不需要知道 QML 内部;
- 菜单 action 与自动化可以复用;
- 故障时能从终端单独验证系统层;
- exit status 和 stdout 可进入 shell pipeline;
- Shell 只负责必须常驻或必须显示的部分。
关键源码索引¶
shell/plugins/notifications/Service.qml— NotificationServer 与持久化编排shell/plugins/notifications/NotificationLogic.js— replace/DND/history 纯逻辑bin/omarchy-notification-send— 发送适配器bin/omarchy-reminder— transient timerbin/omarchy-capture-region— 区域选择基础设施bin/omarchy-capture-screenrecording— 录屏生命周期docs/notifications.md— 通知语义docs/audio-tuning.md— 扬声器调优设计
下一章看应用与包如何进入同一套控制面:12 · 应用与软件包抽象。