如何在 X11/Xorg 中隐藏鼠标光标

How to hide the mouse cursor in X11/Xorg

为什么下面的X11/Xorg代码在Ubuntu18.04下不隐藏鼠标光标?如果这不是这样做的方法,那是什么?是否缺少一些 dependency/library/.dev 包?

我的直觉告诉我这可能是 Ubuntu(或 Debian)X11/Xorg 软件包或类似软件包中的错误。这就是 Haxe/Kha 为了跨平台兼容而隐藏鼠标的方式。

#include <iostream>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>

#include <string>
#include <iostream>

Window window;
void show();

int main()
{
    Display *display;
    XEvent e;
    std::string msg = "Hello, World!";
    int screen;

    display = XOpenDisplay(nullptr);
    if (display == nullptr)
    {
        std::cerr << "Cannot open display\n";
        throw;
    }

    screen = XDefaultScreen(display);
    window = XCreateSimpleWindow(display, RootWindow(display, screen), 10, 10, 500, 500, 1,
                                 BlackPixel(display, screen), WhitePixel(display, screen));
    XStoreName(display, window, "Silly Window");
    XSelectInput(display, window, ExposureMask | KeyPressMask );
    XMapWindow(display, window);

    while (true)
    {
        XNextEvent(display, &e);
        if (e.type == Expose)
        {
            std::cout << "Window Exposed!\n";
            XExposeEvent ev = e.xexpose;
            if (ev.window != window) continue;
            XFillRectangle(display, window, DefaultGC(display, screen), 50, 50, 400, 50);
            XDrawString(display, window, DefaultGC(display, screen), 220, 220, msg.c_str(), msg.length());
            XFillRectangle(display, window, DefaultGC(display, screen), 50, 400, 400, 50);
        }
        else if (e.type == KeyPress)
        {
            char buf[128] = {0};
            KeySym keysym;
            int len = XLookupString(&e.xkey, buf, sizeof buf, &keysym, NULL);
            if (keysym == XK_Escape)
            {
                break;
            }
            else if (keysym == XK_space)
            {
                show();
                XAllowEvents(display, SyncBoth, CurrentTime);
            }
        }

    }

    XDestroyWindow(display, window);
    XCloseDisplay(display);
    return 0;
}

bool toggle = false;
void show()
{
    Display* dpy = XOpenDisplay(0);
    if (toggle)
    {
        std::cout << "toggle On\n";
        XUndefineCursor(dpy, window);
    }
    else
    {
        std::cout << "toggle Off\n";
        XColor col;
        char data[1] = {0X00};
        Pixmap blank = XCreateBitmapFromData(dpy, window, data, 1, 1);
        Cursor cursor = XCreatePixmapCursor(dpy, blank, blank, &col, &col, 0, 0);
        XDefineCursor(dpy, window, cursor);
        // XSetWindowAttributes wa;
        // XChangeWindowAttributes(dpy, window, CWCursor, &wa);
        // wa.cursor = cursor;
        XFreePixmap(dpy, blank);
    }
    toggle = !toggle;
}

是的,我可以确认代码确实有效

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xfixes.h>
#include <string>
#include <iostream>

Window window;
void show(Display *dispy);

int main()
{
    Display *display;
    XEvent e;
    std::string msg = "Hello, World!";
    int screen;

    display = XOpenDisplay(nullptr);
    if (display == nullptr)
    {
        std::cerr << "Cannot open display\n";
        throw;
    }

    screen = XDefaultScreen(display);
    window = XCreateSimpleWindow(display, RootWindow(display, screen), 10, 10, 500, 500, 1,
                                 BlackPixel(display, screen), WhitePixel(display, screen));
    XStoreName(display, window, "Silly Window");
    XSelectInput(display, window, ExposureMask | KeyPressMask );
    XMapWindow(display, window);

    while (true)
    {
        XNextEvent(display, &e);
        if (e.type == Expose)
        {
            std::cout << "Window Exposed!\n";
            XExposeEvent ev = e.xexpose;
            if (ev.window != window) continue;
            XFillRectangle(display, window, DefaultGC(display, screen), 50, 50, 400, 50);
            XDrawString(display, window, DefaultGC(display, screen), 220, 150, msg.c_str(), msg.length());
            XDrawString(display, window, DefaultGC(display, screen), 220, 220, msg.c_str(), msg.length());
            XDrawString(display, window, DefaultGC(display, screen), 220, 300, msg.c_str(), msg.length());
            XFillRectangle(display, window, DefaultGC(display, screen), 50, 400, 400, 50);
        }
        else if (e.type == KeyPress)
        {
            char buf[128] = {0};
            KeySym keysym;
            XLookupString(&e.xkey, buf, sizeof buf, &keysym, NULL);
            if (keysym == XK_Escape)
            {
                break;
            }
            else if (keysym == XK_space)
            {
                show(display);
                XAllowEvents(display, SyncBoth, CurrentTime);
            }
        }

    }

    XDestroyWindow(display, window);
    XCloseDisplay(display);
    return 0;
}

bool toggle = true;
void show(Display *dpy)
{
    if (toggle)
    {
        std::cout << "toggle On->Off\n";
        XFixesHideCursor(dpy, window);
        XFlush(dpy);
    }
    else
    {
        std::cout << "toggle Off->On\n";
        XFixesShowCursor(dpy, window);
        XFlush(dpy);
    }
    toggle = !toggle;
}