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;