跳转至

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 只负责必须常驻或必须显示的部分。

关键源码索引

下一章看应用与包如何进入同一套控制面:12 · 应用与软件包抽象。