前言:此前的修复为什么“有效”,却又不够完整

此前曾记录过一次 KDE Plasma Wayland 环境下的 Fcitx5 冷启动故障。

当时的现象是:系统冷启动后,部分 Chromium 系应用无法正常切换输入法;重新启动 Fcitx5 后,问题又会消失。最终排查发现,系统同时存在两条 Fcitx5 启动路径:

  1. KWin Wayland 的 Virtual Keyboard / Input Method 机制;
  2. 传统的 XDG Autostart 机制。

两条路径在登录时同时尝试启动 Fcitx5,导致 D-Bus 名称竞争和初始化竞态。解决办法是在用户配置目录建立同名覆盖文件,将传统 XDG Autostart 项隐藏:

[Desktop Entry]
Type=Application
Name=Fcitx 5
Hidden=true

示例路径经过脱敏:

/home/demo/.config/autostart/org.fcitx.Fcitx5.desktop

这样便只保留 KWin Wayland 的官方输入法启动路径。

这项修复非常重要,而且确实解决了一个真实问题:

  • Fcitx5 主实例保持唯一;
  • 传统 Autostart 不再生成 systemd 用户单元;
  • Unable to request dbus name 一类冲突消失;
  • 输入法在各类应用中恢复正常。

当时一度认为问题已经完整解决。

后来出现的新现象证明:Hidden=true 解决的是“双启动”,但没有解决所有与启动时序相关的问题。

新的问题不再是输入法不能使用,而是:

  • 输入法实际切换正常;
  • 中文、日文和英文输入均可用;
  • 候选框正常;
  • 托盘图标存在;
  • 但在部分应用中,托盘图标不会随着输入法状态变化而更新。

这两个问题彼此相关,但并不是同一个问题。


一、环境与故障现象

测试环境经过脱敏后大致如下:

  • Arch Linux;
  • KDE Plasma 6;
  • Wayland 会话;
  • KWin 管理 Wayland 输入法;
  • Fcitx5;
  • Rime、Mozc 和英文键盘布局;
  • 同时存在 XWayland,用于兼容部分旧应用。

最典型的现象是:

  • 文件管理器中可以正常输入和切换输入法;
  • Chromium 系浏览器中也可以正常输入;
  • Markdown 编辑器中同样正常;
  • 但系统托盘中的输入法图标,有时只在部分应用中同步,有时完全停留在旧状态。

这说明必须把两个概念分开:

输入法核心状态

负责:

  • 按键处理;
  • 输入法切换;
  • 候选词窗口;
  • 应用输入上下文;
  • Wayland 输入法协议。

托盘显示状态

负责:

  • 显示当前输入法图标;
  • 输入法变化时更新图标;
  • 向 KDE 系统托盘注册;
  • 通过 StatusNotifierItem 或兼容机制传递状态。

因此,托盘状态错误并不意味着 Fcitx5 核心输入功能已经失效。


二、先确认双启动问题没有复发

由于此前已经发生过双启动,第一步仍然是确认旧问题没有回来。

检查结果显示:

  • 当前只有一个 /usr/bin/fcitx5 主进程;
  • KWin 的输入法配置仍然启用;
  • 用户级 Hidden=true 覆盖仍然存在;
  • systemd 用户生成目录中没有传统 Fcitx5 Autostart 单元;
  • D-Bus 上没有第二个主实例竞争名称;
  • fcitx5-remote 能正确查询和切换输入法;
  • Wayland 输入上下文正常存在。

这一步非常关键。

如果没有先排除双启动,很容易把后面的托盘问题错误归因于此前的老问题。实际上,新的故障发生在单一 Fcitx5 主实例正常运行的情况下

换句话说:

第一篇文章中的 Hidden=true 修复仍然正确,必须继续保留;只是它解决的范围没有最初想象得那么大。


三、托盘图标在 KDE 中有两条实现路径

进一步检查系统托盘后,发现 Fcitx5 的托盘图标可能通过两种方式进入 Plasma。

1. 原生 StatusNotifierItem

现代 KDE 应用通常直接注册 StatusNotifierItem,简称 SNI。

这种情况下:

  • 托盘项目的 owner 是 Fcitx5 自己;
  • 对象路径通常类似:
:1.xx/StatusNotifierItem
  • WindowId=0
  • 图标和状态信号由 Fcitx5 直接发送给 KDE;
  • 不需要经过旧式 X11 托盘代理。

