X11:改进运行时动态切换光标 上下文问题尝试修复结论更多信息

问题描述

上下文

我正在根据鼠标是否插入我的 Linux 系统来切换鼠标光标的存在。我已经创建了一个有效的解决方案,尽管不是最佳选择。我目前的解决方案如下:

  1. 修改后的 WM:我扩展了随 WM 一起提供的程序 matchBox-remote.c(参见原始 source here),以允许实时更改光标的远程命令。我的更改基于对类似问题的 this SO answer
  2. udev 规则:我添加了两个 udev 规则,在插入或拔出鼠标时调用 matchBox-remote,并带有我的切换参数。
  3. Systemd 服务:我添加oneshot systemd 服务,可在启动时启用或禁用光标(取决于是否插入鼠标)。这解决udev 规则首次运行时 X 尚未准备好的边缘情况。

如果你想看看我是如何完成每一步的,请移到底部,我用相关文件对部分进行了编号


问题

我的解决方案有效,但不是最佳的,原因有两个:

  1. 如果没有插入鼠标,则在桌面加载后,鼠标光标会在屏幕上显示几秒钟,因为 systemd 规则在 multi-user.target 之后运行。
  2. 鼠标光标有时在被禁用后仍会出现在屏幕上。一旦我与按钮或其他 UI 元素交互,它就会消失。但是,这可能很烦人。

尝试修复

我尝试执行以下操作来改进我的解决方案:

  1. 减少启动延迟:我尝试调整我的服务文件以在启动过程中更早启动。我专门针对它在 xserver-nodm.service 之后开始。但是,尽管我手动将其设置为环境变量,但仍然无法找到 disPLAY
  2. 在事件发生时消失鼠标指针:我尝试重新启动 WM,希望这样可以更无缝地使光标在应该消失时消失。不幸的是,这是一种倒退的解决方案,因为它会使屏幕变黑几秒钟并且更具破坏性。

结论

我想帮助解决以下问题:

  1. 如何在启动时及时更改光标(我是否需要修改 X 服务器或以某种方式将事件排入队列以在到达时发送?)
  2. 如何确保对光标的更改立即反映(而不是有时等到我与 UI 元素交互)?

更多信息

  • 内核:Linux 5.4.3
  • Xorg:版本 1.20.5

(1)matchBox-remote.c(在 /usr/bin/ 中)

display *dpy;
...
#include <X11/cursorfont.h>
#include <X11/extensions/Xfixes.h>
...
void set_show_cursor (int show)
{
    Window root;
    Cursor cursor;
    pixmap bitmap;
    XColor color;
    static char data[8] = {0};

    root = DefaultRootwindow(dpy);
    if (!show) {
        color.red = color.green = color.blue = 0;
        bitmap = xCreateBitmapFromData(dpy,root,data,8,8);
        cursor = XCreatepixmapCursor(dpy,bitmap,&color,0);
        XDefineCursor(dpy,cursor);
        XFreeCursor(dpy,cursor);
        XFreepixmap(dpy,bitmap);
    } else {
        cursor = XCreateFontCursor(dpy,XC_left_ptr);
        XDefineCursor(dpy,cursor);
    }
}
...
static void usage(char *progname) {
    ...
    printf("  -show-cursor [1|0]    Enable or disable the cursor\n");
    ...
}
...
int main (int argc,char* argv[])
{
    ...
    for (i=1; argv[i]; i++) {
        ...
        switch (arg[1])
        {
            ....
            case 's':
            if (NULL != argv[i+1]) {
                set_show_cursor(atoi(argv[i+1]));
            }
            break;
            ...
        }
    }
    XSync(dpy,False);
    XClosedisplay(dpy);
}

(2)98-cursor-toggle.rules(在 /etc/udev/rules.d 中)

SUBSYstemS="usb",ACTION=="add",ENV{ID_INPUT_MOUSE}=="1",RUN+="/bin/sh -c 'disPLAY=:0 /usr/bin/matchBox-remote -show-cursor 1'"
SUBSYstemS="usb",ACTION=="remove",RUN+="/bin/sh -c 'disPLAY=:0 /usr/bin/matchBox-remote -show-cursor 0'"

(3) cursor-init.service(在 /lib/systemd/system 中)

[Unit]
Description=X11 cursor initialisation
After=multi-user.target
Requires=multi-user.target

[Service]
Type=simple
ExecStart=/bin/sh -c 'disPLAY=:0 /usr/bin/matchBox-remote -show-cursor $(ls -1 /dev/input/by-*/*-mouse 2>/dev/null | wc -l)'
RemainAfterExit=true
StandardOutput=journal
Restart=on-failure
RestartUSec=500000

[Install]
WantedBy=graphical.target

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)