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

如何通过XCursor和XInput2修改全系统所有窗口的鼠标光标?

全系统鼠标光标修改方案

你的代码仅能修改浏览器窗口光标,核心问题在于只在鼠标移动时触发光标设置,且未处理窗口切换、新窗口创建等场景,以下是修正方案:

问题根源

  • 仅监听XI_RawMotion事件,窗口切换、新窗口打开时不会触发光标更新
  • 部分应用会自行设置窗口光标,覆盖你的修改
  • XTranslateCoordinates的使用逻辑冗余,XQueryPointer已经能直接获取光标下方的子窗口

修正后的代码

#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
#include <X11/Xcursor/Xcursor.h>

// 补充光标创建函数的实现
void CreateCursor(const char* path, Cursor& cursor, Display* display) {
    cursor = XcursorLibraryLoadCursor(display, path);
    if (!cursor) {
        // 加载失败时用系统默认光标兜底
        cursor = XCreateFontCursor(display, XC_left_ptr);
    }
}

int main(int argc, char **argv)
{
    Display *display = XOpenDisplay(0);
    if (!display) return 1;
    int screen = DefaultScreen(display);
    Window root_window = RootWindow(display, screen);

    Cursor cursorDefault;
    CreateCursor("1.png", cursorDefault, display);

    // 1. 监听XInput2关键事件:鼠标移动、鼠标进入窗口
    unsigned char xi_mask[(XI_LASTEVENT + 7)/8] = {0};
    XISetMask(xi_mask, XI_RawMotion);
    XISetMask(xi_mask, XI_Enter);

    XIEventMask evmasks[1] = {
        {XIAllMasterDevices, sizeof(xi_mask), xi_mask}
    };
    XISelectEvents(display, root_window, evmasks, 1);

    // 2. 监听X核心事件:新窗口创建、鼠标进入窗口
    XSelectInput(display, root_window, SubstructureNotifyMask | EnterWindowMask);

    XEvent xevent;
    while (1)
    {
        XNextEvent(display, &xevent);

        // 处理XInput2通用事件
        if (xevent.type == GenericEvent && xevent.xcookie.extension == XInputDisplay(display)) {
            XGetEventData(display, &xevent.xcookie);
            XFreeEventData(display, &xevent.xcookie);
        }

        // 获取当前光标下方的窗口
        Window root_return, child_return;
        int root_x, root_y, win_x, win_y;
        unsigned int mask;
        XQueryPointer(display, root_window, &root_return, &child_return,
                      &root_x, &root_y, &win_x, &win_y, &mask);

        // 给当前窗口和根窗口设置光标
        if (child_return) {
            XDefineCursor(display, child_return, cursorDefault);
        }
        XDefineCursor(display, root_window, cursorDefault);

        // 新窗口创建时自动设置光标
        if (xevent.type == CreateNotify) {
            XDefineCursor(display, xevent.xcreatewindow.window, cursorDefault);
        }
    }

    XCloseDisplay(display);
    return 0;
}

关键改进点

  • 扩展事件监听:新增XI_Enter(鼠标进入窗口)、CreateNotify(新窗口创建)事件,确保窗口切换和新窗口打开时都能触发光标更新
  • 根窗口兜底设置:直接给根窗口设置自定义光标,当没有子窗口覆盖时生效
  • 简化窗口获取逻辑:直接使用XQueryPointer返回的child_return作为目标窗口,无需额外调用XTranslateCoordinates
  • 强制覆盖应用光标:通过事件触发时重复设置光标,覆盖部分应用自行设置的光标样式

内容的提问来源于stack exchange,提问作者XoDefender

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 12:35:22