aboutsummaryrefslogtreecommitdiffstats
path: root/wiz.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--wiz.c149
1 files changed, 149 insertions, 0 deletions
diff --git a/wiz.c b/wiz.c
new file mode 100644
index 0000000..f5a8540
--- /dev/null
+++ b/wiz.c
@@ -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, &reglistener, 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);
+}