如何解决X11:改进运行时动态切换光标 上下文问题尝试修复结论更多信息
上下文
我正在根据鼠标是否插入我的 Linux 系统来切换鼠标光标的存在。我已经创建了一个有效的解决方案,尽管不是最佳选择。我目前的解决方案如下:
-
修改后的 WM:我扩展了随 WM 一起提供的程序
matchBox-remote.c
(参见原始 source here),以允许实时更改光标的远程命令。我的更改基于对类似问题的 this SO answer。 -
udev 规则:我添加了两个
udev
规则,在插入或拔出鼠标时调用matchBox-remote
,并带有我的切换参数。 -
Systemd 服务:我添加了
oneshot
systemd 服务,可在启动时启用或禁用光标(取决于是否插入鼠标)。这解决了udev
规则首次运行时 X 尚未准备好的边缘情况。
如果你想看看我是如何完成每一步的,请移到底部,我用相关文件对部分进行了编号
问题
我的解决方案有效,但不是最佳的,原因有两个:
- 如果没有插入鼠标,则在桌面加载后,鼠标光标会在屏幕上显示几秒钟,因为 systemd 规则在
multi-user.target
之后运行。 - 鼠标光标有时在被禁用后仍会出现在屏幕上。一旦我与按钮或其他 UI 元素交互,它就会消失。但是,这可能很烦人。
尝试修复
我尝试执行以下操作来改进我的解决方案:
-
减少启动延迟:我尝试调整我的服务文件以在启动过程中更早启动。我专门针对它在
xserver-nodm.service
之后开始。但是,尽管我手动将其设置为环境变量,但仍然无法找到disPLAY
。 - 在事件发生时消失鼠标指针:我尝试重新启动 WM,希望这样可以更无缝地使光标在应该消失时消失。不幸的是,这是一种倒退的解决方案,因为它会使屏幕变黑几秒钟并且更具破坏性。
结论
我想帮助解决以下问题:
- 如何在启动时及时更改光标(我是否需要修改 X 服务器或以某种方式将事件排入队列以在到达时发送?)
- 如何确保对光标的更改立即反映(而不是有时等到我与 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 举报,一经查实,本站将立刻删除。