在 KDE Plasma 从 X11 迁移到 Wayland 之后,一些曾经依赖 X11 窗口属性的工具会逐渐失去作用。KDocker 就是典型例子:它可以在 X11 环境中把普通窗口“塞进”系统托盘,但面对原生 Wayland 窗口时,这种外部包装方式已经不再可靠。

本文记录一次完整迁移过程,目标是让两个应用在 KDE Plasma Wayland 下获得统一的托盘行为:

启动应用
→ 窗口短暂出现
→ 自动进入 System Tray

点击 Minimize
→ 进入 System Tray

点击 Close(×)
→ 真正退出应用

涉及的应用类型包括:

  • 一个系统原生邮件客户端;
  • 一个通过 Chromium 系浏览器独立 Profile 封装的 Web App。

整个迁移过程遵循三个原则:

  1. 应用本身必须保持原生 Wayland 启动;
  2. 先恢复直接启动,再清除旧工具;
  3. 托盘功能由 KWin 原生脚本实现,不再依赖 X11 包装器。

一、旧方案的问题在哪里

旧方案的结构大致如下:

Desktop entry
    ↓
KDocker
    ↓
应用程序

KDocker 在 X11 下通常通过窗口类、窗口 ID 和窗口管理协议操作应用窗口,达到以下效果:

  • 从 Task Manager 隐藏;
  • 从 Task Switcher 隐藏;
  • 创建 System Tray icon;
  • 点击托盘图标恢复窗口。

这种方式在 X11 中相对直接,但 Wayland 的安全模型不同:

  • 普通应用不能任意控制其他应用的窗口;
  • X11 的窗口 ID 不再是可靠的统一接口;
  • WM_CLASS 不再是 Wayland 应用身份的唯一来源;
  • 窗口隐藏和恢复更适合由 compositor 或 window manager 直接完成。

因此,在原生 Wayland 环境中继续维护 KDocker,不仅效果不稳定,还会引入额外的 XWayland 依赖和窗口识别问题。

正确方向不是继续修补 KDocker,而是:

应用直接启动
→ 原生 Wayland 窗口
→ KWin Script 管理托盘行为

二、迁移顺序非常重要

这类迁移最危险的操作顺序是:

先卸载 KDocker
→ 再尝试修复应用启动器

一旦原有 Desktop entry 直接调用 KDocker,先卸载软件包就会让应用入口失效。

更稳妥的顺序是:

审计现有启动链
→ 备份启动器和脚本
→ 移除 KDocker 包装
→ 验证应用可以直接启动
→ 清理 KDocker 配置
→ 卸载 KDocker
→ 安装 KWin 托盘脚本
→ 配置并验证行为

这样即使新的托盘方案暂时不可用,应用本身仍然可以正常启动。


三、先审计当前启动链

在修改之前,需要确认两个应用分别是怎样启动的。

1. 系统原生应用

系统原生应用通常由软件包提供标准 Desktop entry,例如:

<system-applications-dir>/<application>.desktop

典型启动项类似:

Exec=<application> %u

旧方案可能另外创建了用户级 Desktop entry:

<user-applications-dir>/<custom-launcher>.desktop

其中的 Exec 类似:

Exec=kdocker ... <application>

迁移时需要确认:

  • 系统原版 Desktop entry 是否仍然存在;
  • 用户级启动器是否遮蔽了系统原版;
  • 是否存在 Hidden=true 的用户级覆盖文件;
  • Application Launcher 当前显示的是哪一个入口;
  • 是否还有自动启动项继续调用 KDocker。

2. 浏览器封装的 Web App

浏览器封装应用通常采用如下结构:

Desktop entry
    ↓
Launch script
    ↓
Chromium-based browser --app=...

启动脚本中最关键的是独立 Profile:

--user-data-dir="<user-data-dir>/<app-profile>"

