Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package swayidle for openSUSE:Factory checked in at 2021-08-20 16:57:41 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/swayidle (Old) and /work/SRC/openSUSE:Factory/.swayidle.new.1899 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "swayidle" Fri Aug 20 16:57:41 2021 rev:7 rq:913012 version:1.7 Changes: -------- --- /work/SRC/openSUSE:Factory/swayidle/swayidle.changes 2020-01-23 15:55:13.159104811 +0100 +++ /work/SRC/openSUSE:Factory/.swayidle.new.1899/swayidle.changes 2021-08-20 16:57:48.470879645 +0200 @@ -1,0 +2,9 @@ +Tue Aug 17 18:17:06 UTC 2021 - Michael Vetter <mvet...@suse.com> + +- Update to 1.7: + * swayidle can be configured in a file instead of CLI arguments + * The seat can be selected with the -S flag + * logind idle inhibitors are now supported +- Remove swayidle-version.patch: upstreamed + +------------------------------------------------------------------- Old: ---- 1.6.tar.gz swayidle-version.patch New: ---- 1.7.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ swayidle.spec ++++++ --- /var/tmp/diff_new_pack.qR8NTN/_old 2021-08-20 16:57:50.170877057 +0200 +++ /var/tmp/diff_new_pack.qR8NTN/_new 2021-08-20 16:57:50.174877051 +0200 @@ -1,7 +1,7 @@ # # spec file for package swayidle # -# Copyright (c) 2020 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,15 +17,13 @@ Name: swayidle -Version: 1.6 +Version: 1.7 Release: 0 Summary: Idle management daemon for Wayland License: MIT Group: System/GUI/Other URL: https://github.com/swaywm/swayidle Source0: https://github.com/swaywm/swayidle/archive/%{version}.tar.gz -# https://github.com/swaywm/swayidle/pull/53 -Patch0: swayidle-version.patch BuildRequires: meson >= 0.48.0 BuildRequires: pkgconfig BuildRequires: scdoc @@ -69,7 +67,6 @@ %prep %setup -q -%patch0 -p1 %build export CFLAGS="%{optflags} -I/usr/include/wayland" ++++++ 1.6.tar.gz -> 1.7.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/swayidle-1.6/completions/fish/swayidle.fish new/swayidle-1.7/completions/fish/swayidle.fish --- old/swayidle-1.6/completions/fish/swayidle.fish 2020-01-22 17:20:22.000000000 +0100 +++ new/swayidle-1.7/completions/fish/swayidle.fish 2021-05-16 17:38:17.000000000 +0200 @@ -1,4 +1,12 @@ # swayidle +set -l all_events timeout before-sleep after-resume lock unlock idlehint +set -l cmd_events before-sleep after-resume lock unlock +set -l time_events idlehint timeout + +complete -c swayidle --arguments "$all_events" +complete -c swayidle --condition "__fish_seen_subcommand_from $cmd_events" --require-parameter +complete -c swayidle --condition "__fish_seen_subcommand_from $time_events" --exclusive + complete -c swayidle -s h --description 'show help' complete -c swayidle -s d --description 'debug' complete -c swayidle -s w --description 'wait for command to finish' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/swayidle-1.6/main.c new/swayidle-1.7/main.c --- old/swayidle-1.6/main.c 2020-01-22 17:20:22.000000000 +0100 +++ new/swayidle-1.7/main.c 2021-05-16 17:38:17.000000000 +0200 @@ -1,8 +1,6 @@ #define _POSIX_C_SOURCE 200809L -#include <assert.h> #include <errno.h> #include <fcntl.h> -#include <getopt.h> #include <signal.h> #include <stdarg.h> #include <stdio.h> @@ -14,6 +12,7 @@ #include <wayland-client.h> #include <wayland-server.h> #include <wayland-util.h> +#include <wordexp.h> #include "config.h" #include "idle-client-protocol.h" #if HAVE_SYSTEMD @@ -31,11 +30,14 @@ struct wl_display *display; struct wl_event_loop *event_loop; struct wl_list timeout_cmds; // struct swayidle_timeout_cmd * + struct wl_list seats; + char *seat_name; char *before_sleep_cmd; char *after_resume_cmd; char *logind_lock_cmd; char *logind_unlock_cmd; bool logind_idlehint; + bool timeouts_enabled; bool wait; } state; @@ -46,6 +48,15 @@ char *idle_cmd; char *resume_cmd; bool idlehint; + bool resume_pending; +}; + +struct seat { + struct wl_list link; + struct wl_seat *proxy; + + char *name; + uint32_t capabilities; }; enum log_importance { @@ -79,9 +90,31 @@ fprintf(stderr, ": %s\n", strerror(errno)); } +static void swayidle_init() { + memset(&state, 0, sizeof(state)); + wl_list_init(&state.timeout_cmds); + wl_list_init(&state.seats); +} + +static void swayidle_finish() { + + struct swayidle_timeout_cmd *cmd; + struct swayidle_timeout_cmd *tmp; + wl_list_for_each_safe(cmd, tmp, &state.timeout_cmds, link) { + wl_list_remove(&cmd->link); + free(cmd->idle_cmd); + free(cmd->resume_cmd); + free(cmd); + } + + free(state.after_resume_cmd); + free(state.before_sleep_cmd); +} + void sway_terminate(int exit_code) { wl_display_disconnect(state.display); wl_event_loop_destroy(state.event_loop); + swayidle_finish(); exit(exit_code); } @@ -111,39 +144,47 @@ } #if HAVE_SYSTEMD || HAVE_ELOGIND -static int lock_fd = -1; +#define DBUS_LOGIND_SERVICE "org.freedesktop.login1" +#define DBUS_LOGIND_PATH "/org/freedesktop/login1" +#define DBUS_LOGIND_MANAGER_INTERFACE "org.freedesktop.login1.Manager" +#define DBUS_LOGIND_SESSION_INTERFACE "org.freedesktop.login1.Session" + +static void enable_timeouts(void); +static void disable_timeouts(void); + +static int sleep_lock_fd = -1; static struct sd_bus *bus = NULL; static char *session_name = NULL; -static void acquire_sleep_lock(void) { +static void acquire_inhibitor_lock(const char *type, const char *mode, + int *fd) { sd_bus_message *msg = NULL; sd_bus_error error = SD_BUS_ERROR_NULL; - int ret = sd_bus_call_method(bus, "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", "Inhibit", - &error, &msg, "ssss", "sleep", "swayidle", - "Setup Up Lock Screen", "delay"); + char why[35]; + + sprintf(why, "Swayidle is preventing %s", type); + int ret = sd_bus_call_method(bus, DBUS_LOGIND_SERVICE, DBUS_LOGIND_PATH, + DBUS_LOGIND_MANAGER_INTERFACE, "Inhibit", &error, &msg, + "ssss", type, "swayidle", why, mode); if (ret < 0) { swayidle_log(LOG_ERROR, - "Failed to send Inhibit signal: %s", error.message); + "Failed to send %s inhibit signal: %s", type, error.message); goto cleanup; } - ret = sd_bus_message_read(msg, "h", &lock_fd); + ret = sd_bus_message_read(msg, "h", fd); if (ret < 0) { errno = -ret; swayidle_log_errno(LOG_ERROR, - "Failed to parse D-Bus response for Inhibit"); + "Failed to parse D-Bus response for %s inhibit", type); goto cleanup; } - // sd_bus_message_unref closes the file descriptor so we need - // to copy it beforehand - lock_fd = fcntl(lock_fd, F_DUPFD_CLOEXEC, 3); - if (lock_fd >= 0) { - swayidle_log(LOG_INFO, "Got sleep lock: %d", lock_fd); + *fd = fcntl(*fd, F_DUPFD_CLOEXEC, 3); + if (*fd >= 0) { + swayidle_log(LOG_DEBUG, "Got %s lock: %d", type, *fd); } else { - swayidle_log_errno(LOG_ERROR, "Failed to copy sleep lock fd"); + swayidle_log_errno(LOG_ERROR, "Failed to copy %s lock fd", type); } cleanup: @@ -151,12 +192,19 @@ sd_bus_message_unref(msg); } +static void release_inhibitor_lock(int fd) { + if (fd >= 0) { + swayidle_log(LOG_DEBUG, "Releasing inhibitor lock %d", fd); + close(fd); + } +} + static void set_idle_hint(bool hint) { swayidle_log(LOG_DEBUG, "SetIdleHint %d", hint); sd_bus_message *msg = NULL; sd_bus_error error = SD_BUS_ERROR_NULL; - int ret = sd_bus_call_method(bus, "org.freedesktop.login1", - session_name, "org.freedesktop.login1.Session", "SetIdleHint", + int ret = sd_bus_call_method(bus, DBUS_LOGIND_SERVICE, + session_name, DBUS_LOGIND_SESSION_INTERFACE, "SetIdleHint", &error, &msg, "b", hint); if (ret < 0) { swayidle_log(LOG_ERROR, @@ -167,6 +215,36 @@ sd_bus_message_unref(msg); } +static bool get_logind_idle_inhibit(void) { + const char *locks; + bool res; + + sd_bus_message *reply = NULL; + + int ret = sd_bus_get_property(bus, DBUS_LOGIND_SERVICE, DBUS_LOGIND_PATH, + DBUS_LOGIND_MANAGER_INTERFACE, "BlockInhibited", NULL, &reply, "s"); + if (ret < 0) { + goto error; + } + + ret = sd_bus_message_read_basic(reply, 's', &locks); + if (ret < 0) { + goto error; + } + + res = strstr(locks, "idle") != NULL; + sd_bus_message_unref(reply); + + return res; + +error: + sd_bus_message_unref(reply); + errno = -ret; + swayidle_log_errno(LOG_ERROR, + "Failed to parse get BlockInhibited property"); + return false; +} + static int prepare_for_sleep(sd_bus_message *msg, void *userdata, sd_bus_error *ret_error) { /* "b" apparently reads into an int, not a bool */ @@ -179,7 +257,7 @@ } swayidle_log(LOG_DEBUG, "PrepareForSleep signal received %d", going_down); if (!going_down) { - acquire_sleep_lock(); + acquire_inhibitor_lock("sleep", "delay", &sleep_lock_fd); if (state.after_resume_cmd) { cmd_exec(state.after_resume_cmd); } @@ -194,14 +272,10 @@ } swayidle_log(LOG_DEBUG, "Prepare for sleep done"); - swayidle_log(LOG_INFO, "Releasing sleep lock %d", lock_fd); - if (lock_fd >= 0) { - close(lock_fd); - } - lock_fd = -1; - + release_inhibitor_lock(sleep_lock_fd); return 0; } + static int handle_lock(sd_bus_message *msg, void *userdata, sd_bus_error *ret_error) { swayidle_log(LOG_DEBUG, "Lock signal received"); @@ -229,6 +303,66 @@ return 0; } +static int handle_property_changed(sd_bus_message *msg, void *userdata, + sd_bus_error *ret_error) { + const char *name; + swayidle_log(LOG_DEBUG, "PropertiesChanged signal received"); + + int ret = sd_bus_message_read_basic(msg, 's', &name); + if (ret < 0) { + goto error; + } + + if (!strcmp(name, DBUS_LOGIND_MANAGER_INTERFACE)) { + swayidle_log(LOG_DEBUG, "Got PropertyChanged: %s", name); + ret = sd_bus_message_enter_container(msg, 'a', "{sv}"); + if (ret < 0) { + goto error; + } + + const char *prop; + while ((ret = sd_bus_message_enter_container(msg, 'e', "sv")) > 0) { + ret = sd_bus_message_read_basic(msg, 's', &prop); + if (ret < 0) { + goto error; + } + + if (!strcmp(prop, "BlockInhibited")) { + if (get_logind_idle_inhibit()) { + swayidle_log(LOG_DEBUG, "Logind idle inhibitor found"); + disable_timeouts(); + } else { + swayidle_log(LOG_DEBUG, "Logind idle inhibitor not found"); + enable_timeouts(); + } + return 0; + } else { + ret = sd_bus_message_skip(msg, "v"); + if (ret < 0) { + goto error; + } + } + + ret = sd_bus_message_exit_container(msg); + if (ret < 0) { + goto error; + } + } + } + + if (ret < 0) { + goto error; + } + + return 0; + +error: + errno = -ret; + swayidle_log_errno(LOG_ERROR, + "Failed to parse D-Bus response for PropertyChanged"); + return 0; +} + static int dbus_event(int fd, uint32_t mask, void *data) { sd_bus *bus = data; @@ -255,57 +389,74 @@ return count; } -static void connect_to_bus(void) { - int ret = sd_bus_default_system(&bus); +static void set_session(void) { sd_bus_message *msg = NULL; sd_bus_error error = SD_BUS_ERROR_NULL; - pid_t my_pid = getpid(); const char *session_name_tmp; + + int ret = sd_bus_call_method(bus, DBUS_LOGIND_SERVICE, DBUS_LOGIND_PATH, + DBUS_LOGIND_MANAGER_INTERFACE, "GetSession", + &error, &msg, "s", "auto"); if (ret < 0) { - errno = -ret; - swayidle_log_errno(LOG_ERROR, "Failed to open D-Bus connection"); - return; - } - struct wl_event_source *source = wl_event_loop_add_fd(state.event_loop, - sd_bus_get_fd(bus), WL_EVENT_READABLE, dbus_event, bus); - wl_event_source_check(source); - ret = sd_bus_call_method(bus, "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", "GetSessionByPID", - &error, &msg, "u", my_pid); - if (ret < 0) { - swayidle_log(LOG_ERROR, - "Failed to find session name: %s", error.message); - goto cleanup; + swayidle_log(LOG_DEBUG, + "GetSession failed: %s", error.message); + sd_bus_error_free(&error); + sd_bus_message_unref(msg); + + ret = sd_bus_call_method(bus, DBUS_LOGIND_SERVICE, DBUS_LOGIND_PATH, + DBUS_LOGIND_MANAGER_INTERFACE, "GetSessionByPID", + &error, &msg, "u", getpid()); + if (ret < 0) { + swayidle_log(LOG_DEBUG, + "GetSessionByPID failed: %s", error.message); + swayidle_log(LOG_ERROR, + "Failed to find session"); + goto cleanup; + } } ret = sd_bus_message_read(msg, "o", &session_name_tmp); if (ret < 0) { swayidle_log(LOG_ERROR, - "Failed to read session name\n"); + "Failed to read session name"); goto cleanup; } session_name = strdup(session_name_tmp); + swayidle_log(LOG_DEBUG, "Using session: %s", session_name); + cleanup: sd_bus_error_free(&error); sd_bus_message_unref(msg); } +static void connect_to_bus(void) { + int ret = sd_bus_default_system(&bus); + if (ret < 0) { + errno = -ret; + swayidle_log_errno(LOG_ERROR, "Failed to open D-Bus connection"); + return; + } + struct wl_event_source *source = wl_event_loop_add_fd(state.event_loop, + sd_bus_get_fd(bus), WL_EVENT_READABLE, dbus_event, bus); + wl_event_source_check(source); + set_session(); +} + static void setup_sleep_listener(void) { - int ret = sd_bus_match_signal(bus, NULL, "org.freedesktop.login1", - "/org/freedesktop/login1", "org.freedesktop.login1.Manager", + int ret = sd_bus_match_signal(bus, NULL, DBUS_LOGIND_SERVICE, + DBUS_LOGIND_PATH, DBUS_LOGIND_MANAGER_INTERFACE, "PrepareForSleep", prepare_for_sleep, NULL); if (ret < 0) { errno = -ret; swayidle_log_errno(LOG_ERROR, "Failed to add D-Bus signal match : sleep"); return; } - acquire_sleep_lock(); + acquire_inhibitor_lock("sleep", "delay", &sleep_lock_fd); } static void setup_lock_listener(void) { - int ret = sd_bus_match_signal(bus, NULL, "org.freedesktop.login1", - session_name, "org.freedesktop.login1.Session", + int ret = sd_bus_match_signal(bus, NULL, DBUS_LOGIND_SERVICE, + session_name, DBUS_LOGIND_SESSION_INTERFACE, "Lock", handle_lock, NULL); if (ret < 0) { errno = -ret; @@ -315,8 +466,8 @@ } static void setup_unlock_listener(void) { - int ret = sd_bus_match_signal(bus, NULL, "org.freedesktop.login1", - session_name, "org.freedesktop.login1.Session", + int ret = sd_bus_match_signal(bus, NULL, DBUS_LOGIND_SERVICE, + session_name, DBUS_LOGIND_SESSION_INTERFACE, "Unlock", handle_unlock, NULL); if (ret < 0) { errno = -ret; @@ -324,15 +475,47 @@ return; } } + +static void setup_property_changed_listener(void) { + int ret = sd_bus_match_signal(bus, NULL, NULL, + DBUS_LOGIND_PATH, "org.freedesktop.DBus.Properties", + "PropertiesChanged", handle_property_changed, NULL); + if (ret < 0) { + errno = -ret; + swayidle_log_errno(LOG_ERROR, "Failed to add D-Bus signal match : property changed"); + return; + } +} #endif +static void seat_handle_capabilities(void *data, struct wl_seat *seat, + uint32_t capabilities) { + struct seat *self = data; + self->capabilities = capabilities; +} + +static void seat_handle_name(void *data, struct wl_seat *seat, + const char *name) { + struct seat *self = data; + self->name = strdup(name); +} + +static const struct wl_seat_listener wl_seat_listener = { + .name = seat_handle_name, + .capabilities = seat_handle_capabilities, +}; + static void handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { if (strcmp(interface, org_kde_kwin_idle_interface.name) == 0) { idle_manager = wl_registry_bind(registry, name, &org_kde_kwin_idle_interface, 1); } else if (strcmp(interface, wl_seat_interface.name) == 0) { - seat = wl_registry_bind(registry, name, &wl_seat_interface, 1); + struct seat *s = calloc(1, sizeof(struct seat)); + s->proxy = wl_registry_bind(registry, name, &wl_seat_interface, 2); + + wl_seat_add_listener(s->proxy, &wl_seat_listener, s); + wl_list_insert(&state.seats, &s->link); } } @@ -348,12 +531,17 @@ static const struct org_kde_kwin_idle_timeout_listener idle_timer_listener; -static void register_timeout(struct swayidle_timeout_cmd *cmd, - int timeout) { +static void destroy_cmd_timer(struct swayidle_timeout_cmd *cmd) { if (cmd->idle_timer != NULL) { org_kde_kwin_idle_timeout_destroy(cmd->idle_timer); cmd->idle_timer = NULL; } +} + +static void register_timeout(struct swayidle_timeout_cmd *cmd, + int timeout) { + destroy_cmd_timer(cmd); + if (timeout < 0) { swayidle_log(LOG_DEBUG, "Not registering idle timeout"); return; @@ -366,8 +554,46 @@ cmd->registered_timeout = timeout; } +static void enable_timeouts(void) { + if (state.timeouts_enabled) { + return; + } +#if HAVE_SYSTEMD || HAVE_ELOGIND + if (get_logind_idle_inhibit()) { + swayidle_log(LOG_INFO, "Not enabling timeouts: idle inhibitor found"); + return; + } +#endif + swayidle_log(LOG_DEBUG, "Enable idle timeouts"); + + state.timeouts_enabled = true; + struct swayidle_timeout_cmd *cmd; + wl_list_for_each(cmd, &state.timeout_cmds, link) { + register_timeout(cmd, cmd->timeout); + } +} + +#if HAVE_SYSTEMD || HAVE_ELOGIND +static void disable_timeouts(void) { + if (!state.timeouts_enabled) { + return; + } + swayidle_log(LOG_DEBUG, "Disable idle timeouts"); + + state.timeouts_enabled = false; + struct swayidle_timeout_cmd *cmd; + wl_list_for_each(cmd, &state.timeout_cmds, link) { + destroy_cmd_timer(cmd); + } + if (state.logind_idlehint) { + set_idle_hint(false); + } +} +#endif + static void handle_idle(void *data, struct org_kde_kwin_idle_timeout *timer) { struct swayidle_timeout_cmd *cmd = data; + cmd->resume_pending = true; swayidle_log(LOG_DEBUG, "idle state"); #if HAVE_SYSTEMD || HAVE_ELOGIND if (cmd->idlehint) { @@ -381,6 +607,7 @@ static void handle_resume(void *data, struct org_kde_kwin_idle_timeout *timer) { struct swayidle_timeout_cmd *cmd = data; + cmd->resume_pending = false; swayidle_log(LOG_DEBUG, "active state"); if (cmd->registered_timeout != cmd->timeout) { register_timeout(cmd, cmd->timeout); @@ -423,6 +650,7 @@ struct swayidle_timeout_cmd *cmd = calloc(1, sizeof(struct swayidle_timeout_cmd)); cmd->idlehint = false; + cmd->resume_pending = false; if (seconds > 0) { cmd->timeout = seconds * 1000; @@ -561,30 +789,37 @@ return 2; } -static int parse_args(int argc, char *argv[]) { +static int parse_args(int argc, char *argv[], char **config_path) { int c; - while ((c = getopt(argc, argv, "hdw")) != -1) { + while ((c = getopt(argc, argv, "C:hdwS:")) != -1) { switch (c) { + case 'C': + free(*config_path); + *config_path = strdup(optarg); + break; case 'd': verbosity = LOG_DEBUG; break; case 'w': state.wait = true; break; + case 'S': + state.seat_name = strdup(optarg); + break; case 'h': case '?': printf("Usage: %s [OPTIONS]\n", argv[0]); printf(" -h\tthis help menu\n"); + printf(" -C\tpath to config file\n"); printf(" -d\tdebug\n"); printf(" -w\twait for command to finish\n"); + printf(" -S\tpick the seat to work with\n"); return 1; default: return 1; } } - wl_list_init(&state.timeout_cmds); - int i = optind; while (i < argc) { if (!strcmp("timeout", argv[i])) { @@ -615,20 +850,26 @@ } static int handle_signal(int sig, void *data) { + struct swayidle_timeout_cmd *cmd; switch (sig) { case SIGINT: case SIGTERM: + swayidle_log(LOG_DEBUG, "Got SIGTERM"); + wl_list_for_each(cmd, &state.timeout_cmds, link) { + if (cmd->resume_pending) { + handle_resume(cmd, cmd->idle_timer); + } + } sway_terminate(0); return 0; case SIGUSR1: swayidle_log(LOG_DEBUG, "Got SIGUSR1"); - struct swayidle_timeout_cmd *cmd; wl_list_for_each(cmd, &state.timeout_cmds, link) { register_timeout(cmd, 0); } return 1; } - assert(false); // not reached + abort(); // not reached } static int display_event(int fd, uint32_t mask, void *data) { @@ -656,11 +897,116 @@ return count; } +static char *get_config_path(void) { + static char *config_paths[3] = { + "$XDG_CONFIG_HOME/swayidle/config", + "$HOME/.swayidle/config", + SYSCONFDIR "/swayidle/config", + }; + + char *config_home = getenv("XDG_CONFIG_HOME"); + + if (!config_home || config_home[0] == '\n') { + config_paths[0] = "$HOME/.config/swayidle/config"; + } + + wordexp_t p; + char *path; + for (size_t i = 0; i < sizeof(config_paths) / sizeof(char *); ++i) { + if (wordexp(config_paths[i], &p, 0) == 0) { + path = strdup(p.we_wordv[0]); + wordfree(&p); + if (path && access(path, R_OK) == 0) { + return path; + } + free(path); + } + } + + return NULL; +} + +static int load_config(const char *config_path) { + FILE *f = fopen(config_path, "r"); + + if (!f) { + return -ENOENT; + } + + size_t lineno = 0; + char *line = NULL; + size_t n = 0; + ssize_t nread; + while ((nread = getline(&line, &n, f)) != -1) { + lineno++; + if (line[nread-1] == '\n') { + line[nread-1] = '\0'; + } + + if (strlen(line) == 0 || line[0] == '#') { + continue; + } + + size_t i = 0; + while (line[i] != '\0' && line[i] != ' ') { + i++; + } + + wordexp_t p; + wordexp(line, &p, 0); + if (strncmp("timeout", line, i) == 0) { + parse_timeout(p.we_wordc, p.we_wordv); + } else if (strncmp("before-sleep", line, i) == 0) { + parse_sleep(p.we_wordc, p.we_wordv); + } else if (strncmp("after-resume", line, i) == 0) { + parse_resume(p.we_wordc, p.we_wordv); + } else if (strncmp("lock", line, i) == 0) { + parse_lock(p.we_wordc, p.we_wordv); + } else if (strncmp("unlock", line, i) == 0) { + parse_unlock(p.we_wordc, p.we_wordv); + } else if (strncmp("idlehint", line, i) == 0) { + parse_idlehint(p.we_wordc, p.we_wordv); + } else { + line[i] = 0; + swayidle_log(LOG_ERROR, "Unexpected keyword \"%s\" in line %lu", line, lineno); + free(line); + return -EINVAL; + } + wordfree(&p); + } + free(line); + fclose(f); + + return 0; +} + + int main(int argc, char *argv[]) { - if (parse_args(argc, argv) != 0) { + swayidle_init(); + char *config_path = NULL; + if (parse_args(argc, argv, &config_path) != 0) { + swayidle_finish(); + free(config_path); return -1; } + if (!config_path) { + config_path = get_config_path(); + } + + int config_load = load_config(config_path); + + if (config_load == -ENOENT) { + swayidle_log(LOG_DEBUG, "No config file found."); + } else if (config_load == -EINVAL) { + swayidle_log(LOG_ERROR, "Config file %s has errors, exiting.", config_path); + exit(-1); + } else { + swayidle_log(LOG_DEBUG, "Loaded config at %s", config_path); + } + + free(config_path); + state.event_loop = wl_event_loop_create(); wl_event_loop_add_signal(state.event_loop, SIGINT, handle_signal, NULL); @@ -672,25 +1018,41 @@ swayidle_log(LOG_ERROR, "Unable to connect to the compositor. " "If your compositor is running, check or set the " "WAYLAND_DISPLAY environment variable."); + swayidle_finish(); return -3; } struct wl_registry *registry = wl_display_get_registry(state.display); wl_registry_add_listener(registry, ®istry_listener, NULL); wl_display_roundtrip(state.display); + wl_display_roundtrip(state.display); + + struct seat *seat_i; + wl_list_for_each(seat_i, &state.seats, link) { + if (state.seat_name == NULL || strcmp(seat_i->name, state.seat_name) == 0) { + seat = seat_i->proxy; + } + } if (idle_manager == NULL) { swayidle_log(LOG_ERROR, "Display doesn't support idle protocol"); + swayidle_finish(); return -4; } if (seat == NULL) { - swayidle_log(LOG_ERROR, "Seat error"); + if (state.seat_name != NULL) { + swayidle_log(LOG_ERROR, "Seat %s not found", state.seat_name); + } else { + swayidle_log(LOG_ERROR, "No seat found"); + } + swayidle_finish(); return -5; } bool should_run = !wl_list_empty(&state.timeout_cmds); #if HAVE_SYSTEMD || HAVE_ELOGIND connect_to_bus(); + setup_property_changed_listener(); if (state.before_sleep_cmd || state.after_resume_cmd) { should_run = true; setup_sleep_listener(); @@ -712,11 +1074,7 @@ sway_terminate(0); } - struct swayidle_timeout_cmd *cmd; - wl_list_for_each(cmd, &state.timeout_cmds, link) { - register_timeout(cmd, cmd->timeout); - } - + enable_timeouts(); wl_display_roundtrip(state.display); struct wl_event_source *source = wl_event_loop_add_fd(state.event_loop, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/swayidle-1.6/meson.build new/swayidle-1.7/meson.build --- old/swayidle-1.6/meson.build 2020-01-22 17:20:22.000000000 +0100 +++ new/swayidle-1.7/meson.build 2021-05-16 17:38:17.000000000 +0200 @@ -1,7 +1,7 @@ project( 'swayidle', 'c', - version: '1.5', + version: '1.7', license: 'MIT', meson_version: '>=0.48.0', default_options: [ @@ -21,6 +21,12 @@ language: 'c', ) +sysconfdir = get_option('sysconfdir') +prefix = get_option('prefix') +add_project_arguments( + '-DSYSCONFDIR="@0@"'.format(join_paths(prefix, sysconfdir)), + language : 'c') + wayland_client = dependency('wayland-client') wayland_protos = dependency('wayland-protocols', version: '>=1.14') wayland_server = dependency('wayland-server') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/swayidle-1.6/swayidle.1.scd new/swayidle-1.7/swayidle.1.scd --- old/swayidle-1.6/swayidle.1.scd 2020-01-22 17:20:22.000000000 +0100 +++ new/swayidle-1.7/swayidle.1.scd 2021-05-16 17:38:17.000000000 +0200 @@ -10,6 +10,11 @@ # OPTIONS +*-C* <path> + The config file to use. By default, the following paths are checked in the following order: $XDG_CONFIG_HOME/swayidle/config, $HOME/swayidle/config + Config file entries are events as described in the EVENTS section. + Specifying events in the config and as arguments is not mutually exclusive. + *-h* Show help message and quit. @@ -22,13 +27,14 @@ Note: using this option causes swayidle to block until the command finishes. +*-S* <seat-name> + Specify which seat to use. By default, if no name is specified, an arbitrary seat will be picked instead. + # DESCRIPTION swayidle listens for idle activity on your Wayland compositor and executes tasks on various idle-related events. You can specify any number of events at the -command line. - -Sending SIGUSR1 to swayidle will immediately enter idle state. +command line and in the config file. # EVENTS @@ -59,19 +65,29 @@ session should be unlocked *idlehint* <timeout> - If built with systemd support, set IdleHint to indcate an idle logind/elogind + If built with systemd support, set IdleHint to indicate an idle logind/elogind session after <timeout> seconds. Adding an idlehint event will also cause swayidle to call SetIdleHint(false) when run, on resume, unlock, etc. All commands are executed in a shell. +# SIGNALS + +swayidle responds to the following signals: + +*SIGTERM, SIGINT* + Run all pending resume commands. When finished swayidle will terminate. + +*SIGUSR1* + Immediately enter idle state. + # EXAMPLE ``` -swayidle -w \ - timeout 300 'swaylock -f -c 000000' \ - timeout 600 'swaymsg "output * dpms off"' \ - resume 'swaymsg "output * dpms on"' \ +swayidle -w \\ + timeout 300 'swaylock -f -c 000000' \\ + timeout 600 'swaymsg "output * dpms off"' \\ + resume 'swaymsg "output * dpms on"' \\ before-sleep 'swaylock -f -c 000000' ```