Skip to content

Commit

Permalink
add timeout feature (#61)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ckath authored Apr 29, 2021
1 parent 3c81808 commit 725c614
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ INSTALL_DATA ?= install
X11BASE ?= /usr/X11R6
INCLUDES?= -I$(X11BASE)/include
LDPATH ?= -L$(X11BASE)/lib
LIBS += -lX11 -lXfixes -lXi
LIBS += -lX11 -lXfixes -lXi -lXext

PROG = xbanish
OBJS = xbanish.o
Expand Down
5 changes: 5 additions & 0 deletions xbanish.1
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
.Op Fl d
.Op Fl i Ar modifier
.Op Fl m Oo Ar w Oc Ns Ar nw|ne|sw|se
.Op Fl t Ar seconds
.Sh DESCRIPTION
.Nm
hides the X11 mouse cursor when a key is pressed.
Expand Down Expand Up @@ -50,6 +51,10 @@ Modifiers are:
.It Fl m Oo Ar w Oc Ns Ar nw|ne|sw|se
When hiding the mouse cursor, move it to this corner of the screen
or current window, then move it back when showing the cursor.
.It Fl t Ar seconds
Hide the mouse cursor after
.Ic seconds
have passed without mouse movement.
.El
.Sh SEE ALSO
.Xr XFixes 3
Expand Down
82 changes: 79 additions & 3 deletions xbanish.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

#include <err.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
Expand All @@ -24,6 +25,7 @@
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <X11/extensions/sync.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/XInput2.h>
Expand All @@ -33,6 +35,7 @@ void show_cursor(void);
void snoop_root(void);
int snoop_xinput(Window);
void snoop_legacy(Window);
void set_alarm(XSyncAlarm *, XSyncTestType);
void usage(char *);
int swallow_error(Display *, XErrorEvent *);

Expand All @@ -47,7 +50,10 @@ static long last_device_change = -1;

static Display *dpy;
static int hiding = 0, legacy = 0, always_hide = 0;
static unsigned timeout = 0;
static unsigned char ignored;
static XSyncCounter idler_counter = 0;
static XSyncAlarm idle_alarm = None;

static int debug = 0;
#define DPRINTF(x) { if (debug) { printf x; } };
Expand All @@ -69,7 +75,11 @@ main(int argc, char *argv[])
{
int ch, i;
XEvent e;
XSyncAlarmNotifyEvent *alarm_e;
XGenericEventCookie *cookie;
XSyncSystemCounter *counters;
int sync_event, error;
int major, minor, ncounters;

struct mod_lookup {
char *name;
Expand All @@ -82,7 +92,7 @@ main(int argc, char *argv[])
{"all", -1},
};

while ((ch = getopt(argc, argv, "adi:m:")) != -1)
while ((ch = getopt(argc, argv, "adi:m:t:")) != -1)
switch (ch) {
case 'a':
always_hide = 1;
Expand Down Expand Up @@ -119,6 +129,9 @@ main(int argc, char *argv[])
usage(argv[0]);
}
break;
case 't':
timeout = strtoul(optarg, NULL, 0);
break;
default:
usage(argv[0]);
}
Expand All @@ -141,6 +154,26 @@ main(int argc, char *argv[])
if (always_hide)
hide_cursor();

/* required setup for the xsync alarms used by timeout */
if (timeout) {
if (XSyncQueryExtension(dpy, &sync_event, &error) != True)
errx(1, "no sync extension available");

XSyncInitialize(dpy, &major, &minor);

counters = XSyncListSystemCounters(dpy, &ncounters);
for (i = 0; i < ncounters; i++) {
if (!strcmp(counters[i].name, "IDLETIME")) {
idler_counter = counters[i].counter;
break;
}
}
XSyncFreeSystemCounterList(counters);

if (!idler_counter)
errx(1, "no idle counter");
}

for (;;) {
cookie = &e.xcookie;
XNextEvent(dpy, &e);
Expand Down Expand Up @@ -237,7 +270,17 @@ main(int argc, char *argv[])
break;

default:
DPRINTF(("unknown event type %d\n", e.type));
if (!timeout || e.type != (sync_event + XSyncAlarmNotify)) {
DPRINTF(("unknown event type %d\n", e.type));
break;
}

alarm_e = (XSyncAlarmNotifyEvent *)&e;
if (alarm_e->alarm == idle_alarm) {
DPRINTF(("idle counter reached %dms, hiding cursor\n",
XSyncValueLow32(alarm_e->counter_value)));
hide_cursor();
}
}
}
}
Expand Down Expand Up @@ -320,6 +363,11 @@ show_cursor(void)
DPRINTF(("mouse moved, %sunhiding cursor\n",
(hiding ? "" : "already ")));

if (timeout) {
DPRINTF(("(re)setting timeout of %us\n", timeout));
set_alarm(&idle_alarm, XSyncPositiveComparison);
}

if (!hiding)
return;

Expand Down Expand Up @@ -496,10 +544,38 @@ snoop_legacy(Window win)
XFree(kids); /* hide yo kids */
}

void
set_alarm(XSyncAlarm *alarm, XSyncTestType test)
{
XSyncAlarmAttributes attr;
XSyncValue value;
unsigned int flags;
int64_t cur_idle;

XSyncQueryCounter(dpy, idler_counter, &value);
cur_idle = ((int64_t)XSyncValueHigh32(value) << 32) |
XSyncValueLow32(value);
DPRINTF(("cur idle %ld\n", cur_idle));

attr.trigger.counter = idler_counter;
attr.trigger.test_type = test;
attr.trigger.value_type = XSyncRelative;
XSyncIntsToValue(&attr.trigger.wait_value, timeout * 1000,
(unsigned long)(timeout * 1000) >> 32);
XSyncIntToValue(&attr.delta, 0);

flags = XSyncCACounter | XSyncCATestType | XSyncCAValue | XSyncCADelta;

if (*alarm)
XSyncDestroyAlarm(dpy, *alarm);

*alarm = XSyncCreateAlarm(dpy, flags, &attr);
}

void
usage(char *progname)
{
fprintf(stderr, "usage: %s [-a] [-d] [-i mod] [-m [w]nw|ne|sw|se]\n",
fprintf(stderr, "usage: %s [-a] [-d] [-i mod] [-m [w]nw|ne|sw|se] [-t seconds]\n",
progname);
exit(1);
}
Expand Down

0 comments on commit 725c614

Please sign in to comment.