这是理想路径。

2. XEmbed 兼容路径

旧式应用可能创建一个 X11/XEmbed 托盘窗口。

KDE 中的:

plasma-xembedsniproxy.service

会把这个旧式托盘窗口转换成 Plasma 能识别的 StatusNotifierItem。

这种情况下:

  • 托盘项目由 xembedsniproxy 代持;
  • WindowId 通常不是 0;
  • 图标更新需要经过:
Fcitx5
  → XEmbed 窗口
  → xembedsniproxy
  → StatusNotifierItem
  → Plasma 托盘

链路更长,也更容易产生代理同步问题。


四、第一次关键发现:重新建立 Fcitx5 运行态后,托盘路径发生变化

为了定位究竟是哪一层失效,进行了受控 A/B 测试。

依次测试:

  1. 重启 plasma-xembedsniproxy.service
  2. 重启 plasmashell
  3. 退出并重新激活 Fcitx5。

结果如下:

  • 单独重启 xembedsniproxy 没有恢复状态同步;
  • 单独重启 plasmashell 也没有恢复;
  • 重新建立 Fcitx5 运行态后,图标立刻恢复正常。

更重要的是,恢复前后的托盘实现路径不同。

恢复前:

  • Fcitx5 托盘由 xembedsniproxy 代理;
  • WindowId 不为 0;
  • 输入正常,但托盘不同步。

恢复后:

  • 托盘项目由 Fcitx5 自己持有;
  • WindowId=0
  • 变成原生 StatusNotifierItem;
  • 各应用中的托盘状态恢复同步。

这给出了一个非常重要的方向:

问题很可能不是简单的图标缓存,而是 Fcitx5 在启动时选择了不同的托盘注册路径。


五、一次错误尝试:禁用 xembedsniproxy

因为系统使用的是 Plasma Wayland,一度认为 XEmbed 属于旧式 X11 机制,或许可以直接禁用:

systemctl --user mask --now plasma-xembedsniproxy.service

这个判断是错误的。

下一次冷启动后:

  • Fcitx5 核心输入功能仍然存在;
  • 但托盘图标完全消失;
  • 手动重新建立 Fcitx5 后,图标才恢复。

这说明 xembedsniproxy 虽然不是理想路径,却仍然是必要的兼容后备机制。

即使桌面会话是 Wayland,也不代表系统中不存在:

  • XWayland;
  • X11 兼容应用;
  • 旧式托盘组件;
  • 初始化阶段临时落入 XEmbed 的程序。

因此立即回退:

systemctl --user unmask plasma-xembedsniproxy.service
systemctl --user start plasma-xembedsniproxy.service

此后不再尝试禁用该服务。

这一段排查也澄清了两个完全不同的问题:

  • 图标完全消失:是错误禁用 xembedsniproxy 人为造成的;
  • 图标存在但状态不同步:才是原始问题。

前者回退 mask 后已经解决,不应继续与后者混在一起。


六、冷启动观察器与“观察者效应”

为了捕获完整冷启动时序,曾建立一个用户级 observer。

它收集:

  • 用户 journal;
  • 用户 D-Bus 消息;
  • Fcitx5 状态;
  • KWin、Plasma、kded6 和托盘相关进程;
  • StatusNotifierItem 注册事件。

这次取证产生了一个非常庞大的 D-Bus 日志。

原始文本解压后约 1.9 GB,使用 Zstandard 压缩后只有约 3.8 MB。这种极高压缩率并不异常,因为全量 D-Bus 日志包含大量重复的:

  • 接口名称;
  • 对象路径;
  • 字段结构;
  • 状态信号;
  • 相似消息模板。

然而,之后检查 observer 脚本时发现了一个严重问题:

脚本启动时调用了:

fcitx5-remote
fcitx5-remote -n

这些并不是纯粹的被动查询。

org.fcitx.Fcitx5 尚未存在时,访问该 D-Bus 名称会触发 Fcitx5 的 D-Bus 激活。

结果是:

  • observer 在图形会话完全建立前启动;
  • Fcitx5 被提前约二十多秒激活;
  • 当时 KWin 尚未启动;
  • Wayland 显示环境尚未完整可用;
  • 日志出现 Failed to open wayland connection
  • 主题生成器因为无法连接图形显示而崩溃。

