在Linux/X11下如何隐藏鼠标指针?

37

如何在X11下隐藏鼠标指针?我想使用内置库来完成这个功能,而不是像SDL(SDL_ShowCursor(0))或glut(glutSetCursor(GLUT_CURSOR_NONE))那样的东西。另外,无论指针位置在哪里,鼠标指针都应该被隐藏,而不仅仅是在它自己的窗口中。

11个回答

36

以下是 描述 如何实现unclutter 实用程序的内容。

Unclutter 是一个在 X11 会话的后台永久运行的程序。它每隔几秒钟检查一次 X11 指针 (光标) 的位置,当它发现它没有移动(且鼠标上没有按下按钮,且光标不在根窗口中)时,它会创建一个小型子窗口,作为指针所在窗口的子级。 新窗口安装了大小为1x1但掩码为全部0的光标,即一个透明光标。这样您就可以看到 xterm 或 xedit 中的所有文本,例如。人因素群体会认为这应该使事情变得不那么分散注意力。

一旦创建,程序等待指针离开窗口,然后销毁它,恢复原始状态。按钮事件会透明地传递到父窗口。它们通常会导致光标重新出现,因为当按钮按下时,程序会进行活动抓取,因此指针将显然离开窗口,即使其xy位置不改变。


2
现在我也知道为什么Unclutter会如此严重地干扰我的加速窗口了。 我相信mplayer不喜欢那样的子窗口。 - Aktau

25

使用此选项将无法使用带有鼠标驱动器的触摸屏 (如 qemu、mastertouch 等)! - eri

21

我宁愿使用更简单的方法:

unclutter -idle 0

您几乎看不见光标,但它仍然可用。要禁用鼠标:

rmmod psmouse

或者在/etc/某处永久禁用鼠标模块。请查看您的发行版手册。


2
使用Unclutter,您可以将-jitter标志设置为较高的值,然后您将完全看不到鼠标,并且您无需频繁轮询。 - charlie_pl

20

一个替代Unclutter的工具

Unclutter 对于我来说不起作用,因为它不能很好地与硬件加速表面兼容(例如,当解码视频时由英特尔的VA-API产生的那些)。因此,我找到了一个以更简单的方式隐藏鼠标指针的程序hhp,并使用最少的依赖项将其重写为C语言,结果是hhpc。 我这样做是为了避免需要安装Haskell才能编译它,并且因为hhp有时会停止隐藏鼠标指针。

hhpc仅依赖于glibcxlib,因此很容易构建,只需执行make release即可。您可以从我的代码库获取代码和说明。它非常节省内存和CPU资源(因为几乎不执行任何操作)。


1
嗨,Aktau,你能否修改你的hhpc程序,在键盘事件发生时立即隐藏鼠标指针而不是计时器?那将非常有用。 - Ray
1
@Iiridayn 非常感谢!我寻找这种功能已经好几年了!看起来很有效。 - Ray

15

我最终使用了ephemient提到的XDefineCursor。控制应用程序更改了默认根窗口光标,而其他应用程序(在我的控制下)则继承了它。

代码具体细节如下:

// Hide the cursor

if (NULL==(display=XOpenDisplay(NULL))) 
{
   printf("Unable to open NULL display\n");
   exit(1);
}
window = DefaultRootWindow(display);

Cursor invisibleCursor;
Pixmap bitmapNoData;
XColor black;
static char noData[] = { 0,0,0,0,0,0,0,0 };
black.red = black.green = black.blue = 0;

bitmapNoData = XCreateBitmapFromData(display, window, noData, 8, 8);
invisibleCursor = XCreatePixmapCursor(display, bitmapNoData, bitmapNoData, 
                                     &black, &black, 0, 0);
XDefineCursor(display,window, invisibleCursor);
XFreeCursor(display, invisibleCursor);
XFreePixmap(display, bitmapNoData);
为了隐藏光标,之后当我完成后想要恢复。
// Restore the X left facing cursor
Cursor cursor;
cursor=XCreateFontCursor(display,XC_left_ptr);
XDefineCursor(display, window, cursor);
XFreeCursor(display, cursor);
为了恢复X的左手光标(因为它是根窗口,我不希望它保持不可见状态)。 我不确定,但我可能也可以使用

要恢复 X 的左手光标(因为它是根窗口,我不希望它保持不可见状态)。我不确定,但我可能还可以使用

XUndefineCursor(display, window);

2
一位匿名用户的评论:如果你打开它,就关闭它。如果你创建它,就销毁它。你没有销毁这个像素图... - Benjol
我刚刚发现在调用XDefineCursorXUndefineCursor之后需要调用XSync(display, False)才能使其正常工作。如果你的光标没有正确地消失/重新出现,你也可以尝试一下这个方法。 - Pythagoras of Samos

15

你可以创建并设置一个不可见的光标主题。这种技巧被Maemo使用,因为在触摸屏设备上显示光标是相当无意义的。

