initial commit
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*-protocol.*
|
||||||
|
*.o
|
||||||
|
waytils
|
62
Makefile
Normal file
62
Makefile
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
PKG_CONFIG = pkg-config
|
||||||
|
VERSION = 0.1
|
||||||
|
|
||||||
|
# flags and incs
|
||||||
|
PKGS = wayland-client wayland-server
|
||||||
|
CFLAGS = -DVERSION=\"$(VERSION)\" -Wall
|
||||||
|
LIBS = `$(PKG_CONFIG) --libs $(PKGS)`
|
||||||
|
|
||||||
|
PREFIX = /usr/local
|
||||||
|
MANDIR = $(PREFIX)/share/man
|
||||||
|
|
||||||
|
# compiler and linker
|
||||||
|
CC = cc
|
||||||
|
|
||||||
|
# wayland-scanner is a tool which generates C headers and rigging for Wayland
|
||||||
|
# protocols, which are specified in XML. wlroots requires you to rig these up
|
||||||
|
# to your build system yourself and provide them in the include path.
|
||||||
|
WAYLAND_PROTOCOLS = `$(PKG_CONFIG) --variable=pkgdatadir wayland-protocols`
|
||||||
|
WAYLAND_SCANNER = `$(PKG_CONFIG) --variable=wayland_scanner wayland-scanner`
|
||||||
|
|
||||||
|
all: zwp-idle-inhibit-manager-v1-protocol.o xdg-shell-client-protocol.o ext-idle-notify-v1-protocol.o waytils
|
||||||
|
waytils: waytils.o
|
||||||
|
$(CC) -o $@ *.o $(CFLAGS) $(LIBS)
|
||||||
|
waytils.o: waytils.c
|
||||||
|
zwp-idle-inhibit-manager-v1-protocol.o: zwp-idle-inhibit-manager-v1-protocol.c zwp-idle-inhibit-manager-v1-protocol.h
|
||||||
|
xdg-shell-client-protocol.o: xdg-shell-client-protocol.c xdg-shell-client-protocol.h
|
||||||
|
ext-idle-notify-v1-protocol.o: ext-idle-notify-v1-protocol.c ext-idle-notify-v1-protocol.h
|
||||||
|
|
||||||
|
zwp-idle-inhibit-manager-v1-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) client-header \
|
||||||
|
$(WAYLAND_PROTOCOLS)/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml $@
|
||||||
|
zwp-idle-inhibit-manager-v1-protocol.c:
|
||||||
|
$(WAYLAND_SCANNER) private-code \
|
||||||
|
$(WAYLAND_PROTOCOLS)/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml $@
|
||||||
|
|
||||||
|
xdg-shell-client-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) client-header \
|
||||||
|
$(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@
|
||||||
|
xdg-shell-client-protocol.c:
|
||||||
|
$(WAYLAND_SCANNER) private-code \
|
||||||
|
$(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@
|
||||||
|
|
||||||
|
ext-idle-notify-v1-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) client-header \
|
||||||
|
$(WAYLAND_PROTOCOLS)/staging/ext-idle-notify/ext-idle-notify-v1.xml $@
|
||||||
|
ext-idle-notify-v1-protocol.c:
|
||||||
|
$(WAYLAND_SCANNER) private-code \
|
||||||
|
$(WAYLAND_PROTOCOLS)/staging/ext-idle-notify/ext-idle-notify-v1.xml $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f waytils *.o *-protocol.*
|
||||||
|
|
||||||
|
install: waytils
|
||||||
|
mkdir -p $(PREFIX)/bin
|
||||||
|
cp -f waytils $(PREFIX)/bin
|
||||||
|
chmod 755 $(PREFIX)/bin/waytils
|
||||||
|
mkdir -p $(MANDIR)/man1
|
||||||
|
cp -f waytils.1 $(MANDIR)/man1
|
||||||
|
chmod 644 $(MANDIR)/man1/waytils.1
|
||||||
|
|
||||||
|
uninstall: waytils
|
||||||
|
rm -f $(PREFIX)/bin/waytils $(MANDIR)/man1/waytils.1
|
46
waytils.1
Normal file
46
waytils.1
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
.Dd February 16, 2024
|
||||||
|
.Dt WAYTILS 1
|
||||||
|
.Sh NAME
|
||||||
|
.Nm waytils
|
||||||
|
.Nd information about the current wayland session
|
||||||
|
.Os
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm
|
||||||
|
.Op Fl v
|
||||||
|
.Op Fl h
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Nm
|
||||||
|
is a small program to check information about the current wayland session.
|
||||||
|
.Nm
|
||||||
|
requires a compositor that implements the following protocols:
|
||||||
|
.TS
|
||||||
|
tab(;) allbox;
|
||||||
|
c;c.
|
||||||
|
Protocol; Version
|
||||||
|
Idle Inhibit; 1
|
||||||
|
XDG Shell Client; 1
|
||||||
|
Idle Notify; 1
|
||||||
|
.TE
|
||||||
|
.Sh OPTIONS
|
||||||
|
.Pp
|
||||||
|
When given the
|
||||||
|
.Fl v
|
||||||
|
option,
|
||||||
|
.Nm
|
||||||
|
writes it's name and version to standard error and exits with a return value of
|
||||||
|
1.
|
||||||
|
.Pp
|
||||||
|
When given the
|
||||||
|
.Fl h
|
||||||
|
option,
|
||||||
|
.Nm
|
||||||
|
displays some information about flags to standard error and exits with a return
|
||||||
|
.Pp
|
||||||
|
When given the
|
||||||
|
.Fl f
|
||||||
|
option,
|
||||||
|
.Nm
|
||||||
|
forks into the background, and the parent process returns 0
|
||||||
|
value of 1.
|
||||||
|
.Sh BUGS
|
||||||
|
Works on my machine.
|
230
waytils.c
Normal file
230
waytils.c
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/timerfd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#include <wayland-server.h>
|
||||||
|
|
||||||
|
#include "zwp-idle-inhibit-manager-v1-protocol.h"
|
||||||
|
#include "ext-idle-notify-v1-protocol.h"
|
||||||
|
#include "xdg-shell-client-protocol.h"
|
||||||
|
|
||||||
|
#define LEN(X) (sizeof(X) / sizeof(X[0]))
|
||||||
|
|
||||||
|
static struct wl_compositor *compositor;
|
||||||
|
static struct wl_display *display;
|
||||||
|
static struct wl_registry *registry;
|
||||||
|
static struct wl_surface *surface;
|
||||||
|
static struct wl_seat *seat;
|
||||||
|
|
||||||
|
static struct xdg_surface *xdgsurface;
|
||||||
|
static struct xdg_wm_base *base;
|
||||||
|
static struct xdg_toplevel *toplevel;
|
||||||
|
|
||||||
|
static struct zwp_idle_inhibitor_v1 *inhibitor;
|
||||||
|
static struct zwp_idle_inhibit_manager_v1 *inhibitmanager;
|
||||||
|
|
||||||
|
static struct ext_idle_notification_v1 *notif;
|
||||||
|
static struct ext_idle_notifier_v1 *notifier;
|
||||||
|
|
||||||
|
static int subcommand = -1;
|
||||||
|
enum { INSOMNAIC, INHIBITCHECK, PROTOCOLS };
|
||||||
|
|
||||||
|
static void die(const char *fmt, ...);
|
||||||
|
static void pong(void *data, struct xdg_wm_base *base, uint32_t serial);
|
||||||
|
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 interrupt();
|
||||||
|
|
||||||
|
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
|
||||||
|
pong(void *data, struct xdg_wm_base *base, uint32_t serial)
|
||||||
|
{
|
||||||
|
xdg_wm_base_pong(base, serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct xdg_wm_base_listener xdglistener = {
|
||||||
|
.ping = pong,
|
||||||
|
};
|
||||||
|
|
||||||
|
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, xdg_wm_base_interface.name) == 0) {
|
||||||
|
base = wl_registry_bind(registry, id, &xdg_wm_base_interface, 1);
|
||||||
|
xdg_wm_base_add_listener(base, &xdglistener, NULL);
|
||||||
|
} else if (strcmp(interface, wl_seat_interface.name) == 0) {
|
||||||
|
seat = wl_registry_bind(registry, id, &wl_seat_interface, 7);
|
||||||
|
} else if (strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name) == 0) {
|
||||||
|
if (subcommand == INSOMNAIC) {
|
||||||
|
inhibitmanager = wl_registry_bind(registry, id,
|
||||||
|
&zwp_idle_inhibit_manager_v1_interface, 1);
|
||||||
|
}
|
||||||
|
} else if (strcmp(interface, ext_idle_notifier_v1_interface.name) == 0) {
|
||||||
|
if (subcommand == INHIBITCHECK) {
|
||||||
|
notifier = wl_registry_bind(registry, id, &ext_idle_notifier_v1_interface, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (subcommand == PROTOCOLS)
|
||||||
|
fprintf(stdout, "%s (%d)\n", interface, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_registry_listener reglistener = {
|
||||||
|
.global = reghandler,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
idling(void *data, struct ext_idle_notification_v1 *notif)
|
||||||
|
{
|
||||||
|
printf("No idle inhibitor found :)\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
interrupt()
|
||||||
|
{
|
||||||
|
printf("Idle inhibitor found :(\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct ext_idle_notification_v1_listener idlelistener = {
|
||||||
|
.idled = idling,
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int i, c;
|
||||||
|
struct timeval start, end;
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
while ((c = getopt(argc, argv, "hvf")) != -1) {
|
||||||
|
switch (c) {
|
||||||
|
case 'v': die("%s-%s", argv[0], VERSION); break;
|
||||||
|
case 'f':
|
||||||
|
if (fork() != 0)
|
||||||
|
exit(0);
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
default: die("usage: %s [-hvf]", argv[0]); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
if (strcmp("insomniac", argv[i]) == 0) {
|
||||||
|
fprintf(stderr, "Adding an idle lock on the compositor\n");
|
||||||
|
subcommand = INSOMNAIC;
|
||||||
|
} else if (strcmp("inhibitcheck", argv[i]) == 0) {
|
||||||
|
fprintf(stderr, "Checking for an idle inhibitor\n");
|
||||||
|
subcommand = INHIBITCHECK;
|
||||||
|
} else if (strcmp("protocols", argv[i]) == 0) {
|
||||||
|
fprintf(stderr, "Checking for protocols\n");
|
||||||
|
subcommand = PROTOCOLS;
|
||||||
|
} else if (argv[i] == argv[argc - 1]) {
|
||||||
|
fprintf(stderr, "No valid command specified\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the parent process pid to make killing it easier later */
|
||||||
|
pid = getpid();
|
||||||
|
|
||||||
|
/* setup wayland stuff */
|
||||||
|
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 (subcommand == PROTOCOLS)
|
||||||
|
exit(0);
|
||||||
|
if (!compositor || !seat)
|
||||||
|
die("%s: compositor doesn't meet necesary protocols", argv[0]);
|
||||||
|
if (!notifier && subcommand == INHIBITCHECK)
|
||||||
|
die("%s: compositor doesn't support the idle notify protocol", argv[0]);
|
||||||
|
if (!inhibitmanager && subcommand == INSOMNAIC)
|
||||||
|
die("%s: compositor doesn't support the inhibit manager protocol", argv[0]);
|
||||||
|
|
||||||
|
/* register event */
|
||||||
|
if (subcommand == INHIBITCHECK) {
|
||||||
|
notif = ext_idle_notifier_v1_get_idle_notification(notifier, 1, seat);
|
||||||
|
ext_idle_notification_v1_add_listener(notif, &idlelistener, NULL);
|
||||||
|
|
||||||
|
/* event should be registered now get starting time so we can end command
|
||||||
|
* if we should've seen the idle event by now */
|
||||||
|
gettimeofday(&start, NULL);
|
||||||
|
}
|
||||||
|
wl_display_roundtrip(display);
|
||||||
|
|
||||||
|
surface = wl_compositor_create_surface(compositor);
|
||||||
|
xdgsurface = xdg_wm_base_get_xdg_surface(base, surface);
|
||||||
|
toplevel = xdg_surface_get_toplevel(xdgsurface);
|
||||||
|
|
||||||
|
wl_display_roundtrip(display);
|
||||||
|
wl_surface_commit(surface);
|
||||||
|
|
||||||
|
/* register stuff */
|
||||||
|
switch (subcommand) {
|
||||||
|
case INSOMNAIC:
|
||||||
|
inhibitor = zwp_idle_inhibit_manager_v1_create_inhibitor(inhibitmanager, surface);
|
||||||
|
break;
|
||||||
|
case INHIBITCHECK:
|
||||||
|
/* check in a seperate thread so wayland doesn't block or get blocked */
|
||||||
|
if (fork() == 0)
|
||||||
|
while (1) {
|
||||||
|
gettimeofday(&end, NULL);
|
||||||
|
/* check if the program has been running for 10 milliseconds, and then
|
||||||
|
* terminate because at this point we should've seen an idle event */
|
||||||
|
if (end.tv_usec - start.tv_usec > 10000) {
|
||||||
|
kill(pid, SIGPOLL);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* listen for the SIGPOLL signal */
|
||||||
|
signal(SIGPOLL, interrupt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wl_display_roundtrip(display);
|
||||||
|
|
||||||
|
/* start listening for wayland events */
|
||||||
|
while (wl_display_dispatch(display) != -1);
|
||||||
|
|
||||||
|
/* cleanup time */
|
||||||
|
if (subcommand == INSOMNAIC)
|
||||||
|
zwp_idle_inhibitor_v1_destroy(inhibitor);
|
||||||
|
zwp_idle_inhibit_manager_v1_destroy(inhibitmanager);
|
||||||
|
ext_idle_notifier_v1_destroy(notifier);
|
||||||
|
wl_registry_destroy(registry);
|
||||||
|
wl_display_destroy(display);
|
||||||
|
wl_compositor_destroy(compositor);
|
||||||
|
}
|
Reference in New Issue
Block a user