From 17497f10c2a02fd06bed4999e58373b7b61b25c6 Mon Sep 17 00:00:00 2001 From: Jente Hidskes Date: Tue, 8 Jan 2019 23:24:51 +0100 Subject: [PATCH] Add idle inhibitor support With this, some apps (e.g. mpv) can block the idle tracker from kicking in. This way, the screen won't blank (or whatever you configured) when the application doesn't want it to. --- cage.c | 13 +++++++++ idle_inhibit_v1.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++ idle_inhibit_v1.h | 8 ++++++ meson.build | 2 ++ server.h | 4 +++ 5 files changed, 96 insertions(+) create mode 100644 idle_inhibit_v1.c create mode 100644 idle_inhibit_v1.h diff --git a/cage.c b/cage.c index a5e606c..fd9ff33 100644 --- a/cage.c +++ b/cage.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #if CAGE_HAS_XWAYLAND #include @@ -31,6 +32,7 @@ #include #endif +#include "idle_inhibit_v1.h" #include "output.h" #include "seat.h" #include "server.h" @@ -159,6 +161,16 @@ main(int argc, char *argv[]) goto end; } + server.idle_inhibit_v1 = wlr_idle_inhibit_v1_create(server.wl_display); + if (!server.idle_inhibit_v1) { + wlr_log(WLR_ERROR, "Cannot create the idle inhibitor"); + ret = 1; + goto end; + } + server.new_idle_inhibitor_v1.notify = handle_idle_inhibitor_v1_new; + wl_signal_add(&server.idle_inhibit_v1->events.new_inhibitor, &server.new_idle_inhibitor_v1); + wl_list_init(&server.inhibitors); + xdg_shell = wlr_xdg_shell_create(server.wl_display); if (!xdg_shell) { wlr_log(WLR_ERROR, "Unable to create the XDG shell interface"); @@ -236,6 +248,7 @@ end: wlr_xcursor_manager_destroy(xcursor_manager); #endif wlr_xdg_shell_destroy(xdg_shell); + wlr_idle_inhibit_v1_destroy(server.idle_inhibit_v1); if (server.idle) { wlr_idle_destroy(server.idle); } diff --git a/idle_inhibit_v1.c b/idle_inhibit_v1.c new file mode 100644 index 0000000..3b950ad --- /dev/null +++ b/idle_inhibit_v1.c @@ -0,0 +1,69 @@ +/* + * Cage: A Wayland kiosk. + * + * Copyright (C) 2018-2019 Jente Hidskes + * + * See the LICENSE file accompanying this file. + */ + +#include +#include +#include +#include + +#include "idle_inhibit_v1.h" +#include "server.h" + +struct cg_idle_inhibitor_v1 { + struct cg_server *server; + + struct wl_list link; // server::inhibitors + struct wl_listener destroy; +}; + +static void +idle_inhibit_v1_check_active(struct cg_server *server) +{ + /* Due to Cage's unique window management, we don't need to + check for visibility. In the worst cage, the inhibitor is + spawned by a dialog that _may_ be obscured by another + dialog, but this is really an edge case that, until + reported, does not warrant the additional complexity. + Hence, we simply check for any inhibitors and inhibit + accordingly. */ + bool inhibited = !wl_list_empty(&server->inhibitors); + wlr_idle_set_enabled(server->idle, NULL, !inhibited); +} + +static void +handle_destroy(struct wl_listener *listener, void *data) +{ + struct cg_idle_inhibitor_v1 *inhibitor = wl_container_of(listener, inhibitor, destroy); + struct cg_server *server = inhibitor->server; + + wl_list_remove(&inhibitor->link); + wl_list_remove(&inhibitor->destroy.link); + free(inhibitor); + + idle_inhibit_v1_check_active(server); +} + +void +handle_idle_inhibitor_v1_new(struct wl_listener *listener, void *data) +{ + struct cg_server *server = wl_container_of(listener, server, new_idle_inhibitor_v1); + struct wlr_idle_inhibitor_v1 *wlr_inhibitor = data; + + struct cg_idle_inhibitor_v1 *inhibitor = calloc(1, sizeof(struct cg_idle_inhibitor_v1)); + if (!inhibitor) { + return; + } + + inhibitor->server = server; + wl_list_insert(&server->inhibitors, &inhibitor->link); + + inhibitor->destroy.notify = handle_destroy; + wl_signal_add(&wlr_inhibitor->events.destroy, &inhibitor->destroy); + + idle_inhibit_v1_check_active(server); +} diff --git a/idle_inhibit_v1.h b/idle_inhibit_v1.h new file mode 100644 index 0000000..5cde94f --- /dev/null +++ b/idle_inhibit_v1.h @@ -0,0 +1,8 @@ +#ifndef CG_IDLE_INHIBIT_H +#define CG_IDLE_INHIBIT_H + +#include + +void handle_idle_inhibitor_v1_new(struct wl_listener *listener, void *data); + +#endif diff --git a/meson.build b/meson.build index d77e2cf..c97013c 100644 --- a/meson.build +++ b/meson.build @@ -56,6 +56,7 @@ conf_data.set10('CAGE_HAS_XWAYLAND', get_option('xwayland')) cage_sources = [ 'cage.c', + 'idle_inhibit_v1.c', 'output.c', 'seat.c', 'view.c', @@ -66,6 +67,7 @@ cage_headers = [ configure_file(input: 'config.h.in', output: 'config.h', configuration: conf_data), + 'idle_inhibit_v1.h', 'output.h', 'seat.h', 'server.h', diff --git a/server.h b/server.h index e2bc6a5..e93fd3e 100644 --- a/server.h +++ b/server.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #if CAGE_HAS_XWAYLAND #include @@ -23,6 +24,9 @@ struct cg_server { struct cg_seat *seat; struct wlr_idle *idle; + struct wlr_idle_inhibit_manager_v1 *idle_inhibit_v1; + struct wl_listener new_idle_inhibitor_v1; + struct wl_list inhibitors; struct wlr_output_layout *output_layout; struct cg_output *output;