Hotdry.
systems-engineering

Wayland协议碎片化:xdotool跨合成器实验剖析输入模拟兼容诊断与桥接路径

基于xdotool作者实验,揭示Wayland合成器碎片对输入模拟的影响,提供跨compositor诊断清单、libei/XDG桥接参数与uinput回退策略。

Wayland 作为 X11 继任者,本意简化协议以提升安全与性能,但其最小主义设计导致协议扩展碎片化,严重影响如 xdotool 般的输入模拟与窗口管理工具兼容。xdotool 依赖 X11 的 XTest 扩展、EWMH 规范实现键盘鼠标注入与窗口操作,在 Wayland 下这些核心功能被 “安全” 理由移除,转而依赖 compositor-specific 扩展或 Xwayland 桥接。本文从 xdotool 维护者 Jordan Sissel 的亲身实验切入,剖析 GNOME、KDE、wlroots 等主流合成器差异,提炼诊断方法、兼容阈值与工程桥接路径,帮助开发者快速定位问题并落地方案。

Wayland 碎片化根源:协议最小主义 vs. 实际需求缺口

Wayland 核心协议仅定义表面缓冲区共享与基本输入路由,摒弃 X11 的全局查询(如窗口枚举)与合成扩展(如 XTest),以避免 “网络透明” 遗留安全隐患。结果是输入模拟需依赖扩展协议:text-input-v3 用于文本注入、virtual-keyboard-unstable-v1 模拟键码、kde-fake-input 专属 KDE,甚至 libei(Emulated Input)作为新兴通用层。但这些扩展采用率不一,GNOME 偏好 XDG Portal,KDE 用 DBus JS 桥接,wlroots 类支持 wlr-layer-shell 等,导致单一工具难以跨 compositor 通用。

Jordan Sissel 在 2025 年 11 月博客中记录 xdotool “冒险”:在 X11 上,xdotool 无痛支持任意 WM;在 Wayland,GNOME 需 Xwayland+XTest 却弹出 “Allow remote interaction” 提示,KDE 报 “Remote control requested”,wlroots 需额外协议支持。窗口管理更乱:无统一 EWMH 等价物,GNOME 靠 Shell 扩展 + DBus,KDE 有 kdotool,Sway/Hyprland 用 wlrctl。此碎片源于 Wayland 无中央规范,compositor 各自为政,十年后仍无统一输入 / 窗口 API。

证据显见于实验:Sissel 测试 Xwayland XTest 注入键鼠事件,链路为 X11 客户端→Xwayland→XDG RemoteDesktop Portal→DBus 信号→libei FD→libxkbcommon 键图解析。此 Rube-Goldberg 路径虽绕过 “安全禁令”,但引入异步 DBus 与反复提示,生产环境不可靠。uinput 内核模块可绕过 compositor 直发键码 / 指针事件,但需 root 且键码转符号依赖本地映射,跨布局复杂。

诊断方法:快速定位 compositor 与协议支持

诊断前确认环境:echo $XDG_SESSION_TYPE输出 "wayland" 即 Wayland 会话;loginctl show-session $(loginctl | grep $(whoami) | awk '{print $1}') -p Type验证类型。核心命令:

  1. 合成器识别

    WAYLAND_DISPLAY=wayland-0 weston-info  # 输出支持协议列表
    # 或 GNOME: gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell --method org.gnome.Shell.Eval "global.get_window_actors().map(w => w.meta_window.get_title()).join('\n')"
    # KDE: qdbus org.kde.KWin /KWin org.kde.KWin.loadWindowRules  # 检查DBus可用
    

    阈值:若 weston-info 无 text-input-v3/libei,降级 Xwayland 测试。

  2. Xwayland 兼容测试

    xdotool key "ctrl+alt+t"  # 预期:打开终端。若提示“remote interaction”,GNOME/KDE均需Portal授权
    WAYLAND_DEBUG=1 xdotool type "test" 2>&1 | grep -i "portal\|libei"  # 捕获桥接日志
    

    风险阈值:提示 > 3 次 / 分钟,回滚 X11(sudo apt install xserver-xorg)。

  3. 协议支持扫描

    wayland-info | grep -E "text-input|virtual-keyboard|foreign-toplevel|fake-input"
    
    • GNOME/Mutter:支持 xdg-desktop-portal-remote-desktop。
    • KDE/KWin:org_kde_kwin_fake_input。
    • wlroots:wlr-foreign-toplevel-management-unstable-v1。
  4. uinput 基线验证(rootless 需 input 组):

    sudo usermod -aG input $USER; sudo tee /etc/udev/rules.d/99-uinput.rules <<< 'KERNEL=="uinput", GROUP="input", MODE="0660"'
    ydotool key 30:1 30:0  # 键码30=A,按下/释放。若注入成功,uinput可用
    

诊断清单(<5min 完成):

检查点 命令 预期 异常处理
会话类型 $XDG_SESSION_TYPE wayland 切换 X11
合成器 weston-info 协议列表 查 compositor docs
Xwayland 注入 xdotool key ctrl+c 无提示注入 Portal 授权 /libei
协议扩展 wayland-info text-input-v3+ uinput/wtype 回退
键图一致 xkbcli interactive-wayland 键码→符号 libxkbcommon 验证

兼容桥接工程路径:参数化落地方案

桥接分层:优先 Xwayland+libei(零改动),次选 compositor 扩展,最后 uinput。

  1. Xwayland+libei 桥接(GNOME/KDE 通用)

    • 安装:apt install libei-dev libxkbcommon-dev xdg-desktop-portal-gtk
    • 参数:Portal 会话超时 5s,libei FD reuse 阈值 10,避免反复提示。
    • 代码骨架(C):
      #include <libei.h>
      struct ei_device *dev = ei_device_create(...);
      ei_device_key_press(dev, KEY_A, ...);  // 键码注入
      
      监控:journalctl -f -u xdg-desktop-portal观察信号延迟 < 100ms。
  2. Compositor-specific

    • GNOME:启用 Shell Eval DBus(gsettings set org.gnome.mutter experimental-features "['shell-eval']"),用 Focused Window D-Bus 扩展移动窗口。
    • KDE:kdotool search --name "Firefox" windowactivate,阈值:响应 < 200ms。
    • wlroots:wlrctl toplevel move <wid> 100 100,需启 wlr-foreign-toplevel-management。
  3. Uinput 回退(通用,rootless)

    • ydotool/wtype:ydotool type "hello";wtype 参数:-s 50键间延时 50ms。
    • 键图参数:用 xkbcommon 解析/usr/share/X11/xkb/keymap,阈值:映射准确率 > 95%。
    • 清单:添加 input 组,重载 udev,守护进程systemd-run ydotoold

回滚策略:若桥接失败率 > 20%,fallback X11(Ubuntu: sudo nano /etc/gdm3/custom.conf注释 WaylandEnable=false)。生产阈值:注入延迟 < 50ms,成功率 99%。

风险与监控要点

碎片风险:GNOME Portal 提示无限循环(无永久授权);KDE DBus JS 沙箱逃逸。监控:Prometheus 指标wayland_inject_latency_secondsprompt_count。参数调优:libei 缓冲 5 事件,uinput 轮询率 1000Hz。

前瞻:Wayland 若统一 libei+foreign-toplevel-v1,xdotool 复活可期。但当前,工程路径须 compositor-aware 脚本(如 detect via weston-info)。

资料来源:

(正文约 1250 字)

查看归档