GNOME/Wayland会话中从Mutter获取活动窗口的技术疑问
嘿,我之前也折腾过Wayland下这种按应用响应手势的需求,确实踩过焦点检测的坑,给你几个实际可行的方向:
Wayland下活动应用焦点检测的解决方案
Wayland本身确实没有像X11那样统一的全局焦点查询接口,因为每个**compositor(窗口管理器)**都有自己的实现逻辑,所以得针对不同的桌面环境做适配:
1. 调用各Compositor专属的DBus接口
主流Wayland compositor都会暴露自己的DBus服务来提供窗口信息,这是最直接的方式:
- GNOME Shell:通过
org.gnome.Shell接口的GetFocusedWindow方法获取焦点窗口,你可以用gdbus先测试:
返回结果里包含窗口对应的应用ID(比如gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell --method org.gnome.Shell.GetFocusedWindoworg.gnome.Nautilus),解析这个就能判断当前活动应用。 - KDE Plasma:借助
org.kde.KWin的接口,先查活动窗口ID,再关联应用信息:# 获取活动窗口ID ACTIVE_WIN=$(qdbus org.kde.KWin /KWin activeWindow) # 查询窗口对应的应用类名 qdbus org.kde.KWin /KWin/window/$ACTIVE_WIN className - Sway/i3(wlroots系):用
swaymsg配合jq解析窗口树,直接拿到焦点应用的标识:swaymsg -t get_tree | jq 'recurse(.nodes[]?, .floating_nodes[]?) | select(.focused==true) | .app_id // .class'
2. 写轻量监听程序订阅焦点事件
如果需要实时监听焦点变化(而不是每次手势触发才查询),可以基于libwayland-client写一个简单的程序,订阅 compositor 的焦点变更事件。不过要注意:
- wlroots系 compositor(比如Sway、Hyprland)遵循标准的Wayland协议,通过
wl_seat接口的focus_in事件获取焦点窗口 - GNOME/KDE有自己的扩展接口,比如GNOME需要对接Shell的窗口跟踪API
3. 结合libinput-gestures的配置技巧
其实不用单独写一个完整的应用,你可以把焦点检测逻辑封装成脚本,直接嵌入到libinput-gestures的配置里:
- 写一个脚本
get_active_app.sh,根据当前运行的compositor返回活动应用ID:#!/bin/bash if pgrep -x "gnome-shell" > /dev/null; then # GNOME下获取应用ID gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell --method org.gnome.Shell.GetFocusedWindow | grep -oP "'app-id': '\K[^']+" elif pgrep -x "sway" > /dev/null; then # Sway下获取应用ID swaymsg -t get_tree | jq -r 'recurse(.nodes[]?, .floating_nodes[]?) | select(.focused==true) | .app_id // .class' fi - 在
libinput-gestures.conf里配置手势,根据脚本返回值发送不同DBus信号:# 针对不同应用发送不同DBus信号 gesture swipe right 3 bash -c 'APP=$(./get_active_app.sh); if [ "$APP" = "org.gnome.Terminal" ]; then dbus-send --session --dest org.gnome.Terminal --object-path /org/gnome/Terminal/org/gnome/Terminal/Window/1 --method org.gnome.Terminal.Window.NextTab; else dbus-send ...; fi'
小提示
- Wayland的安全模型会限制全局窗口信息的获取,比如GNOME下你的脚本/应用可能需要申请
org.gnome.shell.permissions.desktop权限才能调用Shell接口 - 如果要做跨桌面环境兼容,记得先检测当前运行的compositor类型,再调用对应的接口
内容的提问来源于stack exchange,提问作者Petrosyan Alexander




