diff --git a/Makefile b/Makefile index 186d38d..cc45779 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ MANDIR ?= $(PREFIX)/man/man1 INSTALL_PROGRAM ?= install -s INSTALL_DATA ?= install -LIBS ?= x11 xfixes xi xext +LIBS ?= x11 xfixes xi INCLUDES?= `pkg-config --cflags $(LIBS)` LDFLAGS += `pkg-config --libs $(LIBS)` diff --git a/xbanish.c b/xbanish.c index e15f620..99b121c 100644 --- a/xbanish.c +++ b/xbanish.c @@ -16,15 +16,18 @@ */ #include +#include +#include +#include #include -#include #include +#include #include +#include #include #include #include -#include #include #include #include @@ -35,10 +38,10 @@ 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 *); int parse_geometry(const char *s); +void sighandler(int); /* xinput event type ids to be filled in later */ static int button_press_type = -1; @@ -51,10 +54,10 @@ static long last_device_change = -1; static Display *dpy; static int hiding = 0, legacy = 0, always_hide = 0, ignore_scroll = 0; -static unsigned timeout = 0; +static time_t timeout = 0; +static time_t timeout_at = 0; static unsigned char ignored; -static XSyncCounter idler_counter = 0; -static XSyncAlarm idle_alarm = None; +static int sigpipe[2]; static int debug = 0; #define DPRINTF(x) { if (debug) { printf x; } }; @@ -77,11 +80,7 @@ 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; @@ -149,6 +148,15 @@ main(int argc, char *argv[]) if (!(dpy = XOpenDisplay(NULL))) errx(1, "can't open display %s", XDisplayName(NULL)); + if (pipe(sigpipe) < 0) + err(1, "pipe"); + if (fcntl(sigpipe[1], F_SETFD, O_NONBLOCK) < 0) + err(1, "fcntl"); + struct sigaction sa = { .sa_handler = sighandler }; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGTERM, &sa, NULL) < 0) + err(1, "sigaction"); + #ifdef __OpenBSD__ if (pledge("stdio", NULL) == -1) err(1, "pledge"); @@ -161,27 +169,43 @@ 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"); + for (;;) { + struct pollfd pfd[2] = {0}; + int pending = XPending(dpy) > 0; + if (!pending) { + int poll_timeout = -1; + pfd[0].fd = ConnectionNumber(dpy); + pfd[0].events = POLLIN; + pfd[1].fd = sigpipe[0]; + pfd[1].events = POLLIN; + if (timeout && !hiding) { + poll_timeout = (timeout_at - time(NULL)) * 1000; + if (poll_timeout < 0) + poll_timeout = 0; + } + DPRINTF(("poll_timeout: %d\n", poll_timeout)); + pending = poll(pfd, 2, poll_timeout) > 0 && + (pfd[0].revents & POLLIN); + } - XSyncInitialize(dpy, &major, &minor); + if (pfd[1].revents & POLLIN) { + DPRINTF(("received signal, exiting...\n")); + if (hiding) + show_cursor(); + break; + } - counters = XSyncListSystemCounters(dpy, &ncounters); - for (i = 0; i < ncounters; i++) { - if (!strcmp(counters[i].name, "IDLETIME")) { - idler_counter = counters[i].counter; - break; - } + if (timeout && !hiding && time(NULL) >= timeout_at) { + DPRINTF(("timeout reached, hiding cursor\n")); + hide_cursor(); + continue; } - XSyncFreeSystemCounterList(counters); - if (!idler_counter) - errx(1, "no idle counter"); - } + if (!pending) { + DPRINTF(("no xevent pending, continuing\n")); + continue; + } - for (;;) { cookie = &e.xcookie; XNextEvent(dpy, &e); @@ -280,19 +304,8 @@ main(int argc, char *argv[]) break; default: - 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(); - } + DPRINTF(("unknown event type %d\n", e.type)); + break; } } } @@ -380,8 +393,8 @@ show_cursor(void) (hiding ? "" : "already "))); if (timeout) { - DPRINTF(("(re)setting timeout of %us\n", timeout)); - set_alarm(&idle_alarm, XSyncPositiveComparison); + DPRINTF(("(re)setting timeout of %llds\n", (long long)timeout)); + timeout_at = time(NULL) + timeout; } if (!hiding) @@ -560,30 +573,6 @@ snoop_legacy(Window win) XFree(kids); /* hide yo kids */ } -void -set_alarm(XSyncAlarm *alarm, XSyncTestType test) -{ - XSyncAlarmAttributes attr; - XSyncValue value; - unsigned int flags; - - XSyncQueryCounter(dpy, idler_counter, &value); - - 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) { @@ -621,3 +610,13 @@ parse_geometry(const char *s) } return 0; } + +void +sighandler(int signum) +{ + char dummy = 1; + int saved_errno = errno; + ssize_t res = write(sigpipe[1], &dummy, 1); + (void)res; + errno = saved_errno; +}