遗憾的是,在X11应用程序和工具包中运行时更改全局光标主题的能力并不统一。你可以更改服务器资源Xcursor.theme,并且没有人会注意到(通常只在启动时查询);你可以通知xsettings,但似乎只影响Gtk+程序;KDE使用根窗口上的属性进行某种形式的通信等。

至少对于自己的应用程序来说,更改光标只需要使用XDefineCursor就很容易了,如果你在根窗口上这样做,一些应用程序可能会跟随。


1
你有关于如何创建它的链接吗?并在应用程序启动时启用它,在应用程序退出时禁用它吗? - rck
在X启动时设置全局光标主题很容易,但要能够操作其他窗口的光标...这种能力并不容易获得。你为什么想要这样做? - ephemient
其实,仔细想想,我控制着用户可见的所有应用程序,所以我应该能够使用XDefineCursor。谢谢。 - rck

11

使用xbanish!它可以“在打字时隐藏鼠标光标”!

通过以下命令启动:

xbanish &

享受吧!

xbanish的源代码在这里:
https://github.com/jcs/xbanish


1
这真的是一个很棒的工具,安装容易且运行良好。它应该更加普及。 - Rok
目前为止最好且最简单的解决方案。与i3非常兼容! - Naheel

6
为了隐藏鼠标指针,需要创建一个额外的小文件(我称其为blnk_ptr.xbm):
#define blnk_ptr_width 1
#define blnk_ptr_height 1
#define blnk_ptr_x_hot 0
#define blnk_ptr_y_hot 0
static unsigned char blnk_ptr_bits[] = {
    0x00 };

那么,

  • To hide the mouse pointer cursor,

      $ xsetroot -cursor blnk_ptr.xbm blnk_ptr.xbm
    
  • To show the mouse pointer cursor again,

      $ xsetroot -cursor_name left_ptr
    

    You can use a mouse pointer cursor other than "left_ptr", but this one seems to be widely available across *nix systems.

顺便说一下,我还不知道如何使用xsetroot获取系统当前使用的指针名称。 我猜我会去查找这个问题的答案(像往常一样),但如果有知道怎么做的人给我答案,那就太好了;)


我确实这样做了,但它显示“xsetroot: bad bitmap format file: blnk_ptr.xbm”(在树莓派上)。 - Gik
1
@Gik,我认为你需要将blnk_ptr.xbm文件完全按照它出现的样子输入,包括换行符和所有内容。 - Verax

4
这是我的解决方案。它将光标放置在你看不见的位置(在我的情况下,是在左下角) - 然后,它禁用了鼠标,所以你无法移动它。
注意:你可以从 xrandr 解析数据,或者在登录时将这些数据放入环境变量中,然后使用它;这样,你就不必硬编码它。但是,对我来说,我从不更改屏幕分辨率,所以 768 就可以了 :)
setmouse () {
   DISPLAY=":0" xinput $1 `DISPLAY=":0" xinput | grep Mouse |
           tr -d " " | tr "\t" " " |
           cut -d" " -f2 | cut -d"=" -f2`
}

offmouse () {
   DISPLAY=":0" xdotool mousemove 0 768 # use xrandr to find out
   setmouse disable
}

onmouse () {
   setmouse enable
}

这取决于 xdotool,为什么呢?由于 grep Mouse,它也无法在虚拟设备(例如无线鼠标和键盘)上工作,并且它会完全禁用鼠标 - 就我所理解的问题是关于仅隐藏指针。 - cprn
你可以将setmouse命令缩短为:xinput $1 $(xinput | grep -oP "Mouse.*id=\K[0-9]+") - Ipor Sircer

4

源代码,xtoggle.c:

#include <signal.h>
#include <X11/extensions/Xfixes.h>

Display               *display;
volatile sig_atomic_t breakout = 0;

void toggle_cursor(int x) { breakout = x; }

int main(void) {
    int      hidden = 0;
    struct   sigaction act;
    sigset_t mask;

    if (!(display = XOpenDisplay(NULL))) { return(1); }
    act.sa_handler = toggle_cursor;
    sigaction(SIGUSR1, &act, NULL);
    sigemptyset(&mask);
    while (1) {
        if (hidden) { XFixesShowCursor(display, DefaultRootWindow(display)); } 
        else        { XFixesHideCursor(display, DefaultRootWindow(display)); }
        XFlush(display);
        hidden = !hidden;
        breakout = 0;
        while (!breakout) { sigsuspend(&mask); }
    }
    return(0);
}
  • Depends on Xfixes. On Debian/Ubuntu,

    apt install libxfixes-dev
    
  • Compile it and execute it in the background,

    cc xtoggle.c -lX11 -lXfixes -o xtoggle
    ./xtoggle &
    
  • Toggle cursor visibility by sending it a USR1 signal,

    pkill -USR1 -x xtoggle
    
  • Possibly useful exercise: Use XWarpPointer to move the invisible mouse pointer out of the way when hidden.


到目前为止,我找到的唯一适用于这个目的的解决方案。 - Qetesh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接