pax_global_header00006660000000000000000000000064136120731060014511gustar00rootroot0000000000000052 comment=826a3fc4bcae73ea249ae33e03c256b4f6bfd5c0 swayidle-1.6/000077500000000000000000000000001361207310600132005ustar00rootroot00000000000000swayidle-1.6/.build.yml000066400000000000000000000003641361207310600151030ustar00rootroot00000000000000image: alpine/edge packages: - meson - wayland-dev - wayland-protocols - scdoc sources: - https://github.com/swaywm/swayidle tasks: - setup: | cd swayidle meson build - build: | cd swayidle ninja -C build swayidle-1.6/.gitignore000066400000000000000000000000061361207310600151640ustar00rootroot00000000000000build swayidle-1.6/LICENSE000066400000000000000000000020451361207310600142060ustar00rootroot00000000000000Copyright (c) 2016-2018 Drew DeVault Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. swayidle-1.6/README.md000066400000000000000000000021151361207310600144560ustar00rootroot00000000000000# swayidle This is sway's idle management daemon, swayidle. It is compatible with any Wayland compositor which implements the KDE [idle](https://github.com/swaywm/sway/blob/master/protocols/idle.xml) protocol. See the man page, `swayidle(1)`, for instructions on configuring swayidle. ## Release Signatures Releases are signed with [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) and published [on GitHub](https://github.com/swaywm/swayidle/releases). swayidle releases are managed independently of sway releases. ## Installation ### From Packages Swayidle is available in many distributions. Try installing the "swayidle" package for yours. If you're interested in packaging swayidle for your distribution, stop by the IRC channel or shoot an email to sir@cmpwn.com for advice. ### Compiling from Source Install dependencies: * meson \* * wayland * wayland-protocols \* * [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (optional: man pages) \* * git \* _\*Compile-time dep_ Run these commands: meson build ninja -C build sudo ninja -C build install swayidle-1.6/completions/000077500000000000000000000000001361207310600155345ustar00rootroot00000000000000swayidle-1.6/completions/bash/000077500000000000000000000000001361207310600164515ustar00rootroot00000000000000swayidle-1.6/completions/bash/swayidle000066400000000000000000000017351361207310600202230ustar00rootroot00000000000000# 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 -w ) if [ "$prev" = timeout ]; then # timeout return elif [ "$prev2" = timeout ]; then # timeout COMPREPLY=($(compgen -c -- "$cur")) return elif [ "$prev3" = timeout ]; then # timeout [resume ] 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 swayidle-1.6/completions/fish/000077500000000000000000000000001361207310600164655ustar00rootroot00000000000000swayidle-1.6/completions/fish/swayidle.fish000066400000000000000000000002641361207310600211630ustar00rootroot00000000000000# swayidle 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' swayidle-1.6/completions/zsh/000077500000000000000000000000001361207310600163405ustar00rootroot00000000000000swayidle-1.6/completions/zsh/_swayidle000066400000000000000000000014211361207310600202410ustar00rootroot00000000000000#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 _describe -t "events" 'swayidle' events _arguments -C \ '(-h --help)'{-h,--help}'[Show help message and quit]' \ '(-d)'-d'[Enable debug output]' \ '(-w)'-w'[Wait for command to finish executing before continuing]' 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 swayidle-1.6/idle.xml000066400000000000000000000045621361207310600146460ustar00rootroot00000000000000 . ]]> This interface allows to monitor user idle time on a given seat. The interface allows to register timers which trigger after no user activity was registered on the seat for a given interval. It notifies when user activity resumes. This is useful for applications wanting to perform actions when the user is not interacting with the system, e.g. chat applications setting the user as away, power management features to dim screen, etc.. swayidle-1.6/main.c000066400000000000000000000452271361207310600143020ustar00rootroot00000000000000#define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "idle-client-protocol.h" #if HAVE_SYSTEMD #include #include #elif HAVE_ELOGIND #include #include #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; struct wl_list timeout_cmds; // struct swayidle_timeout_cmd * char *before_sleep_cmd; char *after_resume_cmd; char *logind_lock_cmd; char *logind_unlock_cmd; bool logind_idlehint; bool wait; } state; struct swayidle_timeout_cmd { struct wl_list link; int timeout, registered_timeout; struct org_kde_kwin_idle_timeout *idle_timer; char *idle_cmd; char *resume_cmd; bool idlehint; }; enum log_importance { LOG_DEBUG = 1, LOG_INFO = 2, LOG_ERROR = 3, }; static enum log_importance verbosity = LOG_INFO; static void swayidle_log(enum log_importance importance, const char *fmt, ...) { if (importance < verbosity) { return; } va_list args; va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); fprintf(stderr, "\n"); } static void swayidle_log_errno( enum log_importance importance, const char *fmt, ...) { if (importance < verbosity) { return; } va_list args; va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); fprintf(stderr, ": %s\n", strerror(errno)); } 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) { swayidle_log(LOG_DEBUG, "Cmd exec %s", param); pid_t pid = fork(); if (pid == 0) { if (!state.wait) { pid = fork(); } if (pid == 0) { char *const cmd[] = { "sh", "-c", param, NULL, }; execvp(cmd[0], cmd); swayidle_log_errno(LOG_ERROR, "execve failed!"); exit(1); } else if (pid < 0) { swayidle_log_errno(LOG_ERROR, "fork failed"); exit(1); } exit(0); } else if (pid < 0) { swayidle_log_errno(LOG_ERROR, "fork failed"); } else { swayidle_log(LOG_DEBUG, "Spawned process %s", param); waitpid(pid, NULL, 0); } } #if HAVE_SYSTEMD || HAVE_ELOGIND static int lock_fd = -1; static struct sd_bus *bus = NULL; static char *session_name = NULL; 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) { swayidle_log(LOG_ERROR, "Failed to send Inhibit signal: %s", error.message); goto cleanup; } ret = sd_bus_message_read(msg, "h", &lock_fd); if (ret < 0) { errno = -ret; swayidle_log_errno(LOG_ERROR, "Failed to parse D-Bus response for Inhibit"); 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); } else { swayidle_log_errno(LOG_ERROR, "Failed to copy sleep lock fd"); } cleanup: sd_bus_error_free(&error); sd_bus_message_unref(msg); } 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", &error, &msg, "b", hint); if (ret < 0) { swayidle_log(LOG_ERROR, "Failed to send SetIdleHint signal: %s", error.message); } 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) { errno = -ret; swayidle_log_errno(LOG_ERROR, "Failed to parse D-Bus response for Inhibit: %s"); } swayidle_log(LOG_DEBUG, "PrepareForSleep signal received %d", going_down); if (!going_down) { acquire_sleep_lock(); if (state.after_resume_cmd) { cmd_exec(state.after_resume_cmd); } if (state.logind_idlehint) { set_idle_hint(false); } return 0; } if (state.before_sleep_cmd) { cmd_exec(state.before_sleep_cmd); } 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; return 0; } static int handle_lock(sd_bus_message *msg, void *userdata, sd_bus_error *ret_error) { swayidle_log(LOG_DEBUG, "Lock signal received"); if (state.logind_lock_cmd) { cmd_exec(state.logind_lock_cmd); } swayidle_log(LOG_DEBUG, "Lock command done"); return 0; } static int handle_unlock(sd_bus_message *msg, void *userdata, sd_bus_error *ret_error) { swayidle_log(LOG_DEBUG, "Unlock signal received"); if (state.logind_idlehint) { set_idle_hint(false); } if (state.logind_unlock_cmd) { cmd_exec(state.logind_unlock_cmd); } swayidle_log(LOG_DEBUG, "Unlock command 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) { swayidle_log_errno(LOG_ERROR, "sd_bus_process failed, exiting"); sway_terminate(0); } return count; } static void connect_to_bus(void) { int ret = sd_bus_default_system(&bus); sd_bus_message *msg = NULL; sd_bus_error error = SD_BUS_ERROR_NULL; pid_t my_pid = getpid(); const char *session_name_tmp; 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; } ret = sd_bus_message_read(msg, "o", &session_name_tmp); if (ret < 0) { swayidle_log(LOG_ERROR, "Failed to read session name\n"); goto cleanup; } session_name = strdup(session_name_tmp); cleanup: sd_bus_error_free(&error); sd_bus_message_unref(msg); } static void setup_sleep_listener(void) { int ret = sd_bus_match_signal(bus, NULL, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "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(); } static void setup_lock_listener(void) { int ret = sd_bus_match_signal(bus, NULL, "org.freedesktop.login1", session_name, "org.freedesktop.login1.Session", "Lock", handle_lock, NULL); if (ret < 0) { errno = -ret; swayidle_log_errno(LOG_ERROR, "Failed to add D-Bus signal match : lock"); return; } } static void setup_unlock_listener(void) { int ret = sd_bus_match_signal(bus, NULL, "org.freedesktop.login1", session_name, "org.freedesktop.login1.Session", "Unlock", handle_unlock, NULL); if (ret < 0) { errno = -ret; swayidle_log_errno(LOG_ERROR, "Failed to add D-Bus signal match : unlock"); return; } } #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) { swayidle_log(LOG_DEBUG, "Not registering idle timeout"); return; } swayidle_log(LOG_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; swayidle_log(LOG_DEBUG, "idle state"); #if HAVE_SYSTEMD || HAVE_ELOGIND if (cmd->idlehint) { set_idle_hint(true); } else #endif 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; swayidle_log(LOG_DEBUG, "active state"); if (cmd->registered_timeout != cmd->timeout) { register_timeout(cmd, cmd->timeout); } #if HAVE_SYSTEMD || HAVE_ELOGIND if (cmd->idlehint) { set_idle_hint(false); } else #endif 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) { swayidle_log(LOG_ERROR, "Missing command"); return NULL; } swayidle_log(LOG_DEBUG, "Command: %s", argv[0]); return strdup(argv[0]); } static struct swayidle_timeout_cmd *build_timeout_cmd(int argc, char **argv) { errno = 0; char *endptr; int seconds = strtoul(argv[1], &endptr, 10); if (errno != 0 || *endptr != '\0') { swayidle_log(LOG_ERROR, "Invalid %s parameter '%s', it should be a " "numeric value representing seconds", argv[0], argv[1]); exit(-1); } struct swayidle_timeout_cmd *cmd = calloc(1, sizeof(struct swayidle_timeout_cmd)); cmd->idlehint = false; if (seconds > 0) { cmd->timeout = seconds * 1000; } else { cmd->timeout = -1; } return cmd; } static int parse_timeout(int argc, char **argv) { if (argc < 3) { swayidle_log(LOG_ERROR, "Too few parameters to timeout command. " "Usage: timeout "); exit(-1); } struct swayidle_timeout_cmd *cmd = build_timeout_cmd(argc, argv); swayidle_log(LOG_DEBUG, "Register idle timeout at %d ms", cmd->timeout); swayidle_log(LOG_DEBUG, "Setup idle"); cmd->idle_cmd = parse_command(argc - 2, &argv[2]); int result = 3; if (argc >= 5 && !strcmp("resume", argv[3])) { swayidle_log(LOG_DEBUG, "Setup resume"); cmd->resume_cmd = parse_command(argc - 4, &argv[4]); result = 5; } wl_list_insert(&state.timeout_cmds, &cmd->link); return result; } static int parse_sleep(int argc, char **argv) { #if !HAVE_SYSTEMD && !HAVE_ELOGIND swayidle_log(LOG_ERROR, "%s not supported: swayidle was compiled " "with neither systemd nor elogind support.", "before-sleep"); exit(-1); #endif if (argc < 2) { swayidle_log(LOG_ERROR, "Too few parameters to before-sleep command. " "Usage: before-sleep "); exit(-1); } state.before_sleep_cmd = parse_command(argc - 1, &argv[1]); if (state.before_sleep_cmd) { swayidle_log(LOG_DEBUG, "Setup sleep lock: %s", state.before_sleep_cmd); } return 2; } static int parse_resume(int argc, char **argv) { #if !HAVE_SYSTEMD && !HAVE_ELOGIND swayidle_log(LOG_ERROR, "%s not supported: swayidle was compiled " "with neither systemd nor elogind support.", "after-resume"); exit(-1); #endif if (argc < 2) { swayidle_log(LOG_ERROR, "Too few parameters to after-resume command. " "Usage: after-resume "); exit(-1); } state.after_resume_cmd = parse_command(argc - 1, &argv[1]); if (state.after_resume_cmd) { swayidle_log(LOG_DEBUG, "Setup resume hook: %s", state.after_resume_cmd); } return 2; } static int parse_lock(int argc, char **argv) { #if !HAVE_SYSTEMD && !HAVE_ELOGIND swayidle_log(LOG_ERROR, "%s not supported: swayidle was compiled" " with neither systemd nor elogind support.", "lock"); exit(-1); #endif if (argc < 2) { swayidle_log(LOG_ERROR, "Too few parameters to lock command. " "Usage: lock "); exit(-1); } state.logind_lock_cmd = parse_command(argc - 1, &argv[1]); if (state.logind_lock_cmd) { swayidle_log(LOG_DEBUG, "Setup lock hook: %s", state.logind_lock_cmd); } return 2; } static int parse_unlock(int argc, char **argv) { #if !HAVE_SYSTEMD && !HAVE_ELOGIND swayidle_log(LOG_ERROR, "%s not supported: swayidle was compiled" " with neither systemd nor elogind support.", "unlock"); exit(-1); #endif if (argc < 2) { swayidle_log(LOG_ERROR, "Too few parameters to unlock command. " "Usage: unlock "); exit(-1); } state.logind_unlock_cmd = parse_command(argc - 1, &argv[1]); if (state.logind_unlock_cmd) { swayidle_log(LOG_DEBUG, "Setup unlock hook: %s", state.logind_unlock_cmd); } return 2; } static int parse_idlehint(int argc, char **argv) { #if !HAVE_SYSTEMD && !HAVE_ELOGIND swayidle_log(LOG_ERROR, "%s not supported: swayidle was compiled" " with neither systemd nor elogind support.", "idlehint"); exit(-1); #endif if (state.logind_idlehint) { swayidle_log(LOG_ERROR, "Cannot add multiple idlehint events"); exit(-1); } if (argc < 2) { swayidle_log(LOG_ERROR, "Too few parameters to idlehint command. " "Usage: idlehint "); exit(-1); } struct swayidle_timeout_cmd *cmd = build_timeout_cmd(argc, argv); cmd->idlehint = true; swayidle_log(LOG_DEBUG, "Register idlehint timeout at %d ms", cmd->timeout); wl_list_insert(&state.timeout_cmds, &cmd->link); state.logind_idlehint = true; return 2; } static int parse_args(int argc, char *argv[]) { int c; while ((c = getopt(argc, argv, "hdw")) != -1) { switch (c) { case 'd': verbosity = LOG_DEBUG; break; case 'w': state.wait = true; break; case 'h': case '?': printf("Usage: %s [OPTIONS]\n", argv[0]); printf(" -h\tthis help menu\n"); printf(" -d\tdebug\n"); printf(" -w\twait for command to finish\n"); return 1; default: return 1; } } wl_list_init(&state.timeout_cmds); int i = optind; while (i < argc) { if (!strcmp("timeout", argv[i])) { swayidle_log(LOG_DEBUG, "Got timeout"); i += parse_timeout(argc - i, &argv[i]); } else if (!strcmp("before-sleep", argv[i])) { swayidle_log(LOG_DEBUG, "Got before-sleep"); i += parse_sleep(argc - i, &argv[i]); } else if (!strcmp("after-resume", argv[i])) { swayidle_log(LOG_DEBUG, "Got after-resume"); i += parse_resume(argc - i, &argv[i]); } else if (!strcmp("lock", argv[i])) { swayidle_log(LOG_DEBUG, "Got lock"); i += parse_lock(argc - i, &argv[i]); } else if (!strcmp("unlock", argv[i])) { swayidle_log(LOG_DEBUG, "Got unlock"); i += parse_unlock(argc - i, &argv[i]); } else if (!strcmp("idlehint", argv[i])) { swayidle_log(LOG_DEBUG, "Got idlehint"); i += parse_idlehint(argc - i, &argv[i]); } else { swayidle_log(LOG_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: 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 } 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) { swayidle_log_errno(LOG_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) { swayidle_log(LOG_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) { swayidle_log(LOG_ERROR, "Display doesn't support idle protocol"); return -4; } if (seat == NULL) { swayidle_log(LOG_ERROR, "Seat error"); return -5; } bool should_run = !wl_list_empty(&state.timeout_cmds); #if HAVE_SYSTEMD || HAVE_ELOGIND connect_to_bus(); if (state.before_sleep_cmd || state.after_resume_cmd) { should_run = true; setup_sleep_listener(); } if (state.logind_lock_cmd) { should_run = true; setup_lock_listener(); } if (state.logind_unlock_cmd) { should_run = true; setup_unlock_listener(); } if (state.logind_idlehint) { set_idle_hint(false); } #endif if (!should_run) { swayidle_log(LOG_INFO, "No command specified! Nothing to do, will exit"); sway_terminate(0); } struct swayidle_timeout_cmd *cmd; wl_list_for_each(cmd, &state.timeout_cmds, link) { 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); } swayidle-1.6/meson.build000066400000000000000000000066671361207310600153610ustar00rootroot00000000000000project( 'swayidle', 'c', version: '1.5', license: 'MIT', meson_version: '>=0.48.0', default_options: [ 'c_std=c11', 'warning_level=2', 'werror=true', ], ) add_project_arguments( [ '-Wno-unused-parameter', '-Wno-unused-result', '-Wundef', '-Wvla', ], language: 'c', ) wayland_client = dependency('wayland-client') wayland_protos = dependency('wayland-protocols', version: '>=1.14') wayland_server = dependency('wayland-server') bash_comp = dependency('bash-completion', required: false) fish_comp = dependency('fish', required: false) logind = dependency('lib' + get_option('logind-provider'), required: get_option('logind')) scdoc = find_program('scdoc', required: get_option('man-pages')) wayland_scanner = find_program('wayland-scanner') wl_protocol_dir = wayland_protos.get_pkgconfig_variable('pkgdatadir') if wayland_server.version().version_compare('>=1.14.91') code_type = 'private-code' else code_type = 'code' endif wayland_scanner_code = generator( wayland_scanner, output: '@BASENAME@-protocol.c', arguments: [code_type, '@INPUT@', '@OUTPUT@'], ) wayland_scanner_client = generator( wayland_scanner, output: '@BASENAME@-client-protocol.h', arguments: ['client-header', '@INPUT@', '@OUTPUT@'], ) client_protos_src = wayland_scanner_code.process('idle.xml') client_protos_headers = wayland_scanner_client.process('idle.xml') lib_client_protos = static_library( 'client_protos', [client_protos_src, client_protos_headers], dependencies: [wayland_client] ) # for the include directory client_protos = declare_dependency( link_with: lib_client_protos, sources: client_protos_headers, ) swayidle_deps = [ client_protos, wayland_client, wayland_server, ] conf_data = configuration_data() conf_data.set10('HAVE_SYSTEMD', false) conf_data.set10('HAVE_ELOGIND', false) if logind.found() swayidle_deps += logind conf_data.set10('HAVE_' + get_option('logind-provider').to_upper(), true) endif configure_file(output: 'config.h', configuration: conf_data) executable( 'swayidle', [ 'main.c', ], dependencies: swayidle_deps, install: true, ) if scdoc.found() sh = find_program('sh') mandir = get_option('mandir') man_files = [ 'swayidle.1.scd', ] foreach filename : man_files topic = filename.split('.')[-3].split('/')[-1] section = filename.split('.')[-2] output = '@0@.@1@'.format(topic, section) custom_target( output, input: filename, output: output, command: [ sh, '-c', '@0@ < @INPUT@ > @1@'.format(scdoc.path(), output) ], install: true, install_dir: '@0@/man@1@'.format(mandir, section) ) endforeach endif datadir = get_option('datadir') if get_option('zsh-completions') zsh_files = files( 'completions/zsh/_swayidle', ) zsh_install_dir = datadir + '/zsh/site-functions' install_data(zsh_files, install_dir: zsh_install_dir) endif if get_option('bash-completions') bash_files = files( 'completions/bash/swayidle', ) if bash_comp.found() bash_install_dir = bash_comp.get_pkgconfig_variable('completionsdir') else bash_install_dir = datadir + '/bash-completion/completions' endif install_data(bash_files, install_dir: bash_install_dir) endif if get_option('fish-completions') fish_files = files( 'completions/fish/swayidle.fish', ) if fish_comp.found() fish_install_dir = fish_comp.get_pkgconfig_variable('completionsdir') else fish_install_dir = datadir + '/fish/vendor_completions.d' endif install_data(fish_files, install_dir: fish_install_dir) endif swayidle-1.6/meson_options.txt000066400000000000000000000012061361207310600166340ustar00rootroot00000000000000option('man-pages', type: 'feature', value: 'auto', description: 'Generate and install man pages') option('logind', type: 'feature', value: 'auto', description: 'Enable support for logind') option('logind-provider', type: 'combo', choices: ['systemd', 'elogind'], value: 'systemd', description: 'Provider of logind support library') option('zsh-completions', type: 'boolean', value: true, description: 'Install zsh shell completions.') option('bash-completions', type: 'boolean', value: true, description: 'Install bash shell completions.') option('fish-completions', type: 'boolean', value: true, description: 'Install fish shell completions.') swayidle-1.6/swayidle.1.scd000066400000000000000000000053501361207310600156560ustar00rootroot00000000000000swayidle(1) # NAME swayidle - Idle manager for Wayland # SYNOPSIS *swayidle* [options] [events...] # OPTIONS *-h* Show help message and quit. *-d* Enable debug output. *-w* Wait for command to finish executing before continuing, helpful for ensuring that a *before-sleep* command has finished before the system goes to sleep. Note: using this option causes swayidle to block until the command finishes. # 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* [resume ] Execute _timeout command_ if there is no activity for seconds. If you specify "resume ", _resume command_ will be run when there is activity again. *before-sleep* If built with systemd support, executes _command_ before systemd puts the computer to sleep. Note: this only delays sleeping up to the limit set in *logind.conf(5)* by the option InhibitDelayMaxSec. A command that has not finished by then will continue running after resuming from sleep. *after-resume* If built with systemd support, executes _command_ after logind signals that the computer resumed from sleep. *lock* If built with systemd support, executes _command_ when logind signals that the session should be locked *unlock* If built with systemd support, executes _command_ when logind signals that the session should be unlocked *idlehint* If built with systemd support, set IdleHint to indcate an idle logind/elogind session after 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. # EXAMPLE ``` 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' ``` 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. To make sure swayidle waits for swaylock to lock the screen before it releases the inhibition lock, the *-w* options is used in swayidle, and *-f* in swaylock. # AUTHORS Maintained by Drew DeVault , who is assisted by other open source contributors. For more information about swayidle development, see https://github.com/swaywm/swayidle. # SEE ALSO *sway*(5) *swaymsg*(1) *sway-input*(5) *sway-output*(5) *sway-bar*(5) *loginctl*(1)