diff options
34 files changed, 512 insertions, 808 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/include/sway/commands.h b/include/sway/commands.h index 7d0ff838..04f93ba9 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -198,6 +198,8 @@ sway_cmd bar_cmd_id; sway_cmd bar_cmd_position; sway_cmd bar_cmd_separator_symbol; sway_cmd bar_cmd_status_command; +sway_cmd bar_cmd_status_edge_padding; +sway_cmd bar_cmd_status_padding; sway_cmd bar_cmd_pango_markup; sway_cmd bar_cmd_strip_workspace_numbers; sway_cmd bar_cmd_strip_workspace_name; diff --git a/include/sway/config.h b/include/sway/config.h index ebf16e6a..a667984d 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -27,7 +27,8 @@ struct sway_variable { enum binding_input_type { BINDING_KEYCODE, BINDING_KEYSYM, - BINDING_MOUSE, + BINDING_MOUSECODE, + BINDING_MOUSESYM, }; enum binding_flags { @@ -231,6 +232,8 @@ struct bar_config { bool verbose; struct side_gaps gaps; pid_t pid; + int status_padding; + int status_edge_padding; struct { char *background; char *statusline; diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 22e278b0..4636bf6b 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -86,4 +86,12 @@ void cursor_warp_to_container(struct sway_cursor *cursor, void cursor_warp_to_workspace(struct sway_cursor *cursor, struct sway_workspace *workspace); + +uint32_t get_mouse_bindsym(const char *name, char **error); + +uint32_t get_mouse_bindcode(const char *name, char **error); + +// Considers both bindsym and bindcode +uint32_t get_mouse_button(const char *name, char **error); + #endif diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index e377b8de..2d9ba0d9 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -61,6 +61,7 @@ struct swaybar_output { struct wl_list hotspots; // swaybar_hotspot::link char *name; + char *identifier; bool focused; uint32_t width, height; diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 1f6577bd..add0a1cf 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -43,6 +43,8 @@ struct swaybar_config { struct wl_list outputs; // config_output::link bool all_outputs; int height; + int status_padding; + int status_edge_padding; struct { int top; int right; diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h index 18af7ab4..516a56f4 100644 --- a/include/swaylock/swaylock.h +++ b/include/swaylock/swaylock.h @@ -22,6 +22,7 @@ enum auth_state { struct swaylock_colorset { uint32_t input; uint32_t cleared; + uint32_t caps_lock; uint32_t verifying; uint32_t wrong; }; @@ -30,6 +31,8 @@ struct swaylock_colors { uint32_t background; uint32_t bs_highlight; uint32_t key_highlight; + uint32_t caps_lock_bs_highlight; + uint32_t caps_lock_key_highlight; uint32_t separator; struct swaylock_colorset inside; struct swaylock_colorset line; @@ -45,6 +48,8 @@ struct swaylock_args { uint32_t thickness; bool ignore_empty; bool show_indicator; + bool show_caps_lock_text; + bool show_caps_lock_indicator; bool daemonize; }; 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/commands/bar.c b/sway/commands/bar.c index 507ee10a..3e7c1b0f 100644 --- a/sway/commands/bar.c +++ b/sway/commands/bar.c @@ -23,6 +23,8 @@ static struct cmd_handler bar_handlers[] = { { "position", bar_cmd_position }, { "separator_symbol", bar_cmd_separator_symbol }, { "status_command", bar_cmd_status_command }, + { "status_edge_padding", bar_cmd_status_edge_padding }, + { "status_padding", bar_cmd_status_padding }, { "strip_workspace_name", bar_cmd_strip_workspace_name }, { "strip_workspace_numbers", bar_cmd_strip_workspace_numbers }, { "tray_bindsym", bar_cmd_tray_bindsym }, diff --git a/sway/commands/bar/status_edge_padding.c b/sway/commands/bar/status_edge_padding.c new file mode 100644 index 00000000..f3b10631 --- /dev/null +++ b/sway/commands/bar/status_edge_padding.c @@ -0,0 +1,21 @@ +#include <stdlib.h> +#include <string.h> +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_status_edge_padding(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "status_edge_padding", EXPECTED_EQUAL_TO, 1))) { + return error; + } + char *end; + int padding = strtol(argv[0], &end, 10); + if (strlen(end) || padding < 0) { + return cmd_results_new(CMD_INVALID, "status_edge_padding", + "Padding must be a positive integer"); + } + config->current_bar->status_edge_padding = padding; + wlr_log(WLR_DEBUG, "Status edge padding on bar %s: %d", + config->current_bar->id, config->current_bar->status_edge_padding); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/status_padding.c b/sway/commands/bar/status_padding.c new file mode 100644 index 00000000..13b8eb6b --- /dev/null +++ b/sway/commands/bar/status_padding.c @@ -0,0 +1,21 @@ +#include <stdlib.h> +#include <string.h> +#include "sway/commands.h" +#include "log.h" + +struct cmd_results *bar_cmd_status_padding(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "status_padding", EXPECTED_EQUAL_TO, 1))) { + return error; + } + char *end; + int padding = strtol(argv[0], &end, 10); + if (strlen(end) || padding < 0) { + return cmd_results_new(CMD_INVALID, "status_padding", + "Padding must be a positive integer"); + } + config->current_bar->status_padding = padding; + wlr_log(WLR_DEBUG, "Status padding on bar %s: %d", + config->current_bar->id, config->current_bar->status_padding); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bind.c b/sway/commands/bind.c index 4fceaf8c..be47d412 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -85,69 +85,91 @@ static int key_qsort_cmp(const void *keyp_a, const void *keyp_b) { */ static struct cmd_results *identify_key(const char* name, bool first_key, uint32_t* key_val, enum binding_input_type* type) { - if (*type == BINDING_KEYCODE) { - // check for keycode - xkb_keycode_t keycode = strtol(name, NULL, 10); - if (!xkb_keycode_is_legal_ext(keycode)) { - return cmd_results_new(CMD_INVALID, "bindcode", - "Invalid keycode '%s'", name); + if (*type == BINDING_MOUSECODE) { + // check for mouse bindcodes + char *message = NULL; + uint32_t button = get_mouse_bindcode(name, &message); + if (!button) { + if (message) { + struct cmd_results *error = + cmd_results_new(CMD_INVALID, "bindcode", message); + free(message); + return error; + } else { + return cmd_results_new(CMD_INVALID, "bindcode", + "Unknown button code %s", name); + } } - *key_val = keycode; - } else { - // check for keysym - xkb_keysym_t keysym = xkb_keysym_from_name(name, - XKB_KEYSYM_CASE_INSENSITIVE); - - // Check for mouse binding - uint32_t button = 0; - if (strncasecmp(name, "button", strlen("button")) == 0) { - // Map to x11 mouse buttons - button = name[strlen("button")] - '0'; - if (button < 1 || button > 9 || strlen(name) > strlen("button0")) { + *key_val = button; + } else if (*type == BINDING_MOUSESYM) { + // check for mouse bindsyms (x11 buttons or event names) + char *message = NULL; + uint32_t button = get_mouse_bindsym(name, &message); + if (!button) { + if (message) { + struct cmd_results *error = + cmd_results_new(CMD_INVALID, "bindsym", message); + free(message); + return error; + } else if (!button) { return cmd_results_new(CMD_INVALID, "bindsym", - "Only buttons 1-9 are supported. For other mouse " - "buttons, use the name of the event code."); + "Unknown button %s", name); } - uint32_t buttons[] = {BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, - SWAY_SCROLL_UP, SWAY_SCROLL_DOWN, SWAY_SCROLL_LEFT, - SWAY_SCROLL_RIGHT, BTN_SIDE, BTN_EXTRA}; - button = buttons[button - 1]; - } else if (strncmp(name, "BTN_", strlen("BTN_")) == 0) { - // Get event code - int code = libevdev_event_code_from_name(EV_KEY, name); - if (code == -1) { - return cmd_results_new(CMD_INVALID, "bindsym", - "Invalid event code name %s", name); + } + *key_val = button; + } else if (*type == BINDING_KEYCODE) { + // check for keycode. If it is the first key, allow mouse bindcodes + if (first_key) { + char *message = NULL; + uint32_t button = get_mouse_bindcode(name, &message); + free(message); + if (button) { + *type = BINDING_MOUSECODE; + *key_val = button; + return NULL; } - button = code; } - if (*type == BINDING_KEYSYM) { - if (button) { - if (first_key) { - *type = BINDING_MOUSE; - *key_val = button; - } else { - return cmd_results_new(CMD_INVALID, "bindsym", - "Mixed button '%s' into key sequence", name); - } - } else if (keysym) { - *key_val = keysym; + xkb_keycode_t keycode = strtol(name, NULL, 10); + if (!xkb_keycode_is_legal_ext(keycode)) { + if (first_key) { + return cmd_results_new(CMD_INVALID, "bindcode", + "Invalid keycode or button code '%s'", name); } else { - return cmd_results_new(CMD_INVALID, "bindsym", - "Unknown key '%s'", name); + return cmd_results_new(CMD_INVALID, "bindcode", + "Invalid keycode '%s'", name); } - } else { - if (button) { + } + *key_val = keycode; + } else { + // check for keysym. If it is the first key, allow mouse bindsyms + if (first_key) { + char *message = NULL; + uint32_t button = get_mouse_bindsym(name, &message); + if (message) { + struct cmd_results *error = + cmd_results_new(CMD_INVALID, "bindsym", message); + free(message); + return error; + } else if (button) { + *type = BINDING_MOUSESYM; *key_val = button; - } else if (keysym) { + return NULL; + } + } + + xkb_keysym_t keysym = xkb_keysym_from_name(name, + XKB_KEYSYM_CASE_INSENSITIVE); + if (!keysym) { + if (first_key) { return cmd_results_new(CMD_INVALID, "bindsym", - "Mixed keysym '%s' into button sequence", name); + "Unknown key or button '%s'", name); } else { return cmd_results_new(CMD_INVALID, "bindsym", - "Unknown button '%s'", name); + "Unknown key '%s'", name); } } + *key_val = keysym; } return NULL; } @@ -201,7 +223,8 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv, } if (binding->flags & (BINDING_BORDER | BINDING_CONTENTS | BINDING_TITLEBAR) || exclude_titlebar) { - binding->type = BINDING_MOUSE; + binding->type = binding->type == BINDING_KEYCODE ? + BINDING_MOUSECODE : BINDING_MOUSESYM; } if (argc < 2) { @@ -249,7 +272,8 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv, // that this is one if (exclude_titlebar) { binding->flags &= ~BINDING_TITLEBAR; - } else if (binding->type == BINDING_MOUSE) { + } else if (binding->type == BINDING_MOUSECODE + || binding->type == BINDING_MOUSESYM) { binding->flags |= BINDING_TITLEBAR; } diff --git a/sway/config.c b/sway/config.c index f99f043c..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) { @@ -597,6 +600,7 @@ static ssize_t getline_with_cont(char **lineptr, size_t *line_size, FILE *file) } static int detect_brace(FILE *file) { + int ret = 0; int lines = 0; long pos = ftell(file); char *line = NULL; @@ -605,15 +609,17 @@ static int detect_brace(FILE *file) { lines++; strip_whitespace(line); if (*line) { - if (strcmp(line, "{") != 0) { - fseek(file, pos, SEEK_SET); - lines = 0; + if (strcmp(line, "{") == 0) { + ret = lines; } break; } } free(line); - return lines; + if (ret == 0) { + fseek(file, pos, SEEK_SET); + } + return ret; } static char *expand_line(const char *block, const char *line, bool add_brace) { @@ -660,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"); @@ -676,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/sway/config/bar.c b/sway/config/bar.c index 670219f1..101562d1 100644 --- a/sway/config/bar.c +++ b/sway/config/bar.c @@ -106,6 +106,8 @@ struct bar_config *default_bar_config(void) { bar->verbose = false; bar->pid = 0; bar->modifier = get_modifier_mask_by_name("Mod4"); + bar->status_padding = 1; + bar->status_edge_padding = 3; if (!(bar->mode = strdup("dock"))) { goto cleanup; } diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 96feb47d..9af7ef57 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -2,8 +2,10 @@ #include <math.h> #include <libevdev/libevdev.h> #include <linux/input-event-codes.h> +#include <errno.h> #include <float.h> #include <limits.h> +#include <strings.h> #include <wlr/types/wlr_cursor.h> #include <wlr/types/wlr_xcursor_manager.h> #include <wlr/types/wlr_idle.h> @@ -85,6 +87,10 @@ static struct sway_node *node_at_coords( return NULL; } struct sway_output *output = wlr_output->data; + if (!output) { + // output is being destroyed + return NULL; + } double ox = lx, oy = ly; wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy); @@ -1092,6 +1098,8 @@ static void dispatch_cursor_axis(struct sway_cursor *cursor, enum wlr_edges edge = cont ? find_edge(cont, cursor) : WLR_EDGE_NONE; bool on_border = edge != WLR_EDGE_NONE; bool on_titlebar = cont && !on_border && !surface; + bool on_titlebar_border = cont && on_border && + cursor->cursor->y < cont->content_y; bool on_contents = cont && !on_border && surface; float scroll_factor = (ic == NULL || ic->scroll_factor == FLT_MIN) ? 1.0f : ic->scroll_factor; @@ -1117,7 +1125,7 @@ static void dispatch_cursor_axis(struct sway_cursor *cursor, } // Scrolling on a tabbed or stacked title bar (handled as press event) - if (!handled && on_titlebar) { + if (!handled && (on_titlebar || on_titlebar_border)) { enum sway_container_layout layout = container_parent_layout(cont); if (layout == L_TABBED || layout == L_STACKED) { struct sway_node *tabcontainer = node_get_parent(node); @@ -1527,3 +1535,66 @@ void cursor_warp_to_workspace(struct sway_cursor *cursor, wlr_cursor_warp(cursor->cursor, NULL, x, y); } + +uint32_t get_mouse_bindsym(const char *name, char **error) { + if (strncasecmp(name, "button", strlen("button")) == 0) { + // Map to x11 mouse buttons + int number = name[strlen("button")] - '0'; + if (number < 1 || number > 9 || strlen(name) > strlen("button0")) { + *error = strdup("Only buttons 1-9 are supported. For other mouse " + "buttons, use the name of the event code."); + return 0; + } + static const uint32_t buttons[] = {BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, + SWAY_SCROLL_UP, SWAY_SCROLL_DOWN, SWAY_SCROLL_LEFT, + SWAY_SCROLL_RIGHT, BTN_SIDE, BTN_EXTRA}; + return buttons[number - 1]; + } else if (strncmp(name, "BTN_", strlen("BTN_")) == 0) { + // Get event code from name + int code = libevdev_event_code_from_name(EV_KEY, name); + if (code == -1) { + size_t len = snprintf(NULL, 0, "Unknown event %s", name) + 1; + *error = malloc(len); + if (*error) { + snprintf(*error, len, "Unknown event %s", name); + } + return 0; + } + return code; + } + return 0; +} + +uint32_t get_mouse_bindcode(const char *name, char **error) { + // Validate event code + errno = 0; + char *endptr; + int code = strtol(name, &endptr, 10); + if (endptr == name && code <= 0) { + *error = strdup("Button event code must be a positive integer."); + return 0; + } else if (errno == ERANGE) { + *error = strdup("Button event code out of range."); + return 0; + } + const char *event = libevdev_event_code_get_name(EV_KEY, code); + if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) { + size_t len = snprintf(NULL, 0, "Event code %d (%s) is not a button", + code, event) + 1; + *error = malloc(len); + if (*error) { + snprintf(*error, len, "Event code %d (%s) is not a button", + code, event); + } + return 0; + } + return code; +} + +uint32_t get_mouse_button(const char *name, char **error) { + uint32_t button = get_mouse_bindsym(name, error); + if (!button && !error) { + button = get_mouse_bindcode(name, error); + } + return button; +} diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 19930319..15f89f65 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -681,6 +681,10 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) { } json_object_object_add(json, "bar_height", json_object_new_int(bar->height)); + json_object_object_add(json, "status_padding", + json_object_new_int(bar->status_padding)); + json_object_object_add(json, "status_edge_padding", + json_object_new_int(bar->status_edge_padding)); json_object_object_add(json, "wrap_scroll", json_object_new_boolean(bar->wrap_scroll)); json_object_object_add(json, "workspace_buttons", diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 456db866..ff1bc89f 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -445,8 +445,12 @@ void ipc_event_binding(struct sway_binding *binding) { json_object_object_add(json_binding, "input_code", json_object_new_int(input_code)); json_object_object_add(json_binding, "symbols", symbols); json_object_object_add(json_binding, "symbol", symbol); - json_object_object_add(json_binding, "input_type", binding->type == BINDING_MOUSE ? - json_object_new_string("mouse") : json_object_new_string("keyboard")); + + bool mouse = binding->type == BINDING_MOUSECODE || + binding->type == BINDING_MOUSESYM; + json_object_object_add(json_binding, "input_type", mouse + ? json_object_new_string("mouse") + : json_object_new_string("keyboard")); json_object *json = json_object_new_object(); json_object_object_add(json, "change", json_object_new_string("run")); diff --git a/sway/meson.build b/sway/meson.build index 98676ce0..ab5862c5 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -116,6 +116,8 @@ sway_sources = files( 'commands/bar/position.c', 'commands/bar/separator_symbol.c', 'commands/bar/status_command.c', + 'commands/bar/status_edge_padding.c', + 'commands/bar/status_padding.c', 'commands/bar/strip_workspace_numbers.c', 'commands/bar/strip_workspace_name.c', 'commands/bar/swaybar_command.c', diff --git a/sway/sway-bar.5.scd b/sway/sway-bar.5.scd index 2357591d..b345b392 100644 --- a/sway/sway-bar.5.scd +++ b/sway/sway-bar.5.scd @@ -92,6 +92,16 @@ Sway allows configuring swaybar in the sway configuration file. *modifier* <Modifier>|none Specifies the modifier key that shows a hidden bar. Default is _Mod4_. +*status\_padding* <padding> + Sets the vertical padding that is used for the status line. The default is + _1_. If _padding_ is _0_, blocks will be able to take up the full height of + the bar. This value will be multiplied by the output scale. + +*status\_edge\_padding* <padding> + Sets the padding that is used when the status line is at the right edge of + the bar. This value will be multiplied by the output scale. The default is + _3_. + ## TRAY Swaybar provides a system tray where third-party applications may place icons. diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 3757a097..3398ad58 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -302,7 +302,7 @@ runtime. ``` *bindcode* [--release|--locked] [--input-device=<device>] [--no-warn] <code> <command> - is also available for binding with key codes instead of key names. + is also available for binding with key/button codes instead of key/button names. *client.<class>* <border> <background> <text> <indicator> <child\_border> Configures the color of window borders and title bars. All 5 colors are diff --git a/sway/tree/output.c b/sway/tree/output.c index 95ab9378..f24be010 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -58,6 +58,7 @@ struct sway_output *output_create(struct wlr_output *wlr_output) { wlr_output->data = output; wl_signal_add(&wlr_output->events.destroy, &output->destroy); + wl_signal_init(&output->events.destroy); wl_list_insert(&root->all_outputs, &output->link); @@ -76,7 +77,6 @@ void output_enable(struct sway_output *output, struct output_config *oc) { for (size_t i = 0; i < len; ++i) { wl_list_init(&output->layers[i]); } - wl_signal_init(&output->events.destroy); output->enabled = true; list_add(root->outputs, output); diff --git a/swaybar/bar.c b/swaybar/bar.c index 7aed4dca..d36367fc 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -59,6 +59,7 @@ static void swaybar_output_free(struct swaybar_output *output) { free_workspaces(&output->workspaces); wl_list_remove(&output->link); free(output->name); + free(output->identifier); free(output); } @@ -166,13 +167,15 @@ bool determine_bar_visibility(struct swaybar *bar, bool moving_layer) { return visible; } -static bool bar_uses_output(struct swaybar *bar, const char *name) { - if (bar->config->all_outputs) { +static bool bar_uses_output(struct swaybar_output *output) { + if (output->bar->config->all_outputs) { return true; } + char *identifier = output->identifier; struct config_output *coutput; - wl_list_for_each(coutput, &bar->config->outputs, link) { - if (strcmp(coutput->name, name) == 0) { + wl_list_for_each(coutput, &output->bar->config->outputs, link) { + if (strcmp(coutput->name, output->name) == 0 || + (identifier && strcmp(coutput->name, identifier) == 0)) { return true; } } @@ -233,7 +236,7 @@ static void xdg_output_handle_done(void *data, struct swaybar *bar = output->bar; assert(output->name != NULL); - if (!bar_uses_output(bar, output->name)) { + if (!bar_uses_output(output)) { swaybar_output_free(output); return; } @@ -258,7 +261,22 @@ static void xdg_output_handle_name(void *data, static void xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output, const char *description) { - // Who cares + // wlroots currently sets the description to `make model serial (name)` + // If this changes in the future, this will need to be modified. + struct swaybar_output *output = data; + free(output->identifier); + output->identifier = NULL; + char *paren = strrchr(description, '('); + if (paren) { + size_t length = paren - description; + output->identifier = malloc(length); + if (!output->identifier) { + wlr_log(WLR_ERROR, "Failed to allocate output identifier"); + return; + } + strncpy(output->identifier, description, length); + output->identifier[length - 1] = '\0'; + } } struct zxdg_output_v1_listener xdg_output_listener = { diff --git a/swaybar/config.c b/swaybar/config.c index 9cafe061..d4cc9b1a 100644 --- a/swaybar/config.c +++ b/swaybar/config.c @@ -37,6 +37,8 @@ struct swaybar_config *init_config(void) { config->workspace_buttons = true; config->bindings = create_list(); wl_list_init(&config->outputs); + config->status_padding = 1; + config->status_edge_padding = 3; /* height */ config->height = 0; diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 8e7a542e..bc5c28b4 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -157,7 +157,7 @@ static bool ipc_parse_config( json_object *font, *gaps, *bar_height, *wrap_scroll, *workspace_buttons; json_object *strip_workspace_numbers, *strip_workspace_name; json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol; - json_object *outputs, *bindings; + json_object *outputs, *bindings, *status_padding, *status_edge_padding; json_object_object_get_ex(bar_config, "mode", &mode); json_object_object_get_ex(bar_config, "hidden_state", &hidden_state); json_object_object_get_ex(bar_config, "position", &position); @@ -176,6 +176,9 @@ static bool ipc_parse_config( json_object_object_get_ex(bar_config, "outputs", &outputs); json_object_object_get_ex(bar_config, "pango_markup", &markup); json_object_object_get_ex(bar_config, "bindings", &bindings); + json_object_object_get_ex(bar_config, "status_padding", &status_padding); + json_object_object_get_ex(bar_config, "status_edge_padding", + &status_edge_padding); if (status_command) { free(config->status_command); config->status_command = strdup(json_object_get_string(status_command)); @@ -209,6 +212,12 @@ static bool ipc_parse_config( if (bar_height) { config->height = json_object_get_int(bar_height); } + if (status_padding) { + config->status_padding = json_object_get_int(status_padding); + } + if (status_edge_padding) { + config->status_edge_padding = json_object_get_int(status_edge_padding); + } if (gaps) { json_object *top = json_object_object_get(gaps, "top"); if (top) { diff --git a/swaybar/render.c b/swaybar/render.c index 9fe4ee9c..993c8228 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -35,7 +35,8 @@ static uint32_t render_status_line_error(cairo_t *cairo, cairo_set_source_u32(cairo, 0xFF0000FF); int margin = 3 * output->scale; - int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; + double ws_vertical_padding = + output->bar->config->status_padding * output->scale; char *font = output->bar->config->font; int text_width, text_height; @@ -71,7 +72,7 @@ static uint32_t render_status_line_text(cairo_t *cairo, get_text_size(cairo, config->font, &text_width, &text_height, NULL, output->scale, config->pango_markup, "%s", text); - int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; + double ws_vertical_padding = config->status_padding * output->scale; int margin = 3 * output->scale; uint32_t ideal_height = text_height + ws_vertical_padding * 2; @@ -90,13 +91,24 @@ static uint32_t render_status_line_text(cairo_t *cairo, return output->height; } -static void render_sharp_line(cairo_t *cairo, uint32_t color, +static void render_sharp_rectangle(cairo_t *cairo, uint32_t color, double x, double y, double width, double height) { + cairo_save(cairo); cairo_set_source_u32(cairo, color); + cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE); + cairo_rectangle(cairo, x, y, width, height); + cairo_fill(cairo); + cairo_restore(cairo); +} + +static void render_sharp_line(cairo_t *cairo, uint32_t color, + double x, double y, double width, double height) { if (width > 1 && height > 1) { - cairo_rectangle(cairo, x, y, width, height); - cairo_fill(cairo); + render_sharp_rectangle(cairo, color, x, y, width, height); } else { + cairo_save(cairo); + cairo_set_source_u32(cairo, color); + cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE); if (width == 1) { x += 0.5; height += y; @@ -111,6 +123,7 @@ static void render_sharp_line(cairo_t *cairo, uint32_t color, cairo_set_line_width(cairo, 1.0); cairo_line_to(cairo, width, height); cairo_stroke(cairo); + cairo_restore(cairo); } } @@ -141,7 +154,7 @@ static uint32_t render_status_block(cairo_t *cairo, output->scale, block->markup, "%s", block->full_text); int margin = 3 * output->scale; - int ws_vertical_padding = WS_VERTICAL_PADDING * 2; + double ws_vertical_padding = config->status_padding * output->scale; int width = text_width; if (width < block->min_width) { @@ -157,12 +170,12 @@ static uint32_t render_status_block(cairo_t *cairo, *x -= width; if ((block->border || block->urgent) && block->border_left > 0) { - *x -= (block->border_left + margin); - block_width += block->border_left + margin; + *x -= (block->border_left * output->scale + margin); + block_width += block->border_left * output->scale + margin; } if ((block->border || block->urgent) && block->border_right > 0) { - *x -= (block->border_right + margin); - block_width += block->border_right + margin; + *x -= (block->border_right * output->scale + margin); + block_width += block->border_right * output->scale + margin; } int sep_width, sep_height; @@ -181,8 +194,8 @@ static uint32_t render_status_block(cairo_t *cairo, } } *x -= sep_block_width; - } else { - *x -= margin; + } else if (config->status_edge_padding) { + *x -= config->status_edge_padding * output->scale; } uint32_t height = output->height * output->scale; @@ -199,48 +212,41 @@ static uint32_t render_status_block(cairo_t *cairo, wl_list_insert(&output->hotspots, &hotspot->link); } - double pos = *x; + double x_pos = *x; + double y_pos = ws_vertical_padding; + double render_height = height - ws_vertical_padding * 2; uint32_t bg_color = block->urgent ? config->colors.urgent_workspace.background : block->background; if (bg_color) { - cairo_set_source_u32(cairo, bg_color); - cairo_rectangle(cairo, pos - 0.5 * output->scale, - output->scale, width, height); - cairo_fill(cairo); + render_sharp_rectangle(cairo, bg_color, x_pos, y_pos, + block_width, render_height); } uint32_t border_color = block->urgent ? config->colors.urgent_workspace.border : block->border; if (border_color && block->border_top > 0) { - render_sharp_line(cairo, border_color, - pos - 0.5 * output->scale, output->scale, - text_width, block->border_top); + render_sharp_line(cairo, border_color, x_pos, y_pos, + block_width, block->border_top * output->scale); } if (border_color && block->border_bottom > 0) { - render_sharp_line(cairo, border_color, - pos - 0.5 * output->scale, - height - output->scale - block->border_bottom, - text_width, block->border_bottom); - } - if (border_color != 0 && block->border_left > 0) { - render_sharp_line(cairo, border_color, - pos - 0.5 * output->scale, output->scale, - block->border_left, height); + render_sharp_line(cairo, border_color, x_pos, + y_pos + render_height - block->border_bottom * output->scale, + block_width, block->border_bottom * output->scale); } - if (border_color != 0 && block->border_right > 0) { - render_sharp_line(cairo, border_color, - pos - 0.5 * output->scale + text_width, output->scale, - block->border_right, height); + if (border_color && block->border_left > 0) { + render_sharp_line(cairo, border_color, x_pos, y_pos, + block->border_left * output->scale, render_height); + x_pos += block->border_left * output->scale + margin; } double offset = 0; if (strncmp(block->align, "left", 5) == 0) { - offset = pos; + offset = x_pos; } else if (strncmp(block->align, "right", 5) == 0) { - offset = pos + width - text_width; + offset = x_pos + width - text_width; } else if (strncmp(block->align, "center", 6) == 0) { - offset = pos + (width - text_width) / 2; + offset = x_pos + (width - text_width) / 2; } cairo_move_to(cairo, offset, height / 2.0 - text_height / 2.0); uint32_t color = block->color ? *block->color : config->colors.statusline; @@ -248,14 +254,13 @@ static uint32_t render_status_block(cairo_t *cairo, cairo_set_source_u32(cairo, color); pango_printf(cairo, config->font, output->scale, block->markup, "%s", block->full_text); - pos += width; + x_pos += width; if (block->border && block->border_right > 0) { - pos += margin; - render_sharp_line(cairo, block->border, - pos - 0.5 * output->scale, output->scale, - block->border_right, height); - pos += block->border_right; + x_pos += margin; + render_sharp_line(cairo, border_color, x_pos, y_pos, + block->border_right * output->scale, render_height); + x_pos += block->border_right * output->scale; } if (!edge && block->separator) { @@ -265,14 +270,14 @@ static uint32_t render_status_block(cairo_t *cairo, cairo_set_source_u32(cairo, config->colors.separator); } if (config->sep_symbol) { - offset = pos + (sep_block_width - sep_width) / 2; + offset = x_pos + (sep_block_width - sep_width) / 2; cairo_move_to(cairo, offset, height / 2.0 - sep_height / 2.0); pango_printf(cairo, config->font, output->scale, false, "%s", config->sep_symbol); } else { cairo_set_line_width(cairo, 1); - cairo_move_to(cairo, pos + sep_block_width / 2, margin); - cairo_line_to(cairo, pos + sep_block_width / 2, height - margin); + cairo_move_to(cairo, x_pos + sep_block_width / 2, margin); + cairo_line_to(cairo, x_pos + sep_block_width / 2, height - margin); cairo_stroke(cairo); } } @@ -282,7 +287,7 @@ static uint32_t render_status_block(cairo_t *cairo, static uint32_t render_status_line_i3bar(cairo_t *cairo, struct swaybar_output *output, double *x) { uint32_t max_height = 0; - bool edge = true; + bool edge = *x == output->width * output->scale; struct i3bar_block *block; wl_list_for_each(block, &output->bar->status->blocks, link) { uint32_t h = render_status_block(cairo, output, block, x, edge); diff --git a/swaybar/tray/tray.c b/swaybar/tray/tray.c index 0c3517cb..d5d0c84e 100644 --- a/swaybar/tray/tray.c +++ b/swaybar/tray/tray.c @@ -101,13 +101,17 @@ void tray_in(int fd, short mask, void *data) { } static int cmp_output(const void *item, const void *cmp_to) { - return strcmp(item, cmp_to); + const struct swaybar_output *output = cmp_to; + if (output->identifier && strcmp(item, output->identifier) == 0) { + return 0; + } + return strcmp(item, output->name); } uint32_t render_tray(cairo_t *cairo, struct swaybar_output *output, double *x) { struct swaybar_config *config = output->bar->config; if (config->tray_outputs) { - if (list_seq_find(config->tray_outputs, cmp_output, output->name) == -1) { + if (list_seq_find(config->tray_outputs, cmp_output, output) == -1) { return 0; } } // else display on all 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) diff --git a/swaylock/main.c b/swaylock/main.c index 9a4f3b58..0b167da1 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -396,28 +396,34 @@ static void set_default_colors(struct swaylock_colors *colors) { colors->background = 0xFFFFFFFF; colors->bs_highlight = 0xDB3300FF; colors->key_highlight = 0x33DB00FF; + colors->caps_lock_bs_highlight = 0xDB3300FF; + colors->caps_lock_key_highlight = 0x33DB00FF; colors->separator = 0x000000FF; colors->inside = (struct swaylock_colorset){ .input = 0x000000C0, .cleared = 0xE5A445C0, + .caps_lock = 0x000000C0, .verifying = 0x0072FFC0, .wrong = 0xFA0000C0, }; colors->line = (struct swaylock_colorset){ .input = 0x000000FF, .cleared = 0x000000FF, + .caps_lock = 0x000000FF, .verifying = 0x000000FF, .wrong = 0x000000FF, }; colors->ring = (struct swaylock_colorset){ .input = 0x337D00FF, .cleared = 0xE5A445FF, + .caps_lock = 0xE5A445FF, .verifying = 0x3300FFFF, .wrong = 0x7D3300FF, }; colors->text = (struct swaylock_colorset){ .input = 0xE5A445FF, .cleared = 0x000000FF, + .caps_lock = 0xE5A445FF, .verifying = 0x000000FF, .wrong = 0x000000FF, }; @@ -433,25 +439,31 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, enum line_mode *line_mode, char **config_path) { enum long_option_codes { LO_BS_HL_COLOR = 256, + LO_CAPS_LOCK_BS_HL_COLOR, + LO_CAPS_LOCK_KEY_HL_COLOR, LO_FONT, LO_IND_RADIUS, LO_IND_THICKNESS, LO_INSIDE_COLOR, LO_INSIDE_CLEAR_COLOR, + LO_INSIDE_CAPS_LOCK_COLOR, LO_INSIDE_VER_COLOR, LO_INSIDE_WRONG_COLOR, LO_KEY_HL_COLOR, LO_LINE_COLOR, LO_LINE_CLEAR_COLOR, + LO_LINE_CAPS_LOCK_COLOR, LO_LINE_VER_COLOR, LO_LINE_WRONG_COLOR, LO_RING_COLOR, LO_RING_CLEAR_COLOR, + LO_RING_CAPS_LOCK_COLOR, LO_RING_VER_COLOR, LO_RING_WRONG_COLOR, LO_SEP_COLOR, LO_TEXT_COLOR, LO_TEXT_CLEAR_COLOR, + LO_TEXT_CAPS_LOCK_COLOR, LO_TEXT_VER_COLOR, LO_TEXT_WRONG_COLOR, }; @@ -463,6 +475,8 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, {"daemonize", no_argument, NULL, 'f'}, {"help", no_argument, NULL, 'h'}, {"image", required_argument, NULL, 'i'}, + {"disable-caps-lock-text", no_argument, NULL, 'L'}, + {"indicator-caps-lock", no_argument, NULL, 'l'}, {"line-uses-inside", no_argument, NULL, 'n'}, {"socket", required_argument, NULL, 'p'}, {"line-uses-ring", no_argument, NULL, 'r'}, @@ -471,25 +485,31 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, {"no-unlock-indicator", no_argument, NULL, 'u'}, {"version", no_argument, NULL, 'v'}, {"bs-hl-color", required_argument, NULL, LO_BS_HL_COLOR}, + {"caps-lock-bs-hl-color", required_argument, NULL, LO_CAPS_LOCK_BS_HL_COLOR}, + {"caps-lock-key-hl-color", required_argument, NULL, LO_CAPS_LOCK_KEY_HL_COLOR}, {"font", required_argument, NULL, LO_FONT}, {"indicator-radius", required_argument, NULL, LO_IND_RADIUS}, {"indicator-thickness", required_argument, NULL, LO_IND_THICKNESS}, {"inside-color", required_argument, NULL, LO_INSIDE_COLOR}, {"inside-clear-color", required_argument, NULL, LO_INSIDE_CLEAR_COLOR}, + {"inside-caps-lock-color", required_argument, NULL, LO_INSIDE_CAPS_LOCK_COLOR}, {"inside-ver-color", required_argument, NULL, LO_INSIDE_VER_COLOR}, {"inside-wrong-color", required_argument, NULL, LO_INSIDE_WRONG_COLOR}, {"key-hl-color", required_argument, NULL, LO_KEY_HL_COLOR}, {"line-color", required_argument, NULL, LO_LINE_COLOR}, {"line-clear-color", required_argument, NULL, LO_LINE_CLEAR_COLOR}, + {"line-caps-lock-color", required_argument, NULL, LO_LINE_CAPS_LOCK_COLOR}, {"line-ver-color", required_argument, NULL, LO_LINE_VER_COLOR}, {"line-wrong-color", required_argument, NULL, LO_LINE_WRONG_COLOR}, {"ring-color", required_argument, NULL, LO_RING_COLOR}, {"ring-clear-color", required_argument, NULL, LO_RING_CLEAR_COLOR}, + {"ring-caps-lock-color", required_argument, NULL, LO_RING_CAPS_LOCK_COLOR}, {"ring-ver-color", required_argument, NULL, LO_RING_VER_COLOR}, {"ring-wrong-color", required_argument, NULL, LO_RING_WRONG_COLOR}, {"separator-color", required_argument, NULL, LO_SEP_COLOR}, {"text-color", required_argument, NULL, LO_TEXT_COLOR}, {"text-clear-color", required_argument, NULL, LO_TEXT_CLEAR_COLOR}, + {"text-caps-lock-color", required_argument, NULL, LO_TEXT_CAPS_LOCK_COLOR}, {"text-ver-color", required_argument, NULL, LO_TEXT_VER_COLOR}, {"text-wrong-color", required_argument, NULL, LO_TEXT_WRONG_COLOR}, {0, 0, 0, 0} @@ -498,76 +518,97 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, const char usage[] = "Usage: swaylock [options...]\n" "\n" - " -C, --config <config_file> " + " -C, --config <config_file> " "Path to the config file.\n" - " -c, --color <color> " + " -c, --color <color> " "Turn the screen into the given color instead of white.\n" - " -e, --ignore-empty-password " + " -e, --ignore-empty-password " "When an empty password is provided, do not validate it.\n" - " -f, --daemonize " + " -f, --daemonize " "Detach from the controlling terminal after locking.\n" - " -h, --help " + " -h, --help " "Show help message and quit.\n" - " -i, --image [<output>:]<path> " + " -i, --image [<output>:]<path> " "Display the given image.\n" - " -s, --scaling <mode> " + " -L, --disable-caps-lock-text " + "Disable the Caps Lock text.\n" + " -l, --indicator-caps-lock " + "Show the current Caps Lock state also on the indicator.\n" + " -s, --scaling <mode> " "Scaling mode: stretch, fill, fit, center, tile.\n" - " -t, --tiling " + " -t, --tiling " "Same as --scaling=tile.\n" - " -u, --no-unlock-indicator " + " -u, --no-unlock-indicator " "Disable the unlock indicator.\n" - " -v, --version " + " -v, --version " "Show the version number and quit.\n" - " --bs-hl-color <color> " + " --bs-hl-color <color> " "Sets the color of backspace highlight segments.\n" - " --font <font> " + " --caps-lock-bs-hl-color <color> " + "Sets the color of backspace highlight segments when Caps Lock " + "is active.\n" + " --caps-lock-key-hl-color <color> " + "Sets the color of the key press highlight segments when " + "Caps Lock is active.\n" + " --font <font> " "Sets the font of the text.\n" - " --indicator-radius <radius> " + " --indicator-radius <radius> " "Sets the indicator radius.\n" - " --indicator-thickness <thick> " + " --indicator-thickness <thick> " "Sets the indicator thickness.\n" - " --inside-color <color> " + " --inside-color <color> " "Sets the color of the inside of the indicator.\n" - " --inside-clear-color <color> " + " --inside-clear-color <color> " "Sets the color of the inside of the indicator when cleared.\n" - " --inside-ver-color <color> " + " --inside-caps-lock-color <color> " + "Sets the color of the inside of the indicator when Caps Lock " + "is active.\n" + " --inside-ver-color <color> " "Sets the color of the inside of the indicator when verifying.\n" - " --inside-wrong-color <color> " + " --inside-wrong-color <color> " "Sets the color of the inside of the indicator when invalid.\n" - " --key-hl-color <color> " + " --key-hl-color <color> " "Sets the color of the key press highlight segments.\n" - " --line-color <color> " + " --line-color <color> " "Sets the color of the line between the inside and ring.\n" - " --line-clear-color <color> " + " --line-clear-color <color> " "Sets the color of the line between the inside and ring when " "cleared.\n" - " --line-ver-color <color> " + " --line-caps-lock-color <color> " + "Sets the color of the line between the inside and ring when " + "Caps Lock is active.\n" + " --line-ver-color <color> " "Sets the color of the line between the inside and ring when " "verifying.\n" - " --line-wrong-color <color> " + " --line-wrong-color <color> " "Sets the color of the line between the inside and ring when " "invalid.\n" - " -n, --line-uses-inside " + " -n, --line-uses-inside " "Use the inside color for the line between the inside and ring.\n" - " -r, --line-uses-ring " + " -r, --line-uses-ring " "Use the ring color for the line between the inside and ring.\n" - " --ring-color <color> " + " --ring-color <color> " "Sets the color of the ring of the indicator.\n" - " --ring-clear-color <color> " + " --ring-clear-color <color> " "Sets the color of the ring of the indicator when cleared.\n" - " --ring-ver-color <color> " + " --ring-caps-lock-color <color> " + "Sets the color of the ring of the indicator when Caps Lock " + "is active.\n" + " --ring-ver-color <color> " "Sets the color of the ring of the indicator when verifying.\n" - " --ring-wrong-color <color> " + " --ring-wrong-color <color> " "Sets the color of the ring of the indicator when invalid.\n" - " --separator-color <color> " + " --separator-color <color> " "Sets the color of the lines that separate highlight segments.\n" - " --text-color <color> " + " --text-color <color> " "Sets the color of the text.\n" - " --text-clear-color <color> " + " --text-clear-color <color> " "Sets the color of the text when cleared.\n" - " --text-ver-color <color> " + " --text-caps-lock-color <color> " + "Sets the color of the text when Caps Lock is active.\n" + " --text-ver-color <color> " "Sets the color of the text when verifying.\n" - " --text-wrong-color <color> " + " --text-wrong-color <color> " "Sets the color of the text when invalid.\n" "\n" "All <color> options are of the form <rrggbb[aa]>.\n"; @@ -576,7 +617,7 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, optind = 1; while (1) { int opt_idx = 0; - c = getopt_long(argc, argv, "c:efhi:nrs:tuvC:", long_options, &opt_idx); + c = getopt_long(argc, argv, "c:efhi:Llnrs:tuvC:", long_options, &opt_idx); if (c == -1) { break; } @@ -607,6 +648,16 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, load_image(optarg, state); } break; + case 'L': + if (state) { + state->args.show_caps_lock_text = false; + } + break; + case 'l': + if (state) { + state->args.show_caps_lock_indicator = true; + } + break; case 'n': if (line_mode) { *line_mode = LM_INSIDE; @@ -644,6 +695,16 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, state->args.colors.bs_highlight = parse_color(optarg); } break; + case LO_CAPS_LOCK_BS_HL_COLOR: + if (state) { + state->args.colors.caps_lock_bs_highlight = parse_color(optarg); + } + break; + case LO_CAPS_LOCK_KEY_HL_COLOR: + if (state) { + state->args.colors.caps_lock_key_highlight = parse_color(optarg); + } + break; case LO_FONT: if (state) { free(state->args.font); @@ -670,6 +731,11 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, state->args.colors.inside.cleared = parse_color(optarg); } break; + case LO_INSIDE_CAPS_LOCK_COLOR: + if (state) { + state->args.colors.inside.caps_lock = parse_color(optarg); + } + break; case LO_INSIDE_VER_COLOR: if (state) { state->args.colors.inside.verifying = parse_color(optarg); @@ -695,6 +761,11 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, state->args.colors.line.cleared = parse_color(optarg); } break; + case LO_LINE_CAPS_LOCK_COLOR: + if (state) { + state->args.colors.line.caps_lock = parse_color(optarg); + } + break; case LO_LINE_VER_COLOR: if (state) { state->args.colors.line.verifying = parse_color(optarg); @@ -715,6 +786,11 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, state->args.colors.ring.cleared = parse_color(optarg); } break; + case LO_RING_CAPS_LOCK_COLOR: + if (state) { + state->args.colors.ring.caps_lock = parse_color(optarg); + } + break; case LO_RING_VER_COLOR: if (state) { state->args.colors.ring.verifying = parse_color(optarg); @@ -740,6 +816,11 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state, state->args.colors.text.cleared = parse_color(optarg); } break; + case LO_TEXT_CAPS_LOCK_COLOR: + if (state) { + state->args.colors.text.caps_lock = parse_color(optarg); + } + break; case LO_TEXT_VER_COLOR: if (state) { state->args.colors.text.verifying = parse_color(optarg); @@ -857,6 +938,8 @@ int main(int argc, char **argv) { .thickness = 10, .ignore_empty = false, .show_indicator = true, + .show_caps_lock_indicator = false, + .show_caps_lock_text = true }; wl_list_init(&state.images); set_default_colors(&state.args.colors); diff --git a/swaylock/render.c b/swaylock/render.c index cbd5d01d..5aedaad5 100644 --- a/swaylock/render.c +++ b/swaylock/render.c @@ -18,7 +18,17 @@ static void set_color_for_state(cairo_t *cairo, struct swaylock_state *state, } else if (state->auth_state == AUTH_STATE_CLEAR) { cairo_set_source_u32(cairo, colorset->cleared); } else { - cairo_set_source_u32(cairo, colorset->input); + if (state->xkb.caps_lock && state->args.show_caps_lock_indicator) { + cairo_set_source_u32(cairo, colorset->caps_lock); + } else if (state->xkb.caps_lock && !state->args.show_caps_lock_indicator && + state->args.show_caps_lock_text) { + uint32_t inputtextcolor = state->args.colors.text.input; + state->args.colors.text.input = state->args.colors.text.caps_lock; + cairo_set_source_u32(cairo, colorset->input); + state->args.colors.text.input = inputtextcolor; + } else { + cairo_set_source_u32(cairo, colorset->input); + } } } @@ -92,7 +102,8 @@ void render_frame(struct swaylock_surface *surface) { break; case AUTH_STATE_INPUT: case AUTH_STATE_INPUT_NOP: - if (state->xkb.caps_lock) { + case AUTH_STATE_BACKSPACE: + if (state->xkb.caps_lock && state->args.show_caps_lock_text) { text = "Caps Lock"; } break; @@ -125,9 +136,17 @@ void render_frame(struct swaylock_surface *surface) { arc_radius, highlight_start, highlight_start + TYPE_INDICATOR_RANGE); if (state->auth_state == AUTH_STATE_INPUT) { - cairo_set_source_u32(cairo, state->args.colors.key_highlight); + if (state->xkb.caps_lock && state->args.show_caps_lock_indicator) { + cairo_set_source_u32(cairo, state->args.colors.caps_lock_key_highlight); + } else { + cairo_set_source_u32(cairo, state->args.colors.key_highlight); + } } else { - cairo_set_source_u32(cairo, state->args.colors.bs_highlight); + if (state->xkb.caps_lock && state->args.show_caps_lock_indicator) { + cairo_set_source_u32(cairo, state->args.colors.caps_lock_bs_highlight); + } else { + cairo_set_source_u32(cairo, state->args.colors.bs_highlight); + } } cairo_stroke(cairo); diff --git a/swaylock/swaylock.1.scd b/swaylock/swaylock.1.scd index 9f39a913..2c7979be 100644 --- a/swaylock/swaylock.1.scd +++ b/swaylock/swaylock.1.scd @@ -44,6 +44,12 @@ Locks your Wayland session. Display the given image, optionally only on the given output. Use -c to set a background color. +*-L, --disable-caps-lock-text* + Disable the Caps Lock Text. + +*-l, --indicator-caps-lock* + Show the current Caps Lock state also on the indicator. + *-s, --scaling* Scaling mode for images: _stretch_, _fill_, _fit_, _center_, or _tile_. @@ -58,6 +64,12 @@ Locks your Wayland session. *--bs-hl-color* <rrggbb[aa]> Sets the color of backspace highlight segments. +*--caps-lock-bs-hl-color* <rrggbb[aa]> + Sets the color of backspace highlight segments when Caps Lock is active. + +*--caps-lock-bs-hl-color* <rrggbb[aa]> + Sets the color of the key press highlight segments when Caps Lock is active. + *--font* <font> Sets the font of the text inside the indicator. @@ -75,6 +87,9 @@ Locks your Wayland session. *--inside-clear-color* <rrggbb[aa]> Sets the color of the inside of the indicator when cleared. +*--inside-caps-lock-color* <rrggbb[aa]> + Sets the color of the inside of the indicator when Caps Lock is active. + *--inside-ver-color* <rrggbb[aa]> Sets the color of the inside of the indicator when verifying. @@ -92,6 +107,10 @@ Locks your Wayland session. Sets the color of the lines that separate the inside and outside of the indicator when cleared. +*--line-caps-lock-color* <rrggbb[aa]> + Sets the color of the line between the inside and ring when Caps Lock + is active. + *--line-ver-color* <rrggbb[aa]> Sets the color of the lines that separate the inside and outside of the indicator when verifying. @@ -114,6 +133,9 @@ Locks your Wayland session. *--ring-clear-color* <rrggbb[aa]> Sets the color of the outside of the indicator when cleared. +*--ring-caps-lock-color* <rrggbb[aa]> + Sets the color of the ring of the indicator when Caps Lock is active. + *--ring-ver-color* <rrggbb[aa]> Sets the color of the outside of the indicator when verifying. @@ -129,6 +151,9 @@ Locks your Wayland session. *--text-clear-color* <rrggbb[aa]> Sets the color of the text inside the indicator when cleared. +*--text-caps-lock-color* <rrggbb[aa]> + Sets the color of the text when Caps Lock is active. + *--text-ver-color* <rrggbb[aa]> Sets the color of the text inside the indicator when verifying. |