├── .gitignore ├── LICENSE ├── Makefile ├── README.md └── main.c /.gitignore: -------------------------------------------------------------------------------- 1 | xhidecursor 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Aleksandrs Stier 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PREFIX ?= /usr/local/bin 2 | 3 | CFLAGS += -std=c99 -march=native -O3 -pipe 4 | CFLAGS += -Wall 5 | CFLAGS += -Wconversion 6 | CFLAGS += -Wdouble-promotion 7 | CFLAGS += -Wextra 8 | CFLAGS += -Wmissing-prototypes 9 | CFLAGS += -Wold-style-definition 10 | CFLAGS += -Wpedantic 11 | CFLAGS += -Wshadow 12 | 13 | all: xhidecursor 14 | 15 | xhidecursor: main.c Makefile 16 | $(CC) $(CFLAGS) -o $@ $< -lX11 -lXfixes -lXi 17 | 18 | install: all 19 | install -D xhidecursor $(DESTDIR)$(PREFIX)/xhidecursor 20 | 21 | uninstall: 22 | rm -f $(DESTDIR)$(PREFIX)/xhidecursor 23 | 24 | clean: 25 | rm -f xhidecursor 26 | 27 | .PHONY: all install uninstall clean 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | [xhidecursor](https://github.com/astier/xhidecursor) is a minimal X-application which hides the cursor on key-press and unhides the cursor on mouse-movement. The two main advantages compared to other popular alternatives like [xbanish](https://github.com/jcs/xbanish) are: 4 | 5 | - **Simplicity:** xhidecursor `~40 SLOC` vs. xbanish `~488 SLOC`. This is because xhidecursor only uses the [XFIXES-Extension](https://cgit.freedesktop.org/xorg/proto/fixesproto/plain/fixesproto.txt) to hide the cursor while xbanish implements many different methods. 6 | 7 | - **Performance:** If stress-tested on a i5-8350U CPU by moving the mouse erratically around htop shows a CPU-Utilization of `0%` for xhidecursor and up to `1.3%` for xbanish. This is because xhidecursor only listens to the first mouse-movement to unhide the cursor and ignores all the following mouse-movements. xbanish on the other hand processes every single mouse-movement even if the mouse is already visible. The same goes for key-presses. 8 | 9 | ## Dependencies 10 | 11 | - libx11 12 | - libxi 13 | - libxfixes 14 | 15 | ## Installation 16 | 17 | ```sh 18 | make install 19 | ``` 20 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | static void xi_select_events(int); 6 | 7 | static Display *d; 8 | static Window r; // root-window 9 | 10 | void xi_select_events(const int event) { 11 | unsigned char mask[3] = {None}; 12 | XISetMask(mask, event); 13 | XIEventMask event_mask; 14 | event_mask.deviceid = XIAllMasterDevices; 15 | event_mask.mask_len = sizeof(mask); 16 | event_mask.mask = mask; 17 | XISelectEvents(d, r, &event_mask, 1); 18 | } 19 | 20 | int main(void) { 21 | if (!(d = XOpenDisplay(NULL))) { 22 | printf("Couldn't open Display.\n"); 23 | return 1; 24 | } 25 | r = XDefaultRootWindow(d); 26 | xi_select_events(XI_RawKeyPress); 27 | XEvent e; 28 | XGenericEventCookie *c; 29 | while (!XNextEvent(d, &e)) { 30 | if (!XGetEventData(d, (c = &e.xcookie))) 31 | continue; 32 | switch (c->evtype) { 33 | case XI_RawKeyPress: 34 | xi_select_events(XI_RawMotion); 35 | XFixesHideCursor(d, r); 36 | break; 37 | case XI_RawMotion: 38 | xi_select_events(XI_RawKeyPress); 39 | XFixesShowCursor(d, r); 40 | break; 41 | } 42 | XFreeEventData(d, c); 43 | XSync(d, True); 44 | } 45 | XCloseDisplay(d); 46 | } 47 | --------------------------------------------------------------------------------