36

How do I hide the mouse pointer under X11? I would like to use the built in libraries in order to do this and not something like SDL (SDL_ShowCursor(0)) or glut (glutSetCursor(GLUT_CURSOR_NONE)). Also, the mouse pointer should be hidden no matter the pointer location, not just in its own window.

rck
  • 2,020
  • 2
  • 23
  • 23

11 Answers11

36

Here's a description how unclutter utility does it.

Unclutter is a program which runs permanently in the background of an X11 session. It checks on the X11 pointer (cursor) position every few seconds, and when it finds it has not moved (and no buttons are pressed on the mouse, and the cursor is not in the root window) it creates a small sub-window as a child of the window the cursor is in. The new window installs a cursor of size 1x1 but a mask of all 0, ie an invisible cursor. This allows you to see all the text in an xterm or xedit, for example. The human factors crowd would agree it should make things less distracting.

Once created, the program waits for the pointer to leave the window and then destroys it, restoring the original situation. Button events are passed transparently through to the parent window. They will usually cause the cursor to reappear because an active grab will be made by the program while the button is down, so the pointer will apparently leave the window, even though its x y position doesnt change.

ppl
  • 1,120
  • 5
  • 18
Eugene Morozov
  • 15,081
  • 3
  • 25
  • 32
  • 2
    now I also know why unclutter is messing up my accelerated windows so badly. mplayer doesn't take kindly to child windows like that I believe. – Aktau Apr 29 '13 at 13:35
23

There is a -no-cursor option for Xorg 1.7 and later. https://www.x.org/wiki/AdvancedTopicsFAQ/

xinit -- -nocursor or startx -- -nocursor could work.

rmarscher
  • 5,596
  • 2
  • 28
  • 30
  • with this option touchscreens with mouse driver (qemu, mastertouch, etc) not working! – eri Sep 23 '20 at 18:49
21

I'd rather use simpler method:

unclutter -idle 0

You almost do not see cursor, still it is available. To disable mouse:

rmmod psmouse

Or disable mouse module permanently somewhere in /etc/. See your distribution manual.

Sam Protsenko
  • 14,045
  • 4
  • 59
  • 75
sevenfourk
  • 463
  • 4
  • 12
  • 2
    with unclutter you can set -jitter flag to high value, and then you will not see the mouse at all, and you don't have to poll so often. – charlie_pl Jan 14 '17 at 12:30
20

an alternative to unclutter

