diff --git a/sway/idle.c b/sway/idle.c index 44dd70cd8..b6dd62ef6 100644 --- a/sway/idle.c +++ b/sway/idle.c @@ -6,14 +6,15 @@ #include #include #include +#include #include #include #ifdef WLR_HAS_SYSTEMD - #include - #include +#include +#include #elif defined(WLR_HAS_ELOGIND) - #include - #include +#include +#include #endif void invoke_swaylock() { @@ -27,9 +28,91 @@ void invoke_swaylock() { } #if defined(WLR_HAS_SYSTEMD) || defined(WLR_HAS_ELOGIND) + +bool have_lock() { + if (root_container.children == NULL) + return false; + if (root_container.children->items == NULL) + return false; + for (int i = 0; i < root_container.children->length; ++i) { + struct sway_container *output_container = + root_container.children->items[i]; + if (output_container == NULL) + return false; + struct sway_output *output = + output_container->sway_output; + if (output == NULL) + return false; + if (output->layers == NULL) + return false; + struct wl_list *layers = &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]; + if (layers == NULL) + return false; + struct sway_layer_surface *sway_layer; + wl_list_for_each_reverse(sway_layer, layers, link) { + struct wlr_layer_surface *surface = sway_layer->layer_surface; + if (!strcmp("lockscreen", surface->namespace)) + wlr_log(L_DEBUG, "Lockscreen found!"); + return true; + } + } + + wlr_log(L_DEBUG, "No lock"); + return false; +} + +static int fd = 0; +static int inhibit_cnt=0; + +static int cleanup_inhibit(void *data) { + fd = 0; + inhibit_cnt=0; + wlr_log(L_DEBUG, "Cleanup inhibit"); + return 0; +} + static int prepare_for_sleep(sd_bus_message *msg, void *userdata, sd_bus_error *ret_error) { + struct sway_server *server = userdata; + wlr_log(L_INFO, "PrepareForSleep signal received"); - invoke_swaylock(); + if(inhibit_cnt > 4 || have_lock()) { + wlr_log(L_INFO, "Already have lock, no inhibit"); + cleanup_inhibit(NULL); + return 0; + } + + wlr_log(L_INFO, "No lock, will inhibit"); + + struct sd_bus *bus; + int ret = sd_bus_default_system(&bus); + if (ret < 0) { + wlr_log(L_ERROR, "Failed to open D-Bus connection: %s", strerror(-ret)); + return 0; + } + + ret = sd_bus_call_method(bus, "org.freedesktop.login1", + "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "Inhibit", + ret_error, &msg, "ssss", "sleep", "sway-idle", "Setup Up Lock Screen", "delay"); + if (ret < 0) { + wlr_log(L_ERROR, "Failed to send Inhibit signal: %s", + strerror(-ret)); + } else { + ret = sd_bus_message_read(msg, "h", &fd); + if (ret < 0) { + wlr_log(L_ERROR, "Failed to parse D-Bus response for Inhibit: %s", strerror(-ret)); + } + } + + if (!inhibit_cnt) { + invoke_swaylock(); + + // 3 seconds should be well enough for 5 inhibits to be over and done + struct wl_event_source *source = wl_event_loop_add_timer(server->wl_event_loop, cleanup_inhibit, NULL); + wl_event_source_timer_update(source, 3000); + } + inhibit_cnt++; + + wlr_log(L_ERROR, "Inhibit done %d", inhibit_cnt); return 0; } @@ -49,7 +132,7 @@ void setup_sleep_listener(struct sway_server *server) { "path='%s'"; snprintf(str, sizeof(str), fmt, "Manager", "PrepareForSleep", "/org/freedesktop/login1"); - ret = sd_bus_add_match(bus, NULL, str, prepare_for_sleep, NULL); + ret = sd_bus_add_match(bus, NULL, str, prepare_for_sleep, server); if (ret < 0) { wlr_log(L_ERROR, "Failed to add D-Bus match: %s", strerror(-ret)); return; @@ -112,10 +195,21 @@ void idle_setup_seat(struct sway_server *server, struct sway_seat *seat) { return; } if (config != NULL) { - wlr_log(L_DEBUG, "Setup idle timer %d", config->idle_timeout); - wlr_idle_listen(server->idle, config->idle_timeout * 1000, &idle_listener, seat->wlr_seat); - wlr_log(L_DEBUG, "Setup lock timer %d", config->lock_timeout); - wlr_idle_listen(server->idle, config->lock_timeout * 1000, &lock_listener, seat->wlr_seat); + if (config->idle_timeout > 0) { + wlr_log(L_DEBUG, "Setup idle timer %d", config->idle_timeout); + wlr_idle_listen(server->idle, config->idle_timeout * 1000, &idle_listener, seat->wlr_seat); + } else { + wlr_log(L_INFO, "Idle timeout set to 0, will disable screen power management"); + } + if (config->lock_timeout > 0) { + wlr_log(L_DEBUG, "Setup lock timer %d", config->lock_timeout); + wlr_idle_listen(server->idle, config->lock_timeout * 1000, &lock_listener, seat->wlr_seat); +#if defined(WLR_HAS_SYSTEMD) || defined(WLR_HAS_ELOGIND) + setup_sleep_listener(server); +#endif + } else { + wlr_log(L_INFO, "Lock timeout set to 0, will disable auto lock"); + } } else { wlr_log(L_ERROR, "Cant setup idle timers for seat since no config is available!"); } @@ -128,10 +222,6 @@ bool idle_init(struct sway_server *server) { wl_list_for_each(seat, &input_manager->seats, link) { idle_setup_seat(server, seat); } -#if defined(WLR_HAS_SYSTEMD) || defined(WLR_HAS_ELOGIND) - setup_sleep_listener(server); -#endif - return true; }