服务:dophin怎么单例和自动提升

一句话结论

Dolphin 是单例包装(同名命令压过 Plasma 自带的那份):已有实例时用 DBus 让它在现有窗口里开标签(不堆进程),再补一步 wmctrl -x -a dolphin 把窗口提升到前台。两件事都写在 modules/system/explorer/dolphin.nix 里,全部声明式。

一、两个需求 → 两个机制

需求机制落在哪
不堆进程(单例)已有实例 ⇒ DBus 调用它的 MainWindow 接口在现有窗口开标签dolphin.nix 的 lib.hiPrio singleInstance 包装脚本
打开时到前台(提升)DBus 调用之后再 wmctrl -x -a dolphin(按 WM_CLASS 匹配)同上,脚本末行
真启动(无实例时)exec 真 dolphin包装脚本 svc 为空的分支

二、单例部分的实际行为

输入包装行为
普通目录参数 dolphin ~/x已有实例 ⇒ DBus openDirectories asb <n> <uri…> <split>
--select <file>同上但走 openFiles;无实例时原样交给真 dolphin
--split作为 split 布尔传给 DBus
--new-window被忽略(本包装的意义就是不允许堆实例)
--sudo / --admin / --daemon / --help / --version / --author / --license / --desktopfile*原样 exec 真 dolphin
其它未知开关忽略
无参数默认目标 file://$HOME

三、提升部分(本页重点)

为什么不能靠 DBus 自带的“激活”:
busctl --user call org.kde.dolphin-<pid> /dolphin/Dolphin_1 org.kde.dolphin.MainWindow activate
⇒ Call failed: No such method 'activate' in interface … ✗
同上试 show ✗
该接口只有 openDirectories / openFiles;而且 introspection 数据有重复方法(duplicate method)⇒ busctl introspect 会 Failed ✗

所以用 X11 的窗口管理命令(本机图形会话就是 X11):
wmctrl -x -a dolphin # -x 按 WM_CLASS 匹配;-a 切到该窗口所在桌面并提升
实测 Dolphin 的 WM_CLASS = "dolphin", "dolphin" ⇒ 匹配得上 ✓

四、模块里的最终形态(关键几行)

# 脚本内变量(⚠ 必须在脚本体里赋值:写成 let 绑定 + 脚本里用 $wmctrl 会 unbound variable)
wmctrl="${pkgs.wmctrl}/bin/wmctrl"

# DBus 开标签 / 开文件之后:
"$wmctrl" -x -a dolphin

五、自查判据(可自行复核)

① 包装是否在生效(应该命中 hiPrio 那份):
command -v dolphin ; head -3 $(command -v dolphin)

② 有没有实例、实例的 DBus 服务名:
pgrep -a dolphin
busctl --user list | grep -o 'org\.kde\.dolphin-[0-9]*'

③ 窗口类名(提升靠它匹配):
wmctrl -x -l | grep -i dolphin

④ 提升是否真的发生(端到端):
dolphin "$HOME"; echo $?
xprop -root _NET_ACTIVE_WINDOW | awk '{print $NF}'
xprop -id <上一步的 id> WM_CLASS # 应输出 "dolphin", "dolphin"

六、踩过的坑(本机真实发生)

坑现象正解
把 wmctrl 定义写在 nix 的 let 里脚本报 wmctrl: unbound variable(退出码 1)脚本内自己赋值(同 busctl= 的写法)
用 2>&1 >/dev/null 跑包装验收错误被吞,只看到“退出码非零”验收命令不要重定向掉 stderr
想用 DBus 的 activate/show 提升接口里根本没这两个方法用 wmctrl(X11)
busctl introspect 看方法Failed: duplicate method 'openDirectories'直接按已知签名调用(asb 必须连写)

七、可复用性

项位置nix rebuild 后重装系统(拷 /etc/nixos)后
单例包装 + 提升modules/system/explorer/dolphin.nix保留 ✓可复用 ✓
wmctrl 包由模块内表达式引用保留 ✓可复用 ✓
窗口类名/桌面环境前提X11 会话(非 nix 值)—需同样是 X11 会话(Wayland 下 wmctrl 不适用)

停用/回退:注释掉 configuration.nix 里 dolphin 那一行 ⇒ 恢复 Plasma 原生 dolphin(不再单例、不再提升);或从 /etc/nixos/backup/ 里取起改动前的 dolphin.nix 拷回后 rebuild。

八、相关笔记

  • 「服务:nix收敛代理配置」xi6ugMzM4rB0(代理链路与 30 秒故障定位)
  • 「服务:docker的rootful和rootless困惑」915vFpZhWb2s(本机 docker 两个 daemon 的差异与处置)