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, &registry_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'
 ```
 

Reply via email to