diff options
-rw-r--r-- | completions/bash/swayidle | 48 | ||||
-rw-r--r-- | completions/fish/swayidle.fish | 3 | ||||
-rw-r--r-- | completions/zsh/_swayidle | 22 | ||||
-rw-r--r-- | meson.build | 4 | ||||
-rw-r--r-- | sway/config.c | 10 | ||||
-rw-r--r-- | swayidle/main.c | 483 | ||||
-rw-r--r-- | swayidle/meson.build | 27 | ||||
-rw-r--r-- | swayidle/swayidle.1.scd | 63 |
8 files changed, 7 insertions, 653 deletions
diff --git a/completions/bash/swayidle b/completions/bash/swayidle deleted file mode 100644 index a0cdc8b2..00000000 --- a/completions/bash/swayidle +++ /dev/null @@ -1,48 +0,0 @@ -# swaymsg(1) completion - -_swayidle() -{ - local cur prev - _get_comp_words_by_ref -n : cur prev - local prev2=${COMP_WORDS[COMP_CWORD-2]} - local prev3=${COMP_WORDS[COMP_CWORD-3]} - - events=( - 'timeout' - 'before-sleep' - ) - - short=( - -h - -d - ) - - if [ "$prev" = timeout ]; then - # timeout <timeout> - return - elif [ "$prev2" = timeout ]; then - # timeout <timeout> <timeout command> - COMPREPLY=($(compgen -c -- "$cur")) - return - elif [ "$prev3" = timeout ]; then - # timeout <timeout> <timeout command> [resume <resume command>] - COMPREPLY=(resume) - # optional argument; no return here as user may skip 'resume' - fi - - case "$prev" in - resume) - COMPREPLY=($(compgen -c -- "$cur")) - return - ;; - before-sleep) - COMPREPLY=($(compgen -c -- "$cur")) - return - ;; - esac - - COMPREPLY+=($(compgen -W "${events[*]}" -- "$cur")) - COMPREPLY+=($(compgen -W "${short[*]}" -- "$cur")) - -} && -complete -F _swayidle swayidle diff --git a/completions/fish/swayidle.fish b/completions/fish/swayidle.fish deleted file mode 100644 index 71279925..00000000 --- a/completions/fish/swayidle.fish +++ /dev/null @@ -1,3 +0,0 @@ -# swayidle -complete -c swayidle -s h --description 'show help' -complete -c swayidle -s d --description 'debug' diff --git a/completions/zsh/_swayidle b/completions/zsh/_swayidle deleted file mode 100644 index b419bc2c..00000000 --- a/completions/zsh/_swayidle +++ /dev/null @@ -1,22 +0,0 @@ -#compdef swayidle -# -# Completion script for swayidle -# - -local events=('timeout:Execute timeout command if there is no activity for timeout seconds' - 'before-sleep:Execute before-sleep command before sleep') -local resume=('resume:Execute command when there is activity again') - -if (($#words <= 2)); then - _arguments -C \ - '(-h --help)'{-h,--help}'[Show help message and quit]' \ - '(-d)'-d'[Enable debug output]' - _describe -t "events" 'swayidle' events - -elif [[ "$words[-3]" == before-sleep || "$words[-3]" == resume ]]; then - _describe -t "events" 'swayidle' events - -elif [[ "$words[-4]" == timeout ]]; then - _describe -t "events" 'swayidle' events - _describe -t "resume" 'swayidle' resume -fi diff --git a/meson.build b/meson.build index b1353b59..bffbe312 100644 --- a/meson.build +++ b/meson.build @@ -86,7 +86,6 @@ if scdoc.found() 'sway/sway-output.5.scd', 'swaylock/swaylock.1.scd', 'swaymsg/swaymsg.1.scd', - 'swayidle/swayidle.1.scd', 'swaynag/swaynag.1.scd', 'swaynag/swaynag.5.scd', ] @@ -146,7 +145,6 @@ subdir('swaymsg') subdir('client') subdir('swaybg') subdir('swaybar') -subdir('swayidle') subdir('swaynag') subdir('swaylock') @@ -214,7 +212,6 @@ if (get_option('bash-completions')) bash_files = files( 'completions/bash/sway', 'completions/bash/swaybar', - 'completions/bash/swayidle', 'completions/bash/swaylock', 'completions/bash/swaymsg', ) @@ -226,7 +223,6 @@ endif if (get_option('fish-completions')) fish_files = files( 'completions/fish/sway.fish', - 'completions/fish/swayidle.fish', 'completions/fish/swaylock.fish', 'completions/fish/swaymsg.fish', 'completions/fish/swaynag.fish', diff --git a/sway/config.c b/sway/config.c index 26d22842..b14ebba7 100644 --- a/sway/config.c +++ b/sway/config.c @@ -571,15 +571,18 @@ bool load_include_configs(const char *path, struct sway_config *config, } // get line, with backslash continuation -static ssize_t getline_with_cont(char **lineptr, size_t *line_size, FILE *file) { +static ssize_t getline_with_cont(char **lineptr, size_t *line_size, FILE *file, + int *nlines) { char *next_line = NULL; size_t next_line_size = 0; ssize_t nread = getline(lineptr, line_size, file); + *nlines = nread == -1 ? 0 : 1; while (nread >= 2 && strcmp(&(*lineptr)[nread - 2], "\\\n") == 0) { ssize_t next_nread = getline(&next_line, &next_line_size, file); if (next_nread == -1) { break; } + (*nlines)++; nread += next_nread - 2; if ((ssize_t) *line_size < nread + 1) { @@ -663,7 +666,8 @@ bool read_config(FILE *file, struct sway_config *config, ssize_t nread; list_t *stack = create_list(); size_t read = 0; - while ((nread = getline_with_cont(&line, &line_size, file)) != -1) { + int nlines = 0; + while ((nread = getline_with_cont(&line, &line_size, file, &nlines)) != -1) { if (reading_main_config) { if (read + nread > config_size) { wlr_log(WLR_ERROR, "Config file changed during reading"); @@ -679,7 +683,7 @@ bool read_config(FILE *file, struct sway_config *config, line[nread - 1] = '\0'; } - line_number++; + line_number += nlines; wlr_log(WLR_DEBUG, "Read line %d: %s", line_number, line); strip_whitespace(line); diff --git a/swayidle/main.c b/swayidle/main.c deleted file mode 100644 index 41eecc41..00000000 --- a/swayidle/main.c +++ /dev/null @@ -1,483 +0,0 @@ -#define _POSIX_C_SOURCE 200809L -#include <assert.h> -#include <errno.h> -#include <fcntl.h> -#include <getopt.h> -#include <pthread.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/wait.h> -#include <unistd.h> -#include <wayland-client-protocol.h> -#include <wayland-client.h> -#include <wayland-server.h> -#include <wayland-util.h> -#include <wlr/config.h> -#include <wlr/util/log.h> -#include "config.h" -#include "idle-client-protocol.h" -#include "list.h" -#if HAVE_SYSTEMD -#include <systemd/sd-bus.h> -#include <systemd/sd-login.h> -#elif HAVE_ELOGIND -#include <elogind/sd-bus.h> -#include <elogind/sd-login.h> -#endif - -static struct org_kde_kwin_idle *idle_manager = NULL; -static struct wl_seat *seat = NULL; - -struct swayidle_state { - struct wl_display *display; - struct wl_event_loop *event_loop; - list_t *timeout_cmds; // struct swayidle_timeout_cmd * - char *lock_cmd; -} state; - -struct swayidle_timeout_cmd { - int timeout, registered_timeout; - struct org_kde_kwin_idle_timeout *idle_timer; - char *idle_cmd; - char *resume_cmd; -}; - -void sway_terminate(int exit_code) { - wl_display_disconnect(state.display); - wl_event_loop_destroy(state.event_loop); - exit(exit_code); -} - -static void cmd_exec(char *param) { - wlr_log(WLR_DEBUG, "Cmd exec %s", param); - pid_t pid = fork(); - if (pid == 0) { - pid = fork(); - if (pid == 0) { - char *const cmd[] = { "sh", "-c", param, NULL, }; - execvp(cmd[0], cmd); - wlr_log_errno(WLR_ERROR, "execve failed!"); - exit(1); - } else if (pid < 0) { - wlr_log_errno(WLR_ERROR, "fork failed"); - exit(1); - } - exit(0); - } else if (pid < 0) { - wlr_log_errno(WLR_ERROR, "fork failed"); - } else { - wlr_log(WLR_DEBUG, "Spawned process %s", param); - waitpid(pid, NULL, 0); - } -} - -#if HAVE_SYSTEMD || HAVE_ELOGIND -static int lock_fd = -1; -static int ongoing_fd = -1; -static struct sd_bus *bus = NULL; - -static int release_lock(void *data) { - wlr_log(WLR_INFO, "Releasing sleep lock %d", ongoing_fd); - if (ongoing_fd >= 0) { - close(ongoing_fd); - } - ongoing_fd = -1; - return 0; -} - -static void acquire_sleep_lock(void) { - 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"); - if (ret < 0) { - wlr_log(WLR_ERROR, "Failed to send Inhibit signal: %s", error.message); - sd_bus_error_free(&error); - return; - } - - ret = sd_bus_message_read(msg, "h", &lock_fd); - if (ret < 0) { - wlr_log(WLR_ERROR, "Failed to parse D-Bus response for Inhibit: %s", - strerror(-ret)); - sd_bus_error_free(&error); - sd_bus_message_unref(msg); - return; - } else { - wlr_log(WLR_INFO, "Got sleep lock: %d", lock_fd); - } - - // 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) { - wlr_log(WLR_ERROR, "Failed to copy sleep lock fd: %s", - strerror(errno)); - } - - sd_bus_error_free(&error); - sd_bus_message_unref(msg); -} - -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 */ - int going_down = 1; - int ret = sd_bus_message_read(msg, "b", &going_down); - if (ret < 0) { - wlr_log(WLR_ERROR, "Failed to parse D-Bus response for Inhibit: %s", - strerror(-ret)); - } - wlr_log(WLR_DEBUG, "PrepareForSleep signal received %d", going_down); - if (!going_down) { - acquire_sleep_lock(); - return 0; - } - - ongoing_fd = lock_fd; - - if (state.lock_cmd) { - cmd_exec(state.lock_cmd); - } - - if (ongoing_fd >= 0) { - struct wl_event_source *source = - wl_event_loop_add_timer(state.event_loop, release_lock, NULL); - wl_event_source_timer_update(source, 1000); - } - - wlr_log(WLR_DEBUG, "Prepare for sleep done"); - return 0; -} - -static int dbus_event(int fd, uint32_t mask, void *data) { - sd_bus *bus = data; - - if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) { - sway_terminate(0); - } - - int count = 0; - if (mask & WL_EVENT_READABLE) { - count = sd_bus_process(bus, NULL); - } - if (mask & WL_EVENT_WRITABLE) { - sd_bus_flush(bus); - } - if (mask == 0) { - sd_bus_flush(bus); - } - - if (count < 0) { - wlr_log_errno(WLR_ERROR, "sd_bus_process failed, exiting"); - sway_terminate(0); - } - - return count; -} - -static void setup_sleep_listener(void) { - int ret = sd_bus_default_system(&bus); - if (ret < 0) { - wlr_log(WLR_ERROR, "Failed to open D-Bus connection: %s", - strerror(-ret)); - return; - } - - char str[256]; - const char *fmt = "type='signal'," - "sender='org.freedesktop.login1'," - "interface='org.freedesktop.login1.%s'," - "member='%s'," "path='%s'"; - - snprintf(str, sizeof(str), fmt, "Manager", "PrepareForSleep", - "/org/freedesktop/login1"); - ret = sd_bus_add_match(bus, NULL, str, prepare_for_sleep, NULL); - if (ret < 0) { - wlr_log(WLR_ERROR, "Failed to add D-Bus match: %s", strerror(-ret)); - return; - } - acquire_sleep_lock(); - - 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); -} -#endif - -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); - } -} - -static void handle_global_remove(void *data, struct wl_registry *registry, - uint32_t name) { - // Who cares -} - -static const struct wl_registry_listener registry_listener = { - .global = handle_global, - .global_remove = handle_global_remove, -}; - -static const struct org_kde_kwin_idle_timeout_listener idle_timer_listener; - -static void register_timeout(struct swayidle_timeout_cmd *cmd, - int timeout) { - if (cmd->idle_timer != NULL) { - org_kde_kwin_idle_timeout_destroy(cmd->idle_timer); - cmd->idle_timer = NULL; - } - if (timeout < 0) { - wlr_log(WLR_DEBUG, "Not registering idle timeout"); - return; - } - wlr_log(WLR_DEBUG, "Register with timeout: %d", timeout); - cmd->idle_timer = - org_kde_kwin_idle_get_idle_timeout(idle_manager, seat, timeout); - org_kde_kwin_idle_timeout_add_listener(cmd->idle_timer, - &idle_timer_listener, cmd); - cmd->registered_timeout = timeout; -} - -static void handle_idle(void *data, struct org_kde_kwin_idle_timeout *timer) { - struct swayidle_timeout_cmd *cmd = data; - wlr_log(WLR_DEBUG, "idle state"); - if (cmd->idle_cmd) { - cmd_exec(cmd->idle_cmd); - } -} - -static void handle_resume(void *data, struct org_kde_kwin_idle_timeout *timer) { - struct swayidle_timeout_cmd *cmd = data; - wlr_log(WLR_DEBUG, "active state"); - if (cmd->registered_timeout != cmd->timeout) { - register_timeout(cmd, cmd->timeout); - } - if (cmd->resume_cmd) { - cmd_exec(cmd->resume_cmd); - } -} - -static const struct org_kde_kwin_idle_timeout_listener idle_timer_listener = { - .idle = handle_idle, - .resumed = handle_resume, -}; - -static char *parse_command(int argc, char **argv) { - if (argc < 1) { - wlr_log(WLR_ERROR, "Missing command"); - return NULL; - } - - wlr_log(WLR_DEBUG, "Command: %s", argv[0]); - return strdup(argv[0]); -} - -static int parse_timeout(int argc, char **argv) { - if (argc < 3) { - wlr_log(WLR_ERROR, "Too few parameters to timeout command. " - "Usage: timeout <seconds> <command>"); - exit(-1); - } - errno = 0; - char *endptr; - int seconds = strtoul(argv[1], &endptr, 10); - if (errno != 0 || *endptr != '\0') { - wlr_log(WLR_ERROR, "Invalid timeout parameter '%s', it should be a " - "numeric value representing seconds", optarg); - exit(-1); - } - - struct swayidle_timeout_cmd *cmd = - calloc(1, sizeof(struct swayidle_timeout_cmd)); - - if (seconds > 0) { - cmd->timeout = seconds * 1000; - } else { - cmd->timeout = -1; - } - - wlr_log(WLR_DEBUG, "Register idle timeout at %d ms", cmd->timeout); - wlr_log(WLR_DEBUG, "Setup idle"); - cmd->idle_cmd = parse_command(argc - 2, &argv[2]); - - int result = 3; - if (argc >= 5 && !strcmp("resume", argv[3])) { - wlr_log(WLR_DEBUG, "Setup resume"); - cmd->resume_cmd = parse_command(argc - 4, &argv[4]); - result = 5; - } - list_add(state.timeout_cmds, cmd); - return result; -} - -static int parse_sleep(int argc, char **argv) { - if (argc < 2) { - wlr_log(WLR_ERROR, "Too few parameters to before-sleep command. " - "Usage: before-sleep <command>"); - exit(-1); - } - - state.lock_cmd = parse_command(argc - 1, &argv[1]); - if (state.lock_cmd) { - wlr_log(WLR_DEBUG, "Setup sleep lock: %s", state.lock_cmd); - } - - return 2; -} - -static int parse_args(int argc, char *argv[]) { - bool debug = false; - - int c; - while ((c = getopt(argc, argv, "hd")) != -1) { - switch (c) { - case 'd': - debug = true; - break; - case 'h': - case '?': - printf("Usage: %s [OPTIONS]\n", argv[0]); - printf(" -d\tdebug\n"); - printf(" -h\tthis help menu\n"); - return 1; - default: - return 1; - } - } - - wlr_log_init(debug ? WLR_DEBUG : WLR_INFO, NULL); - - state.timeout_cmds = create_list(); - - int i = optind; - while (i < argc) { - if (!strcmp("timeout", argv[i])) { - wlr_log(WLR_DEBUG, "Got timeout"); - i += parse_timeout(argc - i, &argv[i]); - } else if (!strcmp("before-sleep", argv[i])) { - wlr_log(WLR_DEBUG, "Got before-sleep"); - i += parse_sleep(argc - i, &argv[i]); - } else { - wlr_log(WLR_ERROR, "Unsupported command '%s'", argv[i]); - return 1; - } - } - - return 0; -} - -static int handle_signal(int sig, void *data) { - switch (sig) { - case SIGINT: - case SIGTERM: - sway_terminate(0); - return 0; - case SIGUSR1: - wlr_log(WLR_DEBUG, "Got SIGUSR1"); - for (int i = 0; i < state.timeout_cmds->length; ++i) { - register_timeout(state.timeout_cmds->items[i], 0); - } - return 1; - } - assert(false); // not reached -} - -static int display_event(int fd, uint32_t mask, void *data) { - if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) { - sway_terminate(0); - } - - int count = 0; - if (mask & WL_EVENT_READABLE) { - count = wl_display_dispatch(state.display); - } - if (mask & WL_EVENT_WRITABLE) { - wl_display_flush(state.display); - } - if (mask == 0) { - count = wl_display_dispatch_pending(state.display); - wl_display_flush(state.display); - } - - if (count < 0) { - wlr_log_errno(WLR_ERROR, "wl_display_dispatch failed, exiting"); - sway_terminate(0); - } - - return count; -} - -int main(int argc, char *argv[]) { - if (parse_args(argc, argv) != 0) { - return -1; - } - - state.event_loop = wl_event_loop_create(); - - wl_event_loop_add_signal(state.event_loop, SIGINT, handle_signal, NULL); - wl_event_loop_add_signal(state.event_loop, SIGTERM, handle_signal, NULL); - wl_event_loop_add_signal(state.event_loop, SIGUSR1, handle_signal, NULL); - - state.display = wl_display_connect(NULL); - if (state.display == NULL) { - wlr_log(WLR_ERROR, "Unable to connect to the compositor. " - "If your compositor is running, check or set the " - "WAYLAND_DISPLAY environment variable."); - 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); - - if (idle_manager == NULL) { - wlr_log(WLR_ERROR, "Display doesn't support idle protocol"); - return -4; - } - if (seat == NULL) { - wlr_log(WLR_ERROR, "Seat error"); - return -5; - } - - bool should_run = state.timeout_cmds->length > 0; -#if HAVE_SYSTEMD || HAVE_ELOGIND - if (state.lock_cmd) { - should_run = true; - setup_sleep_listener(); - } -#endif - if (!should_run) { - wlr_log(WLR_INFO, "No command specified! Nothing to do, will exit"); - sway_terminate(0); - } - - for (int i = 0; i < state.timeout_cmds->length; ++i) { - struct swayidle_timeout_cmd *cmd = state.timeout_cmds->items[i]; - register_timeout(cmd, cmd->timeout); - } - - wl_display_roundtrip(state.display); - - struct wl_event_source *source = wl_event_loop_add_fd(state.event_loop, - wl_display_get_fd(state.display), WL_EVENT_READABLE, - display_event, NULL); - wl_event_source_check(source); - - while (wl_event_loop_dispatch(state.event_loop, -1) != 1) { - // This space intentionally left blank - } - - sway_terminate(0); -} diff --git a/swayidle/meson.build b/swayidle/meson.build deleted file mode 100644 index 79d2c5c4..00000000 --- a/swayidle/meson.build +++ /dev/null @@ -1,27 +0,0 @@ -threads = dependency('threads') - -swayidle_deps = [ - client_protos, - pixman, - wayland_client, - wayland_server, - wlroots, -] - -if systemd.found() - swayidle_deps += systemd -endif -if elogind.found() - swayidle_deps += elogind -endif - -executable( - 'swayidle', [ - 'main.c', - ], - include_directories: [sway_inc], - dependencies: swayidle_deps, - link_with: [lib_sway_common, lib_sway_client], - install_rpath : rpathdir, - install: true -) diff --git a/swayidle/swayidle.1.scd b/swayidle/swayidle.1.scd deleted file mode 100644 index 0e3b5c3c..00000000 --- a/swayidle/swayidle.1.scd +++ /dev/null @@ -1,63 +0,0 @@ -swayidle (1) - -# NAME - -swayidle - Idle manager for Wayland - -# SYNOPSIS - -*swayidle* [options] [events...] - -# OPTIONS - -*-h* - Show help message and quit. - -*-d* - Enable debug output. - -# 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. - -# EVENTS - -*timeout* <timeout> <timeout command> [resume <resume command>] - Execute _timeout command_ if there is no activity for <timeout> seconds. - - If you specify "resume <resume command>", _resume command_ will be run when - there is activity again. - -*before-sleep* <command> - If built with systemd support, executes _command_ before systemd puts the - computer to sleep. - -All commands are executed in a shell. - -# EXAMPLE - -``` -swayidle \ - timeout 300 'swaylock -c 000000' \ - timeout 600 'swaymsg "output * dpms off"' \ - resume 'swaymsg "output * dpms on"' \ - before-sleep 'swaylock -c 000000' -``` - -This will lock your screen after 300 seconds of inactivity, then turn off your -displays after another 300 seconds, and turn your screens back on when resumed. -It will also lock your screen before your computer goes to sleep. - -# AUTHORS - -Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open -source contributors. For more information about sway development, see -https://github.com/swaywm/sway. - -# SEE ALSO - -*sway*(5) *swaymsg*(1) *sway-input*(5) *sway-output*(5) *sway-bar*(5) |