Unclutter didn't work for me, as it doesn't play well with hardware accelerated surfaces (such as for example those produced by intels' VA-API when decoding video). So I found a program that hid the mouse pointer in a less roundabout way, hhp, and rewrote it in C with minimal dependencies, the result is hhpc. I did this to obviate the need to have haskell to compile it and because hhp sometimes stopped hiding the mouse pointer.

hhpc, relies only on glibc and xlib, so it's easy to build, just do make release. You can get the code and instructions from my repository. It's very memory and CPU efficient (because it does almost nothing).

Aktau
  • 1,847
  • 21
  • 30
  • 1
    Hi Aktau, could you modify your hhpc to hide the mouse pointer immediately when a keyboard event happening instead of timer? That would be very useful. – Ray Apr 25 '16 at 09:10
  • 1
    @Iiridayn Thank you so much! I looked for this kind of feature for years! It seems works well. – Ray Oct 31 '19 at 00:42
15

You can create and set an invisible cursor theme. This trick is used by maemo, because it's rather pointless to have a cursor on a touchscreen device.

Sadly, the ability to change the global cursor theme at runtime is not uniform across X11 applications and toolkits. You can change the server resource Xcursor.theme, and nobody will notice (generally it's only queried at startup); you can inform xsettings which only seems to affect Gtk+ programs; KDE uses some sort of communication through properties on the root window; etc.

At least changing the cursor for your own application is as easy as XDefineCursor, and if you do that on the root window, some applications might follow along.

ephemient
  • 198,619
  • 38
  • 280
  • 391
  • 1
    Do you have a link on how to create this, enable it when the application starts and disable it when the application exits? – rck Mar 19 '09 at 01:20
  • It's easy to set the global cursor theme when X starts up, but to be able to manipulate other windows' cursors... that ability is not readily available. Why do you want to do this? – ephemient Mar 19 '09 at 02:02
  • Actually, come to think of it, I have control of all applications visible to the user, so I should be able to use XDefineCursor. Thanks. – rck Mar 19 '09 at 16:59
15

I ended up using XDefineCursor like ephemient mentioned. The control application changed the default root window cursor and the other applications (which are under my control) inherited it.

Code specifics look like:

// 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);

In order to hide the cursor and then after I'm done

// Restore the X left facing cursor
Cursor cursor;
cursor=XCreateFontCursor(display,XC_left_ptr);
XDefineCursor(display, window, cursor);
XFreeCursor(display, cursor);

To restore X's left handed cursor (Since it's the root window and I don't want it to stay invisible. I'm not sure, but I might also be able to use

XUndefineCursor(display, window);
rck
  • 2,020
  • 2
  • 23
  • 23
  • 2
    Comment from an anonymous user: *If you open it, close it. If you create it, destroy it. You didn't destroy the pixmap...* – Benjol Oct 19 '11 at 08:15
  • I've just found that I need to call ``XSync(display, False)`` after the calls to ``XDefineCursor`` and ``XUndefineCursor`` for this to work. If your cursor does not disappear/reappear properly, you might want to try it too. – Pythagoras of Samos Jul 09 '19 at 18:04
11

Use xbanish! It "banish the mouse cursor when typing"! Start it with

xbanish &

and enjoy!

The source code for xbanish is here:
https://github.com/jcs/xbanish

mpb
  • 1,277
  • 15
  • 18
ILUXA
  • 121
  • 1
  • 2
6

To hide the mouse cursor, create an extra little file (I called mine 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 };

Then,

  • 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.

Btw, I don't know yet how to get the name of the pointer currently used by the system using xsetroot. I guess I'll [as usual] digg that too, but I'd be happy to have someone who knows the how-to giving me the answer ( It'd be nice ;) )

Quasímodo
  • 3,812
  • 14
  • 25
StephaneAG
  • 1,107
  • 1
  • 12
  • 11
  • I did exactly that but it says "xsetroot: bad bitmap format file: blnk_ptr.xbm" (on a Raspberry Pi) – Gik Mar 30 '21 at 18:29
  • 1
    @Gik, I think you need to type the blnk_ptr.xbm file exactly as it appears with newlines and everything. – Verax Apr 20 '22 at 02:34
4

This is my solution. It places the cursor where you can't see it (in my case, in the bottom-left corner) - then, it disables the mouse, so you can't move it.

Note You could parse data from xrandr, or put that data in an environmental on login, and then use it; that way, you won't have to have it hard coded. But, as for me, I never change my screen resolution, so 768 is OK :)

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
}
Emanuel Berg
  • 499
  • 4
  • 14
  • It depends on `xdotool`, why? It also doesn't work on virtual devices (e.g. wireless mouse & keyboard) due to `grep Mouse`, and it disables the mouse entirely - as far as I understand the question is about hiding the pointer only. – cprn Oct 04 '15 at 13:20
  • You can shorten setmouse command as: `xinput $1 $(xinput | grep -oP "Mouse.*id=\K[0-9]+")` – Ipor Sircer Sep 03 '18 at 10:56
4

Source code, 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.

Quasímodo
  • 3,812
  • 14
  • 25
2

There is an X11 extension called Fixes which has a function one can use to hide the cursor. The advantage of this function is that this sends a message to the X server which hides the sprite. No trick (i.e. invisible cursor from a pixmap) and from what I understand it works on the entire screen.

#include <X11/extensions/Xfixes.h>

...

    XFixesHideCursor(dpy, window);
    XFlush(dpy); // not required unless you want an immediate effect

Source: How to hide the mouse cursor in X11/Xorg

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156