aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksandrs Stier <aleks.stier@icloud.com>2024-04-03 00:12:11 +0200
committerAleksandrs Stier <aleks.stier@icloud.com>2024-04-03 16:32:38 +0200
commit4633c1e57389e49324302246a611766aa043ecf4 (patch)
tree52b2f5d8c3c74f127a1c1bee3261f79a5a96bb7f
Publish xhidecursor
-rw-r--r--.gitignore1
-rw-r--r--LICENSE21
-rw-r--r--Makefile27
-rw-r--r--README.md18
-rw-r--r--main.c45
5 files changed, 112 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..66228a9
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+xhidecursor
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..fe1f4f7
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 Aleksandrs Stier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..6320366
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,27 @@
+PREFIX ?= /usr/local/bin
+
+CFLAGS += -std=c99 -march=native -O3 -pipe
+CFLAGS += -Wall
+CFLAGS += -Wconversion
+CFLAGS += -Wdouble-promotion
+CFLAGS += -Wextra
+CFLAGS += -Wmissing-prototypes
+CFLAGS += -Wold-style-definition
+CFLAGS += -Wpedantic
+CFLAGS += -Wshadow
+
+all: xhidecursor
+
+xhidecursor: main.c Makefile
+ $(CC) $(CFLAGS) -o $@ $< -lX11 -lXfixes -lXi
+
+install: all
+ install -D xhidecursor $(DESTDIR)$(PREFIX)/xhidecursor
+
+uninstall:
+ rm -f $(DESTDIR)$(PREFIX)/xhidecursor
+
+clean:
+ rm -f xhidecursor
+
+.PHONY: all install uninstall clean
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..3c8e0f2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,18 @@
+## Description
+
+[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:
+
+- **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.
+
+- **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.
+
+## Dependencies
+
+- libxi
+- libxifixes
+
+## Installation
+
+```sh
+make install
+```
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..d80e968
--- /dev/null
+++ b/main.c
@@ -0,0 +1,45 @@
+#include <X11/extensions/XInput2.h>
+
+#include <stdio.h>
+
+static void xi_select_events(int);
+
+static Display *d;
+static Window r; // root-window
+
+void xi_select_events(const int event) {
+ unsigned char mask[3] = {None};
+ XISetMask(mask, event);
+ XIEventMask event_mask;
+ event_mask.deviceid = XIAllMasterDevices;
+ event_mask.mask_len = sizeof(mask);
+ event_mask.mask = mask;
+ XISelectEvents(d, r, &event_mask, 1);
+}
+
+int main(void) {
+ if (!(d = XOpenDisplay(NULL))) {
+ printf("Couldn't open Display.\n");
+ return 1;
+ }
+ r = XDefaultRootWindow(d);
+ xi_select_events(XI_RawKeyPress);
+ XEvent e;
+ XGenericEventCookie *c;
+ while (!XNextEvent(d, &e)) {
+ if (!XGetEventData(d, (c = &e.xcookie)))
+ continue;
+ switch (c->evtype) {
+ case XI_RawKeyPress:
+ xi_select_events(XI_RawMotion);
+ XFixesHideCursor(d, r);
+ break;
+ case XI_RawMotion:
+ xi_select_events(XI_RawKeyPress);
+ XFixesShowCursor(d, r);
+ break;
+ }
+ XFreeEventData(d, c);
+ }
+ XCloseDisplay(d);
+}