它负责隔离:

  • 扩展;
  • 登录状态;
  • Cookies;
  • 浏览器设置;
  • 缓存;
  • Local Storage;
  • 会话数据。

这类目录不能在迁移过程中删除或重建,否则可能丢失登录状态。


四、恢复应用直接启动

系统原生应用

旧启动器中的命令可能类似:

Exec=kdocker ... <mail-client>

应改成直接启动:

Exec=env MOZ_ENABLE_WAYLAND=1 <mail-client>

如果原启动器带有 %u%U--profile 等参数,必须原样保留。

如果系统原版启动器已经可以满足需求,也可以删除不再需要的用户级自定义启动器,恢复系统原版入口。

删除用户级 Desktop entry 后,需要刷新 KDE application cache:

kbuildsycoca6 --noincremental

否则 Application Launcher 可能继续显示已经删除的旧入口。

浏览器 Web App

旧 Desktop entry 可能类似:

Exec=kdocker ... <user-data-dir>/<app-profile>/launch.sh

应改为直接调用脚本:

Exec=<user-data-dir>/<app-profile>/launch.sh

脚本本身保留独立 Profile,并明确使用 Wayland:

#!/usr/bin/env bash

exec <browser-path> \
    --user-data-dir="<user-data-dir>/<app-profile>" \
    --no-first-run \
    --no-default-browser-check \
    --ozone-platform=wayland \
    --class=<app-class> \
    --app="chrome-extension://<extension-id>/<entry-page>"

其中:

--ozone-platform=wayland

用于确保浏览器窗口运行在原生 Wayland。

--user-data-dir=...

用于保持应用数据与普通浏览器 Profile 隔离。

--class=...

用于尽量保留独立应用身份。


五、验证应用已经脱离 KDocker

在卸载 KDocker 之前,应先验证两个应用都可以直接启动。

检查重点包括:

  • 应用进程是否存在;
  • 命令链中是否还出现 kdocker
  • 浏览器 Web App 是否仍使用原有独立 Profile;
  • --app= 地址是否没有变化;
  • 是否明确包含 Wayland 参数;
  • 是否出现 Profile lock 或启动崩溃;
  • 用户数据和登录状态是否保留。

只要应用能够直接启动并保持运行,就说明 KDocker 已经不再是必要依赖。


六、清理并卸载 KDocker

确认应用已经脱离 KDocker 后,可以卸载软件包:

sudo pacman -Rns kdocker

随后检查:

pacman -Q kdocker 2>&1 || true
command -v kdocker || true
pgrep -a kdocker || true

理想状态:

package not found
executable absent
no running process

还应确认软件包提供的 Desktop entry 已消失:

<system-applications-dir>/com.kdocker.KDocker.desktop

真正属于 KDocker 的用户配置也可以删除:

<user-config-dir>/com.kdocker/KDocker.conf

但要特别注意,不要误删名字相似的 KDE 配置文件。

例如某些文件名虽然包含 KDocker 字样,实际内容可能只是 KDE File Dialog 设置,与 KDocker 应用无关。清理时必须根据文件内容和软件包归属判断,不能只看文件名。


七、安装 KWin Minimize to Tray

新的托盘功能由 KWin Script 提供。

在 Arch Linux 中,可以通过 AUR 安装:

yay -S kwin-minimize2tray-git

安装后,脚本文件通常进入系统 KWin Script 路径,相关 QML 插件进入 Qt 目录。

在 KDE Plasma 英文界面中的实际设置路径是:

System Settings
→ Apps & Windows
→ Window Management
→ KWin Scripts

安装完成后,脚本可能已经自动启用,不一定需要手动勾选。

点击 Minimize to Tray 右侧的配置按钮,可以看到以下选项:

Start minimized
Notifications as dot
Debug
Hide on minimize

八、窗口身份不能随便填写

Start minimized 需要填写窗口的精确身份。

对于系统原生应用,窗口 class 可能类似:

org.example.Application