因此,这次冷启动不能被视为“完全自然的冷启动”。

但这个被污染的实验仍然提供了重要线索:

当 Fcitx5、KWin launcher 和 StatusNotifierWatcher 的相对启动时间发生变化时,最终托盘路径也会发生变化。

在该次启动中,Fcitx5 虽然提前运行,但等 KWin 和 KDE 托盘服务出现后,最终成功注册了原生 SNI。

所以 observer 不是有效的长期方案,却帮助把调查方向收敛到启动顺序竞态

冷启动记录也显示:Fcitx5 最终直接注册了原生 StatusNotifierItem,而不是先进入 XEmbed 后再切换。


七、静态审计:启动顺序究竟由谁决定

接下来不再继续盲目重启,而是对整个启动链进行静态审计。

1. KWin 的输入法入口

KWin 配置中存在类似:

[Wayland]
InputMethod[$e]=/usr/share/applications/fcitx5-wayland-launcher.desktop
VirtualKeyboardEnabled=true

这意味着 KWin 会根据指定的 Desktop 文件启动 Wayland 输入法 launcher。

2. 官方 launcher

Desktop 文件最终执行:

/usr/lib/fcitx5-wayland-launcher --reopen

该程序不是普通的自启动脚本,而是为 Wayland compositor 使用的专用 launcher。

它会读取 KWin 传入的:

  • WAYLAND_DISPLAY
  • WAYLAND_SOCKET
  • Wayland socket 文件描述符;
  • 用户会话环境。

--reopen 的作用,是让 Fcitx5 使用 KWin 提供的 Wayland 连接重新建立输入法前端。

3. Fcitx5 主进程的 D-Bus 激活

系统中还有:

/usr/share/dbus-1/services/org.fcitx.Fcitx5.service

其行为等价于:

[D-BUS Service]
Name=org.fcitx.Fcitx5
Exec=/usr/bin/fcitx5

因此,Fcitx5 主进程不一定由 launcher 直接 fork。

更准确的关系是:

  • 某个组件访问 org.fcitx.Fcitx5
  • 用户 D-Bus 激活 /usr/bin/fcitx5
  • KWin 随后启动 fcitx5-wayland-launcher --reopen
  • launcher 通知现有 Fcitx5 主进程建立正确的 Wayland 输入法连接。

4. StatusNotifierWatcher 的提供者

检查发现:

org.kde.StatusNotifierWatcher

并不是由 plasmashell 直接提供,而是由:

kded6

中的 StatusNotifierWatcher 模块注册。

因此,Watcher 何时可用,取决于:

  • Plasma 用户 systemd target;
  • plasma-kded6.service
  • kded6 模块初始化;
  • D-Bus 名称注册完成时间。

5. 缺失的顺序依赖

systemd 的用户服务定义中,可以找到:

  • KWin 与 Plasma target 的关系;
  • plasmashell 的启动关系;
  • xembedsniproxy 的启动关系;
  • kded6 的启动位置。

但没有任何明确依赖保证:

org.kde.StatusNotifierWatcher 已准备好
    ↓
fcitx5-wayland-launcher 才运行

而 launcher 又是 KWin 直接启动的子进程,并不是一个方便添加 After= 的 systemd unit。

于是,以下事件实际上依赖每次登录时的运行速度:

  • KWin 何时执行 launcher;
  • kded6 何时注册 Watcher;
  • Fcitx5 何时加载 notificationitem
  • Fcitx5 何时建立 Wayland UI;
  • 首次托盘注册时 Watcher 是否已经存在。

审计结果因此给出了高度可信的竞态模型:KWin launcher 与 kded6 提供的 StatusNotifierWatcher 之间没有显式顺序约束。


八、成功路径与故障路径

根据多轮现场数据,可以建立如下模型。

正常路径

KWin 启动
    ↓
StatusNotifierWatcher 已经准备好
    ↓
fcitx5-wayland-launcher 执行 --reopen
    ↓
Fcitx5 建立 Wayland classic UI
    ↓
notificationitem 注册原生 SNI
    ↓
Fcitx5 自己持有托盘项目
    ↓
WindowId=0
    ↓
托盘状态同步正常

故障路径

KWin 提前执行 launcher
    ↓
Fcitx5 开始建立 Wayland UI
    ↓
