KDE Wayland下如何通过Python获取鼠标所在的当前活动屏幕
KDE Wayland 下检测鼠标所在活动屏幕的实现方案
核心差异说明
Wayland 协议出于安全沙箱设计,不允许普通客户端直接查询全局鼠标指针坐标、也不对外暴露多显示器的全局布局坐标,你之前基于Xlib的X11实现逻辑无法直接在Wayland下运行。
Wayland没有全局统一的跨合成器API来实现这个功能,不同桌面的实现接口不通用。在KDE Plasma的Wayland会话中,最稳定无兼容问题的方案是调用KWin(Plasma的窗口合成器)暴露的DBus接口获取数据——KWin本身运行在会话最高权限层,有权限访问鼠标位置、显示器布局信息,不需要额外安装第三方工具,也不需要给脚本提权。
依赖准备
只需要安装Python的DBus绑定,绝大多数Plasma发行版默认已经预装:
- Debian/Ubuntu 系:
sudo apt install python3-dbus - Arch 系:
sudo pacman -S python-dbus - Fedora 系:
sudo dnf install python3-dbus
实现代码
import dbus import uuid import time def get_active_screen_with_cursor(): # 连接到会话DBus bus = dbus.SessionBus() scripting_proxy = bus.get_object("org.kde.KWin", "/Scripting") scripting_iface = dbus.Interface(scripting_proxy, "org.kde.KWin.Scripting") # 临时KWin脚本:读取鼠标位置、匹配所在屏幕,通过DBus返回结果 script_content = """ const cursorPos = workspace.cursorPos(); let targetScreen = null; const screenCount = workspace.numScreens; for (let i = 0; i < screenCount; i++) { const geo = workspace.screenGeometry(i); const screenName = workspace.screenName(i); if (cursorPos.x >= geo.x && cursorPos.x <= geo.x + geo.width && cursorPos.y >= geo.y && cursorPos.y <= geo.y + geo.height) { targetScreen = screenName; break; } } callDBus("org.kde.KWin", "/ActiveScreenResult", "local.ActiveScreen", "Result", targetScreen); """ # 生成唯一脚本ID避免冲突 script_id = str(uuid.uuid4()) result = [] # 注册信号接收器接收脚本返回结果 def handle_response(screen_name): result.append(str(screen_name)) bus.add_signal_receiver( handle_response, dbus_interface="local.ActiveScreen", signal_name="Result", path="/ActiveScreenResult" ) # 加载运行临时脚本 scripting_iface.loadScript(script_content, script_id) script_proxy = bus.get_object("org.kde.KWin", f"/Scripting/Script/{script_id}") script_iface = dbus.Interface(script_proxy, "org.kde.KWin.Script") script_iface.run() # 等待结果返回,超时时间1秒 timeout = 1 start = time.time() while not result and time.time() - start < timeout: pass # 清理临时脚本,无残留 script_iface.stop() scripting_iface.unloadScript(script_id) if not result: raise RuntimeError("无法获取活动屏幕信息,请确认当前运行在KDE Wayland会话下") return result[0] if __name__ == "__main__": active_screen = get_active_screen_with_cursor() print(f"当前鼠标所在屏幕: {active_screen}")
可选迁移方案
如果你想尽可能复用原有X11版本的判断逻辑,可以拆分两步实现,坐标匹配部分的代码不需要修改:
- 第一步:通过KScreen的DBus接口(
org.kde.KScreen)获取所有显示器的名称、位置、尺寸参数,和你之前X11下遍历output拿到的数据结构完全一致。 - 第二步:通过KWin的DBus属性读取
org.kde.KWin /Cursor org.kde.KWin.Cursor.pos属性拿到鼠标全局坐标,再用你之前写的坐标范围判断逻辑,就能得到鼠标所属的屏幕。
注意:直接读取Cursor坐标的接口在Plasma 5.25之后版本才稳定可用,低版本Plasma建议用上面的临时脚本方案,兼容性更好。
内容的提问来源于stack exchange,提问作者Ashark
相关产品推荐
相关产品推荐