对于 Chromium 系 Web App,窗口 class 可能类似:

brave-<extension-id>__<entry-page>-Default

必须使用实际检测到的完整值,不能只填写:

brave

因为过于宽泛的 brave 可能匹配所有普通浏览器窗口,导致普通浏览器也被自动隐藏到托盘。

窗口身份可通过 KWin Debug Console 查看。需要记录的字段通常包括:

resourceName
resourceClass
desktopFileName
app_id
caption

系统原生应用和浏览器 Web App 的识别方式并不完全相同,因此应分别测试。


九、最终配置

最终采用如下配置:

Start minimized:
<specific-web-app-class>,<specific-mail-client-class>

Notifications as dot:
unchecked

Debug:
unchecked

Hide on minimize:
checked

含义如下。

Start minimized

应用启动后,KWin 在识别到窗口 class 后,自动创建托盘图标并隐藏窗口。

Notifications as dot

是否把通知或计数状态显示成圆点。

不需要此效果时保持关闭。

Debug

正常使用时应关闭,避免产生额外调试输出。

Hide on minimize

窗口从托盘恢复后,再次点击 Minimize,窗口会重新进入 System Tray。


十、保存配置后要重新加载脚本

配置窗口会提示,修改只有在重新加载脚本后才会生效。

操作路径:

System Settings
→ Apps & Windows
→ Window Management
→ KWin Scripts

依次执行:

  1. 取消勾选 Minimize to Tray
  2. 点击 Apply
  3. 重新勾选 Minimize to Tray
  4. 再点击 Apply

如果仍然没有生效,可以执行一次 Log Out,然后重新登录 Plasma。


十一、为什么启动时仍会短暂显示窗口

启用 Start minimized 后,应用启动时仍可能短暂出现窗口。

这是正常现象,并不代表配置失败。

执行顺序是:

应用进程启动
→ 应用创建 Wayland 窗口
→ KWin 收到新窗口
→ 脚本读取窗口身份
→ 判断是否匹配 Start minimized
→ 创建 System Tray icon
→ 隐藏窗口

脚本必须等到窗口真正创建后才能识别它,因此无法做到完全零闪现。

只要最终窗口进入 System Tray,并从 Task Manager、Task Switcher 和 Desktop Pager 中消失,就属于正常行为。


十二、最小化和关闭为何会混在一起

迁移完成后曾出现一个现象:

点击 Minimize
→ 进入 System Tray

点击 Close(×)
→ 也进入 System Tray

最初容易怀疑 KWin Script 拦截了 Close,但实际问题来自应用内部的旧扩展。

邮件客户端中安装了一个类似:

Minimize on Close

的扩展。

它会把:

Close(×)

转换成:

Minimize

而 KWin Script 又会把 Minimize 变成 Tray,所以完整链条变成:

点击 Close(×)
→ 应用扩展将 Close 改为 Minimize
→ KWin Script 捕获 Minimize
→ 窗口进入 System Tray

处理方法是在邮件客户端中打开:

Application Menu
→ Add-ons and Themes
→ Extensions

Minimize on Close 设为 Disabled,或者直接 Remove

处理后行为恢复为:

点击 Minimize
→ 进入 System Tray

点击 Close(×)
→ 真正退出应用

十三、KWin Window Rules 不需要全面重写

系统中原本可能存在应用的 Window Rules,用于控制:

  • Position;
  • Size;
  • Screen;
  • Virtual Desktop;
  • Maximized state。

即使旧规则中仍然使用具体标题或旧式窗口 class,也不代表必须立即删除。

真正可能与托盘功能冲突的是:

Minimized
Skip Taskbar
Skip Pager
Skip Switcher
Closeable

如果规则只控制 Position 和 Size,则通常不会影响 KWin Minimize to Tray。

正确策略是:

先检查实际冲突
→ 只修改有问题的规则项
→ 不重写整个 kwinrulesrc

