summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--completions/bash/swayidle48
-rw-r--r--completions/fish/swayidle.fish3
-rw-r--r--completions/zsh/_swayidle22
-rw-r--r--include/sway/commands.h2
-rw-r--r--include/sway/config.h2
-rw-r--r--include/sway/input/input-manager.h4
-rw-r--r--include/sway/input/seat.h3
-rw-r--r--include/swaybar/bar.h1
-rw-r--r--include/swaybar/config.h2
-rw-r--r--include/swaylock/swaylock.h5
-rw-r--r--meson.build4
-rw-r--r--sway/commands/bar.c2
-rw-r--r--sway/commands/bar/status_edge_padding.c21
-rw-r--r--sway/commands/bar/status_padding.c21
-rw-r--r--sway/commands/input/events.c76
-rw-r--r--sway/config.c23
-rw-r--r--sway/config/bar.c4
-rw-r--r--sway/input/input-manager.c172
-rw-r--r--sway/input/seat.c37
-rw-r--r--sway/ipc-json.c25
-rw-r--r--sway/meson.build2
-rw-r--r--sway/sway-bar.5.scd12
-rw-r--r--sway/sway-input.5.scd9
-rw-r--r--swaybar/bar.c30
-rw-r--r--swaybar/config.c2
-rw-r--r--swaybar/ipc.c11
-rw-r--r--swaybar/render.c37
-rw-r--r--swaybar/tray/tray.c8
-rw-r--r--swayidle/main.c483
-rw-r--r--swayidle/meson.build27
-rw-r--r--swayidle/swayidle.1.scd63
-rw-r--r--swaylock/main.c153
-rw-r--r--swaylock/render.c27
-rw-r--r--swaylock/swaylock.1.scd25
-rw-r--r--swaymsg/main.c6
35 files changed, 642 insertions, 730 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 @@
1# swaymsg(1) completion
2
3_swayidle()
4{
5 local cur prev
6 _get_comp_words_by_ref -n : cur prev
7 local prev2=${COMP_WORDS[COMP_CWORD-2]}
8 local prev3=${COMP_WORDS[COMP_CWORD-3]}
9
10 events=(
11 'timeout'
12 'before-sleep'
13 )
14
15 short=(
16 -h
17 -d
18 )
19
20 if [ "$prev" = timeout ]; then
21 # timeout <timeout>
22 return
23 elif [ "$prev2" = timeout ]; then
24 # timeout <timeout> <timeout command>
25 COMPREPLY=($(compgen -c -- "$cur"))
26 return
27 elif [ "$prev3" = timeout ]; then
28 # timeout <timeout> <timeout command> [resume <resume command>]
29 COMPREPLY=(resume)
30 # optional argument; no return here as user may skip 'resume'
31 fi
32
33 case "$prev" in
34 resume)
35 COMPREPLY=($(compgen -c -- "$cur"))
36 return
37 ;;
38 before-sleep)
39 COMPREPLY=($(compgen -c -- "$cur"))
40 return
41 ;;
42 esac
43
44 COMPREPLY+=($(compgen -W "${events[*]}" -- "$cur"))
45 COMPREPLY+=($(compgen -W "${short[*]}" -- "$cur"))
46
47} &&
48complete -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 @@
1# swayidle
2complete -c swayidle -s h --description 'show help'
3complete -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 @@
1#compdef swayidle
2#
3# Completion script for swayidle
4#
5
6local events=('timeout:Execute timeout command if there is no activity for timeout seconds'
7 'before-sleep:Execute before-sleep command before sleep')
8local resume=('resume:Execute command when there is activity again')
9
10if (($#words <= 2)); then
11 _arguments -C \
12 '(-h --help)'{-h,--help}'[Show help message and quit]' \
13 '(-d)'-d'[Enable debug output]'
14 _describe -t "events" 'swayidle' events
15
16elif [[ "$words[-3]" == before-sleep || "$words[-3]" == resume ]]; then
17 _describe -t "events" 'swayidle' events
18
19elif [[ "$words[-4]" == timeout ]]; then
20 _describe -t "events" 'swayidle' events
21 _describe -t "resume" 'swayidle' resume
22fi
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;
198sway_cmd bar_cmd_position; 198sway_cmd bar_cmd_position;
199sway_cmd bar_cmd_separator_symbol; 199sway_cmd bar_cmd_separator_symbol;
200sway_cmd bar_cmd_status_command; 200sway_cmd bar_cmd_status_command;
201sway_cmd bar_cmd_status_edge_padding;
202sway_cmd bar_cmd_status_padding;
201sway_cmd bar_cmd_pango_markup; 203sway_cmd bar_cmd_pango_markup;
202sway_cmd bar_cmd_strip_workspace_numbers; 204sway_cmd bar_cmd_strip_workspace_numbers;
203sway_cmd bar_cmd_strip_workspace_name; 205sway_cmd bar_cmd_strip_workspace_name;
diff --git a/include/sway/config.h b/include/sway/config.h
index 29c21afe..a667984d 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -232,6 +232,8 @@ struct bar_config {
232 bool verbose; 232 bool verbose;
233 struct side_gaps gaps; 233 struct side_gaps gaps;
234 pid_t pid; 234 pid_t pid;
235 int status_padding;
236 int status_edge_padding;
235 struct { 237 struct {
236 char *background; 238 char *background;
237 char *statusline; 239 char *statusline;
diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h
index 08e749dc..8e8bf1f2 100644
--- a/include/sway/input/input-manager.h
+++ b/include/sway/input/input-manager.h
@@ -37,6 +37,10 @@ void input_manager_configure_xcursor(void);
37 37
38void input_manager_apply_input_config(struct input_config *input_config); 38void input_manager_apply_input_config(struct input_config *input_config);
39 39
40void input_manager_reset_input(struct sway_input_device *input_device);
41
42void input_manager_reset_all_inputs();
43
40void input_manager_apply_seat_config(struct seat_config *seat_config); 44void input_manager_apply_seat_config(struct seat_config *seat_config);
41 45
42struct sway_seat *input_manager_get_default_seat(void); 46struct sway_seat *input_manager_get_default_seat(void);
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h
index ce8abde9..d2f14895 100644
--- a/include/sway/input/seat.h
+++ b/include/sway/input/seat.h
@@ -92,6 +92,9 @@ void seat_add_device(struct sway_seat *seat,
92void seat_configure_device(struct sway_seat *seat, 92void seat_configure_device(struct sway_seat *seat,
93 struct sway_input_device *device); 93 struct sway_input_device *device);
94 94
95void seat_reset_device(struct sway_seat *seat,
96 struct sway_input_device *input_device);
97
95void seat_remove_device(struct sway_seat *seat, 98void seat_remove_device(struct sway_seat *seat,
96 struct sway_input_device *device); 99 struct sway_input_device *device);
97 100
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 {
61 struct wl_list hotspots; // swaybar_hotspot::link 61 struct wl_list hotspots; // swaybar_hotspot::link
62 62
63 char *name; 63 char *name;
64 char *identifier;
64 bool focused; 65 bool focused;
65 66
66 uint32_t width, height; 67 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 {
43 struct wl_list outputs; // config_output::link 43 struct wl_list outputs; // config_output::link
44 bool all_outputs; 44 bool all_outputs;
45 int height; 45 int height;
46 int status_padding;
47 int status_edge_padding;
46 struct { 48 struct {
47 int top; 49 int top;
48 int right; 50 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 {
22struct swaylock_colorset { 22struct swaylock_colorset {
23 uint32_t input; 23 uint32_t input;
24 uint32_t cleared; 24 uint32_t cleared;
25 uint32_t caps_lock;
25 uint32_t verifying; 26 uint32_t verifying;
26 uint32_t wrong; 27 uint32_t wrong;
27}; 28};
@@ -30,6 +31,8 @@ struct swaylock_colors {
30 uint32_t background; 31 uint32_t background;
31 uint32_t bs_highlight; 32 uint32_t bs_highlight;
32 uint32_t key_highlight; 33 uint32_t key_highlight;
34 uint32_t caps_lock_bs_highlight;
35 uint32_t caps_lock_key_highlight;
33 uint32_t separator; 36 uint32_t separator;
34 struct swaylock_colorset inside; 37 struct swaylock_colorset inside;
35 struct swaylock_colorset line; 38 struct swaylock_colorset line;
@@ -45,6 +48,8 @@ struct swaylock_args {
45 uint32_t thickness; 48 uint32_t thickness;
46 bool ignore_empty; 49 bool ignore_empty;
47 bool show_indicator; 50 bool show_indicator;
51 bool show_caps_lock_text;
52 bool show_caps_lock_indicator;
48 bool daemonize; 53 bool daemonize;
49}; 54};
50 55
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()
86 'sway/sway-output.5.scd', 86 'sway/sway-output.5.scd',
87 'swaylock/swaylock.1.scd', 87 'swaylock/swaylock.1.scd',
88 'swaymsg/swaymsg.1.scd', 88 'swaymsg/swaymsg.1.scd',
89 'swayidle/swayidle.1.scd',
90 'swaynag/swaynag.1.scd', 89 'swaynag/swaynag.1.scd',
91 'swaynag/swaynag.5.scd', 90 'swaynag/swaynag.5.scd',
92 ] 91 ]
@@ -146,7 +145,6 @@ subdir('swaymsg')
146subdir('client') 145subdir('client')
147subdir('swaybg') 146subdir('swaybg')
148subdir('swaybar') 147subdir('swaybar')
149subdir('swayidle')
150subdir('swaynag') 148subdir('swaynag')
151subdir('swaylock') 149subdir('swaylock')
152 150
@@ -214,7 +212,6 @@ if (get_option('bash-completions'))
214 bash_files = files( 212 bash_files = files(
215 'completions/bash/sway', 213 'completions/bash/sway',
216 'completions/bash/swaybar', 214 'completions/bash/swaybar',
217 'completions/bash/swayidle',
218 'completions/bash/swaylock', 215 'completions/bash/swaylock',
219 'completions/bash/swaymsg', 216 'completions/bash/swaymsg',
220 ) 217 )
@@ -226,7 +223,6 @@ endif
226if (get_option('fish-completions')) 223if (get_option('fish-completions'))
227 fish_files = files( 224 fish_files = files(
228 'completions/fish/sway.fish', 225 'completions/fish/sway.fish',
229 'completions/fish/swayidle.fish',
230 'completions/fish/swaylock.fish', 226 'completions/fish/swaylock.fish',
231 'completions/fish/swaymsg.fish', 227 'completions/fish/swaymsg.fish',
232 'completions/fish/swaynag.fish', 228 '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[] = {
23 { "position", bar_cmd_position }, 23 { "position", bar_cmd_position },
24 { "separator_symbol", bar_cmd_separator_symbol }, 24 { "separator_symbol", bar_cmd_separator_symbol },
25 { "status_command", bar_cmd_status_command }, 25 { "status_command", bar_cmd_status_command },
26 { "status_edge_padding", bar_cmd_status_edge_padding },
27 { "status_padding", bar_cmd_status_padding },
26 { "strip_workspace_name", bar_cmd_strip_workspace_name }, 28 { "strip_workspace_name", bar_cmd_strip_workspace_name },
27 { "strip_workspace_numbers", bar_cmd_strip_workspace_numbers }, 29 { "strip_workspace_numbers", bar_cmd_strip_workspace_numbers },
28 { "tray_bindsym", bar_cmd_tray_bindsym }, 30 { "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 @@
1#include <stdlib.h>
2#include <string.h>
3#include "sway/commands.h"
4#include "log.h"
5
6struct cmd_results *bar_cmd_status_edge_padding(int argc, char **argv) {
7 struct cmd_results *error = NULL;
8 if ((error = checkarg(argc, "status_edge_padding", EXPECTED_EQUAL_TO, 1))) {
9 return error;
10 }
11 char *end;
12 int padding = strtol(argv[0], &end, 10);
13 if (strlen(end) || padding < 0) {
14 return cmd_results_new(CMD_INVALID, "status_edge_padding",
15 "Padding must be a positive integer");
16 }
17 config->current_bar->status_edge_padding = padding;
18 wlr_log(WLR_DEBUG, "Status edge padding on bar %s: %d",
19 config->current_bar->id, config->current_bar->status_edge_padding);
20 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
21}
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 @@
1#include <stdlib.h>
2#include <string.h>
3#include "sway/commands.h"
4#include "log.h"
5
6struct cmd_results *bar_cmd_status_padding(int argc, char **argv) {
7 struct cmd_results *error = NULL;
8 if ((error = checkarg(argc, "status_padding", EXPECTED_EQUAL_TO, 1))) {
9 return error;
10 }
11 char *end;
12 int padding = strtol(argv[0], &end, 10);
13 if (strlen(end) || padding < 0) {
14 return cmd_results_new(CMD_INVALID, "status_padding",
15 "Padding must be a positive integer");
16 }
17 config->current_bar->status_padding = padding;
18 wlr_log(WLR_DEBUG, "Status padding on bar %s: %d",
19 config->current_bar->id, config->current_bar->status_padding);
20 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
21}
diff --git a/sway/commands/input/events.c b/sway/commands/input/events.c
index e7ed69c6..69f46269 100644
--- a/sway/commands/input/events.c
+++ b/sway/commands/input/events.c
@@ -1,10 +1,69 @@
1#include <limits.h>
1#include <string.h> 2#include <string.h>
2#include <strings.h> 3#include <strings.h>
4#include <wlr/backend/libinput.h>
3#include "sway/config.h" 5#include "sway/config.h"
4#include "sway/commands.h" 6#include "sway/commands.h"
5#include "sway/input/input-manager.h" 7#include "sway/input/input-manager.h"
6#include "log.h" 8#include "log.h"
7 9
10static void toggle_send_events_for_device(struct input_config *ic,
11 struct sway_input_device *input_device) {
12 struct wlr_input_device *wlr_device = input_device->wlr_device;
13 if (!wlr_input_device_is_libinput(wlr_device)) {
14 return;
15 }
16 struct libinput_device *libinput_dev
17 = wlr_libinput_get_device_handle(wlr_device);
18
19 enum libinput_config_send_events_mode mode =
20 libinput_device_config_send_events_get_mode(libinput_dev);
21 uint32_t possible =
22 libinput_device_config_send_events_get_modes(libinput_dev);
23
24 switch (mode) {
25 case LIBINPUT_CONFIG_SEND_EVENTS_ENABLED:
26 mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
27 if (possible & mode) {
28 break;
29 }
30 // fall through
31 case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE:
32 mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
33 if (possible & mode) {
34 break;
35 }
36 // fall through
37 case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED:
38 default:
39 mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
40 break;
41 }
42
43 ic->send_events = mode;
44}
45
46static void toggle_send_events(struct input_config *ic) {
47 struct sway_input_device *input_device = NULL;
48 wl_list_for_each(input_device, &server.input->devices, link) {
49 if (strcmp(input_device->identifier, ic->identifier) == 0) {
50 toggle_send_events_for_device(ic, input_device);
51 }
52 }
53}
54
55static void toggle_wildcard_send_events() {
56 struct sway_input_device *input_device = NULL;
57 wl_list_for_each(input_device, &server.input->devices, link) {
58 struct input_config *ic = new_input_config(input_device->identifier);
59 if (!ic) {
60 break;
61 }
62 toggle_send_events_for_device(ic, input_device);
63 store_input_config(ic);
64 }
65}
66
8struct cmd_results *input_cmd_events(int argc, char **argv) { 67struct cmd_results *input_cmd_events(int argc, char **argv) {
9 struct cmd_results *error = NULL; 68 struct cmd_results *error = NULL;
10 if ((error = checkarg(argc, "events", EXPECTED_AT_LEAST, 1))) { 69 if ((error = checkarg(argc, "events", EXPECTED_AT_LEAST, 1))) {
@@ -23,9 +82,24 @@ struct cmd_results *input_cmd_events(int argc, char **argv) {
23 } else if (strcasecmp(argv[0], "disabled_on_external_mouse") == 0) { 82 } else if (strcasecmp(argv[0], "disabled_on_external_mouse") == 0) {
24 ic->send_events = 83 ic->send_events =
25 LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; 84 LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
26 } else { 85 } else if (config->reading) {
27 return cmd_results_new(CMD_INVALID, "events", 86 return cmd_results_new(CMD_INVALID, "events",
28 "Expected 'events <enabled|disabled|disabled_on_external_mouse>'"); 87 "Expected 'events <enabled|disabled|disabled_on_external_mouse>'");
88 } else if (strcasecmp(argv[0], "toggle") == 0) {
89 if (strcmp(ic->identifier, "*") == 0) {
90 // Update the device input configs and then reset the wildcard
91 // config send events mode so that is does not override the device
92 // ones. The device ones will be applied when attempting to apply
93 // the wildcard config
94 toggle_wildcard_send_events();
95 ic->send_events = INT_MIN;
96 } else {
97 toggle_send_events(ic);
98 }
99 } else {
100 return cmd_results_new(CMD_INVALID, "events",
101 "Expected 'events <enabled|disabled|disabled_on_external_mouse|"
102 "toggle>'");
29 } 103 }
30 104
31 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 105 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
diff --git a/sway/config.c b/sway/config.c
index f99f043c..5ca4806c 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -387,6 +387,8 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
387 memcpy(&config->swaynag_config_errors, 387 memcpy(&config->swaynag_config_errors,
388 &old_config->swaynag_config_errors, 388 &old_config->swaynag_config_errors,
389 sizeof(struct swaynag_instance)); 389 sizeof(struct swaynag_instance));
390
391 input_manager_reset_all_inputs();
390 } 392 }
391 393
392 config->current_config_path = path; 394 config->current_config_path = path;
@@ -571,15 +573,18 @@ bool load_include_configs(const char *path, struct sway_config *config,
571} 573}
572 574
573// get line, with backslash continuation 575// get line, with backslash continuation
574static ssize_t getline_with_cont(char **lineptr, size_t *line_size, FILE *file) { 576static ssize_t getline_with_cont(char **lineptr, size_t *line_size, FILE *file,
577 int *nlines) {
575 char *next_line = NULL; 578 char *next_line = NULL;
576 size_t next_line_size = 0; 579 size_t next_line_size = 0;
577 ssize_t nread = getline(lineptr, line_size, file); 580 ssize_t nread = getline(lineptr, line_size, file);
581 *nlines = nread == -1 ? 0 : 1;
578 while (nread >= 2 && strcmp(&(*lineptr)[nread - 2], "\\\n") == 0) { 582 while (nread >= 2 && strcmp(&(*lineptr)[nread - 2], "\\\n") == 0) {
579 ssize_t next_nread = getline(&next_line, &next_line_size, file); 583 ssize_t next_nread = getline(&next_line, &next_line_size, file);
580 if (next_nread == -1) { 584 if (next_nread == -1) {
581 break; 585 break;
582 } 586 }
587 (*nlines)++;
583 588
584 nread += next_nread - 2; 589 nread += next_nread - 2;
585 if ((ssize_t) *line_size < nread + 1) { 590 if ((ssize_t) *line_size < nread + 1) {
@@ -597,6 +602,7 @@ static ssize_t getline_with_cont(char **lineptr, size_t *line_size, FILE *file)
597} 602}
598 603
599static int detect_brace(FILE *file) { 604static int detect_brace(FILE *file) {
605 int ret = 0;
600 int lines = 0; 606 int lines = 0;
601 long pos = ftell(file); 607 long pos = ftell(file);
602 char *line = NULL; 608 char *line = NULL;
@@ -605,15 +611,17 @@ static int detect_brace(FILE *file) {
605 lines++; 611 lines++;
606 strip_whitespace(line); 612 strip_whitespace(line);
607 if (*line) { 613 if (*line) {
608 if (strcmp(line, "{") != 0) { 614 if (strcmp(line, "{") == 0) {
609 fseek(file, pos, SEEK_SET); 615 ret = lines;
610 lines = 0;
611 } 616 }
612 break; 617 break;
613 } 618 }
614 } 619 }
615 free(line); 620 free(line);
616 return lines; 621 if (ret == 0) {
622 fseek(file, pos, SEEK_SET);
623 }
624 return ret;
617} 625}
618 626
619static char *expand_line(const char *block, const char *line, bool add_brace) { 627static char *expand_line(const char *block, const char *line, bool add_brace) {
@@ -660,7 +668,8 @@ bool read_config(FILE *file, struct sway_config *config,
660 ssize_t nread; 668 ssize_t nread;
661 list_t *stack = create_list(); 669 list_t *stack = create_list();
662 size_t read = 0; 670 size_t read = 0;
663 while ((nread = getline_with_cont(&line, &line_size, file)) != -1) { 671 int nlines = 0;
672 while ((nread = getline_with_cont(&line, &line_size, file, &nlines)) != -1) {
664 if (reading_main_config) { 673 if (reading_main_config) {
665 if (read + nread > config_size) { 674 if (read + nread > config_size) {
666 wlr_log(WLR_ERROR, "Config file changed during reading"); 675 wlr_log(WLR_ERROR, "Config file changed during reading");
@@ -676,7 +685,7 @@ bool read_config(FILE *file, struct sway_config *config,
676 line[nread - 1] = '\0'; 685 line[nread - 1] = '\0';
677 } 686 }
678 687
679 line_number++; 688 line_number += nlines;
680 wlr_log(WLR_DEBUG, "Read line %d: %s", line_number, line); 689 wlr_log(WLR_DEBUG, "Read line %d: %s", line_number, line);
681 690
682 strip_whitespace(line); 691 strip_whitespace(line);
diff --git a/sway/config/bar.c b/sway/config/bar.c
index 670219f1..701bf051 100644
--- a/sway/config/bar.c
+++ b/sway/config/bar.c
@@ -96,7 +96,7 @@ struct bar_config *default_bar_config(void) {
96 bar->pango_markup = false; 96 bar->pango_markup = false;
97 bar->swaybar_command = NULL; 97 bar->swaybar_command = NULL;
98 bar->font = NULL; 98 bar->font = NULL;
99 bar->height = -1; 99 bar->height = 0;
100 bar->workspace_buttons = true; 100 bar->workspace_buttons = true;
101 bar->wrap_scroll = false; 101 bar->wrap_scroll = false;
102 bar->separator_symbol = NULL; 102 bar->separator_symbol = NULL;
@@ -106,6 +106,8 @@ struct bar_config *default_bar_config(void) {
106 bar->verbose = false; 106 bar->verbose = false;
107 bar->pid = 0; 107 bar->pid = 0;
108 bar->modifier = get_modifier_mask_by_name("Mod4"); 108 bar->modifier = get_modifier_mask_by_name("Mod4");
109 bar->status_padding = 1;
110 bar->status_edge_padding = 3;
109 if (!(bar->mode = strdup("dock"))) { 111 if (!(bar->mode = strdup("dock"))) {
110 goto cleanup; 112 goto cleanup;
111 } 113 }
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c
index 04e14355..d90803f6 100644
--- a/sway/input/input-manager.c
+++ b/sway/input/input-manager.c
@@ -129,6 +129,24 @@ static void input_manager_libinput_config_keyboard(
129 } 129 }
130} 130}
131 131
132static void input_manager_libinput_reset_keyboard(
133 struct sway_input_device *input_device) {
134 struct wlr_input_device *wlr_device = input_device->wlr_device;
135 struct libinput_device *libinput_device;
136
137 if (!wlr_input_device_is_libinput(wlr_device)) {
138 return;
139 }
140
141 libinput_device = wlr_libinput_get_device_handle(wlr_device);
142
143 uint32_t send_events =
144 libinput_device_config_send_events_get_default_mode(libinput_device);
145 wlr_log(WLR_DEBUG, "libinput_reset_keyboard(%s) send_events_set_mode(%d)",
146 input_device->identifier, send_events);
147 libinput_device_config_send_events_set_mode(libinput_device, send_events);
148}
149
132static void input_manager_libinput_config_touch( 150static void input_manager_libinput_config_touch(
133 struct sway_input_device *input_device) { 151 struct sway_input_device *input_device) {
134 struct wlr_input_device *wlr_device = input_device->wlr_device; 152 struct wlr_input_device *wlr_device = input_device->wlr_device;
@@ -151,6 +169,24 @@ static void input_manager_libinput_config_touch(
151 } 169 }
152} 170}
153 171
172static void input_manager_libinput_reset_touch(
173 struct sway_input_device *input_device) {
174 struct wlr_input_device *wlr_device = input_device->wlr_device;
175 struct libinput_device *libinput_device;
176
177 if (!wlr_input_device_is_libinput(wlr_device)) {
178 return;
179 }
180
181 libinput_device = wlr_libinput_get_device_handle(wlr_device);
182
183 uint32_t send_events =
184 libinput_device_config_send_events_get_default_mode(libinput_device);
185 wlr_log(WLR_DEBUG, "libinput_reset_touch(%s) send_events_set_mode(%d)",
186 input_device->identifier, send_events);
187 libinput_device_config_send_events_set_mode(libinput_device, send_events);
188}
189
154static void input_manager_libinput_config_pointer( 190static void input_manager_libinput_config_pointer(
155 struct sway_input_device *input_device) { 191 struct sway_input_device *input_device) {
156 struct wlr_input_device *wlr_device = input_device->wlr_device; 192 struct wlr_input_device *wlr_device = input_device->wlr_device;
@@ -180,14 +216,14 @@ static void input_manager_libinput_config_pointer(
180 if (ic->drag != INT_MIN) { 216 if (ic->drag != INT_MIN) {
181 wlr_log(WLR_DEBUG, 217 wlr_log(WLR_DEBUG,
182 "libinput_config_pointer(%s) tap_set_drag_enabled(%d)", 218 "libinput_config_pointer(%s) tap_set_drag_enabled(%d)",
183 ic->identifier, ic->click_method); 219 ic->identifier, ic->drag);
184 libinput_device_config_tap_set_drag_enabled(libinput_device, 220 libinput_device_config_tap_set_drag_enabled(libinput_device,
185 ic->drag); 221 ic->drag);
186 } 222 }
187 if (ic->drag_lock != INT_MIN) { 223 if (ic->drag_lock != INT_MIN) {
188 wlr_log(WLR_DEBUG, 224 wlr_log(WLR_DEBUG,
189 "libinput_config_pointer(%s) tap_set_drag_lock_enabled(%d)", 225 "libinput_config_pointer(%s) tap_set_drag_lock_enabled(%d)",
190 ic->identifier, ic->click_method); 226 ic->identifier, ic->drag_lock);
191 libinput_device_config_tap_set_drag_lock_enabled(libinput_device, 227 libinput_device_config_tap_set_drag_lock_enabled(libinput_device,
192 ic->drag_lock); 228 ic->drag_lock);
193 } 229 }
@@ -248,12 +284,118 @@ static void input_manager_libinput_config_pointer(
248 } 284 }
249 if (ic->tap_button_map != INT_MIN) { 285 if (ic->tap_button_map != INT_MIN) {
250 wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) tap_set_button_map(%d)", 286 wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) tap_set_button_map(%d)",
251 ic->identifier, ic->tap); 287 ic->identifier, ic->tap_button_map);
252 libinput_device_config_tap_set_button_map(libinput_device, 288 libinput_device_config_tap_set_button_map(libinput_device,
253 ic->tap_button_map); 289 ic->tap_button_map);
254 } 290 }
255} 291}
256 292
293static void input_manager_libinput_reset_pointer(
294 struct sway_input_device *input_device) {
295 struct wlr_input_device *wlr_device = input_device->wlr_device;
296
297 if (!wlr_input_device_is_libinput(wlr_device)) {
298 return;
299 }
300
301 struct libinput_device *libinput_device =
302 wlr_libinput_get_device_handle(wlr_device);
303
304 enum libinput_config_accel_profile accel_profile =
305 libinput_device_config_accel_get_default_profile(libinput_device);
306 wlr_log(WLR_DEBUG, "libinput_reset_pointer(%s) accel_set_profile(%d)",
307 input_device->identifier, accel_profile);
308 libinput_device_config_accel_set_profile(libinput_device, accel_profile);
309
310 enum libinput_config_click_method click_method =
311 libinput_device_config_click_get_default_method(libinput_device);
312 wlr_log(WLR_DEBUG, "libinput_reset_pointer(%s) click_set_method(%d)",
313 input_device->identifier, click_method);
314 libinput_device_config_click_set_method(libinput_device, click_method);
315
316 enum libinput_config_drag_state drag =
317 libinput_device_config_tap_get_default_drag_enabled(libinput_device);
318 wlr_log(WLR_DEBUG, "libinput_reset_pointer(%s) tap_set_drag_enabled(%d)",
319 input_device->identifier, drag);
320 libinput_device_config_tap_set_drag_enabled(libinput_device, drag);
321
322 enum libinput_config_drag_lock_state drag_lock =
323 libinput_device_config_tap_get_default_drag_lock_enabled(
324 libinput_device);
325 wlr_log(WLR_DEBUG,
326 "libinput_reset_pointer(%s) tap_set_drag_lock_enabled(%d)",
327 input_device->identifier, drag_lock);
328 libinput_device_config_tap_set_drag_lock_enabled(libinput_device,
329 drag_lock);
330
331 enum libinput_config_dwt_state dwt =
332 libinput_device_config_dwt_get_default_enabled(libinput_device);
333 wlr_log(WLR_DEBUG, "libinput_reset_pointer(%s) dwt_set_enabled(%d)",
334 input_device->identifier, dwt);
335 libinput_device_config_dwt_set_enabled(libinput_device, dwt);
336
337 int left_handed =
338 libinput_device_config_left_handed_get_default(libinput_device);
339 wlr_log(WLR_DEBUG,
340 "libinput_reset_pointer(%s) left_handed_set_enabled(%d)",
341 input_device->identifier, left_handed);
342 libinput_device_config_left_handed_set(libinput_device, left_handed);
343
344 enum libinput_config_middle_emulation_state middle_emulation =
345 libinput_device_config_middle_emulation_get_default_enabled(
346 libinput_device);
347 wlr_log(WLR_DEBUG,
348 "libinput_reset_pointer(%s) middle_emulation_set_enabled(%d)",
349 input_device->identifier, middle_emulation);
350 libinput_device_config_middle_emulation_set_enabled(libinput_device,
351 middle_emulation);
352
353 int natural_scroll =
354 libinput_device_config_scroll_get_default_natural_scroll_enabled(
355 libinput_device);
356 wlr_log(WLR_DEBUG,
357 "libinput_reset_pointer(%s) natural_scroll_set_enabled(%d)",
358 input_device->identifier, natural_scroll);
359 libinput_device_config_scroll_set_natural_scroll_enabled(
360 libinput_device, natural_scroll);
361
362 double pointer_accel =
363 libinput_device_config_accel_get_default_speed(libinput_device);
364 wlr_log(WLR_DEBUG, "libinput_reset_pointer(%s) accel_set_speed(%f)",
365 input_device->identifier, pointer_accel);
366 libinput_device_config_accel_set_speed(libinput_device, pointer_accel);
367
368 uint32_t scroll_button =
369 libinput_device_config_scroll_get_default_button(libinput_device);
370 wlr_log(WLR_DEBUG, "libinput_reset_pointer(%s) scroll_set_button(%d)",
371 input_device->identifier, scroll_button);
372 libinput_device_config_scroll_set_button(libinput_device, scroll_button);
373
374 enum libinput_config_scroll_method scroll_method =
375 libinput_device_config_scroll_get_default_method(libinput_device);
376 wlr_log(WLR_DEBUG, "libinput_reset_pointer(%s) scroll_set_method(%d)",
377 input_device->identifier, scroll_method);
378 libinput_device_config_scroll_set_method(libinput_device, scroll_method);
379
380 uint32_t send_events =
381 libinput_device_config_send_events_get_default_mode(libinput_device);
382 wlr_log(WLR_DEBUG, "libinput_reset_pointer(%s) send_events_set_mode(%d)",
383 input_device->identifier, send_events);
384 libinput_device_config_send_events_set_mode(libinput_device, send_events);
385
386 enum libinput_config_tap_state tap =
387 libinput_device_config_tap_get_default_enabled(libinput_device);
388 wlr_log(WLR_DEBUG, "libinput_reset_pointer(%s) tap_set_enabled(%d)",
389 input_device->identifier, tap);
390 libinput_device_config_tap_set_enabled(libinput_device, tap);
391
392 enum libinput_config_tap_button_map tap_button_map =
393 libinput_device_config_tap_get_button_map(libinput_device);
394 wlr_log(WLR_DEBUG, "libinput_reset_pointer(%s) tap_set_button_map(%d)",
395 input_device->identifier, tap_button_map);
396 libinput_device_config_tap_set_button_map(libinput_device, tap_button_map);
397}
398
257static void handle_device_destroy(struct wl_listener *listener, void *data) { 399static void handle_device_destroy(struct wl_listener *listener, void *data) {
258 struct wlr_input_device *device = data; 400 struct wlr_input_device *device = data;
259 401
@@ -466,6 +608,30 @@ void input_manager_apply_input_config(struct input_config *input_config) {
466 } 608 }
467} 609}
468 610
611void input_manager_reset_input(struct sway_input_device *input_device) {
612 if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER ||
613 input_device->wlr_device->type == WLR_INPUT_DEVICE_TABLET_TOOL) {
614 input_manager_libinput_reset_pointer(input_device);
615 } else if (input_device->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD) {
616 input_manager_libinput_reset_keyboard(input_device);
617 } else if (input_device->wlr_device->type == WLR_INPUT_DEVICE_TOUCH) {
618 input_manager_libinput_reset_touch(input_device);
619 }
620
621 struct sway_seat *seat = NULL;
622 wl_list_for_each(seat, &server.input->seats, link) {
623 seat_reset_device(seat, input_device);
624 }
625}
626
627void input_manager_reset_all_inputs() {
628 struct sway_input_device *input_device = NULL;
629 wl_list_for_each(input_device, &server.input->devices, link) {
630 input_manager_reset_input(input_device);
631 }
632}
633
634
469void input_manager_apply_seat_config(struct seat_config *seat_config) { 635void input_manager_apply_seat_config(struct seat_config *seat_config) {
470 wlr_log(WLR_DEBUG, "applying seat config for seat %s", seat_config->name); 636 wlr_log(WLR_DEBUG, "applying seat config for seat %s", seat_config->name);
471 if (strcmp(seat_config->name, "*") == 0) { 637 if (strcmp(seat_config->name, "*") == 0) {
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 7bd889d7..a63999b6 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -405,6 +405,14 @@ static void seat_update_capabilities(struct sway_seat *seat) {
405 } 405 }
406} 406}
407 407
408static void seat_reset_input_config(struct sway_seat *seat,
409 struct sway_seat_device *sway_device) {
410 wlr_log(WLR_DEBUG, "Resetting output mapping for input device %s",
411 sway_device->input_device->identifier);
412 wlr_cursor_map_input_to_output(seat->cursor->cursor,
413 sway_device->input_device->wlr_device, NULL);
414}
415
408static void seat_apply_input_config(struct sway_seat *seat, 416static void seat_apply_input_config(struct sway_seat *seat,
409 struct sway_seat_device *sway_device) { 417 struct sway_seat_device *sway_device) {
410 const char *mapped_to_output = NULL; 418 const char *mapped_to_output = NULL;
@@ -522,6 +530,35 @@ void seat_configure_device(struct sway_seat *seat,
522 } 530 }
523} 531}
524 532
533void seat_reset_device(struct sway_seat *seat,
534 struct sway_input_device *input_device) {
535 struct sway_seat_device *seat_device = seat_get_device(seat, input_device);
536 if (!seat_device) {
537 return;
538 }
539
540 switch (input_device->wlr_device->type) {
541 case WLR_INPUT_DEVICE_POINTER:
542 seat_reset_input_config(seat, seat_device);
543 break;
544 case WLR_INPUT_DEVICE_KEYBOARD:
545 sway_keyboard_configure(seat_device->keyboard);
546 break;
547 case WLR_INPUT_DEVICE_TOUCH:
548 seat_reset_input_config(seat, seat_device);
549 break;
550 case WLR_INPUT_DEVICE_TABLET_TOOL:
551 seat_reset_input_config(seat, seat_device);
552 break;
553 case WLR_INPUT_DEVICE_TABLET_PAD:
554 wlr_log(WLR_DEBUG, "TODO: reset tablet pad");
555 break;
556 case WLR_INPUT_DEVICE_SWITCH:
557 wlr_log(WLR_DEBUG, "TODO: reset switch device");
558 break;
559 }
560}
561
525void seat_add_device(struct sway_seat *seat, 562void seat_add_device(struct sway_seat *seat,
526 struct sway_input_device *input_device) { 563 struct sway_input_device *input_device) {
527 if (seat_get_device(seat, input_device)) { 564 if (seat_get_device(seat, input_device)) {
diff --git a/sway/ipc-json.c b/sway/ipc-json.c
index 53e0e335..15f89f65 100644
--- a/sway/ipc-json.c
+++ b/sway/ipc-json.c
@@ -11,6 +11,7 @@
11#include "sway/output.h" 11#include "sway/output.h"
12#include "sway/input/input-manager.h" 12#include "sway/input/input-manager.h"
13#include "sway/input/seat.h" 13#include "sway/input/seat.h"
14#include <wlr/backend/libinput.h>
14#include <wlr/types/wlr_box.h> 15#include <wlr/types/wlr_box.h>
15#include <wlr/types/wlr_output.h> 16#include <wlr/types/wlr_output.h>
16#include <xkbcommon/xkbcommon.h> 17#include <xkbcommon/xkbcommon.h>
@@ -598,6 +599,26 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) {
598 } 599 }
599 } 600 }
600 601
602 if (wlr_input_device_is_libinput(device->wlr_device)) {
603 struct libinput_device *libinput_dev;
604 libinput_dev = wlr_libinput_get_device_handle(device->wlr_device);
605
606 const char *events = "unknown";
607 switch (libinput_device_config_send_events_get_mode(libinput_dev)) {
608 case LIBINPUT_CONFIG_SEND_EVENTS_ENABLED:
609 events = "enabled";
610 break;
611 case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE:
612 events = "disabled_on_external_mouse";
613 break;
614 case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED:
615 events = "disabled";
616 break;
617 }
618 json_object_object_add(object, "libinput_send_events",
619 json_object_new_string(events));
620 }
621
601 return object; 622 return object;
602} 623}
603 624
@@ -660,6 +681,10 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) {
660 } 681 }
661 json_object_object_add(json, "bar_height", 682 json_object_object_add(json, "bar_height",
662 json_object_new_int(bar->height)); 683 json_object_new_int(bar->height));
684 json_object_object_add(json, "status_padding",
685 json_object_new_int(bar->status_padding));
686 json_object_object_add(json, "status_edge_padding",
687 json_object_new_int(bar->status_edge_padding));
663 json_object_object_add(json, "wrap_scroll", 688 json_object_object_add(json, "wrap_scroll",
664 json_object_new_boolean(bar->wrap_scroll)); 689 json_object_new_boolean(bar->wrap_scroll));
665 json_object_object_add(json, "workspace_buttons", 690 json_object_object_add(json, "workspace_buttons",
diff --git a/sway/meson.build b/sway/meson.build
index ff326f04..b49d550a 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -121,6 +121,8 @@ sway_sources = files(
121 'commands/bar/position.c', 121 'commands/bar/position.c',
122 'commands/bar/separator_symbol.c', 122 'commands/bar/separator_symbol.c',
123 'commands/bar/status_command.c', 123 'commands/bar/status_command.c',
124 'commands/bar/status_edge_padding.c',
125 'commands/bar/status_padding.c',
124 'commands/bar/strip_workspace_numbers.c', 126 'commands/bar/strip_workspace_numbers.c',
125 'commands/bar/strip_workspace_name.c', 127 'commands/bar/strip_workspace_name.c',
126 'commands/bar/swaybar_command.c', 128 'commands/bar/swaybar_command.c',
diff --git a/sway/sway-bar.5.scd b/sway/sway-bar.5.scd
index 2357591d..e1a4a937 100644
--- a/sway/sway-bar.5.scd
+++ b/sway/sway-bar.5.scd
@@ -69,7 +69,7 @@ Sway allows configuring swaybar in the sway configuration file.
69 use. 69 use.
70 70
71*height* <height> 71*height* <height>
72 Sets the height of the bar. Default height will match the font size. 72 Sets the height of the bar. Default height (0) will match the font size.
73 73
74*bindsym* [--release] button<n> <command> 74*bindsym* [--release] button<n> <command>
75 Executes _command_ when mouse button _n_ has been pressed (or if _released_ 75 Executes _command_ when mouse button _n_ has been pressed (or if _released_
@@ -92,6 +92,16 @@ Sway allows configuring swaybar in the sway configuration file.
92*modifier* <Modifier>|none 92*modifier* <Modifier>|none
93 Specifies the modifier key that shows a hidden bar. Default is _Mod4_. 93 Specifies the modifier key that shows a hidden bar. Default is _Mod4_.
94 94
95*status\_padding* <padding>
96 Sets the vertical padding that is used for the status line. The default is
97 _1_. If _padding_ is _0_, blocks will be able to take up the full height of
98 the bar. This value will be multiplied by the output scale.
99
100*status\_edge\_padding* <padding>
101 Sets the padding that is used when the status line is at the right edge of
102 the bar. This value will be multiplied by the output scale. The default is
103 _3_.
104
95## TRAY 105## TRAY
96 106
97Swaybar provides a system tray where third-party applications may place icons. 107Swaybar provides a system tray where third-party applications may place icons.
diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd
index 820194a9..c54babaa 100644
--- a/sway/sway-input.5.scd
+++ b/sway/sway-input.5.scd
@@ -82,9 +82,12 @@ The following commands may only be used in the configuration file.
82*input* <identifier> dwt enabled|disabled 82*input* <identifier> dwt enabled|disabled
83 Enables or disables disable-while-typing for the specified input device. 83 Enables or disables disable-while-typing for the specified input device.
84 84
85*input* <identifier> events enabled|disabled|disabled\_on\_external\_mouse 85*input* <identifier> events enabled|disabled|disabled\_on\_external\_mouse|toggle
86 Enables or disables send\_events for specified input device. (Disabling 86 Enables or disables send\_events for specified input device. Disabling
87 send\_events disables the input device) 87 send\_events disables the input device. The _toggle_ option cannot be used
88 in the config. The order is enabled, disabled\_on\_external\_mouse,
89 disabled, (loop back to enabled). Any mode which is not supported by the
90 device will be skipped during the toggle.
88 91
89*input* <identifier> left\_handed enabled|disabled 92*input* <identifier> left\_handed enabled|disabled
90 Enables or disables left handed mode for specified input device. 93 Enables or disables left handed mode for specified input device.
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) {
59 free_workspaces(&output->workspaces); 59 free_workspaces(&output->workspaces);
60 wl_list_remove(&output->link); 60 wl_list_remove(&output->link);
61 free(output->name); 61 free(output->name);
62 free(output->identifier);
62 free(output); 63 free(output);
63} 64}
64 65
@@ -166,13 +167,15 @@ bool determine_bar_visibility(struct swaybar *bar, bool moving_layer) {
166 return visible; 167 return visible;
167} 168}
168 169
169static bool bar_uses_output(struct swaybar *bar, const char *name) { 170static bool bar_uses_output(struct swaybar_output *output) {
170 if (bar->config->all_outputs) { 171 if (output->bar->config->all_outputs) {
171 return true; 172 return true;
172 } 173 }
174 char *identifier = output->identifier;
173 struct config_output *coutput; 175 struct config_output *coutput;
174 wl_list_for_each(coutput, &bar->config->outputs, link) { 176 wl_list_for_each(coutput, &output->bar->config->outputs, link) {
175 if (strcmp(coutput->name, name) == 0) { 177 if (strcmp(coutput->name, output->name) == 0 ||
178 (identifier && strcmp(coutput->name, identifier) == 0)) {
176 return true; 179 return true;
177 } 180 }
178 } 181 }
@@ -233,7 +236,7 @@ static void xdg_output_handle_done(void *data,
233 struct swaybar *bar = output->bar; 236 struct swaybar *bar = output->bar;
234 237
235 assert(output->name != NULL); 238 assert(output->name != NULL);
236 if (!bar_uses_output(bar, output->name)) { 239 if (!bar_uses_output(output)) {
237 swaybar_output_free(output); 240 swaybar_output_free(output);
238 return; 241 return;
239 } 242 }
@@ -258,7 +261,22 @@ static void xdg_output_handle_name(void *data,
258 261
259static void xdg_output_handle_description(void *data, 262static void xdg_output_handle_description(void *data,
260 struct zxdg_output_v1 *xdg_output, const char *description) { 263 struct zxdg_output_v1 *xdg_output, const char *description) {
261 // Who cares 264 // wlroots currently sets the description to `make model serial (name)`
265 // If this changes in the future, this will need to be modified.
266 struct swaybar_output *output = data;
267 free(output->identifier);
268 output->identifier = NULL;
269 char *paren = strrchr(description, '(');
270 if (paren) {
271 size_t length = paren - description;
272 output->identifier = malloc(length);
273 if (!output->identifier) {
274 wlr_log(WLR_ERROR, "Failed to allocate output identifier");
275 return;
276 }
277 strncpy(output->identifier, description, length);
278 output->identifier[length - 1] = '\0';
279 }
262} 280}
263 281
264struct zxdg_output_v1_listener xdg_output_listener = { 282struct 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) {
37 config->workspace_buttons = true; 37 config->workspace_buttons = true;
38 config->bindings = create_list(); 38 config->bindings = create_list();
39 wl_list_init(&config->outputs); 39 wl_list_init(&config->outputs);
40 config->status_padding = 1;
41 config->status_edge_padding = 3;
40 42
41 /* height */ 43 /* height */
42 config->height = 0; 44 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(
157 json_object *font, *gaps, *bar_height, *wrap_scroll, *workspace_buttons; 157 json_object *font, *gaps, *bar_height, *wrap_scroll, *workspace_buttons;
158 json_object *strip_workspace_numbers, *strip_workspace_name; 158 json_object *strip_workspace_numbers, *strip_workspace_name;
159 json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol; 159 json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol;
160 json_object *outputs, *bindings; 160 json_object *outputs, *bindings, *status_padding, *status_edge_padding;
161 json_object_object_get_ex(bar_config, "mode", &mode); 161 json_object_object_get_ex(bar_config, "mode", &mode);
162 json_object_object_get_ex(bar_config, "hidden_state", &hidden_state); 162 json_object_object_get_ex(bar_config, "hidden_state", &hidden_state);
163 json_object_object_get_ex(bar_config, "position", &position); 163 json_object_object_get_ex(bar_config, "position", &position);
@@ -176,6 +176,9 @@ static bool ipc_parse_config(
176 json_object_object_get_ex(bar_config, "outputs", &outputs); 176 json_object_object_get_ex(bar_config, "outputs", &outputs);
177 json_object_object_get_ex(bar_config, "pango_markup", &markup); 177 json_object_object_get_ex(bar_config, "pango_markup", &markup);
178 json_object_object_get_ex(bar_config, "bindings", &bindings); 178 json_object_object_get_ex(bar_config, "bindings", &bindings);
179 json_object_object_get_ex(bar_config, "status_padding", &status_padding);
180 json_object_object_get_ex(bar_config, "status_edge_padding",
181 &status_edge_padding);
179 if (status_command) { 182 if (status_command) {
180 free(config->status_command); 183 free(config->status_command);
181 config->status_command = strdup(json_object_get_string(status_command)); 184 config->status_command = strdup(json_object_get_string(status_command));
@@ -209,6 +212,12 @@ static bool ipc_parse_config(
209 if (bar_height) { 212 if (bar_height) {
210 config->height = json_object_get_int(bar_height); 213 config->height = json_object_get_int(bar_height);
211 } 214 }
215 if (status_padding) {
216 config->status_padding = json_object_get_int(status_padding);
217 }
218 if (status_edge_padding) {
219 config->status_edge_padding = json_object_get_int(status_edge_padding);
220 }
212 if (gaps) { 221 if (gaps) {
213 json_object *top = json_object_object_get(gaps, "top"); 222 json_object *top = json_object_object_get(gaps, "top");
214 if (top) { 223 if (top) {
diff --git a/swaybar/render.c b/swaybar/render.c
index 7cbcea07..12dd3b07 100644
--- a/swaybar/render.c
+++ b/swaybar/render.c
@@ -35,7 +35,8 @@ static uint32_t render_status_line_error(cairo_t *cairo,
35 cairo_set_source_u32(cairo, 0xFF0000FF); 35 cairo_set_source_u32(cairo, 0xFF0000FF);
36 36
37 int margin = 3 * output->scale; 37 int margin = 3 * output->scale;
38 int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; 38 double ws_vertical_padding =
39 output->bar->config->status_padding * output->scale;
39 40
40 char *font = output->bar->config->font; 41 char *font = output->bar->config->font;
41 int text_width, text_height; 42 int text_width, text_height;
@@ -44,7 +45,8 @@ static uint32_t render_status_line_error(cairo_t *cairo,
44 45
45 uint32_t ideal_height = text_height + ws_vertical_padding * 2; 46 uint32_t ideal_height = text_height + ws_vertical_padding * 2;
46 uint32_t ideal_surface_height = ideal_height / output->scale; 47 uint32_t ideal_surface_height = ideal_height / output->scale;
47 if (output->height < ideal_surface_height) { 48 if (!output->bar->config->height &&
49 output->height < ideal_surface_height) {
48 return ideal_surface_height; 50 return ideal_surface_height;
49 } 51 }
50 *x -= text_width + margin; 52 *x -= text_width + margin;
@@ -71,12 +73,13 @@ static uint32_t render_status_line_text(cairo_t *cairo,
71 get_text_size(cairo, config->font, &text_width, &text_height, NULL, 73 get_text_size(cairo, config->font, &text_width, &text_height, NULL,
72 output->scale, config->pango_markup, "%s", text); 74 output->scale, config->pango_markup, "%s", text);
73 75
74 int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; 76 double ws_vertical_padding = config->status_padding * output->scale;
75 int margin = 3 * output->scale; 77 int margin = 3 * output->scale;
76 78
77 uint32_t ideal_height = text_height + ws_vertical_padding * 2; 79 uint32_t ideal_height = text_height + ws_vertical_padding * 2;
78 uint32_t ideal_surface_height = ideal_height / output->scale; 80 uint32_t ideal_surface_height = ideal_height / output->scale;
79 if (output->height < ideal_surface_height) { 81 if (!output->bar->config->height &&
82 output->height < ideal_surface_height) {
80 return ideal_surface_height; 83 return ideal_surface_height;
81 } 84 }
82 85
@@ -153,7 +156,7 @@ static uint32_t render_status_block(cairo_t *cairo,
153 output->scale, block->markup, "%s", block->full_text); 156 output->scale, block->markup, "%s", block->full_text);
154 157
155 int margin = 3 * output->scale; 158 int margin = 3 * output->scale;
156 double ws_vertical_padding = WS_VERTICAL_PADDING * 2 * output->scale; 159 double ws_vertical_padding = config->status_padding * output->scale;
157 160
158 int width = text_width; 161 int width = text_width;
159 if (width < block->min_width) { 162 if (width < block->min_width) {
@@ -163,7 +166,8 @@ static uint32_t render_status_block(cairo_t *cairo,
163 double block_width = width; 166 double block_width = width;
164 uint32_t ideal_height = text_height + ws_vertical_padding * 2; 167 uint32_t ideal_height = text_height + ws_vertical_padding * 2;
165 uint32_t ideal_surface_height = ideal_height / output->scale; 168 uint32_t ideal_surface_height = ideal_height / output->scale;
166 if (output->height < ideal_surface_height) { 169 if (!output->bar->config->height &&
170 output->height < ideal_surface_height) {
167 return ideal_surface_height; 171 return ideal_surface_height;
168 } 172 }
169 173
@@ -185,7 +189,8 @@ static uint32_t render_status_block(cairo_t *cairo,
185 output->scale, false, "%s", config->sep_symbol); 189 output->scale, false, "%s", config->sep_symbol);
186 uint32_t _ideal_height = sep_height + ws_vertical_padding * 2; 190 uint32_t _ideal_height = sep_height + ws_vertical_padding * 2;
187 uint32_t _ideal_surface_height = _ideal_height / output->scale; 191 uint32_t _ideal_surface_height = _ideal_height / output->scale;
188 if (output->height < _ideal_surface_height) { 192 if (!output->bar->config->height &&
193 output->height < _ideal_surface_height) {
189 return _ideal_surface_height; 194 return _ideal_surface_height;
190 } 195 }
191 if (sep_width > sep_block_width) { 196 if (sep_width > sep_block_width) {
@@ -193,8 +198,8 @@ static uint32_t render_status_block(cairo_t *cairo,
193 } 198 }
194 } 199 }
195 *x -= sep_block_width; 200 *x -= sep_block_width;
196 } else { 201 } else if (config->status_edge_padding) {
197 *x -= margin; 202 *x -= config->status_edge_padding * output->scale;
198 } 203 }
199 204
200 uint32_t height = output->height * output->scale; 205 uint32_t height = output->height * output->scale;
@@ -212,8 +217,8 @@ static uint32_t render_status_block(cairo_t *cairo,
212 } 217 }
213 218
214 double x_pos = *x; 219 double x_pos = *x;
215 double y_pos = WS_VERTICAL_PADDING * output->scale; 220 double y_pos = ws_vertical_padding;
216 double render_height = height - ws_vertical_padding + output->scale; 221 double render_height = height - ws_vertical_padding * 2;
217 222
218 uint32_t bg_color = block->urgent 223 uint32_t bg_color = block->urgent
219 ? config->colors.urgent_workspace.background : block->background; 224 ? config->colors.urgent_workspace.background : block->background;
@@ -286,7 +291,7 @@ static uint32_t render_status_block(cairo_t *cairo,
286static uint32_t render_status_line_i3bar(cairo_t *cairo, 291static uint32_t render_status_line_i3bar(cairo_t *cairo,
287 struct swaybar_output *output, double *x) { 292 struct swaybar_output *output, double *x) {
288 uint32_t max_height = 0; 293 uint32_t max_height = 0;
289 bool edge = true; 294 bool edge = *x == output->width * output->scale;
290 struct i3bar_block *block; 295 struct i3bar_block *block;
291 wl_list_for_each(block, &output->bar->status->blocks, link) { 296 wl_list_for_each(block, &output->bar->status->blocks, link) {
292 uint32_t h = render_status_block(cairo, output, block, x, edge); 297 uint32_t h = render_status_block(cairo, output, block, x, edge);
@@ -332,7 +337,8 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo,
332 uint32_t ideal_height = text_height + ws_vertical_padding * 2 337 uint32_t ideal_height = text_height + ws_vertical_padding * 2
333 + border_width * 2; 338 + border_width * 2;
334 uint32_t ideal_surface_height = ideal_height / output->scale; 339 uint32_t ideal_surface_height = ideal_height / output->scale;
335 if (output->height < ideal_surface_height) { 340 if (!output->bar->config->height &&
341 output->height < ideal_surface_height) {
336 return ideal_surface_height; 342 return ideal_surface_height;
337 } 343 }
338 uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; 344 uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2;
@@ -398,7 +404,8 @@ static uint32_t render_workspace_button(cairo_t *cairo,
398 uint32_t ideal_height = ws_vertical_padding * 2 + text_height 404 uint32_t ideal_height = ws_vertical_padding * 2 + text_height
399 + border_width * 2; 405 + border_width * 2;
400 uint32_t ideal_surface_height = ideal_height / output->scale; 406 uint32_t ideal_surface_height = ideal_height / output->scale;
401 if (output->height < ideal_surface_height) { 407 if (!output->bar->config->height &&
408 output->height < ideal_surface_height) {
402 return ideal_surface_height; 409 return ideal_surface_height;
403 } 410 }
404 411
@@ -525,7 +532,7 @@ void render_frame(struct swaybar_output *output) {
525 cairo_restore(cairo); 532 cairo_restore(cairo);
526 uint32_t height = render_to_cairo(cairo, output); 533 uint32_t height = render_to_cairo(cairo, output);
527 int config_height = output->bar->config->height; 534 int config_height = output->bar->config->height;
528 if (config_height >= 0 && height < (uint32_t)config_height) { 535 if (config_height > 0) {
529 height = config_height; 536 height = config_height;
530 } 537 }
531 if (height != output->height || output->width == 0) { 538 if (height != output->height || output->width == 0) {
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) {
101} 101}
102 102
103static int cmp_output(const void *item, const void *cmp_to) { 103static int cmp_output(const void *item, const void *cmp_to) {
104 return strcmp(item, cmp_to); 104 const struct swaybar_output *output = cmp_to;
105 if (output->identifier && strcmp(item, output->identifier) == 0) {
106 return 0;
107 }
108 return strcmp(item, output->name);
105} 109}
106 110
107uint32_t render_tray(cairo_t *cairo, struct swaybar_output *output, double *x) { 111uint32_t render_tray(cairo_t *cairo, struct swaybar_output *output, double *x) {
108 struct swaybar_config *config = output->bar->config; 112 struct swaybar_config *config = output->bar->config;
109 if (config->tray_outputs) { 113 if (config->tray_outputs) {
110 if (list_seq_find(config->tray_outputs, cmp_output, output->name) == -1) { 114 if (list_seq_find(config->tray_outputs, cmp_output, output) == -1) {
111 return 0; 115 return 0;
112 } 116 }
113 } // else display on all 117 } // 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 @@
1#define _POSIX_C_SOURCE 200809L
2#include <assert.h>
3#include <errno.h>
4#include <fcntl.h>
5#include <getopt.h>
6#include <pthread.h>
7#include <signal.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <sys/wait.h>
12#include <unistd.h>
13#include <wayland-client-protocol.h>
14#include <wayland-client.h>
15#include <wayland-server.h>
16#include <wayland-util.h>
17#include <wlr/config.h>
18#include <wlr/util/log.h>
19#include "config.h"
20#include "idle-client-protocol.h"
21#include "list.h"
22#if HAVE_SYSTEMD
23#include <systemd/sd-bus.h>
24#include <systemd/sd-login.h>
25#elif HAVE_ELOGIND
26#include <elogind/sd-bus.h>
27#include <elogind/sd-login.h>
28#endif
29
30static struct org_kde_kwin_idle *idle_manager = NULL;
31static struct wl_seat *seat = NULL;
32
33struct swayidle_state {
34 struct wl_display *display;
35 struct wl_event_loop *event_loop;
36 list_t *timeout_cmds; // struct swayidle_timeout_cmd *
37 char *lock_cmd;
38} state;
39
40struct swayidle_timeout_cmd {
41 int timeout, registered_timeout;
42 struct org_kde_kwin_idle_timeout *idle_timer;
43 char *idle_cmd;
44 char *resume_cmd;
45};
46
47void sway_terminate(int exit_code) {
48 wl_display_disconnect(state.display);
49 wl_event_loop_destroy(state.event_loop);
50 exit(exit_code);
51}
52
53static void cmd_exec(char *param) {
54 wlr_log(WLR_DEBUG, "Cmd exec %s", param);
55 pid_t pid = fork();
56 if (pid == 0) {
57 pid = fork();
58 if (pid == 0) {
59 char *const cmd[] = { "sh", "-c", param, NULL, };
60 execvp(cmd[0], cmd);
61 wlr_log_errno(WLR_ERROR, "execve failed!");
62 exit(1);
63 } else if (pid < 0) {
64 wlr_log_errno(WLR_ERROR, "fork failed");
65 exit(1);
66 }
67 exit(0);
68 } else if (pid < 0) {
69 wlr_log_errno(WLR_ERROR, "fork failed");
70 } else {
71 wlr_log(WLR_DEBUG, "Spawned process %s", param);
72 waitpid(pid, NULL, 0);
73 }
74}
75
76#if HAVE_SYSTEMD || HAVE_ELOGIND
77static int lock_fd = -1;
78static int ongoing_fd = -1;
79static struct sd_bus *bus = NULL;
80
81static int release_lock(void *data) {
82 wlr_log(WLR_INFO, "Releasing sleep lock %d", ongoing_fd);
83 if (ongoing_fd >= 0) {
84 close(ongoing_fd);
85 }
86 ongoing_fd = -1;
87 return 0;
88}
89
90static void acquire_sleep_lock(void) {
91 sd_bus_message *msg = NULL;
92 sd_bus_error error = SD_BUS_ERROR_NULL;
93 int ret = sd_bus_call_method(bus, "org.freedesktop.login1",
94 "/org/freedesktop/login1",
95 "org.freedesktop.login1.Manager", "Inhibit",
96 &error, &msg, "ssss", "sleep", "swayidle",
97 "Setup Up Lock Screen", "delay");
98 if (ret < 0) {
99 wlr_log(WLR_ERROR, "Failed to send Inhibit signal: %s", error.message);
100 sd_bus_error_free(&error);
101 return;
102 }
103
104 ret = sd_bus_message_read(msg, "h", &lock_fd);
105 if (ret < 0) {
106 wlr_log(WLR_ERROR, "Failed to parse D-Bus response for Inhibit: %s",
107 strerror(-ret));
108 sd_bus_error_free(&error);
109 sd_bus_message_unref(msg);
110 return;
111 } else {
112 wlr_log(WLR_INFO, "Got sleep lock: %d", lock_fd);
113 }
114
115 // sd_bus_message_unref closes the file descriptor so we need
116 // to copy it beforehand
117 lock_fd = fcntl(lock_fd, F_DUPFD_CLOEXEC, 3);
118 if (lock_fd < 0) {
119 wlr_log(WLR_ERROR, "Failed to copy sleep lock fd: %s",
120 strerror(errno));
121 }
122
123 sd_bus_error_free(&error);
124 sd_bus_message_unref(msg);
125}
126
127static int prepare_for_sleep(sd_bus_message *msg, void *userdata,
128 sd_bus_error *ret_error) {
129 /* "b" apparently reads into an int, not a bool */
130 int going_down = 1;
131 int ret = sd_bus_message_read(msg, "b", &going_down);
132 if (ret < 0) {
133 wlr_log(WLR_ERROR, "Failed to parse D-Bus response for Inhibit: %s",
134 strerror(-ret));
135 }
136 wlr_log(WLR_DEBUG, "PrepareForSleep signal received %d", going_down);
137 if (!going_down) {
138 acquire_sleep_lock();
139 return 0;
140 }
141
142 ongoing_fd = lock_fd;
143
144 if (state.lock_cmd) {
145 cmd_exec(state.lock_cmd);
146 }
147
148 if (ongoing_fd >= 0) {
149 struct wl_event_source *source =
150 wl_event_loop_add_timer(state.event_loop, release_lock, NULL);
151 wl_event_source_timer_update(source, 1000);
152 }
153
154 wlr_log(WLR_DEBUG, "Prepare for sleep done");
155 return 0;
156}
157
158static int dbus_event(int fd, uint32_t mask, void *data) {
159 sd_bus *bus = data;
160
161 if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) {
162 sway_terminate(0);
163 }
164
165 int count = 0;
166 if (mask & WL_EVENT_READABLE) {
167 count = sd_bus_process(bus, NULL);
168 }
169 if (mask & WL_EVENT_WRITABLE) {
170 sd_bus_flush(bus);
171 }
172 if (mask == 0) {
173 sd_bus_flush(bus);
174 }
175
176 if (count < 0) {
177 wlr_log_errno(WLR_ERROR, "sd_bus_process failed, exiting");
178 sway_terminate(0);
179 }
180
181 return count;
182}
183
184static void setup_sleep_listener(void) {
185 int ret = sd_bus_default_system(&bus);
186 if (ret < 0) {
187 wlr_log(WLR_ERROR, "Failed to open D-Bus connection: %s",
188 strerror(-ret));
189 return;
190 }
191
192 char str[256];
193 const char *fmt = "type='signal',"
194 "sender='org.freedesktop.login1',"
195 "interface='org.freedesktop.login1.%s',"
196 "member='%s'," "path='%s'";
197
198 snprintf(str, sizeof(str), fmt, "Manager", "PrepareForSleep",
199 "/org/freedesktop/login1");
200 ret = sd_bus_add_match(bus, NULL, str, prepare_for_sleep, NULL);
201 if (ret < 0) {
202 wlr_log(WLR_ERROR, "Failed to add D-Bus match: %s", strerror(-ret));
203 return;
204 }
205 acquire_sleep_lock();
206
207 struct wl_event_source *source = wl_event_loop_add_fd(state.event_loop,
208 sd_bus_get_fd(bus), WL_EVENT_READABLE, dbus_event, bus);
209 wl_event_source_check(source);
210}
211#endif
212
213static void handle_global(void *data, struct wl_registry *registry,
214 uint32_t name, const char *interface, uint32_t version) {
215 if (strcmp(interface, org_kde_kwin_idle_interface.name) == 0) {
216 idle_manager =
217 wl_registry_bind(registry, name, &org_kde_kwin_idle_interface, 1);
218 } else if (strcmp(interface, wl_seat_interface.name) == 0) {
219 seat = wl_registry_bind(registry, name, &wl_seat_interface, 1);
220 }
221}
222
223static void handle_global_remove(void *data, struct wl_registry *registry,
224 uint32_t name) {
225 // Who cares
226}
227
228static const struct wl_registry_listener registry_listener = {
229 .global = handle_global,
230 .global_remove = handle_global_remove,
231};
232
233static const struct org_kde_kwin_idle_timeout_listener idle_timer_listener;
234
235static void register_timeout(struct swayidle_timeout_cmd *cmd,
236 int timeout) {
237 if (cmd->idle_timer != NULL) {
238 org_kde_kwin_idle_timeout_destroy(cmd->idle_timer);
239 cmd->idle_timer = NULL;
240 }
241 if (timeout < 0) {
242 wlr_log(WLR_DEBUG, "Not registering idle timeout");
243 return;
244 }
245 wlr_log(WLR_DEBUG, "Register with timeout: %d", timeout);
246 cmd->idle_timer =
247 org_kde_kwin_idle_get_idle_timeout(idle_manager, seat, timeout);
248 org_kde_kwin_idle_timeout_add_listener(cmd->idle_timer,
249 &idle_timer_listener, cmd);
250 cmd->registered_timeout = timeout;
251}
252
253static void handle_idle(void *data, struct org_kde_kwin_idle_timeout *timer) {
254 struct swayidle_timeout_cmd *cmd = data;
255 wlr_log(WLR_DEBUG, "idle state");
256 if (cmd->idle_cmd) {
257 cmd_exec(cmd->idle_cmd);
258 }
259}
260
261static void handle_resume(void *data, struct org_kde_kwin_idle_timeout *timer) {
262 struct swayidle_timeout_cmd *cmd = data;
263 wlr_log(WLR_DEBUG, "active state");
264 if (cmd->registered_timeout != cmd->timeout) {
265 register_timeout(cmd, cmd->timeout);
266 }
267 if (cmd->resume_cmd) {
268 cmd_exec(cmd->resume_cmd);
269 }
270}
271
272static const struct org_kde_kwin_idle_timeout_listener idle_timer_listener = {
273 .idle = handle_idle,
274 .resumed = handle_resume,
275};
276
277static char *parse_command(int argc, char **argv) {
278 if (argc < 1) {
279 wlr_log(WLR_ERROR, "Missing command");
280 return NULL;
281 }
282
283 wlr_log(WLR_DEBUG, "Command: %s", argv[0]);
284 return strdup(argv[0]);
285}
286
287static int parse_timeout(int argc, char **argv) {
288 if (argc < 3) {
289 wlr_log(WLR_ERROR, "Too few parameters to timeout command. "
290 "Usage: timeout <seconds> <command>");
291 exit(-1);
292 }
293 errno = 0;
294 char *endptr;
295 int seconds = strtoul(argv[1], &endptr, 10);
296 if (errno != 0 || *endptr != '\0') {
297 wlr_log(WLR_ERROR, "Invalid timeout parameter '%s', it should be a "
298 "numeric value representing seconds", optarg);
299 exit(-1);
300 }
301
302 struct swayidle_timeout_cmd *cmd =
303 calloc(1, sizeof(struct swayidle_timeout_cmd));
304
305 if (seconds > 0) {
306 cmd->timeout = seconds * 1000;
307 } else {
308 cmd->timeout = -1;
309 }
310
311 wlr_log(WLR_DEBUG, "Register idle timeout at %d ms", cmd->timeout);
312 wlr_log(WLR_DEBUG, "Setup idle");
313 cmd->idle_cmd = parse_command(argc - 2, &argv[2]);
314
315 int result = 3;
316 if (argc >= 5 && !strcmp("resume", argv[3])) {
317 wlr_log(WLR_DEBUG, "Setup resume");
318 cmd->resume_cmd = parse_command(argc - 4, &argv[4]);
319 result = 5;
320 }
321 list_add(state.timeout_cmds, cmd);
322 return result;
323}
324
325static int parse_sleep(int argc, char **argv) {
326 if (argc < 2) {
327 wlr_log(WLR_ERROR, "Too few parameters to before-sleep command. "
328 "Usage: before-sleep <command>");
329 exit(-1);
330 }
331
332 state.lock_cmd = parse_command(argc - 1, &argv[1]);
333 if (state.lock_cmd) {
334 wlr_log(WLR_DEBUG, "Setup sleep lock: %s", state.lock_cmd);
335 }
336
337 return 2;
338}
339
340static int parse_args(int argc, char *argv[]) {
341 bool debug = false;
342
343 int c;
344 while ((c = getopt(argc, argv, "hd")) != -1) {
345 switch (c) {
346 case 'd':
347 debug = true;
348 break;
349 case 'h':
350 case '?':
351 printf("Usage: %s [OPTIONS]\n", argv[0]);
352 printf(" -d\tdebug\n");
353 printf(" -h\tthis help menu\n");
354 return 1;
355 default:
356 return 1;
357 }
358 }
359
360 wlr_log_init(debug ? WLR_DEBUG : WLR_INFO, NULL);
361
362 state.timeout_cmds = create_list();
363
364 int i = optind;
365 while (i < argc) {
366 if (!strcmp("timeout", argv[i])) {
367 wlr_log(WLR_DEBUG, "Got timeout");
368 i += parse_timeout(argc - i, &argv[i]);
369 } else if (!strcmp("before-sleep", argv[i])) {
370 wlr_log(WLR_DEBUG, "Got before-sleep");
371 i += parse_sleep(argc - i, &argv[i]);
372 } else {
373 wlr_log(WLR_ERROR, "Unsupported command '%s'", argv[i]);
374 return 1;
375 }
376 }
377
378 return 0;
379}
380
381static int handle_signal(int sig, void *data) {
382 switch (sig) {
383 case SIGINT:
384 case SIGTERM:
385 sway_terminate(0);
386 return 0;
387 case SIGUSR1:
388 wlr_log(WLR_DEBUG, "Got SIGUSR1");
389 for (int i = 0; i < state.timeout_cmds->length; ++i) {
390 register_timeout(state.timeout_cmds->items[i], 0);
391 }
392 return 1;
393 }
394 assert(false); // not reached
395}
396
397static int display_event(int fd, uint32_t mask, void *data) {
398 if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) {
399 sway_terminate(0);
400 }
401
402 int count = 0;
403 if (mask & WL_EVENT_READABLE) {
404 count = wl_display_dispatch(state.display);
405 }
406 if (mask & WL_EVENT_WRITABLE) {
407 wl_display_flush(state.display);
408 }
409 if (mask == 0) {
410 count = wl_display_dispatch_pending(state.display);
411 wl_display_flush(state.display);
412 }
413
414 if (count < 0) {
415 wlr_log_errno(WLR_ERROR, "wl_display_dispatch failed, exiting");
416 sway_terminate(0);
417 }
418
419 return count;
420}
421
422int main(int argc, char *argv[]) {
423 if (parse_args(argc, argv) != 0) {
424 return -1;
425 }
426
427 state.event_loop = wl_event_loop_create();
428
429 wl_event_loop_add_signal(state.event_loop, SIGINT, handle_signal, NULL);
430 wl_event_loop_add_signal(state.event_loop, SIGTERM, handle_signal, NULL);
431 wl_event_loop_add_signal(state.event_loop, SIGUSR1, handle_signal, NULL);
432
433 state.display = wl_display_connect(NULL);
434 if (state.display == NULL) {
435 wlr_log(WLR_ERROR, "Unable to connect to the compositor. "
436 "If your compositor is running, check or set the "
437 "WAYLAND_DISPLAY environment variable.");
438 return -3;
439 }
440
441 struct wl_registry *registry = wl_display_get_registry(state.display);
442 wl_registry_add_listener(registry, &registry_listener, NULL);
443 wl_display_roundtrip(state.display);
444
445 if (idle_manager == NULL) {
446 wlr_log(WLR_ERROR, "Display doesn't support idle protocol");
447 return -4;
448 }
449 if (seat == NULL) {
450 wlr_log(WLR_ERROR, "Seat error");
451 return -5;
452 }
453
454 bool should_run = state.timeout_cmds->length > 0;
455#if HAVE_SYSTEMD || HAVE_ELOGIND
456 if (state.lock_cmd) {
457 should_run = true;
458 setup_sleep_listener();
459 }
460#endif
461 if (!should_run) {
462 wlr_log(WLR_INFO, "No command specified! Nothing to do, will exit");
463 sway_terminate(0);
464 }
465
466 for (int i = 0; i < state.timeout_cmds->length; ++i) {
467 struct swayidle_timeout_cmd *cmd = state.timeout_cmds->items[i];
468 register_timeout(cmd, cmd->timeout);
469 }
470
471 wl_display_roundtrip(state.display);
472
473 struct wl_event_source *source = wl_event_loop_add_fd(state.event_loop,
474 wl_display_get_fd(state.display), WL_EVENT_READABLE,
475 display_event, NULL);
476 wl_event_source_check(source);
477
478 while (wl_event_loop_dispatch(state.event_loop, -1) != 1) {
479 // This space intentionally left blank
480 }
481
482 sway_terminate(0);
483}
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 @@
1threads = dependency('threads')
2
3swayidle_deps = [
4 client_protos,
5 pixman,
6 wayland_client,
7 wayland_server,
8 wlroots,
9]
10
11if systemd.found()
12 swayidle_deps += systemd
13endif
14if elogind.found()
15 swayidle_deps += elogind
16endif
17
18executable(
19 'swayidle', [
20 'main.c',
21 ],
22 include_directories: [sway_inc],
23 dependencies: swayidle_deps,
24 link_with: [lib_sway_common, lib_sway_client],
25 install_rpath : rpathdir,
26 install: true
27)
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 @@
1swayidle (1)
2
3# NAME
4
5swayidle - Idle manager for Wayland
6
7# SYNOPSIS
8
9*swayidle* [options] [events...]
10
11# OPTIONS
12
13*-h*
14 Show help message and quit.
15
16*-d*
17 Enable debug output.
18
19# DESCRIPTION
20
21swayidle listens for idle activity on your Wayland compositor and executes tasks
22on various idle-related events. You can specify any number of events at the
23command line.
24
25Sending SIGUSR1 to swayidle will immediately enter idle state.
26
27# EVENTS
28
29*timeout* <timeout> <timeout command> [resume <resume command>]
30 Execute _timeout command_ if there is no activity for <timeout> seconds.
31
32 If you specify "resume <resume command>", _resume command_ will be run when
33 there is activity again.
34
35*before-sleep* <command>
36 If built with systemd support, executes _command_ before systemd puts the
37 computer to sleep.
38
39All commands are executed in a shell.
40
41# EXAMPLE
42
43```
44swayidle \
45 timeout 300 'swaylock -c 000000' \
46 timeout 600 'swaymsg "output * dpms off"' \
47 resume 'swaymsg "output * dpms on"' \
48 before-sleep 'swaylock -c 000000'
49```
50
51This will lock your screen after 300 seconds of inactivity, then turn off your
52displays after another 300 seconds, and turn your screens back on when resumed.
53It will also lock your screen before your computer goes to sleep.
54
55# AUTHORS
56
57Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open
58source contributors. For more information about sway development, see
59https://github.com/swaywm/sway.
60
61# SEE ALSO
62
63*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) {
396 colors->background = 0xFFFFFFFF; 396 colors->background = 0xFFFFFFFF;
397 colors->bs_highlight = 0xDB3300FF; 397 colors->bs_highlight = 0xDB3300FF;
398 colors->key_highlight = 0x33DB00FF; 398 colors->key_highlight = 0x33DB00FF;
399 colors->caps_lock_bs_highlight = 0xDB3300FF;
400 colors->caps_lock_key_highlight = 0x33DB00FF;
399 colors->separator = 0x000000FF; 401 colors->separator = 0x000000FF;
400 colors->inside = (struct swaylock_colorset){ 402 colors->inside = (struct swaylock_colorset){
401 .input = 0x000000C0, 403 .input = 0x000000C0,
402 .cleared = 0xE5A445C0, 404 .cleared = 0xE5A445C0,
405 .caps_lock = 0x000000C0,
403 .verifying = 0x0072FFC0, 406 .verifying = 0x0072FFC0,
404 .wrong = 0xFA0000C0, 407 .wrong = 0xFA0000C0,
405 }; 408 };
406 colors->line = (struct swaylock_colorset){ 409 colors->line = (struct swaylock_colorset){
407 .input = 0x000000FF, 410 .input = 0x000000FF,
408 .cleared = 0x000000FF, 411 .cleared = 0x000000FF,
412 .caps_lock = 0x000000FF,
409 .verifying = 0x000000FF, 413 .verifying = 0x000000FF,
410 .wrong = 0x000000FF, 414 .wrong = 0x000000FF,
411 }; 415 };
412 colors->ring = (struct swaylock_colorset){ 416 colors->ring = (struct swaylock_colorset){
413 .input = 0x337D00FF, 417 .input = 0x337D00FF,
414 .cleared = 0xE5A445FF, 418 .cleared = 0xE5A445FF,
419 .caps_lock = 0xE5A445FF,
415 .verifying = 0x3300FFFF, 420 .verifying = 0x3300FFFF,
416 .wrong = 0x7D3300FF, 421 .wrong = 0x7D3300FF,
417 }; 422 };
418 colors->text = (struct swaylock_colorset){ 423 colors->text = (struct swaylock_colorset){
419 .input = 0xE5A445FF, 424 .input = 0xE5A445FF,
420 .cleared = 0x000000FF, 425 .cleared = 0x000000FF,
426 .caps_lock = 0xE5A445FF,
421 .verifying = 0x000000FF, 427 .verifying = 0x000000FF,
422 .wrong = 0x000000FF, 428 .wrong = 0x000000FF,
423 }; 429 };
@@ -433,25 +439,31 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state,
433 enum line_mode *line_mode, char **config_path) { 439 enum line_mode *line_mode, char **config_path) {
434 enum long_option_codes { 440 enum long_option_codes {
435 LO_BS_HL_COLOR = 256, 441 LO_BS_HL_COLOR = 256,
442 LO_CAPS_LOCK_BS_HL_COLOR,
443 LO_CAPS_LOCK_KEY_HL_COLOR,
436 LO_FONT, 444 LO_FONT,
437 LO_IND_RADIUS, 445 LO_IND_RADIUS,
438 LO_IND_THICKNESS, 446 LO_IND_THICKNESS,
439 LO_INSIDE_COLOR, 447 LO_INSIDE_COLOR,
440 LO_INSIDE_CLEAR_COLOR, 448 LO_INSIDE_CLEAR_COLOR,
449 LO_INSIDE_CAPS_LOCK_COLOR,
441 LO_INSIDE_VER_COLOR, 450 LO_INSIDE_VER_COLOR,
442 LO_INSIDE_WRONG_COLOR, 451 LO_INSIDE_WRONG_COLOR,
443 LO_KEY_HL_COLOR, 452 LO_KEY_HL_COLOR,
444 LO_LINE_COLOR, 453 LO_LINE_COLOR,
445 LO_LINE_CLEAR_COLOR, 454 LO_LINE_CLEAR_COLOR,
455 LO_LINE_CAPS_LOCK_COLOR,
446 LO_LINE_VER_COLOR, 456 LO_LINE_VER_COLOR,
447 LO_LINE_WRONG_COLOR, 457 LO_LINE_WRONG_COLOR,
448 LO_RING_COLOR, 458 LO_RING_COLOR,
449 LO_RING_CLEAR_COLOR, 459 LO_RING_CLEAR_COLOR,
460 LO_RING_CAPS_LOCK_COLOR,
450 LO_RING_VER_COLOR, 461 LO_RING_VER_COLOR,
451 LO_RING_WRONG_COLOR, 462 LO_RING_WRONG_COLOR,
452 LO_SEP_COLOR, 463 LO_SEP_COLOR,
453 LO_TEXT_COLOR, 464 LO_TEXT_COLOR,
454 LO_TEXT_CLEAR_COLOR, 465 LO_TEXT_CLEAR_COLOR,
466 LO_TEXT_CAPS_LOCK_COLOR,
455 LO_TEXT_VER_COLOR, 467 LO_TEXT_VER_COLOR,
456 LO_TEXT_WRONG_COLOR, 468 LO_TEXT_WRONG_COLOR,
457 }; 469 };
@@ -463,6 +475,8 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state,
463 {"daemonize", no_argument, NULL, 'f'}, 475 {"daemonize", no_argument, NULL, 'f'},
464 {"help", no_argument, NULL, 'h'}, 476 {"help", no_argument, NULL, 'h'},
465 {"image", required_argument, NULL, 'i'}, 477 {"image", required_argument, NULL, 'i'},
478 {"disable-caps-lock-text", no_argument, NULL, 'L'},
479 {"indicator-caps-lock", no_argument, NULL, 'l'},
466 {"line-uses-inside", no_argument, NULL, 'n'}, 480 {"line-uses-inside", no_argument, NULL, 'n'},
467 {"socket", required_argument, NULL, 'p'}, 481 {"socket", required_argument, NULL, 'p'},
468 {"line-uses-ring", no_argument, NULL, 'r'}, 482 {"line-uses-ring", no_argument, NULL, 'r'},
@@ -471,25 +485,31 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state,
471 {"no-unlock-indicator", no_argument, NULL, 'u'}, 485 {"no-unlock-indicator", no_argument, NULL, 'u'},
472 {"version", no_argument, NULL, 'v'}, 486 {"version", no_argument, NULL, 'v'},
473 {"bs-hl-color", required_argument, NULL, LO_BS_HL_COLOR}, 487 {"bs-hl-color", required_argument, NULL, LO_BS_HL_COLOR},
488 {"caps-lock-bs-hl-color", required_argument, NULL, LO_CAPS_LOCK_BS_HL_COLOR},
489 {"caps-lock-key-hl-color", required_argument, NULL, LO_CAPS_LOCK_KEY_HL_COLOR},
474 {"font", required_argument, NULL, LO_FONT}, 490 {"font", required_argument, NULL, LO_FONT},
475 {"indicator-radius", required_argument, NULL, LO_IND_RADIUS}, 491 {"indicator-radius", required_argument, NULL, LO_IND_RADIUS},
476 {"indicator-thickness", required_argument, NULL, LO_IND_THICKNESS}, 492 {"indicator-thickness", required_argument, NULL, LO_IND_THICKNESS},
477 {"inside-color", required_argument, NULL, LO_INSIDE_COLOR}, 493 {"inside-color", required_argument, NULL, LO_INSIDE_COLOR},
478 {"inside-clear-color", required_argument, NULL, LO_INSIDE_CLEAR_COLOR}, 494 {"inside-clear-color", required_argument, NULL, LO_INSIDE_CLEAR_COLOR},
495 {"inside-caps-lock-color", required_argument, NULL, LO_INSIDE_CAPS_LOCK_COLOR},
479 {"inside-ver-color", required_argument, NULL, LO_INSIDE_VER_COLOR}, 496 {"inside-ver-color", required_argument, NULL, LO_INSIDE_VER_COLOR},
480 {"inside-wrong-color", required_argument, NULL, LO_INSIDE_WRONG_COLOR}, 497 {"inside-wrong-color", required_argument, NULL, LO_INSIDE_WRONG_COLOR},
481 {"key-hl-color", required_argument, NULL, LO_KEY_HL_COLOR}, 498 {"key-hl-color", required_argument, NULL, LO_KEY_HL_COLOR},
482 {"line-color", required_argument, NULL, LO_LINE_COLOR}, 499 {"line-color", required_argument, NULL, LO_LINE_COLOR},
483 {"line-clear-color", required_argument, NULL, LO_LINE_CLEAR_COLOR}, 500 {"line-clear-color", required_argument, NULL, LO_LINE_CLEAR_COLOR},
501 {"line-caps-lock-color", required_argument, NULL, LO_LINE_CAPS_LOCK_COLOR},
484 {"line-ver-color", required_argument, NULL, LO_LINE_VER_COLOR}, 502 {"line-ver-color", required_argument, NULL, LO_LINE_VER_COLOR},
485 {"line-wrong-color", required_argument, NULL, LO_LINE_WRONG_COLOR}, 503 {"line-wrong-color", required_argument, NULL, LO_LINE_WRONG_COLOR},
486 {"ring-color", required_argument, NULL, LO_RING_COLOR}, 504 {"ring-color", required_argument, NULL, LO_RING_COLOR},
487 {"ring-clear-color", required_argument, NULL, LO_RING_CLEAR_COLOR}, 505 {"ring-clear-color", required_argument, NULL, LO_RING_CLEAR_COLOR},
506 {"ring-caps-lock-color", required_argument, NULL, LO_RING_CAPS_LOCK_COLOR},
488 {"ring-ver-color", required_argument, NULL, LO_RING_VER_COLOR}, 507 {"ring-ver-color", required_argument, NULL, LO_RING_VER_COLOR},
489 {"ring-wrong-color", required_argument, NULL, LO_RING_WRONG_COLOR}, 508 {"ring-wrong-color", required_argument, NULL, LO_RING_WRONG_COLOR},
490 {"separator-color", required_argument, NULL, LO_SEP_COLOR}, 509 {"separator-color", required_argument, NULL, LO_SEP_COLOR},
491 {"text-color", required_argument, NULL, LO_TEXT_COLOR}, 510 {"text-color", required_argument, NULL, LO_TEXT_COLOR},
492 {"text-clear-color", required_argument, NULL, LO_TEXT_CLEAR_COLOR}, 511 {"text-clear-color", required_argument, NULL, LO_TEXT_CLEAR_COLOR},
512 {"text-caps-lock-color", required_argument, NULL, LO_TEXT_CAPS_LOCK_COLOR},
493 {"text-ver-color", required_argument, NULL, LO_TEXT_VER_COLOR}, 513 {"text-ver-color", required_argument, NULL, LO_TEXT_VER_COLOR},
494 {"text-wrong-color", required_argument, NULL, LO_TEXT_WRONG_COLOR}, 514 {"text-wrong-color", required_argument, NULL, LO_TEXT_WRONG_COLOR},
495 {0, 0, 0, 0} 515 {0, 0, 0, 0}
@@ -498,76 +518,97 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state,
498 const char usage[] = 518 const char usage[] =
499 "Usage: swaylock [options...]\n" 519 "Usage: swaylock [options...]\n"
500 "\n" 520 "\n"
501 " -C, --config <config_file> " 521 " -C, --config <config_file> "
502 "Path to the config file.\n" 522 "Path to the config file.\n"
503 " -c, --color <color> " 523 " -c, --color <color> "
504 "Turn the screen into the given color instead of white.\n" 524 "Turn the screen into the given color instead of white.\n"
505 " -e, --ignore-empty-password " 525 " -e, --ignore-empty-password "
506 "When an empty password is provided, do not validate it.\n" 526 "When an empty password is provided, do not validate it.\n"
507 " -f, --daemonize " 527 " -f, --daemonize "
508 "Detach from the controlling terminal after locking.\n" 528 "Detach from the controlling terminal after locking.\n"
509 " -h, --help " 529 " -h, --help "
510 "Show help message and quit.\n" 530 "Show help message and quit.\n"
511 " -i, --image [<output>:]<path> " 531 " -i, --image [<output>:]<path> "
512 "Display the given image.\n" 532 "Display the given image.\n"
513 " -s, --scaling <mode> " 533 " -L, --disable-caps-lock-text "
534 "Disable the Caps Lock text.\n"
535 " -l, --indicator-caps-lock "
536 "Show the current Caps Lock state also on the indicator.\n"
537 " -s, --scaling <mode> "
514 "Scaling mode: stretch, fill, fit, center, tile.\n" 538 "Scaling mode: stretch, fill, fit, center, tile.\n"
515 " -t, --tiling " 539 " -t, --tiling "
516 "Same as --scaling=tile.\n" 540 "Same as --scaling=tile.\n"
517 " -u, --no-unlock-indicator " 541 " -u, --no-unlock-indicator "
518 "Disable the unlock indicator.\n" 542 "Disable the unlock indicator.\n"
519 " -v, --version " 543 " -v, --version "
520 "Show the version number and quit.\n" 544 "Show the version number and quit.\n"
521 " --bs-hl-color <color> " 545 " --bs-hl-color <color> "
522 "Sets the color of backspace highlight segments.\n" 546 "Sets the color of backspace highlight segments.\n"
523 " --font <font> " 547 " --caps-lock-bs-hl-color <color> "
548 "Sets the color of backspace highlight segments when Caps Lock "
549 "is active.\n"
550 " --caps-lock-key-hl-color <color> "
551 "Sets the color of the key press highlight segments when "
552 "Caps Lock is active.\n"
553 " --font <font> "
524 "Sets the font of the text.\n" 554 "Sets the font of the text.\n"
525 " --indicator-radius <radius> " 555 " --indicator-radius <radius> "
526 "Sets the indicator radius.\n" 556 "Sets the indicator radius.\n"
527 " --indicator-thickness <thick> " 557 " --indicator-thickness <thick> "
528 "Sets the indicator thickness.\n" 558 "Sets the indicator thickness.\n"
529 " --inside-color <color> " 559 " --inside-color <color> "
530 "Sets the color of the inside of the indicator.\n" 560 "Sets the color of the inside of the indicator.\n"
531 " --inside-clear-color <color> " 561 " --inside-clear-color <color> "
532 "Sets the color of the inside of the indicator when cleared.\n" 562 "Sets the color of the inside of the indicator when cleared.\n"
533 " --inside-ver-color <color> " 563 " --inside-caps-lock-color <color> "
564 "Sets the color of the inside of the indicator when Caps Lock "
565 "is active.\n"
566 " --inside-ver-color <color> "
534 "Sets the color of the inside of the indicator when verifying.\n" 567 "Sets the color of the inside of the indicator when verifying.\n"
535 " --inside-wrong-color <color> " 568 " --inside-wrong-color <color> "
536 "Sets the color of the inside of the indicator when invalid.\n" 569 "Sets the color of the inside of the indicator when invalid.\n"
537 " --key-hl-color <color> " 570 " --key-hl-color <color> "
538 "Sets the color of the key press highlight segments.\n" 571 "Sets the color of the key press highlight segments.\n"
539 " --line-color <color> " 572 " --line-color <color> "
540 "Sets the color of the line between the inside and ring.\n" 573 "Sets the color of the line between the inside and ring.\n"
541 " --line-clear-color <color> " 574 " --line-clear-color <color> "
542 "Sets the color of the line between the inside and ring when " 575 "Sets the color of the line between the inside and ring when "
543 "cleared.\n" 576 "cleared.\n"
544 " --line-ver-color <color> " 577 " --line-caps-lock-color <color> "
578 "Sets the color of the line between the inside and ring when "
579 "Caps Lock is active.\n"
580 " --line-ver-color <color> "
545 "Sets the color of the line between the inside and ring when " 581 "Sets the color of the line between the inside and ring when "
546 "verifying.\n" 582 "verifying.\n"
547 " --line-wrong-color <color> " 583 " --line-wrong-color <color> "
548 "Sets the color of the line between the inside and ring when " 584 "Sets the color of the line between the inside and ring when "
549 "invalid.\n" 585 "invalid.\n"
550 " -n, --line-uses-inside " 586 " -n, --line-uses-inside "
551 "Use the inside color for the line between the inside and ring.\n" 587 "Use the inside color for the line between the inside and ring.\n"
552 " -r, --line-uses-ring " 588 " -r, --line-uses-ring "
553 "Use the ring color for the line between the inside and ring.\n" 589 "Use the ring color for the line between the inside and ring.\n"
554 " --ring-color <color> " 590 " --ring-color <color> "
555 "Sets the color of the ring of the indicator.\n" 591 "Sets the color of the ring of the indicator.\n"
556 " --ring-clear-color <color> " 592 " --ring-clear-color <color> "
557 "Sets the color of the ring of the indicator when cleared.\n" 593 "Sets the color of the ring of the indicator when cleared.\n"
558 " --ring-ver-color <color> " 594 " --ring-caps-lock-color <color> "
595 "Sets the color of the ring of the indicator when Caps Lock "
596 "is active.\n"
597 " --ring-ver-color <color> "
559 "Sets the color of the ring of the indicator when verifying.\n" 598 "Sets the color of the ring of the indicator when verifying.\n"
560 " --ring-wrong-color <color> " 599 " --ring-wrong-color <color> "
561 "Sets the color of the ring of the indicator when invalid.\n" 600 "Sets the color of the ring of the indicator when invalid.\n"
562 " --separator-color <color> " 601 " --separator-color <color> "
563 "Sets the color of the lines that separate highlight segments.\n" 602 "Sets the color of the lines that separate highlight segments.\n"
564 " --text-color <color> " 603 " --text-color <color> "
565 "Sets the color of the text.\n" 604 "Sets the color of the text.\n"
566 " --text-clear-color <color> " 605 " --text-clear-color <color> "
567 "Sets the color of the text when cleared.\n" 606 "Sets the color of the text when cleared.\n"
568 " --text-ver-color <color> " 607 " --text-caps-lock-color <color> "
608 "Sets the color of the text when Caps Lock is active.\n"
609 " --text-ver-color <color> "
569 "Sets the color of the text when verifying.\n" 610 "Sets the color of the text when verifying.\n"
570 " --text-wrong-color <color> " 611 " --text-wrong-color <color> "
571 "Sets the color of the text when invalid.\n" 612 "Sets the color of the text when invalid.\n"
572 "\n" 613 "\n"
573 "All <color> options are of the form <rrggbb[aa]>.\n"; 614 "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,
576 optind = 1; 617 optind = 1;
577 while (1) { 618 while (1) {
578 int opt_idx = 0; 619 int opt_idx = 0;
579 c = getopt_long(argc, argv, "c:efhi:nrs:tuvC:", long_options, &opt_idx); 620 c = getopt_long(argc, argv, "c:efhi:Llnrs:tuvC:", long_options, &opt_idx);
580 if (c == -1) { 621 if (c == -1) {
581 break; 622 break;
582 } 623 }
@@ -607,6 +648,16 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state,
607 load_image(optarg, state); 648 load_image(optarg, state);
608 } 649 }
609 break; 650 break;
651 case 'L':
652 if (state) {
653 state->args.show_caps_lock_text = false;
654 }
655 break;
656 case 'l':
657 if (state) {
658 state->args.show_caps_lock_indicator = true;
659 }
660 break;
610 case 'n': 661 case 'n':
611 if (line_mode) { 662 if (line_mode) {
612 *line_mode = LM_INSIDE; 663 *line_mode = LM_INSIDE;
@@ -644,6 +695,16 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state,
644 state->args.colors.bs_highlight = parse_color(optarg); 695 state->args.colors.bs_highlight = parse_color(optarg);
645 } 696 }
646 break; 697 break;
698 case LO_CAPS_LOCK_BS_HL_COLOR:
699 if (state) {
700 state->args.colors.caps_lock_bs_highlight = parse_color(optarg);
701 }
702 break;
703 case LO_CAPS_LOCK_KEY_HL_COLOR:
704 if (state) {
705 state->args.colors.caps_lock_key_highlight = parse_color(optarg);
706 }
707 break;
647 case LO_FONT: 708 case LO_FONT:
648 if (state) { 709 if (state) {
649 free(state->args.font); 710 free(state->args.font);
@@ -670,6 +731,11 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state,
670 state->args.colors.inside.cleared = parse_color(optarg); 731 state->args.colors.inside.cleared = parse_color(optarg);
671 } 732 }
672 break; 733 break;
734 case LO_INSIDE_CAPS_LOCK_COLOR:
735 if (state) {
736 state->args.colors.inside.caps_lock = parse_color(optarg);
737 }
738 break;
673 case LO_INSIDE_VER_COLOR: 739 case LO_INSIDE_VER_COLOR:
674 if (state) { 740 if (state) {
675 state->args.colors.inside.verifying = parse_color(optarg); 741 state->args.colors.inside.verifying = parse_color(optarg);
@@ -695,6 +761,11 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state,
695 state->args.colors.line.cleared = parse_color(optarg); 761 state->args.colors.line.cleared = parse_color(optarg);
696 } 762 }
697 break; 763 break;
764 case LO_LINE_CAPS_LOCK_COLOR:
765 if (state) {
766 state->args.colors.line.caps_lock = parse_color(optarg);
767 }
768 break;
698 case LO_LINE_VER_COLOR: 769 case LO_LINE_VER_COLOR:
699 if (state) { 770 if (state) {
700 state->args.colors.line.verifying = parse_color(optarg); 771 state->args.colors.line.verifying = parse_color(optarg);
@@ -715,6 +786,11 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state,
715 state->args.colors.ring.cleared = parse_color(optarg); 786 state->args.colors.ring.cleared = parse_color(optarg);
716 } 787 }
717 break; 788 break;
789 case LO_RING_CAPS_LOCK_COLOR:
790 if (state) {
791 state->args.colors.ring.caps_lock = parse_color(optarg);
792 }
793 break;
718 case LO_RING_VER_COLOR: 794 case LO_RING_VER_COLOR:
719 if (state) { 795 if (state) {
720 state->args.colors.ring.verifying = parse_color(optarg); 796 state->args.colors.ring.verifying = parse_color(optarg);
@@ -740,6 +816,11 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state,
740 state->args.colors.text.cleared = parse_color(optarg); 816 state->args.colors.text.cleared = parse_color(optarg);
741 } 817 }
742 break; 818 break;
819 case LO_TEXT_CAPS_LOCK_COLOR:
820 if (state) {
821 state->args.colors.text.caps_lock = parse_color(optarg);
822 }
823 break;
743 case LO_TEXT_VER_COLOR: 824 case LO_TEXT_VER_COLOR:
744 if (state) { 825 if (state) {
745 state->args.colors.text.verifying = parse_color(optarg); 826 state->args.colors.text.verifying = parse_color(optarg);
@@ -857,6 +938,8 @@ int main(int argc, char **argv) {
857 .thickness = 10, 938 .thickness = 10,
858 .ignore_empty = false, 939 .ignore_empty = false,
859 .show_indicator = true, 940 .show_indicator = true,
941 .show_caps_lock_indicator = false,
942 .show_caps_lock_text = true
860 }; 943 };
861 wl_list_init(&state.images); 944 wl_list_init(&state.images);
862 set_default_colors(&state.args.colors); 945 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,
18 } else if (state->auth_state == AUTH_STATE_CLEAR) { 18 } else if (state->auth_state == AUTH_STATE_CLEAR) {
19 cairo_set_source_u32(cairo, colorset->cleared); 19 cairo_set_source_u32(cairo, colorset->cleared);
20 } else { 20 } else {
21 cairo_set_source_u32(cairo, colorset->input); 21 if (state->xkb.caps_lock && state->args.show_caps_lock_indicator) {
22 cairo_set_source_u32(cairo, colorset->caps_lock);
23 } else if (state->xkb.caps_lock && !state->args.show_caps_lock_indicator &&
24 state->args.show_caps_lock_text) {
25 uint32_t inputtextcolor = state->args.colors.text.input;
26 state->args.colors.text.input = state->args.colors.text.caps_lock;
27 cairo_set_source_u32(cairo, colorset->input);
28 state->args.colors.text.input = inputtextcolor;
29 } else {
30 cairo_set_source_u32(cairo, colorset->input);
31 }
22 } 32 }
23} 33}
24 34
@@ -92,7 +102,8 @@ void render_frame(struct swaylock_surface *surface) {
92 break; 102 break;
93 case AUTH_STATE_INPUT: 103 case AUTH_STATE_INPUT:
94 case AUTH_STATE_INPUT_NOP: 104 case AUTH_STATE_INPUT_NOP:
95 if (state->xkb.caps_lock) { 105 case AUTH_STATE_BACKSPACE:
106 if (state->xkb.caps_lock && state->args.show_caps_lock_text) {
96 text = "Caps Lock"; 107 text = "Caps Lock";
97 } 108 }
98 break; 109 break;
@@ -125,9 +136,17 @@ void render_frame(struct swaylock_surface *surface) {
125 arc_radius, highlight_start, 136 arc_radius, highlight_start,
126 highlight_start + TYPE_INDICATOR_RANGE); 137 highlight_start + TYPE_INDICATOR_RANGE);
127 if (state->auth_state == AUTH_STATE_INPUT) { 138 if (state->auth_state == AUTH_STATE_INPUT) {
128 cairo_set_source_u32(cairo, state->args.colors.key_highlight); 139 if (state->xkb.caps_lock && state->args.show_caps_lock_indicator) {
140 cairo_set_source_u32(cairo, state->args.colors.caps_lock_key_highlight);
141 } else {
142 cairo_set_source_u32(cairo, state->args.colors.key_highlight);
143 }
129 } else { 144 } else {
130 cairo_set_source_u32(cairo, state->args.colors.bs_highlight); 145 if (state->xkb.caps_lock && state->args.show_caps_lock_indicator) {
146 cairo_set_source_u32(cairo, state->args.colors.caps_lock_bs_highlight);
147 } else {
148 cairo_set_source_u32(cairo, state->args.colors.bs_highlight);
149 }
131 } 150 }
132 cairo_stroke(cairo); 151 cairo_stroke(cairo);
133 152
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.
44 Display the given image, optionally only on the given output. Use -c to set 44 Display the given image, optionally only on the given output. Use -c to set
45 a background color. 45 a background color.
46 46
47*-L, --disable-caps-lock-text*
48 Disable the Caps Lock Text.
49
50*-l, --indicator-caps-lock*
51 Show the current Caps Lock state also on the indicator.
52
47*-s, --scaling* 53*-s, --scaling*
48 Scaling mode for images: _stretch_, _fill_, _fit_, _center_, or _tile_. 54 Scaling mode for images: _stretch_, _fill_, _fit_, _center_, or _tile_.
49 55
@@ -58,6 +64,12 @@ Locks your Wayland session.
58*--bs-hl-color* <rrggbb[aa]> 64*--bs-hl-color* <rrggbb[aa]>
59 Sets the color of backspace highlight segments. 65 Sets the color of backspace highlight segments.
60 66
67*--caps-lock-bs-hl-color* <rrggbb[aa]>
68 Sets the color of backspace highlight segments when Caps Lock is active.
69
70*--caps-lock-bs-hl-color* <rrggbb[aa]>
71 Sets the color of the key press highlight segments when Caps Lock is active.
72
61*--font* <font> 73*--font* <font>
62 Sets the font of the text inside the indicator. 74 Sets the font of the text inside the indicator.
63 75
@@ -75,6 +87,9 @@ Locks your Wayland session.
75*--inside-clear-color* <rrggbb[aa]> 87*--inside-clear-color* <rrggbb[aa]>
76 Sets the color of the inside of the indicator when cleared. 88 Sets the color of the inside of the indicator when cleared.
77 89
90*--inside-caps-lock-color* <rrggbb[aa]>
91 Sets the color of the inside of the indicator when Caps Lock is active.
92
78*--inside-ver-color* <rrggbb[aa]> 93*--inside-ver-color* <rrggbb[aa]>
79 Sets the color of the inside of the indicator when verifying. 94 Sets the color of the inside of the indicator when verifying.
80 95
@@ -92,6 +107,10 @@ Locks your Wayland session.
92 Sets the color of the lines that separate the inside and outside of the 107 Sets the color of the lines that separate the inside and outside of the
93 indicator when cleared. 108 indicator when cleared.
94 109
110*--line-caps-lock-color* <rrggbb[aa]>
111 Sets the color of the line between the inside and ring when Caps Lock
112 is active.
113
95*--line-ver-color* <rrggbb[aa]> 114*--line-ver-color* <rrggbb[aa]>
96 Sets the color of the lines that separate the inside and outside of the 115 Sets the color of the lines that separate the inside and outside of the
97 indicator when verifying. 116 indicator when verifying.
@@ -114,6 +133,9 @@ Locks your Wayland session.
114*--ring-clear-color* <rrggbb[aa]> 133*--ring-clear-color* <rrggbb[aa]>
115 Sets the color of the outside of the indicator when cleared. 134 Sets the color of the outside of the indicator when cleared.
116 135
136*--ring-caps-lock-color* <rrggbb[aa]>
137 Sets the color of the ring of the indicator when Caps Lock is active.
138
117*--ring-ver-color* <rrggbb[aa]> 139*--ring-ver-color* <rrggbb[aa]>
118 Sets the color of the outside of the indicator when verifying. 140 Sets the color of the outside of the indicator when verifying.
119 141
@@ -129,6 +151,9 @@ Locks your Wayland session.
129*--text-clear-color* <rrggbb[aa]> 151*--text-clear-color* <rrggbb[aa]>
130 Sets the color of the text inside the indicator when cleared. 152 Sets the color of the text inside the indicator when cleared.
131 153
154*--text-caps-lock-color* <rrggbb[aa]>
155 Sets the color of the text when Caps Lock is active.
156
132*--text-ver-color* <rrggbb[aa]> 157*--text-ver-color* <rrggbb[aa]>
133 Sets the color of the text inside the indicator when verifying. 158 Sets the color of the text inside the indicator when verifying.
134 159
diff --git a/swaymsg/main.c b/swaymsg/main.c
index f1bb5e3e..e5eee631 100644
--- a/swaymsg/main.c
+++ b/swaymsg/main.c
@@ -113,7 +113,7 @@ static const char *pretty_type_name(const char *name) {
113} 113}
114 114
115static void pretty_print_input(json_object *i) { 115static void pretty_print_input(json_object *i) {
116 json_object *id, *name, *type, *product, *vendor, *kbdlayout; 116 json_object *id, *name, *type, *product, *vendor, *kbdlayout, *events;
117 json_object_object_get_ex(i, "identifier", &id); 117 json_object_object_get_ex(i, "identifier", &id);
118 json_object_object_get_ex(i, "name", &name); 118 json_object_object_get_ex(i, "name", &name);
119 json_object_object_get_ex(i, "type", &type); 119 json_object_object_get_ex(i, "type", &type);
@@ -139,6 +139,10 @@ static void pretty_print_input(json_object *i) {
139 json_object_get_string(kbdlayout)); 139 json_object_get_string(kbdlayout));
140 } 140 }
141 141
142 if (json_object_object_get_ex(i, "libinput_send_events", &events)) {
143 printf(" Libinput Send Events: %s\n", json_object_get_string(events));
144 }
145
142 printf("\n"); 146 printf("\n");
143} 147}
144 148