StatusNotifierWatcher 尚未准备好
    ↓
原生 SNI 首次注册未稳定完成
    ↓
进入 classicui/XEmbed 后备路径
    ↓
xembedsniproxy 代持托盘项目
    ↓
WindowId!=0
    ↓
实际输入正常,但图标更新可能失真

“Watcher 尚未就绪后,Fcitx5 是否缺少可靠重试”没有通过源码级证据完全确认,因此更严谨的表述应是:

原始故障高度可能发生在 Fcitx5 托盘注册时机与 KDE StatusNotifierWatcher 就绪时机之间。

但从工程角度看,已经足以设计一个最小、可逆的顺序修复。


九、为什么没有使用 systemd After=

最理想的方案本来是建立类似:

After=plasma-kded6.service

这样的正式依赖。

问题在于:

  • fcitx5-wayland-launcher 不是独立的 systemd 用户服务;
  • 它是 KWin 直接启动的子进程;
  • KWin 启动输入法 launcher 的行为来自 kwinrc 中的 Desktop 文件;
  • 不能简单给 launcher 添加一个 systemd After=

也不适合把 Fcitx5 改成普通 systemd 自启动服务,因为这可能破坏:

  • KWin 传入的 WAYLAND_SOCKET
  • Wayland input-method 连接;
  • compositor 与输入法之间的文件描述符传递。

因此选择了一个更小的方案:

保留 KWin 为唯一启动者,只在官方 launcher 前增加一个等待条件。


十、最终方案:等待 Watcher 后再执行官方 launcher

正式脚本放在用户自定义脚本目录中。

以下用户名、路径和脚本名均为脱敏示例:

/home/demo/bin/fcitx5-launcher-wait-tray

脚本的核心逻辑如下:

#!/bin/sh
set -eu

watcher='org.kde.StatusNotifierWatcher'
elapsed=0
interval_ms=100
timeout_ms=15000

while [ "$elapsed" -lt "$timeout_ms" ]; do
    result=$(
        busctl --user call \
            org.freedesktop.DBus \
            /org/freedesktop/DBus \
            org.freedesktop.DBus \
            NameHasOwner \
            s "$watcher" 2>/dev/null || true
    )

    case "$result" in
        *"true"*)
            printf '%s\n' "watcher-ready ${elapsed}ms" >&2
            exec /usr/lib/fcitx5-wayland-launcher --reopen
            ;;
    esac

    sleep 0.1
    elapsed=$((elapsed + interval_ms))
done

printf '%s\n' "watcher-timeout ${timeout_ms}ms" >&2
exec /usr/lib/fcitx5-wayland-launcher --reopen

这段脚本有几个重要设计原则。

1. 不直接启动 Fcitx5

脚本没有运行:

/usr/bin/fcitx5

因此不会新增第二条主进程启动入口。

2. 不调用 fcitx5-remote

这样不会通过 D-Bus 提前激活 Fcitx5,也不会重复 observer 的错误。

3. 不直接调用 Watcher 的功能接口

脚本只向 D-Bus 自身询问:

org.kde.StatusNotifierWatcher 是否已经有 owner

也就是 NameHasOwner

这不会主动激活 Watcher,只会判断它是否已经真正注册成功。

4. 不使用固定延迟

没有简单地写:

sleep 1

因为不同启动中,Watcher 的准备时间可能不同。

当前逻辑是:

  • Watcher 一旦就绪,立即继续;
  • 系统快时不浪费时间;
  • 系统慢时多等待一会;
  • 最长只等待有限时间。

5. 超时后仍继续启动

即使 Watcher 因其他故障一直没有出现,15 秒后仍然执行官方 launcher。

这样可以避免托盘服务异常时,输入法本身也被永久阻塞。

6. 使用 exec

最终执行:

exec /usr/lib/fcitx5-wayland-launcher --reopen

exec 会用官方 launcher 替换当前 wrapper 进程。

这样可以保留 KWin 传入的:

  • 环境变量;
  • Wayland socket;
  • 已打开文件描述符;
  • D-Bus 会话地址。

不会额外产生一个后台父进程,也不会绕开 KWin 的官方输入法连接机制。


十一、用户级 Desktop 文件

新的用户级 Desktop 文件放在标准位置:

/home/demo/.local/share/applications/fcitx5-launcher-wait-tray.desktop