窗口标题匹配可能较脆弱,但只要当前功能正常,可以先保留。


十四、System Tray 显示设置

如果应用已经进入 System Tray,但图标被放进隐藏区域,可以打开:

Right-click System Tray
→ Configure System Tray...
→ Entries

将对应应用设置为:

Always Shown

这只影响托盘图标是否常驻显示,不影响窗口隐藏逻辑。


十五、最终行为

迁移完成后的应用行为如下。

启动

启动应用
→ 窗口短暂出现
→ 自动进入 System Tray

恢复

点击 System Tray icon
→ 窗口恢复

最小化

点击 Minimize
→ 进入 System Tray

关闭

点击 Close(×)
→ 应用真正退出

系统原生应用

系统 Desktop entry
→ 原生 Wayland
→ KWin Minimize to Tray

浏览器 Web App

自定义 Desktop entry
→ 独立 Browser Profile
→ Wayland Ozone
→ KWin Minimize to Tray

十六、最终审计内容

配置完成后,需要进行一次完整的只读审计。

建议检查以下项目:

KDocker

软件包不存在
可执行文件不存在
运行进程不存在
系统 Desktop entry 不存在
活动配置引用不存在

KWin Script

只安装一份
Plugin ID 唯一
脚本已启用
没有用户级和系统级重复安装

Minimize to Tray 配置

Start minimized 使用具体 class
没有宽泛的 browser class
Debug=false
Hide on minimize=true
Notifications as dot=false

系统原生应用

系统 Desktop entry 正常
不存在 KDocker 包装
Minimize on Close 扩展已禁用
Close 不再被转换为 Minimize

浏览器 Web App

Desktop entry 直接调用启动脚本
独立 Profile 保留
Wayland 参数存在
App URL 保持不变
不存在 KDocker 引用

KWin Window Rules

不存在强制 Minimized
不存在强制 Skip Taskbar
不存在强制 Skip Pager
不存在强制 Skip Switcher
不存在 Closeable=false

其他项目

没有异常 Autostart
没有相关用户 systemd service
没有用户目录顶层垃圾输出
历史备份不参与当前启动链

十七、常见误区

误区一:先卸载 KDocker

如果 Desktop entry 仍然依赖 KDocker,应用入口会直接失效。

误区二:把 brave 填入 Start minimized

这样可能导致所有 Brave 窗口进入托盘。

误区三:删除独立浏览器 Profile

这可能丢失 Web App 的登录状态和扩展配置。

误区四:把 Close 进入托盘归咎于 KWin

很多时候真正原因是应用内部仍安装着 Minimize on Close 扩展。

误区五:看到相似文件名就删除

某些 KDE 配置文件名字与 KDocker 相似,但内容完全无关。

误区六:全面重写 KWin Window Rules

只控制窗口位置和大小的规则不需要因为托盘迁移而删除。

误区七:忽略 KDE application cache

删除用户级 Desktop entry 后,需要运行:

kbuildsycoca6 --noincremental

否则 Application Launcher 可能继续显示旧入口。


十八、经验总结

从 X11 迁移到 Wayland 时,托盘功能不只是换一个工具,而是在重新设计整个窗口管理链。

最可靠的处理思路是:

恢复应用直接启动
→ 确认原生 Wayland
→ 清除旧 X11 包装器
→ 使用 KWin 原生脚本
→ 精确匹配窗口身份
→ 检查应用自身扩展
→ 最后进行完整只读审计

这次迁移最终实现了:

旧 X11 包装器:彻底移除
系统原生应用:直接启动
浏览器 Web App:独立 Profile 保留
Wayland:原生运行
Minimize:进入 System Tray
Close:真正退出
KWin Window Rules:无托盘冲突

相比继续维护 KDocker,KWin Minimize to Tray 更符合 Plasma Wayland 的架构,也更容易随着桌面环境升级继续维护。

Leave a Reply

Your email address will not be published. Required fields are marked *