You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 10:42:21