diff options
Diffstat (limited to '')
-rw-r--r-- | wiz.c | 149 |
1 files changed, 149 insertions, 0 deletions
@@ -0,0 +1,149 @@ +#include <signal.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#include <wayland-client.h> +#include <wayland-server.h> +#include "ext-idle-notify-v1-protocol.h" + +#define LEN(X) (sizeof(X) / sizeof(X[0])) + +static struct ext_idle_notifier_v1 *notifier; +static struct wl_compositor *compositor; +static struct wl_display *display; +static struct wl_registry *registry; +static struct wl_seat *seat; +static const struct ext_idle_notification_v1_listener idlelistener; +static const struct wl_registry_listener reglistener; + +pid_t cpid; + +struct Events { + uint32_t delay; /* in ms */ + char **idlecmd; + char **resumecmd; + struct ext_idle_notification_v1 *notif; +}; + +#include "config.h" + +static void die(const char *fmt, ...); +static void reghandler(void *data, struct wl_registry *registry, uint32_t id, + const char *interface, uint32_t version); +static void idling(void *data, struct ext_idle_notification_v1 *notif); +static void resuming(void *data, struct ext_idle_notification_v1 *notif); +static void run(char **cmd); + +static void +die(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + if (fmt[0] && fmt[strlen(fmt)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } else + fputc('\n', stderr); + exit(1); +} + +static void +reghandler(void *data, struct wl_registry *registry, uint32_t id, + const char *interface, uint32_t version) +{ + if (strcmp(interface, wl_compositor_interface.name) == 0) + compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 1); + else if (strcmp(interface, ext_idle_notifier_v1_interface.name) == 0) + notifier = wl_registry_bind(registry, id, &ext_idle_notifier_v1_interface, 1); + else if (strcmp(interface, wl_seat_interface.name) == 0) + seat = wl_registry_bind(registry, id, &wl_seat_interface, 7); +} + +static const struct wl_registry_listener reglistener = { + .global = reghandler, +}; + +static void +idling(void *data, struct ext_idle_notification_v1 *notif) +{ + struct Events *event = data; + run(event->idlecmd); +} + +static void +resuming(void *data, struct ext_idle_notification_v1 *notif) +{ + struct Events *event = data; + run(event->resumecmd); +} + +static const struct ext_idle_notification_v1_listener idlelistener = { + .idled = idling, + .resumed = resuming, +}; + +static void +run(char **cmd) +{ + waitpid(-1, NULL, WNOHANG); + if (killchild && cpid) + kill(cpid, SIGINT); + if ((cpid = fork()) == 0) { + dup2(STDERR_FILENO, STDOUT_FILENO); + setsid(); + execvp(cmd[0], cmd); + die("execvp failed:"); + } +} + +int +main(int argc, char *argv[]) +{ + int i, c; + + while ((c = getopt(argc, argv, "hv")) != -1) { + switch (c) { + case 'v': die("%s-%s", argv[0], VERSION); break; + case 'h': + default: die("usage: %s [-hv]", argv[0]); break; + } + } + + display = wl_display_connect(NULL); + if (!display) + die("%s: failed to connect to wayland display :(", argv[0]); + + registry = wl_display_get_registry(display); + wl_registry_add_listener(registry, ®listener, NULL); + wl_display_roundtrip(display); + if (!compositor || !notifier || !seat) + die("%s: compositor doesn't support all necessary protocols", argv[0]); + + /* register all events */ + for (i = 0; i < LEN(events); i++) { + if (events[i].delay < 0) + continue; + + events[i].notif = ext_idle_notifier_v1_get_idle_notification(notifier, + events[i].delay, seat); + ext_idle_notification_v1_add_listener(events[i].notif, &idlelistener, + &events[i]); + } + wl_display_roundtrip(display); + + while (wl_display_dispatch(display) != -1); + + ext_idle_notifier_v1_destroy(notifier); + wl_registry_destroy(registry); + wl_display_destroy(display); + wl_compositor_destroy(compositor); +} |