内容以系统官方文件为模板,只修改名称和 Exec

[Desktop Entry]
Name=Fcitx 5 Wayland Launcher with Tray Wait
Comment=Wait for KDE StatusNotifierWatcher before launching Fcitx5 Wayland bridge
Exec=/home/demo/bin/fcitx5-launcher-wait-tray
Terminal=false
Type=Application
NoDisplay=true

实际实施时应保留官方 Desktop 文件中的其他兼容字段,不应凭空删减。

随后把 KWin 配置从:

InputMethod[$e]=/usr/share/applications/fcitx5-wayland-launcher.desktop

改为:

InputMethod[$e]=/home/demo/.local/share/applications/fcitx5-launcher-wait-tray.desktop

VirtualKeyboardEnabled=true 保持不变。

修改前先对配置文件进行备份。

示例备份:

/home/demo/.config/kwinrc.20260101-120000

备份时间戳来自原文件时间,而不是备份执行时的当前时间;文件名不使用 .bak


十二、第一次冷启动验证

第一次重启后,日志显示:

watcher-ready 900ms

也就是说,wrapper 实际等待了约 900 毫秒,随后立即 exec 官方 launcher。

机器侧检查确认:

  • KWin 确实调用了用户 wrapper;
  • wrapper 已被官方 launcher 替换;
  • 没有残留第二个包装进程;
  • Wayland 环境变量仍然存在;
  • KWin 传入的 socket 文件描述符仍然保留;
  • waylandim 正常加载;
  • 当前只有一个 Fcitx5 主实例;
  • 没有传统 XDG Autostart 单元;
  • 没有 D-Bus 名称竞争;
  • Fcitx5 托盘项由 Fcitx5 自己持有;
  • WindowId=0
  • 没有由 xembedsniproxy 代理的 Fcitx5 项。

人工检查也全部通过:

  • 文件管理器:输入正常,托盘同步;
  • Chromium 系浏览器:输入正常,托盘同步;
  • Markdown 编辑器:输入正常,托盘同步。

第一次启动的机器侧和人工侧均通过。

当时发现脚本日志中存在一个纯格式错误:

printf %sn ...

导致日志显示:

watcher-ready 900msn

该错误不影响等待逻辑和 exec 行为,但为了避免后续审计歧义,将其修正为:

printf '%s\n' ...

修正前保留了时间戳备份。


十三、第二次冷启动验证

修正日志格式后,再进行一次完全独立的冷启动。

第二次仍然显示:

watcher-ready 900ms

再次确认:

  • KWin 输入法配置仍指向用户 Desktop 文件;
  • wrapper 确实被调用;
  • 官方 launcher 正常完成短生命周期任务后退出;
  • 只有一个 Fcitx5 主实例;
  • waylandim 正常;
  • 没有传统 Autostart;
  • 没有 Unable to request dbus name
  • 没有 Failed to open wayland connection
  • 没有本轮新增的相关崩溃;
  • StatusNotifierWatcher 由 kded6 提供;
  • Fcitx5 自己注册原生 StatusNotifierItem;
  • WindowId=0
  • xembedsniproxy 正常运行,但没有代理 Fcitx5 项目。

三个测试应用再次全部通过。

至此,方案连续两次独立冷启动验证成功。

两次都等待 900 毫秒并不异常。脚本以固定间隔轮询,而 KDE 组件启动时间在同一系统上通常较稳定,所以两次很可能恰好落在同一轮检测上。


十四、完成后的清理

排查过程中创建了不少临时内容,包括:

  • 冷启动 observer;
  • 用户 systemd unit;
  • 全量 D-Bus monitor;
  • pkexec 重启脚本;
  • 环境检查脚本;
  • 临时用户总线日志;
  • 临时 systemd 启用链接。

最终遵循一个原则:

只保留具有实际功能的正式文件和备份;调查结束后删除无功能遗留。

工作站上最终保留:

/home/demo/bin/fcitx5-launcher-wait-tray
/home/demo/.local/share/applications/fcitx5-launcher-wait-tray.desktop
/home/demo/.config/kwinrc
/home/demo/.config/autostart/org.fcitx.Fcitx5.desktop

以及脚本和 kwinrc 的时间戳备份。

删除:

  • 冷启动 observer unit;
  • observer 启用残留;
  • 全量 monitor 进程;
  • 临时 pkexec 文件;
  • 一次性环境检查脚本。

完整取证目录被转移到另一台服务机的审计输出目录中保存。

其中约 1.9 GB 的原始 D-Bus 日志压缩后只有约 3.8 MB,因此完整保留并不会造成明显空间负担。


十五、最终结论:这是两层修复,而不是一次修复

整个问题最终包含两个相互独立、但彼此关联的层次。

第一层:解决双启动

使用用户级同名 XDG Autostart 覆盖:

Hidden=true

目的:

  • 禁止传统 Autostart 启动 Fcitx5;
  • 只保留 KWin Wayland Input Method 路径;
  • 消除第二实例和 D-Bus 名称竞争。

这一项修复一直是正确的,也必须继续保留。

第二层:解决托盘注册时序竞态

通过用户 wrapper:

等待 org.kde.StatusNotifierWatcher 有 owner
    ↓
exec 官方 fcitx5-wayland-launcher --reopen

目的:

  • 保持 KWin 为唯一 launcher 调用者;
  • 保留 KWin 传递的 Wayland socket;
  • 确保关键重连动作发生时 KDE 托盘服务已准备好;
  • 稳定走 Fcitx5 原生 StatusNotifierItem;
  • 避免落入可能状态不同步的 XEmbed 代理路径。

因此,此前那篇文章并没有错。

更准确的评价是:

Hidden=true 完整解决了 Fcitx5 双启动问题,但没有完整解决 Fcitx5 在 Plasma Wayland 登录过程中的所有初始化竞态。

最初看到输入恢复正常后,很容易把“双启动”和“托盘初始化”视为同一问题。后来出现“输入正常、图标存在、状态却不同步”,才证明托盘注册还有独立的时序问题。

现在两部分分别得到处理:

Hidden=true
    → 保证只有一个 Fcitx5 主实例

等待 StatusNotifierWatcher
    → 保证官方 Wayland launcher 在正确时机运行

两者结合后,连续两次冷启动均表现正常:

  • 单一 Fcitx5 主实例;
  • Wayland 输入上下文正常;
  • 原生 SNI;
  • WindowId=0
  • 多个应用输入正常;
  • 托盘图标切换同步。

十六、这次排查带来的经验

1. “输入正常”不代表“输入法整体正常”

输入处理、候选框和托盘图标可能属于不同链路。

2. 同一个程序可能同时使用现代和兼容机制

Fcitx5 可以直接注册原生 SNI,也可能落入 XEmbed 后备路径。

3. Wayland 会话不等于可以禁用所有 X11 兼容组件

XWayland 和旧式托盘应用仍然可能依赖 xembedsniproxy

4. 重启后恢复通常意味着初始化状态被重建

它不是永久修复,但可以用来寻找分叉点。

5. 监控脚本也可能改变被监控对象

调用 D-Bus 客户端命令可能触发服务激活。所谓“只读查询”不一定真的是旁路观察。

6. 固定 sleep 通常不是理想的竞态修复

等待明确条件比等待固定秒数可靠。

7. 最小修复应尽量保留官方启动链

没有直接运行第二个 Fcitx5,而是继续让 KWin 调用官方 launcher,只补上缺失的就绪条件。

8. 验证至少要包含两次独立冷启动

一次成功只能证明“可以成功”;连续独立重启更能说明顺序控制确实稳定。

9. 排查结束后必须清理临时产物

临时 unit、监控脚本和一次性重启文件不应长期留在系统中。


结语

这次故障表面上只是“输入法图标不跟着切换”,实际涉及:

  • KWin Wayland Input Method;
  • Fcitx5 D-Bus 激活;
  • Wayland socket 传递;
  • kded6;
  • StatusNotifierWatcher;
  • 原生 StatusNotifierItem;
  • XEmbed;
  • xembedsniproxy;
  • systemd 用户会话;
  • XDG Autostart;
  • 启动时序竞态。

最终没有采用粗暴的“登录后重启 Fcitx5”,也没有通过禁用兼容组件掩盖问题,而是在保留 KDE 官方输入法启动链的前提下,只补充了一个缺失的条件:

系统托盘服务真正就绪之后,才让 KWin 的官方 Fcitx5 Wayland launcher继续执行。

这是一种非常小的改动,却解决了一个长期、间歇、难以复现的桌面初始化问题。

Leave a Reply

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