diff options
author | Ryan Dwyer <RyanDwyer@users.noreply.github.com> | 2018-07-18 09:32:03 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-18 09:32:03 +1000 |
commit | 8ce7e3b44eea0a270ecc35a9da2ae801aaf6bce1 (patch) | |
tree | 6badffb0c6ee33b4e23e914c4c9f9b39a625b5f3 | |
parent | Destroy empty workspace when destroying its output (diff) | |
parent | Merge pull request #2281 from pvsr/X11_click (diff) | |
download | sway-8ce7e3b44eea0a270ecc35a9da2ae801aaf6bce1.tar.gz sway-8ce7e3b44eea0a270ecc35a9da2ae801aaf6bce1.tar.zst sway-8ce7e3b44eea0a270ecc35a9da2ae801aaf6bce1.zip |
Merge branch 'master' into destroy-output-destroy-empty-workspaces
131 files changed, 2642 insertions, 992 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8a6c0208..f450563a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md | |||
@@ -107,7 +107,7 @@ int main(int argc, const char **argv) { | |||
107 | } | 107 | } |
108 | 108 | ||
109 | int desired_output = atoi(argv[1]); | 109 | int desired_output = atoi(argv[1]); |
110 | sway_log(L_INFO, "Using output %d of %d", desired_output, registry->outputs->length); | 110 | sway_log(WLR_INFO, "Using output %d of %d", desired_output, registry->outputs->length); |
111 | int i; | 111 | int i; |
112 | struct output_state *output = registry->outputs->items[desired_output]; | 112 | struct output_state *output = registry->outputs->items[desired_output]; |
113 | struct window *window = window_setup(registry, 100, 100, false); | 113 | struct window *window = window_setup(registry, 100, 100, false); |
@@ -3,9 +3,9 @@ | |||
3 | Use `sway_log(importance, fmt, ...)` to log. The following importances are | 3 | Use `sway_log(importance, fmt, ...)` to log. The following importances are |
4 | available: | 4 | available: |
5 | 5 | ||
6 | * `L_DEBUG`: Debug messages, only shows with `sway -d` | 6 | * `WLR_DEBUG`: Debug messages, only shows with `sway -d` |
7 | * `L_INFO`: Informational messages | 7 | * `WLR_INFO`: Informational messages |
8 | * `L_ERROR`: Error messages | 8 | * `WLR_ERROR`: Error messages |
9 | 9 | ||
10 | `sway_log` is a macro that calls `_sway_log` with the current filename and line | 10 | `sway_log` is a macro that calls `_sway_log` with the current filename and line |
11 | number, which are written into the log with your message. | 11 | number, which are written into the log with your message. |
diff --git a/common/background-image.c b/common/background-image.c index e5fb4433..f3d2551e 100644 --- a/common/background-image.c +++ b/common/background-image.c | |||
@@ -18,7 +18,7 @@ enum background_mode parse_background_mode(const char *mode) { | |||
18 | } else if (strcmp(mode, "solid_color") == 0) { | 18 | } else if (strcmp(mode, "solid_color") == 0) { |
19 | return BACKGROUND_MODE_SOLID_COLOR; | 19 | return BACKGROUND_MODE_SOLID_COLOR; |
20 | } | 20 | } |
21 | wlr_log(L_ERROR, "Unsupported background mode: %s", mode); | 21 | wlr_log(WLR_ERROR, "Unsupported background mode: %s", mode); |
22 | return BACKGROUND_MODE_INVALID; | 22 | return BACKGROUND_MODE_INVALID; |
23 | } | 23 | } |
24 | 24 | ||
@@ -28,7 +28,7 @@ cairo_surface_t *load_background_image(const char *path) { | |||
28 | GError *err = NULL; | 28 | GError *err = NULL; |
29 | GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &err); | 29 | GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &err); |
30 | if (!pixbuf) { | 30 | if (!pixbuf) { |
31 | wlr_log(L_ERROR, "Failed to load background image (%s).", | 31 | wlr_log(WLR_ERROR, "Failed to load background image (%s).", |
32 | err->message); | 32 | err->message); |
33 | return false; | 33 | return false; |
34 | } | 34 | } |
@@ -38,11 +38,11 @@ cairo_surface_t *load_background_image(const char *path) { | |||
38 | image = cairo_image_surface_create_from_png(path); | 38 | image = cairo_image_surface_create_from_png(path); |
39 | #endif //HAVE_GDK_PIXBUF | 39 | #endif //HAVE_GDK_PIXBUF |
40 | if (!image) { | 40 | if (!image) { |
41 | wlr_log(L_ERROR, "Failed to read background image."); | 41 | wlr_log(WLR_ERROR, "Failed to read background image."); |
42 | return NULL; | 42 | return NULL; |
43 | } | 43 | } |
44 | if (cairo_surface_status(image) != CAIRO_STATUS_SUCCESS) { | 44 | if (cairo_surface_status(image) != CAIRO_STATUS_SUCCESS) { |
45 | wlr_log(L_ERROR, "Failed to read background image: %s." | 45 | wlr_log(WLR_ERROR, "Failed to read background image: %s." |
46 | #ifndef HAVE_GDK_PIXBUF | 46 | #ifndef HAVE_GDK_PIXBUF |
47 | "\nSway was compiled without gdk_pixbuf support, so only" | 47 | "\nSway was compiled without gdk_pixbuf support, so only" |
48 | "\nPNG images can be loaded. This is the likely cause." | 48 | "\nPNG images can be loaded. This is the likely cause." |
diff --git a/common/ipc-client.c b/common/ipc-client.c index a88df080..4d2d88cc 100644 --- a/common/ipc-client.c +++ b/common/ipc-client.c | |||
@@ -97,7 +97,7 @@ struct ipc_response *ipc_recv_response(int socketfd) { | |||
97 | error_2: | 97 | error_2: |
98 | free(response); | 98 | free(response); |
99 | error_1: | 99 | error_1: |
100 | wlr_log(L_ERROR, "Unable to allocate memory for IPC response"); | 100 | wlr_log(WLR_ERROR, "Unable to allocate memory for IPC response"); |
101 | return NULL; | 101 | return NULL; |
102 | } | 102 | } |
103 | 103 | ||
diff --git a/common/list.c b/common/list.c index 39cc10e1..66d52f70 100644 --- a/common/list.c +++ b/common/list.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <stdio.h> | 2 | #include <stdio.h> |
3 | #include <stdlib.h> | 3 | #include <stdlib.h> |
4 | #include <string.h> | 4 | #include <string.h> |
5 | #include "log.h" | ||
5 | 6 | ||
6 | list_t *create_list(void) { | 7 | list_t *create_list(void) { |
7 | list_t *list = malloc(sizeof(list_t)); | 8 | list_t *list = malloc(sizeof(list_t)); |
@@ -82,6 +83,20 @@ void list_swap(list_t *list, int src, int dest) { | |||
82 | list->items[dest] = tmp; | 83 | list->items[dest] = tmp; |
83 | } | 84 | } |
84 | 85 | ||
86 | void list_move_to_end(list_t *list, void *item) { | ||
87 | int i; | ||
88 | for (i = 0; i < list->length; ++i) { | ||
89 | if (list->items[i] == item) { | ||
90 | break; | ||
91 | } | ||
92 | } | ||
93 | if (!sway_assert(i < list->length, "Item not found in list")) { | ||
94 | return; | ||
95 | } | ||
96 | list_del(list, i); | ||
97 | list_add(list, item); | ||
98 | } | ||
99 | |||
85 | static void list_rotate(list_t *list, int from, int to) { | 100 | static void list_rotate(list_t *list, int from, int to) { |
86 | void *tmp = list->items[to]; | 101 | void *tmp = list->items[to]; |
87 | 102 | ||
diff --git a/common/log.c b/common/log.c index 2cc7289c..847f3952 100644 --- a/common/log.c +++ b/common/log.c | |||
@@ -8,7 +8,7 @@ void sway_terminate(int code); | |||
8 | void _sway_abort(const char *format, ...) { | 8 | void _sway_abort(const char *format, ...) { |
9 | va_list args; | 9 | va_list args; |
10 | va_start(args, format); | 10 | va_start(args, format); |
11 | _wlr_vlog(L_ERROR, format, args); | 11 | _wlr_vlog(WLR_ERROR, format, args); |
12 | va_end(args); | 12 | va_end(args); |
13 | sway_terminate(EXIT_FAILURE); | 13 | sway_terminate(EXIT_FAILURE); |
14 | } | 14 | } |
@@ -20,7 +20,7 @@ bool _sway_assert(bool condition, const char *format, ...) { | |||
20 | 20 | ||
21 | va_list args; | 21 | va_list args; |
22 | va_start(args, format); | 22 | va_start(args, format); |
23 | _wlr_vlog(L_ERROR, format, args); | 23 | _wlr_vlog(WLR_ERROR, format, args); |
24 | va_end(args); | 24 | va_end(args); |
25 | 25 | ||
26 | #ifndef NDEBUG | 26 | #ifndef NDEBUG |
diff --git a/common/pango.c b/common/pango.c index c88e50ce..92703f80 100644 --- a/common/pango.c +++ b/common/pango.c | |||
@@ -81,7 +81,7 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, | |||
81 | pango_layout_set_markup(layout, buf, -1); | 81 | pango_layout_set_markup(layout, buf, -1); |
82 | free(buf); | 82 | free(buf); |
83 | } else { | 83 | } else { |
84 | wlr_log(L_ERROR, "pango_parse_markup '%s' -> error %s", text, | 84 | wlr_log(WLR_ERROR, "pango_parse_markup '%s' -> error %s", text, |
85 | error->message); | 85 | error->message); |
86 | g_error_free(error); | 86 | g_error_free(error); |
87 | markup = false; // fallback to plain text | 87 | markup = false; // fallback to plain text |
diff --git a/common/readline.c b/common/readline.c index 1c396a90..a2c69018 100644 --- a/common/readline.c +++ b/common/readline.c | |||
@@ -9,7 +9,7 @@ char *read_line(FILE *file) { | |||
9 | char *string = malloc(size); | 9 | char *string = malloc(size); |
10 | char lastChar = '\0'; | 10 | char lastChar = '\0'; |
11 | if (!string) { | 11 | if (!string) { |
12 | wlr_log(L_ERROR, "Unable to allocate memory for read_line"); | 12 | wlr_log(WLR_ERROR, "Unable to allocate memory for read_line"); |
13 | return NULL; | 13 | return NULL; |
14 | } | 14 | } |
15 | while (1) { | 15 | while (1) { |
@@ -30,7 +30,7 @@ char *read_line(FILE *file) { | |||
30 | char *new_string = realloc(string, size *= 2); | 30 | char *new_string = realloc(string, size *= 2); |
31 | if (!new_string) { | 31 | if (!new_string) { |
32 | free(string); | 32 | free(string); |
33 | wlr_log(L_ERROR, "Unable to allocate memory for read_line"); | 33 | wlr_log(WLR_ERROR, "Unable to allocate memory for read_line"); |
34 | return NULL; | 34 | return NULL; |
35 | } | 35 | } |
36 | string = new_string; | 36 | string = new_string; |
diff --git a/common/util.c b/common/util.c index 678926ed..e8a88772 100644 --- a/common/util.c +++ b/common/util.c | |||
@@ -113,7 +113,7 @@ uint32_t parse_color(const char *color) { | |||
113 | 113 | ||
114 | int len = strlen(color); | 114 | int len = strlen(color); |
115 | if (len != 6 && len != 8) { | 115 | if (len != 6 && len != 8) { |
116 | wlr_log(L_DEBUG, "Invalid color %s, defaulting to color 0xFFFFFFFF", color); | 116 | wlr_log(WLR_DEBUG, "Invalid color %s, defaulting to color 0xFFFFFFFF", color); |
117 | return 0xFFFFFFFF; | 117 | return 0xFFFFFFFF; |
118 | } | 118 | } |
119 | uint32_t res = (uint32_t)strtoul(color, NULL, 16); | 119 | uint32_t res = (uint32_t)strtoul(color, NULL, 16); |
diff --git a/completions/zsh/_swaymsg b/completions/zsh/_swaymsg index 6bb03279..2e39deb6 100644 --- a/completions/zsh/_swaymsg +++ b/completions/zsh/_swaymsg | |||
@@ -22,7 +22,6 @@ types=( | |||
22 | 'get_marks' | 22 | 'get_marks' |
23 | 'get_bar_config' | 23 | 'get_bar_config' |
24 | 'get_version' | 24 | 'get_version' |
25 | 'get_clipboard' | ||
26 | ) | 25 | ) |
27 | 26 | ||
28 | _arguments -s \ | 27 | _arguments -s \ |
diff --git a/include/ipc.h b/include/ipc.h index 8172c782..0010718b 100644 --- a/include/ipc.h +++ b/include/ipc.h | |||
@@ -13,11 +13,12 @@ enum ipc_command_type { | |||
13 | IPC_GET_MARKS = 5, | 13 | IPC_GET_MARKS = 5, |
14 | IPC_GET_BAR_CONFIG = 6, | 14 | IPC_GET_BAR_CONFIG = 6, |
15 | IPC_GET_VERSION = 7, | 15 | IPC_GET_VERSION = 7, |
16 | IPC_GET_BINDING_MODES = 8, | ||
17 | IPC_GET_CONFIG = 9, | ||
16 | 18 | ||
17 | // sway-specific command types | 19 | // sway-specific command types |
18 | IPC_GET_INPUTS = 100, | 20 | IPC_GET_INPUTS = 100, |
19 | IPC_GET_CLIPBOARD = 101, | 21 | IPC_GET_SEATS = 101, |
20 | IPC_GET_SEATS = 102, | ||
21 | 22 | ||
22 | // Events sent from sway to clients. Events have the highest bits set. | 23 | // Events sent from sway to clients. Events have the highest bits set. |
23 | IPC_EVENT_WORKSPACE = ((1<<31) | 0), | 24 | IPC_EVENT_WORKSPACE = ((1<<31) | 0), |
diff --git a/include/list.h b/include/list.h index 7eead4ac..5a0d7d80 100644 --- a/include/list.h +++ b/include/list.h | |||
@@ -24,4 +24,6 @@ int list_seq_find(list_t *list, int compare(const void *item, const void *cmp_to | |||
24 | void list_stable_sort(list_t *list, int compare(const void *a, const void *b)); | 24 | void list_stable_sort(list_t *list, int compare(const void *a, const void *b)); |
25 | // swap two elements in a list | 25 | // swap two elements in a list |
26 | void list_swap(list_t *list, int src, int dest); | 26 | void list_swap(list_t *list, int src, int dest); |
27 | // move item to end of list | ||
28 | void list_move_to_end(list_t *list, void *item); | ||
27 | #endif | 29 | #endif |
diff --git a/include/log.h b/include/log.h index a9748127..dd526143 100644 --- a/include/log.h +++ b/include/log.h | |||
@@ -3,13 +3,19 @@ | |||
3 | #include <stdbool.h> | 3 | #include <stdbool.h> |
4 | #include <wlr/util/log.h> | 4 | #include <wlr/util/log.h> |
5 | 5 | ||
6 | #ifdef __GNUC__ | ||
7 | #define ATTRIB_PRINTF(start, end) __attribute__((format(printf, start, end))) | ||
8 | #else | ||
9 | #define ATTRIB_PRINTF(start, end) | ||
10 | #endif | ||
11 | |||
6 | void _sway_abort(const char *filename, ...) ATTRIB_PRINTF(1, 2); | 12 | void _sway_abort(const char *filename, ...) ATTRIB_PRINTF(1, 2); |
7 | #define sway_abort(FMT, ...) \ | 13 | #define sway_abort(FMT, ...) \ |
8 | _sway_abort("[%s:%d] " FMT, wlr_strip_path(__FILE__), __LINE__, ##__VA_ARGS__) | 14 | _sway_abort("[%s:%d] " FMT, _wlr_strip_path(__FILE__), __LINE__, ##__VA_ARGS__) |
9 | 15 | ||
10 | bool _sway_assert(bool condition, const char* format, ...) ATTRIB_PRINTF(2, 3); | 16 | bool _sway_assert(bool condition, const char* format, ...) ATTRIB_PRINTF(2, 3); |
11 | #define sway_assert(COND, FMT, ...) \ | 17 | #define sway_assert(COND, FMT, ...) \ |
12 | _sway_assert(COND, "[%s:%d] %s:" FMT, wlr_strip_path(__FILE__), __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__) | 18 | _sway_assert(COND, "[%s:%d] %s:" FMT, _wlr_strip_path(__FILE__), __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__) |
13 | 19 | ||
14 | void error_handler(int sig); | 20 | void error_handler(int sig); |
15 | 21 | ||
diff --git a/include/sway/commands.h b/include/sway/commands.h index 6d17144a..1e93e2a3 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h | |||
@@ -95,7 +95,6 @@ sway_cmd cmd_client_unfocused; | |||
95 | sway_cmd cmd_client_urgent; | 95 | sway_cmd cmd_client_urgent; |
96 | sway_cmd cmd_client_placeholder; | 96 | sway_cmd cmd_client_placeholder; |
97 | sway_cmd cmd_client_background; | 97 | sway_cmd cmd_client_background; |
98 | sway_cmd cmd_clipboard; | ||
99 | sway_cmd cmd_commands; | 98 | sway_cmd cmd_commands; |
100 | sway_cmd cmd_debuglog; | 99 | sway_cmd cmd_debuglog; |
101 | sway_cmd cmd_default_border; | 100 | sway_cmd cmd_default_border; |
@@ -153,6 +152,7 @@ sway_cmd cmd_swaybg_command; | |||
153 | sway_cmd cmd_swap; | 152 | sway_cmd cmd_swap; |
154 | sway_cmd cmd_title_format; | 153 | sway_cmd cmd_title_format; |
155 | sway_cmd cmd_unmark; | 154 | sway_cmd cmd_unmark; |
155 | sway_cmd cmd_urgent; | ||
156 | sway_cmd cmd_workspace; | 156 | sway_cmd cmd_workspace; |
157 | sway_cmd cmd_ws_auto_back_and_forth; | 157 | sway_cmd cmd_ws_auto_back_and_forth; |
158 | sway_cmd cmd_workspace_layout; | 158 | sway_cmd cmd_workspace_layout; |
@@ -208,8 +208,10 @@ sway_cmd input_cmd_natural_scroll; | |||
208 | sway_cmd input_cmd_pointer_accel; | 208 | sway_cmd input_cmd_pointer_accel; |
209 | sway_cmd input_cmd_repeat_delay; | 209 | sway_cmd input_cmd_repeat_delay; |
210 | sway_cmd input_cmd_repeat_rate; | 210 | sway_cmd input_cmd_repeat_rate; |
211 | sway_cmd input_cmd_scroll_button; | ||
211 | sway_cmd input_cmd_scroll_method; | 212 | sway_cmd input_cmd_scroll_method; |
212 | sway_cmd input_cmd_tap; | 213 | sway_cmd input_cmd_tap; |
214 | sway_cmd input_cmd_tap_button_map; | ||
213 | sway_cmd input_cmd_xkb_layout; | 215 | sway_cmd input_cmd_xkb_layout; |
214 | sway_cmd input_cmd_xkb_model; | 216 | sway_cmd input_cmd_xkb_model; |
215 | sway_cmd input_cmd_xkb_options; | 217 | sway_cmd input_cmd_xkb_options; |
diff --git a/include/sway/config.h b/include/sway/config.h index ac668c24..f660a269 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -75,9 +75,11 @@ struct input_config { | |||
75 | float pointer_accel; | 75 | float pointer_accel; |
76 | int repeat_delay; | 76 | int repeat_delay; |
77 | int repeat_rate; | 77 | int repeat_rate; |
78 | int scroll_button; | ||
78 | int scroll_method; | 79 | int scroll_method; |
79 | int send_events; | 80 | int send_events; |
80 | int tap; | 81 | int tap; |
82 | int tap_button_map; | ||
81 | 83 | ||
82 | char *xkb_layout; | 84 | char *xkb_layout; |
83 | char *xkb_model; | 85 | char *xkb_model; |
@@ -271,11 +273,10 @@ enum ipc_feature { | |||
271 | IPC_FEATURE_EVENT_WINDOW = 2048, | 273 | IPC_FEATURE_EVENT_WINDOW = 2048, |
272 | IPC_FEATURE_EVENT_BINDING = 4096, | 274 | IPC_FEATURE_EVENT_BINDING = 4096, |
273 | IPC_FEATURE_EVENT_INPUT = 8192, | 275 | IPC_FEATURE_EVENT_INPUT = 8192, |
274 | IPC_FEATURE_GET_CLIPBOARD = 16384, | 276 | IPC_FEATURE_GET_SEATS = 16384, |
275 | IPC_FEATURE_GET_SEATS = 32768, | ||
276 | 277 | ||
277 | IPC_FEATURE_ALL_COMMANDS = | 278 | IPC_FEATURE_ALL_COMMANDS = |
278 | 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 | 16384 | 32768, | 279 | 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 | 16384, |
279 | IPC_FEATURE_ALL_EVENTS = 256 | 512 | 1024 | 2048 | 4096 | 8192, | 280 | IPC_FEATURE_ALL_EVENTS = 256 | 512 | 1024 | 2048 | 4096 | 8192, |
280 | 281 | ||
281 | IPC_FEATURE_ALL = IPC_FEATURE_ALL_COMMANDS | IPC_FEATURE_ALL_EVENTS, | 282 | IPC_FEATURE_ALL = IPC_FEATURE_ALL_COMMANDS | IPC_FEATURE_ALL_EVENTS, |
@@ -341,6 +342,7 @@ struct sway_config { | |||
341 | int gaps_outer; | 342 | int gaps_outer; |
342 | 343 | ||
343 | list_t *config_chain; | 344 | list_t *config_chain; |
345 | const char *current_config_path; | ||
344 | const char *current_config; | 346 | const char *current_config; |
345 | 347 | ||
346 | enum sway_container_border border; | 348 | enum sway_container_border border; |
@@ -496,7 +498,4 @@ void config_update_font_height(bool recalculate); | |||
496 | /* Global config singleton. */ | 498 | /* Global config singleton. */ |
497 | extern struct sway_config *config; | 499 | extern struct sway_config *config; |
498 | 500 | ||
499 | /* Config file currently being read */ | ||
500 | extern const char *current_config_path; | ||
501 | |||
502 | #endif | 501 | #endif |
diff --git a/include/sway/criteria.h b/include/sway/criteria.h index bd3ca0ac..6a8337c5 100644 --- a/include/sway/criteria.h +++ b/include/sway/criteria.h | |||
@@ -6,9 +6,10 @@ | |||
6 | #include "tree/view.h" | 6 | #include "tree/view.h" |
7 | 7 | ||
8 | enum criteria_type { | 8 | enum criteria_type { |
9 | CT_COMMAND = 1 << 0, | 9 | CT_COMMAND = 1 << 0, |
10 | CT_ASSIGN_OUTPUT = 1 << 1, | 10 | CT_ASSIGN_OUTPUT = 1 << 1, |
11 | CT_ASSIGN_WORKSPACE = 1 << 2, | 11 | CT_ASSIGN_WORKSPACE = 1 << 2, |
12 | CT_NO_FOCUS = 1 << 3, | ||
12 | }; | 13 | }; |
13 | 14 | ||
14 | struct criteria { | 15 | struct criteria { |
diff --git a/include/sway/debug.h b/include/sway/debug.h index 2430d319..38d4eccd 100644 --- a/include/sway/debug.h +++ b/include/sway/debug.h | |||
@@ -1,7 +1,15 @@ | |||
1 | #ifndef SWAY_DEBUG_H | 1 | #ifndef SWAY_DEBUG_H |
2 | #define SWAY_DEBUG_H | 2 | #define SWAY_DEBUG_H |
3 | 3 | ||
4 | // Tree | ||
4 | extern bool enable_debug_tree; | 5 | extern bool enable_debug_tree; |
5 | void update_debug_tree(); | 6 | void update_debug_tree(); |
6 | 7 | ||
8 | // Damage | ||
9 | extern const char *damage_debug; | ||
10 | |||
11 | // Transactions | ||
12 | extern int txn_timeout_ms; | ||
13 | extern bool txn_debug; | ||
14 | |||
7 | #endif | 15 | #endif |
diff --git a/include/sway/desktop.h b/include/sway/desktop.h index f1ad759a..348fb187 100644 --- a/include/sway/desktop.h +++ b/include/sway/desktop.h | |||
@@ -1,4 +1,8 @@ | |||
1 | #include <wlr/types/wlr_surface.h> | 1 | #include <wlr/types/wlr_surface.h> |
2 | 2 | ||
3 | struct sway_container; | ||
4 | |||
3 | void desktop_damage_surface(struct wlr_surface *surface, double lx, double ly, | 5 | void desktop_damage_surface(struct wlr_surface *surface, double lx, double ly, |
4 | bool whole); | 6 | bool whole); |
7 | |||
8 | void desktop_damage_whole_container(struct sway_container *con); | ||
diff --git a/include/sway/desktop/transaction.h b/include/sway/desktop/transaction.h index 7ab80eb8..cee4afed 100644 --- a/include/sway/desktop/transaction.h +++ b/include/sway/desktop/transaction.h | |||
@@ -6,34 +6,25 @@ | |||
6 | /** | 6 | /** |
7 | * Transactions enable us to perform atomic layout updates. | 7 | * Transactions enable us to perform atomic layout updates. |
8 | * | 8 | * |
9 | * When we want to make adjustments to the layout, we create a transaction. | 9 | * A transaction contains a list of containers and their new state. |
10 | * A transaction contains a list of affected containers and their new state. | ||
11 | * A state might contain a new size, or new border settings, or new parent/child | 10 | * A state might contain a new size, or new border settings, or new parent/child |
12 | * relationships. | 11 | * relationships. |
13 | * | 12 | * |
14 | * Calling transaction_commit() makes sway notify of all the affected clients | 13 | * Committing a transaction makes sway notify of all the affected clients with |
15 | * with their new sizes. We then wait for all the views to respond with their | 14 | * their new sizes. We then wait for all the views to respond with their new |
16 | * new surface sizes. When all are ready, or when a timeout has passed, we apply | 15 | * surface sizes. When all are ready, or when a timeout has passed, we apply the |
17 | * the updates all at the same time. | 16 | * updates all at the same time. |
18 | */ | 17 | * |
19 | 18 | * When we want to make adjustments to the layout, we change the pending state | |
20 | struct sway_transaction; | 19 | * in containers, mark them as dirty and call transaction_commit_dirty(). This |
21 | 20 | * create and commits a transaction from the dirty containers. | |
22 | /** | ||
23 | * Create a new transaction. | ||
24 | */ | ||
25 | struct sway_transaction *transaction_create(void); | ||
26 | |||
27 | /** | ||
28 | * Add a container's pending state to the transaction. | ||
29 | */ | 21 | */ |
30 | void transaction_add_container(struct sway_transaction *transaction, | ||
31 | struct sway_container *container); | ||
32 | 22 | ||
33 | /** | 23 | /** |
34 | * Submit a transaction to the client views for configuration. | 24 | * Find all dirty containers, create and commit a transaction containing them, |
25 | * and unmark them as dirty. | ||
35 | */ | 26 | */ |
36 | void transaction_commit(struct sway_transaction *transaction); | 27 | void transaction_commit_dirty(void); |
37 | 28 | ||
38 | /** | 29 | /** |
39 | * Notify the transaction system that a view is ready for the new layout. | 30 | * Notify the transaction system that a view is ready for the new layout. |
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 0e440701..1f7792ba 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h | |||
@@ -119,17 +119,6 @@ struct sway_container *seat_get_active_child(struct sway_seat *seat, | |||
119 | struct sway_container *container); | 119 | struct sway_container *container); |
120 | 120 | ||
121 | /** | 121 | /** |
122 | * Return the immediate child of container which was most recently focused, with | ||
123 | * fallback to selecting the child in the parent's `current` (rendered) children | ||
124 | * list. | ||
125 | * | ||
126 | * This is useful for when a tabbed container and its children are destroyed but | ||
127 | * still being rendered, and we have to render an appropriate child. | ||
128 | */ | ||
129 | struct sway_container *seat_get_active_current_child(struct sway_seat *seat, | ||
130 | struct sway_container *container); | ||
131 | |||
132 | /** | ||
133 | * Iterate over the focus-inactive children of the container calling the | 122 | * Iterate over the focus-inactive children of the container calling the |
134 | * function on each. | 123 | * function on each. |
135 | */ | 124 | */ |
diff --git a/include/sway/server.h b/include/sway/server.h index a3e32898..a017d1c4 100644 --- a/include/sway/server.h +++ b/include/sway/server.h | |||
@@ -47,10 +47,7 @@ struct sway_server { | |||
47 | bool debug_txn_timings; | 47 | bool debug_txn_timings; |
48 | 48 | ||
49 | list_t *transactions; | 49 | list_t *transactions; |
50 | 50 | list_t *dirty_containers; | |
51 | // When a view is being destroyed and is waiting for a transaction to | ||
52 | // complete it will be stored here. | ||
53 | list_t *destroying_containers; | ||
54 | }; | 51 | }; |
55 | 52 | ||
56 | struct sway_server server; | 53 | struct sway_server server; |
diff --git a/include/sway/tree/arrange.h b/include/sway/tree/arrange.h index 58235642..d6abcc81 100644 --- a/include/sway/tree/arrange.h +++ b/include/sway/tree/arrange.h | |||
@@ -11,26 +11,8 @@ void remove_gaps(struct sway_container *c); | |||
11 | void add_gaps(struct sway_container *c); | 11 | void add_gaps(struct sway_container *c); |
12 | 12 | ||
13 | /** | 13 | /** |
14 | * Arrange layout for all the children of the given container, and add them to | 14 | * Arrange layout for all the children of the given container. |
15 | * the given transaction. | ||
16 | * | ||
17 | * Use this function if you need to arrange multiple sections of the tree in one | ||
18 | * transaction. | ||
19 | * | ||
20 | * You must set the desired state of the container before calling | ||
21 | * arrange_windows, then don't change any state-tracked properties in the | ||
22 | * container until you've called transaction_commit. | ||
23 | */ | 15 | */ |
24 | void arrange_windows(struct sway_container *container, | 16 | void arrange_windows(struct sway_container *container); |
25 | struct sway_transaction *transaction); | ||
26 | |||
27 | /** | ||
28 | * Arrange layout for the given container and commit the transaction. | ||
29 | * | ||
30 | * This function is a wrapper around arrange_windows, and handles creating and | ||
31 | * committing the transaction for you. Use this function if you're only doing | ||
32 | * one arrange operation. | ||
33 | */ | ||
34 | void arrange_and_commit(struct sway_container *container); | ||
35 | 17 | ||
36 | #endif | 18 | #endif |
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 728daa84..ca7a3288 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h | |||
@@ -68,6 +68,9 @@ struct sway_container_state { | |||
68 | struct sway_container *parent; | 68 | struct sway_container *parent; |
69 | list_t *children; | 69 | list_t *children; |
70 | 70 | ||
71 | struct sway_container *focused_inactive_child; | ||
72 | bool focused; | ||
73 | |||
71 | // View properties | 74 | // View properties |
72 | double view_x, view_y; | 75 | double view_x, view_y; |
73 | double view_width, view_height; | 76 | double view_width, view_height; |
@@ -144,6 +147,10 @@ struct sway_container { | |||
144 | 147 | ||
145 | bool destroying; | 148 | bool destroying; |
146 | 149 | ||
150 | // If true, indicates that the container has pending state that differs from | ||
151 | // the current. | ||
152 | bool dirty; | ||
153 | |||
147 | struct { | 154 | struct { |
148 | struct wl_signal destroy; | 155 | struct wl_signal destroy; |
149 | // Raised after the tree updates, but before arrange_windows | 156 | // Raised after the tree updates, but before arrange_windows |
@@ -297,4 +304,18 @@ bool container_is_floating(struct sway_container *container); | |||
297 | */ | 304 | */ |
298 | void container_get_box(struct sway_container *container, struct wlr_box *box); | 305 | void container_get_box(struct sway_container *container, struct wlr_box *box); |
299 | 306 | ||
307 | /** | ||
308 | * Move a floating container to a new layout-local position. | ||
309 | */ | ||
310 | void container_floating_move_to(struct sway_container *con, | ||
311 | double lx, double ly); | ||
312 | |||
313 | /** | ||
314 | * Mark a container as dirty if it isn't already. Dirty containers will be | ||
315 | * included in the next transaction then unmarked as dirty. | ||
316 | */ | ||
317 | void container_set_dirty(struct sway_container *container); | ||
318 | |||
319 | bool container_has_urgent_child(struct sway_container *container); | ||
320 | |||
300 | #endif | 321 | #endif |
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 7dc8ac46..e270f851 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h | |||
@@ -35,6 +35,7 @@ struct sway_view_impl { | |||
35 | void (*set_tiled)(struct sway_view *view, bool tiled); | 35 | void (*set_tiled)(struct sway_view *view, bool tiled); |
36 | void (*set_fullscreen)(struct sway_view *view, bool fullscreen); | 36 | void (*set_fullscreen)(struct sway_view *view, bool fullscreen); |
37 | bool (*wants_floating)(struct sway_view *view); | 37 | bool (*wants_floating)(struct sway_view *view); |
38 | bool (*has_client_side_decorations)(struct sway_view *view); | ||
38 | void (*for_each_surface)(struct sway_view *view, | 39 | void (*for_each_surface)(struct sway_view *view, |
39 | wlr_surface_iterator_func_t iterator, void *user_data); | 40 | wlr_surface_iterator_func_t iterator, void *user_data); |
40 | void (*close)(struct sway_view *view); | 41 | void (*close)(struct sway_view *view); |
@@ -68,6 +69,11 @@ struct sway_view { | |||
68 | bool border_bottom; | 69 | bool border_bottom; |
69 | bool border_left; | 70 | bool border_left; |
70 | bool border_right; | 71 | bool border_right; |
72 | bool using_csd; | ||
73 | |||
74 | struct timespec urgent; | ||
75 | bool allow_request_urgent; | ||
76 | struct wl_event_source *urgent_timer; | ||
71 | 77 | ||
72 | bool destroying; | 78 | bool destroying; |
73 | 79 | ||
@@ -304,4 +310,8 @@ void view_update_marks_textures(struct sway_view *view); | |||
304 | */ | 310 | */ |
305 | bool view_is_visible(struct sway_view *view); | 311 | bool view_is_visible(struct sway_view *view); |
306 | 312 | ||
313 | void view_set_urgent(struct sway_view *view, bool enable); | ||
314 | |||
315 | bool view_is_urgent(struct sway_view *view); | ||
316 | |||
307 | #endif | 317 | #endif |
diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index c72a4ac0..bc95317a 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h | |||
@@ -10,6 +10,7 @@ struct sway_workspace { | |||
10 | struct sway_view *fullscreen; | 10 | struct sway_view *fullscreen; |
11 | struct sway_container *floating; | 11 | struct sway_container *floating; |
12 | list_t *output_priority; | 12 | list_t *output_priority; |
13 | bool urgent; | ||
13 | }; | 14 | }; |
14 | 15 | ||
15 | extern char *prev_workspace_name; | 16 | extern char *prev_workspace_name; |
@@ -42,4 +43,7 @@ void workspace_output_add_priority(struct sway_container *workspace, | |||
42 | 43 | ||
43 | struct sway_container *workspace_output_get_highest_available( | 44 | struct sway_container *workspace_output_get_highest_available( |
44 | struct sway_container *ws, struct sway_container *exclude); | 45 | struct sway_container *ws, struct sway_container *exclude); |
46 | |||
47 | void workspace_detect_urgent(struct sway_container *workspace); | ||
48 | |||
45 | #endif | 49 | #endif |
diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index af478f33..f1ff25b2 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h | |||
@@ -16,11 +16,24 @@ struct swaybar_pointer { | |||
16 | int x, y; | 16 | int x, y; |
17 | }; | 17 | }; |
18 | 18 | ||
19 | enum x11_button { | ||
20 | NONE, | ||
21 | LEFT, | ||
22 | MIDDLE, | ||
23 | RIGHT, | ||
24 | SCROLL_UP, | ||
25 | SCROLL_DOWN, | ||
26 | SCROLL_LEFT, | ||
27 | SCROLL_RIGHT, | ||
28 | BACK, | ||
29 | FORWARD, | ||
30 | }; | ||
31 | |||
19 | struct swaybar_hotspot { | 32 | struct swaybar_hotspot { |
20 | struct wl_list link; | 33 | struct wl_list link; |
21 | int x, y, width, height; | 34 | int x, y, width, height; |
22 | void (*callback)(struct swaybar_output *output, | 35 | void (*callback)(struct swaybar_output *output, |
23 | int x, int y, uint32_t button, void *data); | 36 | int x, int y, enum x11_button button, void *data); |
24 | void (*destroy)(void *data); | 37 | void (*destroy)(void *data); |
25 | void *data; | 38 | void *data; |
26 | }; | 39 | }; |
diff --git a/include/swaybar/status_line.h b/include/swaybar/status_line.h index bf12a842..2eaf8140 100644 --- a/include/swaybar/status_line.h +++ b/include/swaybar/status_line.h | |||
@@ -72,7 +72,9 @@ bool status_handle_readable(struct status_line *status); | |||
72 | void status_line_free(struct status_line *status); | 72 | void status_line_free(struct status_line *status); |
73 | bool i3bar_handle_readable(struct status_line *status); | 73 | bool i3bar_handle_readable(struct status_line *status); |
74 | void i3bar_block_send_click(struct status_line *status, | 74 | void i3bar_block_send_click(struct status_line *status, |
75 | struct i3bar_block *block, int x, int y, uint32_t button); | 75 | struct i3bar_block *block, int x, int y, enum x11_button button); |
76 | void i3bar_block_free(struct i3bar_block *block); | 76 | void i3bar_block_free(struct i3bar_block *block); |
77 | enum x11_button wl_button_to_x11_button(uint32_t button); | ||
78 | enum x11_button wl_axis_to_x11_button(uint32_t axis, wl_fixed_t value); | ||
77 | 79 | ||
78 | #endif | 80 | #endif |
diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h index cf80a6ba..950cfaaf 100644 --- a/include/swaylock/swaylock.h +++ b/include/swaylock/swaylock.h | |||
@@ -19,9 +19,31 @@ enum auth_state { | |||
19 | AUTH_STATE_INVALID, | 19 | AUTH_STATE_INVALID, |
20 | }; | 20 | }; |
21 | 21 | ||
22 | struct swaylock_colorset { | ||
23 | uint32_t input; | ||
24 | uint32_t cleared; | ||
25 | uint32_t verifying; | ||
26 | uint32_t wrong; | ||
27 | }; | ||
28 | |||
29 | struct swaylock_colors { | ||
30 | uint32_t background; | ||
31 | uint32_t bs_highlight; | ||
32 | uint32_t key_highlight; | ||
33 | uint32_t separator; | ||
34 | struct swaylock_colorset inside; | ||
35 | struct swaylock_colorset line; | ||
36 | struct swaylock_colorset ring; | ||
37 | struct swaylock_colorset text; | ||
38 | }; | ||
39 | |||
22 | struct swaylock_args { | 40 | struct swaylock_args { |
23 | uint32_t color; | 41 | struct swaylock_colors colors; |
24 | enum background_mode mode; | 42 | enum background_mode mode; |
43 | char *font; | ||
44 | uint32_t radius; | ||
45 | uint32_t thickness; | ||
46 | bool ignore_empty; | ||
25 | bool show_indicator; | 47 | bool show_indicator; |
26 | bool daemonize; | 48 | bool daemonize; |
27 | }; | 49 | }; |
diff --git a/sway/commands.c b/sway/commands.c index ef477f38..a3e6a500 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -98,8 +98,11 @@ static struct cmd_handler handlers[] = { | |||
98 | { "client.unfocused", cmd_client_unfocused }, | 98 | { "client.unfocused", cmd_client_unfocused }, |
99 | { "client.urgent", cmd_client_urgent }, | 99 | { "client.urgent", cmd_client_urgent }, |
100 | { "default_border", cmd_default_border }, | 100 | { "default_border", cmd_default_border }, |
101 | { "default_floating_border", cmd_default_floating_border }, | ||
101 | { "exec", cmd_exec }, | 102 | { "exec", cmd_exec }, |
102 | { "exec_always", cmd_exec_always }, | 103 | { "exec_always", cmd_exec_always }, |
104 | { "floating_maximum_size", cmd_floating_maximum_size }, | ||
105 | { "floating_minimum_size", cmd_floating_minimum_size }, | ||
103 | { "focus_follows_mouse", cmd_focus_follows_mouse }, | 106 | { "focus_follows_mouse", cmd_focus_follows_mouse }, |
104 | { "focus_wrapping", cmd_focus_wrapping }, | 107 | { "focus_wrapping", cmd_focus_wrapping }, |
105 | { "font", cmd_font }, | 108 | { "font", cmd_font }, |
@@ -112,6 +115,7 @@ static struct cmd_handler handlers[] = { | |||
112 | { "input", cmd_input }, | 115 | { "input", cmd_input }, |
113 | { "mode", cmd_mode }, | 116 | { "mode", cmd_mode }, |
114 | { "mouse_warping", cmd_mouse_warping }, | 117 | { "mouse_warping", cmd_mouse_warping }, |
118 | { "no_focus", cmd_no_focus }, | ||
115 | { "output", cmd_output }, | 119 | { "output", cmd_output }, |
116 | { "seat", cmd_seat }, | 120 | { "seat", cmd_seat }, |
117 | { "set", cmd_set }, | 121 | { "set", cmd_set }, |
@@ -151,6 +155,7 @@ static struct cmd_handler command_handlers[] = { | |||
151 | { "swap", cmd_swap }, | 155 | { "swap", cmd_swap }, |
152 | { "title_format", cmd_title_format }, | 156 | { "title_format", cmd_title_format }, |
153 | { "unmark", cmd_unmark }, | 157 | { "unmark", cmd_unmark }, |
158 | { "urgent", cmd_urgent }, | ||
154 | }; | 159 | }; |
155 | 160 | ||
156 | static int handler_compare(const void *_a, const void *_b) { | 161 | static int handler_compare(const void *_a, const void *_b) { |
@@ -163,7 +168,7 @@ struct cmd_handler *find_handler(char *line, struct cmd_handler *cmd_handlers, | |||
163 | int handlers_size) { | 168 | int handlers_size) { |
164 | struct cmd_handler d = { .command=line }; | 169 | struct cmd_handler d = { .command=line }; |
165 | struct cmd_handler *res = NULL; | 170 | struct cmd_handler *res = NULL; |
166 | wlr_log(L_DEBUG, "find_handler(%s)", line); | 171 | wlr_log(WLR_DEBUG, "find_handler(%s)", line); |
167 | 172 | ||
168 | bool config_loading = config->reading || !config->active; | 173 | bool config_loading = config->reading || !config->active; |
169 | 174 | ||
@@ -248,10 +253,10 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) { | |||
248 | cmd = argsep(&cmdlist, ","); | 253 | cmd = argsep(&cmdlist, ","); |
249 | cmd += strspn(cmd, whitespace); | 254 | cmd += strspn(cmd, whitespace); |
250 | if (strcmp(cmd, "") == 0) { | 255 | if (strcmp(cmd, "") == 0) { |
251 | wlr_log(L_INFO, "Ignoring empty command."); | 256 | wlr_log(WLR_INFO, "Ignoring empty command."); |
252 | continue; | 257 | continue; |
253 | } | 258 | } |
254 | wlr_log(L_INFO, "Handling command '%s'", cmd); | 259 | wlr_log(WLR_INFO, "Handling command '%s'", cmd); |
255 | //TODO better handling of argv | 260 | //TODO better handling of argv |
256 | int argc; | 261 | int argc; |
257 | char **argv = split_args(cmd, &argc); | 262 | char **argv = split_args(cmd, &argc); |
@@ -344,7 +349,7 @@ struct cmd_results *config_command(char *exec) { | |||
344 | 349 | ||
345 | // Start block | 350 | // Start block |
346 | if (argc > 1 && strcmp(argv[argc - 1], "{") == 0) { | 351 | if (argc > 1 && strcmp(argv[argc - 1], "{") == 0) { |
347 | char *block = join_args(argv, argc - 1); | 352 | char *block = join_args(argv, argc - 1); |
348 | results = cmd_results_new(CMD_BLOCK, block, NULL); | 353 | results = cmd_results_new(CMD_BLOCK, block, NULL); |
349 | free(block); | 354 | free(block); |
350 | goto cleanup; | 355 | goto cleanup; |
@@ -355,7 +360,7 @@ struct cmd_results *config_command(char *exec) { | |||
355 | results = cmd_results_new(CMD_BLOCK_END, NULL, NULL); | 360 | results = cmd_results_new(CMD_BLOCK_END, NULL, NULL); |
356 | goto cleanup; | 361 | goto cleanup; |
357 | } | 362 | } |
358 | wlr_log(L_INFO, "handling config command '%s'", exec); | 363 | wlr_log(WLR_INFO, "handling config command '%s'", exec); |
359 | struct cmd_handler *handler = find_handler(argv[0], NULL, 0); | 364 | struct cmd_handler *handler = find_handler(argv[0], NULL, 0); |
360 | if (!handler) { | 365 | if (!handler) { |
361 | char *input = argv[0] ? argv[0] : "(empty)"; | 366 | char *input = argv[0] ? argv[0] : "(empty)"; |
@@ -388,7 +393,7 @@ cleanup: | |||
388 | struct cmd_results *config_subcommand(char **argv, int argc, | 393 | struct cmd_results *config_subcommand(char **argv, int argc, |
389 | struct cmd_handler *handlers, size_t handlers_size) { | 394 | struct cmd_handler *handlers, size_t handlers_size) { |
390 | char *command = join_args(argv, argc); | 395 | char *command = join_args(argv, argc); |
391 | wlr_log(L_DEBUG, "Subcommand: %s", command); | 396 | wlr_log(WLR_DEBUG, "Subcommand: %s", command); |
392 | free(command); | 397 | free(command); |
393 | 398 | ||
394 | struct cmd_handler *handler = find_handler(argv[0], handlers, | 399 | struct cmd_handler *handler = find_handler(argv[0], handlers, |
@@ -479,7 +484,7 @@ struct cmd_results *config_commands_command(char *exec) { | |||
479 | } | 484 | } |
480 | policy->context = context; | 485 | policy->context = context; |
481 | 486 | ||
482 | wlr_log(L_INFO, "Set command policy for %s to %d", | 487 | wlr_log(WLR_INFO, "Set command policy for %s to %d", |
483 | policy->command, policy->context); | 488 | policy->command, policy->context); |
484 | 489 | ||
485 | results = cmd_results_new(CMD_SUCCESS, NULL, NULL); | 490 | results = cmd_results_new(CMD_SUCCESS, NULL, NULL); |
@@ -493,7 +498,7 @@ struct cmd_results *cmd_results_new(enum cmd_status status, | |||
493 | const char *input, const char *format, ...) { | 498 | const char *input, const char *format, ...) { |
494 | struct cmd_results *results = malloc(sizeof(struct cmd_results)); | 499 | struct cmd_results *results = malloc(sizeof(struct cmd_results)); |
495 | if (!results) { | 500 | if (!results) { |
496 | wlr_log(L_ERROR, "Unable to allocate command results"); | 501 | wlr_log(WLR_ERROR, "Unable to allocate command results"); |
497 | return NULL; | 502 | return NULL; |
498 | } | 503 | } |
499 | results->status = status; | 504 | results->status = status; |
diff --git a/sway/commands/assign.c b/sway/commands/assign.c index a90498ce..0bc0929a 100644 --- a/sway/commands/assign.c +++ b/sway/commands/assign.c | |||
@@ -45,7 +45,7 @@ struct cmd_results *cmd_assign(int argc, char **argv) { | |||
45 | criteria->target = join_args(argv, target_len); | 45 | criteria->target = join_args(argv, target_len); |
46 | 46 | ||
47 | list_add(config->criteria, criteria); | 47 | list_add(config->criteria, criteria); |
48 | wlr_log(L_DEBUG, "assign: '%s' -> '%s' added", criteria->raw, | 48 | wlr_log(WLR_DEBUG, "assign: '%s' -> '%s' added", criteria->raw, |
49 | criteria->target); | 49 | criteria->target); |
50 | 50 | ||
51 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 51 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
diff --git a/sway/commands/bar.c b/sway/commands/bar.c index d84ce808..f6a70c17 100644 --- a/sway/commands/bar.c +++ b/sway/commands/bar.c | |||
@@ -63,13 +63,13 @@ struct cmd_results *cmd_bar(int argc, char **argv) { | |||
63 | for (int i = 0; i < config->bars->length; ++i) { | 63 | for (int i = 0; i < config->bars->length; ++i) { |
64 | struct bar_config *item = config->bars->items[i]; | 64 | struct bar_config *item = config->bars->items[i]; |
65 | if (strcmp(item->id, argv[0]) == 0) { | 65 | if (strcmp(item->id, argv[0]) == 0) { |
66 | wlr_log(L_DEBUG, "Selecting bar: %s", argv[0]); | 66 | wlr_log(WLR_DEBUG, "Selecting bar: %s", argv[0]); |
67 | bar = item; | 67 | bar = item; |
68 | break; | 68 | break; |
69 | } | 69 | } |
70 | } | 70 | } |
71 | if (!bar) { | 71 | if (!bar) { |
72 | wlr_log(L_DEBUG, "Creating bar: %s", argv[0]); | 72 | wlr_log(WLR_DEBUG, "Creating bar: %s", argv[0]); |
73 | bar = default_bar_config(); | 73 | bar = default_bar_config(); |
74 | if (!bar) { | 74 | if (!bar) { |
75 | return cmd_results_new(CMD_FAILURE, "bar", | 75 | return cmd_results_new(CMD_FAILURE, "bar", |
@@ -108,7 +108,7 @@ struct cmd_results *cmd_bar(int argc, char **argv) { | |||
108 | 108 | ||
109 | // Set current bar | 109 | // Set current bar |
110 | config->current_bar = bar; | 110 | config->current_bar = bar; |
111 | wlr_log(L_DEBUG, "Creating bar %s", bar->id); | 111 | wlr_log(WLR_DEBUG, "Creating bar %s", bar->id); |
112 | } | 112 | } |
113 | 113 | ||
114 | return config_subcommand(argv, argc, bar_handlers, sizeof(bar_handlers)); | 114 | return config_subcommand(argv, argc, bar_handlers, sizeof(bar_handlers)); |
diff --git a/sway/commands/bar/binding_mode_indicator.c b/sway/commands/bar/binding_mode_indicator.c index 3ba5f33f..0c48bee9 100644 --- a/sway/commands/bar/binding_mode_indicator.c +++ b/sway/commands/bar/binding_mode_indicator.c | |||
@@ -15,11 +15,11 @@ struct cmd_results *bar_cmd_binding_mode_indicator(int argc, char **argv) { | |||
15 | } | 15 | } |
16 | if (strcasecmp("yes", argv[0]) == 0) { | 16 | if (strcasecmp("yes", argv[0]) == 0) { |
17 | config->current_bar->binding_mode_indicator = true; | 17 | config->current_bar->binding_mode_indicator = true; |
18 | wlr_log(L_DEBUG, "Enabling binding mode indicator on bar: %s", | 18 | wlr_log(WLR_DEBUG, "Enabling binding mode indicator on bar: %s", |
19 | config->current_bar->id); | 19 | config->current_bar->id); |
20 | } else if (strcasecmp("no", argv[0]) == 0) { | 20 | } else if (strcasecmp("no", argv[0]) == 0) { |
21 | config->current_bar->binding_mode_indicator = false; | 21 | config->current_bar->binding_mode_indicator = false; |
22 | wlr_log(L_DEBUG, "Disabling binding mode indicator on bar: %s", | 22 | wlr_log(WLR_DEBUG, "Disabling binding mode indicator on bar: %s", |
23 | config->current_bar->id); | 23 | config->current_bar->id); |
24 | } | 24 | } |
25 | return cmd_results_new(CMD_INVALID, "binding_mode_indicator", | 25 | return cmd_results_new(CMD_INVALID, "binding_mode_indicator", |
diff --git a/sway/commands/bar/font.c b/sway/commands/bar/font.c index f036cbc3..2aa4e895 100644 --- a/sway/commands/bar/font.c +++ b/sway/commands/bar/font.c | |||
@@ -15,7 +15,7 @@ struct cmd_results *bar_cmd_font(int argc, char **argv) { | |||
15 | char *font = join_args(argv, argc); | 15 | char *font = join_args(argv, argc); |
16 | free(config->current_bar->font); | 16 | free(config->current_bar->font); |
17 | config->current_bar->font = font; | 17 | config->current_bar->font = font; |
18 | wlr_log(L_DEBUG, "Settings font '%s' for bar: %s", | 18 | wlr_log(WLR_DEBUG, "Settings font '%s' for bar: %s", |
19 | config->current_bar->font, config->current_bar->id); | 19 | config->current_bar->font, config->current_bar->id); |
20 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 20 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
21 | } | 21 | } |
diff --git a/sway/commands/bar/height.c b/sway/commands/bar/height.c index 3160caed..18258526 100644 --- a/sway/commands/bar/height.c +++ b/sway/commands/bar/height.c | |||
@@ -14,7 +14,7 @@ struct cmd_results *bar_cmd_height(int argc, char **argv) { | |||
14 | "Invalid height value: %s", argv[0]); | 14 | "Invalid height value: %s", argv[0]); |
15 | } | 15 | } |
16 | config->current_bar->height = height; | 16 | config->current_bar->height = height; |
17 | wlr_log(L_DEBUG, "Setting bar height to %d on bar: %s", | 17 | wlr_log(WLR_DEBUG, "Setting bar height to %d on bar: %s", |
18 | height, config->current_bar->id); | 18 | height, config->current_bar->id); |
19 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 19 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
20 | } | 20 | } |
diff --git a/sway/commands/bar/hidden_state.c b/sway/commands/bar/hidden_state.c index 6641f184..502ce2c4 100644 --- a/sway/commands/bar/hidden_state.c +++ b/sway/commands/bar/hidden_state.c | |||
@@ -27,7 +27,7 @@ static struct cmd_results *bar_set_hidden_state(struct bar_config *bar, | |||
27 | if (!config->reading) { | 27 | if (!config->reading) { |
28 | ipc_event_barconfig_update(bar); | 28 | ipc_event_barconfig_update(bar); |
29 | } | 29 | } |
30 | wlr_log(L_DEBUG, "Setting hidden_state: '%s' for bar: %s", | 30 | wlr_log(WLR_DEBUG, "Setting hidden_state: '%s' for bar: %s", |
31 | bar->hidden_state, bar->id); | 31 | bar->hidden_state, bar->id); |
32 | } | 32 | } |
33 | // free old mode | 33 | // free old mode |
diff --git a/sway/commands/bar/id.c b/sway/commands/bar/id.c index 6ce86fef..65fa69fd 100644 --- a/sway/commands/bar/id.c +++ b/sway/commands/bar/id.c | |||
@@ -24,7 +24,7 @@ struct cmd_results *bar_cmd_id(int argc, char **argv) { | |||
24 | } | 24 | } |
25 | } | 25 | } |
26 | 26 | ||
27 | wlr_log(L_DEBUG, "Renaming bar: '%s' to '%s'", oldname, name); | 27 | wlr_log(WLR_DEBUG, "Renaming bar: '%s' to '%s'", oldname, name); |
28 | 28 | ||
29 | // free old bar id | 29 | // free old bar id |
30 | free(config->current_bar->id); | 30 | free(config->current_bar->id); |
diff --git a/sway/commands/bar/mode.c b/sway/commands/bar/mode.c index 34bb0a4f..28e2d77b 100644 --- a/sway/commands/bar/mode.c +++ b/sway/commands/bar/mode.c | |||
@@ -28,7 +28,7 @@ static struct cmd_results *bar_set_mode(struct bar_config *bar, const char *mode | |||
28 | if (!config->reading) { | 28 | if (!config->reading) { |
29 | ipc_event_barconfig_update(bar); | 29 | ipc_event_barconfig_update(bar); |
30 | } | 30 | } |
31 | wlr_log(L_DEBUG, "Setting mode: '%s' for bar: %s", bar->mode, bar->id); | 31 | wlr_log(WLR_DEBUG, "Setting mode: '%s' for bar: %s", bar->mode, bar->id); |
32 | } | 32 | } |
33 | 33 | ||
34 | // free old mode | 34 | // free old mode |
diff --git a/sway/commands/bar/modifier.c b/sway/commands/bar/modifier.c index 02f845e6..09025fff 100644 --- a/sway/commands/bar/modifier.c +++ b/sway/commands/bar/modifier.c | |||
@@ -30,7 +30,7 @@ struct cmd_results *bar_cmd_modifier(int argc, char **argv) { | |||
30 | } | 30 | } |
31 | free_flat_list(split); | 31 | free_flat_list(split); |
32 | config->current_bar->modifier = mod; | 32 | config->current_bar->modifier = mod; |
33 | wlr_log(L_DEBUG, | 33 | wlr_log(WLR_DEBUG, |
34 | "Show/Hide the bar when pressing '%s' in hide mode.", argv[0]); | 34 | "Show/Hide the bar when pressing '%s' in hide mode.", argv[0]); |
35 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 35 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
36 | } | 36 | } |
diff --git a/sway/commands/bar/output.c b/sway/commands/bar/output.c index f7ca0aa4..72754e05 100644 --- a/sway/commands/bar/output.c +++ b/sway/commands/bar/output.c | |||
@@ -42,7 +42,7 @@ struct cmd_results *bar_cmd_output(int argc, char **argv) { | |||
42 | 42 | ||
43 | if (add_output) { | 43 | if (add_output) { |
44 | list_add(outputs, strdup(output)); | 44 | list_add(outputs, strdup(output)); |
45 | wlr_log(L_DEBUG, "Adding bar: '%s' to output '%s'", | 45 | wlr_log(WLR_DEBUG, "Adding bar: '%s' to output '%s'", |
46 | config->current_bar->id, output); | 46 | config->current_bar->id, output); |
47 | } | 47 | } |
48 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 48 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
diff --git a/sway/commands/bar/pango_markup.c b/sway/commands/bar/pango_markup.c index 480af724..857571fb 100644 --- a/sway/commands/bar/pango_markup.c +++ b/sway/commands/bar/pango_markup.c | |||
@@ -13,11 +13,11 @@ struct cmd_results *bar_cmd_pango_markup(int argc, char **argv) { | |||
13 | } | 13 | } |
14 | if (strcasecmp("enabled", argv[0]) == 0) { | 14 | if (strcasecmp("enabled", argv[0]) == 0) { |
15 | config->current_bar->pango_markup = true; | 15 | config->current_bar->pango_markup = true; |
16 | wlr_log(L_DEBUG, "Enabling pango markup for bar: %s", | 16 | wlr_log(WLR_DEBUG, "Enabling pango markup for bar: %s", |
17 | config->current_bar->id); | 17 | config->current_bar->id); |
18 | } else if (strcasecmp("disabled", argv[0]) == 0) { | 18 | } else if (strcasecmp("disabled", argv[0]) == 0) { |
19 | config->current_bar->pango_markup = false; | 19 | config->current_bar->pango_markup = false; |
20 | wlr_log(L_DEBUG, "Disabling pango markup for bar: %s", | 20 | wlr_log(WLR_DEBUG, "Disabling pango markup for bar: %s", |
21 | config->current_bar->id); | 21 | config->current_bar->id); |
22 | } else { | 22 | } else { |
23 | error = cmd_results_new(CMD_INVALID, "pango_markup", | 23 | error = cmd_results_new(CMD_INVALID, "pango_markup", |
diff --git a/sway/commands/bar/position.c b/sway/commands/bar/position.c index 9c580483..44bb4ae3 100644 --- a/sway/commands/bar/position.c +++ b/sway/commands/bar/position.c | |||
@@ -15,8 +15,9 @@ struct cmd_results *bar_cmd_position(int argc, char **argv) { | |||
15 | char *valid[] = { "top", "bottom", "left", "right" }; | 15 | char *valid[] = { "top", "bottom", "left", "right" }; |
16 | for (size_t i = 0; i < sizeof(valid) / sizeof(valid[0]); ++i) { | 16 | for (size_t i = 0; i < sizeof(valid) / sizeof(valid[0]); ++i) { |
17 | if (strcasecmp(valid[i], argv[0]) == 0) { | 17 | if (strcasecmp(valid[i], argv[0]) == 0) { |
18 | wlr_log(L_DEBUG, "Setting bar position '%s' for bar: %s", | 18 | wlr_log(WLR_DEBUG, "Setting bar position '%s' for bar: %s", |
19 | argv[0], config->current_bar->id); | 19 | argv[0], config->current_bar->id); |
20 | free(config->current_bar->position); | ||
20 | config->current_bar->position = strdup(argv[0]); | 21 | config->current_bar->position = strdup(argv[0]); |
21 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 22 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
22 | } | 23 | } |
diff --git a/sway/commands/bar/separator_symbol.c b/sway/commands/bar/separator_symbol.c index 1e08df6d..392ab730 100644 --- a/sway/commands/bar/separator_symbol.c +++ b/sway/commands/bar/separator_symbol.c | |||
@@ -14,7 +14,7 @@ struct cmd_results *bar_cmd_separator_symbol(int argc, char **argv) { | |||
14 | } | 14 | } |
15 | free(config->current_bar->separator_symbol); | 15 | free(config->current_bar->separator_symbol); |
16 | config->current_bar->separator_symbol = strdup(argv[0]); | 16 | config->current_bar->separator_symbol = strdup(argv[0]); |
17 | wlr_log(L_DEBUG, "Settings separator_symbol '%s' for bar: %s", | 17 | wlr_log(WLR_DEBUG, "Settings separator_symbol '%s' for bar: %s", |
18 | config->current_bar->separator_symbol, config->current_bar->id); | 18 | config->current_bar->separator_symbol, config->current_bar->id); |
19 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 19 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
20 | } | 20 | } |
diff --git a/sway/commands/bar/status_command.c b/sway/commands/bar/status_command.c index 5e199cde..6f6f81a3 100644 --- a/sway/commands/bar/status_command.c +++ b/sway/commands/bar/status_command.c | |||
@@ -14,7 +14,7 @@ struct cmd_results *bar_cmd_status_command(int argc, char **argv) { | |||
14 | } | 14 | } |
15 | free(config->current_bar->status_command); | 15 | free(config->current_bar->status_command); |
16 | config->current_bar->status_command = join_args(argv, argc); | 16 | config->current_bar->status_command = join_args(argv, argc); |
17 | wlr_log(L_DEBUG, "Feeding bar with status command: %s", | 17 | wlr_log(WLR_DEBUG, "Feeding bar with status command: %s", |
18 | config->current_bar->status_command); | 18 | config->current_bar->status_command); |
19 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 19 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
20 | } | 20 | } |
diff --git a/sway/commands/bar/strip_workspace_numbers.c b/sway/commands/bar/strip_workspace_numbers.c index 4f24a356..4e47d047 100644 --- a/sway/commands/bar/strip_workspace_numbers.c +++ b/sway/commands/bar/strip_workspace_numbers.c | |||
@@ -15,11 +15,11 @@ struct cmd_results *bar_cmd_strip_workspace_numbers(int argc, char **argv) { | |||
15 | } | 15 | } |
16 | if (strcasecmp("yes", argv[0]) == 0) { | 16 | if (strcasecmp("yes", argv[0]) == 0) { |
17 | config->current_bar->strip_workspace_numbers = true; | 17 | config->current_bar->strip_workspace_numbers = true; |
18 | wlr_log(L_DEBUG, "Stripping workspace numbers on bar: %s", | 18 | wlr_log(WLR_DEBUG, "Stripping workspace numbers on bar: %s", |
19 | config->current_bar->id); | 19 | config->current_bar->id); |
20 | } else if (strcasecmp("no", argv[0]) == 0) { | 20 | } else if (strcasecmp("no", argv[0]) == 0) { |
21 | config->current_bar->strip_workspace_numbers = false; | 21 | config->current_bar->strip_workspace_numbers = false; |
22 | wlr_log(L_DEBUG, "Enabling workspace numbers on bar: %s", | 22 | wlr_log(WLR_DEBUG, "Enabling workspace numbers on bar: %s", |
23 | config->current_bar->id); | 23 | config->current_bar->id); |
24 | } else { | 24 | } else { |
25 | return cmd_results_new(CMD_INVALID, | 25 | return cmd_results_new(CMD_INVALID, |
diff --git a/sway/commands/bar/swaybar_command.c b/sway/commands/bar/swaybar_command.c index 520cdd11..04e78e77 100644 --- a/sway/commands/bar/swaybar_command.c +++ b/sway/commands/bar/swaybar_command.c | |||
@@ -14,7 +14,7 @@ struct cmd_results *bar_cmd_swaybar_command(int argc, char **argv) { | |||
14 | } | 14 | } |
15 | free(config->current_bar->swaybar_command); | 15 | free(config->current_bar->swaybar_command); |
16 | config->current_bar->swaybar_command = join_args(argv, argc); | 16 | config->current_bar->swaybar_command = join_args(argv, argc); |
17 | wlr_log(L_DEBUG, "Using custom swaybar command: %s", | 17 | wlr_log(WLR_DEBUG, "Using custom swaybar command: %s", |
18 | config->current_bar->swaybar_command); | 18 | config->current_bar->swaybar_command); |
19 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 19 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
20 | } | 20 | } |
diff --git a/sway/commands/bar/workspace_buttons.c b/sway/commands/bar/workspace_buttons.c index 6edc3a0d..a4079b2a 100644 --- a/sway/commands/bar/workspace_buttons.c +++ b/sway/commands/bar/workspace_buttons.c | |||
@@ -14,11 +14,11 @@ struct cmd_results *bar_cmd_workspace_buttons(int argc, char **argv) { | |||
14 | } | 14 | } |
15 | if (strcasecmp("yes", argv[0]) == 0) { | 15 | if (strcasecmp("yes", argv[0]) == 0) { |
16 | config->current_bar->workspace_buttons = true; | 16 | config->current_bar->workspace_buttons = true; |
17 | wlr_log(L_DEBUG, "Enabling workspace buttons on bar: %s", | 17 | wlr_log(WLR_DEBUG, "Enabling workspace buttons on bar: %s", |
18 | config->current_bar->id); | 18 | config->current_bar->id); |
19 | } else if (strcasecmp("no", argv[0]) == 0) { | 19 | } else if (strcasecmp("no", argv[0]) == 0) { |
20 | config->current_bar->workspace_buttons = false; | 20 | config->current_bar->workspace_buttons = false; |
21 | wlr_log(L_DEBUG, "Disabling workspace buttons on bar: %s", | 21 | wlr_log(WLR_DEBUG, "Disabling workspace buttons on bar: %s", |
22 | config->current_bar->id); | 22 | config->current_bar->id); |
23 | } else { | 23 | } else { |
24 | return cmd_results_new(CMD_INVALID, "workspace_buttons", | 24 | return cmd_results_new(CMD_INVALID, "workspace_buttons", |
diff --git a/sway/commands/bar/wrap_scroll.c b/sway/commands/bar/wrap_scroll.c index 7386f82c..701de00a 100644 --- a/sway/commands/bar/wrap_scroll.c +++ b/sway/commands/bar/wrap_scroll.c | |||
@@ -13,11 +13,11 @@ struct cmd_results *bar_cmd_wrap_scroll(int argc, char **argv) { | |||
13 | } | 13 | } |
14 | if (strcasecmp("yes", argv[0]) == 0) { | 14 | if (strcasecmp("yes", argv[0]) == 0) { |
15 | config->current_bar->wrap_scroll = true; | 15 | config->current_bar->wrap_scroll = true; |
16 | wlr_log(L_DEBUG, "Enabling wrap scroll on bar: %s", | 16 | wlr_log(WLR_DEBUG, "Enabling wrap scroll on bar: %s", |
17 | config->current_bar->id); | 17 | config->current_bar->id); |
18 | } else if (strcasecmp("no", argv[0]) == 0) { | 18 | } else if (strcasecmp("no", argv[0]) == 0) { |
19 | config->current_bar->wrap_scroll = false; | 19 | config->current_bar->wrap_scroll = false; |
20 | wlr_log(L_DEBUG, "Disabling wrap scroll on bar: %s", | 20 | wlr_log(WLR_DEBUG, "Disabling wrap scroll on bar: %s", |
21 | config->current_bar->id); | 21 | config->current_bar->id); |
22 | } else { | 22 | } else { |
23 | return cmd_results_new(CMD_INVALID, | 23 | return cmd_results_new(CMD_INVALID, |
diff --git a/sway/commands/bind.c b/sway/commands/bind.c index 821f9cd1..83e9e432 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c | |||
@@ -184,7 +184,7 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv, | |||
184 | for (int i = 0; i < mode_bindings->length; ++i) { | 184 | for (int i = 0; i < mode_bindings->length; ++i) { |
185 | struct sway_binding *config_binding = mode_bindings->items[i]; | 185 | struct sway_binding *config_binding = mode_bindings->items[i]; |
186 | if (binding_key_compare(binding, config_binding)) { | 186 | if (binding_key_compare(binding, config_binding)) { |
187 | wlr_log(L_DEBUG, "overwriting old binding with command '%s'", | 187 | wlr_log(WLR_DEBUG, "overwriting old binding with command '%s'", |
188 | config_binding->command); | 188 | config_binding->command); |
189 | free_sway_binding(config_binding); | 189 | free_sway_binding(config_binding); |
190 | mode_bindings->items[i] = binding; | 190 | mode_bindings->items[i] = binding; |
@@ -196,7 +196,7 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv, | |||
196 | list_add(mode_bindings, binding); | 196 | list_add(mode_bindings, binding); |
197 | } | 197 | } |
198 | 198 | ||
199 | wlr_log(L_DEBUG, "%s - Bound %s to command %s", | 199 | wlr_log(WLR_DEBUG, "%s - Bound %s to command %s", |
200 | bindtype, argv[0], binding->command); | 200 | bindtype, argv[0], binding->command); |
201 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 201 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
202 | 202 | ||
diff --git a/sway/commands/border.c b/sway/commands/border.c index 6db85395..9c19e20a 100644 --- a/sway/commands/border.c +++ b/sway/commands/border.c | |||
@@ -42,7 +42,7 @@ struct cmd_results *cmd_border(int argc, char **argv) { | |||
42 | container_set_geometry_from_floating_view(view->swayc); | 42 | container_set_geometry_from_floating_view(view->swayc); |
43 | } | 43 | } |
44 | 44 | ||
45 | arrange_and_commit(view->swayc); | 45 | arrange_windows(view->swayc); |
46 | 46 | ||
47 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 47 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
48 | if (seat->cursor) { | 48 | if (seat->cursor) { |
diff --git a/sway/commands/default_floating_border.c b/sway/commands/default_floating_border.c new file mode 100644 index 00000000..1bfc24af --- /dev/null +++ b/sway/commands/default_floating_border.c | |||
@@ -0,0 +1,29 @@ | |||
1 | #include "log.h" | ||
2 | #include "sway/commands.h" | ||
3 | #include "sway/config.h" | ||
4 | #include "sway/tree/container.h" | ||
5 | |||
6 | struct cmd_results *cmd_default_floating_border(int argc, char **argv) { | ||
7 | struct cmd_results *error = NULL; | ||
8 | if ((error = checkarg(argc, "default_floating_border", | ||
9 | EXPECTED_AT_LEAST, 1))) { | ||
10 | return error; | ||
11 | } | ||
12 | |||
13 | if (strcmp(argv[0], "none") == 0) { | ||
14 | config->floating_border = B_NONE; | ||
15 | } else if (strcmp(argv[0], "normal") == 0) { | ||
16 | config->floating_border = B_NORMAL; | ||
17 | } else if (strcmp(argv[0], "pixel") == 0) { | ||
18 | config->floating_border = B_PIXEL; | ||
19 | } else { | ||
20 | return cmd_results_new(CMD_INVALID, "default_floating_border", | ||
21 | "Expected 'default_floating_border <none|normal|pixel>' " | ||
22 | "or 'default_floating_border <normal|pixel> <px>'"); | ||
23 | } | ||
24 | if (argc == 2) { | ||
25 | config->floating_border_thickness = atoi(argv[1]); | ||
26 | } | ||
27 | |||
28 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
29 | } | ||
diff --git a/sway/commands/exec.c b/sway/commands/exec.c index 363d5bef..7fc54123 100644 --- a/sway/commands/exec.c +++ b/sway/commands/exec.c | |||
@@ -8,7 +8,7 @@ struct cmd_results *cmd_exec(int argc, char **argv) { | |||
8 | if (!config->active) return cmd_results_new(CMD_DEFER, "exec", NULL); | 8 | if (!config->active) return cmd_results_new(CMD_DEFER, "exec", NULL); |
9 | if (config->reloading) { | 9 | if (config->reloading) { |
10 | char *args = join_args(argv, argc); | 10 | char *args = join_args(argv, argc); |
11 | wlr_log(L_DEBUG, "Ignoring 'exec %s' due to reload", args); | 11 | wlr_log(WLR_DEBUG, "Ignoring 'exec %s' due to reload", args); |
12 | free(args); | 12 | free(args); |
13 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 13 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
14 | } | 14 | } |
diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index 1c99de97..c7727857 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c | |||
@@ -20,7 +20,7 @@ struct cmd_results *cmd_exec_always(int argc, char **argv) { | |||
20 | 20 | ||
21 | char *tmp = NULL; | 21 | char *tmp = NULL; |
22 | if (strcmp((char*)*argv, "--no-startup-id") == 0) { | 22 | if (strcmp((char*)*argv, "--no-startup-id") == 0) { |
23 | wlr_log(L_INFO, "exec switch '--no-startup-id' not supported, ignored."); | 23 | wlr_log(WLR_INFO, "exec switch '--no-startup-id' not supported, ignored."); |
24 | if ((error = checkarg(argc - 1, "exec_always", EXPECTED_MORE_THAN, 0))) { | 24 | if ((error = checkarg(argc - 1, "exec_always", EXPECTED_MORE_THAN, 0))) { |
25 | return error; | 25 | return error; |
26 | } | 26 | } |
@@ -35,11 +35,11 @@ struct cmd_results *cmd_exec_always(int argc, char **argv) { | |||
35 | strncpy(cmd, tmp, sizeof(cmd) - 1); | 35 | strncpy(cmd, tmp, sizeof(cmd) - 1); |
36 | cmd[sizeof(cmd) - 1] = 0; | 36 | cmd[sizeof(cmd) - 1] = 0; |
37 | free(tmp); | 37 | free(tmp); |
38 | wlr_log(L_DEBUG, "Executing %s", cmd); | 38 | wlr_log(WLR_DEBUG, "Executing %s", cmd); |
39 | 39 | ||
40 | int fd[2]; | 40 | int fd[2]; |
41 | if (pipe(fd) != 0) { | 41 | if (pipe(fd) != 0) { |
42 | wlr_log(L_ERROR, "Unable to create pipe for fork"); | 42 | wlr_log(WLR_ERROR, "Unable to create pipe for fork"); |
43 | } | 43 | } |
44 | 44 | ||
45 | pid_t pid, child; | 45 | pid_t pid, child; |
@@ -73,7 +73,7 @@ struct cmd_results *cmd_exec_always(int argc, char **argv) { | |||
73 | // cleanup child process | 73 | // cleanup child process |
74 | waitpid(pid, NULL, 0); | 74 | waitpid(pid, NULL, 0); |
75 | if (child > 0) { | 75 | if (child > 0) { |
76 | wlr_log(L_DEBUG, "Child process created with pid %d", child); | 76 | wlr_log(WLR_DEBUG, "Child process created with pid %d", child); |
77 | // TODO: add PID to active workspace | 77 | // TODO: add PID to active workspace |
78 | } else { | 78 | } else { |
79 | return cmd_results_new(CMD_FAILURE, "exec_always", | 79 | return cmd_results_new(CMD_FAILURE, "exec_always", |
diff --git a/sway/commands/floating.c b/sway/commands/floating.c index e6003521..6ab56c3b 100644 --- a/sway/commands/floating.c +++ b/sway/commands/floating.c | |||
@@ -37,7 +37,7 @@ struct cmd_results *cmd_floating(int argc, char **argv) { | |||
37 | container_set_floating(container, wants_floating); | 37 | container_set_floating(container, wants_floating); |
38 | 38 | ||
39 | struct sway_container *workspace = container_parent(container, C_WORKSPACE); | 39 | struct sway_container *workspace = container_parent(container, C_WORKSPACE); |
40 | arrange_and_commit(workspace); | 40 | arrange_windows(workspace); |
41 | 41 | ||
42 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 42 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
43 | } | 43 | } |
diff --git a/sway/commands/floating_minmax_size.c b/sway/commands/floating_minmax_size.c new file mode 100644 index 00000000..0af78908 --- /dev/null +++ b/sway/commands/floating_minmax_size.c | |||
@@ -0,0 +1,53 @@ | |||
1 | #include <errno.h> | ||
2 | #include <math.h> | ||
3 | #include <stdbool.h> | ||
4 | #include <stdlib.h> | ||
5 | #include <string.h> | ||
6 | #include <strings.h> | ||
7 | #include <wlr/util/log.h> | ||
8 | #include "sway/commands.h" | ||
9 | #include "log.h" | ||
10 | |||
11 | static const char* min_usage = | ||
12 | "Expected 'floating_minimum_size <width> x <height>'"; | ||
13 | |||
14 | static const char* max_usage = | ||
15 | "Expected 'floating_maximum_size <width> x <height>'"; | ||
16 | |||
17 | static struct cmd_results *handle_command(int argc, char **argv, char *cmd_name, | ||
18 | const char *usage, int *config_width, int *config_height) { | ||
19 | struct cmd_results *error; | ||
20 | if ((error = checkarg(argc, cmd_name, EXPECTED_EQUAL_TO, 3))) { | ||
21 | return error; | ||
22 | } | ||
23 | |||
24 | char *err; | ||
25 | int width = (int)strtol(argv[0], &err, 10); | ||
26 | if (*err) { | ||
27 | return cmd_results_new(CMD_INVALID, cmd_name, usage); | ||
28 | } | ||
29 | |||
30 | if (strcmp(argv[1], "x") != 0) { | ||
31 | return cmd_results_new(CMD_INVALID, cmd_name, usage); | ||
32 | } | ||
33 | |||
34 | int height = (int)strtol(argv[2], &err, 10); | ||
35 | if (*err) { | ||
36 | return cmd_results_new(CMD_INVALID, cmd_name, usage); | ||
37 | } | ||
38 | |||
39 | *config_width = width; | ||
40 | *config_height = height; | ||
41 | |||
42 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
43 | } | ||
44 | |||
45 | struct cmd_results *cmd_floating_minimum_size(int argc, char **argv) { | ||
46 | return handle_command(argc, argv, "floating_minimum_size", min_usage, | ||
47 | &config->floating_minimum_width, &config->floating_minimum_height); | ||
48 | } | ||
49 | |||
50 | struct cmd_results *cmd_floating_maximum_size(int argc, char **argv) { | ||
51 | return handle_command(argc, argv, "floating_maximum_size", max_usage, | ||
52 | &config->floating_maximum_width, &config->floating_maximum_height); | ||
53 | } | ||
diff --git a/sway/commands/focus.c b/sway/commands/focus.c index 74d9d535..b24d5007 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c | |||
@@ -1,10 +1,12 @@ | |||
1 | #include <strings.h> | 1 | #include <strings.h> |
2 | #include <wlr/util/log.h> | 2 | #include <wlr/util/log.h> |
3 | #include "log.h" | 3 | #include "log.h" |
4 | #include "sway/commands.h" | ||
4 | #include "sway/input/input-manager.h" | 5 | #include "sway/input/input-manager.h" |
5 | #include "sway/input/seat.h" | 6 | #include "sway/input/seat.h" |
7 | #include "sway/tree/arrange.h" | ||
6 | #include "sway/tree/view.h" | 8 | #include "sway/tree/view.h" |
7 | #include "sway/commands.h" | 9 | #include "sway/tree/workspace.h" |
8 | 10 | ||
9 | static bool parse_movement_direction(const char *name, | 11 | static bool parse_movement_direction(const char *name, |
10 | enum movement_direction *out) { | 12 | enum movement_direction *out) { |
@@ -27,6 +29,21 @@ static bool parse_movement_direction(const char *name, | |||
27 | return true; | 29 | return true; |
28 | } | 30 | } |
29 | 31 | ||
32 | static struct cmd_results *focus_mode(struct sway_container *con, | ||
33 | struct sway_seat *seat, bool floating) { | ||
34 | struct sway_container *ws = con->type == C_WORKSPACE ? | ||
35 | con : container_parent(con, C_WORKSPACE); | ||
36 | struct sway_container *new_focus = ws; | ||
37 | if (floating) { | ||
38 | new_focus = ws->sway_workspace->floating; | ||
39 | if (new_focus->children->length == 0) { | ||
40 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
41 | } | ||
42 | } | ||
43 | seat_set_focus(seat, seat_get_active_child(seat, new_focus)); | ||
44 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
45 | } | ||
46 | |||
30 | struct cmd_results *cmd_focus(int argc, char **argv) { | 47 | struct cmd_results *cmd_focus(int argc, char **argv) { |
31 | struct sway_container *con = config->handler_context.current_container; | 48 | struct sway_container *con = config->handler_context.current_container; |
32 | struct sway_seat *seat = config->handler_context.seat; | 49 | struct sway_seat *seat = config->handler_context.seat; |
@@ -40,11 +57,20 @@ struct cmd_results *cmd_focus(int argc, char **argv) { | |||
40 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 57 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
41 | } | 58 | } |
42 | 59 | ||
43 | // TODO mode_toggle | 60 | if (strcmp(argv[0], "floating") == 0) { |
61 | return focus_mode(con, seat, true); | ||
62 | } else if (strcmp(argv[0], "tiling") == 0) { | ||
63 | return focus_mode(con, seat, false); | ||
64 | } else if (strcmp(argv[0], "mode_toggle") == 0) { | ||
65 | return focus_mode(con, seat, !container_is_floating(con)); | ||
66 | } | ||
67 | |||
68 | // TODO: focus output <direction|name> | ||
44 | enum movement_direction direction = 0; | 69 | enum movement_direction direction = 0; |
45 | if (!parse_movement_direction(argv[0], &direction)) { | 70 | if (!parse_movement_direction(argv[0], &direction)) { |
46 | return cmd_results_new(CMD_INVALID, "focus", | 71 | return cmd_results_new(CMD_INVALID, "focus", |
47 | "Expected 'focus <direction|parent|child|mode_toggle>' or 'focus output <direction|name>'"); | 72 | "Expected 'focus <direction|parent|child|mode_toggle|floating|tiling>' " |
73 | "or 'focus output <direction|name>'"); | ||
48 | } | 74 | } |
49 | 75 | ||
50 | struct sway_container *next_focus = container_get_in_direction( | 76 | struct sway_container *next_focus = container_get_in_direction( |
diff --git a/sway/commands/for_window.c b/sway/commands/for_window.c index 8c425a1d..ac4d6563 100644 --- a/sway/commands/for_window.c +++ b/sway/commands/for_window.c | |||
@@ -24,7 +24,7 @@ struct cmd_results *cmd_for_window(int argc, char **argv) { | |||
24 | criteria->cmdlist = join_args(argv + 1, argc - 1); | 24 | criteria->cmdlist = join_args(argv + 1, argc - 1); |
25 | 25 | ||
26 | list_add(config->criteria, criteria); | 26 | list_add(config->criteria, criteria); |
27 | wlr_log(L_DEBUG, "for_window: '%s' -> '%s' added", criteria->raw, criteria->cmdlist); | 27 | wlr_log(WLR_DEBUG, "for_window: '%s' -> '%s' added", criteria->raw, criteria->cmdlist); |
28 | 28 | ||
29 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 29 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
30 | } | 30 | } |
diff --git a/sway/commands/fullscreen.c b/sway/commands/fullscreen.c index 1a4d8b41..0b5beaa2 100644 --- a/sway/commands/fullscreen.c +++ b/sway/commands/fullscreen.c | |||
@@ -34,7 +34,7 @@ struct cmd_results *cmd_fullscreen(int argc, char **argv) { | |||
34 | view_set_fullscreen(view, wants_fullscreen); | 34 | view_set_fullscreen(view, wants_fullscreen); |
35 | 35 | ||
36 | struct sway_container *workspace = container_parent(container, C_WORKSPACE); | 36 | struct sway_container *workspace = container_parent(container, C_WORKSPACE); |
37 | arrange_and_commit(workspace->parent); | 37 | arrange_windows(workspace->parent); |
38 | 38 | ||
39 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 39 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
40 | } | 40 | } |
diff --git a/sway/commands/gaps.c b/sway/commands/gaps.c index 801fb179..3906eb70 100644 --- a/sway/commands/gaps.c +++ b/sway/commands/gaps.c | |||
@@ -43,7 +43,7 @@ struct cmd_results *cmd_gaps(int argc, char **argv) { | |||
43 | return cmd_results_new(CMD_INVALID, "gaps", | 43 | return cmd_results_new(CMD_INVALID, "gaps", |
44 | "gaps edge_gaps on|off|toggle"); | 44 | "gaps edge_gaps on|off|toggle"); |
45 | } | 45 | } |
46 | arrange_and_commit(&root_container); | 46 | arrange_windows(&root_container); |
47 | } else { | 47 | } else { |
48 | int amount_idx = 0; // the current index in argv | 48 | int amount_idx = 0; // the current index in argv |
49 | enum gaps_op op = GAPS_OP_SET; | 49 | enum gaps_op op = GAPS_OP_SET; |
@@ -124,7 +124,7 @@ struct cmd_results *cmd_gaps(int argc, char **argv) { | |||
124 | if (amount_idx == 0) { // gaps <amount> | 124 | if (amount_idx == 0) { // gaps <amount> |
125 | config->gaps_inner = val; | 125 | config->gaps_inner = val; |
126 | config->gaps_outer = val; | 126 | config->gaps_outer = val; |
127 | arrange_and_commit(&root_container); | 127 | arrange_windows(&root_container); |
128 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 128 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
129 | } | 129 | } |
130 | // Other variants. The middle-length variant (gaps inner|outer <amount>) | 130 | // Other variants. The middle-length variant (gaps inner|outer <amount>) |
@@ -155,7 +155,7 @@ struct cmd_results *cmd_gaps(int argc, char **argv) { | |||
155 | } else { | 155 | } else { |
156 | config->gaps_outer = total; | 156 | config->gaps_outer = total; |
157 | } | 157 | } |
158 | arrange_and_commit(&root_container); | 158 | arrange_windows(&root_container); |
159 | } else { | 159 | } else { |
160 | struct sway_container *c = | 160 | struct sway_container *c = |
161 | config->handler_context.current_container; | 161 | config->handler_context.current_container; |
@@ -169,7 +169,7 @@ struct cmd_results *cmd_gaps(int argc, char **argv) { | |||
169 | c->gaps_outer = total; | 169 | c->gaps_outer = total; |
170 | } | 170 | } |
171 | 171 | ||
172 | arrange_and_commit(c->parent ? c->parent : &root_container); | 172 | arrange_windows(c->parent ? c->parent : &root_container); |
173 | } | 173 | } |
174 | } | 174 | } |
175 | 175 | ||
diff --git a/sway/commands/input.c b/sway/commands/input.c index 678c57c4..5b203ea0 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c | |||
@@ -20,8 +20,10 @@ static struct cmd_handler input_handlers[] = { | |||
20 | { "pointer_accel", input_cmd_pointer_accel }, | 20 | { "pointer_accel", input_cmd_pointer_accel }, |
21 | { "repeat_delay", input_cmd_repeat_delay }, | 21 | { "repeat_delay", input_cmd_repeat_delay }, |
22 | { "repeat_rate", input_cmd_repeat_rate }, | 22 | { "repeat_rate", input_cmd_repeat_rate }, |
23 | { "scroll_button", input_cmd_scroll_button }, | ||
23 | { "scroll_method", input_cmd_scroll_method }, | 24 | { "scroll_method", input_cmd_scroll_method }, |
24 | { "tap", input_cmd_tap }, | 25 | { "tap", input_cmd_tap }, |
26 | { "tap_button_map", input_cmd_tap_button_map }, | ||
25 | { "xkb_layout", input_cmd_xkb_layout }, | 27 | { "xkb_layout", input_cmd_xkb_layout }, |
26 | { "xkb_model", input_cmd_xkb_model }, | 28 | { "xkb_model", input_cmd_xkb_model }, |
27 | { "xkb_options", input_cmd_xkb_options }, | 29 | { "xkb_options", input_cmd_xkb_options }, |
@@ -35,7 +37,7 @@ struct cmd_results *cmd_input(int argc, char **argv) { | |||
35 | return error; | 37 | return error; |
36 | } | 38 | } |
37 | 39 | ||
38 | wlr_log(L_DEBUG, "entering input block: %s", argv[0]); | 40 | wlr_log(WLR_DEBUG, "entering input block: %s", argv[0]); |
39 | 41 | ||
40 | config->handler_context.input_config = new_input_config(argv[0]); | 42 | config->handler_context.input_config = new_input_config(argv[0]); |
41 | if (!config->handler_context.input_config) { | 43 | if (!config->handler_context.input_config) { |
diff --git a/sway/commands/input/events.c b/sway/commands/input/events.c index e2ccdc94..abfe3b12 100644 --- a/sway/commands/input/events.c +++ b/sway/commands/input/events.c | |||
@@ -16,7 +16,7 @@ struct cmd_results *input_cmd_events(int argc, char **argv) { | |||
16 | return cmd_results_new(CMD_FAILURE, "events", | 16 | return cmd_results_new(CMD_FAILURE, "events", |
17 | "No input device defined."); | 17 | "No input device defined."); |
18 | } | 18 | } |
19 | wlr_log(L_DEBUG, "events for device: %s", | 19 | wlr_log(WLR_DEBUG, "events for device: %s", |
20 | current_input_config->identifier); | 20 | current_input_config->identifier); |
21 | struct input_config *new_config = | 21 | struct input_config *new_config = |
22 | new_input_config(current_input_config->identifier); | 22 | new_input_config(current_input_config->identifier); |
diff --git a/sway/commands/input/scroll_button.c b/sway/commands/input/scroll_button.c new file mode 100644 index 00000000..350fcca2 --- /dev/null +++ b/sway/commands/input/scroll_button.c | |||
@@ -0,0 +1,44 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include <errno.h> | ||
4 | #include "sway/config.h" | ||
5 | #include "sway/commands.h" | ||
6 | #include "sway/input/input-manager.h" | ||
7 | |||
8 | struct cmd_results *input_cmd_scroll_button(int argc, char **argv) { | ||
9 | struct cmd_results *error = NULL; | ||
10 | if ((error = checkarg(argc, "scroll_button", EXPECTED_AT_LEAST, 1))) { | ||
11 | return error; | ||
12 | } | ||
13 | struct input_config *current_input_config = | ||
14 | config->handler_context.input_config; | ||
15 | if (!current_input_config) { | ||
16 | return cmd_results_new(CMD_FAILURE, "scroll_button", | ||
17 | "No input device defined."); | ||
18 | } | ||
19 | struct input_config *new_config = | ||
20 | new_input_config(current_input_config->identifier); | ||
21 | |||
22 | errno = 0; | ||
23 | char *endptr; | ||
24 | int scroll_button = strtol(*argv, &endptr, 10); | ||
25 | if (endptr == *argv && scroll_button == 0) { | ||
26 | free_input_config(new_config); | ||
27 | return cmd_results_new(CMD_INVALID, "scroll_button", | ||
28 | "Scroll button identifier must be an integer."); | ||
29 | } | ||
30 | if (errno == ERANGE) { | ||
31 | free_input_config(new_config); | ||
32 | return cmd_results_new(CMD_INVALID, "scroll_button", | ||
33 | "Scroll button identifier out of range."); | ||
34 | } | ||
35 | if (scroll_button < 0) { | ||
36 | free_input_config(new_config); | ||
37 | return cmd_results_new(CMD_INVALID, "scroll_button", | ||
38 | "Scroll button identifier cannot be negative."); | ||
39 | } | ||
40 | new_config->scroll_button = scroll_button; | ||
41 | |||
42 | apply_input_config(new_config); | ||
43 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
44 | } | ||
diff --git a/sway/commands/input/tap.c b/sway/commands/input/tap.c index 7d027d5d..a8d1a10c 100644 --- a/sway/commands/input/tap.c +++ b/sway/commands/input/tap.c | |||
@@ -28,7 +28,7 @@ struct cmd_results *input_cmd_tap(int argc, char **argv) { | |||
28 | "Expected 'tap <enabled|disabled>'"); | 28 | "Expected 'tap <enabled|disabled>'"); |
29 | } | 29 | } |
30 | 30 | ||
31 | wlr_log(L_DEBUG, "apply-tap for device: %s", | 31 | wlr_log(WLR_DEBUG, "apply-tap for device: %s", |
32 | current_input_config->identifier); | 32 | current_input_config->identifier); |
33 | apply_input_config(new_config); | 33 | apply_input_config(new_config); |
34 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 34 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
diff --git a/sway/commands/input/tap_button_map.c b/sway/commands/input/tap_button_map.c new file mode 100644 index 00000000..bdbba472 --- /dev/null +++ b/sway/commands/input/tap_button_map.c | |||
@@ -0,0 +1,33 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/config.h" | ||
4 | #include "sway/commands.h" | ||
5 | #include "sway/input/input-manager.h" | ||
6 | |||
7 | struct cmd_results *input_cmd_tap_button_map(int argc, char **argv) { | ||
8 | struct cmd_results *error = NULL; | ||
9 | if ((error = checkarg(argc, "tap_button_map", EXPECTED_AT_LEAST, 1))) { | ||
10 | return error; | ||
11 | } | ||
12 | struct input_config *current_input_config = | ||
13 | config->handler_context.input_config; | ||
14 | if (!current_input_config) { | ||
15 | return cmd_results_new(CMD_FAILURE, "tap_button_map", | ||
16 | "No input device defined."); | ||
17 | } | ||
18 | struct input_config *new_config = | ||
19 | new_input_config(current_input_config->identifier); | ||
20 | |||
21 | if (strcasecmp(argv[0], "lrm") == 0) { | ||
22 | new_config->tap_button_map = LIBINPUT_CONFIG_TAP_MAP_LRM; | ||
23 | } else if (strcasecmp(argv[0], "lmr") == 0) { | ||
24 | new_config->tap_button_map = LIBINPUT_CONFIG_TAP_MAP_LMR; | ||
25 | } else { | ||
26 | free_input_config(new_config); | ||
27 | return cmd_results_new(CMD_INVALID, "tap_button_map", | ||
28 | "Expected 'tap_button_map <lrm|lmr>'"); | ||
29 | } | ||
30 | |||
31 | apply_input_config(new_config); | ||
32 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
33 | } | ||
diff --git a/sway/commands/input/xkb_layout.c b/sway/commands/input/xkb_layout.c index 867e65d3..9fa5a344 100644 --- a/sway/commands/input/xkb_layout.c +++ b/sway/commands/input/xkb_layout.c | |||
@@ -19,7 +19,7 @@ struct cmd_results *input_cmd_xkb_layout(int argc, char **argv) { | |||
19 | 19 | ||
20 | new_config->xkb_layout = strdup(argv[0]); | 20 | new_config->xkb_layout = strdup(argv[0]); |
21 | 21 | ||
22 | wlr_log(L_DEBUG, "apply-xkb_layout for device: %s layout: %s", | 22 | wlr_log(WLR_DEBUG, "apply-xkb_layout for device: %s layout: %s", |
23 | current_input_config->identifier, new_config->xkb_layout); | 23 | current_input_config->identifier, new_config->xkb_layout); |
24 | apply_input_config(new_config); | 24 | apply_input_config(new_config); |
25 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 25 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
diff --git a/sway/commands/input/xkb_model.c b/sway/commands/input/xkb_model.c index e8c8e04e..0d082625 100644 --- a/sway/commands/input/xkb_model.c +++ b/sway/commands/input/xkb_model.c | |||
@@ -19,7 +19,7 @@ struct cmd_results *input_cmd_xkb_model(int argc, char **argv) { | |||
19 | 19 | ||
20 | new_config->xkb_model = strdup(argv[0]); | 20 | new_config->xkb_model = strdup(argv[0]); |
21 | 21 | ||
22 | wlr_log(L_DEBUG, "apply-xkb_model for device: %s model: %s", | 22 | wlr_log(WLR_DEBUG, "apply-xkb_model for device: %s model: %s", |
23 | current_input_config->identifier, new_config->xkb_model); | 23 | current_input_config->identifier, new_config->xkb_model); |
24 | apply_input_config(new_config); | 24 | apply_input_config(new_config); |
25 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 25 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
diff --git a/sway/commands/input/xkb_options.c b/sway/commands/input/xkb_options.c index e9ddd6e3..3059d941 100644 --- a/sway/commands/input/xkb_options.c +++ b/sway/commands/input/xkb_options.c | |||
@@ -19,7 +19,7 @@ struct cmd_results *input_cmd_xkb_options(int argc, char **argv) { | |||
19 | 19 | ||
20 | new_config->xkb_options = strdup(argv[0]); | 20 | new_config->xkb_options = strdup(argv[0]); |
21 | 21 | ||
22 | wlr_log(L_DEBUG, "apply-xkb_options for device: %s options: %s", | 22 | wlr_log(WLR_DEBUG, "apply-xkb_options for device: %s options: %s", |
23 | current_input_config->identifier, new_config->xkb_options); | 23 | current_input_config->identifier, new_config->xkb_options); |
24 | apply_input_config(new_config); | 24 | apply_input_config(new_config); |
25 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 25 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
diff --git a/sway/commands/input/xkb_rules.c b/sway/commands/input/xkb_rules.c index 926d0ac1..560f088e 100644 --- a/sway/commands/input/xkb_rules.c +++ b/sway/commands/input/xkb_rules.c | |||
@@ -19,7 +19,7 @@ struct cmd_results *input_cmd_xkb_rules(int argc, char **argv) { | |||
19 | 19 | ||
20 | new_config->xkb_rules = strdup(argv[0]); | 20 | new_config->xkb_rules = strdup(argv[0]); |
21 | 21 | ||
22 | wlr_log(L_DEBUG, "apply-xkb_rules for device: %s rules: %s", | 22 | wlr_log(WLR_DEBUG, "apply-xkb_rules for device: %s rules: %s", |
23 | current_input_config->identifier, new_config->xkb_rules); | 23 | current_input_config->identifier, new_config->xkb_rules); |
24 | apply_input_config(new_config); | 24 | apply_input_config(new_config); |
25 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 25 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
diff --git a/sway/commands/input/xkb_variant.c b/sway/commands/input/xkb_variant.c index 0e3ffd41..0aa03440 100644 --- a/sway/commands/input/xkb_variant.c +++ b/sway/commands/input/xkb_variant.c | |||
@@ -19,7 +19,7 @@ struct cmd_results *input_cmd_xkb_variant(int argc, char **argv) { | |||
19 | 19 | ||
20 | new_config->xkb_variant = strdup(argv[0]); | 20 | new_config->xkb_variant = strdup(argv[0]); |
21 | 21 | ||
22 | wlr_log(L_DEBUG, "apply-xkb_variant for device: %s variant: %s", | 22 | wlr_log(WLR_DEBUG, "apply-xkb_variant for device: %s variant: %s", |
23 | current_input_config->identifier, new_config->xkb_variant); | 23 | current_input_config->identifier, new_config->xkb_variant); |
24 | apply_input_config(new_config); | 24 | apply_input_config(new_config); |
25 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 25 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
diff --git a/sway/commands/layout.c b/sway/commands/layout.c index 9945fa5c..c446f1f9 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c | |||
@@ -49,7 +49,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) { | |||
49 | } | 49 | } |
50 | 50 | ||
51 | container_notify_subtree_changed(parent); | 51 | container_notify_subtree_changed(parent); |
52 | arrange_and_commit(parent); | 52 | arrange_windows(parent); |
53 | 53 | ||
54 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 54 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
55 | } | 55 | } |
diff --git a/sway/commands/mode.c b/sway/commands/mode.c index d2c14468..b460fcb5 100644 --- a/sway/commands/mode.c +++ b/sway/commands/mode.c | |||
@@ -65,7 +65,7 @@ struct cmd_results *cmd_mode(int argc, char **argv) { | |||
65 | return error; | 65 | return error; |
66 | } | 66 | } |
67 | if ((config->reading && argc > 1) || (!config->reading && argc == 1)) { | 67 | if ((config->reading && argc > 1) || (!config->reading && argc == 1)) { |
68 | wlr_log(L_DEBUG, "Switching to mode `%s' (pango=%d)", | 68 | wlr_log(WLR_DEBUG, "Switching to mode `%s' (pango=%d)", |
69 | mode->name, mode->pango); | 69 | mode->name, mode->pango); |
70 | } | 70 | } |
71 | // Set current mode | 71 | // Set current mode |
diff --git a/sway/commands/move.c b/sway/commands/move.c index a4fae388..6ec050a8 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c | |||
@@ -1,11 +1,12 @@ | |||
1 | #define _XOPEN_SOURCE 500 | 1 | #define _XOPEN_SOURCE 500 |
2 | #include <string.h> | 2 | #include <string.h> |
3 | #include <strings.h> | 3 | #include <strings.h> |
4 | #include <wlr/types/wlr_cursor.h> | ||
4 | #include <wlr/types/wlr_output.h> | 5 | #include <wlr/types/wlr_output.h> |
5 | #include <wlr/types/wlr_output_layout.h> | 6 | #include <wlr/types/wlr_output_layout.h> |
6 | #include <wlr/util/log.h> | 7 | #include <wlr/util/log.h> |
7 | #include "sway/commands.h" | 8 | #include "sway/commands.h" |
8 | #include "sway/desktop/transaction.h" | 9 | #include "sway/input/cursor.h" |
9 | #include "sway/input/seat.h" | 10 | #include "sway/input/seat.h" |
10 | #include "sway/output.h" | 11 | #include "sway/output.h" |
11 | #include "sway/tree/arrange.h" | 12 | #include "sway/tree/arrange.h" |
@@ -103,10 +104,8 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, | |||
103 | // TODO: Ideally we would arrange the surviving parent after reaping, | 104 | // TODO: Ideally we would arrange the surviving parent after reaping, |
104 | // but container_reap_empty does not return it, so we arrange the | 105 | // but container_reap_empty does not return it, so we arrange the |
105 | // workspace instead. | 106 | // workspace instead. |
106 | struct sway_transaction *txn = transaction_create(); | 107 | arrange_windows(old_ws); |
107 | arrange_windows(old_ws, txn); | 108 | arrange_windows(destination->parent); |
108 | arrange_windows(destination->parent, txn); | ||
109 | transaction_commit(txn); | ||
110 | 109 | ||
111 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 110 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
112 | } else if (strcasecmp(argv[1], "to") == 0 | 111 | } else if (strcasecmp(argv[1], "to") == 0 |
@@ -142,10 +141,8 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, | |||
142 | // TODO: Ideally we would arrange the surviving parent after reaping, | 141 | // TODO: Ideally we would arrange the surviving parent after reaping, |
143 | // but container_reap_empty does not return it, so we arrange the | 142 | // but container_reap_empty does not return it, so we arrange the |
144 | // workspace instead. | 143 | // workspace instead. |
145 | struct sway_transaction *txn = transaction_create(); | 144 | arrange_windows(old_ws); |
146 | arrange_windows(old_ws, txn); | 145 | arrange_windows(focus->parent); |
147 | arrange_windows(focus->parent, txn); | ||
148 | transaction_commit(txn); | ||
149 | 146 | ||
150 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 147 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
151 | } | 148 | } |
@@ -175,20 +172,56 @@ static struct cmd_results *cmd_move_workspace(struct sway_container *current, | |||
175 | } | 172 | } |
176 | container_move_to(current, destination); | 173 | container_move_to(current, destination); |
177 | 174 | ||
178 | struct sway_transaction *txn = transaction_create(); | 175 | arrange_windows(source); |
179 | arrange_windows(source, txn); | 176 | arrange_windows(destination); |
180 | arrange_windows(destination, txn); | ||
181 | transaction_commit(txn); | ||
182 | 177 | ||
183 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 178 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
184 | } | 179 | } |
185 | 180 | ||
186 | static struct cmd_results *move_in_direction(struct sway_container *container, | 181 | static struct cmd_results *move_in_direction(struct sway_container *container, |
187 | enum movement_direction direction, int move_amt) { | 182 | enum movement_direction direction, int argc, char **argv) { |
183 | int move_amt = 10; | ||
184 | if (argc > 1) { | ||
185 | char *inv; | ||
186 | move_amt = (int)strtol(argv[1], &inv, 10); | ||
187 | if (*inv != '\0' && strcasecmp(inv, "px") != 0) { | ||
188 | return cmd_results_new(CMD_FAILURE, "move", | ||
189 | "Invalid distance specified"); | ||
190 | } | ||
191 | } | ||
192 | |||
188 | if (container->type == C_WORKSPACE) { | 193 | if (container->type == C_WORKSPACE) { |
189 | return cmd_results_new(CMD_FAILURE, "move", | 194 | return cmd_results_new(CMD_FAILURE, "move", |
190 | "Cannot move workspaces in a direction"); | 195 | "Cannot move workspaces in a direction"); |
191 | } | 196 | } |
197 | if (container_is_floating(container)) { | ||
198 | if (container->type == C_VIEW && container->sway_view->is_fullscreen) { | ||
199 | return cmd_results_new(CMD_FAILURE, "move", | ||
200 | "Cannot move fullscreen floating container"); | ||
201 | } | ||
202 | double lx = container->x; | ||
203 | double ly = container->y; | ||
204 | switch (direction) { | ||
205 | case MOVE_LEFT: | ||
206 | lx -= move_amt; | ||
207 | break; | ||
208 | case MOVE_RIGHT: | ||
209 | lx += move_amt; | ||
210 | break; | ||
211 | case MOVE_UP: | ||
212 | ly -= move_amt; | ||
213 | break; | ||
214 | case MOVE_DOWN: | ||
215 | ly += move_amt; | ||
216 | break; | ||
217 | case MOVE_PARENT: | ||
218 | case MOVE_CHILD: | ||
219 | return cmd_results_new(CMD_FAILURE, "move", | ||
220 | "Cannot move floating container to parent or child"); | ||
221 | } | ||
222 | container_floating_move_to(container, lx, ly); | ||
223 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
224 | } | ||
192 | // For simplicity, we'll arrange the entire workspace. The reason for this | 225 | // For simplicity, we'll arrange the entire workspace. The reason for this |
193 | // is moving the container might reap the old parent, and container_move | 226 | // is moving the container might reap the old parent, and container_move |
194 | // does not return a surviving parent. | 227 | // does not return a surviving parent. |
@@ -198,41 +231,86 @@ static struct cmd_results *move_in_direction(struct sway_container *container, | |||
198 | container_move(container, direction, move_amt); | 231 | container_move(container, direction, move_amt); |
199 | struct sway_container *new_ws = container_parent(container, C_WORKSPACE); | 232 | struct sway_container *new_ws = container_parent(container, C_WORKSPACE); |
200 | 233 | ||
201 | struct sway_transaction *txn = transaction_create(); | 234 | arrange_windows(old_ws); |
202 | arrange_windows(old_ws, txn); | ||
203 | if (new_ws != old_ws) { | 235 | if (new_ws != old_ws) { |
204 | arrange_windows(new_ws, txn); | 236 | arrange_windows(new_ws); |
205 | } | 237 | } |
206 | transaction_commit(txn); | ||
207 | 238 | ||
208 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 239 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
209 | } | 240 | } |
210 | 241 | ||
242 | static const char* expected_position_syntax = | ||
243 | "Expected 'move [absolute] position <x> <y>' or " | ||
244 | "'move [absolute] position mouse'"; | ||
245 | |||
246 | static struct cmd_results *move_to_position(struct sway_container *container, | ||
247 | int argc, char **argv) { | ||
248 | if (!container_is_floating(container)) { | ||
249 | return cmd_results_new(CMD_FAILURE, "move", | ||
250 | "Only floating containers " | ||
251 | "can be moved to an absolute position"); | ||
252 | } | ||
253 | if (!argc) { | ||
254 | return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax); | ||
255 | } | ||
256 | if (strcmp(argv[0], "absolute") == 0) { | ||
257 | --argc; | ||
258 | ++argv; | ||
259 | } | ||
260 | if (!argc) { | ||
261 | return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax); | ||
262 | } | ||
263 | if (strcmp(argv[0], "position") == 0) { | ||
264 | --argc; | ||
265 | ++argv; | ||
266 | } | ||
267 | if (!argc) { | ||
268 | return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax); | ||
269 | } | ||
270 | if (strcmp(argv[0], "mouse") == 0) { | ||
271 | struct sway_seat *seat = config->handler_context.seat; | ||
272 | if (!seat->cursor) { | ||
273 | return cmd_results_new(CMD_FAILURE, "move", "No cursor device"); | ||
274 | } | ||
275 | double lx = seat->cursor->cursor->x - container->width / 2; | ||
276 | double ly = seat->cursor->cursor->y - container->height / 2; | ||
277 | container_floating_move_to(container, lx, ly); | ||
278 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
279 | } | ||
280 | if (argc != 2) { | ||
281 | return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax); | ||
282 | } | ||
283 | double lx, ly; | ||
284 | char *inv; | ||
285 | lx = (double)strtol(argv[0], &inv, 10); | ||
286 | if (*inv != '\0' && strcasecmp(inv, "px") != 0) { | ||
287 | return cmd_results_new(CMD_FAILURE, "move", | ||
288 | "Invalid position specified"); | ||
289 | } | ||
290 | ly = (double)strtol(argv[1], &inv, 10); | ||
291 | if (*inv != '\0' && strcasecmp(inv, "px") != 0) { | ||
292 | return cmd_results_new(CMD_FAILURE, "move", | ||
293 | "Invalid position specified"); | ||
294 | } | ||
295 | container_floating_move_to(container, lx, ly); | ||
296 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
297 | } | ||
298 | |||
211 | struct cmd_results *cmd_move(int argc, char **argv) { | 299 | struct cmd_results *cmd_move(int argc, char **argv) { |
212 | struct cmd_results *error = NULL; | 300 | struct cmd_results *error = NULL; |
213 | int move_amt = 10; | ||
214 | if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) { | 301 | if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) { |
215 | return error; | 302 | return error; |
216 | } | 303 | } |
217 | struct sway_container *current = config->handler_context.current_container; | 304 | struct sway_container *current = config->handler_context.current_container; |
218 | 305 | ||
219 | if (argc == 2 || (argc == 3 && strcasecmp(argv[2], "px") == 0)) { | ||
220 | char *inv; | ||
221 | move_amt = (int)strtol(argv[1], &inv, 10); | ||
222 | if (*inv != '\0' && strcasecmp(inv, "px") != 0) { | ||
223 | return cmd_results_new(CMD_FAILURE, "move", | ||
224 | "Invalid distance specified"); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | if (strcasecmp(argv[0], "left") == 0) { | 306 | if (strcasecmp(argv[0], "left") == 0) { |
229 | return move_in_direction(current, MOVE_LEFT, move_amt); | 307 | return move_in_direction(current, MOVE_LEFT, argc, argv); |
230 | } else if (strcasecmp(argv[0], "right") == 0) { | 308 | } else if (strcasecmp(argv[0], "right") == 0) { |
231 | return move_in_direction(current, MOVE_RIGHT, move_amt); | 309 | return move_in_direction(current, MOVE_RIGHT, argc, argv); |
232 | } else if (strcasecmp(argv[0], "up") == 0) { | 310 | } else if (strcasecmp(argv[0], "up") == 0) { |
233 | return move_in_direction(current, MOVE_UP, move_amt); | 311 | return move_in_direction(current, MOVE_UP, argc, argv); |
234 | } else if (strcasecmp(argv[0], "down") == 0) { | 312 | } else if (strcasecmp(argv[0], "down") == 0) { |
235 | return move_in_direction(current, MOVE_DOWN, move_amt); | 313 | return move_in_direction(current, MOVE_DOWN, argc, argv); |
236 | } else if (strcasecmp(argv[0], "container") == 0 | 314 | } else if (strcasecmp(argv[0], "container") == 0 |
237 | || strcasecmp(argv[0], "window") == 0) { | 315 | || strcasecmp(argv[0], "window") == 0) { |
238 | return cmd_move_container(current, argc, argv); | 316 | return cmd_move_container(current, argc, argv); |
@@ -244,8 +322,9 @@ struct cmd_results *cmd_move(int argc, char **argv) { | |||
244 | // TODO: scratchpad | 322 | // TODO: scratchpad |
245 | return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); | 323 | return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); |
246 | } else if (strcasecmp(argv[0], "position") == 0) { | 324 | } else if (strcasecmp(argv[0], "position") == 0) { |
247 | // TODO: floating | 325 | return move_to_position(current, argc, argv); |
248 | return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); | 326 | } else if (strcasecmp(argv[0], "absolute") == 0) { |
327 | return move_to_position(current, argc, argv); | ||
249 | } else { | 328 | } else { |
250 | return cmd_results_new(CMD_INVALID, "move", expected_syntax); | 329 | return cmd_results_new(CMD_INVALID, "move", expected_syntax); |
251 | } | 330 | } |
diff --git a/sway/commands/no_focus.c b/sway/commands/no_focus.c new file mode 100644 index 00000000..61a8de7e --- /dev/null +++ b/sway/commands/no_focus.c | |||
@@ -0,0 +1,26 @@ | |||
1 | #define _XOPEN_SOURCE 500 | ||
2 | #include <string.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/criteria.h" | ||
5 | #include "list.h" | ||
6 | #include "log.h" | ||
7 | |||
8 | struct cmd_results *cmd_no_focus(int argc, char **argv) { | ||
9 | struct cmd_results *error = NULL; | ||
10 | if ((error = checkarg(argc, "no_focus", EXPECTED_AT_LEAST, 1))) { | ||
11 | return error; | ||
12 | } | ||
13 | |||
14 | char *err_str = NULL; | ||
15 | struct criteria *criteria = criteria_parse(argv[0], &err_str); | ||
16 | if (!criteria) { | ||
17 | error = cmd_results_new(CMD_INVALID, "no_focus", err_str); | ||
18 | free(err_str); | ||
19 | return error; | ||
20 | } | ||
21 | |||
22 | criteria->type = CT_NO_FOCUS; | ||
23 | list_add(config->criteria, criteria); | ||
24 | |||
25 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
26 | } | ||
diff --git a/sway/commands/output.c b/sway/commands/output.c index f955bf90..15bbd687 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c | |||
@@ -29,7 +29,7 @@ struct cmd_results *cmd_output(int argc, char **argv) { | |||
29 | 29 | ||
30 | struct output_config *output = new_output_config(argv[0]); | 30 | struct output_config *output = new_output_config(argv[0]); |
31 | if (!output) { | 31 | if (!output) { |
32 | wlr_log(L_ERROR, "Failed to allocate output config"); | 32 | wlr_log(WLR_ERROR, "Failed to allocate output config"); |
33 | return NULL; | 33 | return NULL; |
34 | } | 34 | } |
35 | argc--; argv++; | 35 | argc--; argv++; |
@@ -71,7 +71,7 @@ struct cmd_results *cmd_output(int argc, char **argv) { | |||
71 | list_add(config->output_configs, output); | 71 | list_add(config->output_configs, output); |
72 | } | 72 | } |
73 | 73 | ||
74 | wlr_log(L_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " | 74 | wlr_log(WLR_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " |
75 | "position %d,%d scale %f transform %d) (bg %s %s) (dpms %d)", | 75 | "position %d,%d scale %f transform %d) (bg %s %s) (dpms %d)", |
76 | output->name, output->enabled, output->width, output->height, | 76 | output->name, output->enabled, output->width, output->height, |
77 | output->refresh_rate, output->x, output->y, output->scale, | 77 | output->refresh_rate, output->x, output->y, output->scale, |
@@ -85,7 +85,7 @@ struct cmd_results *cmd_output(int argc, char **argv) { | |||
85 | struct sway_output *sway_output; | 85 | struct sway_output *sway_output; |
86 | wl_list_for_each(sway_output, &root_container.sway_root->outputs, link) { | 86 | wl_list_for_each(sway_output, &root_container.sway_root->outputs, link) { |
87 | output_get_identifier(identifier, sizeof(identifier), sway_output); | 87 | output_get_identifier(identifier, sizeof(identifier), sway_output); |
88 | wlr_log(L_DEBUG, "Checking identifier %s", identifier); | 88 | wlr_log(WLR_DEBUG, "Checking identifier %s", identifier); |
89 | if (all || strcmp(sway_output->wlr_output->name, output->name) == 0 | 89 | if (all || strcmp(sway_output->wlr_output->name, output->name) == 0 |
90 | || strcmp(identifier, output->name) == 0) { | 90 | || strcmp(identifier, output->name) == 0) { |
91 | if (!sway_output->swayc) { | 91 | if (!sway_output->swayc) { |
diff --git a/sway/commands/output/background.c b/sway/commands/output/background.c index 65b5f902..4ed56c2a 100644 --- a/sway/commands/output/background.c +++ b/sway/commands/output/background.c | |||
@@ -72,7 +72,7 @@ struct cmd_results *output_cmd_background(int argc, char **argv) { | |||
72 | src = strdup(p.we_wordv[0]); | 72 | src = strdup(p.we_wordv[0]); |
73 | wordfree(&p); | 73 | wordfree(&p); |
74 | if (!src) { | 74 | if (!src) { |
75 | wlr_log(L_ERROR, "Failed to duplicate string"); | 75 | wlr_log(WLR_ERROR, "Failed to duplicate string"); |
76 | return cmd_results_new(CMD_FAILURE, "output", | 76 | return cmd_results_new(CMD_FAILURE, "output", |
77 | "Unable to allocate resource"); | 77 | "Unable to allocate resource"); |
78 | } | 78 | } |
@@ -80,9 +80,9 @@ struct cmd_results *output_cmd_background(int argc, char **argv) { | |||
80 | if (config->reading && *src != '/') { | 80 | if (config->reading && *src != '/') { |
81 | // src file is inside configuration dir | 81 | // src file is inside configuration dir |
82 | 82 | ||
83 | char *conf = strdup(config->current_config); | 83 | char *conf = strdup(config->current_config_path); |
84 | if (!conf) { | 84 | if (!conf) { |
85 | wlr_log(L_ERROR, "Failed to duplicate string"); | 85 | wlr_log(WLR_ERROR, "Failed to duplicate string"); |
86 | free(src); | 86 | free(src); |
87 | return cmd_results_new(CMD_FAILURE, "output", | 87 | return cmd_results_new(CMD_FAILURE, "output", |
88 | "Unable to allocate resources"); | 88 | "Unable to allocate resources"); |
@@ -94,7 +94,7 @@ struct cmd_results *output_cmd_background(int argc, char **argv) { | |||
94 | if (!src) { | 94 | if (!src) { |
95 | free(rel_path); | 95 | free(rel_path); |
96 | free(conf); | 96 | free(conf); |
97 | wlr_log(L_ERROR, "Unable to allocate memory"); | 97 | wlr_log(WLR_ERROR, "Unable to allocate memory"); |
98 | return cmd_results_new(CMD_FAILURE, "output", | 98 | return cmd_results_new(CMD_FAILURE, "output", |
99 | "Unable to allocate resources"); | 99 | "Unable to allocate resources"); |
100 | } | 100 | } |
diff --git a/sway/commands/reload.c b/sway/commands/reload.c index 9fc213c4..cea6a94b 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c | |||
@@ -7,11 +7,11 @@ struct cmd_results *cmd_reload(int argc, char **argv) { | |||
7 | if ((error = checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0))) { | 7 | if ((error = checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0))) { |
8 | return error; | 8 | return error; |
9 | } | 9 | } |
10 | if (!load_main_config(config->current_config, true)) { | 10 | if (!load_main_config(config->current_config_path, true)) { |
11 | return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); | 11 | return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); |
12 | } | 12 | } |
13 | 13 | ||
14 | load_swaybars(); | 14 | load_swaybars(); |
15 | arrange_and_commit(&root_container); | 15 | arrange_windows(&root_container); |
16 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 16 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
17 | } | 17 | } |
diff --git a/sway/commands/rename.c b/sway/commands/rename.c index 104a3392..a380ff9c 100644 --- a/sway/commands/rename.c +++ b/sway/commands/rename.c | |||
@@ -68,7 +68,7 @@ struct cmd_results *cmd_rename(int argc, char **argv) { | |||
68 | "Workspace already exists"); | 68 | "Workspace already exists"); |
69 | } | 69 | } |
70 | 70 | ||
71 | wlr_log(L_DEBUG, "renaming workspace '%s' to '%s'", workspace->name, new_name); | 71 | wlr_log(WLR_DEBUG, "renaming workspace '%s' to '%s'", workspace->name, new_name); |
72 | free(workspace->name); | 72 | free(workspace->name); |
73 | workspace->name = new_name; | 73 | workspace->name = new_name; |
74 | 74 | ||
diff --git a/sway/commands/resize.c b/sway/commands/resize.c index 6357343e..e657864c 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #include <errno.h> | 1 | #include <errno.h> |
2 | #include <limits.h> | ||
2 | #include <math.h> | 3 | #include <math.h> |
3 | #include <stdbool.h> | 4 | #include <stdbool.h> |
4 | #include <stdlib.h> | 5 | #include <stdlib.h> |
@@ -7,6 +8,7 @@ | |||
7 | #include <wlr/util/log.h> | 8 | #include <wlr/util/log.h> |
8 | #include "sway/commands.h" | 9 | #include "sway/commands.h" |
9 | #include "sway/tree/arrange.h" | 10 | #include "sway/tree/arrange.h" |
11 | #include "sway/tree/view.h" | ||
10 | #include "log.h" | 12 | #include "log.h" |
11 | 13 | ||
12 | static const int MIN_SANE_W = 100, MIN_SANE_H = 60; | 14 | static const int MIN_SANE_W = 100, MIN_SANE_H = 60; |
@@ -21,9 +23,18 @@ enum resize_unit { | |||
21 | enum resize_axis { | 23 | enum resize_axis { |
22 | RESIZE_AXIS_HORIZONTAL, | 24 | RESIZE_AXIS_HORIZONTAL, |
23 | RESIZE_AXIS_VERTICAL, | 25 | RESIZE_AXIS_VERTICAL, |
26 | RESIZE_AXIS_UP, | ||
27 | RESIZE_AXIS_DOWN, | ||
28 | RESIZE_AXIS_LEFT, | ||
29 | RESIZE_AXIS_RIGHT, | ||
24 | RESIZE_AXIS_INVALID, | 30 | RESIZE_AXIS_INVALID, |
25 | }; | 31 | }; |
26 | 32 | ||
33 | struct resize_amount { | ||
34 | int amount; | ||
35 | enum resize_unit unit; | ||
36 | }; | ||
37 | |||
27 | static enum resize_unit parse_resize_unit(const char *unit) { | 38 | static enum resize_unit parse_resize_unit(const char *unit) { |
28 | if (strcasecmp(unit, "px") == 0) { | 39 | if (strcasecmp(unit, "px") == 0) { |
29 | return RESIZE_UNIT_PX; | 40 | return RESIZE_UNIT_PX; |
@@ -37,6 +48,69 @@ static enum resize_unit parse_resize_unit(const char *unit) { | |||
37 | return RESIZE_UNIT_INVALID; | 48 | return RESIZE_UNIT_INVALID; |
38 | } | 49 | } |
39 | 50 | ||
51 | // Parse arguments such as "10", "10px" or "10 px". | ||
52 | // Returns the number of arguments consumed. | ||
53 | static int parse_resize_amount(int argc, char **argv, | ||
54 | struct resize_amount *amount) { | ||
55 | char *err; | ||
56 | amount->amount = (int)strtol(argv[0], &err, 10); | ||
57 | if (*err) { | ||
58 | // e.g. 10px | ||
59 | amount->unit = parse_resize_unit(err); | ||
60 | return 1; | ||
61 | } | ||
62 | if (argc == 1) { | ||
63 | amount->unit = RESIZE_UNIT_DEFAULT; | ||
64 | return 1; | ||
65 | } | ||
66 | // Try the second argument | ||
67 | amount->unit = parse_resize_unit(argv[1]); | ||
68 | if (amount->unit == RESIZE_UNIT_INVALID) { | ||
69 | amount->unit = RESIZE_UNIT_DEFAULT; | ||
70 | return 1; | ||
71 | } | ||
72 | return 2; | ||
73 | } | ||
74 | |||
75 | static void calculate_constraints(int *min_width, int *max_width, | ||
76 | int *min_height, int *max_height) { | ||
77 | struct sway_container *con = config->handler_context.current_container; | ||
78 | |||
79 | if (config->floating_minimum_width == -1) { // no minimum | ||
80 | *min_width = 0; | ||
81 | } else if (config->floating_minimum_width == 0) { // automatic | ||
82 | *min_width = 75; | ||
83 | } else { | ||
84 | *min_width = config->floating_minimum_width; | ||
85 | } | ||
86 | |||
87 | if (config->floating_minimum_height == -1) { // no minimum | ||
88 | *min_height = 0; | ||
89 | } else if (config->floating_minimum_height == 0) { // automatic | ||
90 | *min_height = 50; | ||
91 | } else { | ||
92 | *min_height = config->floating_minimum_height; | ||
93 | } | ||
94 | |||
95 | if (config->floating_maximum_width == -1) { // no maximum | ||
96 | *max_width = INT_MAX; | ||
97 | } else if (config->floating_maximum_width == 0) { // automatic | ||
98 | struct sway_container *ws = container_parent(con, C_WORKSPACE); | ||
99 | *max_width = ws->width; | ||
100 | } else { | ||
101 | *max_width = config->floating_maximum_width; | ||
102 | } | ||
103 | |||
104 | if (config->floating_maximum_height == -1) { // no maximum | ||
105 | *max_height = INT_MAX; | ||
106 | } else if (config->floating_maximum_height == 0) { // automatic | ||
107 | struct sway_container *ws = container_parent(con, C_WORKSPACE); | ||
108 | *max_height = ws->height; | ||
109 | } else { | ||
110 | *max_height = config->floating_maximum_height; | ||
111 | } | ||
112 | } | ||
113 | |||
40 | static enum resize_axis parse_resize_axis(const char *axis) { | 114 | static enum resize_axis parse_resize_axis(const char *axis) { |
41 | if (strcasecmp(axis, "width") == 0 || strcasecmp(axis, "horizontal") == 0) { | 115 | if (strcasecmp(axis, "width") == 0 || strcasecmp(axis, "horizontal") == 0) { |
42 | return RESIZE_AXIS_HORIZONTAL; | 116 | return RESIZE_AXIS_HORIZONTAL; |
@@ -44,6 +118,18 @@ static enum resize_axis parse_resize_axis(const char *axis) { | |||
44 | if (strcasecmp(axis, "height") == 0 || strcasecmp(axis, "vertical") == 0) { | 118 | if (strcasecmp(axis, "height") == 0 || strcasecmp(axis, "vertical") == 0) { |
45 | return RESIZE_AXIS_VERTICAL; | 119 | return RESIZE_AXIS_VERTICAL; |
46 | } | 120 | } |
121 | if (strcasecmp(axis, "up") == 0) { | ||
122 | return RESIZE_AXIS_UP; | ||
123 | } | ||
124 | if (strcasecmp(axis, "down") == 0) { | ||
125 | return RESIZE_AXIS_DOWN; | ||
126 | } | ||
127 | if (strcasecmp(axis, "left") == 0) { | ||
128 | return RESIZE_AXIS_LEFT; | ||
129 | } | ||
130 | if (strcasecmp(axis, "right") == 0) { | ||
131 | return RESIZE_AXIS_RIGHT; | ||
132 | } | ||
47 | return RESIZE_AXIS_INVALID; | 133 | return RESIZE_AXIS_INVALID; |
48 | } | 134 | } |
49 | 135 | ||
@@ -95,7 +181,7 @@ static void resize_tiled(int amount, enum resize_axis axis) { | |||
95 | return; | 181 | return; |
96 | } | 182 | } |
97 | 183 | ||
98 | wlr_log(L_DEBUG, | 184 | wlr_log(WLR_DEBUG, |
99 | "Found the proper parent: %p. It has %d l conts, and %d r conts", | 185 | "Found the proper parent: %p. It has %d l conts, and %d r conts", |
100 | parent->parent, minor_weight, major_weight); | 186 | parent->parent, minor_weight, major_weight); |
101 | 187 | ||
@@ -182,105 +268,315 @@ static void resize_tiled(int amount, enum resize_axis axis) { | |||
182 | } | 268 | } |
183 | } | 269 | } |
184 | 270 | ||
185 | arrange_and_commit(parent->parent); | 271 | arrange_windows(parent->parent); |
186 | } | 272 | } |
187 | 273 | ||
188 | static void resize(int amount, enum resize_axis axis, enum resize_unit unit) { | 274 | /** |
189 | struct sway_container *current = config->handler_context.current_container; | 275 | * Implement `resize <grow|shrink>` for a floating container. |
190 | if (unit == RESIZE_UNIT_DEFAULT) { | 276 | */ |
191 | // Default for tiling; TODO floating should be px | 277 | static struct cmd_results *resize_adjust_floating(enum resize_axis axis, |
192 | unit = RESIZE_UNIT_PPT; | 278 | struct resize_amount *amount) { |
279 | struct sway_container *con = config->handler_context.current_container; | ||
280 | int grow_width = 0, grow_height = 0; | ||
281 | switch (axis) { | ||
282 | case RESIZE_AXIS_HORIZONTAL: | ||
283 | case RESIZE_AXIS_LEFT: | ||
284 | case RESIZE_AXIS_RIGHT: | ||
285 | grow_width = amount->amount; | ||
286 | break; | ||
287 | case RESIZE_AXIS_VERTICAL: | ||
288 | case RESIZE_AXIS_UP: | ||
289 | case RESIZE_AXIS_DOWN: | ||
290 | grow_height = amount->amount; | ||
291 | break; | ||
292 | case RESIZE_AXIS_INVALID: | ||
293 | return cmd_results_new(CMD_INVALID, "resize", "Invalid axis/direction"); | ||
294 | } | ||
295 | // Make sure we're not adjusting beyond floating min/max size | ||
296 | int min_width, max_width, min_height, max_height; | ||
297 | calculate_constraints(&min_width, &max_width, &min_height, &max_height); | ||
298 | if (con->width + grow_width < min_width) { | ||
299 | grow_width = min_width - con->width; | ||
300 | } else if (con->width + grow_width > max_width) { | ||
301 | grow_width = max_width - con->width; | ||
193 | } | 302 | } |
303 | if (con->height + grow_height < min_height) { | ||
304 | grow_height = min_height - con->height; | ||
305 | } else if (con->height + grow_height > max_height) { | ||
306 | grow_height = max_height - con->height; | ||
307 | } | ||
308 | int grow_x = 0, grow_y = 0; | ||
309 | switch (axis) { | ||
310 | case RESIZE_AXIS_HORIZONTAL: | ||
311 | grow_x = -grow_width / 2; | ||
312 | break; | ||
313 | case RESIZE_AXIS_VERTICAL: | ||
314 | grow_y = -grow_height / 2; | ||
315 | break; | ||
316 | case RESIZE_AXIS_UP: | ||
317 | grow_y = -grow_height; | ||
318 | break; | ||
319 | case RESIZE_AXIS_LEFT: | ||
320 | grow_x = -grow_width; | ||
321 | break; | ||
322 | case RESIZE_AXIS_DOWN: | ||
323 | case RESIZE_AXIS_RIGHT: | ||
324 | break; | ||
325 | case RESIZE_AXIS_INVALID: | ||
326 | return cmd_results_new(CMD_INVALID, "resize", "Invalid axis/direction"); | ||
327 | } | ||
328 | con->x += grow_x; | ||
329 | con->y += grow_y; | ||
330 | con->width += grow_width; | ||
331 | con->height += grow_height; | ||
332 | |||
333 | if (con->type == C_VIEW) { | ||
334 | struct sway_view *view = con->sway_view; | ||
335 | view->x += grow_x; | ||
336 | view->y += grow_y; | ||
337 | view->width += grow_width; | ||
338 | view->height += grow_height; | ||
339 | } | ||
340 | |||
341 | arrange_windows(con); | ||
342 | |||
343 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
344 | } | ||
194 | 345 | ||
195 | if (unit == RESIZE_UNIT_PPT) { | 346 | /** |
196 | float pct = amount / 100.0f; | 347 | * Implement `resize <grow|shrink>` for a tiled container. |
348 | */ | ||
349 | static struct cmd_results *resize_adjust_tiled(enum resize_axis axis, | ||
350 | struct resize_amount *amount) { | ||
351 | struct sway_container *current = config->handler_context.current_container; | ||
352 | |||
353 | if (amount->unit == RESIZE_UNIT_DEFAULT) { | ||
354 | amount->unit = RESIZE_UNIT_PPT; | ||
355 | } | ||
356 | if (amount->unit == RESIZE_UNIT_PPT) { | ||
357 | float pct = amount->amount / 100.0f; | ||
358 | // TODO: Make left/right/up/down resize in that direction? | ||
197 | switch (axis) { | 359 | switch (axis) { |
360 | case RESIZE_AXIS_LEFT: | ||
361 | case RESIZE_AXIS_RIGHT: | ||
198 | case RESIZE_AXIS_HORIZONTAL: | 362 | case RESIZE_AXIS_HORIZONTAL: |
199 | amount = (float)current->width * pct; | 363 | amount->amount = (float)current->width * pct; |
200 | break; | 364 | break; |
365 | case RESIZE_AXIS_UP: | ||
366 | case RESIZE_AXIS_DOWN: | ||
201 | case RESIZE_AXIS_VERTICAL: | 367 | case RESIZE_AXIS_VERTICAL: |
202 | amount = (float)current->height * pct; | 368 | amount->amount = (float)current->height * pct; |
203 | break; | 369 | break; |
204 | default: | 370 | case RESIZE_AXIS_INVALID: |
205 | sway_assert(0, "invalid resize axis"); | 371 | return cmd_results_new(CMD_INVALID, "resize", |
206 | return; | 372 | "Invalid resize axis/direction"); |
207 | } | 373 | } |
208 | } | 374 | } |
209 | 375 | ||
210 | return resize_tiled(amount, axis); | 376 | resize_tiled(amount->amount, axis); |
377 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
211 | } | 378 | } |
212 | 379 | ||
213 | struct cmd_results *cmd_resize(int argc, char **argv) { | 380 | /** |
214 | struct sway_container *current = config->handler_context.current_container; | 381 | * Implement `resize set` for a tiled container. |
215 | if (!current) { | 382 | */ |
216 | return cmd_results_new(CMD_INVALID, "resize", "Cannot resize nothing"); | 383 | static struct cmd_results *resize_set_tiled(struct sway_container *con, |
217 | } | 384 | struct resize_amount *width, struct resize_amount *height) { |
218 | if (current->type != C_VIEW && current->type != C_CONTAINER) { | 385 | return cmd_results_new(CMD_INVALID, "resize", |
219 | return cmd_results_new(CMD_INVALID, "resize", | 386 | "'resize set' is not implemented for tiled views"); |
220 | "Can only resize views/containers"); | 387 | } |
388 | |||
389 | /** | ||
390 | * Implement `resize set` for a floating container. | ||
391 | */ | ||
392 | static struct cmd_results *resize_set_floating(struct sway_container *con, | ||
393 | struct resize_amount *width, struct resize_amount *height) { | ||
394 | int min_width, max_width, min_height, max_height; | ||
395 | calculate_constraints(&min_width, &max_width, &min_height, &max_height); | ||
396 | width->amount = fmax(min_width, fmin(width->amount, max_width)); | ||
397 | height->amount = fmax(min_height, fmin(height->amount, max_height)); | ||
398 | int grow_width = width->amount - con->width; | ||
399 | int grow_height = height->amount - con->height; | ||
400 | con->x -= grow_width / 2; | ||
401 | con->y -= grow_height / 2; | ||
402 | con->width = width->amount; | ||
403 | con->height = height->amount; | ||
404 | |||
405 | if (con->type == C_VIEW) { | ||
406 | struct sway_view *view = con->sway_view; | ||
407 | view->x -= grow_width / 2; | ||
408 | view->y -= grow_height / 2; | ||
409 | view->width += grow_width; | ||
410 | view->height += grow_height; | ||
221 | } | 411 | } |
222 | 412 | ||
413 | arrange_windows(con); | ||
414 | |||
415 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
416 | } | ||
417 | |||
418 | /** | ||
419 | * resize set <args> | ||
420 | * | ||
421 | * args: <width> [px|ppt] <height> [px|ppt] | ||
422 | */ | ||
423 | static struct cmd_results *cmd_resize_set(int argc, char **argv) { | ||
223 | struct cmd_results *error; | 424 | struct cmd_results *error; |
224 | if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 2))) { | 425 | if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 2))) { |
225 | return error; | 426 | return error; |
226 | } | 427 | } |
227 | 428 | const char *usage = "Expected 'resize set <width> <height>'"; | |
228 | if (strcasecmp(argv[0], "set") == 0) { | 429 | |
229 | // TODO | 430 | // Width |
230 | //return cmd_resize_set(argc - 1, &argv[1]); | 431 | struct resize_amount width; |
231 | return cmd_results_new(CMD_INVALID, "resize", "resize set unimplemented"); | 432 | int num_consumed_args = parse_resize_amount(argc, argv, &width); |
433 | argc -= num_consumed_args; | ||
434 | argv += num_consumed_args; | ||
435 | if (width.unit == RESIZE_UNIT_INVALID) { | ||
436 | return cmd_results_new(CMD_INVALID, "resize", usage); | ||
437 | } | ||
438 | if (!argc) { | ||
439 | return cmd_results_new(CMD_INVALID, "resize", usage); | ||
232 | } | 440 | } |
233 | 441 | ||
234 | // TODO: resize grow|shrink left|right|up|down | 442 | // Height |
443 | struct resize_amount height; | ||
444 | num_consumed_args = parse_resize_amount(argc, argv, &height); | ||
445 | argc -= num_consumed_args; | ||
446 | argv += num_consumed_args; | ||
447 | if (height.unit == RESIZE_UNIT_INVALID) { | ||
448 | return cmd_results_new(CMD_INVALID, "resize", usage); | ||
449 | } | ||
235 | 450 | ||
236 | const char *usage = "Expected 'resize <shrink|grow> " | 451 | // If 0, don't resize that dimension |
237 | "<width|height> [<amount>] [px|ppt]'"; | 452 | struct sway_container *con = config->handler_context.current_container; |
453 | if (width.amount <= 0) { | ||
454 | width.amount = con->width; | ||
455 | } | ||
456 | if (height.amount <= 0) { | ||
457 | height.amount = con->height; | ||
458 | } | ||
238 | 459 | ||
239 | int multiplier = 0; | 460 | if (container_is_floating(con)) { |
240 | if (strcasecmp(*argv, "grow") == 0) { | 461 | return resize_set_floating(con, &width, &height); |
241 | multiplier = 1; | ||
242 | } else if (strcasecmp(*argv, "shrink") == 0) { | ||
243 | multiplier = -1; | ||
244 | } else { | ||
245 | return cmd_results_new(CMD_INVALID, "resize", usage); | ||
246 | } | 462 | } |
247 | --argc; ++argv; | 463 | return resize_set_tiled(con, &width, &height); |
464 | } | ||
248 | 465 | ||
466 | /** | ||
467 | * resize <grow|shrink> <args> | ||
468 | * | ||
469 | * args: <direction> | ||
470 | * args: <direction> <amount> <unit> | ||
471 | * args: <direction> <amount> <unit> or <amount> <other_unit> | ||
472 | */ | ||
473 | static struct cmd_results *cmd_resize_adjust(int argc, char **argv, | ||
474 | int multiplier) { | ||
475 | const char *usage = "Expected 'resize grow|shrink <direction> " | ||
476 | "[<amount> px|ppt [or <amount> px|ppt]]'"; | ||
249 | enum resize_axis axis = parse_resize_axis(*argv); | 477 | enum resize_axis axis = parse_resize_axis(*argv); |
250 | if (axis == RESIZE_AXIS_INVALID) { | 478 | if (axis == RESIZE_AXIS_INVALID) { |
251 | return cmd_results_new(CMD_INVALID, "resize", usage); | 479 | return cmd_results_new(CMD_INVALID, "resize", usage); |
252 | } | 480 | } |
253 | --argc; ++argv; | 481 | --argc; ++argv; |
254 | 482 | ||
255 | int amount = 10; // Default amount | 483 | // First amount |
256 | enum resize_unit unit = RESIZE_UNIT_DEFAULT; | 484 | struct resize_amount first_amount; |
257 | |||
258 | if (argc) { | 485 | if (argc) { |
259 | char *err; | 486 | int num_consumed_args = parse_resize_amount(argc, argv, &first_amount); |
260 | amount = (int)strtol(*argv, &err, 10); | 487 | argc -= num_consumed_args; |
261 | if (*err) { | 488 | argv += num_consumed_args; |
262 | // e.g. `resize grow width 10px` | 489 | if (first_amount.unit == RESIZE_UNIT_INVALID) { |
263 | unit = parse_resize_unit(err); | 490 | return cmd_results_new(CMD_INVALID, "resize", usage); |
264 | if (unit == RESIZE_UNIT_INVALID) { | ||
265 | return cmd_results_new(CMD_INVALID, "resize", usage); | ||
266 | } | ||
267 | } | 491 | } |
268 | --argc; ++argv; | 492 | } else { |
493 | first_amount.amount = 10; | ||
494 | first_amount.unit = RESIZE_UNIT_DEFAULT; | ||
269 | } | 495 | } |
270 | 496 | ||
497 | // "or" | ||
271 | if (argc) { | 498 | if (argc) { |
272 | unit = parse_resize_unit(*argv); | 499 | if (strcmp(*argv, "or") != 0) { |
273 | if (unit == RESIZE_UNIT_INVALID) { | ||
274 | return cmd_results_new(CMD_INVALID, "resize", usage); | 500 | return cmd_results_new(CMD_INVALID, "resize", usage); |
275 | } | 501 | } |
276 | --argc; ++argv; | 502 | --argc; ++argv; |
277 | } | 503 | } |
278 | 504 | ||
505 | // Second amount | ||
506 | struct resize_amount second_amount; | ||
279 | if (argc) { | 507 | if (argc) { |
280 | // Provied too many args, the bastard | 508 | int num_consumed_args = parse_resize_amount(argc, argv, &second_amount); |
281 | return cmd_results_new(CMD_INVALID, "resize", usage); | 509 | argc -= num_consumed_args; |
510 | argv += num_consumed_args; | ||
511 | if (second_amount.unit == RESIZE_UNIT_INVALID) { | ||
512 | return cmd_results_new(CMD_INVALID, "resize", usage); | ||
513 | } | ||
514 | } else { | ||
515 | second_amount.unit = RESIZE_UNIT_INVALID; | ||
282 | } | 516 | } |
283 | 517 | ||
284 | resize(amount * multiplier, axis, unit); | 518 | first_amount.amount *= multiplier; |
285 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 519 | second_amount.amount *= multiplier; |
520 | |||
521 | struct sway_container *con = config->handler_context.current_container; | ||
522 | if (container_is_floating(con)) { | ||
523 | // Floating containers can only resize in px. Choose an amount which | ||
524 | // uses px, with fallback to an amount that specified no unit. | ||
525 | if (first_amount.unit == RESIZE_UNIT_PX) { | ||
526 | return resize_adjust_floating(axis, &first_amount); | ||
527 | } else if (second_amount.unit == RESIZE_UNIT_PX) { | ||
528 | return resize_adjust_floating(axis, &second_amount); | ||
529 | } else if (first_amount.unit == RESIZE_UNIT_DEFAULT) { | ||
530 | return resize_adjust_floating(axis, &first_amount); | ||
531 | } else if (second_amount.unit == RESIZE_UNIT_DEFAULT) { | ||
532 | return resize_adjust_floating(axis, &second_amount); | ||
533 | } else { | ||
534 | return cmd_results_new(CMD_INVALID, "resize", | ||
535 | "Floating containers cannot use ppt measurements"); | ||
536 | } | ||
537 | } | ||
538 | |||
539 | // For tiling, prefer ppt -> default -> px | ||
540 | if (first_amount.unit == RESIZE_UNIT_PPT) { | ||
541 | return resize_adjust_tiled(axis, &first_amount); | ||
542 | } else if (second_amount.unit == RESIZE_UNIT_PPT) { | ||
543 | return resize_adjust_tiled(axis, &second_amount); | ||
544 | } else if (first_amount.unit == RESIZE_UNIT_DEFAULT) { | ||
545 | return resize_adjust_tiled(axis, &first_amount); | ||
546 | } else if (second_amount.unit == RESIZE_UNIT_DEFAULT) { | ||
547 | return resize_adjust_tiled(axis, &second_amount); | ||
548 | } else { | ||
549 | return resize_adjust_tiled(axis, &first_amount); | ||
550 | } | ||
551 | } | ||
552 | |||
553 | struct cmd_results *cmd_resize(int argc, char **argv) { | ||
554 | struct sway_container *current = config->handler_context.current_container; | ||
555 | if (!current) { | ||
556 | return cmd_results_new(CMD_INVALID, "resize", "Cannot resize nothing"); | ||
557 | } | ||
558 | if (current->type != C_VIEW && current->type != C_CONTAINER) { | ||
559 | return cmd_results_new(CMD_INVALID, "resize", | ||
560 | "Can only resize views/containers"); | ||
561 | } | ||
562 | |||
563 | struct cmd_results *error; | ||
564 | if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 2))) { | ||
565 | return error; | ||
566 | } | ||
567 | |||
568 | if (strcasecmp(argv[0], "set") == 0) { | ||
569 | return cmd_resize_set(argc - 1, &argv[1]); | ||
570 | } | ||
571 | if (strcasecmp(argv[0], "grow") == 0) { | ||
572 | return cmd_resize_adjust(argc - 1, &argv[1], 1); | ||
573 | } | ||
574 | if (strcasecmp(argv[0], "shrink") == 0) { | ||
575 | return cmd_resize_adjust(argc - 1, &argv[1], -1); | ||
576 | } | ||
577 | |||
578 | const char *usage = "Expected 'resize <shrink|grow> " | ||
579 | "<width|height|up|down|left|right> [<amount>] [px|ppt]'"; | ||
580 | |||
581 | return cmd_results_new(CMD_INVALID, "resize", usage); | ||
286 | } | 582 | } |
diff --git a/sway/commands/set.c b/sway/commands/set.c index 84e9b792..ea388d3b 100644 --- a/sway/commands/set.c +++ b/sway/commands/set.c | |||
@@ -32,7 +32,7 @@ struct cmd_results *cmd_set(int argc, char **argv) { | |||
32 | } | 32 | } |
33 | 33 | ||
34 | if (argv[0][0] != '$') { | 34 | if (argv[0][0] != '$') { |
35 | wlr_log(L_INFO, "Warning: variable '%s' doesn't start with $", argv[0]); | 35 | wlr_log(WLR_INFO, "Warning: variable '%s' doesn't start with $", argv[0]); |
36 | 36 | ||
37 | size_t size = snprintf(NULL, 0, "$%s", argv[0]); | 37 | size_t size = snprintf(NULL, 0, "$%s", argv[0]); |
38 | tmp = malloc(size + 1); | 38 | tmp = malloc(size + 1); |
diff --git a/sway/commands/smart_gaps.c b/sway/commands/smart_gaps.c index f687e78e..7d27e571 100644 --- a/sway/commands/smart_gaps.c +++ b/sway/commands/smart_gaps.c | |||
@@ -23,7 +23,7 @@ struct cmd_results *cmd_smart_gaps(int argc, char **argv) { | |||
23 | "Expected 'smart_gaps <on|off>' "); | 23 | "Expected 'smart_gaps <on|off>' "); |
24 | } | 24 | } |
25 | 25 | ||
26 | arrange_and_commit(&root_container); | 26 | arrange_windows(&root_container); |
27 | 27 | ||
28 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 28 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
29 | } | 29 | } |
diff --git a/sway/commands/split.c b/sway/commands/split.c index c40f4d9f..313799da 100644 --- a/sway/commands/split.c +++ b/sway/commands/split.c | |||
@@ -16,7 +16,7 @@ static struct cmd_results *do_split(int layout) { | |||
16 | } | 16 | } |
17 | struct sway_container *parent = container_split(con, layout); | 17 | struct sway_container *parent = container_split(con, layout); |
18 | container_create_notify(parent); | 18 | container_create_notify(parent); |
19 | arrange_and_commit(parent->parent); | 19 | arrange_windows(parent->parent); |
20 | 20 | ||
21 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 21 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
22 | } | 22 | } |
diff --git a/sway/commands/swap.c b/sway/commands/swap.c index e052058f..2fc88308 100644 --- a/sway/commands/swap.c +++ b/sway/commands/swap.c | |||
@@ -1,7 +1,6 @@ | |||
1 | #include <strings.h> | 1 | #include <strings.h> |
2 | #include <wlr/util/log.h> | 2 | #include <wlr/util/log.h> |
3 | #include "sway/commands.h" | 3 | #include "sway/commands.h" |
4 | #include "sway/desktop/transaction.h" | ||
5 | #include "sway/tree/arrange.h" | 4 | #include "sway/tree/arrange.h" |
6 | #include "sway/tree/layout.h" | 5 | #include "sway/tree/layout.h" |
7 | #include "sway/tree/view.h" | 6 | #include "sway/tree/view.h" |
@@ -79,14 +78,10 @@ struct cmd_results *cmd_swap(int argc, char **argv) { | |||
79 | 78 | ||
80 | container_swap(current, other); | 79 | container_swap(current, other); |
81 | 80 | ||
82 | struct sway_transaction *txn = transaction_create(); | 81 | arrange_windows(current->parent); |
83 | arrange_windows(current->parent, txn); | ||
84 | |||
85 | if (other->parent != current->parent) { | 82 | if (other->parent != current->parent) { |
86 | arrange_windows(other->parent, txn); | 83 | arrange_windows(other->parent); |
87 | } | 84 | } |
88 | 85 | ||
89 | transaction_commit(txn); | ||
90 | |||
91 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 86 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
92 | } | 87 | } |
diff --git a/sway/commands/swaybg_command.c b/sway/commands/swaybg_command.c index 770d4821..36f7fdcd 100644 --- a/sway/commands/swaybg_command.c +++ b/sway/commands/swaybg_command.c | |||
@@ -13,7 +13,7 @@ struct cmd_results *cmd_swaybg_command(int argc, char **argv) { | |||
13 | free(config->swaybg_command); | 13 | free(config->swaybg_command); |
14 | } | 14 | } |
15 | config->swaybg_command = join_args(argv, argc); | 15 | config->swaybg_command = join_args(argv, argc); |
16 | wlr_log(L_DEBUG, "Using custom swaybg command: %s", | 16 | wlr_log(WLR_DEBUG, "Using custom swaybg command: %s", |
17 | config->swaybg_command); | 17 | config->swaybg_command); |
18 | 18 | ||
19 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 19 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
diff --git a/sway/commands/urgent.c b/sway/commands/urgent.c new file mode 100644 index 00000000..d199858a --- /dev/null +++ b/sway/commands/urgent.c | |||
@@ -0,0 +1,36 @@ | |||
1 | #include "log.h" | ||
2 | #include "sway/commands.h" | ||
3 | #include "sway/config.h" | ||
4 | #include "sway/tree/arrange.h" | ||
5 | #include "sway/tree/container.h" | ||
6 | #include "sway/tree/view.h" | ||
7 | #include "sway/tree/layout.h" | ||
8 | |||
9 | struct cmd_results *cmd_urgent(int argc, char **argv) { | ||
10 | struct cmd_results *error = NULL; | ||
11 | if ((error = checkarg(argc, "urgent", EXPECTED_EQUAL_TO, 1))) { | ||
12 | return error; | ||
13 | } | ||
14 | struct sway_container *container = | ||
15 | config->handler_context.current_container; | ||
16 | if (container->type != C_VIEW) { | ||
17 | return cmd_results_new(CMD_INVALID, "urgent", | ||
18 | "Only views can be urgent"); | ||
19 | } | ||
20 | struct sway_view *view = container->sway_view; | ||
21 | |||
22 | if (strcmp(argv[0], "enable") == 0) { | ||
23 | view_set_urgent(view, true); | ||
24 | } else if (strcmp(argv[0], "disable") == 0) { | ||
25 | view_set_urgent(view, false); | ||
26 | } else if (strcmp(argv[0], "allow") == 0) { | ||
27 | view->allow_request_urgent = true; | ||
28 | } else if (strcmp(argv[0], "deny") == 0) { | ||
29 | view->allow_request_urgent = false; | ||
30 | } else { | ||
31 | return cmd_results_new(CMD_INVALID, "urgent", | ||
32 | "Expected 'urgent <enable|disable|allow|deny>'"); | ||
33 | } | ||
34 | |||
35 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
36 | } | ||
diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index d15be571..e8b37182 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c | |||
@@ -51,7 +51,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { | |||
51 | free(old); // workspaces can only be assigned to a single output | 51 | free(old); // workspaces can only be assigned to a single output |
52 | list_del(config->workspace_outputs, i); | 52 | list_del(config->workspace_outputs, i); |
53 | } | 53 | } |
54 | wlr_log(L_DEBUG, "Assigning workspace %s to output %s", wso->workspace, wso->output); | 54 | wlr_log(WLR_DEBUG, "Assigning workspace %s to output %s", wso->workspace, wso->output); |
55 | list_add(config->workspace_outputs, wso); | 55 | list_add(config->workspace_outputs, wso); |
56 | } else { | 56 | } else { |
57 | if (config->reading || !config->active) { | 57 | if (config->reading || !config->active) { |
diff --git a/sway/config.c b/sway/config.c index 89b7d349..c620e4c7 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "sway/input/seat.h" | 24 | #include "sway/input/seat.h" |
25 | #include "sway/commands.h" | 25 | #include "sway/commands.h" |
26 | #include "sway/config.h" | 26 | #include "sway/config.h" |
27 | #include "sway/criteria.h" | ||
27 | #include "sway/tree/arrange.h" | 28 | #include "sway/tree/arrange.h" |
28 | #include "sway/tree/layout.h" | 29 | #include "sway/tree/layout.h" |
29 | #include "sway/tree/workspace.h" | 30 | #include "sway/tree/workspace.h" |
@@ -105,7 +106,12 @@ void free_config(struct sway_config *config) { | |||
105 | } | 106 | } |
106 | list_free(config->seat_configs); | 107 | list_free(config->seat_configs); |
107 | } | 108 | } |
108 | list_free(config->criteria); | 109 | if (config->criteria) { |
110 | for (int i = 0; i < config->criteria->length; ++i) { | ||
111 | criteria_destroy(config->criteria->items[i]); | ||
112 | } | ||
113 | list_free(config->criteria); | ||
114 | } | ||
109 | list_free(config->no_focus); | 115 | list_free(config->no_focus); |
110 | list_free(config->active_bar_modifiers); | 116 | list_free(config->active_bar_modifiers); |
111 | list_free(config->config_chain); | 117 | list_free(config->config_chain); |
@@ -117,6 +123,7 @@ void free_config(struct sway_config *config) { | |||
117 | free(config->floating_scroll_left_cmd); | 123 | free(config->floating_scroll_left_cmd); |
118 | free(config->floating_scroll_right_cmd); | 124 | free(config->floating_scroll_right_cmd); |
119 | free(config->font); | 125 | free(config->font); |
126 | free((char *)config->current_config_path); | ||
120 | free((char *)config->current_config); | 127 | free((char *)config->current_config); |
121 | free(config); | 128 | free(config); |
122 | } | 129 | } |
@@ -205,6 +212,7 @@ static void config_defaults(struct sway_config *config) { | |||
205 | if (!(config->active_bar_modifiers = create_list())) goto cleanup; | 212 | if (!(config->active_bar_modifiers = create_list())) goto cleanup; |
206 | 213 | ||
207 | if (!(config->config_chain = create_list())) goto cleanup; | 214 | if (!(config->config_chain = create_list())) goto cleanup; |
215 | config->current_config_path = NULL; | ||
208 | config->current_config = NULL; | 216 | config->current_config = NULL; |
209 | 217 | ||
210 | // borders | 218 | // borders |
@@ -276,12 +284,12 @@ static char *get_config_path(void) { | |||
276 | char *home = getenv("HOME"); | 284 | char *home = getenv("HOME"); |
277 | char *config_home = malloc(strlen(home) + strlen("/.config") + 1); | 285 | char *config_home = malloc(strlen(home) + strlen("/.config") + 1); |
278 | if (!config_home) { | 286 | if (!config_home) { |
279 | wlr_log(L_ERROR, "Unable to allocate $HOME/.config"); | 287 | wlr_log(WLR_ERROR, "Unable to allocate $HOME/.config"); |
280 | } else { | 288 | } else { |
281 | strcpy(config_home, home); | 289 | strcpy(config_home, home); |
282 | strcat(config_home, "/.config"); | 290 | strcat(config_home, "/.config"); |
283 | setenv("XDG_CONFIG_HOME", config_home, 1); | 291 | setenv("XDG_CONFIG_HOME", config_home, 1); |
284 | wlr_log(L_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home); | 292 | wlr_log(WLR_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home); |
285 | free(config_home); | 293 | free(config_home); |
286 | } | 294 | } |
287 | } | 295 | } |
@@ -304,16 +312,13 @@ static char *get_config_path(void) { | |||
304 | return NULL; // Not reached | 312 | return NULL; // Not reached |
305 | } | 313 | } |
306 | 314 | ||
307 | const char *current_config_path; | ||
308 | |||
309 | static bool load_config(const char *path, struct sway_config *config) { | 315 | static bool load_config(const char *path, struct sway_config *config) { |
310 | if (path == NULL) { | 316 | if (path == NULL) { |
311 | wlr_log(L_ERROR, "Unable to find a config file!"); | 317 | wlr_log(WLR_ERROR, "Unable to find a config file!"); |
312 | return false; | 318 | return false; |
313 | } | 319 | } |
314 | 320 | ||
315 | wlr_log(L_INFO, "Loading config from %s", path); | 321 | wlr_log(WLR_INFO, "Loading config from %s", path); |
316 | current_config_path = path; | ||
317 | 322 | ||
318 | struct stat sb; | 323 | struct stat sb; |
319 | if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { | 324 | if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { |
@@ -322,7 +327,7 @@ static bool load_config(const char *path, struct sway_config *config) { | |||
322 | 327 | ||
323 | FILE *f = fopen(path, "r"); | 328 | FILE *f = fopen(path, "r"); |
324 | if (!f) { | 329 | if (!f) { |
325 | wlr_log(L_ERROR, "Unable to open %s for reading", path); | 330 | wlr_log(WLR_ERROR, "Unable to open %s for reading", path); |
326 | return false; | 331 | return false; |
327 | } | 332 | } |
328 | 333 | ||
@@ -330,10 +335,9 @@ static bool load_config(const char *path, struct sway_config *config) { | |||
330 | fclose(f); | 335 | fclose(f); |
331 | 336 | ||
332 | if (!config_load_success) { | 337 | if (!config_load_success) { |
333 | wlr_log(L_ERROR, "Error(s) loading config!"); | 338 | wlr_log(WLR_ERROR, "Error(s) loading config!"); |
334 | } | 339 | } |
335 | 340 | ||
336 | current_config_path = NULL; | ||
337 | return true; | 341 | return true; |
338 | } | 342 | } |
339 | 343 | ||
@@ -353,12 +357,12 @@ bool load_main_config(const char *file, bool is_active) { | |||
353 | 357 | ||
354 | config_defaults(config); | 358 | config_defaults(config); |
355 | if (is_active) { | 359 | if (is_active) { |
356 | wlr_log(L_DEBUG, "Performing configuration file reload"); | 360 | wlr_log(WLR_DEBUG, "Performing configuration file reload"); |
357 | config->reloading = true; | 361 | config->reloading = true; |
358 | config->active = true; | 362 | config->active = true; |
359 | } | 363 | } |
360 | 364 | ||
361 | config->current_config = path; | 365 | config->current_config_path = path; |
362 | list_add(config->config_chain, path); | 366 | list_add(config->config_chain, path); |
363 | 367 | ||
364 | config->reading = true; | 368 | config->reading = true; |
@@ -369,7 +373,7 @@ bool load_main_config(const char *file, bool is_active) { | |||
369 | /* | 373 | /* |
370 | DIR *dir = opendir(SYSCONFDIR "/sway/security.d"); | 374 | DIR *dir = opendir(SYSCONFDIR "/sway/security.d"); |
371 | if (!dir) { | 375 | if (!dir) { |
372 | wlr_log(L_ERROR, | 376 | wlr_log(WLR_ERROR, |
373 | "%s does not exist, sway will have no security configuration" | 377 | "%s does not exist, sway will have no security configuration" |
374 | " and will probably be broken", SYSCONFDIR "/sway/security.d"); | 378 | " and will probably be broken", SYSCONFDIR "/sway/security.d"); |
375 | } else { | 379 | } else { |
@@ -398,7 +402,7 @@ bool load_main_config(const char *file, bool is_active) { | |||
398 | if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 || | 402 | if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 || |
399 | (((s.st_mode & 0777) != 0644) && | 403 | (((s.st_mode & 0777) != 0644) && |
400 | (s.st_mode & 0777) != 0444)) { | 404 | (s.st_mode & 0777) != 0444)) { |
401 | wlr_log(L_ERROR, | 405 | wlr_log(WLR_ERROR, |
402 | "Refusing to load %s - it must be owned by root " | 406 | "Refusing to load %s - it must be owned by root " |
403 | "and mode 644 or 444", _path); | 407 | "and mode 644 or 444", _path); |
404 | success = false; | 408 | success = false; |
@@ -428,7 +432,7 @@ bool load_main_config(const char *file, bool is_active) { | |||
428 | static bool load_include_config(const char *path, const char *parent_dir, | 432 | static bool load_include_config(const char *path, const char *parent_dir, |
429 | struct sway_config *config) { | 433 | struct sway_config *config) { |
430 | // save parent config | 434 | // save parent config |
431 | const char *parent_config = config->current_config; | 435 | const char *parent_config = config->current_config_path; |
432 | 436 | ||
433 | char *full_path; | 437 | char *full_path; |
434 | int len = strlen(path); | 438 | int len = strlen(path); |
@@ -436,7 +440,7 @@ static bool load_include_config(const char *path, const char *parent_dir, | |||
436 | len = len + strlen(parent_dir) + 2; | 440 | len = len + strlen(parent_dir) + 2; |
437 | full_path = malloc(len * sizeof(char)); | 441 | full_path = malloc(len * sizeof(char)); |
438 | if (!full_path) { | 442 | if (!full_path) { |
439 | wlr_log(L_ERROR, | 443 | wlr_log(WLR_ERROR, |
440 | "Unable to allocate full path to included config"); | 444 | "Unable to allocate full path to included config"); |
441 | return false; | 445 | return false; |
442 | } | 446 | } |
@@ -449,7 +453,7 @@ static bool load_include_config(const char *path, const char *parent_dir, | |||
449 | free(full_path); | 453 | free(full_path); |
450 | 454 | ||
451 | if (real_path == NULL) { | 455 | if (real_path == NULL) { |
452 | wlr_log(L_DEBUG, "%s not found.", path); | 456 | wlr_log(WLR_DEBUG, "%s not found.", path); |
453 | return false; | 457 | return false; |
454 | } | 458 | } |
455 | 459 | ||
@@ -458,7 +462,7 @@ static bool load_include_config(const char *path, const char *parent_dir, | |||
458 | for (j = 0; j < config->config_chain->length; ++j) { | 462 | for (j = 0; j < config->config_chain->length; ++j) { |
459 | char *old_path = config->config_chain->items[j]; | 463 | char *old_path = config->config_chain->items[j]; |
460 | if (strcmp(real_path, old_path) == 0) { | 464 | if (strcmp(real_path, old_path) == 0) { |
461 | wlr_log(L_DEBUG, | 465 | wlr_log(WLR_DEBUG, |
462 | "%s already included once, won't be included again.", | 466 | "%s already included once, won't be included again.", |
463 | real_path); | 467 | real_path); |
464 | free(real_path); | 468 | free(real_path); |
@@ -466,25 +470,25 @@ static bool load_include_config(const char *path, const char *parent_dir, | |||
466 | } | 470 | } |
467 | } | 471 | } |
468 | 472 | ||
469 | config->current_config = real_path; | 473 | config->current_config_path = real_path; |
470 | list_add(config->config_chain, real_path); | 474 | list_add(config->config_chain, real_path); |
471 | int index = config->config_chain->length - 1; | 475 | int index = config->config_chain->length - 1; |
472 | 476 | ||
473 | if (!load_config(real_path, config)) { | 477 | if (!load_config(real_path, config)) { |
474 | free(real_path); | 478 | free(real_path); |
475 | config->current_config = parent_config; | 479 | config->current_config_path = parent_config; |
476 | list_del(config->config_chain, index); | 480 | list_del(config->config_chain, index); |
477 | return false; | 481 | return false; |
478 | } | 482 | } |
479 | 483 | ||
480 | // restore current_config | 484 | // restore current_config_path |
481 | config->current_config = parent_config; | 485 | config->current_config_path = parent_config; |
482 | return true; | 486 | return true; |
483 | } | 487 | } |
484 | 488 | ||
485 | bool load_include_configs(const char *path, struct sway_config *config) { | 489 | bool load_include_configs(const char *path, struct sway_config *config) { |
486 | char *wd = getcwd(NULL, 0); | 490 | char *wd = getcwd(NULL, 0); |
487 | char *parent_path = strdup(config->current_config); | 491 | char *parent_path = strdup(config->current_config_path); |
488 | const char *parent_dir = dirname(parent_path); | 492 | const char *parent_dir = dirname(parent_path); |
489 | 493 | ||
490 | if (chdir(parent_dir) < 0) { | 494 | if (chdir(parent_dir) < 0) { |
@@ -512,7 +516,7 @@ bool load_include_configs(const char *path, struct sway_config *config) { | |||
512 | // restore wd | 516 | // restore wd |
513 | if (chdir(wd) < 0) { | 517 | if (chdir(wd) < 0) { |
514 | free(wd); | 518 | free(wd); |
515 | wlr_log(L_ERROR, "failed to restore working directory"); | 519 | wlr_log(WLR_ERROR, "failed to restore working directory"); |
516 | return false; | 520 | return false; |
517 | } | 521 | } |
518 | 522 | ||
@@ -527,13 +531,13 @@ static int detect_brace_on_following_line(FILE *file, char *line, | |||
527 | char *peeked = NULL; | 531 | char *peeked = NULL; |
528 | long position = 0; | 532 | long position = 0; |
529 | do { | 533 | do { |
530 | wlr_log(L_DEBUG, "Peeking line %d", line_number + lines + 1); | 534 | wlr_log(WLR_DEBUG, "Peeking line %d", line_number + lines + 1); |
531 | free(peeked); | 535 | free(peeked); |
532 | peeked = peek_line(file, lines, &position); | 536 | peeked = peek_line(file, lines, &position); |
533 | if (peeked) { | 537 | if (peeked) { |
534 | peeked = strip_whitespace(peeked); | 538 | peeked = strip_whitespace(peeked); |
535 | } | 539 | } |
536 | wlr_log(L_DEBUG, "Peeked line: `%s`", peeked); | 540 | wlr_log(WLR_DEBUG, "Peeked line: `%s`", peeked); |
537 | lines++; | 541 | lines++; |
538 | } while (peeked && strlen(peeked) == 0); | 542 | } while (peeked && strlen(peeked) == 0); |
539 | 543 | ||
@@ -552,7 +556,7 @@ static char *expand_line(const char *block, const char *line, bool add_brace) { | |||
552 | + (add_brace ? 2 : 0) + 1; | 556 | + (add_brace ? 2 : 0) + 1; |
553 | char *expanded = calloc(1, size); | 557 | char *expanded = calloc(1, size); |
554 | if (!expanded) { | 558 | if (!expanded) { |
555 | wlr_log(L_ERROR, "Cannot allocate expanded line buffer"); | 559 | wlr_log(WLR_ERROR, "Cannot allocate expanded line buffer"); |
556 | return NULL; | 560 | return NULL; |
557 | } | 561 | } |
558 | snprintf(expanded, size, "%s%s%s%s", block ? block : "", | 562 | snprintf(expanded, size, "%s%s%s%s", block ? block : "", |
@@ -561,10 +565,33 @@ static char *expand_line(const char *block, const char *line, bool add_brace) { | |||
561 | } | 565 | } |
562 | 566 | ||
563 | bool read_config(FILE *file, struct sway_config *config) { | 567 | bool read_config(FILE *file, struct sway_config *config) { |
568 | bool reading_main_config = false; | ||
569 | char *this_config = NULL; | ||
570 | size_t config_size = 0; | ||
571 | if (config->current_config == NULL) { | ||
572 | reading_main_config = true; | ||
573 | |||
574 | int ret_seek = fseek(file, 0, SEEK_END); | ||
575 | long ret_tell = ftell(file); | ||
576 | if (ret_seek == -1 || ret_tell == -1) { | ||
577 | wlr_log(WLR_ERROR, "Unable to get size of config file"); | ||
578 | return false; | ||
579 | } | ||
580 | config_size = ret_tell; | ||
581 | rewind(file); | ||
582 | |||
583 | config->current_config = this_config = calloc(1, config_size + 1); | ||
584 | if (this_config == NULL) { | ||
585 | wlr_log(WLR_ERROR, "Unable to allocate buffer for config contents"); | ||
586 | return false; | ||
587 | } | ||
588 | } | ||
589 | |||
564 | bool success = true; | 590 | bool success = true; |
565 | int line_number = 0; | 591 | int line_number = 0; |
566 | char *line; | 592 | char *line; |
567 | list_t *stack = create_list(); | 593 | list_t *stack = create_list(); |
594 | size_t read = 0; | ||
568 | while (!feof(file)) { | 595 | while (!feof(file)) { |
569 | char *block = stack->length ? stack->items[0] : NULL; | 596 | char *block = stack->length ? stack->items[0] : NULL; |
570 | line = read_line(file); | 597 | line = read_line(file); |
@@ -572,7 +599,26 @@ bool read_config(FILE *file, struct sway_config *config) { | |||
572 | continue; | 599 | continue; |
573 | } | 600 | } |
574 | line_number++; | 601 | line_number++; |
575 | wlr_log(L_DEBUG, "Read line %d: %s", line_number, line); | 602 | wlr_log(WLR_DEBUG, "Read line %d: %s", line_number, line); |
603 | |||
604 | if (reading_main_config) { | ||
605 | size_t length = strlen(line); | ||
606 | |||
607 | if (read + length > config_size) { | ||
608 | wlr_log(WLR_ERROR, "Config file changed during reading"); | ||
609 | list_foreach(stack, free); | ||
610 | list_free(stack); | ||
611 | free(line); | ||
612 | return false; | ||
613 | } | ||
614 | |||
615 | strcpy(this_config + read, line); | ||
616 | if (line_number != 1) { | ||
617 | this_config[read - 1] = '\n'; | ||
618 | } | ||
619 | read += length + 1; | ||
620 | } | ||
621 | |||
576 | line = strip_whitespace(line); | 622 | line = strip_whitespace(line); |
577 | if (line[0] == '#') { | 623 | if (line[0] == '#') { |
578 | free(line); | 624 | free(line); |
@@ -586,15 +632,16 @@ bool read_config(FILE *file, struct sway_config *config) { | |||
586 | line_number); | 632 | line_number); |
587 | if (brace_detected > 0) { | 633 | if (brace_detected > 0) { |
588 | line_number += brace_detected; | 634 | line_number += brace_detected; |
589 | wlr_log(L_DEBUG, "Detected open brace on line %d", line_number); | 635 | wlr_log(WLR_DEBUG, "Detected open brace on line %d", line_number); |
590 | } | 636 | } |
591 | char *expanded = expand_line(block, line, brace_detected > 0); | 637 | char *expanded = expand_line(block, line, brace_detected > 0); |
592 | if (!expanded) { | 638 | if (!expanded) { |
593 | list_foreach(stack, free); | 639 | list_foreach(stack, free); |
594 | list_free(stack); | 640 | list_free(stack); |
641 | free(line); | ||
595 | return false; | 642 | return false; |
596 | } | 643 | } |
597 | wlr_log(L_DEBUG, "Expanded line: %s", expanded); | 644 | wlr_log(WLR_DEBUG, "Expanded line: %s", expanded); |
598 | struct cmd_results *res; | 645 | struct cmd_results *res; |
599 | if (block && strcmp(block, "<commands>") == 0) { | 646 | if (block && strcmp(block, "<commands>") == 0) { |
600 | // Special case | 647 | // Special case |
@@ -606,23 +653,23 @@ bool read_config(FILE *file, struct sway_config *config) { | |||
606 | switch(res->status) { | 653 | switch(res->status) { |
607 | case CMD_FAILURE: | 654 | case CMD_FAILURE: |
608 | case CMD_INVALID: | 655 | case CMD_INVALID: |
609 | wlr_log(L_ERROR, "Error on line %i '%s': %s (%s)", line_number, | 656 | wlr_log(WLR_ERROR, "Error on line %i '%s': %s (%s)", line_number, |
610 | line, res->error, config->current_config); | 657 | line, res->error, config->current_config_path); |
611 | success = false; | 658 | success = false; |
612 | break; | 659 | break; |
613 | 660 | ||
614 | case CMD_DEFER: | 661 | case CMD_DEFER: |
615 | wlr_log(L_DEBUG, "Deferring command `%s'", line); | 662 | wlr_log(WLR_DEBUG, "Deferring command `%s'", line); |
616 | list_add(config->cmd_queue, strdup(line)); | 663 | list_add(config->cmd_queue, strdup(line)); |
617 | break; | 664 | break; |
618 | 665 | ||
619 | case CMD_BLOCK_COMMANDS: | 666 | case CMD_BLOCK_COMMANDS: |
620 | wlr_log(L_DEBUG, "Entering commands block"); | 667 | wlr_log(WLR_DEBUG, "Entering commands block"); |
621 | list_insert(stack, 0, "<commands>"); | 668 | list_insert(stack, 0, "<commands>"); |
622 | break; | 669 | break; |
623 | 670 | ||
624 | case CMD_BLOCK: | 671 | case CMD_BLOCK: |
625 | wlr_log(L_DEBUG, "Entering block '%s'", res->input); | 672 | wlr_log(WLR_DEBUG, "Entering block '%s'", res->input); |
626 | list_insert(stack, 0, strdup(res->input)); | 673 | list_insert(stack, 0, strdup(res->input)); |
627 | if (strcmp(res->input, "bar") == 0) { | 674 | if (strcmp(res->input, "bar") == 0) { |
628 | config->current_bar = NULL; | 675 | config->current_bar = NULL; |
@@ -631,7 +678,7 @@ bool read_config(FILE *file, struct sway_config *config) { | |||
631 | 678 | ||
632 | case CMD_BLOCK_END: | 679 | case CMD_BLOCK_END: |
633 | if (!block) { | 680 | if (!block) { |
634 | wlr_log(L_DEBUG, "Unmatched '}' on line %i", line_number); | 681 | wlr_log(WLR_DEBUG, "Unmatched '}' on line %i", line_number); |
635 | success = false; | 682 | success = false; |
636 | break; | 683 | break; |
637 | } | 684 | } |
@@ -639,7 +686,7 @@ bool read_config(FILE *file, struct sway_config *config) { | |||
639 | config->current_bar = NULL; | 686 | config->current_bar = NULL; |
640 | } | 687 | } |
641 | 688 | ||
642 | wlr_log(L_DEBUG, "Exiting block '%s'", block); | 689 | wlr_log(WLR_DEBUG, "Exiting block '%s'", block); |
643 | list_del(stack, 0); | 690 | list_del(stack, 0); |
644 | free(block); | 691 | free(block); |
645 | memset(&config->handler_context, 0, | 692 | memset(&config->handler_context, 0, |
@@ -682,7 +729,7 @@ char *do_var_replacement(char *str) { | |||
682 | int vvlen = strlen(var->value); | 729 | int vvlen = strlen(var->value); |
683 | char *newstr = malloc(strlen(str) - vnlen + vvlen + 1); | 730 | char *newstr = malloc(strlen(str) - vnlen + vvlen + 1); |
684 | if (!newstr) { | 731 | if (!newstr) { |
685 | wlr_log(L_ERROR, | 732 | wlr_log(WLR_ERROR, |
686 | "Unable to allocate replacement " | 733 | "Unable to allocate replacement " |
687 | "during variable expansion"); | 734 | "during variable expansion"); |
688 | break; | 735 | break; |
@@ -744,6 +791,6 @@ void config_update_font_height(bool recalculate) { | |||
744 | } | 791 | } |
745 | 792 | ||
746 | if (config->font_height != prev_max_height) { | 793 | if (config->font_height != prev_max_height) { |
747 | arrange_and_commit(&root_container); | 794 | arrange_windows(&root_container); |
748 | } | 795 | } |
749 | } | 796 | } |
diff --git a/sway/config/bar.c b/sway/config/bar.c index ee062c6a..3a74331e 100644 --- a/sway/config/bar.c +++ b/sway/config/bar.c | |||
@@ -16,10 +16,10 @@ | |||
16 | #include "log.h" | 16 | #include "log.h" |
17 | 17 | ||
18 | static void terminate_swaybar(pid_t pid) { | 18 | static void terminate_swaybar(pid_t pid) { |
19 | wlr_log(L_DEBUG, "Terminating swaybar %d", pid); | 19 | wlr_log(WLR_DEBUG, "Terminating swaybar %d", pid); |
20 | int ret = kill(-pid, SIGTERM); | 20 | int ret = kill(-pid, SIGTERM); |
21 | if (ret != 0) { | 21 | if (ret != 0) { |
22 | wlr_log_errno(L_ERROR, "Unable to terminate swaybar %d", pid); | 22 | wlr_log_errno(WLR_ERROR, "Unable to terminate swaybar %d", pid); |
23 | } else { | 23 | } else { |
24 | int status; | 24 | int status; |
25 | waitpid(pid, &status, 0); | 25 | waitpid(pid, &status, 0); |
@@ -167,7 +167,7 @@ void invoke_swaybar(struct bar_config *bar) { | |||
167 | // Pipe to communicate errors | 167 | // Pipe to communicate errors |
168 | int filedes[2]; | 168 | int filedes[2]; |
169 | if (pipe(filedes) == -1) { | 169 | if (pipe(filedes) == -1) { |
170 | wlr_log(L_ERROR, "Pipe setup failed! Cannot fork into bar"); | 170 | wlr_log(WLR_ERROR, "Pipe setup failed! Cannot fork into bar"); |
171 | return; | 171 | return; |
172 | } | 172 | } |
173 | 173 | ||
@@ -197,17 +197,17 @@ void invoke_swaybar(struct bar_config *bar) { | |||
197 | execvp(cmd[0], cmd); | 197 | execvp(cmd[0], cmd); |
198 | exit(1); | 198 | exit(1); |
199 | } | 199 | } |
200 | wlr_log(L_DEBUG, "Spawned swaybar %d", bar->pid); | 200 | wlr_log(WLR_DEBUG, "Spawned swaybar %d", bar->pid); |
201 | close(filedes[0]); | 201 | close(filedes[0]); |
202 | size_t len; | 202 | size_t len; |
203 | if (read(filedes[1], &len, sizeof(size_t)) == sizeof(size_t)) { | 203 | if (read(filedes[1], &len, sizeof(size_t)) == sizeof(size_t)) { |
204 | char *buf = malloc(len); | 204 | char *buf = malloc(len); |
205 | if(!buf) { | 205 | if(!buf) { |
206 | wlr_log(L_ERROR, "Cannot allocate error string"); | 206 | wlr_log(WLR_ERROR, "Cannot allocate error string"); |
207 | return; | 207 | return; |
208 | } | 208 | } |
209 | if (read(filedes[1], buf, len)) { | 209 | if (read(filedes[1], buf, len)) { |
210 | wlr_log(L_ERROR, "%s", buf); | 210 | wlr_log(WLR_ERROR, "%s", buf); |
211 | } | 211 | } |
212 | free(buf); | 212 | free(buf); |
213 | } | 213 | } |
@@ -244,7 +244,7 @@ void load_swaybars() { | |||
244 | if (bar->pid != 0) { | 244 | if (bar->pid != 0) { |
245 | terminate_swaybar(bar->pid); | 245 | terminate_swaybar(bar->pid); |
246 | } | 246 | } |
247 | wlr_log(L_DEBUG, "Invoking swaybar for bar id '%s'", bar->id); | 247 | wlr_log(WLR_DEBUG, "Invoking swaybar for bar id '%s'", bar->id); |
248 | invoke_swaybar(bar); | 248 | invoke_swaybar(bar); |
249 | } | 249 | } |
250 | } | 250 | } |
diff --git a/sway/config/input.c b/sway/config/input.c index 17303ccc..8d687a6d 100644 --- a/sway/config/input.c +++ b/sway/config/input.c | |||
@@ -8,17 +8,18 @@ | |||
8 | struct input_config *new_input_config(const char* identifier) { | 8 | struct input_config *new_input_config(const char* identifier) { |
9 | struct input_config *input = calloc(1, sizeof(struct input_config)); | 9 | struct input_config *input = calloc(1, sizeof(struct input_config)); |
10 | if (!input) { | 10 | if (!input) { |
11 | wlr_log(L_DEBUG, "Unable to allocate input config"); | 11 | wlr_log(WLR_DEBUG, "Unable to allocate input config"); |
12 | return NULL; | 12 | return NULL; |
13 | } | 13 | } |
14 | wlr_log(L_DEBUG, "new_input_config(%s)", identifier); | 14 | wlr_log(WLR_DEBUG, "new_input_config(%s)", identifier); |
15 | if (!(input->identifier = strdup(identifier))) { | 15 | if (!(input->identifier = strdup(identifier))) { |
16 | free(input); | 16 | free(input); |
17 | wlr_log(L_DEBUG, "Unable to allocate input config"); | 17 | wlr_log(WLR_DEBUG, "Unable to allocate input config"); |
18 | return NULL; | 18 | return NULL; |
19 | } | 19 | } |
20 | 20 | ||
21 | input->tap = INT_MIN; | 21 | input->tap = INT_MIN; |
22 | input->tap_button_map = INT_MIN; | ||
22 | input->drag_lock = INT_MIN; | 23 | input->drag_lock = INT_MIN; |
23 | input->dwt = INT_MIN; | 24 | input->dwt = INT_MIN; |
24 | input->send_events = INT_MIN; | 25 | input->send_events = INT_MIN; |
@@ -27,6 +28,7 @@ struct input_config *new_input_config(const char* identifier) { | |||
27 | input->natural_scroll = INT_MIN; | 28 | input->natural_scroll = INT_MIN; |
28 | input->accel_profile = INT_MIN; | 29 | input->accel_profile = INT_MIN; |
29 | input->pointer_accel = FLT_MIN; | 30 | input->pointer_accel = FLT_MIN; |
31 | input->scroll_button = INT_MIN; | ||
30 | input->scroll_method = INT_MIN; | 32 | input->scroll_method = INT_MIN; |
31 | input->left_handed = INT_MIN; | 33 | input->left_handed = INT_MIN; |
32 | input->repeat_delay = INT_MIN; | 34 | input->repeat_delay = INT_MIN; |
@@ -70,12 +72,18 @@ void merge_input_config(struct input_config *dst, struct input_config *src) { | |||
70 | if (src->scroll_method != INT_MIN) { | 72 | if (src->scroll_method != INT_MIN) { |
71 | dst->scroll_method = src->scroll_method; | 73 | dst->scroll_method = src->scroll_method; |
72 | } | 74 | } |
75 | if (src->scroll_button != INT_MIN) { | ||
76 | dst->scroll_button = src->scroll_button; | ||
77 | } | ||
73 | if (src->send_events != INT_MIN) { | 78 | if (src->send_events != INT_MIN) { |
74 | dst->send_events = src->send_events; | 79 | dst->send_events = src->send_events; |
75 | } | 80 | } |
76 | if (src->tap != INT_MIN) { | 81 | if (src->tap != INT_MIN) { |
77 | dst->tap = src->tap; | 82 | dst->tap = src->tap; |
78 | } | 83 | } |
84 | if (src->tap_button_map != INT_MIN) { | ||
85 | dst->tap_button_map = src->tap_button_map; | ||
86 | } | ||
79 | if (src->xkb_layout) { | 87 | if (src->xkb_layout) { |
80 | free(dst->xkb_layout); | 88 | free(dst->xkb_layout); |
81 | dst->xkb_layout = strdup(src->xkb_layout); | 89 | dst->xkb_layout = strdup(src->xkb_layout); |
@@ -112,7 +120,7 @@ void merge_input_config(struct input_config *dst, struct input_config *src) { | |||
112 | struct input_config *copy_input_config(struct input_config *ic) { | 120 | struct input_config *copy_input_config(struct input_config *ic) { |
113 | struct input_config *copy = calloc(1, sizeof(struct input_config)); | 121 | struct input_config *copy = calloc(1, sizeof(struct input_config)); |
114 | if (copy == NULL) { | 122 | if (copy == NULL) { |
115 | wlr_log(L_ERROR, "could not allocate input config"); | 123 | wlr_log(WLR_ERROR, "could not allocate input config"); |
116 | return NULL; | 124 | return NULL; |
117 | } | 125 | } |
118 | merge_input_config(copy, ic); | 126 | merge_input_config(copy, ic); |
diff --git a/sway/config/output.c b/sway/config/output.c index 648ded27..1bf9e5f1 100644 --- a/sway/config/output.c +++ b/sway/config/output.c | |||
@@ -90,7 +90,7 @@ static void set_mode(struct wlr_output *output, int width, int height, | |||
90 | float refresh_rate) { | 90 | float refresh_rate) { |
91 | int mhz = (int)(refresh_rate * 1000); | 91 | int mhz = (int)(refresh_rate * 1000); |
92 | if (wl_list_empty(&output->modes)) { | 92 | if (wl_list_empty(&output->modes)) { |
93 | wlr_log(L_DEBUG, "Assigning custom mode to %s", output->name); | 93 | wlr_log(WLR_DEBUG, "Assigning custom mode to %s", output->name); |
94 | wlr_output_set_custom_mode(output, width, height, mhz); | 94 | wlr_output_set_custom_mode(output, width, height, mhz); |
95 | return; | 95 | return; |
96 | } | 96 | } |
@@ -106,9 +106,9 @@ static void set_mode(struct wlr_output *output, int width, int height, | |||
106 | } | 106 | } |
107 | } | 107 | } |
108 | if (!best) { | 108 | if (!best) { |
109 | wlr_log(L_ERROR, "Configured mode for %s not available", output->name); | 109 | wlr_log(WLR_ERROR, "Configured mode for %s not available", output->name); |
110 | } else { | 110 | } else { |
111 | wlr_log(L_DEBUG, "Assigning configured mode to %s", output->name); | 111 | wlr_log(WLR_DEBUG, "Assigning configured mode to %s", output->name); |
112 | wlr_output_set_mode(output, best); | 112 | wlr_output_set_mode(output, best); |
113 | } | 113 | } |
114 | } | 114 | } |
@@ -116,7 +116,7 @@ static void set_mode(struct wlr_output *output, int width, int height, | |||
116 | void terminate_swaybg(pid_t pid) { | 116 | void terminate_swaybg(pid_t pid) { |
117 | int ret = kill(pid, SIGTERM); | 117 | int ret = kill(pid, SIGTERM); |
118 | if (ret != 0) { | 118 | if (ret != 0) { |
119 | wlr_log(L_ERROR, "Unable to terminate swaybg [pid: %d]", pid); | 119 | wlr_log(WLR_ERROR, "Unable to terminate swaybg [pid: %d]", pid); |
120 | } else { | 120 | } else { |
121 | int status; | 121 | int status; |
122 | waitpid(pid, &status, 0); | 122 | waitpid(pid, &status, 0); |
@@ -144,22 +144,22 @@ void apply_output_config(struct output_config *oc, struct sway_container *output | |||
144 | } | 144 | } |
145 | 145 | ||
146 | if (oc && oc->width > 0 && oc->height > 0) { | 146 | if (oc && oc->width > 0 && oc->height > 0) { |
147 | wlr_log(L_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width, | 147 | wlr_log(WLR_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width, |
148 | oc->height, oc->refresh_rate); | 148 | oc->height, oc->refresh_rate); |
149 | set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate); | 149 | set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate); |
150 | } | 150 | } |
151 | if (oc && oc->scale > 0) { | 151 | if (oc && oc->scale > 0) { |
152 | wlr_log(L_DEBUG, "Set %s scale to %f", oc->name, oc->scale); | 152 | wlr_log(WLR_DEBUG, "Set %s scale to %f", oc->name, oc->scale); |
153 | wlr_output_set_scale(wlr_output, oc->scale); | 153 | wlr_output_set_scale(wlr_output, oc->scale); |
154 | } | 154 | } |
155 | if (oc && oc->transform >= 0) { | 155 | if (oc && oc->transform >= 0) { |
156 | wlr_log(L_DEBUG, "Set %s transform to %d", oc->name, oc->transform); | 156 | wlr_log(WLR_DEBUG, "Set %s transform to %d", oc->name, oc->transform); |
157 | wlr_output_set_transform(wlr_output, oc->transform); | 157 | wlr_output_set_transform(wlr_output, oc->transform); |
158 | } | 158 | } |
159 | 159 | ||
160 | // Find position for it | 160 | // Find position for it |
161 | if (oc && (oc->x != -1 || oc->y != -1)) { | 161 | if (oc && (oc->x != -1 || oc->y != -1)) { |
162 | wlr_log(L_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y); | 162 | wlr_log(WLR_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y); |
163 | wlr_output_layout_add(output_layout, wlr_output, oc->x, oc->y); | 163 | wlr_output_layout_add(output_layout, wlr_output, oc->x, oc->y); |
164 | } else { | 164 | } else { |
165 | wlr_output_layout_add_auto(output_layout, wlr_output); | 165 | wlr_output_layout_add_auto(output_layout, wlr_output); |
@@ -187,7 +187,7 @@ void apply_output_config(struct output_config *oc, struct sway_container *output | |||
187 | terminate_swaybg(output->sway_output->bg_pid); | 187 | terminate_swaybg(output->sway_output->bg_pid); |
188 | } | 188 | } |
189 | 189 | ||
190 | wlr_log(L_DEBUG, "Setting background for output %d to %s", | 190 | wlr_log(WLR_DEBUG, "Setting background for output %d to %s", |
191 | output_i, oc->background); | 191 | output_i, oc->background); |
192 | 192 | ||
193 | size_t len = snprintf(NULL, 0, "%s %d %s %s", | 193 | size_t len = snprintf(NULL, 0, "%s %d %s %s", |
@@ -195,28 +195,30 @@ void apply_output_config(struct output_config *oc, struct sway_container *output | |||
195 | output_i, oc->background, oc->background_option); | 195 | output_i, oc->background, oc->background_option); |
196 | char *command = malloc(len + 1); | 196 | char *command = malloc(len + 1); |
197 | if (!command) { | 197 | if (!command) { |
198 | wlr_log(L_DEBUG, "Unable to allocate swaybg command"); | 198 | wlr_log(WLR_DEBUG, "Unable to allocate swaybg command"); |
199 | return; | 199 | return; |
200 | } | 200 | } |
201 | snprintf(command, len + 1, "%s %d %s %s", | 201 | snprintf(command, len + 1, "%s %d %s %s", |
202 | config->swaybg_command ? config->swaybg_command : "swaybg", | 202 | config->swaybg_command ? config->swaybg_command : "swaybg", |
203 | output_i, oc->background, oc->background_option); | 203 | output_i, oc->background, oc->background_option); |
204 | wlr_log(L_DEBUG, "-> %s", command); | 204 | wlr_log(WLR_DEBUG, "-> %s", command); |
205 | 205 | ||
206 | char *const cmd[] = { "sh", "-c", command, NULL }; | 206 | char *const cmd[] = { "sh", "-c", command, NULL }; |
207 | output->sway_output->bg_pid = fork(); | 207 | output->sway_output->bg_pid = fork(); |
208 | if (output->sway_output->bg_pid == 0) { | 208 | if (output->sway_output->bg_pid == 0) { |
209 | execvp(cmd[0], cmd); | 209 | execvp(cmd[0], cmd); |
210 | } else { | ||
211 | free(command); | ||
210 | } | 212 | } |
211 | } | 213 | } |
212 | if (oc && oc->dpms_state != DPMS_IGNORE) { | 214 | if (oc && oc->dpms_state != DPMS_IGNORE) { |
213 | switch (oc->dpms_state) { | 215 | switch (oc->dpms_state) { |
214 | case DPMS_ON: | 216 | case DPMS_ON: |
215 | wlr_log(L_DEBUG, "Turning on screen"); | 217 | wlr_log(WLR_DEBUG, "Turning on screen"); |
216 | wlr_output_enable(wlr_output, true); | 218 | wlr_output_enable(wlr_output, true); |
217 | break; | 219 | break; |
218 | case DPMS_OFF: | 220 | case DPMS_OFF: |
219 | wlr_log(L_DEBUG, "Turning off screen"); | 221 | wlr_log(WLR_DEBUG, "Turning off screen"); |
220 | wlr_output_enable(wlr_output, false); | 222 | wlr_output_enable(wlr_output, false); |
221 | break; | 223 | break; |
222 | case DPMS_IGNORE: | 224 | case DPMS_IGNORE: |
diff --git a/sway/config/seat.c b/sway/config/seat.c index bd8b45c8..83dac4c0 100644 --- a/sway/config/seat.c +++ b/sway/config/seat.c | |||
@@ -7,11 +7,11 @@ | |||
7 | struct seat_config *new_seat_config(const char* name) { | 7 | struct seat_config *new_seat_config(const char* name) { |
8 | struct seat_config *seat = calloc(1, sizeof(struct seat_config)); | 8 | struct seat_config *seat = calloc(1, sizeof(struct seat_config)); |
9 | if (!seat) { | 9 | if (!seat) { |
10 | wlr_log(L_DEBUG, "Unable to allocate seat config"); | 10 | wlr_log(WLR_DEBUG, "Unable to allocate seat config"); |
11 | return NULL; | 11 | return NULL; |
12 | } | 12 | } |
13 | 13 | ||
14 | wlr_log(L_DEBUG, "new_seat_config(%s)", name); | 14 | wlr_log(WLR_DEBUG, "new_seat_config(%s)", name); |
15 | seat->name = strdup(name); | 15 | seat->name = strdup(name); |
16 | if (!sway_assert(seat->name, "could not allocate name for seat")) { | 16 | if (!sway_assert(seat->name, "could not allocate name for seat")) { |
17 | free(seat); | 17 | free(seat); |
@@ -34,7 +34,7 @@ struct seat_attachment_config *seat_attachment_config_new() { | |||
34 | struct seat_attachment_config *attachment = | 34 | struct seat_attachment_config *attachment = |
35 | calloc(1, sizeof(struct seat_attachment_config)); | 35 | calloc(1, sizeof(struct seat_attachment_config)); |
36 | if (!attachment) { | 36 | if (!attachment) { |
37 | wlr_log(L_DEBUG, "cannot allocate attachment config"); | 37 | wlr_log(WLR_DEBUG, "cannot allocate attachment config"); |
38 | return NULL; | 38 | return NULL; |
39 | } | 39 | } |
40 | return attachment; | 40 | return attachment; |
diff --git a/sway/criteria.c b/sway/criteria.c index d9f09ecc..e2b248de 100644 --- a/sway/criteria.c +++ b/sway/criteria.c | |||
@@ -37,7 +37,7 @@ void criteria_destroy(struct criteria *criteria) { | |||
37 | pcre_free(criteria->con_mark); | 37 | pcre_free(criteria->con_mark); |
38 | pcre_free(criteria->window_role); | 38 | pcre_free(criteria->window_role); |
39 | free(criteria->workspace); | 39 | free(criteria->workspace); |
40 | 40 | free(criteria->cmdlist); | |
41 | free(criteria->raw); | 41 | free(criteria->raw); |
42 | free(criteria); | 42 | free(criteria); |
43 | } | 43 | } |
@@ -46,6 +46,31 @@ static int regex_cmp(const char *item, const pcre *regex) { | |||
46 | return pcre_exec(regex, NULL, item, strlen(item), 0, 0, NULL, 0); | 46 | return pcre_exec(regex, NULL, item, strlen(item), 0, 0, NULL, 0); |
47 | } | 47 | } |
48 | 48 | ||
49 | static int cmp_urgent(const void *_a, const void *_b) { | ||
50 | struct sway_view *a = *(void **)_a; | ||
51 | struct sway_view *b = *(void **)_b; | ||
52 | |||
53 | if (a->urgent.tv_sec < b->urgent.tv_sec) { | ||
54 | return -1; | ||
55 | } else if (a->urgent.tv_sec > b->urgent.tv_sec) { | ||
56 | return 1; | ||
57 | } | ||
58 | if (a->urgent.tv_nsec < b->urgent.tv_nsec) { | ||
59 | return -1; | ||
60 | } else if (a->urgent.tv_nsec > b->urgent.tv_nsec) { | ||
61 | return 1; | ||
62 | } | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static void find_urgent_iterator(struct sway_container *swayc, void *data) { | ||
67 | if (swayc->type != C_VIEW || !view_is_urgent(swayc->sway_view)) { | ||
68 | return; | ||
69 | } | ||
70 | list_t *urgent_views = data; | ||
71 | list_add(urgent_views, swayc->sway_view); | ||
72 | } | ||
73 | |||
49 | static bool criteria_matches_view(struct criteria *criteria, | 74 | static bool criteria_matches_view(struct criteria *criteria, |
50 | struct sway_view *view) { | 75 | struct sway_view *view) { |
51 | if (criteria->title) { | 76 | if (criteria->title) { |
@@ -133,8 +158,23 @@ static bool criteria_matches_view(struct criteria *criteria, | |||
133 | } | 158 | } |
134 | 159 | ||
135 | if (criteria->urgent) { | 160 | if (criteria->urgent) { |
136 | // TODO | 161 | if (!view_is_urgent(view)) { |
137 | return false; | 162 | return false; |
163 | } | ||
164 | list_t *urgent_views = create_list(); | ||
165 | container_for_each_descendant_dfs(&root_container, | ||
166 | find_urgent_iterator, urgent_views); | ||
167 | list_stable_sort(urgent_views, cmp_urgent); | ||
168 | struct sway_view *target; | ||
169 | if (criteria->urgent == 'o') { // oldest | ||
170 | target = urgent_views->items[0]; | ||
171 | } else { // latest | ||
172 | target = urgent_views->items[urgent_views->length - 1]; | ||
173 | } | ||
174 | list_free(urgent_views); | ||
175 | if (view != target) { | ||
176 | return false; | ||
177 | } | ||
138 | } | 178 | } |
139 | 179 | ||
140 | if (criteria->workspace) { | 180 | if (criteria->workspace) { |
@@ -507,7 +547,7 @@ struct criteria *criteria_parse(char *raw, char **error_arg) { | |||
507 | } | 547 | } |
508 | unescape(value); | 548 | unescape(value); |
509 | } | 549 | } |
510 | wlr_log(L_DEBUG, "Found pair: %s=%s", name, value); | 550 | wlr_log(WLR_DEBUG, "Found pair: %s=%s", name, value); |
511 | if (!parse_token(criteria, name, value)) { | 551 | if (!parse_token(criteria, name, value)) { |
512 | *error_arg = error; | 552 | *error_arg = error; |
513 | goto cleanup; | 553 | goto cleanup; |
diff --git a/sway/desktop/desktop.c b/sway/desktop/desktop.c index e495790c..6575519d 100644 --- a/sway/desktop/desktop.c +++ b/sway/desktop/desktop.c | |||
@@ -13,3 +13,12 @@ void desktop_damage_surface(struct wlr_surface *surface, double lx, double ly, | |||
13 | } | 13 | } |
14 | } | 14 | } |
15 | } | 15 | } |
16 | |||
17 | void desktop_damage_whole_container(struct sway_container *con) { | ||
18 | for (int i = 0; i < root_container.children->length; ++i) { | ||
19 | struct sway_container *cont = root_container.children->items[i]; | ||
20 | if (cont->type == C_OUTPUT) { | ||
21 | output_damage_whole_container(cont->sway_output, con); | ||
22 | } | ||
23 | } | ||
24 | } | ||
diff --git a/sway/desktop/idle_inhibit_v1.c b/sway/desktop/idle_inhibit_v1.c index c02ca26e..da17d0f2 100644 --- a/sway/desktop/idle_inhibit_v1.c +++ b/sway/desktop/idle_inhibit_v1.c | |||
@@ -9,7 +9,7 @@ | |||
9 | static void handle_destroy(struct wl_listener *listener, void *data) { | 9 | static void handle_destroy(struct wl_listener *listener, void *data) { |
10 | struct sway_idle_inhibitor_v1 *inhibitor = | 10 | struct sway_idle_inhibitor_v1 *inhibitor = |
11 | wl_container_of(listener, inhibitor, destroy); | 11 | wl_container_of(listener, inhibitor, destroy); |
12 | wlr_log(L_DEBUG, "Sway idle inhibitor destroyed"); | 12 | wlr_log(WLR_DEBUG, "Sway idle inhibitor destroyed"); |
13 | wl_list_remove(&inhibitor->link); | 13 | wl_list_remove(&inhibitor->link); |
14 | wl_list_remove(&inhibitor->destroy.link); | 14 | wl_list_remove(&inhibitor->destroy.link); |
15 | idle_inhibit_v1_check_active(inhibitor->manager); | 15 | idle_inhibit_v1_check_active(inhibitor->manager); |
@@ -20,7 +20,7 @@ void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) { | |||
20 | struct wlr_idle_inhibitor_v1 *wlr_inhibitor = data; | 20 | struct wlr_idle_inhibitor_v1 *wlr_inhibitor = data; |
21 | struct sway_idle_inhibit_manager_v1 *manager = | 21 | struct sway_idle_inhibit_manager_v1 *manager = |
22 | wl_container_of(listener, manager, new_idle_inhibitor_v1); | 22 | wl_container_of(listener, manager, new_idle_inhibitor_v1); |
23 | wlr_log(L_DEBUG, "New sway idle inhibitor"); | 23 | wlr_log(WLR_DEBUG, "New sway idle inhibitor"); |
24 | 24 | ||
25 | struct sway_idle_inhibitor_v1 *inhibitor = | 25 | struct sway_idle_inhibitor_v1 *inhibitor = |
26 | calloc(1, sizeof(struct sway_idle_inhibitor_v1)); | 26 | calloc(1, sizeof(struct sway_idle_inhibitor_v1)); |
@@ -67,6 +67,7 @@ struct sway_idle_inhibit_manager_v1 *sway_idle_inhibit_manager_v1_create( | |||
67 | 67 | ||
68 | manager->wlr_manager = wlr_idle_inhibit_v1_create(wl_display); | 68 | manager->wlr_manager = wlr_idle_inhibit_v1_create(wl_display); |
69 | if (!manager->wlr_manager) { | 69 | if (!manager->wlr_manager) { |
70 | free(manager); | ||
70 | return NULL; | 71 | return NULL; |
71 | } | 72 | } |
72 | manager->idle = idle; | 73 | manager->idle = idle; |
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index de1fe349..a7d96717 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include "sway/layers.h" | 12 | #include "sway/layers.h" |
13 | #include "sway/output.h" | 13 | #include "sway/output.h" |
14 | #include "sway/server.h" | 14 | #include "sway/server.h" |
15 | #include "sway/tree/arrange.h" | ||
16 | #include "sway/tree/layout.h" | 15 | #include "sway/tree/layout.h" |
17 | #include "log.h" | 16 | #include "log.h" |
18 | 17 | ||
@@ -174,9 +173,9 @@ void arrange_layers(struct sway_output *output) { | |||
174 | 173 | ||
175 | if (memcmp(&usable_area, &output->usable_area, | 174 | if (memcmp(&usable_area, &output->usable_area, |
176 | sizeof(struct wlr_box)) != 0) { | 175 | sizeof(struct wlr_box)) != 0) { |
177 | wlr_log(L_DEBUG, "Usable area changed, rearranging output"); | 176 | wlr_log(WLR_DEBUG, "Usable area changed, rearranging output"); |
178 | memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); | 177 | memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); |
179 | arrange_and_commit(output->swayc); | 178 | container_set_dirty(output->swayc); |
180 | } | 179 | } |
181 | 180 | ||
182 | // Arrange non-exlusive surfaces from top->bottom | 181 | // Arrange non-exlusive surfaces from top->bottom |
@@ -269,7 +268,7 @@ static void unmap(struct sway_layer_surface *sway_layer) { | |||
269 | static void handle_destroy(struct wl_listener *listener, void *data) { | 268 | static void handle_destroy(struct wl_listener *listener, void *data) { |
270 | struct sway_layer_surface *sway_layer = | 269 | struct sway_layer_surface *sway_layer = |
271 | wl_container_of(listener, sway_layer, destroy); | 270 | wl_container_of(listener, sway_layer, destroy); |
272 | wlr_log(L_DEBUG, "Layer surface destroyed (%s)", | 271 | wlr_log(WLR_DEBUG, "Layer surface destroyed (%s)", |
273 | sway_layer->layer_surface->namespace); | 272 | sway_layer->layer_surface->namespace); |
274 | if (sway_layer->layer_surface->mapped) { | 273 | if (sway_layer->layer_surface->mapped) { |
275 | unmap(sway_layer); | 274 | unmap(sway_layer); |
@@ -316,7 +315,7 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { | |||
316 | struct wlr_layer_surface *layer_surface = data; | 315 | struct wlr_layer_surface *layer_surface = data; |
317 | struct sway_server *server = | 316 | struct sway_server *server = |
318 | wl_container_of(listener, server, layer_shell_surface); | 317 | wl_container_of(listener, server, layer_shell_surface); |
319 | wlr_log(L_DEBUG, "new layer surface: namespace %s layer %d anchor %d " | 318 | wlr_log(WLR_DEBUG, "new layer surface: namespace %s layer %d anchor %d " |
320 | "size %dx%d margin %d,%d,%d,%d", | 319 | "size %dx%d margin %d,%d,%d,%d", |
321 | layer_surface->namespace, layer_surface->layer, layer_surface->layer, | 320 | layer_surface->namespace, layer_surface->layer, layer_surface->layer, |
322 | layer_surface->client_pending.desired_width, | 321 | layer_surface->client_pending.desired_width, |
@@ -326,12 +325,6 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { | |||
326 | layer_surface->client_pending.margin.bottom, | 325 | layer_surface->client_pending.margin.bottom, |
327 | layer_surface->client_pending.margin.left); | 326 | layer_surface->client_pending.margin.left); |
328 | 327 | ||
329 | struct sway_layer_surface *sway_layer = | ||
330 | calloc(1, sizeof(struct sway_layer_surface)); | ||
331 | if (!sway_layer) { | ||
332 | return; | ||
333 | } | ||
334 | |||
335 | if (!layer_surface->output) { | 328 | if (!layer_surface->output) { |
336 | // Assign last active output | 329 | // Assign last active output |
337 | struct sway_container *output = NULL; | 330 | struct sway_container *output = NULL; |
@@ -353,6 +346,12 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { | |||
353 | layer_surface->output = output->sway_output->wlr_output; | 346 | layer_surface->output = output->sway_output->wlr_output; |
354 | } | 347 | } |
355 | 348 | ||
349 | struct sway_layer_surface *sway_layer = | ||
350 | calloc(1, sizeof(struct sway_layer_surface)); | ||
351 | if (!sway_layer) { | ||
352 | return; | ||
353 | } | ||
354 | |||
356 | sway_layer->surface_commit.notify = handle_surface_commit; | 355 | sway_layer->surface_commit.notify = handle_surface_commit; |
357 | wl_signal_add(&layer_surface->surface->events.commit, | 356 | wl_signal_add(&layer_surface->surface->events.commit, |
358 | &sway_layer->surface_commit); | 357 | &sway_layer->surface_commit); |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 8b50bc44..a9808406 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -204,11 +204,11 @@ bool output_has_opaque_lockscreen(struct sway_output *output, | |||
204 | }; | 204 | }; |
205 | pixman_region32_t surface_opaque_box; | 205 | pixman_region32_t surface_opaque_box; |
206 | pixman_region32_init(&surface_opaque_box); | 206 | pixman_region32_init(&surface_opaque_box); |
207 | pixman_region32_copy(&surface_opaque_box, &wlr_surface->current.opaque); | 207 | pixman_region32_copy(&surface_opaque_box, &wlr_surface->opaque_region); |
208 | pixman_region32_translate(&surface_opaque_box, | 208 | pixman_region32_translate(&surface_opaque_box, |
209 | sway_layer_surface->geo.x, sway_layer_surface->geo.y); | 209 | sway_layer_surface->geo.x, sway_layer_surface->geo.y); |
210 | bool contains = pixman_region32_contains_rectangle( | 210 | bool contains = pixman_region32_contains_rectangle(&surface_opaque_box, |
211 | &wlr_surface->current.opaque, &output_box); | 211 | &output_box); |
212 | pixman_region32_fini(&surface_opaque_box); | 212 | pixman_region32_fini(&surface_opaque_box); |
213 | if (contains) { | 213 | if (contains) { |
214 | return true; | 214 | return true; |
@@ -492,19 +492,21 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
492 | output->wlr_output->data = NULL; | 492 | output->wlr_output->data = NULL; |
493 | free(output); | 493 | free(output); |
494 | 494 | ||
495 | arrange_and_commit(&root_container); | 495 | arrange_windows(&root_container); |
496 | } | 496 | } |
497 | 497 | ||
498 | static void handle_mode(struct wl_listener *listener, void *data) { | 498 | static void handle_mode(struct wl_listener *listener, void *data) { |
499 | struct sway_output *output = wl_container_of(listener, output, mode); | 499 | struct sway_output *output = wl_container_of(listener, output, mode); |
500 | arrange_layers(output); | 500 | arrange_layers(output); |
501 | arrange_and_commit(output->swayc); | 501 | arrange_windows(output->swayc); |
502 | transaction_commit_dirty(); | ||
502 | } | 503 | } |
503 | 504 | ||
504 | static void handle_transform(struct wl_listener *listener, void *data) { | 505 | static void handle_transform(struct wl_listener *listener, void *data) { |
505 | struct sway_output *output = wl_container_of(listener, output, transform); | 506 | struct sway_output *output = wl_container_of(listener, output, transform); |
506 | arrange_layers(output); | 507 | arrange_layers(output); |
507 | arrange_and_commit(output->swayc); | 508 | arrange_windows(output->swayc); |
509 | transaction_commit_dirty(); | ||
508 | } | 510 | } |
509 | 511 | ||
510 | static void handle_scale_iterator(struct sway_container *view, void *data) { | 512 | static void handle_scale_iterator(struct sway_container *view, void *data) { |
@@ -515,7 +517,8 @@ static void handle_scale(struct wl_listener *listener, void *data) { | |||
515 | struct sway_output *output = wl_container_of(listener, output, scale); | 517 | struct sway_output *output = wl_container_of(listener, output, scale); |
516 | arrange_layers(output); | 518 | arrange_layers(output); |
517 | container_descendants(output->swayc, C_VIEW, handle_scale_iterator, NULL); | 519 | container_descendants(output->swayc, C_VIEW, handle_scale_iterator, NULL); |
518 | arrange_and_commit(output->swayc); | 520 | arrange_windows(output->swayc); |
521 | transaction_commit_dirty(); | ||
519 | } | 522 | } |
520 | 523 | ||
521 | struct sway_output *output_from_wlr_output(struct wlr_output *wlr_output) { | 524 | struct sway_output *output_from_wlr_output(struct wlr_output *wlr_output) { |
@@ -525,7 +528,7 @@ struct sway_output *output_from_wlr_output(struct wlr_output *wlr_output) { | |||
525 | void handle_new_output(struct wl_listener *listener, void *data) { | 528 | void handle_new_output(struct wl_listener *listener, void *data) { |
526 | struct sway_server *server = wl_container_of(listener, server, new_output); | 529 | struct sway_server *server = wl_container_of(listener, server, new_output); |
527 | struct wlr_output *wlr_output = data; | 530 | struct wlr_output *wlr_output = data; |
528 | wlr_log(L_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); | 531 | wlr_log(WLR_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); |
529 | 532 | ||
530 | struct sway_output *output = calloc(1, sizeof(struct sway_output)); | 533 | struct sway_output *output = calloc(1, sizeof(struct sway_output)); |
531 | if (!output) { | 534 | if (!output) { |
@@ -584,5 +587,6 @@ void output_enable(struct sway_output *output) { | |||
584 | output->damage_destroy.notify = damage_handle_destroy; | 587 | output->damage_destroy.notify = damage_handle_destroy; |
585 | 588 | ||
586 | arrange_layers(output); | 589 | arrange_layers(output); |
587 | arrange_and_commit(&root_container); | 590 | arrange_windows(&root_container); |
591 | transaction_commit_dirty(); | ||
588 | } | 592 | } |
diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 43948f29..4c85e516 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <wlr/util/region.h> | 15 | #include <wlr/util/region.h> |
16 | #include "log.h" | 16 | #include "log.h" |
17 | #include "sway/config.h" | 17 | #include "sway/config.h" |
18 | #include "sway/debug.h" | ||
18 | #include "sway/input/input-manager.h" | 19 | #include "sway/input/input-manager.h" |
19 | #include "sway/input/seat.h" | 20 | #include "sway/input/seat.h" |
20 | #include "sway/layers.h" | 21 | #include "sway/layers.h" |
@@ -255,6 +256,10 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, | |||
255 | render_view_surfaces(view, output, damage, view->swayc->alpha); | 256 | render_view_surfaces(view, output, damage, view->swayc->alpha); |
256 | } | 257 | } |
257 | 258 | ||
259 | if (view->using_csd) { | ||
260 | return; | ||
261 | } | ||
262 | |||
258 | struct wlr_box box; | 263 | struct wlr_box box; |
259 | float output_scale = output->wlr_output->scale; | 264 | float output_scale = output->wlr_output->scale; |
260 | float color[4]; | 265 | float color[4]; |
@@ -542,9 +547,6 @@ static void render_container(struct sway_output *output, | |||
542 | static void render_container_simple(struct sway_output *output, | 547 | static void render_container_simple(struct sway_output *output, |
543 | pixman_region32_t *damage, struct sway_container *con, | 548 | pixman_region32_t *damage, struct sway_container *con, |
544 | bool parent_focused) { | 549 | bool parent_focused) { |
545 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
546 | struct sway_container *focus = seat_get_focus(seat); | ||
547 | |||
548 | for (int i = 0; i < con->current.children->length; ++i) { | 550 | for (int i = 0; i < con->current.children->length; ++i) { |
549 | struct sway_container *child = con->current.children->items[i]; | 551 | struct sway_container *child = con->current.children->items[i]; |
550 | 552 | ||
@@ -555,11 +557,15 @@ static void render_container_simple(struct sway_output *output, | |||
555 | struct wlr_texture *marks_texture; | 557 | struct wlr_texture *marks_texture; |
556 | struct sway_container_state *state = &child->current; | 558 | struct sway_container_state *state = &child->current; |
557 | 559 | ||
558 | if (focus == child || parent_focused) { | 560 | if (view_is_urgent(view)) { |
561 | colors = &config->border_colors.urgent; | ||
562 | title_texture = child->title_urgent; | ||
563 | marks_texture = view->marks_urgent; | ||
564 | } else if (state->focused || parent_focused) { | ||
559 | colors = &config->border_colors.focused; | 565 | colors = &config->border_colors.focused; |
560 | title_texture = child->title_focused; | 566 | title_texture = child->title_focused; |
561 | marks_texture = view->marks_focused; | 567 | marks_texture = view->marks_focused; |
562 | } else if (seat_get_focus_inactive(seat, con) == child) { | 568 | } else if (con->current.focused_inactive_child == child) { |
563 | colors = &config->border_colors.focused_inactive; | 569 | colors = &config->border_colors.focused_inactive; |
564 | title_texture = child->title_focused_inactive; | 570 | title_texture = child->title_focused_inactive; |
565 | marks_texture = view->marks_focused_inactive; | 571 | marks_texture = view->marks_focused_inactive; |
@@ -569,17 +575,19 @@ static void render_container_simple(struct sway_output *output, | |||
569 | marks_texture = view->marks_unfocused; | 575 | marks_texture = view->marks_unfocused; |
570 | } | 576 | } |
571 | 577 | ||
572 | if (state->border == B_NORMAL) { | 578 | if (!view->using_csd) { |
573 | render_titlebar(output, damage, child, state->swayc_x, | 579 | if (state->border == B_NORMAL) { |
574 | state->swayc_y, state->swayc_width, colors, | 580 | render_titlebar(output, damage, child, state->swayc_x, |
575 | title_texture, marks_texture); | 581 | state->swayc_y, state->swayc_width, colors, |
576 | } else { | 582 | title_texture, marks_texture); |
577 | render_top_border(output, damage, child, colors); | 583 | } else { |
584 | render_top_border(output, damage, child, colors); | ||
585 | } | ||
578 | } | 586 | } |
579 | render_view(output, damage, child, colors); | 587 | render_view(output, damage, child, colors); |
580 | } else { | 588 | } else { |
581 | render_container(output, damage, child, | 589 | render_container(output, damage, child, |
582 | parent_focused || focus == child); | 590 | parent_focused || child->current.focused); |
583 | } | 591 | } |
584 | } | 592 | } |
585 | } | 593 | } |
@@ -593,26 +601,34 @@ static void render_container_tabbed(struct sway_output *output, | |||
593 | if (!con->current.children->length) { | 601 | if (!con->current.children->length) { |
594 | return; | 602 | return; |
595 | } | 603 | } |
596 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
597 | struct sway_container *focus = seat_get_focus(seat); | ||
598 | struct sway_container *current = seat_get_active_current_child(seat, con); | ||
599 | struct border_colors *current_colors = &config->border_colors.unfocused; | ||
600 | struct sway_container_state *pstate = &con->current; | 604 | struct sway_container_state *pstate = &con->current; |
605 | struct sway_container *current = pstate->focused_inactive_child; | ||
606 | struct border_colors *current_colors = &config->border_colors.unfocused; | ||
607 | |||
608 | double width_gap_adjustment = 2 * pstate->current_gaps; | ||
609 | int tab_width = | ||
610 | (pstate->swayc_width - width_gap_adjustment) / pstate->children->length; | ||
601 | 611 | ||
602 | // Render tabs | 612 | // Render tabs |
603 | for (int i = 0; i < con->current.children->length; ++i) { | 613 | for (int i = 0; i < pstate->children->length; ++i) { |
604 | struct sway_container *child = con->current.children->items[i]; | 614 | struct sway_container *child = pstate->children->items[i]; |
605 | struct sway_view *view = child->type == C_VIEW ? child->sway_view : NULL; | 615 | struct sway_view *view = child->type == C_VIEW ? child->sway_view : NULL; |
606 | struct sway_container_state *cstate = &child->current; | 616 | struct sway_container_state *cstate = &child->current; |
607 | struct border_colors *colors; | 617 | struct border_colors *colors; |
608 | struct wlr_texture *title_texture; | 618 | struct wlr_texture *title_texture; |
609 | struct wlr_texture *marks_texture; | 619 | struct wlr_texture *marks_texture; |
610 | 620 | bool urgent = view ? | |
611 | if (focus == child || parent_focused) { | 621 | view_is_urgent(view) : container_has_urgent_child(child); |
622 | |||
623 | if (urgent) { | ||
624 | colors = &config->border_colors.urgent; | ||
625 | title_texture = child->title_urgent; | ||
626 | marks_texture = view ? view->marks_urgent : NULL; | ||
627 | } else if (cstate->focused || parent_focused) { | ||
612 | colors = &config->border_colors.focused; | 628 | colors = &config->border_colors.focused; |
613 | title_texture = child->title_focused; | 629 | title_texture = child->title_focused; |
614 | marks_texture = view ? view->marks_focused : NULL; | 630 | marks_texture = view ? view->marks_focused : NULL; |
615 | } else if (child == current) { | 631 | } else if (child == pstate->focused_inactive_child) { |
616 | colors = &config->border_colors.focused_inactive; | 632 | colors = &config->border_colors.focused_inactive; |
617 | title_texture = child->title_focused_inactive; | 633 | title_texture = child->title_focused_inactive; |
618 | marks_texture = view ? view->marks_focused_inactive : NULL; | 634 | marks_texture = view ? view->marks_focused_inactive : NULL; |
@@ -622,11 +638,12 @@ static void render_container_tabbed(struct sway_output *output, | |||
622 | marks_texture = view ? view->marks_unfocused : NULL; | 638 | marks_texture = view ? view->marks_unfocused : NULL; |
623 | } | 639 | } |
624 | 640 | ||
625 | int tab_width = pstate->swayc_width / pstate->children->length; | 641 | int x = cstate->swayc_x + tab_width * i; |
626 | int x = pstate->swayc_x + tab_width * i; | 642 | |
627 | // Make last tab use the remaining width of the parent | 643 | // Make last tab use the remaining width of the parent |
628 | if (i == pstate->children->length - 1) { | 644 | if (i == pstate->children->length - 1) { |
629 | tab_width = pstate->swayc_width - tab_width * i; | 645 | tab_width = |
646 | pstate->swayc_width - width_gap_adjustment - tab_width * i; | ||
630 | } | 647 | } |
631 | 648 | ||
632 | render_titlebar(output, damage, child, x, cstate->swayc_y, tab_width, | 649 | render_titlebar(output, damage, child, x, cstate->swayc_y, tab_width, |
@@ -638,13 +655,11 @@ static void render_container_tabbed(struct sway_output *output, | |||
638 | } | 655 | } |
639 | 656 | ||
640 | // Render surface and left/right/bottom borders | 657 | // Render surface and left/right/bottom borders |
641 | if (current) { | 658 | if (current->type == C_VIEW) { |
642 | if (current->type == C_VIEW) { | 659 | render_view(output, damage, current, current_colors); |
643 | render_view(output, damage, current, current_colors); | 660 | } else { |
644 | } else { | 661 | render_container(output, damage, current, |
645 | render_container(output, damage, current, | 662 | parent_focused || current->current.focused); |
646 | parent_focused || current == focus); | ||
647 | } | ||
648 | } | 663 | } |
649 | } | 664 | } |
650 | 665 | ||
@@ -657,26 +672,32 @@ static void render_container_stacked(struct sway_output *output, | |||
657 | if (!con->current.children->length) { | 672 | if (!con->current.children->length) { |
658 | return; | 673 | return; |
659 | } | 674 | } |
660 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
661 | struct sway_container *focus = seat_get_focus(seat); | ||
662 | struct sway_container *current = seat_get_active_current_child(seat, con); | ||
663 | struct border_colors *current_colors = &config->border_colors.unfocused; | ||
664 | struct sway_container_state *pstate = &con->current; | 675 | struct sway_container_state *pstate = &con->current; |
676 | struct sway_container *current = pstate->focused_inactive_child; | ||
677 | struct border_colors *current_colors = &config->border_colors.unfocused; | ||
678 | |||
679 | size_t titlebar_height = container_titlebar_height(); | ||
665 | 680 | ||
666 | // Render titles | 681 | // Render titles |
667 | for (int i = 0; i < con->current.children->length; ++i) { | 682 | for (int i = 0; i < pstate->children->length; ++i) { |
668 | struct sway_container *child = con->current.children->items[i]; | 683 | struct sway_container *child = pstate->children->items[i]; |
669 | struct sway_view *view = child->type == C_VIEW ? child->sway_view : NULL; | 684 | struct sway_view *view = child->type == C_VIEW ? child->sway_view : NULL; |
670 | struct sway_container_state *cstate = &child->current; | 685 | struct sway_container_state *cstate = &child->current; |
671 | struct border_colors *colors; | 686 | struct border_colors *colors; |
672 | struct wlr_texture *title_texture; | 687 | struct wlr_texture *title_texture; |
673 | struct wlr_texture *marks_texture; | 688 | struct wlr_texture *marks_texture; |
674 | 689 | bool urgent = view ? | |
675 | if (focus == child || parent_focused) { | 690 | view_is_urgent(view) : container_has_urgent_child(child); |
691 | |||
692 | if (urgent) { | ||
693 | colors = &config->border_colors.urgent; | ||
694 | title_texture = child->title_urgent; | ||
695 | marks_texture = view ? view->marks_urgent : NULL; | ||
696 | } else if (cstate->focused || parent_focused) { | ||
676 | colors = &config->border_colors.focused; | 697 | colors = &config->border_colors.focused; |
677 | title_texture = child->title_focused; | 698 | title_texture = child->title_focused; |
678 | marks_texture = view ? view->marks_focused : NULL; | 699 | marks_texture = view ? view->marks_focused : NULL; |
679 | } else if (child == current) { | 700 | } else if (child == pstate->focused_inactive_child) { |
680 | colors = &config->border_colors.focused_inactive; | 701 | colors = &config->border_colors.focused_inactive; |
681 | title_texture = child->title_focused_inactive; | 702 | title_texture = child->title_focused_inactive; |
682 | marks_texture = view ? view->marks_focused_inactive : NULL; | 703 | marks_texture = view ? view->marks_focused_inactive : NULL; |
@@ -686,7 +707,7 @@ static void render_container_stacked(struct sway_output *output, | |||
686 | marks_texture = view ? view->marks_unfocused : NULL; | 707 | marks_texture = view ? view->marks_unfocused : NULL; |
687 | } | 708 | } |
688 | 709 | ||
689 | int y = pstate->swayc_y + container_titlebar_height() * i; | 710 | int y = cstate->swayc_y + titlebar_height * i; |
690 | render_titlebar(output, damage, child, cstate->swayc_x, y, | 711 | render_titlebar(output, damage, child, cstate->swayc_x, y, |
691 | cstate->swayc_width, colors, title_texture, marks_texture); | 712 | cstate->swayc_width, colors, title_texture, marks_texture); |
692 | 713 | ||
@@ -696,13 +717,11 @@ static void render_container_stacked(struct sway_output *output, | |||
696 | } | 717 | } |
697 | 718 | ||
698 | // Render surface and left/right/bottom borders | 719 | // Render surface and left/right/bottom borders |
699 | if (current) { | 720 | if (current->type == C_VIEW) { |
700 | if (current->type == C_VIEW) { | 721 | render_view(output, damage, current, current_colors); |
701 | render_view(output, damage, current, current_colors); | 722 | } else { |
702 | } else { | 723 | render_container(output, damage, current, |
703 | render_container(output, damage, current, | 724 | parent_focused || current->current.focused); |
704 | parent_focused || current == focus); | ||
705 | } | ||
706 | } | 725 | } |
707 | } | 726 | } |
708 | 727 | ||
@@ -730,13 +749,15 @@ static void render_floating_container(struct sway_output *soutput, | |||
730 | pixman_region32_t *damage, struct sway_container *con) { | 749 | pixman_region32_t *damage, struct sway_container *con) { |
731 | if (con->type == C_VIEW) { | 750 | if (con->type == C_VIEW) { |
732 | struct sway_view *view = con->sway_view; | 751 | struct sway_view *view = con->sway_view; |
733 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
734 | struct sway_container *focus = seat_get_focus(seat); | ||
735 | struct border_colors *colors; | 752 | struct border_colors *colors; |
736 | struct wlr_texture *title_texture; | 753 | struct wlr_texture *title_texture; |
737 | struct wlr_texture *marks_texture; | 754 | struct wlr_texture *marks_texture; |
738 | 755 | ||
739 | if (focus == con) { | 756 | if (view_is_urgent(view)) { |
757 | colors = &config->border_colors.urgent; | ||
758 | title_texture = con->title_urgent; | ||
759 | marks_texture = view->marks_urgent; | ||
760 | } else if (con->current.focused) { | ||
740 | colors = &config->border_colors.focused; | 761 | colors = &config->border_colors.focused; |
741 | title_texture = con->title_focused; | 762 | title_texture = con->title_focused; |
742 | marks_texture = view->marks_focused; | 763 | marks_texture = view->marks_focused; |
@@ -746,12 +767,14 @@ static void render_floating_container(struct sway_output *soutput, | |||
746 | marks_texture = view->marks_unfocused; | 767 | marks_texture = view->marks_unfocused; |
747 | } | 768 | } |
748 | 769 | ||
749 | if (con->current.border == B_NORMAL) { | 770 | if (!view->using_csd) { |
750 | render_titlebar(soutput, damage, con, con->current.swayc_x, | 771 | if (con->current.border == B_NORMAL) { |
751 | con->current.swayc_y, con->current.swayc_width, colors, | 772 | render_titlebar(soutput, damage, con, con->current.swayc_x, |
752 | title_texture, marks_texture); | 773 | con->current.swayc_y, con->current.swayc_width, colors, |
753 | } else if (con->current.border != B_NONE) { | 774 | title_texture, marks_texture); |
754 | render_top_border(soutput, damage, con, colors); | 775 | } else if (con->current.border != B_NONE) { |
776 | render_top_border(soutput, damage, con, colors); | ||
777 | } | ||
755 | } | 778 | } |
756 | render_view(soutput, damage, con, colors); | 779 | render_view(soutput, damage, con, colors); |
757 | } else { | 780 | } else { |
@@ -779,6 +802,8 @@ static void render_floating(struct sway_output *soutput, | |||
779 | } | 802 | } |
780 | } | 803 | } |
781 | 804 | ||
805 | const char *damage_debug = NULL; | ||
806 | |||
782 | void output_render(struct sway_output *output, struct timespec *when, | 807 | void output_render(struct sway_output *output, struct timespec *when, |
783 | pixman_region32_t *damage) { | 808 | pixman_region32_t *damage) { |
784 | struct wlr_output *wlr_output = output->wlr_output; | 809 | struct wlr_output *wlr_output = output->wlr_output; |
@@ -798,7 +823,6 @@ void output_render(struct sway_output *output, struct timespec *when, | |||
798 | goto renderer_end; | 823 | goto renderer_end; |
799 | } | 824 | } |
800 | 825 | ||
801 | const char *damage_debug = getenv("SWAY_DAMAGE_DEBUG"); | ||
802 | if (damage_debug != NULL) { | 826 | if (damage_debug != NULL) { |
803 | if (strcmp(damage_debug, "highlight") == 0) { | 827 | if (strcmp(damage_debug, "highlight") == 0) { |
804 | wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1}); | 828 | wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1}); |
@@ -837,7 +861,11 @@ void output_render(struct sway_output *output, struct timespec *when, | |||
837 | } | 861 | } |
838 | 862 | ||
839 | // TODO: handle views smaller than the output | 863 | // TODO: handle views smaller than the output |
840 | render_view_surfaces(fullscreen_view, output, damage, 1.0f); | 864 | if (fullscreen_view->swayc->instructions->length) { |
865 | render_saved_view(fullscreen_view, output, damage, 1.0f); | ||
866 | } else { | ||
867 | render_view_surfaces(fullscreen_view, output, damage, 1.0f); | ||
868 | } | ||
841 | 869 | ||
842 | if (fullscreen_view->type == SWAY_VIEW_XWAYLAND) { | 870 | if (fullscreen_view->type == SWAY_VIEW_XWAYLAND) { |
843 | render_unmanaged(output, damage, | 871 | render_unmanaged(output, damage, |
@@ -858,9 +886,7 @@ void output_render(struct sway_output *output, struct timespec *when, | |||
858 | render_layer(output, damage, | 886 | render_layer(output, damage, |
859 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); | 887 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); |
860 | 888 | ||
861 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 889 | render_container(output, damage, workspace, workspace->current.focused); |
862 | struct sway_container *focus = seat_get_focus(seat); | ||
863 | render_container(output, damage, workspace, focus == workspace); | ||
864 | render_floating(output, damage); | 890 | render_floating(output, damage); |
865 | 891 | ||
866 | render_unmanaged(output, damage, | 892 | render_unmanaged(output, damage, |
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 179af617..fcfb0b51 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c | |||
@@ -19,14 +19,14 @@ | |||
19 | * How long we should wait for views to respond to the configure before giving | 19 | * How long we should wait for views to respond to the configure before giving |
20 | * up and applying the transaction anyway. | 20 | * up and applying the transaction anyway. |
21 | */ | 21 | */ |
22 | #define TIMEOUT_MS 200 | 22 | int txn_timeout_ms = 200; |
23 | 23 | ||
24 | /** | 24 | /** |
25 | * If enabled, sway will always wait for the transaction timeout before | 25 | * If enabled, sway will always wait for the transaction timeout before |
26 | * applying it, rather than applying it when the views are ready. This allows us | 26 | * applying it, rather than applying it when the views are ready. This allows us |
27 | * to observe the rendered state while a transaction is in progress. | 27 | * to observe the rendered state while a transaction is in progress. |
28 | */ | 28 | */ |
29 | #define TRANSACTION_DEBUG false | 29 | bool txn_debug = false; |
30 | 30 | ||
31 | struct sway_transaction { | 31 | struct sway_transaction { |
32 | struct wl_event_source *timer; | 32 | struct wl_event_source *timer; |
@@ -47,7 +47,7 @@ struct sway_transaction_instruction { | |||
47 | bool ready; | 47 | bool ready; |
48 | }; | 48 | }; |
49 | 49 | ||
50 | struct sway_transaction *transaction_create() { | 50 | static struct sway_transaction *transaction_create() { |
51 | struct sway_transaction *transaction = | 51 | struct sway_transaction *transaction = |
52 | calloc(1, sizeof(struct sway_transaction)); | 52 | calloc(1, sizeof(struct sway_transaction)); |
53 | transaction->instructions = create_list(); | 53 | transaction->instructions = create_list(); |
@@ -139,25 +139,18 @@ static void copy_pending_state(struct sway_container *container, | |||
139 | state->children = create_list(); | 139 | state->children = create_list(); |
140 | list_cat(state->children, container->children); | 140 | list_cat(state->children, container->children); |
141 | } | 141 | } |
142 | } | ||
143 | 142 | ||
144 | static bool transaction_has_container(struct sway_transaction *transaction, | 143 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
145 | struct sway_container *container) { | 144 | state->focused = seat_get_focus(seat) == container; |
146 | for (int i = 0; i < transaction->instructions->length; ++i) { | 145 | |
147 | struct sway_transaction_instruction *instruction = | 146 | if (container->type != C_VIEW) { |
148 | transaction->instructions->items[i]; | 147 | state->focused_inactive_child = |
149 | if (instruction->container == container) { | 148 | seat_get_active_child(seat, container); |
150 | return true; | ||
151 | } | ||
152 | } | 149 | } |
153 | return false; | ||
154 | } | 150 | } |
155 | 151 | ||
156 | void transaction_add_container(struct sway_transaction *transaction, | 152 | static void transaction_add_container(struct sway_transaction *transaction, |
157 | struct sway_container *container) { | 153 | struct sway_container *container) { |
158 | if (transaction_has_container(transaction, container)) { | ||
159 | return; | ||
160 | } | ||
161 | struct sway_transaction_instruction *instruction = | 154 | struct sway_transaction_instruction *instruction = |
162 | calloc(1, sizeof(struct sway_transaction_instruction)); | 155 | calloc(1, sizeof(struct sway_transaction_instruction)); |
163 | instruction->transaction = transaction; | 156 | instruction->transaction = transaction; |
@@ -175,7 +168,7 @@ void transaction_add_container(struct sway_transaction *transaction, | |||
175 | * Apply a transaction to the "current" state of the tree. | 168 | * Apply a transaction to the "current" state of the tree. |
176 | */ | 169 | */ |
177 | static void transaction_apply(struct sway_transaction *transaction) { | 170 | static void transaction_apply(struct sway_transaction *transaction) { |
178 | wlr_log(L_DEBUG, "Applying transaction %p", transaction); | 171 | wlr_log(WLR_DEBUG, "Applying transaction %p", transaction); |
179 | if (server.debug_txn_timings) { | 172 | if (server.debug_txn_timings) { |
180 | struct timespec now; | 173 | struct timespec now; |
181 | clock_gettime(CLOCK_MONOTONIC, &now); | 174 | clock_gettime(CLOCK_MONOTONIC, &now); |
@@ -186,7 +179,7 @@ static void transaction_apply(struct sway_transaction *transaction) { | |||
186 | float ms_waiting = (now.tv_sec - commit->tv_sec) * 1000 + | 179 | float ms_waiting = (now.tv_sec - commit->tv_sec) * 1000 + |
187 | (now.tv_nsec - commit->tv_nsec) / 1000000.0; | 180 | (now.tv_nsec - commit->tv_nsec) / 1000000.0; |
188 | float ms_total = ms_arranging + ms_waiting; | 181 | float ms_total = ms_arranging + ms_waiting; |
189 | wlr_log(L_DEBUG, "Transaction %p: %.1fms arranging, %.1fms waiting, " | 182 | wlr_log(WLR_DEBUG, "Transaction %p: %.1fms arranging, %.1fms waiting, " |
190 | "%.1fms total (%.1f frames if 60Hz)", transaction, | 183 | "%.1fms total (%.1f frames if 60Hz)", transaction, |
191 | ms_arranging, ms_waiting, ms_total, ms_total / (1000.0f / 60)); | 184 | ms_arranging, ms_waiting, ms_total, ms_total / (1000.0f / 60)); |
192 | } | 185 | } |
@@ -210,10 +203,12 @@ static void transaction_apply(struct sway_transaction *transaction) { | |||
210 | .width = instruction->state.swayc_width, | 203 | .width = instruction->state.swayc_width, |
211 | .height = instruction->state.swayc_height, | 204 | .height = instruction->state.swayc_height, |
212 | }; | 205 | }; |
213 | for (int j = 0; j < root_container.children->length; ++j) { | 206 | for (int j = 0; j < root_container.current.children->length; ++j) { |
214 | struct sway_container *output = root_container.children->items[j]; | 207 | struct sway_container *output = root_container.current.children->items[j]; |
215 | output_damage_box(output->sway_output, &old_box); | 208 | if (output->sway_output) { |
216 | output_damage_box(output->sway_output, &new_box); | 209 | output_damage_box(output->sway_output, &old_box); |
210 | output_damage_box(output->sway_output, &new_box); | ||
211 | } | ||
217 | } | 212 | } |
218 | 213 | ||
219 | // There are separate children lists for each instruction state, the | 214 | // There are separate children lists for each instruction state, the |
@@ -251,7 +246,7 @@ static void transaction_progress_queue() { | |||
251 | 246 | ||
252 | static int handle_timeout(void *data) { | 247 | static int handle_timeout(void *data) { |
253 | struct sway_transaction *transaction = data; | 248 | struct sway_transaction *transaction = data; |
254 | wlr_log(L_DEBUG, "Transaction %p timed out (%li waiting)", | 249 | wlr_log(WLR_DEBUG, "Transaction %p timed out (%li waiting)", |
255 | transaction, transaction->num_waiting); | 250 | transaction, transaction->num_waiting); |
256 | transaction->num_waiting = 0; | 251 | transaction->num_waiting = 0; |
257 | transaction_progress_queue(); | 252 | transaction_progress_queue(); |
@@ -285,8 +280,8 @@ static bool should_configure(struct sway_container *con, | |||
285 | return true; | 280 | return true; |
286 | } | 281 | } |
287 | 282 | ||
288 | void transaction_commit(struct sway_transaction *transaction) { | 283 | static void transaction_commit(struct sway_transaction *transaction) { |
289 | wlr_log(L_DEBUG, "Transaction %p committing with %i instructions", | 284 | wlr_log(WLR_DEBUG, "Transaction %p committing with %i instructions", |
290 | transaction, transaction->instructions->length); | 285 | transaction, transaction->instructions->length); |
291 | transaction->num_waiting = 0; | 286 | transaction->num_waiting = 0; |
292 | for (int i = 0; i < transaction->instructions->length; ++i) { | 287 | for (int i = 0; i < transaction->instructions->length; ++i) { |
@@ -319,7 +314,7 @@ void transaction_commit(struct sway_transaction *transaction) { | |||
319 | } else { | 314 | } else { |
320 | // There are no other transactions in progress, and this one has nothing | 315 | // There are no other transactions in progress, and this one has nothing |
321 | // to wait for, so we can skip the queue. | 316 | // to wait for, so we can skip the queue. |
322 | wlr_log(L_DEBUG, "Transaction %p has nothing to wait for", transaction); | 317 | wlr_log(WLR_DEBUG, "Transaction %p has nothing to wait for", transaction); |
323 | transaction_apply(transaction); | 318 | transaction_apply(transaction); |
324 | transaction_destroy(transaction); | 319 | transaction_destroy(transaction); |
325 | idle_inhibit_v1_check_active(server.idle_inhibit_manager_v1); | 320 | idle_inhibit_v1_check_active(server.idle_inhibit_manager_v1); |
@@ -330,7 +325,7 @@ void transaction_commit(struct sway_transaction *transaction) { | |||
330 | // Set up a timer which the views must respond within | 325 | // Set up a timer which the views must respond within |
331 | transaction->timer = wl_event_loop_add_timer(server.wl_event_loop, | 326 | transaction->timer = wl_event_loop_add_timer(server.wl_event_loop, |
332 | handle_timeout, transaction); | 327 | handle_timeout, transaction); |
333 | wl_event_source_timer_update(transaction->timer, TIMEOUT_MS); | 328 | wl_event_source_timer_update(transaction->timer, txn_timeout_ms); |
334 | } | 329 | } |
335 | 330 | ||
336 | // The debug tree shows the pending/live tree. Here is a good place to | 331 | // The debug tree shows the pending/live tree. Here is a good place to |
@@ -350,7 +345,7 @@ static void set_instruction_ready( | |||
350 | struct timespec *start = &transaction->commit_time; | 345 | struct timespec *start = &transaction->commit_time; |
351 | float ms = (now.tv_sec - start->tv_sec) * 1000 + | 346 | float ms = (now.tv_sec - start->tv_sec) * 1000 + |
352 | (now.tv_nsec - start->tv_nsec) / 1000000.0; | 347 | (now.tv_nsec - start->tv_nsec) / 1000000.0; |
353 | wlr_log(L_DEBUG, "Transaction %p: %li/%li ready in %.1fms (%s)", | 348 | wlr_log(WLR_DEBUG, "Transaction %p: %li/%li ready in %.1fms (%s)", |
354 | transaction, | 349 | transaction, |
355 | transaction->num_configures - transaction->num_waiting + 1, | 350 | transaction->num_configures - transaction->num_waiting + 1, |
356 | transaction->num_configures, ms, | 351 | transaction->num_configures, ms, |
@@ -361,11 +356,11 @@ static void set_instruction_ready( | |||
361 | // If all views are ready, apply the transaction. | 356 | // If all views are ready, apply the transaction. |
362 | // If the transaction has timed out then its num_waiting will be 0 already. | 357 | // If the transaction has timed out then its num_waiting will be 0 already. |
363 | if (transaction->num_waiting > 0 && --transaction->num_waiting == 0) { | 358 | if (transaction->num_waiting > 0 && --transaction->num_waiting == 0) { |
364 | #if !TRANSACTION_DEBUG | 359 | if (!txn_debug) { |
365 | wlr_log(L_DEBUG, "Transaction %p is ready", transaction); | 360 | wlr_log(WLR_DEBUG, "Transaction %p is ready", transaction); |
366 | wl_event_source_timer_update(transaction->timer, 0); | 361 | wl_event_source_timer_update(transaction->timer, 0); |
367 | transaction_progress_queue(); | 362 | transaction_progress_queue(); |
368 | #endif | 363 | } |
369 | } | 364 | } |
370 | } | 365 | } |
371 | 366 | ||
@@ -418,3 +413,17 @@ struct wlr_texture *transaction_get_saved_texture(struct sway_view *view, | |||
418 | *height = instruction->saved_buffer_height; | 413 | *height = instruction->saved_buffer_height; |
419 | return instruction->saved_buffer->texture; | 414 | return instruction->saved_buffer->texture; |
420 | } | 415 | } |
416 | |||
417 | void transaction_commit_dirty(void) { | ||
418 | if (!server.dirty_containers->length) { | ||
419 | return; | ||
420 | } | ||
421 | struct sway_transaction *transaction = transaction_create(); | ||
422 | for (int i = 0; i < server.dirty_containers->length; ++i) { | ||
423 | struct sway_container *container = server.dirty_containers->items[i]; | ||
424 | transaction_add_container(transaction, container); | ||
425 | container->dirty = false; | ||
426 | } | ||
427 | server.dirty_containers->length = 0; | ||
428 | transaction_commit(transaction); | ||
429 | } | ||
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index ac35a8d1..98c16faf 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c | |||
@@ -45,6 +45,24 @@ static void popup_handle_destroy(struct wl_listener *listener, void *data) { | |||
45 | view_child_destroy(&popup->child); | 45 | view_child_destroy(&popup->child); |
46 | } | 46 | } |
47 | 47 | ||
48 | static void popup_unconstrain(struct sway_xdg_popup *popup) { | ||
49 | struct sway_view *view = popup->child.view; | ||
50 | struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_surface->popup; | ||
51 | |||
52 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); | ||
53 | |||
54 | // the output box expressed in the coordinate system of the toplevel parent | ||
55 | // of the popup | ||
56 | struct wlr_box output_toplevel_sx_box = { | ||
57 | .x = output->x - view->x, | ||
58 | .y = output->y - view->y, | ||
59 | .width = output->width, | ||
60 | .height = output->height, | ||
61 | }; | ||
62 | |||
63 | wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); | ||
64 | } | ||
65 | |||
48 | static struct sway_xdg_popup *popup_create( | 66 | static struct sway_xdg_popup *popup_create( |
49 | struct wlr_xdg_popup *wlr_popup, struct sway_view *view) { | 67 | struct wlr_xdg_popup *wlr_popup, struct sway_view *view) { |
50 | struct wlr_xdg_surface *xdg_surface = wlr_popup->base; | 68 | struct wlr_xdg_surface *xdg_surface = wlr_popup->base; |
@@ -55,12 +73,15 @@ static struct sway_xdg_popup *popup_create( | |||
55 | return NULL; | 73 | return NULL; |
56 | } | 74 | } |
57 | view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); | 75 | view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); |
76 | popup->wlr_xdg_surface = xdg_surface; | ||
58 | 77 | ||
59 | wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); | 78 | wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); |
60 | popup->new_popup.notify = popup_handle_new_popup; | 79 | popup->new_popup.notify = popup_handle_new_popup; |
61 | wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); | 80 | wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); |
62 | popup->destroy.notify = popup_handle_destroy; | 81 | popup->destroy.notify = popup_handle_destroy; |
63 | 82 | ||
83 | popup_unconstrain(popup); | ||
84 | |||
64 | return popup; | 85 | return popup; |
65 | } | 86 | } |
66 | 87 | ||
@@ -223,7 +244,8 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) | |||
223 | view_set_fullscreen(view, e->fullscreen); | 244 | view_set_fullscreen(view, e->fullscreen); |
224 | 245 | ||
225 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); | 246 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); |
226 | arrange_and_commit(output); | 247 | arrange_windows(output); |
248 | transaction_commit_dirty(); | ||
227 | } | 249 | } |
228 | 250 | ||
229 | static void handle_unmap(struct wl_listener *listener, void *data) { | 251 | static void handle_unmap(struct wl_listener *listener, void *data) { |
@@ -260,10 +282,11 @@ static void handle_map(struct wl_listener *listener, void *data) { | |||
260 | if (xdg_surface->toplevel->client_pending.fullscreen) { | 282 | if (xdg_surface->toplevel->client_pending.fullscreen) { |
261 | view_set_fullscreen(view, true); | 283 | view_set_fullscreen(view, true); |
262 | struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); | 284 | struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); |
263 | arrange_and_commit(ws); | 285 | arrange_windows(ws); |
264 | } else { | 286 | } else { |
265 | arrange_and_commit(view->swayc->parent); | 287 | arrange_windows(view->swayc->parent); |
266 | } | 288 | } |
289 | transaction_commit_dirty(); | ||
267 | 290 | ||
268 | xdg_shell_view->commit.notify = handle_commit; | 291 | xdg_shell_view->commit.notify = handle_commit; |
269 | wl_signal_add(&xdg_surface->surface->events.commit, | 292 | wl_signal_add(&xdg_surface->surface->events.commit, |
@@ -304,11 +327,11 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { | |||
304 | struct wlr_xdg_surface *xdg_surface = data; | 327 | struct wlr_xdg_surface *xdg_surface = data; |
305 | 328 | ||
306 | if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { | 329 | if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { |
307 | wlr_log(L_DEBUG, "New xdg_shell popup"); | 330 | wlr_log(WLR_DEBUG, "New xdg_shell popup"); |
308 | return; | 331 | return; |
309 | } | 332 | } |
310 | 333 | ||
311 | wlr_log(L_DEBUG, "New xdg_shell toplevel title='%s' app_id='%s'", | 334 | wlr_log(WLR_DEBUG, "New xdg_shell toplevel title='%s' app_id='%s'", |
312 | xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); | 335 | xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); |
313 | wlr_xdg_surface_ping(xdg_surface); | 336 | wlr_xdg_surface_ping(xdg_surface); |
314 | 337 | ||
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 56bbb244..4d76f0a7 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c | |||
@@ -44,6 +44,24 @@ static void popup_handle_destroy(struct wl_listener *listener, void *data) { | |||
44 | view_child_destroy(&popup->child); | 44 | view_child_destroy(&popup->child); |
45 | } | 45 | } |
46 | 46 | ||
47 | static void popup_unconstrain(struct sway_xdg_popup_v6 *popup) { | ||
48 | struct sway_view *view = popup->child.view; | ||
49 | struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_xdg_surface_v6->popup; | ||
50 | |||
51 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); | ||
52 | |||
53 | // the output box expressed in the coordinate system of the toplevel parent | ||
54 | // of the popup | ||
55 | struct wlr_box output_toplevel_sx_box = { | ||
56 | .x = output->x - view->x, | ||
57 | .y = output->y - view->y, | ||
58 | .width = output->width, | ||
59 | .height = output->height, | ||
60 | }; | ||
61 | |||
62 | wlr_xdg_popup_v6_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); | ||
63 | } | ||
64 | |||
47 | static struct sway_xdg_popup_v6 *popup_create( | 65 | static struct sway_xdg_popup_v6 *popup_create( |
48 | struct wlr_xdg_popup_v6 *wlr_popup, struct sway_view *view) { | 66 | struct wlr_xdg_popup_v6 *wlr_popup, struct sway_view *view) { |
49 | struct wlr_xdg_surface_v6 *xdg_surface = wlr_popup->base; | 67 | struct wlr_xdg_surface_v6 *xdg_surface = wlr_popup->base; |
@@ -54,12 +72,15 @@ static struct sway_xdg_popup_v6 *popup_create( | |||
54 | return NULL; | 72 | return NULL; |
55 | } | 73 | } |
56 | view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); | 74 | view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); |
75 | popup->wlr_xdg_surface_v6 = xdg_surface; | ||
57 | 76 | ||
58 | wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); | 77 | wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); |
59 | popup->new_popup.notify = popup_handle_new_popup; | 78 | popup->new_popup.notify = popup_handle_new_popup; |
60 | wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); | 79 | wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); |
61 | popup->destroy.notify = popup_handle_destroy; | 80 | popup->destroy.notify = popup_handle_destroy; |
62 | 81 | ||
82 | popup_unconstrain(popup); | ||
83 | |||
63 | return popup; | 84 | return popup; |
64 | } | 85 | } |
65 | 86 | ||
@@ -218,7 +239,8 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) | |||
218 | view_set_fullscreen(view, e->fullscreen); | 239 | view_set_fullscreen(view, e->fullscreen); |
219 | 240 | ||
220 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); | 241 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); |
221 | arrange_and_commit(output); | 242 | arrange_windows(output); |
243 | transaction_commit_dirty(); | ||
222 | } | 244 | } |
223 | 245 | ||
224 | static void handle_unmap(struct wl_listener *listener, void *data) { | 246 | static void handle_unmap(struct wl_listener *listener, void *data) { |
@@ -255,10 +277,11 @@ static void handle_map(struct wl_listener *listener, void *data) { | |||
255 | if (xdg_surface->toplevel->client_pending.fullscreen) { | 277 | if (xdg_surface->toplevel->client_pending.fullscreen) { |
256 | view_set_fullscreen(view, true); | 278 | view_set_fullscreen(view, true); |
257 | struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); | 279 | struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); |
258 | arrange_and_commit(ws); | 280 | arrange_windows(ws); |
259 | } else { | 281 | } else { |
260 | arrange_and_commit(view->swayc->parent); | 282 | arrange_windows(view->swayc->parent); |
261 | } | 283 | } |
284 | transaction_commit_dirty(); | ||
262 | 285 | ||
263 | xdg_shell_v6_view->commit.notify = handle_commit; | 286 | xdg_shell_v6_view->commit.notify = handle_commit; |
264 | wl_signal_add(&xdg_surface->surface->events.commit, | 287 | wl_signal_add(&xdg_surface->surface->events.commit, |
@@ -295,11 +318,11 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { | |||
295 | struct wlr_xdg_surface_v6 *xdg_surface = data; | 318 | struct wlr_xdg_surface_v6 *xdg_surface = data; |
296 | 319 | ||
297 | if (xdg_surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) { | 320 | if (xdg_surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) { |
298 | wlr_log(L_DEBUG, "New xdg_shell_v6 popup"); | 321 | wlr_log(WLR_DEBUG, "New xdg_shell_v6 popup"); |
299 | return; | 322 | return; |
300 | } | 323 | } |
301 | 324 | ||
302 | wlr_log(L_DEBUG, "New xdg_shell_v6 toplevel title='%s' app_id='%s'", | 325 | wlr_log(WLR_DEBUG, "New xdg_shell_v6 toplevel title='%s' app_id='%s'", |
303 | xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); | 326 | xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); |
304 | wlr_xdg_surface_v6_ping(xdg_surface); | 327 | wlr_xdg_surface_v6_ping(xdg_surface); |
305 | 328 | ||
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index b2874cfe..9df7977d 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -119,7 +119,7 @@ static struct sway_xwayland_unmanaged *create_unmanaged( | |||
119 | struct sway_xwayland_unmanaged *surface = | 119 | struct sway_xwayland_unmanaged *surface = |
120 | calloc(1, sizeof(struct sway_xwayland_unmanaged)); | 120 | calloc(1, sizeof(struct sway_xwayland_unmanaged)); |
121 | if (surface == NULL) { | 121 | if (surface == NULL) { |
122 | wlr_log(L_ERROR, "Allocation failed"); | 122 | wlr_log(WLR_ERROR, "Allocation failed"); |
123 | return NULL; | 123 | return NULL; |
124 | } | 124 | } |
125 | 125 | ||
@@ -246,6 +246,14 @@ static bool wants_floating(struct sway_view *view) { | |||
246 | return false; | 246 | return false; |
247 | } | 247 | } |
248 | 248 | ||
249 | static bool has_client_side_decorations(struct sway_view *view) { | ||
250 | if (xwayland_view_from_view(view) == NULL) { | ||
251 | return false; | ||
252 | } | ||
253 | struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; | ||
254 | return surface->decorations != WLR_XWAYLAND_SURFACE_DECORATIONS_ALL; | ||
255 | } | ||
256 | |||
249 | static void _close(struct sway_view *view) { | 257 | static void _close(struct sway_view *view) { |
250 | if (xwayland_view_from_view(view) == NULL) { | 258 | if (xwayland_view_from_view(view) == NULL) { |
251 | return; | 259 | return; |
@@ -269,6 +277,7 @@ static const struct sway_view_impl view_impl = { | |||
269 | .set_tiled = set_tiled, | 277 | .set_tiled = set_tiled, |
270 | .set_fullscreen = set_fullscreen, | 278 | .set_fullscreen = set_fullscreen, |
271 | .wants_floating = wants_floating, | 279 | .wants_floating = wants_floating, |
280 | .has_client_side_decorations = has_client_side_decorations, | ||
272 | .close = _close, | 281 | .close = _close, |
273 | .destroy = destroy, | 282 | .destroy = destroy, |
274 | }; | 283 | }; |
@@ -288,6 +297,10 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
288 | } | 297 | } |
289 | 298 | ||
290 | view_damage_from(view); | 299 | view_damage_from(view); |
300 | |||
301 | if (view->allow_request_urgent) { | ||
302 | view_set_urgent(view, (bool)xsurface->hints_urgency); | ||
303 | } | ||
291 | } | 304 | } |
292 | 305 | ||
293 | static void handle_unmap(struct wl_listener *listener, void *data) { | 306 | static void handle_unmap(struct wl_listener *listener, void *data) { |
@@ -324,10 +337,11 @@ static void handle_map(struct wl_listener *listener, void *data) { | |||
324 | if (xsurface->fullscreen) { | 337 | if (xsurface->fullscreen) { |
325 | view_set_fullscreen(view, true); | 338 | view_set_fullscreen(view, true); |
326 | struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); | 339 | struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); |
327 | arrange_and_commit(ws); | 340 | arrange_windows(ws); |
328 | } else { | 341 | } else { |
329 | arrange_and_commit(view->swayc->parent); | 342 | arrange_windows(view->swayc->parent); |
330 | } | 343 | } |
344 | transaction_commit_dirty(); | ||
331 | } | 345 | } |
332 | 346 | ||
333 | static void handle_destroy(struct wl_listener *listener, void *data) { | 347 | static void handle_destroy(struct wl_listener *listener, void *data) { |
@@ -383,7 +397,8 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) | |||
383 | view_set_fullscreen(view, xsurface->fullscreen); | 397 | view_set_fullscreen(view, xsurface->fullscreen); |
384 | 398 | ||
385 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); | 399 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); |
386 | arrange_and_commit(output); | 400 | arrange_windows(output); |
401 | transaction_commit_dirty(); | ||
387 | } | 402 | } |
388 | 403 | ||
389 | static void handle_set_title(struct wl_listener *listener, void *data) { | 404 | static void handle_set_title(struct wl_listener *listener, void *data) { |
@@ -432,12 +447,12 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { | |||
432 | 447 | ||
433 | if (wlr_xwayland_surface_is_unmanaged(xsurface) || | 448 | if (wlr_xwayland_surface_is_unmanaged(xsurface) || |
434 | xsurface->override_redirect) { | 449 | xsurface->override_redirect) { |
435 | wlr_log(L_DEBUG, "New xwayland unmanaged surface"); | 450 | wlr_log(WLR_DEBUG, "New xwayland unmanaged surface"); |
436 | create_unmanaged(xsurface); | 451 | create_unmanaged(xsurface); |
437 | return; | 452 | return; |
438 | } | 453 | } |
439 | 454 | ||
440 | wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", | 455 | wlr_log(WLR_DEBUG, "New xwayland surface title='%s' class='%s'", |
441 | xsurface->title, xsurface->class); | 456 | xsurface->title, xsurface->class); |
442 | 457 | ||
443 | struct sway_xwayland_view *xwayland_view = | 458 | struct sway_xwayland_view *xwayland_view = |
@@ -490,7 +505,7 @@ void handle_xwayland_ready(struct wl_listener *listener, void *data) { | |||
490 | xcb_connection_t *xcb_conn = xcb_connect(NULL, NULL); | 505 | xcb_connection_t *xcb_conn = xcb_connect(NULL, NULL); |
491 | int err = xcb_connection_has_error(xcb_conn); | 506 | int err = xcb_connection_has_error(xcb_conn); |
492 | if (err) { | 507 | if (err) { |
493 | wlr_log(L_ERROR, "XCB connect failed: %d", err); | 508 | wlr_log(WLR_ERROR, "XCB connect failed: %d", err); |
494 | return; | 509 | return; |
495 | } | 510 | } |
496 | 511 | ||
@@ -509,7 +524,7 @@ void handle_xwayland_ready(struct wl_listener *listener, void *data) { | |||
509 | free(reply); | 524 | free(reply); |
510 | 525 | ||
511 | if (error != NULL) { | 526 | if (error != NULL) { |
512 | wlr_log(L_ERROR, "could not resolve atom %s, X11 error code %d", | 527 | wlr_log(WLR_ERROR, "could not resolve atom %s, X11 error code %d", |
513 | atom_map[i], error->error_code); | 528 | atom_map[i], error->error_code); |
514 | free(error); | 529 | free(error); |
515 | break; | 530 | break; |
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index a2f11557..7a9f3ed7 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <wlr/types/wlr_idle.h> | 10 | #include <wlr/types/wlr_idle.h> |
11 | #include "list.h" | 11 | #include "list.h" |
12 | #include "log.h" | 12 | #include "log.h" |
13 | #include "sway/desktop/transaction.h" | ||
13 | #include "sway/input/cursor.h" | 14 | #include "sway/input/cursor.h" |
14 | #include "sway/layers.h" | 15 | #include "sway/layers.h" |
15 | #include "sway/output.h" | 16 | #include "sway/output.h" |
@@ -219,6 +220,7 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, | |||
219 | struct sway_drag_icon *drag_icon = wlr_drag_icon->data; | 220 | struct sway_drag_icon *drag_icon = wlr_drag_icon->data; |
220 | drag_icon_update_position(drag_icon); | 221 | drag_icon_update_position(drag_icon); |
221 | } | 222 | } |
223 | transaction_commit_dirty(); | ||
222 | } | 224 | } |
223 | 225 | ||
224 | static void handle_cursor_motion(struct wl_listener *listener, void *data) { | 226 | static void handle_cursor_motion(struct wl_listener *listener, void *data) { |
@@ -278,6 +280,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor, | |||
278 | 280 | ||
279 | wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, | 281 | wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, |
280 | time_msec, button, state); | 282 | time_msec, button, state); |
283 | transaction_commit_dirty(); | ||
281 | } | 284 | } |
282 | 285 | ||
283 | static void handle_cursor_button(struct wl_listener *listener, void *data) { | 286 | static void handle_cursor_button(struct wl_listener *listener, void *data) { |
@@ -474,7 +477,7 @@ static void handle_request_set_cursor(struct wl_listener *listener, | |||
474 | // TODO: check cursor mode | 477 | // TODO: check cursor mode |
475 | if (focused_client == NULL || | 478 | if (focused_client == NULL || |
476 | event->seat_client->client != focused_client) { | 479 | event->seat_client->client != focused_client) { |
477 | wlr_log(L_DEBUG, "denying request to set cursor from unfocused client"); | 480 | wlr_log(WLR_DEBUG, "denying request to set cursor from unfocused client"); |
478 | return; | 481 | return; |
479 | } | 482 | } |
480 | 483 | ||
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 98f7d7cf..0b7cb766 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c | |||
@@ -61,7 +61,7 @@ static char *get_device_identifier(struct wlr_input_device *device) { | |||
61 | int len = snprintf(NULL, 0, fmt, vendor, product, name) + 1; | 61 | int len = snprintf(NULL, 0, fmt, vendor, product, name) + 1; |
62 | char *identifier = malloc(len); | 62 | char *identifier = malloc(len); |
63 | if (!identifier) { | 63 | if (!identifier) { |
64 | wlr_log(L_ERROR, "Unable to allocate unique input device name"); | 64 | wlr_log(WLR_ERROR, "Unable to allocate unique input device name"); |
65 | return NULL; | 65 | return NULL; |
66 | } | 66 | } |
67 | 67 | ||
@@ -104,77 +104,89 @@ static void input_manager_libinput_config_pointer( | |||
104 | } | 104 | } |
105 | 105 | ||
106 | libinput_device = wlr_libinput_get_device_handle(wlr_device); | 106 | libinput_device = wlr_libinput_get_device_handle(wlr_device); |
107 | wlr_log(L_DEBUG, "input_manager_libinput_config_pointer(%s)", | 107 | wlr_log(WLR_DEBUG, "input_manager_libinput_config_pointer(%s)", |
108 | ic->identifier); | 108 | ic->identifier); |
109 | 109 | ||
110 | if (ic->accel_profile != INT_MIN) { | 110 | if (ic->accel_profile != INT_MIN) { |
111 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_profile(%d)", | 111 | wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) accel_set_profile(%d)", |
112 | ic->identifier, ic->accel_profile); | 112 | ic->identifier, ic->accel_profile); |
113 | libinput_device_config_accel_set_profile(libinput_device, | 113 | libinput_device_config_accel_set_profile(libinput_device, |
114 | ic->accel_profile); | 114 | ic->accel_profile); |
115 | } | 115 | } |
116 | if (ic->click_method != INT_MIN) { | 116 | if (ic->click_method != INT_MIN) { |
117 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) click_set_method(%d)", | 117 | wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) click_set_method(%d)", |
118 | ic->identifier, ic->click_method); | 118 | ic->identifier, ic->click_method); |
119 | libinput_device_config_click_set_method(libinput_device, | 119 | libinput_device_config_click_set_method(libinput_device, |
120 | ic->click_method); | 120 | ic->click_method); |
121 | } | 121 | } |
122 | if (ic->drag_lock != INT_MIN) { | 122 | if (ic->drag_lock != INT_MIN) { |
123 | wlr_log(L_DEBUG, | 123 | wlr_log(WLR_DEBUG, |
124 | "libinput_config_pointer(%s) tap_set_drag_lock_enabled(%d)", | 124 | "libinput_config_pointer(%s) tap_set_drag_lock_enabled(%d)", |
125 | ic->identifier, ic->click_method); | 125 | ic->identifier, ic->click_method); |
126 | libinput_device_config_tap_set_drag_lock_enabled(libinput_device, | 126 | libinput_device_config_tap_set_drag_lock_enabled(libinput_device, |
127 | ic->drag_lock); | 127 | ic->drag_lock); |
128 | } | 128 | } |
129 | if (ic->dwt != INT_MIN) { | 129 | if (ic->dwt != INT_MIN) { |
130 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) dwt_set_enabled(%d)", | 130 | wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) dwt_set_enabled(%d)", |
131 | ic->identifier, ic->dwt); | 131 | ic->identifier, ic->dwt); |
132 | libinput_device_config_dwt_set_enabled(libinput_device, ic->dwt); | 132 | libinput_device_config_dwt_set_enabled(libinput_device, ic->dwt); |
133 | } | 133 | } |
134 | if (ic->left_handed != INT_MIN) { | 134 | if (ic->left_handed != INT_MIN) { |
135 | wlr_log(L_DEBUG, | 135 | wlr_log(WLR_DEBUG, |
136 | "libinput_config_pointer(%s) left_handed_set_enabled(%d)", | 136 | "libinput_config_pointer(%s) left_handed_set_enabled(%d)", |
137 | ic->identifier, ic->left_handed); | 137 | ic->identifier, ic->left_handed); |
138 | libinput_device_config_left_handed_set(libinput_device, | 138 | libinput_device_config_left_handed_set(libinput_device, |
139 | ic->left_handed); | 139 | ic->left_handed); |
140 | } | 140 | } |
141 | if (ic->middle_emulation != INT_MIN) { | 141 | if (ic->middle_emulation != INT_MIN) { |
142 | wlr_log(L_DEBUG, | 142 | wlr_log(WLR_DEBUG, |
143 | "libinput_config_pointer(%s) middle_emulation_set_enabled(%d)", | 143 | "libinput_config_pointer(%s) middle_emulation_set_enabled(%d)", |
144 | ic->identifier, ic->middle_emulation); | 144 | ic->identifier, ic->middle_emulation); |
145 | libinput_device_config_middle_emulation_set_enabled(libinput_device, | 145 | libinput_device_config_middle_emulation_set_enabled(libinput_device, |
146 | ic->middle_emulation); | 146 | ic->middle_emulation); |
147 | } | 147 | } |
148 | if (ic->natural_scroll != INT_MIN) { | 148 | if (ic->natural_scroll != INT_MIN) { |
149 | wlr_log(L_DEBUG, | 149 | wlr_log(WLR_DEBUG, |
150 | "libinput_config_pointer(%s) natural_scroll_set_enabled(%d)", | 150 | "libinput_config_pointer(%s) natural_scroll_set_enabled(%d)", |
151 | ic->identifier, ic->natural_scroll); | 151 | ic->identifier, ic->natural_scroll); |
152 | libinput_device_config_scroll_set_natural_scroll_enabled( | 152 | libinput_device_config_scroll_set_natural_scroll_enabled( |
153 | libinput_device, ic->natural_scroll); | 153 | libinput_device, ic->natural_scroll); |
154 | } | 154 | } |
155 | if (ic->pointer_accel != FLT_MIN) { | 155 | if (ic->pointer_accel != FLT_MIN) { |
156 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_speed(%f)", | 156 | wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) accel_set_speed(%f)", |
157 | ic->identifier, ic->pointer_accel); | 157 | ic->identifier, ic->pointer_accel); |
158 | libinput_device_config_accel_set_speed(libinput_device, | 158 | libinput_device_config_accel_set_speed(libinput_device, |
159 | ic->pointer_accel); | 159 | ic->pointer_accel); |
160 | } | 160 | } |
161 | if (ic->scroll_button != INT_MIN) { | ||
162 | wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) scroll_set_button(%d)", | ||
163 | ic->identifier, ic->scroll_button); | ||
164 | libinput_device_config_scroll_set_button(libinput_device, | ||
165 | ic->scroll_button); | ||
166 | } | ||
161 | if (ic->scroll_method != INT_MIN) { | 167 | if (ic->scroll_method != INT_MIN) { |
162 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) scroll_set_method(%d)", | 168 | wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) scroll_set_method(%d)", |
163 | ic->identifier, ic->scroll_method); | 169 | ic->identifier, ic->scroll_method); |
164 | libinput_device_config_scroll_set_method(libinput_device, | 170 | libinput_device_config_scroll_set_method(libinput_device, |
165 | ic->scroll_method); | 171 | ic->scroll_method); |
166 | } | 172 | } |
167 | if (ic->send_events != INT_MIN) { | 173 | if (ic->send_events != INT_MIN) { |
168 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) send_events_set_mode(%d)", | 174 | wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) send_events_set_mode(%d)", |
169 | ic->identifier, ic->send_events); | 175 | ic->identifier, ic->send_events); |
170 | libinput_device_config_send_events_set_mode(libinput_device, | 176 | libinput_device_config_send_events_set_mode(libinput_device, |
171 | ic->send_events); | 177 | ic->send_events); |
172 | } | 178 | } |
173 | if (ic->tap != INT_MIN) { | 179 | if (ic->tap != INT_MIN) { |
174 | wlr_log(L_DEBUG, "libinput_config_pointer(%s) tap_set_enabled(%d)", | 180 | wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) tap_set_enabled(%d)", |
175 | ic->identifier, ic->tap); | 181 | ic->identifier, ic->tap); |
176 | libinput_device_config_tap_set_enabled(libinput_device, ic->tap); | 182 | libinput_device_config_tap_set_enabled(libinput_device, ic->tap); |
177 | } | 183 | } |
184 | if (ic->tap_button_map != INT_MIN) { | ||
185 | wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) tap_set_button_map(%d)", | ||
186 | ic->identifier, ic->tap); | ||
187 | libinput_device_config_tap_set_button_map(libinput_device, | ||
188 | ic->tap_button_map); | ||
189 | } | ||
178 | } | 190 | } |
179 | 191 | ||
180 | static void handle_device_destroy(struct wl_listener *listener, void *data) { | 192 | static void handle_device_destroy(struct wl_listener *listener, void *data) { |
@@ -187,7 +199,7 @@ static void handle_device_destroy(struct wl_listener *listener, void *data) { | |||
187 | return; | 199 | return; |
188 | } | 200 | } |
189 | 201 | ||
190 | wlr_log(L_DEBUG, "removing device: '%s'", | 202 | wlr_log(WLR_DEBUG, "removing device: '%s'", |
191 | input_device->identifier); | 203 | input_device->identifier); |
192 | 204 | ||
193 | struct sway_seat *seat = NULL; | 205 | struct sway_seat *seat = NULL; |
@@ -217,7 +229,7 @@ static void handle_new_input(struct wl_listener *listener, void *data) { | |||
217 | input_device->identifier = get_device_identifier(device); | 229 | input_device->identifier = get_device_identifier(device); |
218 | wl_list_insert(&input->devices, &input_device->link); | 230 | wl_list_insert(&input->devices, &input_device->link); |
219 | 231 | ||
220 | wlr_log(L_DEBUG, "adding device: '%s'", | 232 | wlr_log(WLR_DEBUG, "adding device: '%s'", |
221 | input_device->identifier); | 233 | input_device->identifier); |
222 | 234 | ||
223 | if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) { | 235 | if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) { |
@@ -229,7 +241,7 @@ static void handle_new_input(struct wl_listener *listener, void *data) { | |||
229 | 241 | ||
230 | struct sway_seat *seat = NULL; | 242 | struct sway_seat *seat = NULL; |
231 | if (!input_has_seat_configuration(input)) { | 243 | if (!input_has_seat_configuration(input)) { |
232 | wlr_log(L_DEBUG, "no seat configuration, using default seat"); | 244 | wlr_log(WLR_DEBUG, "no seat configuration, using default seat"); |
233 | seat = input_manager_get_seat(input, default_seat); | 245 | seat = input_manager_get_seat(input, default_seat); |
234 | seat_add_device(seat, input_device); | 246 | seat_add_device(seat, input_device); |
235 | return; | 247 | return; |
@@ -259,7 +271,7 @@ static void handle_new_input(struct wl_listener *listener, void *data) { | |||
259 | } | 271 | } |
260 | 272 | ||
261 | if (!added) { | 273 | if (!added) { |
262 | wlr_log(L_DEBUG, | 274 | wlr_log(WLR_DEBUG, |
263 | "device '%s' is not configured on any seats", | 275 | "device '%s' is not configured on any seats", |
264 | input_device->identifier); | 276 | input_device->identifier); |
265 | } | 277 | } |
@@ -282,7 +294,7 @@ static void handle_inhibit_deactivate(struct wl_listener *listener, void *data) | |||
282 | seat_set_exclusive_client(seat, NULL); | 294 | seat_set_exclusive_client(seat, NULL); |
283 | struct sway_container *previous = seat_get_focus(seat); | 295 | struct sway_container *previous = seat_get_focus(seat); |
284 | if (previous) { | 296 | if (previous) { |
285 | wlr_log(L_DEBUG, "Returning focus to %p %s '%s'", previous, | 297 | wlr_log(WLR_DEBUG, "Returning focus to %p %s '%s'", previous, |
286 | container_type_to_str(previous->type), previous->name); | 298 | container_type_to_str(previous->type), previous->name); |
287 | // Hack to get seat to re-focus the return value of get_focus | 299 | // Hack to get seat to re-focus the return value of get_focus |
288 | seat_set_focus(seat, previous->parent); | 300 | seat_set_focus(seat, previous->parent); |
@@ -359,7 +371,7 @@ void input_manager_apply_input_config(struct sway_input_manager *input, | |||
359 | 371 | ||
360 | void input_manager_apply_seat_config(struct sway_input_manager *input, | 372 | void input_manager_apply_seat_config(struct sway_input_manager *input, |
361 | struct seat_config *seat_config) { | 373 | struct seat_config *seat_config) { |
362 | wlr_log(L_DEBUG, "applying new seat config for seat %s", | 374 | wlr_log(WLR_DEBUG, "applying new seat config for seat %s", |
363 | seat_config->name); | 375 | seat_config->name); |
364 | struct sway_seat *seat = input_manager_get_seat(input, seat_config->name); | 376 | struct sway_seat *seat = input_manager_get_seat(input, seat_config->name); |
365 | if (!seat) { | 377 | if (!seat) { |
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 182536de..ede38519 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <wlr/backend/multi.h> | 3 | #include <wlr/backend/multi.h> |
4 | #include <wlr/backend/session.h> | 4 | #include <wlr/backend/session.h> |
5 | #include <wlr/types/wlr_idle.h> | 5 | #include <wlr/types/wlr_idle.h> |
6 | #include "sway/desktop/transaction.h" | ||
6 | #include "sway/input/seat.h" | 7 | #include "sway/input/seat.h" |
7 | #include "sway/input/keyboard.h" | 8 | #include "sway/input/keyboard.h" |
8 | #include "sway/input/input-manager.h" | 9 | #include "sway/input/input-manager.h" |
@@ -108,7 +109,7 @@ static void get_active_binding(const struct sway_shortcut_state *state, | |||
108 | } | 109 | } |
109 | 110 | ||
110 | if (*current_binding && *current_binding != binding) { | 111 | if (*current_binding && *current_binding != binding) { |
111 | wlr_log(L_DEBUG, "encountered duplicate bindings %d and %d", | 112 | wlr_log(WLR_DEBUG, "encountered duplicate bindings %d and %d", |
112 | (*current_binding)->order, binding->order); | 113 | (*current_binding)->order, binding->order); |
113 | } else { | 114 | } else { |
114 | *current_binding = binding; | 115 | *current_binding = binding; |
@@ -122,12 +123,13 @@ static void get_active_binding(const struct sway_shortcut_state *state, | |||
122 | */ | 123 | */ |
123 | static void keyboard_execute_command(struct sway_keyboard *keyboard, | 124 | static void keyboard_execute_command(struct sway_keyboard *keyboard, |
124 | struct sway_binding *binding) { | 125 | struct sway_binding *binding) { |
125 | wlr_log(L_DEBUG, "running command for binding: %s", | 126 | wlr_log(WLR_DEBUG, "running command for binding: %s", |
126 | binding->command); | 127 | binding->command); |
127 | config->handler_context.seat = keyboard->seat_device->sway_seat; | 128 | config->handler_context.seat = keyboard->seat_device->sway_seat; |
128 | struct cmd_results *results = execute_command(binding->command, NULL); | 129 | struct cmd_results *results = execute_command(binding->command, NULL); |
130 | transaction_commit_dirty(); | ||
129 | if (results->status != CMD_SUCCESS) { | 131 | if (results->status != CMD_SUCCESS) { |
130 | wlr_log(L_DEBUG, "could not run command for binding: %s (%s)", | 132 | wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)", |
131 | binding->command, results->error); | 133 | binding->command, results->error); |
132 | } | 134 | } |
133 | free_cmd_results(results); | 135 | free_cmd_results(results); |
@@ -386,7 +388,7 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { | |||
386 | xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); | 388 | xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); |
387 | 389 | ||
388 | if (!keymap) { | 390 | if (!keymap) { |
389 | wlr_log(L_DEBUG, "cannot configure keyboard: keymap does not exist"); | 391 | wlr_log(WLR_DEBUG, "cannot configure keyboard: keymap does not exist"); |
390 | xkb_context_unref(context); | 392 | xkb_context_unref(context); |
391 | return; | 393 | return; |
392 | } | 394 | } |
diff --git a/sway/input/seat.c b/sway/input/seat.c index 6c5abcd8..12b1fab5 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -75,7 +75,7 @@ static void seat_send_activate(struct sway_container *con, | |||
75 | struct sway_seat *seat) { | 75 | struct sway_seat *seat) { |
76 | if (con->type == C_VIEW) { | 76 | if (con->type == C_VIEW) { |
77 | if (!seat_is_input_allowed(seat, con->sway_view->surface)) { | 77 | if (!seat_is_input_allowed(seat, con->sway_view->surface)) { |
78 | wlr_log(L_DEBUG, "Refusing to set focus, input is inhibited"); | 78 | wlr_log(WLR_DEBUG, "Refusing to set focus, input is inhibited"); |
79 | return; | 79 | return; |
80 | } | 80 | } |
81 | view_set_activated(con->sway_view, true); | 81 | view_set_activated(con->sway_view, true); |
@@ -219,7 +219,7 @@ static struct sway_seat_container *seat_container_from_container( | |||
219 | 219 | ||
220 | seat_con = calloc(1, sizeof(struct sway_seat_container)); | 220 | seat_con = calloc(1, sizeof(struct sway_seat_container)); |
221 | if (seat_con == NULL) { | 221 | if (seat_con == NULL) { |
222 | wlr_log(L_ERROR, "could not allocate seat container"); | 222 | wlr_log(WLR_ERROR, "could not allocate seat container"); |
223 | return NULL; | 223 | return NULL; |
224 | } | 224 | } |
225 | 225 | ||
@@ -301,7 +301,7 @@ static void handle_new_drag_icon(struct wl_listener *listener, void *data) { | |||
301 | 301 | ||
302 | struct sway_drag_icon *icon = calloc(1, sizeof(struct sway_drag_icon)); | 302 | struct sway_drag_icon *icon = calloc(1, sizeof(struct sway_drag_icon)); |
303 | if (icon == NULL) { | 303 | if (icon == NULL) { |
304 | wlr_log(L_ERROR, "Allocation failed"); | 304 | wlr_log(WLR_ERROR, "Allocation failed"); |
305 | return; | 305 | return; |
306 | } | 306 | } |
307 | icon->seat = seat; | 307 | icon->seat = seat; |
@@ -391,7 +391,7 @@ static void seat_apply_input_config(struct sway_seat *seat, | |||
391 | struct input_config *ic = input_device_get_config( | 391 | struct input_config *ic = input_device_get_config( |
392 | sway_device->input_device); | 392 | sway_device->input_device); |
393 | if (ic != NULL) { | 393 | if (ic != NULL) { |
394 | wlr_log(L_DEBUG, "Applying input config to %s", | 394 | wlr_log(WLR_DEBUG, "Applying input config to %s", |
395 | sway_device->input_device->identifier); | 395 | sway_device->input_device->identifier); |
396 | 396 | ||
397 | mapped_to_output = ic->mapped_to_output; | 397 | mapped_to_output = ic->mapped_to_output; |
@@ -401,7 +401,7 @@ static void seat_apply_input_config(struct sway_seat *seat, | |||
401 | mapped_to_output = sway_device->input_device->wlr_device->output_name; | 401 | mapped_to_output = sway_device->input_device->wlr_device->output_name; |
402 | } | 402 | } |
403 | if (mapped_to_output != NULL) { | 403 | if (mapped_to_output != NULL) { |
404 | wlr_log(L_DEBUG, "Mapping input device %s to output %s", | 404 | wlr_log(WLR_DEBUG, "Mapping input device %s to output %s", |
405 | sway_device->input_device->identifier, mapped_to_output); | 405 | sway_device->input_device->identifier, mapped_to_output); |
406 | struct sway_container *output = NULL; | 406 | struct sway_container *output = NULL; |
407 | for (int i = 0; i < root_container.children->length; ++i) { | 407 | for (int i = 0; i < root_container.children->length; ++i) { |
@@ -415,7 +415,7 @@ static void seat_apply_input_config(struct sway_seat *seat, | |||
415 | wlr_cursor_map_input_to_output(seat->cursor->cursor, | 415 | wlr_cursor_map_input_to_output(seat->cursor->cursor, |
416 | sway_device->input_device->wlr_device, | 416 | sway_device->input_device->wlr_device, |
417 | output->sway_output->wlr_output); | 417 | output->sway_output->wlr_output); |
418 | wlr_log(L_DEBUG, "Mapped to output %s", output->name); | 418 | wlr_log(WLR_DEBUG, "Mapped to output %s", output->name); |
419 | } | 419 | } |
420 | } | 420 | } |
421 | } | 421 | } |
@@ -495,7 +495,7 @@ void seat_configure_device(struct sway_seat *seat, | |||
495 | seat_configure_tablet_tool(seat, seat_device); | 495 | seat_configure_tablet_tool(seat, seat_device); |
496 | break; | 496 | break; |
497 | case WLR_INPUT_DEVICE_TABLET_PAD: | 497 | case WLR_INPUT_DEVICE_TABLET_PAD: |
498 | wlr_log(L_DEBUG, "TODO: configure tablet pad"); | 498 | wlr_log(WLR_DEBUG, "TODO: configure tablet pad"); |
499 | break; | 499 | break; |
500 | } | 500 | } |
501 | } | 501 | } |
@@ -510,11 +510,11 @@ void seat_add_device(struct sway_seat *seat, | |||
510 | struct sway_seat_device *seat_device = | 510 | struct sway_seat_device *seat_device = |
511 | calloc(1, sizeof(struct sway_seat_device)); | 511 | calloc(1, sizeof(struct sway_seat_device)); |
512 | if (!seat_device) { | 512 | if (!seat_device) { |
513 | wlr_log(L_DEBUG, "could not allocate seat device"); | 513 | wlr_log(WLR_DEBUG, "could not allocate seat device"); |
514 | return; | 514 | return; |
515 | } | 515 | } |
516 | 516 | ||
517 | wlr_log(L_DEBUG, "adding device %s to seat %s", | 517 | wlr_log(WLR_DEBUG, "adding device %s to seat %s", |
518 | input_device->identifier, seat->wlr_seat->name); | 518 | input_device->identifier, seat->wlr_seat->name); |
519 | 519 | ||
520 | seat_device->sway_seat = seat; | 520 | seat_device->sway_seat = seat; |
@@ -533,7 +533,7 @@ void seat_remove_device(struct sway_seat *seat, | |||
533 | return; | 533 | return; |
534 | } | 534 | } |
535 | 535 | ||
536 | wlr_log(L_DEBUG, "removing device %s from seat %s", | 536 | wlr_log(WLR_DEBUG, "removing device %s from seat %s", |
537 | input_device->identifier, seat->wlr_seat->name); | 537 | input_device->identifier, seat->wlr_seat->name); |
538 | 538 | ||
539 | seat_device_destroy(seat_device); | 539 | seat_device_destroy(seat_device); |
@@ -594,6 +594,12 @@ static void seat_send_unfocus(struct sway_container *container, | |||
594 | } | 594 | } |
595 | } | 595 | } |
596 | 596 | ||
597 | static int handle_urgent_timeout(void *data) { | ||
598 | struct sway_view *view = data; | ||
599 | view_set_urgent(view, false); | ||
600 | return 0; | ||
601 | } | ||
602 | |||
597 | void seat_set_focus_warp(struct sway_seat *seat, | 603 | void seat_set_focus_warp(struct sway_seat *seat, |
598 | struct sway_container *container, bool warp) { | 604 | struct sway_container *container, bool warp) { |
599 | if (seat->focused_layer) { | 605 | if (seat->focused_layer) { |
@@ -649,6 +655,7 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
649 | while (parent) { | 655 | while (parent) { |
650 | wl_list_remove(&parent->link); | 656 | wl_list_remove(&parent->link); |
651 | wl_list_insert(&seat->focus_stack, &parent->link); | 657 | wl_list_insert(&seat->focus_stack, &parent->link); |
658 | container_set_dirty(parent->container); | ||
652 | 659 | ||
653 | parent = | 660 | parent = |
654 | seat_container_from_container(seat, | 661 | seat_container_from_container(seat, |
@@ -661,9 +668,33 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
661 | if (last_focus) { | 668 | if (last_focus) { |
662 | seat_send_unfocus(last_focus, seat); | 669 | seat_send_unfocus(last_focus, seat); |
663 | } | 670 | } |
664 | |||
665 | seat_send_focus(container, seat); | 671 | seat_send_focus(container, seat); |
666 | container_damage_whole(container->parent); | 672 | |
673 | container_set_dirty(container); | ||
674 | container_set_dirty(container->parent); // for focused_inactive_child | ||
675 | if (last_focus) { | ||
676 | container_set_dirty(last_focus); | ||
677 | } | ||
678 | } | ||
679 | |||
680 | // If urgent, start a timer to unset it | ||
681 | if (container && container->type == C_VIEW && | ||
682 | view_is_urgent(container->sway_view) && | ||
683 | !container->sway_view->urgent_timer) { | ||
684 | struct sway_view *view = container->sway_view; | ||
685 | view->urgent_timer = wl_event_loop_add_timer(server.wl_event_loop, | ||
686 | handle_urgent_timeout, view); | ||
687 | wl_event_source_timer_update(view->urgent_timer, 1000); | ||
688 | } | ||
689 | |||
690 | // If we've focused a floating container, bring it to the front. | ||
691 | // We do this by putting it at the end of the floating list. | ||
692 | // This must happen for both the pending and current children lists. | ||
693 | if (container && container_is_floating(container)) { | ||
694 | list_move_to_end(container->parent->children, container); | ||
695 | if (container_has_ancestor(container, container->current.parent)) { | ||
696 | list_move_to_end(container->parent->current.children, container); | ||
697 | } | ||
667 | } | 698 | } |
668 | 699 | ||
669 | // clean up unfocused empty workspace on new output | 700 | // clean up unfocused empty workspace on new output |
@@ -707,10 +738,6 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
707 | } | 738 | } |
708 | } | 739 | } |
709 | 740 | ||
710 | if (last_focus) { | ||
711 | container_damage_whole(last_focus); | ||
712 | } | ||
713 | |||
714 | if (last_workspace && last_workspace != new_workspace) { | 741 | if (last_workspace && last_workspace != new_workspace) { |
715 | cursor_send_pointer_motion(seat->cursor, 0, true); | 742 | cursor_send_pointer_motion(seat->cursor, 0, true); |
716 | } | 743 | } |
@@ -752,7 +779,7 @@ void seat_set_focus_layer(struct sway_seat *seat, | |||
752 | struct sway_container *previous = | 779 | struct sway_container *previous = |
753 | seat_get_focus_inactive(seat, &root_container); | 780 | seat_get_focus_inactive(seat, &root_container); |
754 | if (previous) { | 781 | if (previous) { |
755 | wlr_log(L_DEBUG, "Returning focus to %p %s '%s'", previous, | 782 | wlr_log(WLR_DEBUG, "Returning focus to %p %s '%s'", previous, |
756 | container_type_to_str(previous->type), previous->name); | 783 | container_type_to_str(previous->type), previous->name); |
757 | // Hack to get seat to re-focus the return value of get_focus | 784 | // Hack to get seat to re-focus the return value of get_focus |
758 | seat_set_focus(seat, previous->parent); | 785 | seat_set_focus(seat, previous->parent); |
@@ -830,18 +857,6 @@ struct sway_container *seat_get_active_child(struct sway_seat *seat, | |||
830 | return NULL; | 857 | return NULL; |
831 | } | 858 | } |
832 | 859 | ||
833 | struct sway_container *seat_get_active_current_child(struct sway_seat *seat, | ||
834 | struct sway_container *container) { | ||
835 | struct sway_seat_container *current = NULL; | ||
836 | wl_list_for_each(current, &seat->focus_stack, link) { | ||
837 | if (current->container->current.parent == container && | ||
838 | current->container->current.layout != L_FLOATING) { | ||
839 | return current->container; | ||
840 | } | ||
841 | } | ||
842 | return NULL; | ||
843 | } | ||
844 | |||
845 | struct sway_container *seat_get_focus(struct sway_seat *seat) { | 860 | struct sway_container *seat_get_focus(struct sway_seat *seat) { |
846 | if (!seat->has_focus) { | 861 | if (!seat->has_focus) { |
847 | return NULL; | 862 | return NULL; |
diff --git a/sway/ipc-json.c b/sway/ipc-json.c index b9289e25..c49ea47e 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <stdio.h> | 2 | #include <stdio.h> |
3 | #include <ctype.h> | 3 | #include <ctype.h> |
4 | #include "log.h" | 4 | #include "log.h" |
5 | #include "sway/config.h" | ||
5 | #include "sway/ipc-json.h" | 6 | #include "sway/ipc-json.h" |
6 | #include "sway/tree/container.h" | 7 | #include "sway/tree/container.h" |
7 | #include "sway/tree/workspace.h" | 8 | #include "sway/tree/workspace.h" |
@@ -41,6 +42,7 @@ json_object *ipc_json_get_version() { | |||
41 | json_object_object_add(version, "major", json_object_new_int(major)); | 42 | json_object_object_add(version, "major", json_object_new_int(major)); |
42 | json_object_object_add(version, "minor", json_object_new_int(minor)); | 43 | json_object_object_add(version, "minor", json_object_new_int(minor)); |
43 | json_object_object_add(version, "patch", json_object_new_int(patch)); | 44 | json_object_object_add(version, "patch", json_object_new_int(patch)); |
45 | json_object_object_add(version, "loaded_config_file_name", json_object_new_string(config->current_config_path)); | ||
44 | 46 | ||
45 | return version; | 47 | return version; |
46 | } | 48 | } |
@@ -168,7 +170,8 @@ static void ipc_json_describe_workspace(struct sway_container *workspace, | |||
168 | json_object_object_add(object, "output", workspace->parent ? | 170 | json_object_object_add(object, "output", workspace->parent ? |
169 | json_object_new_string(workspace->parent->name) : NULL); | 171 | json_object_new_string(workspace->parent->name) : NULL); |
170 | json_object_object_add(object, "type", json_object_new_string("workspace")); | 172 | json_object_object_add(object, "type", json_object_new_string("workspace")); |
171 | json_object_object_add(object, "urgent", json_object_new_boolean(false)); | 173 | json_object_object_add(object, "urgent", |
174 | json_object_new_boolean(workspace->sway_workspace->urgent)); | ||
172 | json_object_object_add(object, "representation", workspace->formatted_title ? | 175 | json_object_object_add(object, "representation", workspace->formatted_title ? |
173 | json_object_new_string(workspace->formatted_title) : NULL); | 176 | json_object_new_string(workspace->formatted_title) : NULL); |
174 | 177 | ||
@@ -194,6 +197,10 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object | |||
194 | json_object_object_add(object, "layout", | 197 | json_object_object_add(object, "layout", |
195 | json_object_new_string(ipc_json_layout_description(c->layout))); | 198 | json_object_new_string(ipc_json_layout_description(c->layout))); |
196 | } | 199 | } |
200 | |||
201 | bool urgent = c->type == C_VIEW ? | ||
202 | view_is_urgent(c->sway_view) : container_has_urgent_child(c); | ||
203 | json_object_object_add(object, "urgent", json_object_new_boolean(urgent)); | ||
197 | } | 204 | } |
198 | 205 | ||
199 | static void focus_inactive_children_iterator(struct sway_container *c, void *data) { | 206 | static void focus_inactive_children_iterator(struct sway_container *c, void *data) { |
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index abdaa237..be703915 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <unistd.h> | 17 | #include <unistd.h> |
18 | #include <wayland-server.h> | 18 | #include <wayland-server.h> |
19 | #include "sway/commands.h" | 19 | #include "sway/commands.h" |
20 | #include "sway/config.h" | ||
21 | #include "sway/desktop/transaction.h" | ||
20 | #include "sway/ipc-json.h" | 22 | #include "sway/ipc-json.h" |
21 | #include "sway/ipc-server.h" | 23 | #include "sway/ipc-server.h" |
22 | #include "sway/output.h" | 24 | #include "sway/output.h" |
@@ -138,32 +140,32 @@ struct sockaddr_un *ipc_user_sockaddr(void) { | |||
138 | int ipc_handle_connection(int fd, uint32_t mask, void *data) { | 140 | int ipc_handle_connection(int fd, uint32_t mask, void *data) { |
139 | (void) fd; | 141 | (void) fd; |
140 | struct sway_server *server = data; | 142 | struct sway_server *server = data; |
141 | wlr_log(L_DEBUG, "Event on IPC listening socket"); | 143 | wlr_log(WLR_DEBUG, "Event on IPC listening socket"); |
142 | assert(mask == WL_EVENT_READABLE); | 144 | assert(mask == WL_EVENT_READABLE); |
143 | 145 | ||
144 | int client_fd = accept(ipc_socket, NULL, NULL); | 146 | int client_fd = accept(ipc_socket, NULL, NULL); |
145 | if (client_fd == -1) { | 147 | if (client_fd == -1) { |
146 | wlr_log_errno(L_ERROR, "Unable to accept IPC client connection"); | 148 | wlr_log_errno(WLR_ERROR, "Unable to accept IPC client connection"); |
147 | return 0; | 149 | return 0; |
148 | } | 150 | } |
149 | 151 | ||
150 | int flags; | 152 | int flags; |
151 | if ((flags = fcntl(client_fd, F_GETFD)) == -1 | 153 | if ((flags = fcntl(client_fd, F_GETFD)) == -1 |
152 | || fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC) == -1) { | 154 | || fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC) == -1) { |
153 | wlr_log_errno(L_ERROR, "Unable to set CLOEXEC on IPC client socket"); | 155 | wlr_log_errno(WLR_ERROR, "Unable to set CLOEXEC on IPC client socket"); |
154 | close(client_fd); | 156 | close(client_fd); |
155 | return 0; | 157 | return 0; |
156 | } | 158 | } |
157 | if ((flags = fcntl(client_fd, F_GETFL)) == -1 | 159 | if ((flags = fcntl(client_fd, F_GETFL)) == -1 |
158 | || fcntl(client_fd, F_SETFL, flags|O_NONBLOCK) == -1) { | 160 | || fcntl(client_fd, F_SETFL, flags|O_NONBLOCK) == -1) { |
159 | wlr_log_errno(L_ERROR, "Unable to set NONBLOCK on IPC client socket"); | 161 | wlr_log_errno(WLR_ERROR, "Unable to set NONBLOCK on IPC client socket"); |
160 | close(client_fd); | 162 | close(client_fd); |
161 | return 0; | 163 | return 0; |
162 | } | 164 | } |
163 | 165 | ||
164 | struct ipc_client *client = malloc(sizeof(struct ipc_client)); | 166 | struct ipc_client *client = malloc(sizeof(struct ipc_client)); |
165 | if (!client) { | 167 | if (!client) { |
166 | wlr_log(L_ERROR, "Unable to allocate ipc client"); | 168 | wlr_log(WLR_ERROR, "Unable to allocate ipc client"); |
167 | close(client_fd); | 169 | close(client_fd); |
168 | return 0; | 170 | return 0; |
169 | } | 171 | } |
@@ -179,12 +181,12 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { | |||
179 | client->write_buffer_len = 0; | 181 | client->write_buffer_len = 0; |
180 | client->write_buffer = malloc(client->write_buffer_size); | 182 | client->write_buffer = malloc(client->write_buffer_size); |
181 | if (!client->write_buffer) { | 183 | if (!client->write_buffer) { |
182 | wlr_log(L_ERROR, "Unable to allocate ipc client write buffer"); | 184 | wlr_log(WLR_ERROR, "Unable to allocate ipc client write buffer"); |
183 | close(client_fd); | 185 | close(client_fd); |
184 | return 0; | 186 | return 0; |
185 | } | 187 | } |
186 | 188 | ||
187 | wlr_log(L_DEBUG, "New client: fd %d", client_fd); | 189 | wlr_log(WLR_DEBUG, "New client: fd %d", client_fd); |
188 | list_add(ipc_client_list, client); | 190 | list_add(ipc_client_list, client); |
189 | return 0; | 191 | return 0; |
190 | } | 192 | } |
@@ -195,22 +197,22 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { | |||
195 | struct ipc_client *client = data; | 197 | struct ipc_client *client = data; |
196 | 198 | ||
197 | if (mask & WL_EVENT_ERROR) { | 199 | if (mask & WL_EVENT_ERROR) { |
198 | wlr_log(L_ERROR, "IPC Client socket error, removing client"); | 200 | wlr_log(WLR_ERROR, "IPC Client socket error, removing client"); |
199 | ipc_client_disconnect(client); | 201 | ipc_client_disconnect(client); |
200 | return 0; | 202 | return 0; |
201 | } | 203 | } |
202 | 204 | ||
203 | if (mask & WL_EVENT_HANGUP) { | 205 | if (mask & WL_EVENT_HANGUP) { |
204 | wlr_log(L_DEBUG, "Client %d hung up", client->fd); | 206 | wlr_log(WLR_DEBUG, "Client %d hung up", client->fd); |
205 | ipc_client_disconnect(client); | 207 | ipc_client_disconnect(client); |
206 | return 0; | 208 | return 0; |
207 | } | 209 | } |
208 | 210 | ||
209 | wlr_log(L_DEBUG, "Client %d readable", client->fd); | 211 | wlr_log(WLR_DEBUG, "Client %d readable", client->fd); |
210 | 212 | ||
211 | int read_available; | 213 | int read_available; |
212 | if (ioctl(client_fd, FIONREAD, &read_available) == -1) { | 214 | if (ioctl(client_fd, FIONREAD, &read_available) == -1) { |
213 | wlr_log_errno(L_INFO, "Unable to read IPC socket buffer size"); | 215 | wlr_log_errno(WLR_INFO, "Unable to read IPC socket buffer size"); |
214 | ipc_client_disconnect(client); | 216 | ipc_client_disconnect(client); |
215 | return 0; | 217 | return 0; |
216 | } | 218 | } |
@@ -232,13 +234,13 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { | |||
232 | // Should be fully available, because read_available >= ipc_header_size | 234 | // Should be fully available, because read_available >= ipc_header_size |
233 | ssize_t received = recv(client_fd, buf, ipc_header_size, 0); | 235 | ssize_t received = recv(client_fd, buf, ipc_header_size, 0); |
234 | if (received == -1) { | 236 | if (received == -1) { |
235 | wlr_log_errno(L_INFO, "Unable to receive header from IPC client"); | 237 | wlr_log_errno(WLR_INFO, "Unable to receive header from IPC client"); |
236 | ipc_client_disconnect(client); | 238 | ipc_client_disconnect(client); |
237 | return 0; | 239 | return 0; |
238 | } | 240 | } |
239 | 241 | ||
240 | if (memcmp(buf, ipc_magic, sizeof(ipc_magic)) != 0) { | 242 | if (memcmp(buf, ipc_magic, sizeof(ipc_magic)) != 0) { |
241 | wlr_log(L_DEBUG, "IPC header check failed"); | 243 | wlr_log(WLR_DEBUG, "IPC header check failed"); |
242 | ipc_client_disconnect(client); | 244 | ipc_client_disconnect(client); |
243 | return 0; | 245 | return 0; |
244 | } | 246 | } |
@@ -272,7 +274,7 @@ static void ipc_send_event(const char *json_string, enum ipc_command_type event) | |||
272 | } | 274 | } |
273 | client->current_command = event; | 275 | client->current_command = event; |
274 | if (!ipc_send_reply(client, json_string, (uint32_t) strlen(json_string))) { | 276 | if (!ipc_send_reply(client, json_string, (uint32_t) strlen(json_string))) { |
275 | wlr_log_errno(L_INFO, "Unable to send reply to IPC client"); | 277 | wlr_log_errno(WLR_INFO, "Unable to send reply to IPC client"); |
276 | /* ipc_send_reply destroys client on error, which also | 278 | /* ipc_send_reply destroys client on error, which also |
277 | * removes it from the list, so we need to process | 279 | * removes it from the list, so we need to process |
278 | * current index again */ | 280 | * current index again */ |
@@ -286,7 +288,7 @@ void ipc_event_workspace(struct sway_container *old, | |||
286 | if (!ipc_has_event_listeners(IPC_EVENT_WORKSPACE)) { | 288 | if (!ipc_has_event_listeners(IPC_EVENT_WORKSPACE)) { |
287 | return; | 289 | return; |
288 | } | 290 | } |
289 | wlr_log(L_DEBUG, "Sending workspace::%s event", change); | 291 | wlr_log(WLR_DEBUG, "Sending workspace::%s event", change); |
290 | json_object *obj = json_object_new_object(); | 292 | json_object *obj = json_object_new_object(); |
291 | json_object_object_add(obj, "change", json_object_new_string(change)); | 293 | json_object_object_add(obj, "change", json_object_new_string(change)); |
292 | if (strcmp("focus", change) == 0) { | 294 | if (strcmp("focus", change) == 0) { |
@@ -314,7 +316,7 @@ void ipc_event_window(struct sway_container *window, const char *change) { | |||
314 | if (!ipc_has_event_listeners(IPC_EVENT_WINDOW)) { | 316 | if (!ipc_has_event_listeners(IPC_EVENT_WINDOW)) { |
315 | return; | 317 | return; |
316 | } | 318 | } |
317 | wlr_log(L_DEBUG, "Sending window::%s event", change); | 319 | wlr_log(WLR_DEBUG, "Sending window::%s event", change); |
318 | json_object *obj = json_object_new_object(); | 320 | json_object *obj = json_object_new_object(); |
319 | json_object_object_add(obj, "change", json_object_new_string(change)); | 321 | json_object_object_add(obj, "change", json_object_new_string(change)); |
320 | json_object_object_add(obj, "container", ipc_json_describe_container_recursive(window)); | 322 | json_object_object_add(obj, "container", ipc_json_describe_container_recursive(window)); |
@@ -328,7 +330,7 @@ void ipc_event_barconfig_update(struct bar_config *bar) { | |||
328 | if (!ipc_has_event_listeners(IPC_EVENT_BARCONFIG_UPDATE)) { | 330 | if (!ipc_has_event_listeners(IPC_EVENT_BARCONFIG_UPDATE)) { |
329 | return; | 331 | return; |
330 | } | 332 | } |
331 | wlr_log(L_DEBUG, "Sending barconfig_update event"); | 333 | wlr_log(WLR_DEBUG, "Sending barconfig_update event"); |
332 | json_object *json = ipc_json_describe_bar_config(bar); | 334 | json_object *json = ipc_json_describe_bar_config(bar); |
333 | 335 | ||
334 | const char *json_string = json_object_to_json_string(json); | 336 | const char *json_string = json_object_to_json_string(json); |
@@ -340,7 +342,7 @@ void ipc_event_mode(const char *mode, bool pango) { | |||
340 | if (!ipc_has_event_listeners(IPC_EVENT_MODE)) { | 342 | if (!ipc_has_event_listeners(IPC_EVENT_MODE)) { |
341 | return; | 343 | return; |
342 | } | 344 | } |
343 | wlr_log(L_DEBUG, "Sending mode::%s event", mode); | 345 | wlr_log(WLR_DEBUG, "Sending mode::%s event", mode); |
344 | json_object *obj = json_object_new_object(); | 346 | json_object *obj = json_object_new_object(); |
345 | json_object_object_add(obj, "change", json_object_new_string(mode)); | 347 | json_object_object_add(obj, "change", json_object_new_string(mode)); |
346 | json_object_object_add(obj, "pango_markup", | 348 | json_object_object_add(obj, "pango_markup", |
@@ -355,13 +357,13 @@ int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { | |||
355 | struct ipc_client *client = data; | 357 | struct ipc_client *client = data; |
356 | 358 | ||
357 | if (mask & WL_EVENT_ERROR) { | 359 | if (mask & WL_EVENT_ERROR) { |
358 | wlr_log(L_ERROR, "IPC Client socket error, removing client"); | 360 | wlr_log(WLR_ERROR, "IPC Client socket error, removing client"); |
359 | ipc_client_disconnect(client); | 361 | ipc_client_disconnect(client); |
360 | return 0; | 362 | return 0; |
361 | } | 363 | } |
362 | 364 | ||
363 | if (mask & WL_EVENT_HANGUP) { | 365 | if (mask & WL_EVENT_HANGUP) { |
364 | wlr_log(L_DEBUG, "Client %d hung up", client->fd); | 366 | wlr_log(WLR_DEBUG, "Client %d hung up", client->fd); |
365 | ipc_client_disconnect(client); | 367 | ipc_client_disconnect(client); |
366 | return 0; | 368 | return 0; |
367 | } | 369 | } |
@@ -370,14 +372,14 @@ int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { | |||
370 | return 0; | 372 | return 0; |
371 | } | 373 | } |
372 | 374 | ||
373 | wlr_log(L_DEBUG, "Client %d writable", client->fd); | 375 | wlr_log(WLR_DEBUG, "Client %d writable", client->fd); |
374 | 376 | ||
375 | ssize_t written = write(client->fd, client->write_buffer, client->write_buffer_len); | 377 | ssize_t written = write(client->fd, client->write_buffer, client->write_buffer_len); |
376 | 378 | ||
377 | if (written == -1 && errno == EAGAIN) { | 379 | if (written == -1 && errno == EAGAIN) { |
378 | return 0; | 380 | return 0; |
379 | } else if (written == -1) { | 381 | } else if (written == -1) { |
380 | wlr_log_errno(L_INFO, "Unable to send data from queue to IPC client"); | 382 | wlr_log_errno(WLR_INFO, "Unable to send data from queue to IPC client"); |
381 | ipc_client_disconnect(client); | 383 | ipc_client_disconnect(client); |
382 | return 0; | 384 | return 0; |
383 | } | 385 | } |
@@ -400,7 +402,7 @@ void ipc_client_disconnect(struct ipc_client *client) { | |||
400 | 402 | ||
401 | shutdown(client->fd, SHUT_RDWR); | 403 | shutdown(client->fd, SHUT_RDWR); |
402 | 404 | ||
403 | wlr_log(L_INFO, "IPC Client %d disconnected", client->fd); | 405 | wlr_log(WLR_INFO, "IPC Client %d disconnected", client->fd); |
404 | wl_event_source_remove(client->event_source); | 406 | wl_event_source_remove(client->event_source); |
405 | if (client->writable_event_source) { | 407 | if (client->writable_event_source) { |
406 | wl_event_source_remove(client->writable_event_source); | 408 | wl_event_source_remove(client->writable_event_source); |
@@ -461,7 +463,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
461 | 463 | ||
462 | char *buf = malloc(client->payload_length + 1); | 464 | char *buf = malloc(client->payload_length + 1); |
463 | if (!buf) { | 465 | if (!buf) { |
464 | wlr_log_errno(L_INFO, "Unable to allocate IPC payload"); | 466 | wlr_log_errno(WLR_INFO, "Unable to allocate IPC payload"); |
465 | ipc_client_disconnect(client); | 467 | ipc_client_disconnect(client); |
466 | return; | 468 | return; |
467 | } | 469 | } |
@@ -470,7 +472,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
470 | ssize_t received = recv(client->fd, buf, client->payload_length, 0); | 472 | ssize_t received = recv(client->fd, buf, client->payload_length, 0); |
471 | if (received == -1) | 473 | if (received == -1) |
472 | { | 474 | { |
473 | wlr_log_errno(L_INFO, "Unable to receive payload from IPC client"); | 475 | wlr_log_errno(WLR_INFO, "Unable to receive payload from IPC client"); |
474 | ipc_client_disconnect(client); | 476 | ipc_client_disconnect(client); |
475 | free(buf); | 477 | free(buf); |
476 | return; | 478 | return; |
@@ -483,6 +485,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
483 | case IPC_COMMAND: | 485 | case IPC_COMMAND: |
484 | { | 486 | { |
485 | struct cmd_results *results = execute_command(buf, NULL); | 487 | struct cmd_results *results = execute_command(buf, NULL); |
488 | transaction_commit_dirty(); | ||
486 | char *json = cmd_results_to_json(results); | 489 | char *json = cmd_results_to_json(results); |
487 | int length = strlen(json); | 490 | int length = strlen(json); |
488 | client_valid = ipc_send_reply(client, json, (uint32_t)length); | 491 | client_valid = ipc_send_reply(client, json, (uint32_t)length); |
@@ -533,7 +536,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
533 | struct json_object *request = json_tokener_parse(buf); | 536 | struct json_object *request = json_tokener_parse(buf); |
534 | if (request == NULL) { | 537 | if (request == NULL) { |
535 | client_valid = ipc_send_reply(client, "{\"success\": false}", 18); | 538 | client_valid = ipc_send_reply(client, "{\"success\": false}", 18); |
536 | wlr_log_errno(L_INFO, "Failed to read request"); | 539 | wlr_log_errno(WLR_INFO, "Failed to read request"); |
537 | goto exit_cleanup; | 540 | goto exit_cleanup; |
538 | } | 541 | } |
539 | 542 | ||
@@ -556,7 +559,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
556 | client_valid = | 559 | client_valid = |
557 | ipc_send_reply(client, "{\"success\": false}", 18); | 560 | ipc_send_reply(client, "{\"success\": false}", 18); |
558 | json_object_put(request); | 561 | json_object_put(request); |
559 | wlr_log_errno(L_INFO, "Failed to parse request"); | 562 | wlr_log_errno(WLR_INFO, "Failed to parse request"); |
560 | goto exit_cleanup; | 563 | goto exit_cleanup; |
561 | } | 564 | } |
562 | } | 565 | } |
@@ -667,8 +670,33 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
667 | goto exit_cleanup; | 670 | goto exit_cleanup; |
668 | } | 671 | } |
669 | 672 | ||
673 | case IPC_GET_BINDING_MODES: | ||
674 | { | ||
675 | json_object *modes = json_object_new_array(); | ||
676 | for (int i = 0; i < config->modes->length; i++) { | ||
677 | struct sway_mode *mode = config->modes->items[i]; | ||
678 | json_object_array_add(modes, json_object_new_string(mode->name)); | ||
679 | } | ||
680 | const char *json_string = json_object_to_json_string(modes); | ||
681 | client_valid = | ||
682 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | ||
683 | json_object_put(modes); // free | ||
684 | goto exit_cleanup; | ||
685 | } | ||
686 | |||
687 | case IPC_GET_CONFIG: | ||
688 | { | ||
689 | json_object *json = json_object_new_object(); | ||
690 | json_object_object_add(json, "config", json_object_new_string(config->current_config)); | ||
691 | const char *json_string = json_object_to_json_string(json); | ||
692 | client_valid = | ||
693 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | ||
694 | json_object_put(json); // free | ||
695 | goto exit_cleanup; | ||
696 | } | ||
697 | |||
670 | default: | 698 | default: |
671 | wlr_log(L_INFO, "Unknown IPC command type %i", client->current_command); | 699 | wlr_log(WLR_INFO, "Unknown IPC command type %i", client->current_command); |
672 | goto exit_cleanup; | 700 | goto exit_cleanup; |
673 | } | 701 | } |
674 | 702 | ||
@@ -696,14 +724,14 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay | |||
696 | } | 724 | } |
697 | 725 | ||
698 | if (client->write_buffer_size > 4e6) { // 4 MB | 726 | if (client->write_buffer_size > 4e6) { // 4 MB |
699 | wlr_log(L_ERROR, "Client write buffer too big, disconnecting client"); | 727 | wlr_log(WLR_ERROR, "Client write buffer too big, disconnecting client"); |
700 | ipc_client_disconnect(client); | 728 | ipc_client_disconnect(client); |
701 | return false; | 729 | return false; |
702 | } | 730 | } |
703 | 731 | ||
704 | char *new_buffer = realloc(client->write_buffer, client->write_buffer_size); | 732 | char *new_buffer = realloc(client->write_buffer, client->write_buffer_size); |
705 | if (!new_buffer) { | 733 | if (!new_buffer) { |
706 | wlr_log(L_ERROR, "Unable to reallocate ipc client write buffer"); | 734 | wlr_log(WLR_ERROR, "Unable to reallocate ipc client write buffer"); |
707 | ipc_client_disconnect(client); | 735 | ipc_client_disconnect(client); |
708 | return false; | 736 | return false; |
709 | } | 737 | } |
@@ -720,6 +748,6 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay | |||
720 | ipc_client_handle_writable, client); | 748 | ipc_client_handle_writable, client); |
721 | } | 749 | } |
722 | 750 | ||
723 | wlr_log(L_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload); | 751 | wlr_log(WLR_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload); |
724 | return true; | 752 | return true; |
725 | } | 753 | } |
diff --git a/sway/main.c b/sway/main.c index ec7353be..1a55b519 100644 --- a/sway/main.c +++ b/sway/main.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "sway/commands.h" | 20 | #include "sway/commands.h" |
21 | #include "sway/config.h" | 21 | #include "sway/config.h" |
22 | #include "sway/debug.h" | 22 | #include "sway/debug.h" |
23 | #include "sway/desktop/transaction.h" | ||
23 | #include "sway/server.h" | 24 | #include "sway/server.h" |
24 | #include "sway/tree/layout.h" | 25 | #include "sway/tree/layout.h" |
25 | #include "sway/ipc-server.h" | 26 | #include "sway/ipc-server.h" |
@@ -129,7 +130,7 @@ static void log_env() { | |||
129 | "SWAYSOCK" | 130 | "SWAYSOCK" |
130 | }; | 131 | }; |
131 | for (size_t i = 0; i < sizeof(log_vars) / sizeof(char *); ++i) { | 132 | for (size_t i = 0; i < sizeof(log_vars) / sizeof(char *); ++i) { |
132 | wlr_log(L_INFO, "%s=%s", log_vars[i], getenv(log_vars[i])); | 133 | wlr_log(WLR_INFO, "%s=%s", log_vars[i], getenv(log_vars[i])); |
133 | } | 134 | } |
134 | } | 135 | } |
135 | 136 | ||
@@ -144,14 +145,14 @@ static void log_distro() { | |||
144 | for (size_t i = 0; i < sizeof(paths) / sizeof(char *); ++i) { | 145 | for (size_t i = 0; i < sizeof(paths) / sizeof(char *); ++i) { |
145 | FILE *f = fopen(paths[i], "r"); | 146 | FILE *f = fopen(paths[i], "r"); |
146 | if (f) { | 147 | if (f) { |
147 | wlr_log(L_INFO, "Contents of %s:", paths[i]); | 148 | wlr_log(WLR_INFO, "Contents of %s:", paths[i]); |
148 | while (!feof(f)) { | 149 | while (!feof(f)) { |
149 | char *line; | 150 | char *line; |
150 | if (!(line = read_line(f))) { | 151 | if (!(line = read_line(f))) { |
151 | break; | 152 | break; |
152 | } | 153 | } |
153 | if (*line) { | 154 | if (*line) { |
154 | wlr_log(L_INFO, "%s", line); | 155 | wlr_log(WLR_INFO, "%s", line); |
155 | } | 156 | } |
156 | free(line); | 157 | free(line); |
157 | } | 158 | } |
@@ -163,7 +164,7 @@ static void log_distro() { | |||
163 | static void log_kernel() { | 164 | static void log_kernel() { |
164 | FILE *f = popen("uname -a", "r"); | 165 | FILE *f = popen("uname -a", "r"); |
165 | if (!f) { | 166 | if (!f) { |
166 | wlr_log(L_INFO, "Unable to determine kernel version"); | 167 | wlr_log(WLR_INFO, "Unable to determine kernel version"); |
167 | return; | 168 | return; |
168 | } | 169 | } |
169 | while (!feof(f)) { | 170 | while (!feof(f)) { |
@@ -172,7 +173,7 @@ static void log_kernel() { | |||
172 | break; | 173 | break; |
173 | } | 174 | } |
174 | if (*line) { | 175 | if (*line) { |
175 | wlr_log(L_INFO, "%s", line); | 176 | wlr_log(WLR_INFO, "%s", line); |
176 | } | 177 | } |
177 | free(line); | 178 | free(line); |
178 | } | 179 | } |
@@ -183,14 +184,14 @@ static void security_sanity_check() { | |||
183 | // TODO: Notify users visually if this has issues | 184 | // TODO: Notify users visually if this has issues |
184 | struct stat s; | 185 | struct stat s; |
185 | if (stat("/proc", &s)) { | 186 | if (stat("/proc", &s)) { |
186 | wlr_log(L_ERROR, | 187 | wlr_log(WLR_ERROR, |
187 | "!! DANGER !! /proc is not available - sway CANNOT enforce security rules!"); | 188 | "!! DANGER !! /proc is not available - sway CANNOT enforce security rules!"); |
188 | } | 189 | } |
189 | #ifdef __linux__ | 190 | #ifdef __linux__ |
190 | cap_flag_value_t v; | 191 | cap_flag_value_t v; |
191 | cap_t cap = cap_get_proc(); | 192 | cap_t cap = cap_get_proc(); |
192 | if (!cap || cap_get_flag(cap, CAP_SYS_PTRACE, CAP_PERMITTED, &v) != 0 || v != CAP_SET) { | 193 | if (!cap || cap_get_flag(cap, CAP_SYS_PTRACE, CAP_PERMITTED, &v) != 0 || v != CAP_SET) { |
193 | wlr_log(L_ERROR, | 194 | wlr_log(WLR_ERROR, |
194 | "!! DANGER !! Sway does not have CAP_SYS_PTRACE and cannot enforce security rules for processes running as other users."); | 195 | "!! DANGER !! Sway does not have CAP_SYS_PTRACE and cannot enforce security rules for processes running as other users."); |
195 | } | 196 | } |
196 | if (cap) { | 197 | if (cap) { |
@@ -206,13 +207,13 @@ static void executable_sanity_check() { | |||
206 | stat(exe, &sb); | 207 | stat(exe, &sb); |
207 | // We assume that cap_get_file returning NULL implies ENODATA | 208 | // We assume that cap_get_file returning NULL implies ENODATA |
208 | if (sb.st_mode & (S_ISUID|S_ISGID) && cap_get_file(exe)) { | 209 | if (sb.st_mode & (S_ISUID|S_ISGID) && cap_get_file(exe)) { |
209 | wlr_log(L_ERROR, | 210 | wlr_log(WLR_ERROR, |
210 | "sway executable has both the s(g)uid bit AND file caps set."); | 211 | "sway executable has both the s(g)uid bit AND file caps set."); |
211 | wlr_log(L_ERROR, | 212 | wlr_log(WLR_ERROR, |
212 | "This is strongly discouraged (and completely broken)."); | 213 | "This is strongly discouraged (and completely broken)."); |
213 | wlr_log(L_ERROR, | 214 | wlr_log(WLR_ERROR, |
214 | "Please clear one of them (either the suid bit, or the file caps)."); | 215 | "Please clear one of them (either the suid bit, or the file caps)."); |
215 | wlr_log(L_ERROR, | 216 | wlr_log(WLR_ERROR, |
216 | "If unsure, strip the file caps."); | 217 | "If unsure, strip the file caps."); |
217 | exit(EXIT_FAILURE); | 218 | exit(EXIT_FAILURE); |
218 | } | 219 | } |
@@ -223,16 +224,16 @@ static void executable_sanity_check() { | |||
223 | static void drop_permissions(bool keep_caps) { | 224 | static void drop_permissions(bool keep_caps) { |
224 | if (getuid() != geteuid() || getgid() != getegid()) { | 225 | if (getuid() != geteuid() || getgid() != getegid()) { |
225 | if (setgid(getgid()) != 0) { | 226 | if (setgid(getgid()) != 0) { |
226 | wlr_log(L_ERROR, "Unable to drop root"); | 227 | wlr_log(WLR_ERROR, "Unable to drop root"); |
227 | exit(EXIT_FAILURE); | 228 | exit(EXIT_FAILURE); |
228 | } | 229 | } |
229 | if (setuid(getuid()) != 0) { | 230 | if (setuid(getuid()) != 0) { |
230 | wlr_log(L_ERROR, "Unable to drop root"); | 231 | wlr_log(WLR_ERROR, "Unable to drop root"); |
231 | exit(EXIT_FAILURE); | 232 | exit(EXIT_FAILURE); |
232 | } | 233 | } |
233 | } | 234 | } |
234 | if (setuid(0) != -1) { | 235 | if (setuid(0) != -1) { |
235 | wlr_log(L_ERROR, "Root privileges can be restored."); | 236 | wlr_log(WLR_ERROR, "Root privileges can be restored."); |
236 | exit(EXIT_FAILURE); | 237 | exit(EXIT_FAILURE); |
237 | } | 238 | } |
238 | #ifdef __linux__ | 239 | #ifdef __linux__ |
@@ -240,17 +241,29 @@ static void drop_permissions(bool keep_caps) { | |||
240 | // Drop every cap except CAP_SYS_PTRACE | 241 | // Drop every cap except CAP_SYS_PTRACE |
241 | cap_t caps = cap_init(); | 242 | cap_t caps = cap_init(); |
242 | cap_value_t keep = CAP_SYS_PTRACE; | 243 | cap_value_t keep = CAP_SYS_PTRACE; |
243 | wlr_log(L_INFO, "Dropping extra capabilities"); | 244 | wlr_log(WLR_INFO, "Dropping extra capabilities"); |
244 | if (cap_set_flag(caps, CAP_PERMITTED, 1, &keep, CAP_SET) || | 245 | if (cap_set_flag(caps, CAP_PERMITTED, 1, &keep, CAP_SET) || |
245 | cap_set_flag(caps, CAP_EFFECTIVE, 1, &keep, CAP_SET) || | 246 | cap_set_flag(caps, CAP_EFFECTIVE, 1, &keep, CAP_SET) || |
246 | cap_set_proc(caps)) { | 247 | cap_set_proc(caps)) { |
247 | wlr_log(L_ERROR, "Failed to drop extra capabilities"); | 248 | wlr_log(WLR_ERROR, "Failed to drop extra capabilities"); |
248 | exit(EXIT_FAILURE); | 249 | exit(EXIT_FAILURE); |
249 | } | 250 | } |
250 | } | 251 | } |
251 | #endif | 252 | #endif |
252 | } | 253 | } |
253 | 254 | ||
255 | void enable_debug_flag(const char *flag) { | ||
256 | if (strcmp(flag, "render-tree") == 0) { | ||
257 | enable_debug_tree = true; | ||
258 | } else if (strncmp(flag, "damage=", 7) == 0) { | ||
259 | damage_debug = &flag[7]; | ||
260 | } else if (strcmp(flag, "txn-debug") == 0) { | ||
261 | txn_debug = true; | ||
262 | } else if (strncmp(flag, "txn-timeout=", 12) == 0) { | ||
263 | txn_timeout_ms = atoi(&flag[12]); | ||
264 | } | ||
265 | } | ||
266 | |||
254 | int main(int argc, char **argv) { | 267 | int main(int argc, char **argv) { |
255 | static int verbose = 0, debug = 0, validate = 0; | 268 | static int verbose = 0, debug = 0, validate = 0; |
256 | 269 | ||
@@ -290,7 +303,7 @@ int main(int argc, char **argv) { | |||
290 | int c; | 303 | int c; |
291 | while (1) { | 304 | while (1) { |
292 | int option_index = 0; | 305 | int option_index = 0; |
293 | c = getopt_long(argc, argv, "hCdDvVc:", long_options, &option_index); | 306 | c = getopt_long(argc, argv, "hCdD:vVc:", long_options, &option_index); |
294 | if (c == -1) { | 307 | if (c == -1) { |
295 | break; | 308 | break; |
296 | } | 309 | } |
@@ -309,7 +322,7 @@ int main(int argc, char **argv) { | |||
309 | debug = 1; | 322 | debug = 1; |
310 | break; | 323 | break; |
311 | case 'D': // extended debug options | 324 | case 'D': // extended debug options |
312 | enable_debug_tree = true; | 325 | enable_debug_flag(optarg); |
313 | break; | 326 | break; |
314 | case 'v': // version | 327 | case 'v': // version |
315 | fprintf(stdout, "sway version " SWAY_VERSION "\n"); | 328 | fprintf(stdout, "sway version " SWAY_VERSION "\n"); |
@@ -335,22 +348,22 @@ int main(int argc, char **argv) { | |||
335 | 348 | ||
336 | // TODO: switch logging over to wlroots? | 349 | // TODO: switch logging over to wlroots? |
337 | if (debug) { | 350 | if (debug) { |
338 | wlr_log_init(L_DEBUG, NULL); | 351 | wlr_log_init(WLR_DEBUG, NULL); |
339 | } else if (verbose || validate) { | 352 | } else if (verbose || validate) { |
340 | wlr_log_init(L_INFO, NULL); | 353 | wlr_log_init(WLR_INFO, NULL); |
341 | } else { | 354 | } else { |
342 | wlr_log_init(L_ERROR, NULL); | 355 | wlr_log_init(WLR_ERROR, NULL); |
343 | } | 356 | } |
344 | 357 | ||
345 | if (optind < argc) { // Behave as IPC client | 358 | if (optind < argc) { // Behave as IPC client |
346 | if(optind != 1) { | 359 | if(optind != 1) { |
347 | wlr_log(L_ERROR, "Don't use options with the IPC client"); | 360 | wlr_log(WLR_ERROR, "Don't use options with the IPC client"); |
348 | exit(EXIT_FAILURE); | 361 | exit(EXIT_FAILURE); |
349 | } | 362 | } |
350 | drop_permissions(false); | 363 | drop_permissions(false); |
351 | char *socket_path = getenv("SWAYSOCK"); | 364 | char *socket_path = getenv("SWAYSOCK"); |
352 | if (!socket_path) { | 365 | if (!socket_path) { |
353 | wlr_log(L_ERROR, "Unable to retrieve socket path"); | 366 | wlr_log(WLR_ERROR, "Unable to retrieve socket path"); |
354 | exit(EXIT_FAILURE); | 367 | exit(EXIT_FAILURE); |
355 | } | 368 | } |
356 | char *command = join_args(argv + optind, argc - optind); | 369 | char *command = join_args(argv + optind, argc - optind); |
@@ -369,7 +382,7 @@ int main(int argc, char **argv) { | |||
369 | if (getuid() != geteuid() || getgid() != getegid()) { | 382 | if (getuid() != geteuid() || getgid() != getegid()) { |
370 | // Retain capabilities after setuid() | 383 | // Retain capabilities after setuid() |
371 | if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) { | 384 | if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) { |
372 | wlr_log(L_ERROR, "Cannot keep caps after setuid()"); | 385 | wlr_log(WLR_ERROR, "Cannot keep caps after setuid()"); |
373 | exit(EXIT_FAILURE); | 386 | exit(EXIT_FAILURE); |
374 | } | 387 | } |
375 | suid = true; | 388 | suid = true; |
@@ -390,7 +403,7 @@ int main(int argc, char **argv) { | |||
390 | // prevent ipc from crashing sway | 403 | // prevent ipc from crashing sway |
391 | signal(SIGPIPE, SIG_IGN); | 404 | signal(SIGPIPE, SIG_IGN); |
392 | 405 | ||
393 | wlr_log(L_INFO, "Starting sway version " SWAY_VERSION); | 406 | wlr_log(WLR_INFO, "Starting sway version " SWAY_VERSION); |
394 | 407 | ||
395 | layout_init(); | 408 | layout_init(); |
396 | 409 | ||
@@ -423,18 +436,19 @@ int main(int argc, char **argv) { | |||
423 | char *line = config->cmd_queue->items[0]; | 436 | char *line = config->cmd_queue->items[0]; |
424 | struct cmd_results *res = execute_command(line, NULL); | 437 | struct cmd_results *res = execute_command(line, NULL); |
425 | if (res->status != CMD_SUCCESS) { | 438 | if (res->status != CMD_SUCCESS) { |
426 | wlr_log(L_ERROR, "Error on line '%s': %s", line, res->error); | 439 | wlr_log(WLR_ERROR, "Error on line '%s': %s", line, res->error); |
427 | } | 440 | } |
428 | free_cmd_results(res); | 441 | free_cmd_results(res); |
429 | free(line); | 442 | free(line); |
430 | list_del(config->cmd_queue, 0); | 443 | list_del(config->cmd_queue, 0); |
431 | } | 444 | } |
445 | transaction_commit_dirty(); | ||
432 | 446 | ||
433 | if (!terminate_request) { | 447 | if (!terminate_request) { |
434 | server_run(&server); | 448 | server_run(&server); |
435 | } | 449 | } |
436 | 450 | ||
437 | wlr_log(L_INFO, "Shutting down sway"); | 451 | wlr_log(WLR_INFO, "Shutting down sway"); |
438 | 452 | ||
439 | server_fini(&server); | 453 | server_fini(&server); |
440 | 454 | ||
diff --git a/sway/meson.build b/sway/meson.build index e492aeee..c58d3470 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -35,11 +35,13 @@ sway_sources = files( | |||
35 | 'commands/border.c', | 35 | 'commands/border.c', |
36 | 'commands/client.c', | 36 | 'commands/client.c', |
37 | 'commands/default_border.c', | 37 | 'commands/default_border.c', |
38 | 'commands/default_floating_border.c', | ||
38 | 'commands/default_orientation.c', | 39 | 'commands/default_orientation.c', |
39 | 'commands/exit.c', | 40 | 'commands/exit.c', |
40 | 'commands/exec.c', | 41 | 'commands/exec.c', |
41 | 'commands/exec_always.c', | 42 | 'commands/exec_always.c', |
42 | 'commands/floating.c', | 43 | 'commands/floating.c', |
44 | 'commands/floating_minmax_size.c', | ||
43 | 'commands/focus.c', | 45 | 'commands/focus.c', |
44 | 'commands/focus_follows_mouse.c', | 46 | 'commands/focus_follows_mouse.c', |
45 | 'commands/focus_wrapping.c', | 47 | 'commands/focus_wrapping.c', |
@@ -58,6 +60,7 @@ sway_sources = files( | |||
58 | 'commands/mode.c', | 60 | 'commands/mode.c', |
59 | 'commands/mouse_warping.c', | 61 | 'commands/mouse_warping.c', |
60 | 'commands/move.c', | 62 | 'commands/move.c', |
63 | 'commands/no_focus.c', | ||
61 | 'commands/output.c', | 64 | 'commands/output.c', |
62 | 'commands/reload.c', | 65 | 'commands/reload.c', |
63 | 'commands/rename.c', | 66 | 'commands/rename.c', |
@@ -75,6 +78,7 @@ sway_sources = files( | |||
75 | 'commands/swap.c', | 78 | 'commands/swap.c', |
76 | 'commands/title_format.c', | 79 | 'commands/title_format.c', |
77 | 'commands/unmark.c', | 80 | 'commands/unmark.c', |
81 | 'commands/urgent.c', | ||
78 | 'commands/workspace.c', | 82 | 'commands/workspace.c', |
79 | 'commands/workspace_layout.c', | 83 | 'commands/workspace_layout.c', |
80 | 'commands/ws_auto_back_and_forth.c', | 84 | 'commands/ws_auto_back_and_forth.c', |
@@ -117,8 +121,10 @@ sway_sources = files( | |||
117 | 'commands/input/pointer_accel.c', | 121 | 'commands/input/pointer_accel.c', |
118 | 'commands/input/repeat_delay.c', | 122 | 'commands/input/repeat_delay.c', |
119 | 'commands/input/repeat_rate.c', | 123 | 'commands/input/repeat_rate.c', |
124 | 'commands/input/scroll_button.c', | ||
120 | 'commands/input/scroll_method.c', | 125 | 'commands/input/scroll_method.c', |
121 | 'commands/input/tap.c', | 126 | 'commands/input/tap.c', |
127 | 'commands/input/tap_button_map.c', | ||
122 | 'commands/input/xkb_layout.c', | 128 | 'commands/input/xkb_layout.c', |
123 | 'commands/input/xkb_model.c', | 129 | 'commands/input/xkb_model.c', |
124 | 'commands/input/xkb_options.c', | 130 | 'commands/input/xkb_options.c', |
diff --git a/sway/server.c b/sway/server.c index cd15f454..f904b177 100644 --- a/sway/server.c +++ b/sway/server.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <wlr/types/wlr_linux_dmabuf.h> | 14 | #include <wlr/types/wlr_linux_dmabuf.h> |
15 | #include <wlr/types/wlr_primary_selection.h> | 15 | #include <wlr/types/wlr_primary_selection.h> |
16 | #include <wlr/types/wlr_screencopy_v1.h> | 16 | #include <wlr/types/wlr_screencopy_v1.h> |
17 | #include <wlr/types/wlr_screenshooter.h> | ||
18 | #include <wlr/types/wlr_server_decoration.h> | 17 | #include <wlr/types/wlr_server_decoration.h> |
19 | #include <wlr/types/wlr_xcursor_manager.h> | 18 | #include <wlr/types/wlr_xcursor_manager.h> |
20 | #include <wlr/types/wlr_xdg_output.h> | 19 | #include <wlr/types/wlr_xdg_output.h> |
@@ -29,20 +28,20 @@ | |||
29 | #include "sway/xwayland.h" | 28 | #include "sway/xwayland.h" |
30 | 29 | ||
31 | bool server_privileged_prepare(struct sway_server *server) { | 30 | bool server_privileged_prepare(struct sway_server *server) { |
32 | wlr_log(L_DEBUG, "Preparing Wayland server initialization"); | 31 | wlr_log(WLR_DEBUG, "Preparing Wayland server initialization"); |
33 | server->wl_display = wl_display_create(); | 32 | server->wl_display = wl_display_create(); |
34 | server->wl_event_loop = wl_display_get_event_loop(server->wl_display); | 33 | server->wl_event_loop = wl_display_get_event_loop(server->wl_display); |
35 | server->backend = wlr_backend_autocreate(server->wl_display, NULL); | 34 | server->backend = wlr_backend_autocreate(server->wl_display, NULL); |
36 | 35 | ||
37 | if (!server->backend) { | 36 | if (!server->backend) { |
38 | wlr_log(L_ERROR, "Unable to create backend"); | 37 | wlr_log(WLR_ERROR, "Unable to create backend"); |
39 | return false; | 38 | return false; |
40 | } | 39 | } |
41 | return true; | 40 | return true; |
42 | } | 41 | } |
43 | 42 | ||
44 | bool server_init(struct sway_server *server) { | 43 | bool server_init(struct sway_server *server) { |
45 | wlr_log(L_DEBUG, "Initializing Wayland server"); | 44 | wlr_log(WLR_DEBUG, "Initializing Wayland server"); |
46 | 45 | ||
47 | struct wlr_renderer *renderer = wlr_backend_get_renderer(server->backend); | 46 | struct wlr_renderer *renderer = wlr_backend_get_renderer(server->backend); |
48 | assert(renderer); | 47 | assert(renderer); |
@@ -53,7 +52,6 @@ bool server_init(struct sway_server *server) { | |||
53 | server->data_device_manager = | 52 | server->data_device_manager = |
54 | wlr_data_device_manager_create(server->wl_display); | 53 | wlr_data_device_manager_create(server->wl_display); |
55 | 54 | ||
56 | wlr_screenshooter_create(server->wl_display); | ||
57 | wlr_gamma_control_manager_create(server->wl_display); | 55 | wlr_gamma_control_manager_create(server->wl_display); |
58 | wlr_primary_selection_device_manager_create(server->wl_display); | 56 | wlr_primary_selection_device_manager_create(server->wl_display); |
59 | 57 | ||
@@ -116,7 +114,7 @@ bool server_init(struct sway_server *server) { | |||
116 | 114 | ||
117 | server->socket = wl_display_add_socket_auto(server->wl_display); | 115 | server->socket = wl_display_add_socket_auto(server->wl_display); |
118 | if (!server->socket) { | 116 | if (!server->socket) { |
119 | wlr_log(L_ERROR, "Unable to open wayland socket"); | 117 | wlr_log(WLR_ERROR, "Unable to open wayland socket"); |
120 | wlr_backend_destroy(server->backend); | 118 | wlr_backend_destroy(server->backend); |
121 | return false; | 119 | return false; |
122 | } | 120 | } |
@@ -125,8 +123,7 @@ bool server_init(struct sway_server *server) { | |||
125 | if (debug != NULL && strcmp(debug, "txn_timings") == 0) { | 123 | if (debug != NULL && strcmp(debug, "txn_timings") == 0) { |
126 | server->debug_txn_timings = true; | 124 | server->debug_txn_timings = true; |
127 | } | 125 | } |
128 | server->destroying_containers = create_list(); | 126 | server->dirty_containers = create_list(); |
129 | |||
130 | server->transactions = create_list(); | 127 | server->transactions = create_list(); |
131 | 128 | ||
132 | input_manager = input_manager_create(server); | 129 | input_manager = input_manager_create(server); |
@@ -136,15 +133,15 @@ bool server_init(struct sway_server *server) { | |||
136 | void server_fini(struct sway_server *server) { | 133 | void server_fini(struct sway_server *server) { |
137 | // TODO: free sway-specific resources | 134 | // TODO: free sway-specific resources |
138 | wl_display_destroy(server->wl_display); | 135 | wl_display_destroy(server->wl_display); |
139 | list_free(server->destroying_containers); | 136 | list_free(server->dirty_containers); |
140 | list_free(server->transactions); | 137 | list_free(server->transactions); |
141 | } | 138 | } |
142 | 139 | ||
143 | void server_run(struct sway_server *server) { | 140 | void server_run(struct sway_server *server) { |
144 | wlr_log(L_INFO, "Running compositor on wayland display '%s'", | 141 | wlr_log(WLR_INFO, "Running compositor on wayland display '%s'", |
145 | server->socket); | 142 | server->socket); |
146 | if (!wlr_backend_start(server->backend)) { | 143 | if (!wlr_backend_start(server->backend)) { |
147 | wlr_log(L_ERROR, "Failed to start backend"); | 144 | wlr_log(WLR_ERROR, "Failed to start backend"); |
148 | wlr_backend_destroy(server->backend); | 145 | wlr_backend_destroy(server->backend); |
149 | return; | 146 | return; |
150 | } | 147 | } |
diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index cf7a6385..b6391431 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd | |||
@@ -92,9 +92,20 @@ For more information on these xkb configuration options, see | |||
92 | *input* <identifier> scroll\_method none|two\_finger|edge|on\_button\_down | 92 | *input* <identifier> scroll\_method none|two\_finger|edge|on\_button\_down |
93 | Changes the scroll method for the specified input device. | 93 | Changes the scroll method for the specified input device. |
94 | 94 | ||
95 | *input* <identifier> scroll\_button <button\_identifier> | ||
96 | Sets button used for scroll\_method on\_button\_down. The button identifier | ||
97 | can be obtained from `libinput debug-events`. | ||
98 | If set to 0, it disables the scroll\_button on\_button\_down. | ||
99 | |||
95 | *input* <identifier> tap enabled|disabled | 100 | *input* <identifier> tap enabled|disabled |
96 | Enables or disables tap for specified input device. | 101 | Enables or disables tap for specified input device. |
97 | 102 | ||
103 | *input* <identifier> tap_button_map lrm|lmr | ||
104 | Specifies which button mapping to use for tapping. _lrm_ treats 1 finger as | ||
105 | left click, 2 fingers as right click, and 3 fingers as middle click. _lmr_ | ||
106 | treats 1 finger as left click, 2 fingers as middle click, and 3 fingers as | ||
107 | right click. | ||
108 | |||
98 | ## SEAT CONFIGURATION | 109 | ## SEAT CONFIGURATION |
99 | 110 | ||
100 | Configure options for multiseat mode. sway-seat commands must be used inside a | 111 | Configure options for multiseat mode. sway-seat commands must be used inside a |
diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 7c553d3f..d369d7b6 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd | |||
@@ -92,6 +92,12 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1). | |||
92 | *focus* output <name> | 92 | *focus* output <name> |
93 | Moves focus to the named output. | 93 | Moves focus to the named output. |
94 | 94 | ||
95 | *focus tiling* | ||
96 | Sets focus to the last focused tiling container. | ||
97 | |||
98 | *focus floating* | ||
99 | Sets focus to the last focused floating container. | ||
100 | |||
95 | *focus* mode\_toggle | 101 | *focus* mode\_toggle |
96 | Moves focus between the floating and tiled layers. | 102 | Moves focus between the floating and tiled layers. |
97 | 103 | ||
@@ -493,6 +499,11 @@ config after the others, or it will be matched instead of the others. | |||
493 | *unmark* will remove _identifier_ from the list of current marks on a | 499 | *unmark* will remove _identifier_ from the list of current marks on a |
494 | window. If _identifier_ is omitted, all marks are removed. | 500 | window. If _identifier_ is omitted, all marks are removed. |
495 | 501 | ||
502 | *urgent* enable|disable|allow|deny | ||
503 | Using _enable_ or _disable_ manually sets or unsets the window's urgent | ||
504 | state. Using _allow_ or _deny_ controls the window's ability to set itself | ||
505 | as urgent. By default, windows are allowed to set their own urgency. | ||
506 | |||
496 | *workspace* [number] <name> | 507 | *workspace* [number] <name> |
497 | Switches to the specified workspace. The string "number" is optional and is | 508 | Switches to the specified workspace. The string "number" is optional and is |
498 | used to sort workspaces. | 509 | used to sort workspaces. |
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c index 582b2891..533cf71c 100644 --- a/sway/tree/arrange.c +++ b/sway/tree/arrange.c | |||
@@ -47,11 +47,11 @@ static void apply_horiz_layout(struct sway_container *parent) { | |||
47 | double scale = parent->width / total_width; | 47 | double scale = parent->width / total_width; |
48 | 48 | ||
49 | // Resize windows | 49 | // Resize windows |
50 | wlr_log(L_DEBUG, "Arranging %p horizontally", parent); | 50 | wlr_log(WLR_DEBUG, "Arranging %p horizontally", parent); |
51 | double child_x = parent->x; | 51 | double child_x = parent->x; |
52 | for (size_t i = 0; i < num_children; ++i) { | 52 | for (size_t i = 0; i < num_children; ++i) { |
53 | struct sway_container *child = parent->children->items[i]; | 53 | struct sway_container *child = parent->children->items[i]; |
54 | wlr_log(L_DEBUG, | 54 | wlr_log(WLR_DEBUG, |
55 | "Calculating arrangement for %p:%d (will scale %f by %f)", | 55 | "Calculating arrangement for %p:%d (will scale %f by %f)", |
56 | child, child->type, child->width, scale); | 56 | child, child->type, child->width, scale); |
57 | child->x = child_x; | 57 | child->x = child_x; |
@@ -99,11 +99,11 @@ static void apply_vert_layout(struct sway_container *parent) { | |||
99 | double scale = parent_height / total_height; | 99 | double scale = parent_height / total_height; |
100 | 100 | ||
101 | // Resize | 101 | // Resize |
102 | wlr_log(L_DEBUG, "Arranging %p vertically", parent); | 102 | wlr_log(WLR_DEBUG, "Arranging %p vertically", parent); |
103 | double child_y = parent->y + parent_offset; | 103 | double child_y = parent->y + parent_offset; |
104 | for (size_t i = 0; i < num_children; ++i) { | 104 | for (size_t i = 0; i < num_children; ++i) { |
105 | struct sway_container *child = parent->children->items[i]; | 105 | struct sway_container *child = parent->children->items[i]; |
106 | wlr_log(L_DEBUG, | 106 | wlr_log(WLR_DEBUG, |
107 | "Calculating arrangement for %p:%d (will scale %f by %f)", | 107 | "Calculating arrangement for %p:%d (will scale %f by %f)", |
108 | child, child->type, child->height, scale); | 108 | child, child->type, child->height, scale); |
109 | child->x = parent->x; | 109 | child->x = parent->x; |
@@ -144,42 +144,26 @@ static void apply_tabbed_or_stacked_layout(struct sway_container *parent) { | |||
144 | } | 144 | } |
145 | } | 145 | } |
146 | 146 | ||
147 | /** | 147 | static void arrange_children_of(struct sway_container *parent); |
148 | * If a container has been deleted from the pending tree state, we must add it | ||
149 | * to the transaction so it can be freed afterwards. To do this, we iterate the | ||
150 | * server's destroying_containers list and add all of them. We may add more than | ||
151 | * what we need to, but this is easy and has no negative consequences. | ||
152 | */ | ||
153 | static void add_deleted_containers(struct sway_transaction *transaction) { | ||
154 | for (int i = 0; i < server.destroying_containers->length; ++i) { | ||
155 | struct sway_container *child = server.destroying_containers->items[i]; | ||
156 | transaction_add_container(transaction, child); | ||
157 | } | ||
158 | } | ||
159 | |||
160 | static void arrange_children_of(struct sway_container *parent, | ||
161 | struct sway_transaction *transaction); | ||
162 | 148 | ||
163 | static void arrange_floating(struct sway_container *floating, | 149 | static void arrange_floating(struct sway_container *floating) { |
164 | struct sway_transaction *transaction) { | ||
165 | for (int i = 0; i < floating->children->length; ++i) { | 150 | for (int i = 0; i < floating->children->length; ++i) { |
166 | struct sway_container *floater = floating->children->items[i]; | 151 | struct sway_container *floater = floating->children->items[i]; |
167 | if (floater->type == C_VIEW) { | 152 | if (floater->type == C_VIEW) { |
168 | view_autoconfigure(floater->sway_view); | 153 | view_autoconfigure(floater->sway_view); |
169 | } else { | 154 | } else { |
170 | arrange_children_of(floater, transaction); | 155 | arrange_children_of(floater); |
171 | } | 156 | } |
172 | transaction_add_container(transaction, floater); | 157 | container_set_dirty(floater); |
173 | } | 158 | } |
174 | transaction_add_container(transaction, floating); | 159 | container_set_dirty(floating); |
175 | } | 160 | } |
176 | 161 | ||
177 | static void arrange_children_of(struct sway_container *parent, | 162 | static void arrange_children_of(struct sway_container *parent) { |
178 | struct sway_transaction *transaction) { | ||
179 | if (config->reloading) { | 163 | if (config->reloading) { |
180 | return; | 164 | return; |
181 | } | 165 | } |
182 | wlr_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", parent, | 166 | wlr_log(WLR_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", parent, |
183 | parent->name, parent->width, parent->height, parent->x, parent->y); | 167 | parent->name, parent->width, parent->height, parent->x, parent->y); |
184 | 168 | ||
185 | // Calculate x, y, width and height of children | 169 | // Calculate x, y, width and height of children |
@@ -198,7 +182,7 @@ static void arrange_children_of(struct sway_container *parent, | |||
198 | apply_horiz_layout(parent); | 182 | apply_horiz_layout(parent); |
199 | break; | 183 | break; |
200 | case L_FLOATING: | 184 | case L_FLOATING: |
201 | arrange_floating(parent, transaction); | 185 | arrange_floating(parent); |
202 | break; | 186 | break; |
203 | } | 187 | } |
204 | 188 | ||
@@ -213,20 +197,19 @@ static void arrange_children_of(struct sway_container *parent, | |||
213 | if (child->type == C_VIEW) { | 197 | if (child->type == C_VIEW) { |
214 | view_autoconfigure(child->sway_view); | 198 | view_autoconfigure(child->sway_view); |
215 | } else { | 199 | } else { |
216 | arrange_children_of(child, transaction); | 200 | arrange_children_of(child); |
217 | } | 201 | } |
218 | transaction_add_container(transaction, child); | 202 | container_set_dirty(child); |
219 | } | 203 | } |
220 | } | 204 | } |
221 | 205 | ||
222 | static void arrange_workspace(struct sway_container *workspace, | 206 | static void arrange_workspace(struct sway_container *workspace) { |
223 | struct sway_transaction *transaction) { | ||
224 | if (config->reloading) { | 207 | if (config->reloading) { |
225 | return; | 208 | return; |
226 | } | 209 | } |
227 | struct sway_container *output = workspace->parent; | 210 | struct sway_container *output = workspace->parent; |
228 | struct wlr_box *area = &output->sway_output->usable_area; | 211 | struct wlr_box *area = &output->sway_output->usable_area; |
229 | wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d", | 212 | wlr_log(WLR_DEBUG, "Usable area for ws: %dx%d@%d,%d", |
230 | area->width, area->height, area->x, area->y); | 213 | area->width, area->height, area->x, area->y); |
231 | remove_gaps(workspace); | 214 | remove_gaps(workspace); |
232 | workspace->width = area->width; | 215 | workspace->width = area->width; |
@@ -234,15 +217,14 @@ static void arrange_workspace(struct sway_container *workspace, | |||
234 | workspace->x = output->x + area->x; | 217 | workspace->x = output->x + area->x; |
235 | workspace->y = output->y + area->y; | 218 | workspace->y = output->y + area->y; |
236 | add_gaps(workspace); | 219 | add_gaps(workspace); |
237 | transaction_add_container(transaction, workspace); | 220 | container_set_dirty(workspace); |
238 | wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", workspace->name, | 221 | wlr_log(WLR_DEBUG, "Arranging workspace '%s' at %f, %f", workspace->name, |
239 | workspace->x, workspace->y); | 222 | workspace->x, workspace->y); |
240 | arrange_floating(workspace->sway_workspace->floating, transaction); | 223 | arrange_floating(workspace->sway_workspace->floating); |
241 | arrange_children_of(workspace, transaction); | 224 | arrange_children_of(workspace); |
242 | } | 225 | } |
243 | 226 | ||
244 | static void arrange_output(struct sway_container *output, | 227 | static void arrange_output(struct sway_container *output) { |
245 | struct sway_transaction *transaction) { | ||
246 | if (config->reloading) { | 228 | if (config->reloading) { |
247 | return; | 229 | return; |
248 | } | 230 | } |
@@ -253,16 +235,16 @@ static void arrange_output(struct sway_container *output, | |||
253 | output->y = output_box->y; | 235 | output->y = output_box->y; |
254 | output->width = output_box->width; | 236 | output->width = output_box->width; |
255 | output->height = output_box->height; | 237 | output->height = output_box->height; |
256 | transaction_add_container(transaction, output); | 238 | container_set_dirty(output); |
257 | wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f", | 239 | wlr_log(WLR_DEBUG, "Arranging output '%s' at %f,%f", |
258 | output->name, output->x, output->y); | 240 | output->name, output->x, output->y); |
259 | for (int i = 0; i < output->children->length; ++i) { | 241 | for (int i = 0; i < output->children->length; ++i) { |
260 | struct sway_container *workspace = output->children->items[i]; | 242 | struct sway_container *workspace = output->children->items[i]; |
261 | arrange_workspace(workspace, transaction); | 243 | arrange_workspace(workspace); |
262 | } | 244 | } |
263 | } | 245 | } |
264 | 246 | ||
265 | static void arrange_root(struct sway_transaction *transaction) { | 247 | static void arrange_root() { |
266 | if (config->reloading) { | 248 | if (config->reloading) { |
267 | return; | 249 | return; |
268 | } | 250 | } |
@@ -274,48 +256,40 @@ static void arrange_root(struct sway_transaction *transaction) { | |||
274 | root_container.y = layout_box->y; | 256 | root_container.y = layout_box->y; |
275 | root_container.width = layout_box->width; | 257 | root_container.width = layout_box->width; |
276 | root_container.height = layout_box->height; | 258 | root_container.height = layout_box->height; |
277 | transaction_add_container(transaction, &root_container); | 259 | container_set_dirty(&root_container); |
278 | for (int i = 0; i < root_container.children->length; ++i) { | 260 | for (int i = 0; i < root_container.children->length; ++i) { |
279 | struct sway_container *output = root_container.children->items[i]; | 261 | struct sway_container *output = root_container.children->items[i]; |
280 | arrange_output(output, transaction); | 262 | arrange_output(output); |
281 | } | 263 | } |
282 | } | 264 | } |
283 | 265 | ||
284 | void arrange_windows(struct sway_container *container, | 266 | void arrange_windows(struct sway_container *container) { |
285 | struct sway_transaction *transaction) { | ||
286 | switch (container->type) { | 267 | switch (container->type) { |
287 | case C_ROOT: | 268 | case C_ROOT: |
288 | arrange_root(transaction); | 269 | arrange_root(); |
289 | break; | 270 | break; |
290 | case C_OUTPUT: | 271 | case C_OUTPUT: |
291 | arrange_output(container, transaction); | 272 | arrange_output(container); |
292 | break; | 273 | break; |
293 | case C_WORKSPACE: | 274 | case C_WORKSPACE: |
294 | arrange_workspace(container, transaction); | 275 | arrange_workspace(container); |
295 | break; | 276 | break; |
296 | case C_CONTAINER: | 277 | case C_CONTAINER: |
297 | arrange_children_of(container, transaction); | 278 | arrange_children_of(container); |
298 | transaction_add_container(transaction, container); | 279 | container_set_dirty(container); |
299 | break; | 280 | break; |
300 | case C_VIEW: | 281 | case C_VIEW: |
301 | view_autoconfigure(container->sway_view); | 282 | view_autoconfigure(container->sway_view); |
302 | transaction_add_container(transaction, container); | 283 | container_set_dirty(container); |
303 | break; | 284 | break; |
304 | case C_TYPES: | 285 | case C_TYPES: |
305 | break; | 286 | break; |
306 | } | 287 | } |
307 | add_deleted_containers(transaction); | ||
308 | } | ||
309 | |||
310 | void arrange_and_commit(struct sway_container *container) { | ||
311 | struct sway_transaction *transaction = transaction_create(); | ||
312 | arrange_windows(container, transaction); | ||
313 | transaction_commit(transaction); | ||
314 | } | 288 | } |
315 | 289 | ||
316 | void remove_gaps(struct sway_container *c) { | 290 | void remove_gaps(struct sway_container *c) { |
317 | if (c->current_gaps == 0) { | 291 | if (c->current_gaps == 0) { |
318 | wlr_log(L_DEBUG, "Removing gaps: not gapped: %p", c); | 292 | wlr_log(WLR_DEBUG, "Removing gaps: not gapped: %p", c); |
319 | return; | 293 | return; |
320 | } | 294 | } |
321 | 295 | ||
@@ -326,12 +300,12 @@ void remove_gaps(struct sway_container *c) { | |||
326 | 300 | ||
327 | c->current_gaps = 0; | 301 | c->current_gaps = 0; |
328 | 302 | ||
329 | wlr_log(L_DEBUG, "Removing gaps %p", c); | 303 | wlr_log(WLR_DEBUG, "Removing gaps %p", c); |
330 | } | 304 | } |
331 | 305 | ||
332 | void add_gaps(struct sway_container *c) { | 306 | void add_gaps(struct sway_container *c) { |
333 | if (c->current_gaps > 0 || c->type == C_CONTAINER) { | 307 | if (c->current_gaps > 0 || c->type == C_CONTAINER) { |
334 | wlr_log(L_DEBUG, "Not adding gaps: %p", c); | 308 | wlr_log(WLR_DEBUG, "Not adding gaps: %p", c); |
335 | return; | 309 | return; |
336 | } | 310 | } |
337 | 311 | ||
@@ -348,5 +322,5 @@ void add_gaps(struct sway_container *c) { | |||
348 | c->height -= 2 * gaps; | 322 | c->height -= 2 * gaps; |
349 | c->current_gaps = gaps; | 323 | c->current_gaps = gaps; |
350 | 324 | ||
351 | wlr_log(L_DEBUG, "Adding gaps: %p", c); | 325 | wlr_log(WLR_DEBUG, "Adding gaps: %p", c); |
352 | } | 326 | } |
diff --git a/sway/tree/container.c b/sway/tree/container.c index 7cea43fa..02384199 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -11,11 +11,14 @@ | |||
11 | #include "cairo.h" | 11 | #include "cairo.h" |
12 | #include "pango.h" | 12 | #include "pango.h" |
13 | #include "sway/config.h" | 13 | #include "sway/config.h" |
14 | #include "sway/desktop.h" | ||
15 | #include "sway/desktop/transaction.h" | ||
14 | #include "sway/input/input-manager.h" | 16 | #include "sway/input/input-manager.h" |
15 | #include "sway/input/seat.h" | 17 | #include "sway/input/seat.h" |
16 | #include "sway/ipc-server.h" | 18 | #include "sway/ipc-server.h" |
17 | #include "sway/output.h" | 19 | #include "sway/output.h" |
18 | #include "sway/server.h" | 20 | #include "sway/server.h" |
21 | #include "sway/tree/arrange.h" | ||
19 | #include "sway/tree/layout.h" | 22 | #include "sway/tree/layout.h" |
20 | #include "sway/tree/view.h" | 23 | #include "sway/tree/view.h" |
21 | #include "sway/tree/workspace.h" | 24 | #include "sway/tree/workspace.h" |
@@ -28,7 +31,7 @@ static list_t *get_bfs_queue() { | |||
28 | if (!bfs_queue) { | 31 | if (!bfs_queue) { |
29 | bfs_queue = create_list(); | 32 | bfs_queue = create_list(); |
30 | if (!bfs_queue) { | 33 | if (!bfs_queue) { |
31 | wlr_log(L_ERROR, "could not allocate list for bfs queue"); | 34 | wlr_log(WLR_ERROR, "could not allocate list for bfs queue"); |
32 | return NULL; | 35 | return NULL; |
33 | } | 36 | } |
34 | } | 37 | } |
@@ -156,14 +159,6 @@ void container_free(struct sway_container *cont) { | |||
156 | wlr_texture_destroy(cont->title_focused_inactive); | 159 | wlr_texture_destroy(cont->title_focused_inactive); |
157 | wlr_texture_destroy(cont->title_unfocused); | 160 | wlr_texture_destroy(cont->title_unfocused); |
158 | wlr_texture_destroy(cont->title_urgent); | 161 | wlr_texture_destroy(cont->title_urgent); |
159 | |||
160 | for (int i = 0; i < server.destroying_containers->length; ++i) { | ||
161 | if (server.destroying_containers->items[i] == cont) { | ||
162 | list_del(server.destroying_containers, i); | ||
163 | break; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | list_free(cont->instructions); | 162 | list_free(cont->instructions); |
168 | list_free(cont->children); | 163 | list_free(cont->children); |
169 | list_free(cont->current.children); | 164 | list_free(cont->current.children); |
@@ -218,7 +213,7 @@ static struct sway_container *container_workspace_destroy( | |||
218 | return NULL; | 213 | return NULL; |
219 | } | 214 | } |
220 | 215 | ||
221 | wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); | 216 | wlr_log(WLR_DEBUG, "destroying workspace '%s'", workspace->name); |
222 | 217 | ||
223 | if (!workspace_is_empty(workspace)) { | 218 | if (!workspace_is_empty(workspace)) { |
224 | // Move children to a different workspace on this output | 219 | // Move children to a different workspace on this output |
@@ -230,7 +225,7 @@ static struct sway_container *container_workspace_destroy( | |||
230 | } | 225 | } |
231 | } | 226 | } |
232 | 227 | ||
233 | wlr_log(L_DEBUG, "moving children to different workspace '%s' -> '%s'", | 228 | wlr_log(WLR_DEBUG, "moving children to different workspace '%s' -> '%s'", |
234 | workspace->name, new_workspace->name); | 229 | workspace->name, new_workspace->name); |
235 | for (int i = 0; i < workspace->children->length; i++) { | 230 | for (int i = 0; i < workspace->children->length; i++) { |
236 | container_move_to(workspace->children->items[i], new_workspace); | 231 | container_move_to(workspace->children->items[i], new_workspace); |
@@ -296,7 +291,7 @@ static struct sway_container *container_output_destroy( | |||
296 | output->sway_output->swayc = NULL; | 291 | output->sway_output->swayc = NULL; |
297 | output->sway_output = NULL; | 292 | output->sway_output = NULL; |
298 | 293 | ||
299 | wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); | 294 | wlr_log(WLR_DEBUG, "OUTPUT: Destroying output '%s'", output->name); |
300 | 295 | ||
301 | return &root_container; | 296 | return &root_container; |
302 | } | 297 | } |
@@ -323,13 +318,13 @@ static struct sway_container *container_destroy_noreaping( | |||
323 | // Workspaces will refuse to be destroyed if they're the last workspace | 318 | // Workspaces will refuse to be destroyed if they're the last workspace |
324 | // on their output. | 319 | // on their output. |
325 | if (!container_workspace_destroy(con)) { | 320 | if (!container_workspace_destroy(con)) { |
326 | wlr_log(L_ERROR, "workspace doesn't want to destroy"); | 321 | wlr_log(WLR_ERROR, "workspace doesn't want to destroy"); |
327 | return NULL; | 322 | return NULL; |
328 | } | 323 | } |
329 | } | 324 | } |
330 | 325 | ||
331 | con->destroying = true; | 326 | con->destroying = true; |
332 | list_add(server.destroying_containers, con); | 327 | container_set_dirty(con); |
333 | 328 | ||
334 | if (!con->parent) { | 329 | if (!con->parent) { |
335 | return NULL; | 330 | return NULL; |
@@ -350,7 +345,7 @@ bool container_reap_empty(struct sway_container *con) { | |||
350 | break; | 345 | break; |
351 | case C_WORKSPACE: | 346 | case C_WORKSPACE: |
352 | if (!workspace_is_visible(con) && workspace_is_empty(con)) { | 347 | if (!workspace_is_visible(con) && workspace_is_empty(con)) { |
353 | wlr_log(L_DEBUG, "Destroying workspace via reaper"); | 348 | wlr_log(WLR_DEBUG, "Destroying workspace via reaper"); |
354 | container_destroy_noreaping(con); | 349 | container_destroy_noreaping(con); |
355 | return true; | 350 | return true; |
356 | } | 351 | } |
@@ -443,7 +438,7 @@ struct sway_container *container_view_create(struct sway_container *sibling, | |||
443 | } | 438 | } |
444 | const char *title = view_get_title(sway_view); | 439 | const char *title = view_get_title(sway_view); |
445 | struct sway_container *swayc = container_create(C_VIEW); | 440 | struct sway_container *swayc = container_create(C_VIEW); |
446 | wlr_log(L_DEBUG, "Adding new view %p:%s to container %p %d %s", | 441 | wlr_log(WLR_DEBUG, "Adding new view %p:%s to container %p %d %s", |
447 | swayc, title, sibling, sibling ? sibling->type : 0, sibling->name); | 442 | swayc, title, sibling, sibling ? sibling->type : 0, sibling->name); |
448 | // Setup values | 443 | // Setup values |
449 | swayc->sway_view = sway_view; | 444 | swayc->sway_view = sway_view; |
@@ -686,16 +681,23 @@ struct sway_container *floating_container_at(double lx, double ly, | |||
686 | void container_for_each_descendant_dfs(struct sway_container *container, | 681 | void container_for_each_descendant_dfs(struct sway_container *container, |
687 | void (*f)(struct sway_container *container, void *data), | 682 | void (*f)(struct sway_container *container, void *data), |
688 | void *data) { | 683 | void *data) { |
689 | if (container) { | 684 | if (!container) { |
690 | if (container->children) { | 685 | return; |
691 | for (int i = 0; i < container->children->length; ++i) { | 686 | } |
692 | struct sway_container *child = | 687 | if (container->children) { |
693 | container->children->items[i]; | 688 | for (int i = 0; i < container->children->length; ++i) { |
694 | container_for_each_descendant_dfs(child, f, data); | 689 | struct sway_container *child = container->children->items[i]; |
695 | } | 690 | container_for_each_descendant_dfs(child, f, data); |
691 | } | ||
692 | } | ||
693 | if (container->type == C_WORKSPACE) { | ||
694 | struct sway_container *floating = container->sway_workspace->floating; | ||
695 | for (int i = 0; i < floating->children->length; ++i) { | ||
696 | struct sway_container *child = floating->children->items[i]; | ||
697 | container_for_each_descendant_dfs(child, f, data); | ||
696 | } | 698 | } |
697 | f(container, data); | ||
698 | } | 699 | } |
700 | f(container, data); | ||
699 | } | 701 | } |
700 | 702 | ||
701 | void container_for_each_descendant_bfs(struct sway_container *con, | 703 | void container_for_each_descendant_bfs(struct sway_container *con, |
@@ -706,7 +708,7 @@ void container_for_each_descendant_bfs(struct sway_container *con, | |||
706 | } | 708 | } |
707 | 709 | ||
708 | if (queue == NULL) { | 710 | if (queue == NULL) { |
709 | wlr_log(L_ERROR, "could not allocate list"); | 711 | wlr_log(WLR_ERROR, "could not allocate list"); |
710 | return; | 712 | return; |
711 | } | 713 | } |
712 | 714 | ||
@@ -972,9 +974,14 @@ void container_set_geometry_from_floating_view(struct sway_container *con) { | |||
972 | return; | 974 | return; |
973 | } | 975 | } |
974 | struct sway_view *view = con->sway_view; | 976 | struct sway_view *view = con->sway_view; |
975 | size_t border_width = view->border_thickness * (view->border != B_NONE); | 977 | size_t border_width = 0; |
976 | size_t top = | 978 | size_t top = 0; |
977 | view->border == B_NORMAL ? container_titlebar_height() : border_width; | 979 | |
980 | if (!view->using_csd) { | ||
981 | border_width = view->border_thickness * (view->border != B_NONE); | ||
982 | top = view->border == B_NORMAL ? | ||
983 | container_titlebar_height() : border_width; | ||
984 | } | ||
978 | 985 | ||
979 | con->x = view->x - border_width; | 986 | con->x = view->x - border_width; |
980 | con->y = view->y - top; | 987 | con->y = view->y - top; |
@@ -996,3 +1003,103 @@ void container_get_box(struct sway_container *container, struct wlr_box *box) { | |||
996 | box->width = container->width; | 1003 | box->width = container->width; |
997 | box->height = container->height; | 1004 | box->height = container->height; |
998 | } | 1005 | } |
1006 | |||
1007 | /** | ||
1008 | * Translate the container's position as well as all children. | ||
1009 | */ | ||
1010 | static void container_floating_translate(struct sway_container *con, | ||
1011 | double x_amount, double y_amount) { | ||
1012 | con->x += x_amount; | ||
1013 | con->y += y_amount; | ||
1014 | con->current.swayc_x += x_amount; | ||
1015 | con->current.swayc_y += y_amount; | ||
1016 | if (con->type == C_VIEW) { | ||
1017 | con->sway_view->x += x_amount; | ||
1018 | con->sway_view->y += y_amount; | ||
1019 | con->current.view_x += x_amount; | ||
1020 | con->current.view_y += y_amount; | ||
1021 | } else { | ||
1022 | for (int i = 0; i < con->children->length; ++i) { | ||
1023 | struct sway_container *child = con->children->items[i]; | ||
1024 | container_floating_translate(child, x_amount, y_amount); | ||
1025 | } | ||
1026 | } | ||
1027 | } | ||
1028 | |||
1029 | /** | ||
1030 | * Choose an output for the floating container's new position. | ||
1031 | * | ||
1032 | * If the center of the container intersects an output then we'll choose that | ||
1033 | * one, otherwise we'll choose whichever output is closest to the container's | ||
1034 | * center. | ||
1035 | */ | ||
1036 | static struct sway_container *container_floating_find_output( | ||
1037 | struct sway_container *con) { | ||
1038 | double center_x = con->x + con->width / 2; | ||
1039 | double center_y = con->y + con->height / 2; | ||
1040 | struct sway_container *closest_output = NULL; | ||
1041 | double closest_distance = DBL_MAX; | ||
1042 | for (int i = 0; i < root_container.children->length; ++i) { | ||
1043 | struct sway_container *output = root_container.children->items[i]; | ||
1044 | struct wlr_box output_box; | ||
1045 | double closest_x, closest_y; | ||
1046 | container_get_box(output, &output_box); | ||
1047 | wlr_box_closest_point(&output_box, center_x, center_y, | ||
1048 | &closest_x, &closest_y); | ||
1049 | if (center_x == closest_x && center_y == closest_y) { | ||
1050 | // The center of the floating container is on this output | ||
1051 | return output; | ||
1052 | } | ||
1053 | double x_dist = closest_x - center_x; | ||
1054 | double y_dist = closest_y - center_y; | ||
1055 | double distance = x_dist * x_dist + y_dist * y_dist; | ||
1056 | if (distance < closest_distance) { | ||
1057 | closest_output = output; | ||
1058 | closest_distance = distance; | ||
1059 | } | ||
1060 | } | ||
1061 | return closest_output; | ||
1062 | } | ||
1063 | |||
1064 | void container_floating_move_to(struct sway_container *con, | ||
1065 | double lx, double ly) { | ||
1066 | if (!sway_assert(container_is_floating(con), | ||
1067 | "Expected a floating container")) { | ||
1068 | return; | ||
1069 | } | ||
1070 | desktop_damage_whole_container(con); | ||
1071 | container_floating_translate(con, lx - con->x, ly - con->y); | ||
1072 | desktop_damage_whole_container(con); | ||
1073 | struct sway_container *old_workspace = container_parent(con, C_WORKSPACE); | ||
1074 | struct sway_container *new_output = container_floating_find_output(con); | ||
1075 | if (!sway_assert(new_output, "Unable to find any output")) { | ||
1076 | return; | ||
1077 | } | ||
1078 | struct sway_container *new_workspace = | ||
1079 | output_get_active_workspace(new_output->sway_output); | ||
1080 | if (old_workspace != new_workspace) { | ||
1081 | container_remove_child(con); | ||
1082 | container_add_child(new_workspace->sway_workspace->floating, con); | ||
1083 | arrange_windows(old_workspace); | ||
1084 | arrange_windows(new_workspace); | ||
1085 | workspace_detect_urgent(old_workspace); | ||
1086 | workspace_detect_urgent(new_workspace); | ||
1087 | } | ||
1088 | } | ||
1089 | |||
1090 | void container_set_dirty(struct sway_container *container) { | ||
1091 | if (container->dirty) { | ||
1092 | return; | ||
1093 | } | ||
1094 | container->dirty = true; | ||
1095 | list_add(server.dirty_containers, container); | ||
1096 | } | ||
1097 | |||
1098 | static bool find_urgent_iterator(struct sway_container *con, | ||
1099 | void *data) { | ||
1100 | return con->type == C_VIEW && view_is_urgent(con->sway_view); | ||
1101 | } | ||
1102 | |||
1103 | bool container_has_urgent_child(struct sway_container *container) { | ||
1104 | return container_find(container, find_urgent_iterator, NULL); | ||
1105 | } | ||
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 14631ad4..197a2fc8 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -22,7 +22,8 @@ struct sway_container root_container; | |||
22 | 22 | ||
23 | static void output_layout_handle_change(struct wl_listener *listener, | 23 | static void output_layout_handle_change(struct wl_listener *listener, |
24 | void *data) { | 24 | void *data) { |
25 | arrange_and_commit(&root_container); | 25 | arrange_windows(&root_container); |
26 | transaction_commit_dirty(); | ||
26 | } | 27 | } |
27 | 28 | ||
28 | void layout_init(void) { | 29 | void layout_init(void) { |
@@ -101,7 +102,7 @@ void container_insert_child(struct sway_container *parent, | |||
101 | if (old_parent) { | 102 | if (old_parent) { |
102 | container_remove_child(child); | 103 | container_remove_child(child); |
103 | } | 104 | } |
104 | wlr_log(L_DEBUG, "Inserting id:%zd at index %d", child->id, i); | 105 | wlr_log(WLR_DEBUG, "Inserting id:%zd at index %d", child->id, i); |
105 | list_insert(parent->children, i, child); | 106 | list_insert(parent->children, i, child); |
106 | child->parent = parent; | 107 | child->parent = parent; |
107 | container_handle_fullscreen_reparent(child, old_parent); | 108 | container_handle_fullscreen_reparent(child, old_parent); |
@@ -127,7 +128,7 @@ struct sway_container *container_add_sibling(struct sway_container *fixed, | |||
127 | 128 | ||
128 | void container_add_child(struct sway_container *parent, | 129 | void container_add_child(struct sway_container *parent, |
129 | struct sway_container *child) { | 130 | struct sway_container *child) { |
130 | wlr_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", | 131 | wlr_log(WLR_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", |
131 | child, child->type, child->width, child->height, | 132 | child, child->type, child->width, child->height, |
132 | parent, parent->type, parent->width, parent->height); | 133 | parent, parent->type, parent->width, parent->height); |
133 | struct sway_container *old_parent = child->parent; | 134 | struct sway_container *old_parent = child->parent; |
@@ -168,7 +169,12 @@ void container_move_to(struct sway_container *container, | |||
168 | struct sway_container *old_parent = container_remove_child(container); | 169 | struct sway_container *old_parent = container_remove_child(container); |
169 | container->width = container->height = 0; | 170 | container->width = container->height = 0; |
170 | container->saved_width = container->saved_height = 0; | 171 | container->saved_width = container->saved_height = 0; |
171 | struct sway_container *new_parent; | 172 | |
173 | struct sway_container *new_parent, *new_parent_focus; | ||
174 | struct sway_seat *seat = input_manager_get_default_seat(input_manager); | ||
175 | |||
176 | // Get the focus of the destination before we change it. | ||
177 | new_parent_focus = seat_get_focus_inactive(seat, destination); | ||
172 | if (destination->type == C_VIEW) { | 178 | if (destination->type == C_VIEW) { |
173 | new_parent = container_add_sibling(destination, container); | 179 | new_parent = container_add_sibling(destination, container); |
174 | } else { | 180 | } else { |
@@ -176,17 +182,20 @@ void container_move_to(struct sway_container *container, | |||
176 | container_add_child(destination, container); | 182 | container_add_child(destination, container); |
177 | } | 183 | } |
178 | wl_signal_emit(&container->events.reparent, old_parent); | 184 | wl_signal_emit(&container->events.reparent, old_parent); |
185 | |||
179 | if (container->type == C_WORKSPACE) { | 186 | if (container->type == C_WORKSPACE) { |
180 | // If moving a workspace to a new output, maybe create a new workspace | 187 | // If moving a workspace to a new output, maybe create a new workspace |
181 | // on the previous output | 188 | // on the previous output |
182 | struct sway_seat *seat = input_manager_get_default_seat(input_manager); | ||
183 | if (old_parent->children->length == 0) { | 189 | if (old_parent->children->length == 0) { |
184 | char *ws_name = workspace_next_name(old_parent->name); | 190 | char *ws_name = workspace_next_name(old_parent->name); |
185 | struct sway_container *ws = | 191 | struct sway_container *ws = workspace_create(old_parent, ws_name); |
186 | workspace_create(old_parent, ws_name); | ||
187 | free(ws_name); | 192 | free(ws_name); |
188 | seat_set_focus(seat, ws); | 193 | seat_set_focus(seat, ws); |
189 | } | 194 | } |
195 | |||
196 | // Try to remove an empty workspace from the destination output. | ||
197 | container_reap_empty_recursive(new_parent_focus); | ||
198 | |||
190 | container_sort_workspaces(new_parent); | 199 | container_sort_workspaces(new_parent); |
191 | seat_set_focus(seat, new_parent); | 200 | seat_set_focus(seat, new_parent); |
192 | workspace_output_raise_priority(container, old_parent, new_parent); | 201 | workspace_output_raise_priority(container, old_parent, new_parent); |
@@ -216,6 +225,15 @@ void container_move_to(struct sway_container *container, | |||
216 | } | 225 | } |
217 | } | 226 | } |
218 | } | 227 | } |
228 | // Update workspace urgent state | ||
229 | struct sway_container *old_workspace = old_parent; | ||
230 | if (old_workspace->type != C_WORKSPACE) { | ||
231 | old_workspace = container_parent(old_workspace, C_WORKSPACE); | ||
232 | } | ||
233 | if (new_workspace != old_workspace) { | ||
234 | workspace_detect_urgent(new_workspace); | ||
235 | workspace_detect_urgent(old_workspace); | ||
236 | } | ||
219 | } | 237 | } |
220 | 238 | ||
221 | static bool sway_dir_to_wlr(enum movement_direction dir, | 239 | static bool sway_dir_to_wlr(enum movement_direction dir, |
@@ -311,13 +329,13 @@ static void move_out_of_tabs_stacks(struct sway_container *container, | |||
311 | int offs) { | 329 | int offs) { |
312 | if (container->parent == current->parent | 330 | if (container->parent == current->parent |
313 | && current->parent->children->length == 1) { | 331 | && current->parent->children->length == 1) { |
314 | wlr_log(L_DEBUG, "Changing layout of %zd", current->parent->id); | 332 | wlr_log(WLR_DEBUG, "Changing layout of %zd", current->parent->id); |
315 | current->parent->layout = move_dir == | 333 | current->parent->layout = move_dir == |
316 | MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT; | 334 | MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT; |
317 | return; | 335 | return; |
318 | } | 336 | } |
319 | 337 | ||
320 | wlr_log(L_DEBUG, "Moving out of tab/stack into a split"); | 338 | wlr_log(WLR_DEBUG, "Moving out of tab/stack into a split"); |
321 | bool is_workspace = current->parent->type == C_WORKSPACE; | 339 | bool is_workspace = current->parent->type == C_WORKSPACE; |
322 | struct sway_container *new_parent = container_split(current->parent, | 340 | struct sway_container *new_parent = container_split(current->parent, |
323 | move_dir == MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT); | 341 | move_dir == MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT); |
@@ -362,7 +380,7 @@ void container_move(struct sway_container *container, | |||
362 | } | 380 | } |
363 | 381 | ||
364 | parent = current->parent; | 382 | parent = current->parent; |
365 | wlr_log(L_DEBUG, "Visiting %p %s '%s'", current, | 383 | wlr_log(WLR_DEBUG, "Visiting %p %s '%s'", current, |
366 | container_type_to_str(current->type), current->name); | 384 | container_type_to_str(current->type), current->name); |
367 | 385 | ||
368 | int index = index_child(current); | 386 | int index = index_child(current); |
@@ -380,12 +398,12 @@ void container_move(struct sway_container *container, | |||
380 | root_container.sway_root->output_layout, wlr_dir, | 398 | root_container.sway_root->output_layout, wlr_dir, |
381 | current->sway_output->wlr_output, ref_lx, ref_ly); | 399 | current->sway_output->wlr_output, ref_lx, ref_ly); |
382 | if (!next) { | 400 | if (!next) { |
383 | wlr_log(L_DEBUG, "Hit edge of output, nowhere else to go"); | 401 | wlr_log(WLR_DEBUG, "Hit edge of output, nowhere else to go"); |
384 | return; | 402 | return; |
385 | } | 403 | } |
386 | struct sway_output *next_output = next->data; | 404 | struct sway_output *next_output = next->data; |
387 | current = next_output->swayc; | 405 | current = next_output->swayc; |
388 | wlr_log(L_DEBUG, "Selected next output (%s)", current->name); | 406 | wlr_log(WLR_DEBUG, "Selected next output (%s)", current->name); |
389 | // Select workspace and get outta here | 407 | // Select workspace and get outta here |
390 | current = seat_get_focus_inactive( | 408 | current = seat_get_focus_inactive( |
391 | config->handler_context.seat, current); | 409 | config->handler_context.seat, current); |
@@ -398,20 +416,20 @@ void container_move(struct sway_container *container, | |||
398 | case C_WORKSPACE: | 416 | case C_WORKSPACE: |
399 | if (!is_parallel(current->layout, move_dir)) { | 417 | if (!is_parallel(current->layout, move_dir)) { |
400 | if (current->children->length >= 2) { | 418 | if (current->children->length >= 2) { |
401 | wlr_log(L_DEBUG, "Rejiggering the workspace (%d kiddos)", | 419 | wlr_log(WLR_DEBUG, "Rejiggering the workspace (%d kiddos)", |
402 | current->children->length); | 420 | current->children->length); |
403 | workspace_rejigger(current, container, move_dir); | 421 | workspace_rejigger(current, container, move_dir); |
404 | return; | 422 | return; |
405 | } else { | 423 | } else { |
406 | wlr_log(L_DEBUG, "Selecting output"); | 424 | wlr_log(WLR_DEBUG, "Selecting output"); |
407 | current = current->parent; | 425 | current = current->parent; |
408 | } | 426 | } |
409 | } else if (current->layout == L_TABBED | 427 | } else if (current->layout == L_TABBED |
410 | || current->layout == L_STACKED) { | 428 | || current->layout == L_STACKED) { |
411 | wlr_log(L_DEBUG, "Rejiggering out of tabs/stacks"); | 429 | wlr_log(WLR_DEBUG, "Rejiggering out of tabs/stacks"); |
412 | workspace_rejigger(current, container, move_dir); | 430 | workspace_rejigger(current, container, move_dir); |
413 | } else { | 431 | } else { |
414 | wlr_log(L_DEBUG, "Selecting output"); | 432 | wlr_log(WLR_DEBUG, "Selecting output"); |
415 | current = current->parent; | 433 | current = current->parent; |
416 | } | 434 | } |
417 | break; | 435 | break; |
@@ -427,11 +445,11 @@ void container_move(struct sway_container *container, | |||
427 | move_dir, offs); | 445 | move_dir, offs); |
428 | return; | 446 | return; |
429 | } else { | 447 | } else { |
430 | wlr_log(L_DEBUG, "Hit limit, selecting parent"); | 448 | wlr_log(WLR_DEBUG, "Hit limit, selecting parent"); |
431 | current = current->parent; | 449 | current = current->parent; |
432 | } | 450 | } |
433 | } else { | 451 | } else { |
434 | wlr_log(L_DEBUG, "Hit limit, " | 452 | wlr_log(WLR_DEBUG, "Hit limit, " |
435 | "promoting descendant to sibling"); | 453 | "promoting descendant to sibling"); |
436 | // Special case | 454 | // Special case |
437 | container_insert_child(current->parent, container, | 455 | container_insert_child(current->parent, container, |
@@ -441,14 +459,14 @@ void container_move(struct sway_container *container, | |||
441 | } | 459 | } |
442 | } else { | 460 | } else { |
443 | sibling = parent->children->items[index + offs]; | 461 | sibling = parent->children->items[index + offs]; |
444 | wlr_log(L_DEBUG, "Selecting sibling id:%zd", sibling->id); | 462 | wlr_log(WLR_DEBUG, "Selecting sibling id:%zd", sibling->id); |
445 | } | 463 | } |
446 | } else if (parent->layout == L_TABBED | 464 | } else if (parent->layout == L_TABBED |
447 | || parent->layout == L_STACKED) { | 465 | || parent->layout == L_STACKED) { |
448 | move_out_of_tabs_stacks(container, current, move_dir, offs); | 466 | move_out_of_tabs_stacks(container, current, move_dir, offs); |
449 | return; | 467 | return; |
450 | } else { | 468 | } else { |
451 | wlr_log(L_DEBUG, "Moving up to find a parallel container"); | 469 | wlr_log(WLR_DEBUG, "Moving up to find a parallel container"); |
452 | current = current->parent; | 470 | current = current->parent; |
453 | } | 471 | } |
454 | break; | 472 | break; |
@@ -467,11 +485,11 @@ void container_move(struct sway_container *container, | |||
467 | switch (sibling->type) { | 485 | switch (sibling->type) { |
468 | case C_VIEW: | 486 | case C_VIEW: |
469 | if (sibling->parent == container->parent) { | 487 | if (sibling->parent == container->parent) { |
470 | wlr_log(L_DEBUG, "Swapping siblings"); | 488 | wlr_log(WLR_DEBUG, "Swapping siblings"); |
471 | sibling->parent->children->items[index + offs] = container; | 489 | sibling->parent->children->items[index + offs] = container; |
472 | sibling->parent->children->items[index] = sibling; | 490 | sibling->parent->children->items[index] = sibling; |
473 | } else { | 491 | } else { |
474 | wlr_log(L_DEBUG, "Promoting to sibling of cousin"); | 492 | wlr_log(WLR_DEBUG, "Promoting to sibling of cousin"); |
475 | container_insert_child(sibling->parent, container, | 493 | container_insert_child(sibling->parent, container, |
476 | index_child(sibling) + (offs > 0 ? 0 : 1)); | 494 | index_child(sibling) + (offs > 0 ? 0 : 1)); |
477 | container->width = container->height = 0; | 495 | container->width = container->height = 0; |
@@ -482,31 +500,31 @@ void container_move(struct sway_container *container, | |||
482 | case C_CONTAINER: | 500 | case C_CONTAINER: |
483 | if (is_parallel(sibling->layout, move_dir)) { | 501 | if (is_parallel(sibling->layout, move_dir)) { |
484 | int limit = container_limit(sibling, invert_movement(move_dir)); | 502 | int limit = container_limit(sibling, invert_movement(move_dir)); |
485 | wlr_log(L_DEBUG, "limit: %d", limit); | 503 | wlr_log(WLR_DEBUG, "limit: %d", limit); |
486 | wlr_log(L_DEBUG, | 504 | wlr_log(WLR_DEBUG, |
487 | "Reparenting container (parallel) to index %d " | 505 | "Reparenting container (parallel) to index %d " |
488 | "(move dir: %d)", limit, move_dir); | 506 | "(move dir: %d)", limit, move_dir); |
489 | container_insert_child(sibling, container, limit); | 507 | container_insert_child(sibling, container, limit); |
490 | container->width = container->height = 0; | 508 | container->width = container->height = 0; |
491 | sibling = NULL; | 509 | sibling = NULL; |
492 | } else { | 510 | } else { |
493 | wlr_log(L_DEBUG, "Reparenting container (perpendicular)"); | 511 | wlr_log(WLR_DEBUG, "Reparenting container (perpendicular)"); |
494 | struct sway_container *focus_inactive = seat_get_focus_inactive( | 512 | struct sway_container *focus_inactive = seat_get_focus_inactive( |
495 | config->handler_context.seat, sibling); | 513 | config->handler_context.seat, sibling); |
496 | if (focus_inactive && focus_inactive != sibling) { | 514 | if (focus_inactive && focus_inactive != sibling) { |
497 | while (focus_inactive->parent != sibling) { | 515 | while (focus_inactive->parent != sibling) { |
498 | focus_inactive = focus_inactive->parent; | 516 | focus_inactive = focus_inactive->parent; |
499 | } | 517 | } |
500 | wlr_log(L_DEBUG, "Focus inactive: id:%zd", | 518 | wlr_log(WLR_DEBUG, "Focus inactive: id:%zd", |
501 | focus_inactive->id); | 519 | focus_inactive->id); |
502 | sibling = focus_inactive; | 520 | sibling = focus_inactive; |
503 | continue; | 521 | continue; |
504 | } else if (sibling->children->length) { | 522 | } else if (sibling->children->length) { |
505 | wlr_log(L_DEBUG, "No focus-inactive, adding arbitrarily"); | 523 | wlr_log(WLR_DEBUG, "No focus-inactive, adding arbitrarily"); |
506 | container_remove_child(container); | 524 | container_remove_child(container); |
507 | container_add_sibling(sibling->children->items[0], container); | 525 | container_add_sibling(sibling->children->items[0], container); |
508 | } else { | 526 | } else { |
509 | wlr_log(L_DEBUG, "No kiddos, adding container alone"); | 527 | wlr_log(WLR_DEBUG, "No kiddos, adding container alone"); |
510 | container_remove_child(container); | 528 | container_remove_child(container); |
511 | container_add_child(sibling, container); | 529 | container_add_child(sibling, container); |
512 | } | 530 | } |
@@ -539,6 +557,8 @@ void container_move(struct sway_container *container, | |||
539 | } | 557 | } |
540 | if (last_ws && next_ws && last_ws != next_ws) { | 558 | if (last_ws && next_ws && last_ws != next_ws) { |
541 | ipc_event_workspace(last_ws, container, "focus"); | 559 | ipc_event_workspace(last_ws, container, "focus"); |
560 | workspace_detect_urgent(last_ws); | ||
561 | workspace_detect_urgent(next_ws); | ||
542 | } | 562 | } |
543 | } | 563 | } |
544 | 564 | ||
@@ -603,7 +623,7 @@ static struct sway_container *get_swayc_in_output_direction( | |||
603 | } | 623 | } |
604 | 624 | ||
605 | if (ws == NULL) { | 625 | if (ws == NULL) { |
606 | wlr_log(L_ERROR, "got an output without a workspace"); | 626 | wlr_log(WLR_ERROR, "got an output without a workspace"); |
607 | return NULL; | 627 | return NULL; |
608 | } | 628 | } |
609 | 629 | ||
@@ -775,7 +795,7 @@ struct sway_container *container_get_in_direction( | |||
775 | } else { | 795 | } else { |
776 | struct sway_container *desired_con = | 796 | struct sway_container *desired_con = |
777 | parent->children->items[desired]; | 797 | parent->children->items[desired]; |
778 | wlr_log(L_DEBUG, | 798 | wlr_log(WLR_DEBUG, |
779 | "cont %d-%p dir %i sibling %d: %p", idx, | 799 | "cont %d-%p dir %i sibling %d: %p", idx, |
780 | container, dir, desired, desired_con); | 800 | container, dir, desired, desired_con); |
781 | return seat_get_focus_inactive_view(seat, desired_con); | 801 | return seat_get_focus_inactive_view(seat, desired_con); |
@@ -840,7 +860,7 @@ struct sway_container *container_split(struct sway_container *child, | |||
840 | 860 | ||
841 | struct sway_container *cont = container_create(C_CONTAINER); | 861 | struct sway_container *cont = container_create(C_CONTAINER); |
842 | 862 | ||
843 | wlr_log(L_DEBUG, "creating container %p around %p", cont, child); | 863 | wlr_log(WLR_DEBUG, "creating container %p around %p", cont, child); |
844 | 864 | ||
845 | remove_gaps(child); | 865 | remove_gaps(child); |
846 | 866 | ||
@@ -888,7 +908,7 @@ struct sway_container *container_split(struct sway_container *child, | |||
888 | void container_recursive_resize(struct sway_container *container, | 908 | void container_recursive_resize(struct sway_container *container, |
889 | double amount, enum resize_edge edge) { | 909 | double amount, enum resize_edge edge) { |
890 | bool layout_match = true; | 910 | bool layout_match = true; |
891 | wlr_log(L_DEBUG, "Resizing %p with amount: %f", container, amount); | 911 | wlr_log(WLR_DEBUG, "Resizing %p with amount: %f", container, amount); |
892 | if (edge == RESIZE_EDGE_LEFT || edge == RESIZE_EDGE_RIGHT) { | 912 | if (edge == RESIZE_EDGE_LEFT || edge == RESIZE_EDGE_RIGHT) { |
893 | container->width += amount; | 913 | container->width += amount; |
894 | layout_match = container->layout == L_HORIZ; | 914 | layout_match = container->layout == L_HORIZ; |
@@ -978,7 +998,7 @@ void container_swap(struct sway_container *con1, struct sway_container *con2) { | |||
978 | return; | 998 | return; |
979 | } | 999 | } |
980 | 1000 | ||
981 | wlr_log(L_DEBUG, "Swapping containers %zu and %zu", con1->id, con2->id); | 1001 | wlr_log(WLR_DEBUG, "Swapping containers %zu and %zu", con1->id, con2->id); |
982 | 1002 | ||
983 | int fs1 = con1->type == C_VIEW && con1->sway_view->is_fullscreen; | 1003 | int fs1 = con1->type == C_VIEW && con1->sway_view->is_fullscreen; |
984 | int fs2 = con2->type == C_VIEW && con2->sway_view->is_fullscreen; | 1004 | int fs2 = con2->type == C_VIEW && con2->sway_view->is_fullscreen; |
diff --git a/sway/tree/output.c b/sway/tree/output.c index e2927cdb..da535c18 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c | |||
@@ -43,11 +43,11 @@ struct sway_container *output_create( | |||
43 | 43 | ||
44 | if (strcasecmp(name, cur->name) == 0 || | 44 | if (strcasecmp(name, cur->name) == 0 || |
45 | strcasecmp(identifier, cur->name) == 0) { | 45 | strcasecmp(identifier, cur->name) == 0) { |
46 | wlr_log(L_DEBUG, "Matched output config for %s", name); | 46 | wlr_log(WLR_DEBUG, "Matched output config for %s", name); |
47 | oc = cur; | 47 | oc = cur; |
48 | } | 48 | } |
49 | if (strcasecmp("*", cur->name) == 0) { | 49 | if (strcasecmp("*", cur->name) == 0) { |
50 | wlr_log(L_DEBUG, "Matched wildcard output config for %s", name); | 50 | wlr_log(WLR_DEBUG, "Matched wildcard output config for %s", name); |
51 | all = cur; | 51 | all = cur; |
52 | } | 52 | } |
53 | 53 | ||
@@ -86,7 +86,7 @@ struct sway_container *output_create( | |||
86 | if (!output->children->length) { | 86 | if (!output->children->length) { |
87 | // Create workspace | 87 | // Create workspace |
88 | char *ws_name = workspace_next_name(output->name); | 88 | char *ws_name = workspace_next_name(output->name); |
89 | wlr_log(L_DEBUG, "Creating default workspace %s", ws_name); | 89 | wlr_log(WLR_DEBUG, "Creating default workspace %s", ws_name); |
90 | struct sway_container *ws = workspace_create(output, ws_name); | 90 | struct sway_container *ws = workspace_create(output, ws_name); |
91 | // Set each seat's focus if not already set | 91 | // Set each seat's focus if not already set |
92 | struct sway_seat *seat = NULL; | 92 | struct sway_seat *seat = NULL; |
diff --git a/sway/tree/view.c b/sway/tree/view.c index 3ef79fa8..fc31699c 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -25,6 +25,7 @@ void view_init(struct sway_view *view, enum sway_view_type type, | |||
25 | view->impl = impl; | 25 | view->impl = impl; |
26 | view->executed_criteria = create_list(); | 26 | view->executed_criteria = create_list(); |
27 | view->marks = create_list(); | 27 | view->marks = create_list(); |
28 | view->allow_request_urgent = true; | ||
28 | wl_signal_init(&view->events.unmap); | 29 | wl_signal_init(&view->events.unmap); |
29 | } | 30 | } |
30 | 31 | ||
@@ -150,12 +151,43 @@ uint32_t view_configure(struct sway_view *view, double lx, double ly, int width, | |||
150 | 151 | ||
151 | void view_init_floating(struct sway_view *view) { | 152 | void view_init_floating(struct sway_view *view) { |
152 | struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); | 153 | struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); |
153 | int max_width = ws->width * 0.6666; | 154 | int min_width, min_height; |
154 | int max_height = ws->height * 0.6666; | 155 | int max_width, max_height; |
155 | view->width = | 156 | |
156 | view->natural_width > max_width ? max_width : view->natural_width; | 157 | if (config->floating_minimum_width == -1) { // no minimum |
157 | view->height = | 158 | min_width = 0; |
158 | view->natural_height > max_height ? max_height : view->natural_height; | 159 | } else if (config->floating_minimum_width == 0) { // automatic |
160 | min_width = 75; | ||
161 | } else { | ||
162 | min_width = config->floating_minimum_width; | ||
163 | } | ||
164 | |||
165 | if (config->floating_minimum_height == -1) { // no minimum | ||
166 | min_height = 0; | ||
167 | } else if (config->floating_minimum_height == 0) { // automatic | ||
168 | min_height = 50; | ||
169 | } else { | ||
170 | min_height = config->floating_minimum_height; | ||
171 | } | ||
172 | |||
173 | if (config->floating_maximum_width == -1) { // no maximum | ||
174 | max_width = INT_MAX; | ||
175 | } else if (config->floating_maximum_width == 0) { // automatic | ||
176 | max_width = ws->width * 0.6666; | ||
177 | } else { | ||
178 | max_width = config->floating_maximum_width; | ||
179 | } | ||
180 | |||
181 | if (config->floating_maximum_height == -1) { // no maximum | ||
182 | max_height = INT_MAX; | ||
183 | } else if (config->floating_maximum_height == 0) { // automatic | ||
184 | max_height = ws->height * 0.6666; | ||
185 | } else { | ||
186 | max_height = config->floating_maximum_height; | ||
187 | } | ||
188 | |||
189 | view->width = fmax(min_width, fmin(view->natural_width, max_width)); | ||
190 | view->height = fmax(min_height, fmin(view->natural_height, max_height)); | ||
159 | view->x = ws->x + (ws->width - view->width) / 2; | 191 | view->x = ws->x + (ws->width - view->width) / 2; |
160 | view->y = ws->y + (ws->height - view->height) / 2; | 192 | view->y = ws->y + (ws->height - view->height) / 2; |
161 | 193 | ||
@@ -284,7 +316,15 @@ void view_set_activated(struct sway_view *view, bool activated) { | |||
284 | } | 316 | } |
285 | 317 | ||
286 | void view_set_tiled(struct sway_view *view, bool tiled) { | 318 | void view_set_tiled(struct sway_view *view, bool tiled) { |
287 | view->border = tiled ? config->border : B_NONE; | 319 | if (!tiled) { |
320 | view->using_csd = true; | ||
321 | if (view->impl->has_client_side_decorations) { | ||
322 | view->using_csd = view->impl->has_client_side_decorations(view); | ||
323 | } | ||
324 | } else { | ||
325 | view->using_csd = false; | ||
326 | } | ||
327 | |||
288 | if (view->impl->set_tiled) { | 328 | if (view->impl->set_tiled) { |
289 | view->impl->set_tiled(view, tiled); | 329 | view->impl->set_tiled(view, tiled); |
290 | } | 330 | } |
@@ -462,27 +502,45 @@ void view_execute_criteria(struct sway_view *view) { | |||
462 | list_t *criterias = criteria_for_view(view, CT_COMMAND); | 502 | list_t *criterias = criteria_for_view(view, CT_COMMAND); |
463 | for (int i = 0; i < criterias->length; i++) { | 503 | for (int i = 0; i < criterias->length; i++) { |
464 | struct criteria *criteria = criterias->items[i]; | 504 | struct criteria *criteria = criterias->items[i]; |
465 | wlr_log(L_DEBUG, "Checking criteria %s", criteria->raw); | 505 | wlr_log(WLR_DEBUG, "Checking criteria %s", criteria->raw); |
466 | if (view_has_executed_criteria(view, criteria)) { | 506 | if (view_has_executed_criteria(view, criteria)) { |
467 | wlr_log(L_DEBUG, "Criteria already executed"); | 507 | wlr_log(WLR_DEBUG, "Criteria already executed"); |
468 | continue; | 508 | continue; |
469 | } | 509 | } |
470 | wlr_log(L_DEBUG, "for_window '%s' matches view %p, cmd: '%s'", | 510 | wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'", |
471 | criteria->raw, view, criteria->cmdlist); | 511 | criteria->raw, view, criteria->cmdlist); |
512 | seat_set_focus(seat, view->swayc); | ||
472 | list_add(view->executed_criteria, criteria); | 513 | list_add(view->executed_criteria, criteria); |
473 | struct cmd_results *res = execute_command(criteria->cmdlist, NULL); | 514 | struct cmd_results *res = execute_command(criteria->cmdlist, NULL); |
474 | if (res->status != CMD_SUCCESS) { | 515 | if (res->status != CMD_SUCCESS) { |
475 | wlr_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error); | 516 | wlr_log(WLR_ERROR, "Command '%s' failed: %s", res->input, res->error); |
476 | } | 517 | } |
477 | free_cmd_results(res); | 518 | free_cmd_results(res); |
478 | // view must be focused for commands to affect it, | ||
479 | // so always refocus in-between command lists | ||
480 | seat_set_focus(seat, view->swayc); | ||
481 | } | 519 | } |
482 | list_free(criterias); | 520 | list_free(criterias); |
483 | seat_set_focus(seat, prior_focus); | 521 | seat_set_focus(seat, prior_focus); |
484 | } | 522 | } |
485 | 523 | ||
524 | static bool should_focus(struct sway_view *view) { | ||
525 | // If the view is the only one in the focused workspace, it'll get focus | ||
526 | // regardless of any no_focus criteria. | ||
527 | struct sway_container *parent = view->swayc->parent; | ||
528 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
529 | if (parent->type == C_WORKSPACE && seat_get_focus(seat) == parent) { | ||
530 | size_t num_children = parent->children->length + | ||
531 | parent->sway_workspace->floating->children->length; | ||
532 | if (num_children == 1) { | ||
533 | return true; | ||
534 | } | ||
535 | } | ||
536 | |||
537 | // Check no_focus criteria | ||
538 | list_t *criterias = criteria_for_view(view, CT_NO_FOCUS); | ||
539 | size_t len = criterias->length; | ||
540 | list_free(criterias); | ||
541 | return len == 0; | ||
542 | } | ||
543 | |||
486 | void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { | 544 | void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { |
487 | if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { | 545 | if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { |
488 | return; | 546 | return; |
@@ -519,8 +577,6 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { | |||
519 | 577 | ||
520 | view->surface = wlr_surface; | 578 | view->surface = wlr_surface; |
521 | view->swayc = cont; | 579 | view->swayc = cont; |
522 | view->border = config->border; | ||
523 | view->border_thickness = config->border_thickness; | ||
524 | 580 | ||
525 | view_init_subsurfaces(view, wlr_surface); | 581 | view_init_subsurfaces(view, wlr_surface); |
526 | wl_signal_add(&wlr_surface->events.new_subsurface, | 582 | wl_signal_add(&wlr_surface->events.new_subsurface, |
@@ -531,14 +587,20 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { | |||
531 | view->container_reparent.notify = view_handle_container_reparent; | 587 | view->container_reparent.notify = view_handle_container_reparent; |
532 | 588 | ||
533 | if (view->impl->wants_floating && view->impl->wants_floating(view)) { | 589 | if (view->impl->wants_floating && view->impl->wants_floating(view)) { |
590 | view->border = config->floating_border; | ||
591 | view->border_thickness = config->floating_border_thickness; | ||
534 | container_set_floating(view->swayc, true); | 592 | container_set_floating(view->swayc, true); |
535 | } else { | 593 | } else { |
594 | view->border = config->border; | ||
595 | view->border_thickness = config->border_thickness; | ||
536 | view_set_tiled(view, true); | 596 | view_set_tiled(view, true); |
537 | } | 597 | } |
538 | 598 | ||
539 | input_manager_set_focus(input_manager, cont); | 599 | if (should_focus(view)) { |
540 | if (workspace) { | 600 | input_manager_set_focus(input_manager, cont); |
541 | workspace_switch(workspace); | 601 | if (workspace) { |
602 | workspace_switch(workspace); | ||
603 | } | ||
542 | } | 604 | } |
543 | 605 | ||
544 | view_update_title(view, false); | 606 | view_update_title(view, false); |
@@ -554,16 +616,27 @@ void view_unmap(struct sway_view *view) { | |||
554 | wl_list_remove(&view->surface_new_subsurface.link); | 616 | wl_list_remove(&view->surface_new_subsurface.link); |
555 | wl_list_remove(&view->container_reparent.link); | 617 | wl_list_remove(&view->container_reparent.link); |
556 | 618 | ||
619 | if (view->urgent_timer) { | ||
620 | wl_event_source_remove(view->urgent_timer); | ||
621 | view->urgent_timer = NULL; | ||
622 | } | ||
623 | |||
624 | struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); | ||
625 | |||
626 | struct sway_container *parent; | ||
557 | if (view->is_fullscreen) { | 627 | if (view->is_fullscreen) { |
558 | struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); | ||
559 | ws->sway_workspace->fullscreen = NULL; | 628 | ws->sway_workspace->fullscreen = NULL; |
560 | container_destroy(view->swayc); | 629 | parent = container_destroy(view->swayc); |
561 | 630 | ||
562 | arrange_and_commit(ws->parent); | 631 | arrange_windows(ws->parent); |
563 | } else { | 632 | } else { |
564 | struct sway_container *parent = container_destroy(view->swayc); | 633 | parent = container_destroy(view->swayc); |
565 | arrange_and_commit(parent); | 634 | arrange_windows(parent); |
635 | } | ||
636 | if (parent->type >= C_WORKSPACE) { // if the workspace still exists | ||
637 | workspace_detect_urgent(ws); | ||
566 | } | 638 | } |
639 | transaction_commit_dirty(); | ||
567 | view->surface = NULL; | 640 | view->surface = NULL; |
568 | } | 641 | } |
569 | 642 | ||
@@ -601,7 +674,7 @@ static void view_subsurface_create(struct sway_view *view, | |||
601 | struct wlr_subsurface *subsurface) { | 674 | struct wlr_subsurface *subsurface) { |
602 | struct sway_view_child *child = calloc(1, sizeof(struct sway_view_child)); | 675 | struct sway_view_child *child = calloc(1, sizeof(struct sway_view_child)); |
603 | if (child == NULL) { | 676 | if (child == NULL) { |
604 | wlr_log(L_ERROR, "Allocation failed"); | 677 | wlr_log(WLR_ERROR, "Allocation failed"); |
605 | return; | 678 | return; |
606 | } | 679 | } |
607 | view_child_init(child, NULL, view, subsurface->surface); | 680 | view_child_init(child, NULL, view, subsurface->surface); |
@@ -721,8 +794,9 @@ struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) { | |||
721 | return NULL; | 794 | return NULL; |
722 | } | 795 | } |
723 | 796 | ||
724 | wlr_log(L_DEBUG, "Surface of unknown type (role %s): %p", | 797 | const char *role = wlr_surface->role ? wlr_surface->role->name : NULL; |
725 | wlr_surface->role, wlr_surface); | 798 | wlr_log(WLR_DEBUG, "Surface of unknown type (role %s): %p", |
799 | role, wlr_surface); | ||
726 | return NULL; | 800 | return NULL; |
727 | } | 801 | } |
728 | 802 | ||
@@ -789,7 +863,7 @@ static char *escape_title(char *buffer) { | |||
789 | char *escaped_title = calloc(length + 1, sizeof(char)); | 863 | char *escaped_title = calloc(length + 1, sizeof(char)); |
790 | int result = escape_markup_text(buffer, escaped_title, length); | 864 | int result = escape_markup_text(buffer, escaped_title, length); |
791 | if (result != length) { | 865 | if (result != length) { |
792 | wlr_log(L_ERROR, "Could not escape title: %s", buffer); | 866 | wlr_log(WLR_ERROR, "Could not escape title: %s", buffer); |
793 | free(escaped_title); | 867 | free(escaped_title); |
794 | return buffer; | 868 | return buffer; |
795 | } | 869 | } |
@@ -1010,3 +1084,32 @@ bool view_is_visible(struct sway_view *view) { | |||
1010 | } | 1084 | } |
1011 | return true; | 1085 | return true; |
1012 | } | 1086 | } |
1087 | |||
1088 | void view_set_urgent(struct sway_view *view, bool enable) { | ||
1089 | if (view_is_urgent(view) == enable) { | ||
1090 | return; | ||
1091 | } | ||
1092 | if (enable) { | ||
1093 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
1094 | if (seat_get_focus(seat) == view->swayc) { | ||
1095 | return; | ||
1096 | } | ||
1097 | clock_gettime(CLOCK_MONOTONIC, &view->urgent); | ||
1098 | } else { | ||
1099 | view->urgent = (struct timespec){ 0 }; | ||
1100 | if (view->urgent_timer) { | ||
1101 | wl_event_source_remove(view->urgent_timer); | ||
1102 | view->urgent_timer = NULL; | ||
1103 | } | ||
1104 | } | ||
1105 | container_damage_whole(view->swayc); | ||
1106 | |||
1107 | ipc_event_window(view->swayc, "urgent"); | ||
1108 | |||
1109 | struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); | ||
1110 | workspace_detect_urgent(ws); | ||
1111 | } | ||
1112 | |||
1113 | bool view_is_urgent(struct sway_view *view) { | ||
1114 | return view->urgent.tv_sec || view->urgent.tv_nsec; | ||
1115 | } | ||
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 51f0fcb4..622f01ec 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include "sway/ipc-server.h" | 11 | #include "sway/ipc-server.h" |
12 | #include "sway/tree/arrange.h" | 12 | #include "sway/tree/arrange.h" |
13 | #include "sway/tree/container.h" | 13 | #include "sway/tree/container.h" |
14 | #include "sway/tree/view.h" | ||
14 | #include "sway/tree/workspace.h" | 15 | #include "sway/tree/workspace.h" |
15 | #include "list.h" | 16 | #include "list.h" |
16 | #include "log.h" | 17 | #include "log.h" |
@@ -49,7 +50,7 @@ struct sway_container *workspace_create(struct sway_container *output, | |||
49 | output = get_workspace_initial_output(name); | 50 | output = get_workspace_initial_output(name); |
50 | } | 51 | } |
51 | 52 | ||
52 | wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); | 53 | wlr_log(WLR_DEBUG, "Added workspace %s for output %s", name, output->name); |
53 | struct sway_container *workspace = container_create(C_WORKSPACE); | 54 | struct sway_container *workspace = container_create(C_WORKSPACE); |
54 | 55 | ||
55 | workspace->x = output->x; | 56 | workspace->x = output->x; |
@@ -107,7 +108,7 @@ static bool workspace_valid_on_output(const char *output_name, | |||
107 | } | 108 | } |
108 | 109 | ||
109 | char *workspace_next_name(const char *output_name) { | 110 | char *workspace_next_name(const char *output_name) { |
110 | wlr_log(L_DEBUG, "Workspace: Generating new workspace name for output %s", | 111 | wlr_log(WLR_DEBUG, "Workspace: Generating new workspace name for output %s", |
111 | output_name); | 112 | output_name); |
112 | // Scan all workspace bindings to find the next available workspace name, | 113 | // Scan all workspace bindings to find the next available workspace name, |
113 | // if none are found/available then default to a number | 114 | // if none are found/available then default to a number |
@@ -135,7 +136,7 @@ char *workspace_next_name(const char *output_name) { | |||
135 | while (isspace(*_target)) { | 136 | while (isspace(*_target)) { |
136 | memmove(_target, _target+1, strlen(_target+1)); | 137 | memmove(_target, _target+1, strlen(_target+1)); |
137 | } | 138 | } |
138 | wlr_log(L_DEBUG, "Got valid workspace command for target: '%s'", | 139 | wlr_log(WLR_DEBUG, "Got valid workspace command for target: '%s'", |
139 | _target); | 140 | _target); |
140 | 141 | ||
141 | // Make sure that the command references an actual workspace | 142 | // Make sure that the command references an actual workspace |
@@ -161,7 +162,7 @@ char *workspace_next_name(const char *output_name) { | |||
161 | temp[length - 1] = '\0'; | 162 | temp[length - 1] = '\0'; |
162 | free(_target); | 163 | free(_target); |
163 | _target = temp; | 164 | _target = temp; |
164 | wlr_log(L_DEBUG, "Isolated name from workspace number: '%s'", _target); | 165 | wlr_log(WLR_DEBUG, "Isolated name from workspace number: '%s'", _target); |
165 | 166 | ||
166 | // Make sure the workspace number doesn't already exist | 167 | // Make sure the workspace number doesn't already exist |
167 | if (workspace_by_number(_target)) { | 168 | if (workspace_by_number(_target)) { |
@@ -190,7 +191,7 @@ char *workspace_next_name(const char *output_name) { | |||
190 | order = binding->order; | 191 | order = binding->order; |
191 | free(target); | 192 | free(target); |
192 | target = _target; | 193 | target = _target; |
193 | wlr_log(L_DEBUG, "Workspace: Found free name %s", _target); | 194 | wlr_log(WLR_DEBUG, "Workspace: Found free name %s", _target); |
194 | } else { | 195 | } else { |
195 | free(_target); | 196 | free(_target); |
196 | } | 197 | } |
@@ -387,7 +388,7 @@ bool workspace_switch(struct sway_container *workspace) { | |||
387 | free(prev_workspace_name); | 388 | free(prev_workspace_name); |
388 | prev_workspace_name = malloc(strlen(active_ws->name) + 1); | 389 | prev_workspace_name = malloc(strlen(active_ws->name) + 1); |
389 | if (!prev_workspace_name) { | 390 | if (!prev_workspace_name) { |
390 | wlr_log(L_ERROR, "Unable to allocate previous workspace name"); | 391 | wlr_log(WLR_ERROR, "Unable to allocate previous workspace name"); |
391 | return false; | 392 | return false; |
392 | } | 393 | } |
393 | strcpy(prev_workspace_name, active_ws->name); | 394 | strcpy(prev_workspace_name, active_ws->name); |
@@ -409,7 +410,7 @@ bool workspace_switch(struct sway_container *workspace) { | |||
409 | } | 410 | } |
410 | } | 411 | } |
411 | 412 | ||
412 | wlr_log(L_DEBUG, "Switching to workspace %p:%s", | 413 | wlr_log(WLR_DEBUG, "Switching to workspace %p:%s", |
413 | workspace, workspace->name); | 414 | workspace, workspace->name); |
414 | struct sway_container *next = seat_get_focus_inactive(seat, workspace); | 415 | struct sway_container *next = seat_get_focus_inactive(seat, workspace); |
415 | if (next == NULL) { | 416 | if (next == NULL) { |
@@ -427,7 +428,7 @@ bool workspace_switch(struct sway_container *workspace) { | |||
427 | } | 428 | } |
428 | seat_set_focus(seat, next); | 429 | seat_set_focus(seat, next); |
429 | struct sway_container *output = container_parent(workspace, C_OUTPUT); | 430 | struct sway_container *output = container_parent(workspace, C_OUTPUT); |
430 | arrange_and_commit(output); | 431 | arrange_windows(output); |
431 | return true; | 432 | return true; |
432 | } | 433 | } |
433 | 434 | ||
@@ -518,3 +519,13 @@ struct sway_container *workspace_output_get_highest_available( | |||
518 | 519 | ||
519 | return NULL; | 520 | return NULL; |
520 | } | 521 | } |
522 | |||
523 | void workspace_detect_urgent(struct sway_container *workspace) { | ||
524 | bool new_urgent = container_has_urgent_child(workspace); | ||
525 | |||
526 | if (workspace->sway_workspace->urgent != new_urgent) { | ||
527 | workspace->sway_workspace->urgent = new_urgent; | ||
528 | ipc_event_workspace(NULL, workspace, "urgent"); | ||
529 | container_damage_whole(workspace); | ||
530 | } | ||
531 | } | ||
diff --git a/swaybar/bar.c b/swaybar/bar.c index 5b8028e5..94bc48bc 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c | |||
@@ -46,7 +46,7 @@ static void swaybar_output_free(struct swaybar_output *output) { | |||
46 | if (!output) { | 46 | if (!output) { |
47 | return; | 47 | return; |
48 | } | 48 | } |
49 | wlr_log(L_DEBUG, "Removing output %s", output->name); | 49 | wlr_log(WLR_DEBUG, "Removing output %s", output->name); |
50 | zwlr_layer_surface_v1_destroy(output->layer_surface); | 50 | zwlr_layer_surface_v1_destroy(output->layer_surface); |
51 | wl_surface_destroy(output->surface); | 51 | wl_surface_destroy(output->surface); |
52 | wl_output_destroy(output->output); | 52 | wl_output_destroy(output->output); |
@@ -147,7 +147,7 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, | |||
147 | && x < hotspot->x + hotspot->width | 147 | && x < hotspot->x + hotspot->width |
148 | && y < hotspot->y + hotspot->height) { | 148 | && y < hotspot->y + hotspot->height) { |
149 | hotspot->callback(output, pointer->x, pointer->y, | 149 | hotspot->callback(output, pointer->x, pointer->y, |
150 | button, hotspot->data); | 150 | wl_button_to_x11_button(button), hotspot->data); |
151 | } | 151 | } |
152 | } | 152 | } |
153 | } | 153 | } |
@@ -155,11 +155,26 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, | |||
155 | static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, | 155 | static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, |
156 | uint32_t time, uint32_t axis, wl_fixed_t value) { | 156 | uint32_t time, uint32_t axis, wl_fixed_t value) { |
157 | struct swaybar *bar = data; | 157 | struct swaybar *bar = data; |
158 | struct swaybar_pointer *pointer = &bar->pointer; | ||
158 | struct swaybar_output *output = bar->pointer.current; | 159 | struct swaybar_output *output = bar->pointer.current; |
159 | if (!sway_assert(output, "axis with no active output")) { | 160 | if (!sway_assert(output, "axis with no active output")) { |
160 | return; | 161 | return; |
161 | } | 162 | } |
162 | 163 | ||
164 | struct swaybar_hotspot *hotspot; | ||
165 | wl_list_for_each(hotspot, &output->hotspots, link) { | ||
166 | double x = pointer->x * output->scale; | ||
167 | double y = pointer->y * output->scale; | ||
168 | if (x >= hotspot->x | ||
169 | && y >= hotspot->y | ||
170 | && x < hotspot->x + hotspot->width | ||
171 | && y < hotspot->y + hotspot->height) { | ||
172 | hotspot->callback(output, pointer->x, pointer->y, | ||
173 | wl_axis_to_x11_button(axis, value), hotspot->data); | ||
174 | return; | ||
175 | } | ||
176 | } | ||
177 | |||
163 | double amt = wl_fixed_to_double(value); | 178 | double amt = wl_fixed_to_double(value); |
164 | if (amt == 0.0) { | 179 | if (amt == 0.0) { |
165 | return; | 180 | return; |
diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c index 141612a6..78b183ad 100644 --- a/swaybar/i3bar.c +++ b/swaybar/i3bar.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | 1 | #define _POSIX_C_SOURCE 200809L |
2 | #include <json-c/json.h> | 2 | #include <json-c/json.h> |
3 | #include <linux/input-event-codes.h> | ||
3 | #include <stdlib.h> | 4 | #include <stdlib.h> |
4 | #include <string.h> | 5 | #include <string.h> |
5 | #include <unistd.h> | 6 | #include <unistd.h> |
@@ -31,7 +32,7 @@ static bool i3bar_parse_json(struct status_line *status, const char *text) { | |||
31 | status_error(status, "[failed to parse i3bar json]"); | 32 | status_error(status, "[failed to parse i3bar json]"); |
32 | return false; | 33 | return false; |
33 | } | 34 | } |
34 | wlr_log(L_DEBUG, "Got i3bar json: '%s'", text); | 35 | wlr_log(WLR_DEBUG, "Got i3bar json: '%s'", text); |
35 | for (size_t i = 0; i < json_object_array_length(results); ++i) { | 36 | for (size_t i = 0; i < json_object_array_length(results); ++i) { |
36 | json_object *full_text, *short_text, *color, *min_width, *align, *urgent; | 37 | json_object *full_text, *short_text, *color, *min_width, *align, *urgent; |
37 | json_object *name, *instance, *separator, *separator_block_width; | 38 | json_object *name, *instance, *separator, *separator_block_width; |
@@ -192,8 +193,8 @@ bool i3bar_handle_readable(struct status_line *status) { | |||
192 | } | 193 | } |
193 | 194 | ||
194 | void i3bar_block_send_click(struct status_line *status, | 195 | void i3bar_block_send_click(struct status_line *status, |
195 | struct i3bar_block *block, int x, int y, uint32_t button) { | 196 | struct i3bar_block *block, int x, int y, enum x11_button button) { |
196 | wlr_log(L_DEBUG, "block %s clicked", block->name ? block->name : "(nil)"); | 197 | wlr_log(WLR_DEBUG, "block %s clicked", block->name ? block->name : "(nil)"); |
197 | if (!block->name || !status->i3bar_state.click_events) { | 198 | if (!block->name || !status->i3bar_state.click_events) { |
198 | return; | 199 | return; |
199 | } | 200 | } |
@@ -215,3 +216,32 @@ void i3bar_block_send_click(struct status_line *status, | |||
215 | } | 216 | } |
216 | json_object_put(event_json); | 217 | json_object_put(event_json); |
217 | } | 218 | } |
219 | |||
220 | enum x11_button wl_button_to_x11_button(uint32_t button) { | ||
221 | switch (button) { | ||
222 | case BTN_LEFT: | ||
223 | return LEFT; | ||
224 | case BTN_MIDDLE: | ||
225 | return MIDDLE; | ||
226 | case BTN_RIGHT: | ||
227 | return RIGHT; | ||
228 | case BTN_SIDE: | ||
229 | return BACK; | ||
230 | case BTN_EXTRA: | ||
231 | return FORWARD; | ||
232 | default: | ||
233 | return NONE; | ||
234 | } | ||
235 | } | ||
236 | |||
237 | enum x11_button wl_axis_to_x11_button(uint32_t axis, wl_fixed_t value) { | ||
238 | switch (axis) { | ||
239 | case WL_POINTER_AXIS_VERTICAL_SCROLL: | ||
240 | return wl_fixed_to_double(value) < 0 ? SCROLL_UP : SCROLL_DOWN; | ||
241 | case WL_POINTER_AXIS_HORIZONTAL_SCROLL: | ||
242 | return wl_fixed_to_double(value) < 0 ? SCROLL_LEFT : SCROLL_RIGHT; | ||
243 | default: | ||
244 | wlr_log(WLR_DEBUG, "Unexpected axis value on mouse scroll"); | ||
245 | return NONE; | ||
246 | } | ||
247 | } | ||
diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 959fa095..c2d05920 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c | |||
@@ -115,6 +115,18 @@ static void ipc_parse_colors( | |||
115 | config->colors.inactive_workspace.text = parse_color( | 115 | config->colors.inactive_workspace.text = parse_color( |
116 | json_object_get_string(inactive_workspace_text)); | 116 | json_object_get_string(inactive_workspace_text)); |
117 | } | 117 | } |
118 | if (urgent_workspace_border) { | ||
119 | config->colors.urgent_workspace.border = parse_color( | ||
120 | json_object_get_string(urgent_workspace_border)); | ||
121 | } | ||
122 | if (urgent_workspace_bg) { | ||
123 | config->colors.urgent_workspace.background = parse_color( | ||
124 | json_object_get_string(urgent_workspace_bg)); | ||
125 | } | ||
126 | if (urgent_workspace_text) { | ||
127 | config->colors.urgent_workspace.text = parse_color( | ||
128 | json_object_get_string(urgent_workspace_text)); | ||
129 | } | ||
118 | if (binding_mode_border) { | 130 | if (binding_mode_border) { |
119 | config->colors.binding_mode.border = parse_color( | 131 | config->colors.binding_mode.border = parse_color( |
120 | json_object_get_string(binding_mode_border)); | 132 | json_object_get_string(binding_mode_border)); |
@@ -327,7 +339,7 @@ bool handle_ipc_readable(struct swaybar *bar) { | |||
327 | json_object *result = json_tokener_parse(resp->payload); | 339 | json_object *result = json_tokener_parse(resp->payload); |
328 | if (!result) { | 340 | if (!result) { |
329 | free_ipc_response(resp); | 341 | free_ipc_response(resp); |
330 | wlr_log(L_ERROR, "failed to parse payload as json"); | 342 | wlr_log(WLR_ERROR, "failed to parse payload as json"); |
331 | return false; | 343 | return false; |
332 | } | 344 | } |
333 | json_object *json_change, *json_pango_markup; | 345 | json_object *json_change, *json_pango_markup; |
@@ -340,7 +352,7 @@ bool handle_ipc_readable(struct swaybar *bar) { | |||
340 | bar->config->mode = strdup(change); | 352 | bar->config->mode = strdup(change); |
341 | } | 353 | } |
342 | } else { | 354 | } else { |
343 | wlr_log(L_ERROR, "failed to parse response"); | 355 | wlr_log(WLR_ERROR, "failed to parse response"); |
344 | json_object_put(result); | 356 | json_object_put(result); |
345 | free_ipc_response(resp); | 357 | free_ipc_response(resp); |
346 | return false; | 358 | return false; |
diff --git a/swaybar/main.c b/swaybar/main.c index c897e1c9..60e4b37c 100644 --- a/swaybar/main.c +++ b/swaybar/main.c | |||
@@ -75,13 +75,13 @@ int main(int argc, char **argv) { | |||
75 | } | 75 | } |
76 | 76 | ||
77 | if (debug) { | 77 | if (debug) { |
78 | wlr_log_init(L_DEBUG, NULL); | 78 | wlr_log_init(WLR_DEBUG, NULL); |
79 | } else { | 79 | } else { |
80 | wlr_log_init(L_ERROR, NULL); | 80 | wlr_log_init(WLR_ERROR, NULL); |
81 | } | 81 | } |
82 | 82 | ||
83 | if (!bar_id) { | 83 | if (!bar_id) { |
84 | wlr_log(L_ERROR, "No bar_id passed. " | 84 | wlr_log(WLR_ERROR, "No bar_id passed. " |
85 | "Provide --bar_id or let sway start swaybar"); | 85 | "Provide --bar_id or let sway start swaybar"); |
86 | return 1; | 86 | return 1; |
87 | } | 87 | } |
@@ -89,7 +89,7 @@ int main(int argc, char **argv) { | |||
89 | if (!socket_path) { | 89 | if (!socket_path) { |
90 | socket_path = get_socketpath(); | 90 | socket_path = get_socketpath(); |
91 | if (!socket_path) { | 91 | if (!socket_path) { |
92 | wlr_log(L_ERROR, "Unable to retrieve socket path"); | 92 | wlr_log(WLR_ERROR, "Unable to retrieve socket path"); |
93 | return 1; | 93 | return 1; |
94 | } | 94 | } |
95 | } | 95 | } |
diff --git a/swaybar/render.c b/swaybar/render.c index 2ebd338e..d210e25a 100644 --- a/swaybar/render.c +++ b/swaybar/render.c | |||
@@ -109,7 +109,7 @@ static void render_sharp_line(cairo_t *cairo, uint32_t color, | |||
109 | } | 109 | } |
110 | 110 | ||
111 | static void block_hotspot_callback(struct swaybar_output *output, | 111 | static void block_hotspot_callback(struct swaybar_output *output, |
112 | int x, int y, uint32_t button, void *data) { | 112 | int x, int y, enum x11_button button, void *data) { |
113 | struct i3bar_block *block = data; | 113 | struct i3bar_block *block = data; |
114 | struct status_line *status = output->bar->status; | 114 | struct status_line *status = output->bar->status; |
115 | i3bar_block_send_click(status, block, x, y, button); | 115 | i3bar_block_send_click(status, block, x, y, button); |
@@ -349,7 +349,7 @@ static const char *strip_workspace_number(const char *ws_name) { | |||
349 | } | 349 | } |
350 | 350 | ||
351 | static void workspace_hotspot_callback(struct swaybar_output *output, | 351 | static void workspace_hotspot_callback(struct swaybar_output *output, |
352 | int x, int y, uint32_t button, void *data) { | 352 | int x, int y, enum x11_button button, void *data) { |
353 | ipc_send_workspace_command(output->bar, (const char *)data); | 353 | ipc_send_workspace_command(output->bar, (const char *)data); |
354 | } | 354 | } |
355 | 355 | ||
@@ -503,6 +503,9 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) { | |||
503 | output->buffers, | 503 | output->buffers, |
504 | output->width * output->scale, | 504 | output->width * output->scale, |
505 | output->height * output->scale); | 505 | output->height * output->scale); |
506 | if (!output->current_buffer) { | ||
507 | return; | ||
508 | } | ||
506 | cairo_t *shm = output->current_buffer->cairo; | 509 | cairo_t *shm = output->current_buffer->cairo; |
507 | 510 | ||
508 | cairo_save(shm); | 511 | cairo_save(shm); |
diff --git a/swaybar/status_line.c b/swaybar/status_line.c index e0e7414a..bc47580b 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c | |||
@@ -49,14 +49,14 @@ bool status_handle_readable(struct status_line *status) { | |||
49 | json_object *version; | 49 | json_object *version; |
50 | if (json_object_object_get_ex(proto, "version", &version) | 50 | if (json_object_object_get_ex(proto, "version", &version) |
51 | && json_object_get_int(version) == 1) { | 51 | && json_object_get_int(version) == 1) { |
52 | wlr_log(L_DEBUG, "Switched to i3bar protocol."); | 52 | wlr_log(WLR_DEBUG, "Switched to i3bar protocol."); |
53 | status->protocol = PROTOCOL_I3BAR; | 53 | status->protocol = PROTOCOL_I3BAR; |
54 | } | 54 | } |
55 | json_object *click_events; | 55 | json_object *click_events; |
56 | if (json_object_object_get_ex( | 56 | if (json_object_object_get_ex( |
57 | proto, "click_events", &click_events) | 57 | proto, "click_events", &click_events) |
58 | && json_object_get_boolean(click_events)) { | 58 | && json_object_get_boolean(click_events)) { |
59 | wlr_log(L_DEBUG, "Enabled click events."); | 59 | wlr_log(WLR_DEBUG, "Enabled click events."); |
60 | status->i3bar_state.click_events = true; | 60 | status->i3bar_state.click_events = true; |
61 | const char *events_array = "[\n"; | 61 | const char *events_array = "[\n"; |
62 | ssize_t len = strlen(events_array); | 62 | ssize_t len = strlen(events_array); |
@@ -91,7 +91,7 @@ struct status_line *status_line_init(char *cmd) { | |||
91 | int pipe_read_fd[2]; | 91 | int pipe_read_fd[2]; |
92 | int pipe_write_fd[2]; | 92 | int pipe_write_fd[2]; |
93 | if (pipe(pipe_read_fd) != 0 || pipe(pipe_write_fd) != 0) { | 93 | if (pipe(pipe_read_fd) != 0 || pipe(pipe_write_fd) != 0) { |
94 | wlr_log(L_ERROR, "Unable to create pipes for status_command fork"); | 94 | wlr_log(WLR_ERROR, "Unable to create pipes for status_command fork"); |
95 | exit(1); | 95 | exit(1); |
96 | } | 96 | } |
97 | 97 | ||
diff --git a/swaybg/main.c b/swaybg/main.c index 5b6c378c..f8e7e7ef 100644 --- a/swaybg/main.c +++ b/swaybg/main.c | |||
@@ -48,7 +48,7 @@ struct swaybg_state { | |||
48 | bool is_valid_color(const char *color) { | 48 | bool is_valid_color(const char *color) { |
49 | int len = strlen(color); | 49 | int len = strlen(color); |
50 | if (len != 7 || color[0] != '#') { | 50 | if (len != 7 || color[0] != '#') { |
51 | wlr_log(L_ERROR, "%s is not a valid color for swaybg. " | 51 | wlr_log(WLR_ERROR, "%s is not a valid color for swaybg. " |
52 | "Color should be specified as #rrggbb (no alpha).", color); | 52 | "Color should be specified as #rrggbb (no alpha).", color); |
53 | return false; | 53 | return false; |
54 | } | 54 | } |
@@ -68,6 +68,9 @@ static void render_frame(struct swaybg_state *state) { | |||
68 | buffer_height = state->height * state->scale; | 68 | buffer_height = state->height * state->scale; |
69 | state->current_buffer = get_next_buffer(state->shm, | 69 | state->current_buffer = get_next_buffer(state->shm, |
70 | state->buffers, buffer_width, buffer_height); | 70 | state->buffers, buffer_width, buffer_height); |
71 | if (!state->current_buffer) { | ||
72 | return; | ||
73 | } | ||
71 | cairo_t *cairo = state->current_buffer->cairo; | 74 | cairo_t *cairo = state->current_buffer->cairo; |
72 | if (state->args->mode == BACKGROUND_MODE_SOLID_COLOR) { | 75 | if (state->args->mode == BACKGROUND_MODE_SOLID_COLOR) { |
73 | cairo_set_source_u32(cairo, state->context.color); | 76 | cairo_set_source_u32(cairo, state->context.color); |
@@ -185,10 +188,10 @@ int main(int argc, const char **argv) { | |||
185 | struct swaybg_args args = {0}; | 188 | struct swaybg_args args = {0}; |
186 | struct swaybg_state state = {0}; | 189 | struct swaybg_state state = {0}; |
187 | state.args = &args; | 190 | state.args = &args; |
188 | wlr_log_init(L_DEBUG, NULL); | 191 | wlr_log_init(WLR_DEBUG, NULL); |
189 | 192 | ||
190 | if (argc != 4) { | 193 | if (argc != 4) { |
191 | wlr_log(L_ERROR, "Do not run this program manually. " | 194 | wlr_log(WLR_ERROR, "Do not run this program manually. " |
192 | "See man 5 sway and look for output options."); | 195 | "See man 5 sway and look for output options."); |
193 | return 1; | 196 | return 1; |
194 | } | 197 | } |
diff --git a/swayidle/main.c b/swayidle/main.c index 7666578f..678d622f 100644 --- a/swayidle/main.c +++ b/swayidle/main.c | |||
@@ -1,22 +1,21 @@ | |||
1 | #define _XOPEN_SOURCE 500 | 1 | #define _XOPEN_SOURCE 500 |
2 | #include <errno.h> | ||
2 | #include <getopt.h> | 3 | #include <getopt.h> |
3 | #include <signal.h> | ||
4 | #include <pthread.h> | 4 | #include <pthread.h> |
5 | #include <signal.h> | ||
5 | #include <stdio.h> | 6 | #include <stdio.h> |
6 | #include <stdlib.h> | 7 | #include <stdlib.h> |
7 | #include <errno.h> | ||
8 | #include <string.h> | 8 | #include <string.h> |
9 | #include <sys/wait.h> | 9 | #include <sys/wait.h> |
10 | #include <unistd.h> | 10 | #include <unistd.h> |
11 | #include <wayland-client-protocol.h> | 11 | #include <wayland-client-protocol.h> |
12 | #include <wayland-client.h> | 12 | #include <wayland-client.h> |
13 | #include <wayland-server.h> | ||
13 | #include <wayland-util.h> | 14 | #include <wayland-util.h> |
14 | #include <wlr/config.h> | 15 | #include <wlr/config.h> |
15 | #include <wlr/util/log.h> | 16 | #include <wlr/util/log.h> |
16 | #include <wlr/types/wlr_output_layout.h> | ||
17 | #include <wlr/types/wlr_output.h> | ||
18 | #include "idle-client-protocol.h" | ||
19 | #include "config.h" | 17 | #include "config.h" |
18 | #include "idle-client-protocol.h" | ||
20 | #include "list.h" | 19 | #include "list.h" |
21 | #ifdef SWAY_IDLE_HAS_SYSTEMD | 20 | #ifdef SWAY_IDLE_HAS_SYSTEMD |
22 | #include <systemd/sd-bus.h> | 21 | #include <systemd/sd-bus.h> |
@@ -36,7 +35,6 @@ struct swayidle_state { | |||
36 | struct wl_display *display; | 35 | struct wl_display *display; |
37 | struct org_kde_kwin_idle_timeout *idle_timer; | 36 | struct org_kde_kwin_idle_timeout *idle_timer; |
38 | struct org_kde_kwin_idle_timeout *lock_timer; | 37 | struct org_kde_kwin_idle_timeout *lock_timer; |
39 | struct wlr_output_layout *layout; | ||
40 | struct wl_event_loop *event_loop; | 38 | struct wl_event_loop *event_loop; |
41 | list_t *timeout_cmds; | 39 | list_t *timeout_cmds; |
42 | } state; | 40 | } state; |
@@ -59,24 +57,24 @@ static void cmd_exec(void *data) { | |||
59 | return; | 57 | return; |
60 | } | 58 | } |
61 | char *param = (char *)data; | 59 | char *param = (char *)data; |
62 | wlr_log(L_DEBUG, "Cmd exec %s", param); | 60 | wlr_log(WLR_DEBUG, "Cmd exec %s", param); |
63 | pid_t pid = fork(); | 61 | pid_t pid = fork(); |
64 | if (pid == 0) { | 62 | if (pid == 0) { |
65 | pid = fork(); | 63 | pid = fork(); |
66 | if (pid == 0) { | 64 | if (pid == 0) { |
67 | char *const cmd[] = { "sh", "-c", param, NULL, }; | 65 | char *const cmd[] = { "sh", "-c", param, NULL, }; |
68 | execvp(cmd[0], cmd); | 66 | execvp(cmd[0], cmd); |
69 | wlr_log_errno(L_ERROR, "execve failed!"); | 67 | wlr_log_errno(WLR_ERROR, "execve failed!"); |
70 | exit(1); | 68 | exit(1); |
71 | } else if (pid < 0) { | 69 | } else if (pid < 0) { |
72 | wlr_log_errno(L_ERROR, "fork failed"); | 70 | wlr_log_errno(WLR_ERROR, "fork failed"); |
73 | exit(1); | 71 | exit(1); |
74 | } | 72 | } |
75 | exit(0); | 73 | exit(0); |
76 | } else if (pid < 0) { | 74 | } else if (pid < 0) { |
77 | wlr_log_errno(L_ERROR, "fork failed"); | 75 | wlr_log_errno(WLR_ERROR, "fork failed"); |
78 | } else { | 76 | } else { |
79 | wlr_log(L_DEBUG, "Spawned process %s", param); | 77 | wlr_log(WLR_DEBUG, "Spawned process %s", param); |
80 | waitpid(pid, NULL, 0); | 78 | waitpid(pid, NULL, 0); |
81 | } | 79 | } |
82 | } | 80 | } |
@@ -86,7 +84,7 @@ static int lock_fd = -1; | |||
86 | static int ongoing_fd = -1; | 84 | static int ongoing_fd = -1; |
87 | 85 | ||
88 | static int release_lock(void *data) { | 86 | static int release_lock(void *data) { |
89 | wlr_log(L_INFO, "Releasing sleep lock %d", ongoing_fd); | 87 | wlr_log(WLR_INFO, "Releasing sleep lock %d", ongoing_fd); |
90 | if (ongoing_fd >= 0) { | 88 | if (ongoing_fd >= 0) { |
91 | close(ongoing_fd); | 89 | close(ongoing_fd); |
92 | } | 90 | } |
@@ -101,7 +99,7 @@ void acquire_sleep_lock() { | |||
101 | int ret = sd_bus_default_system(&bus); | 99 | int ret = sd_bus_default_system(&bus); |
102 | 100 | ||
103 | if (ret < 0) { | 101 | if (ret < 0) { |
104 | wlr_log(L_ERROR, "Failed to open D-Bus connection: %s", | 102 | wlr_log(WLR_ERROR, "Failed to open D-Bus connection: %s", |
105 | strerror(-ret)); | 103 | strerror(-ret)); |
106 | return; | 104 | return; |
107 | } | 105 | } |
@@ -112,17 +110,17 @@ void acquire_sleep_lock() { | |||
112 | &error, &msg, "ssss", "sleep", "swayidle", | 110 | &error, &msg, "ssss", "sleep", "swayidle", |
113 | "Setup Up Lock Screen", "delay"); | 111 | "Setup Up Lock Screen", "delay"); |
114 | if (ret < 0) { | 112 | if (ret < 0) { |
115 | wlr_log(L_ERROR, "Failed to send Inhibit signal: %s", | 113 | wlr_log(WLR_ERROR, "Failed to send Inhibit signal: %s", |
116 | strerror(-ret)); | 114 | strerror(-ret)); |
117 | } else { | 115 | } else { |
118 | ret = sd_bus_message_read(msg, "h", &lock_fd); | 116 | ret = sd_bus_message_read(msg, "h", &lock_fd); |
119 | if (ret < 0) { | 117 | if (ret < 0) { |
120 | wlr_log(L_ERROR, | 118 | wlr_log(WLR_ERROR, |
121 | "Failed to parse D-Bus response for Inhibit: %s", | 119 | "Failed to parse D-Bus response for Inhibit: %s", |
122 | strerror(-ret)); | 120 | strerror(-ret)); |
123 | } | 121 | } |
124 | } | 122 | } |
125 | wlr_log(L_INFO, "Got sleep lock: %d", lock_fd); | 123 | wlr_log(WLR_INFO, "Got sleep lock: %d", lock_fd); |
126 | } | 124 | } |
127 | 125 | ||
128 | static int prepare_for_sleep(sd_bus_message *msg, void *userdata, | 126 | static int prepare_for_sleep(sd_bus_message *msg, void *userdata, |
@@ -131,10 +129,10 @@ static int prepare_for_sleep(sd_bus_message *msg, void *userdata, | |||
131 | int going_down = 1; | 129 | int going_down = 1; |
132 | int ret = sd_bus_message_read(msg, "b", &going_down); | 130 | int ret = sd_bus_message_read(msg, "b", &going_down); |
133 | if (ret < 0) { | 131 | if (ret < 0) { |
134 | wlr_log(L_ERROR, "Failed to parse D-Bus response for Inhibit: %s", | 132 | wlr_log(WLR_ERROR, "Failed to parse D-Bus response for Inhibit: %s", |
135 | strerror(-ret)); | 133 | strerror(-ret)); |
136 | } | 134 | } |
137 | wlr_log(L_DEBUG, "PrepareForSleep signal received %d", going_down); | 135 | wlr_log(WLR_DEBUG, "PrepareForSleep signal received %d", going_down); |
138 | if (!going_down) { | 136 | if (!going_down) { |
139 | acquire_sleep_lock(); | 137 | acquire_sleep_lock(); |
140 | return 0; | 138 | return 0; |
@@ -151,7 +149,7 @@ static int prepare_for_sleep(sd_bus_message *msg, void *userdata, | |||
151 | wl_event_loop_add_timer(state.event_loop, release_lock, NULL); | 149 | wl_event_loop_add_timer(state.event_loop, release_lock, NULL); |
152 | wl_event_source_timer_update(source, 1000); | 150 | wl_event_source_timer_update(source, 1000); |
153 | } | 151 | } |
154 | wlr_log(L_DEBUG, "Prepare for sleep done"); | 152 | wlr_log(WLR_DEBUG, "Prepare for sleep done"); |
155 | return 0; | 153 | return 0; |
156 | } | 154 | } |
157 | 155 | ||
@@ -165,10 +163,10 @@ static int dbus_event(int fd, uint32_t mask, void *data) { | |||
165 | 163 | ||
166 | void setup_sleep_listener() { | 164 | void setup_sleep_listener() { |
167 | struct sd_bus *bus; | 165 | struct sd_bus *bus; |
168 | 166 | ||
169 | int ret = sd_bus_default_system(&bus); | 167 | int ret = sd_bus_default_system(&bus); |
170 | if (ret < 0) { | 168 | if (ret < 0) { |
171 | wlr_log(L_ERROR, "Failed to open D-Bus connection: %s", | 169 | wlr_log(WLR_ERROR, "Failed to open D-Bus connection: %s", |
172 | strerror(-ret)); | 170 | strerror(-ret)); |
173 | return; | 171 | return; |
174 | } | 172 | } |
@@ -183,7 +181,7 @@ void setup_sleep_listener() { | |||
183 | "/org/freedesktop/login1"); | 181 | "/org/freedesktop/login1"); |
184 | ret = sd_bus_add_match(bus, NULL, str, prepare_for_sleep, NULL); | 182 | ret = sd_bus_add_match(bus, NULL, str, prepare_for_sleep, NULL); |
185 | if (ret < 0) { | 183 | if (ret < 0) { |
186 | wlr_log(L_ERROR, "Failed to add D-Bus match: %s", strerror(-ret)); | 184 | wlr_log(WLR_ERROR, "Failed to add D-Bus match: %s", strerror(-ret)); |
187 | return; | 185 | return; |
188 | } | 186 | } |
189 | acquire_sleep_lock(); | 187 | acquire_sleep_lock(); |
@@ -214,7 +212,7 @@ static const struct wl_registry_listener registry_listener = { | |||
214 | 212 | ||
215 | static void handle_idle(void *data, struct org_kde_kwin_idle_timeout *timer) { | 213 | static void handle_idle(void *data, struct org_kde_kwin_idle_timeout *timer) { |
216 | struct swayidle_timeout_cmd *cmd = data; | 214 | struct swayidle_timeout_cmd *cmd = data; |
217 | wlr_log(L_DEBUG, "idle state"); | 215 | wlr_log(WLR_DEBUG, "idle state"); |
218 | if (cmd && cmd->idle_cmd && cmd->idle_cmd->callback) { | 216 | if (cmd && cmd->idle_cmd && cmd->idle_cmd->callback) { |
219 | cmd->idle_cmd->callback(cmd->idle_cmd->param); | 217 | cmd->idle_cmd->callback(cmd->idle_cmd->param); |
220 | } | 218 | } |
@@ -222,7 +220,7 @@ static void handle_idle(void *data, struct org_kde_kwin_idle_timeout *timer) { | |||
222 | 220 | ||
223 | static void handle_resume(void *data, struct org_kde_kwin_idle_timeout *timer) { | 221 | static void handle_resume(void *data, struct org_kde_kwin_idle_timeout *timer) { |
224 | struct swayidle_timeout_cmd *cmd = data; | 222 | struct swayidle_timeout_cmd *cmd = data; |
225 | wlr_log(L_DEBUG, "active state"); | 223 | wlr_log(WLR_DEBUG, "active state"); |
226 | if (cmd && cmd->resume_cmd && cmd->resume_cmd->callback) { | 224 | if (cmd && cmd->resume_cmd && cmd->resume_cmd->callback) { |
227 | cmd->resume_cmd->callback(cmd->resume_cmd->param); | 225 | cmd->resume_cmd->callback(cmd->resume_cmd->param); |
228 | } | 226 | } |
@@ -235,12 +233,12 @@ static const struct org_kde_kwin_idle_timeout_listener idle_timer_listener = { | |||
235 | 233 | ||
236 | struct swayidle_cmd *parse_command(int argc, char **argv) { | 234 | struct swayidle_cmd *parse_command(int argc, char **argv) { |
237 | if (argc < 1) { | 235 | if (argc < 1) { |
238 | wlr_log(L_ERROR, "Too few parameters for command in parse_command"); | 236 | wlr_log(WLR_ERROR, "Too few parameters for command in parse_command"); |
239 | return NULL; | 237 | return NULL; |
240 | } | 238 | } |
241 | 239 | ||
242 | struct swayidle_cmd *cmd = calloc(1, sizeof(struct swayidle_cmd)); | 240 | struct swayidle_cmd *cmd = calloc(1, sizeof(struct swayidle_cmd)); |
243 | wlr_log(L_DEBUG, "Command: %s", argv[0]); | 241 | wlr_log(WLR_DEBUG, "Command: %s", argv[0]); |
244 | cmd->callback = cmd_exec; | 242 | cmd->callback = cmd_exec; |
245 | cmd->param = argv[0]; | 243 | cmd->param = argv[0]; |
246 | return cmd; | 244 | return cmd; |
@@ -248,7 +246,7 @@ struct swayidle_cmd *parse_command(int argc, char **argv) { | |||
248 | 246 | ||
249 | int parse_timeout(int argc, char **argv) { | 247 | int parse_timeout(int argc, char **argv) { |
250 | if (argc < 3) { | 248 | if (argc < 3) { |
251 | wlr_log(L_ERROR, "Too few parameters to timeout command. " | 249 | wlr_log(WLR_ERROR, "Too few parameters to timeout command. " |
252 | "Usage: timeout <seconds> <command>"); | 250 | "Usage: timeout <seconds> <command>"); |
253 | exit(-1); | 251 | exit(-1); |
254 | } | 252 | } |
@@ -256,7 +254,7 @@ int parse_timeout(int argc, char **argv) { | |||
256 | char *endptr; | 254 | char *endptr; |
257 | int seconds = strtoul(argv[1], &endptr, 10); | 255 | int seconds = strtoul(argv[1], &endptr, 10); |
258 | if (errno != 0 || *endptr != '\0') { | 256 | if (errno != 0 || *endptr != '\0') { |
259 | wlr_log(L_ERROR, "Invalid timeout parameter '%s', it should be a " | 257 | wlr_log(WLR_ERROR, "Invalid timeout parameter '%s', it should be a " |
260 | "numeric value representing seconds", optarg); | 258 | "numeric value representing seconds", optarg); |
261 | exit(-1); | 259 | exit(-1); |
262 | } | 260 | } |
@@ -264,13 +262,13 @@ int parse_timeout(int argc, char **argv) { | |||
264 | calloc(1, sizeof(struct swayidle_timeout_cmd)); | 262 | calloc(1, sizeof(struct swayidle_timeout_cmd)); |
265 | cmd->timeout = seconds * 1000; | 263 | cmd->timeout = seconds * 1000; |
266 | 264 | ||
267 | wlr_log(L_DEBUG, "Register idle timeout at %d ms", cmd->timeout); | 265 | wlr_log(WLR_DEBUG, "Register idle timeout at %d ms", cmd->timeout); |
268 | wlr_log(L_DEBUG, "Setup idle"); | 266 | wlr_log(WLR_DEBUG, "Setup idle"); |
269 | cmd->idle_cmd = parse_command(argc - 2, &argv[2]); | 267 | cmd->idle_cmd = parse_command(argc - 2, &argv[2]); |
270 | 268 | ||
271 | int result = 3; | 269 | int result = 3; |
272 | if (argc >= 5 && !strcmp("resume", argv[3])) { | 270 | if (argc >= 5 && !strcmp("resume", argv[3])) { |
273 | wlr_log(L_DEBUG, "Setup resume"); | 271 | wlr_log(WLR_DEBUG, "Setup resume"); |
274 | cmd->resume_cmd = parse_command(argc - 4, &argv[4]); | 272 | cmd->resume_cmd = parse_command(argc - 4, &argv[4]); |
275 | result = 5; | 273 | result = 5; |
276 | } | 274 | } |
@@ -280,14 +278,14 @@ int parse_timeout(int argc, char **argv) { | |||
280 | 278 | ||
281 | int parse_sleep(int argc, char **argv) { | 279 | int parse_sleep(int argc, char **argv) { |
282 | if (argc < 2) { | 280 | if (argc < 2) { |
283 | wlr_log(L_ERROR, "Too few parameters to before-sleep command. " | 281 | wlr_log(WLR_ERROR, "Too few parameters to before-sleep command. " |
284 | "Usage: before-sleep <command>"); | 282 | "Usage: before-sleep <command>"); |
285 | exit(-1); | 283 | exit(-1); |
286 | } | 284 | } |
287 | 285 | ||
288 | lock_cmd = parse_command(argc - 1, &argv[1]); | 286 | lock_cmd = parse_command(argc - 1, &argv[1]); |
289 | if (lock_cmd) { | 287 | if (lock_cmd) { |
290 | wlr_log(L_DEBUG, "Setup sleep lock: %s", lock_cmd->param); | 288 | wlr_log(WLR_DEBUG, "Setup sleep lock: %s", lock_cmd->param); |
291 | } | 289 | } |
292 | 290 | ||
293 | return 2; | 291 | return 2; |
@@ -314,10 +312,10 @@ int parse_args(int argc, char *argv[]) { | |||
314 | } | 312 | } |
315 | 313 | ||
316 | if (debug) { | 314 | if (debug) { |
317 | wlr_log_init(L_DEBUG, NULL); | 315 | wlr_log_init(WLR_DEBUG, NULL); |
318 | wlr_log(L_DEBUG, "Loglevel debug"); | 316 | wlr_log(WLR_DEBUG, "Loglevel debug"); |
319 | } else { | 317 | } else { |
320 | wlr_log_init(L_INFO, NULL); | 318 | wlr_log_init(WLR_INFO, NULL); |
321 | } | 319 | } |
322 | 320 | ||
323 | 321 | ||
@@ -326,13 +324,13 @@ int parse_args(int argc, char *argv[]) { | |||
326 | int i = optind; | 324 | int i = optind; |
327 | while (i < argc) { | 325 | while (i < argc) { |
328 | if (!strcmp("timeout", argv[i])) { | 326 | if (!strcmp("timeout", argv[i])) { |
329 | wlr_log(L_DEBUG, "Got timeout"); | 327 | wlr_log(WLR_DEBUG, "Got timeout"); |
330 | i += parse_timeout(argc - i, &argv[i]); | 328 | i += parse_timeout(argc - i, &argv[i]); |
331 | } else if (!strcmp("before-sleep", argv[i])) { | 329 | } else if (!strcmp("before-sleep", argv[i])) { |
332 | wlr_log(L_DEBUG, "Got before-sleep"); | 330 | wlr_log(WLR_DEBUG, "Got before-sleep"); |
333 | i += parse_sleep(argc - i, &argv[i]); | 331 | i += parse_sleep(argc - i, &argv[i]); |
334 | } else { | 332 | } else { |
335 | wlr_log(L_ERROR, "Unsupported command '%s'", argv[i]); | 333 | wlr_log(WLR_ERROR, "Unsupported command '%s'", argv[i]); |
336 | exit(-1); | 334 | exit(-1); |
337 | } | 335 | } |
338 | } | 336 | } |
@@ -358,16 +356,16 @@ static int display_event(int fd, uint32_t mask, void *data) { | |||
358 | sway_terminate(0); | 356 | sway_terminate(0); |
359 | } | 357 | } |
360 | if (wl_display_dispatch(state.display) < 0) { | 358 | if (wl_display_dispatch(state.display) < 0) { |
361 | wlr_log_errno(L_ERROR, "wl_display_dispatch failed, exiting"); | 359 | wlr_log_errno(WLR_ERROR, "wl_display_dispatch failed, exiting"); |
362 | sway_terminate(0); | 360 | sway_terminate(0); |
363 | }; | 361 | } |
364 | return 0; | 362 | return 0; |
365 | } | 363 | } |
366 | 364 | ||
367 | void register_idle_timeout(void *item) { | 365 | void register_idle_timeout(void *item) { |
368 | struct swayidle_timeout_cmd *cmd = item; | 366 | struct swayidle_timeout_cmd *cmd = item; |
369 | if (cmd == NULL || !cmd->timeout) { | 367 | if (cmd == NULL || !cmd->timeout) { |
370 | wlr_log(L_ERROR, "Invalid idle cmd, will not register"); | 368 | wlr_log(WLR_ERROR, "Invalid idle cmd, will not register"); |
371 | return; | 369 | return; |
372 | } | 370 | } |
373 | state.idle_timer = | 371 | state.idle_timer = |
@@ -376,7 +374,7 @@ void register_idle_timeout(void *item) { | |||
376 | org_kde_kwin_idle_timeout_add_listener(state.idle_timer, | 374 | org_kde_kwin_idle_timeout_add_listener(state.idle_timer, |
377 | &idle_timer_listener, cmd); | 375 | &idle_timer_listener, cmd); |
378 | } else { | 376 | } else { |
379 | wlr_log(L_ERROR, "Could not create idle timer"); | 377 | wlr_log(WLR_ERROR, "Could not create idle timer"); |
380 | } | 378 | } |
381 | } | 379 | } |
382 | 380 | ||
@@ -390,22 +388,21 @@ int main(int argc, char *argv[]) { | |||
390 | 388 | ||
391 | state.display = wl_display_connect(NULL); | 389 | state.display = wl_display_connect(NULL); |
392 | if (state.display == NULL) { | 390 | if (state.display == NULL) { |
393 | wlr_log(L_ERROR, "Failed to create display"); | 391 | wlr_log(WLR_ERROR, "Failed to create display"); |
394 | return -3; | 392 | return -3; |
395 | } | 393 | } |
396 | 394 | ||
397 | struct wl_registry *registry = wl_display_get_registry(state.display); | 395 | struct wl_registry *registry = wl_display_get_registry(state.display); |
398 | wl_registry_add_listener(registry, ®istry_listener, NULL); | 396 | wl_registry_add_listener(registry, ®istry_listener, NULL); |
399 | wl_display_roundtrip(state.display); | 397 | wl_display_roundtrip(state.display); |
400 | state.layout = wlr_output_layout_create(); | ||
401 | state.event_loop = wl_event_loop_create(); | 398 | state.event_loop = wl_event_loop_create(); |
402 | 399 | ||
403 | if (idle_manager == NULL) { | 400 | if (idle_manager == NULL) { |
404 | wlr_log(L_ERROR, "Display doesn't support idle protocol"); | 401 | wlr_log(WLR_ERROR, "Display doesn't support idle protocol"); |
405 | return -4; | 402 | return -4; |
406 | } | 403 | } |
407 | if (seat == NULL) { | 404 | if (seat == NULL) { |
408 | wlr_log(L_ERROR, "Seat error"); | 405 | wlr_log(WLR_ERROR, "Seat error"); |
409 | return -5; | 406 | return -5; |
410 | } | 407 | } |
411 | 408 | ||
@@ -417,7 +414,7 @@ int main(int argc, char *argv[]) { | |||
417 | } | 414 | } |
418 | #endif | 415 | #endif |
419 | if (!should_run) { | 416 | if (!should_run) { |
420 | wlr_log(L_INFO, "No command specified! Nothing to do, will exit"); | 417 | wlr_log(WLR_INFO, "No command specified! Nothing to do, will exit"); |
421 | sway_terminate(0); | 418 | sway_terminate(0); |
422 | } | 419 | } |
423 | list_foreach(state.timeout_cmds, register_idle_timeout); | 420 | list_foreach(state.timeout_cmds, register_idle_timeout); |
diff --git a/swaylock/main.c b/swaylock/main.c index 73c2b5d6..ae5b86b9 100644 --- a/swaylock/main.c +++ b/swaylock/main.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include "pool-buffer.h" | 21 | #include "pool-buffer.h" |
22 | #include "cairo.h" | 22 | #include "cairo.h" |
23 | #include "log.h" | 23 | #include "log.h" |
24 | #include "readline.h" | ||
24 | #include "stringop.h" | 25 | #include "stringop.h" |
25 | #include "util.h" | 26 | #include "util.h" |
26 | #include "wlr-input-inhibitor-unstable-v1-client-protocol.h" | 27 | #include "wlr-input-inhibitor-unstable-v1-client-protocol.h" |
@@ -34,7 +35,7 @@ void sway_terminate(int exit_code) { | |||
34 | static void daemonize() { | 35 | static void daemonize() { |
35 | int fds[2]; | 36 | int fds[2]; |
36 | if (pipe(fds) != 0) { | 37 | if (pipe(fds) != 0) { |
37 | wlr_log(L_ERROR, "Failed to pipe"); | 38 | wlr_log(WLR_ERROR, "Failed to pipe"); |
38 | exit(1); | 39 | exit(1); |
39 | } | 40 | } |
40 | if (fork() == 0) { | 41 | if (fork() == 0) { |
@@ -58,7 +59,7 @@ static void daemonize() { | |||
58 | close(fds[1]); | 59 | close(fds[1]); |
59 | uint8_t success; | 60 | uint8_t success; |
60 | if (read(fds[0], &success, 1) != 1 || !success) { | 61 | if (read(fds[0], &success, 1) != 1 || !success) { |
61 | wlr_log(L_ERROR, "Failed to daemonize"); | 62 | wlr_log(WLR_ERROR, "Failed to daemonize"); |
62 | exit(1); | 63 | exit(1); |
63 | } | 64 | } |
64 | close(fds[0]); | 65 | close(fds[0]); |
@@ -89,7 +90,7 @@ static bool surface_is_opaque(struct swaylock_surface *surface) { | |||
89 | if (surface->image) { | 90 | if (surface->image) { |
90 | return cairo_surface_get_content(surface->image) == CAIRO_CONTENT_COLOR; | 91 | return cairo_surface_get_content(surface->image) == CAIRO_CONTENT_COLOR; |
91 | } | 92 | } |
92 | return (surface->state->args.color & 0xff) == 0xff; | 93 | return (surface->state->args.colors.background & 0xff) == 0xff; |
93 | } | 94 | } |
94 | 95 | ||
95 | static void create_layer_surface(struct swaylock_surface *surface) { | 96 | static void create_layer_surface(struct swaylock_surface *surface) { |
@@ -238,7 +239,7 @@ static void handle_xdg_output_logical_position(void *data, | |||
238 | 239 | ||
239 | static void handle_xdg_output_name(void *data, struct zxdg_output_v1 *output, | 240 | static void handle_xdg_output_name(void *data, struct zxdg_output_v1 *output, |
240 | const char *name) { | 241 | const char *name) { |
241 | wlr_log(L_DEBUG, "output name is %s", name); | 242 | wlr_log(WLR_DEBUG, "output name is %s", name); |
242 | struct swaylock_surface *surface = data; | 243 | struct swaylock_surface *surface = data; |
243 | surface->xdg_output = output; | 244 | surface->xdg_output = output; |
244 | surface->output_name = strdup(name); | 245 | surface->output_name = strdup(name); |
@@ -354,10 +355,10 @@ static void load_image(char *arg, struct swaylock_state *state) { | |||
354 | } | 355 | } |
355 | if (exists) { | 356 | if (exists) { |
356 | if (image->output_name) { | 357 | if (image->output_name) { |
357 | wlr_log(L_ERROR, "Multiple images defined for output %s", | 358 | wlr_log(WLR_ERROR, "Multiple images defined for output %s", |
358 | image->output_name); | 359 | image->output_name); |
359 | } else { | 360 | } else { |
360 | wlr_log(L_ERROR, "Multiple default images defined"); | 361 | wlr_log(WLR_ERROR, "Multiple default images defined"); |
361 | } | 362 | } |
362 | } | 363 | } |
363 | 364 | ||
@@ -377,71 +378,232 @@ static void load_image(char *arg, struct swaylock_state *state) { | |||
377 | } | 378 | } |
378 | wl_list_insert(&state->images, &image->link); | 379 | wl_list_insert(&state->images, &image->link); |
379 | state->args.mode = BACKGROUND_MODE_FILL; | 380 | state->args.mode = BACKGROUND_MODE_FILL; |
380 | wlr_log(L_DEBUG, "Loaded image %s for output %s", | 381 | wlr_log(WLR_DEBUG, "Loaded image %s for output %s", |
381 | image->path, image->output_name ? image->output_name : "*"); | 382 | image->path, image->output_name ? image->output_name : "*"); |
382 | } | 383 | } |
383 | 384 | ||
384 | static struct swaylock_state state; | 385 | static void set_default_colors(struct swaylock_colors *colors) { |
386 | colors->background = 0xFFFFFFFF; | ||
387 | colors->bs_highlight = 0xDB3300FF; | ||
388 | colors->key_highlight = 0x33DB00FF; | ||
389 | colors->separator = 0x000000FF; | ||
390 | colors->inside = (struct swaylock_colorset){ | ||
391 | .input = 0x000000C0, | ||
392 | .cleared = 0xE5A445C0, | ||
393 | .verifying = 0x0072FFC0, | ||
394 | .wrong = 0xFA0000C0, | ||
395 | }; | ||
396 | colors->line = (struct swaylock_colorset){ | ||
397 | .input = 0x000000FF, | ||
398 | .cleared = 0x000000FF, | ||
399 | .verifying = 0x000000FF, | ||
400 | .wrong = 0x000000FF, | ||
401 | }; | ||
402 | colors->ring = (struct swaylock_colorset){ | ||
403 | .input = 0x337D00FF, | ||
404 | .cleared = 0xE5A445FF, | ||
405 | .verifying = 0x3300FFFF, | ||
406 | .wrong = 0x7D3300FF, | ||
407 | }; | ||
408 | colors->text = (struct swaylock_colorset){ | ||
409 | .input = 0xE5A445FF, | ||
410 | .cleared = 0x000000FF, | ||
411 | .verifying = 0x000000FF, | ||
412 | .wrong = 0x000000FF, | ||
413 | }; | ||
414 | } | ||
415 | |||
416 | enum line_mode { | ||
417 | LM_LINE, | ||
418 | LM_INSIDE, | ||
419 | LM_RING, | ||
420 | }; | ||
421 | |||
422 | static int parse_options(int argc, char **argv, struct swaylock_state *state, | ||
423 | enum line_mode *line_mode) { | ||
424 | enum long_option_codes { | ||
425 | LO_BS_HL_COLOR = 256, | ||
426 | LO_FONT, | ||
427 | LO_IND_RADIUS, | ||
428 | LO_IND_THICKNESS, | ||
429 | LO_INSIDE_COLOR, | ||
430 | LO_INSIDE_CLEAR_COLOR, | ||
431 | LO_INSIDE_VER_COLOR, | ||
432 | LO_INSIDE_WRONG_COLOR, | ||
433 | LO_KEY_HL_COLOR, | ||
434 | LO_LINE_COLOR, | ||
435 | LO_LINE_CLEAR_COLOR, | ||
436 | LO_LINE_VER_COLOR, | ||
437 | LO_LINE_WRONG_COLOR, | ||
438 | LO_RING_COLOR, | ||
439 | LO_RING_CLEAR_COLOR, | ||
440 | LO_RING_VER_COLOR, | ||
441 | LO_RING_WRONG_COLOR, | ||
442 | LO_SEP_COLOR, | ||
443 | LO_TEXT_COLOR, | ||
444 | LO_TEXT_CLEAR_COLOR, | ||
445 | LO_TEXT_VER_COLOR, | ||
446 | LO_TEXT_WRONG_COLOR, | ||
447 | }; | ||
385 | 448 | ||
386 | int main(int argc, char **argv) { | ||
387 | static struct option long_options[] = { | 449 | static struct option long_options[] = { |
388 | {"help", no_argument, NULL, 'h'}, | 450 | {"config", required_argument, NULL, 'C'}, |
389 | {"color", required_argument, NULL, 'c'}, | 451 | {"color", required_argument, NULL, 'c'}, |
452 | {"ignore-empty-password", no_argument, NULL, 'e'}, | ||
453 | {"daemonize", no_argument, NULL, 'f'}, | ||
454 | {"help", no_argument, NULL, 'h'}, | ||
390 | {"image", required_argument, NULL, 'i'}, | 455 | {"image", required_argument, NULL, 'i'}, |
456 | {"line-uses-inside", no_argument, NULL, 'n'}, | ||
457 | {"socket", required_argument, NULL, 'p'}, | ||
458 | {"line-uses-ring", no_argument, NULL, 'r'}, | ||
391 | {"scaling", required_argument, NULL, 's'}, | 459 | {"scaling", required_argument, NULL, 's'}, |
392 | {"tiling", no_argument, NULL, 't'}, | 460 | {"tiling", no_argument, NULL, 't'}, |
393 | {"version", no_argument, NULL, 'v'}, | ||
394 | {"socket", required_argument, NULL, 'p'}, | ||
395 | {"no-unlock-indicator", no_argument, NULL, 'u'}, | 461 | {"no-unlock-indicator", no_argument, NULL, 'u'}, |
396 | {"daemonize", no_argument, NULL, 'f'}, | 462 | {"version", no_argument, NULL, 'v'}, |
463 | {"bs-hl-color", required_argument, NULL, LO_BS_HL_COLOR}, | ||
464 | {"font", required_argument, NULL, LO_FONT}, | ||
465 | {"indicator-radius", required_argument, NULL, LO_IND_RADIUS}, | ||
466 | {"indicator-thickness", required_argument, NULL, LO_IND_THICKNESS}, | ||
467 | {"inside-color", required_argument, NULL, LO_INSIDE_COLOR}, | ||
468 | {"inside-clear-color", required_argument, NULL, LO_INSIDE_CLEAR_COLOR}, | ||
469 | {"inside-ver-color", required_argument, NULL, LO_INSIDE_VER_COLOR}, | ||
470 | {"inside-wrong-color", required_argument, NULL, LO_INSIDE_WRONG_COLOR}, | ||
471 | {"key-hl-color", required_argument, NULL, LO_KEY_HL_COLOR}, | ||
472 | {"line-color", required_argument, NULL, LO_LINE_COLOR}, | ||
473 | {"line-clear-color", required_argument, NULL, LO_LINE_CLEAR_COLOR}, | ||
474 | {"line-ver-color", required_argument, NULL, LO_LINE_VER_COLOR}, | ||
475 | {"line-wrong-color", required_argument, NULL, LO_LINE_WRONG_COLOR}, | ||
476 | {"ring-color", required_argument, NULL, LO_RING_COLOR}, | ||
477 | {"ring-clear-color", required_argument, NULL, LO_RING_CLEAR_COLOR}, | ||
478 | {"ring-ver-color", required_argument, NULL, LO_RING_VER_COLOR}, | ||
479 | {"ring-wrong-color", required_argument, NULL, LO_RING_WRONG_COLOR}, | ||
480 | {"separator-color", required_argument, NULL, LO_SEP_COLOR}, | ||
481 | {"text-color", required_argument, NULL, LO_TEXT_COLOR}, | ||
482 | {"text-clear-color", required_argument, NULL, LO_TEXT_CLEAR_COLOR}, | ||
483 | {"text-ver-color", required_argument, NULL, LO_TEXT_VER_COLOR}, | ||
484 | {"text-wrong-color", required_argument, NULL, LO_TEXT_WRONG_COLOR}, | ||
397 | {0, 0, 0, 0} | 485 | {0, 0, 0, 0} |
398 | }; | 486 | }; |
399 | 487 | ||
400 | const char usage[] = | 488 | const char usage[] = |
401 | "Usage: swaylock [options...]\n" | 489 | "Usage: swaylock [options...]\n" |
402 | "\n" | 490 | "\n" |
403 | " -h, --help Show help message and quit.\n" | 491 | " -C, --config <config_file> " |
404 | " -c, --color <rrggbb[aa]> Turn the screen into the given color instead of white.\n" | 492 | "Path to the config file.\n" |
405 | " -s, --scaling Scaling mode: stretch, fill, fit, center, tile.\n" | 493 | " -c, --color <color> " |
406 | " -t, --tiling Same as --scaling=tile.\n" | 494 | "Turn the screen into the given color instead of white.\n" |
407 | " -v, --version Show the version number and quit.\n" | 495 | " -e, --ignore-empty-password " |
408 | " -i, --image [<output>:]<path> Display the given image.\n" | 496 | "When an empty password is provided, do not validate it.\n" |
409 | " -u, --no-unlock-indicator Disable the unlock indicator.\n" | 497 | " -f, --daemonize " |
410 | " -f, --daemonize Detach from the controlling terminal after locking.\n"; | 498 | "Detach from the controlling terminal after locking.\n" |
411 | 499 | " -h, --help " | |
412 | state.args = (struct swaylock_args){ | 500 | "Show help message and quit.\n" |
413 | .mode = BACKGROUND_MODE_SOLID_COLOR, | 501 | " -i, --image [<output>:]<path> " |
414 | .color = 0xFFFFFFFF, | 502 | "Display the given image.\n" |
415 | .show_indicator = true, | 503 | " -s, --scaling <mode> " |
416 | }; | 504 | "Scaling mode: stretch, fill, fit, center, tile.\n" |
417 | wl_list_init(&state.images); | 505 | " -t, --tiling " |
418 | 506 | "Same as --scaling=tile.\n" | |
419 | wlr_log_init(L_DEBUG, NULL); | 507 | " -u, --no-unlock-indicator " |
508 | "Disable the unlock indicator.\n" | ||
509 | " -v, --version " | ||
510 | "Show the version number and quit.\n" | ||
511 | " --bs-hl-color <color> " | ||
512 | "Sets the color of backspace highlight segments.\n" | ||
513 | " --font <font> " | ||
514 | "Sets the font of the text.\n" | ||
515 | " --indicator-radius <radius> " | ||
516 | "Sets the indicator radius.\n" | ||
517 | " --indicator-thickness <thick> " | ||
518 | "Sets the indicator thickness.\n" | ||
519 | " --inside-color <color> " | ||
520 | "Sets the color of the inside of the indicator.\n" | ||
521 | " --inside-clear-color <color> " | ||
522 | "Sets the color of the inside of the indicator when cleared.\n" | ||
523 | " --inside-ver-color <color> " | ||
524 | "Sets the color of the inside of the indicator when verifying.\n" | ||
525 | " --inside-wrong-color <color> " | ||
526 | "Sets the color of the inside of the indicator when invalid.\n" | ||
527 | " --key-hl-color <color> " | ||
528 | "Sets the color of the key press highlight segments.\n" | ||
529 | " --line-color <color> " | ||
530 | "Sets the color of the line between the inside and ring.\n" | ||
531 | " --line-clear-color <color> " | ||
532 | "Sets the color of the line between the inside and ring when " | ||
533 | "cleared.\n" | ||
534 | " --line-ver-color <color> " | ||
535 | "Sets the color of the line between the inside and ring when " | ||
536 | "verifying.\n" | ||
537 | " --line-wrong-color <color> " | ||
538 | "Sets the color of the line between the inside and ring when " | ||
539 | "invalid.\n" | ||
540 | " -n, --line-uses-inside " | ||
541 | "Use the inside color for the line between the inside and ring.\n" | ||
542 | " -r, --line-uses-ring " | ||
543 | "Use the ring color for the line between the inside and ring.\n" | ||
544 | " --ring-color <color> " | ||
545 | "Sets the color of the ring of the indicator.\n" | ||
546 | " --ring-clear-color <color> " | ||
547 | "Sets the color of the ring of the indicator when cleared.\n" | ||
548 | " --ring-ver-color <color> " | ||
549 | "Sets the color of the ring of the indicator when verifying.\n" | ||
550 | " --ring-wrong-color <color> " | ||
551 | "Sets the color of the ring of the indicator when invalid.\n" | ||
552 | " --separator-color <color> " | ||
553 | "Sets the color of the lines that separate highlight segments.\n" | ||
554 | " --text-color <color> " | ||
555 | "Sets the color of the text.\n" | ||
556 | " --text-clear-color <color> " | ||
557 | "Sets the color of the text when cleared.\n" | ||
558 | " --text-ver-color <color> " | ||
559 | "Sets the color of the text when verifying.\n" | ||
560 | " --text-wrong-color <color> " | ||
561 | "Sets the color of the text when invalid.\n" | ||
562 | "\n" | ||
563 | "All <color> options are of the form <rrggbb[aa]>.\n"; | ||
420 | 564 | ||
421 | int c; | 565 | int c; |
566 | optind = 1; | ||
422 | while (1) { | 567 | while (1) { |
423 | int option_index = 0; | 568 | int opt_idx = 0; |
424 | c = getopt_long(argc, argv, "hc:i:s:tvuf", long_options, &option_index); | 569 | c = getopt_long(argc, argv, "c:efhi:nrs:tuvC:", long_options, &opt_idx); |
425 | if (c == -1) { | 570 | if (c == -1) { |
426 | break; | 571 | break; |
427 | } | 572 | } |
428 | switch (c) { | 573 | switch (c) { |
429 | case 'c': { | 574 | case 'C': |
430 | state.args.color = parse_color(optarg); | 575 | // Config file. This will have already been handled so just ignore. |
431 | state.args.mode = BACKGROUND_MODE_SOLID_COLOR; | 576 | break; |
577 | case 'c': | ||
578 | state->args.colors.background = parse_color(optarg); | ||
579 | state->args.mode = BACKGROUND_MODE_SOLID_COLOR; | ||
580 | break; | ||
581 | case 'e': | ||
582 | state->args.ignore_empty = true; | ||
583 | break; | ||
584 | case 'f': | ||
585 | state->args.daemonize = true; | ||
432 | break; | 586 | break; |
433 | } | ||
434 | case 'i': | 587 | case 'i': |
435 | load_image(optarg, &state); | 588 | load_image(optarg, state); |
589 | break; | ||
590 | case 'n': | ||
591 | *line_mode = LM_INSIDE; | ||
592 | break; | ||
593 | case 'r': | ||
594 | *line_mode = LM_RING; | ||
436 | break; | 595 | break; |
437 | case 's': | 596 | case 's': |
438 | state.args.mode = parse_background_mode(optarg); | 597 | state->args.mode = parse_background_mode(optarg); |
439 | if (state.args.mode == BACKGROUND_MODE_INVALID) { | 598 | if (state->args.mode == BACKGROUND_MODE_INVALID) { |
440 | return 1; | 599 | return 1; |
441 | } | 600 | } |
442 | break; | 601 | break; |
443 | case 't': | 602 | case 't': |
444 | state.args.mode = BACKGROUND_MODE_TILE; | 603 | state->args.mode = BACKGROUND_MODE_TILE; |
604 | break; | ||
605 | case 'u': | ||
606 | state->args.show_indicator = false; | ||
445 | break; | 607 | break; |
446 | case 'v': | 608 | case 'v': |
447 | #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE | 609 | #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE |
@@ -451,11 +613,72 @@ int main(int argc, char **argv) { | |||
451 | fprintf(stdout, "version unknown\n"); | 613 | fprintf(stdout, "version unknown\n"); |
452 | #endif | 614 | #endif |
453 | return 0; | 615 | return 0; |
454 | case 'u': | 616 | case LO_BS_HL_COLOR: |
455 | state.args.show_indicator = false; | 617 | state->args.colors.bs_highlight = parse_color(optarg); |
456 | break; | 618 | break; |
457 | case 'f': | 619 | case LO_FONT: |
458 | state.args.daemonize = true; | 620 | free(state->args.font); |
621 | state->args.font = strdup(optarg); | ||
622 | break; | ||
623 | case LO_IND_RADIUS: | ||
624 | state->args.radius = strtol(optarg, NULL, 0); | ||
625 | break; | ||
626 | case LO_IND_THICKNESS: | ||
627 | state->args.thickness = strtol(optarg, NULL, 0); | ||
628 | break; | ||
629 | case LO_INSIDE_COLOR: | ||
630 | state->args.colors.inside.input = parse_color(optarg); | ||
631 | break; | ||
632 | case LO_INSIDE_CLEAR_COLOR: | ||
633 | state->args.colors.inside.cleared = parse_color(optarg); | ||
634 | break; | ||
635 | case LO_INSIDE_VER_COLOR: | ||
636 | state->args.colors.inside.verifying = parse_color(optarg); | ||
637 | break; | ||
638 | case LO_INSIDE_WRONG_COLOR: | ||
639 | state->args.colors.inside.wrong = parse_color(optarg); | ||
640 | break; | ||
641 | case LO_KEY_HL_COLOR: | ||
642 | state->args.colors.key_highlight = parse_color(optarg); | ||
643 | break; | ||
644 | case LO_LINE_COLOR: | ||
645 | state->args.colors.line.input = parse_color(optarg); | ||
646 | break; | ||
647 | case LO_LINE_CLEAR_COLOR: | ||
648 | state->args.colors.line.cleared = parse_color(optarg); | ||
649 | break; | ||
650 | case LO_LINE_VER_COLOR: | ||
651 | state->args.colors.line.verifying = parse_color(optarg); | ||
652 | break; | ||
653 | case LO_LINE_WRONG_COLOR: | ||
654 | state->args.colors.line.wrong = parse_color(optarg); | ||
655 | break; | ||
656 | case LO_RING_COLOR: | ||
657 | state->args.colors.ring.input = parse_color(optarg); | ||
658 | break; | ||
659 | case LO_RING_CLEAR_COLOR: | ||
660 | state->args.colors.ring.cleared = parse_color(optarg); | ||
661 | break; | ||
662 | case LO_RING_VER_COLOR: | ||
663 | state->args.colors.ring.verifying = parse_color(optarg); | ||
664 | break; | ||
665 | case LO_RING_WRONG_COLOR: | ||
666 | state->args.colors.ring.wrong = parse_color(optarg); | ||
667 | break; | ||
668 | case LO_SEP_COLOR: | ||
669 | state->args.colors.separator = parse_color(optarg); | ||
670 | break; | ||
671 | case LO_TEXT_COLOR: | ||
672 | state->args.colors.text.input = parse_color(optarg); | ||
673 | break; | ||
674 | case LO_TEXT_CLEAR_COLOR: | ||
675 | state->args.colors.text.cleared = parse_color(optarg); | ||
676 | break; | ||
677 | case LO_TEXT_VER_COLOR: | ||
678 | state->args.colors.text.verifying = parse_color(optarg); | ||
679 | break; | ||
680 | case LO_TEXT_WRONG_COLOR: | ||
681 | state->args.colors.text.wrong = parse_color(optarg); | ||
459 | break; | 682 | break; |
460 | default: | 683 | default: |
461 | fprintf(stderr, "%s", usage); | 684 | fprintf(stderr, "%s", usage); |
@@ -463,6 +686,149 @@ int main(int argc, char **argv) { | |||
463 | } | 686 | } |
464 | } | 687 | } |
465 | 688 | ||
689 | return 0; | ||
690 | } | ||
691 | |||
692 | static bool file_exists(const char *path) { | ||
693 | return path && access(path, R_OK) != -1; | ||
694 | } | ||
695 | |||
696 | static char *get_config_path(void) { | ||
697 | static const char *config_paths[] = { | ||
698 | "$HOME/.swaylock/config", | ||
699 | "$XDG_CONFIG_HOME/swaylock/config", | ||
700 | SYSCONFDIR "/swaylock/config", | ||
701 | }; | ||
702 | |||
703 | if (!getenv("XDG_CONFIG_HOME")) { | ||
704 | char *home = getenv("HOME"); | ||
705 | char *config_home = malloc(strlen(home) + strlen("/.config") + 1); | ||
706 | if (!config_home) { | ||
707 | wlr_log(WLR_ERROR, "Unable to allocate $HOME/.config"); | ||
708 | } else { | ||
709 | strcpy(config_home, home); | ||
710 | strcat(config_home, "/.config"); | ||
711 | setenv("XDG_CONFIG_HOME", config_home, 1); | ||
712 | wlr_log(WLR_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home); | ||
713 | free(config_home); | ||
714 | } | ||
715 | } | ||
716 | |||
717 | wordexp_t p; | ||
718 | char *path; | ||
719 | for (size_t i = 0; i < sizeof(config_paths) / sizeof(char *); ++i) { | ||
720 | if (wordexp(config_paths[i], &p, 0) == 0) { | ||
721 | path = strdup(p.we_wordv[0]); | ||
722 | wordfree(&p); | ||
723 | if (file_exists(path)) { | ||
724 | return path; | ||
725 | } | ||
726 | free(path); | ||
727 | } | ||
728 | } | ||
729 | |||
730 | return NULL; | ||
731 | } | ||
732 | |||
733 | static int load_config(char *path, struct swaylock_state *state, | ||
734 | enum line_mode *line_mode) { | ||
735 | FILE *config = fopen(path, "r"); | ||
736 | if (!config) { | ||
737 | wlr_log(WLR_ERROR, "Failed to read config. Running without it."); | ||
738 | return 0; | ||
739 | } | ||
740 | char *line; | ||
741 | int line_number = 0; | ||
742 | while (!feof(config)) { | ||
743 | line = read_line(config); | ||
744 | if (!line) { | ||
745 | continue; | ||
746 | } | ||
747 | |||
748 | line_number++; | ||
749 | if (line[0] == '#') { | ||
750 | free(line); | ||
751 | continue; | ||
752 | } | ||
753 | if (strlen(line) == 0) { | ||
754 | free(line); | ||
755 | continue; | ||
756 | } | ||
757 | |||
758 | wlr_log(WLR_DEBUG, "Config Line #%d: %s", line_number, line); | ||
759 | char flag[strlen(line) + 3]; | ||
760 | sprintf(flag, "--%s", line); | ||
761 | char *argv[] = {"swaylock", flag}; | ||
762 | int result = parse_options(2, argv, state, line_mode); | ||
763 | if (result != 0) { | ||
764 | free(line); | ||
765 | fclose(config); | ||
766 | return result; | ||
767 | } | ||
768 | free(line); | ||
769 | } | ||
770 | fclose(config); | ||
771 | return 0; | ||
772 | } | ||
773 | |||
774 | static struct swaylock_state state; | ||
775 | |||
776 | int main(int argc, char **argv) { | ||
777 | enum line_mode line_mode = LM_LINE; | ||
778 | state.args = (struct swaylock_args){ | ||
779 | .mode = BACKGROUND_MODE_SOLID_COLOR, | ||
780 | .font = strdup("sans-serif"), | ||
781 | .radius = 50, | ||
782 | .thickness = 10, | ||
783 | .ignore_empty = false, | ||
784 | .show_indicator = true, | ||
785 | }; | ||
786 | wl_list_init(&state.images); | ||
787 | set_default_colors(&state.args.colors); | ||
788 | |||
789 | wlr_log_init(WLR_DEBUG, NULL); | ||
790 | |||
791 | char *config_path = NULL; | ||
792 | static struct option long_options[] = { | ||
793 | {"config", required_argument, NULL, 'C'}, | ||
794 | {0, 0, 0, 0}, | ||
795 | }; | ||
796 | while (1) { | ||
797 | int c = getopt_long(argc, argv, "C:", long_options, NULL); | ||
798 | if (c == -1) { | ||
799 | break; | ||
800 | } else if (c == 'C') { | ||
801 | config_path = strdup(optarg); | ||
802 | break; | ||
803 | } | ||
804 | } | ||
805 | if (!config_path) { | ||
806 | config_path = get_config_path(); | ||
807 | } | ||
808 | |||
809 | if (config_path) { | ||
810 | wlr_log(WLR_DEBUG, "Found config at %s", config_path); | ||
811 | int config_status = load_config(config_path, &state, &line_mode); | ||
812 | free(config_path); | ||
813 | if (config_status != 0) { | ||
814 | return config_status; | ||
815 | } | ||
816 | } | ||
817 | |||
818 | if (argc > 1) { | ||
819 | wlr_log(WLR_DEBUG, "Parsing CLI Args"); | ||
820 | int result = parse_options(argc, argv, &state, &line_mode); | ||
821 | if (result != 0) { | ||
822 | return result; | ||
823 | } | ||
824 | } | ||
825 | |||
826 | if (line_mode == LM_INSIDE) { | ||
827 | state.args.colors.line = state.args.colors.inside; | ||
828 | } else if (line_mode == LM_RING) { | ||
829 | state.args.colors.line = state.args.colors.ring; | ||
830 | } | ||
831 | |||
466 | #ifdef __linux__ | 832 | #ifdef __linux__ |
467 | // Most non-linux platforms require root to mlock() | 833 | // Most non-linux platforms require root to mlock() |
468 | if (mlock(state.password.buffer, sizeof(state.password.buffer)) != 0) { | 834 | if (mlock(state.password.buffer, sizeof(state.password.buffer)) != 0) { |
@@ -480,13 +846,13 @@ int main(int argc, char **argv) { | |||
480 | wl_display_roundtrip(state.display); | 846 | wl_display_roundtrip(state.display); |
481 | assert(state.compositor && state.layer_shell && state.shm); | 847 | assert(state.compositor && state.layer_shell && state.shm); |
482 | if (!state.input_inhibit_manager) { | 848 | if (!state.input_inhibit_manager) { |
483 | wlr_log(L_ERROR, "Compositor does not support the input inhibitor " | 849 | wlr_log(WLR_ERROR, "Compositor does not support the input inhibitor " |
484 | "protocol, refusing to run insecurely"); | 850 | "protocol, refusing to run insecurely"); |
485 | return 1; | 851 | return 1; |
486 | } | 852 | } |
487 | 853 | ||
488 | if (wl_list_empty(&state.surfaces)) { | 854 | if (wl_list_empty(&state.surfaces)) { |
489 | wlr_log(L_DEBUG, "Exiting - no outputs to show on."); | 855 | wlr_log(WLR_DEBUG, "Exiting - no outputs to show on."); |
490 | return 0; | 856 | return 0; |
491 | } | 857 | } |
492 | 858 | ||
@@ -502,7 +868,7 @@ int main(int argc, char **argv) { | |||
502 | } | 868 | } |
503 | wl_display_roundtrip(state.display); | 869 | wl_display_roundtrip(state.display); |
504 | } else { | 870 | } else { |
505 | wlr_log(L_INFO, "Compositor does not support zxdg output manager, " | 871 | wlr_log(WLR_INFO, "Compositor does not support zxdg output manager, " |
506 | "images assigned to named outputs will not work"); | 872 | "images assigned to named outputs will not work"); |
507 | } | 873 | } |
508 | 874 | ||
@@ -520,5 +886,7 @@ int main(int argc, char **argv) { | |||
520 | while (wl_display_dispatch(state.display) != -1 && state.run_display) { | 886 | while (wl_display_dispatch(state.display) != -1 && state.run_display) { |
521 | // This space intentionally left blank | 887 | // This space intentionally left blank |
522 | } | 888 | } |
889 | |||
890 | free(state.args.font); | ||
523 | return 0; | 891 | return 0; |
524 | } | 892 | } |
diff --git a/swaylock/password.c b/swaylock/password.c index d844ec98..7c686b34 100644 --- a/swaylock/password.c +++ b/swaylock/password.c | |||
@@ -53,15 +53,15 @@ static bool attempt_password(struct swaylock_password *pw) { | |||
53 | // TODO: only call pam_start once. keep the same handle the whole time | 53 | // TODO: only call pam_start once. keep the same handle the whole time |
54 | if ((pam_err = pam_start("swaylock", username, | 54 | if ((pam_err = pam_start("swaylock", username, |
55 | &local_conversation, &local_auth_handle)) != PAM_SUCCESS) { | 55 | &local_conversation, &local_auth_handle)) != PAM_SUCCESS) { |
56 | wlr_log(L_ERROR, "PAM returned error %d", pam_err); | 56 | wlr_log(WLR_ERROR, "PAM returned error %d", pam_err); |
57 | } | 57 | } |
58 | if ((pam_err = pam_authenticate(local_auth_handle, 0)) != PAM_SUCCESS) { | 58 | if ((pam_err = pam_authenticate(local_auth_handle, 0)) != PAM_SUCCESS) { |
59 | wlr_log(L_ERROR, "pam_authenticate failed"); | 59 | wlr_log(WLR_ERROR, "pam_authenticate failed"); |
60 | goto fail; | 60 | goto fail; |
61 | } | 61 | } |
62 | // TODO: only call pam_end once we succeed at authing. refresh tokens beforehand | 62 | // TODO: only call pam_end once we succeed at authing. refresh tokens beforehand |
63 | if ((pam_err = pam_end(local_auth_handle, pam_err)) != PAM_SUCCESS) { | 63 | if ((pam_err = pam_end(local_auth_handle, pam_err)) != PAM_SUCCESS) { |
64 | wlr_log(L_ERROR, "pam_end failed"); | 64 | wlr_log(WLR_ERROR, "pam_end failed"); |
65 | goto fail; | 65 | goto fail; |
66 | } | 66 | } |
67 | clear_password_buffer(pw); | 67 | clear_password_buffer(pw); |
@@ -95,6 +95,10 @@ void swaylock_handle_key(struct swaylock_state *state, | |||
95 | switch (keysym) { | 95 | switch (keysym) { |
96 | case XKB_KEY_KP_Enter: /* fallthrough */ | 96 | case XKB_KEY_KP_Enter: /* fallthrough */ |
97 | case XKB_KEY_Return: | 97 | case XKB_KEY_Return: |
98 | if (state->args.ignore_empty && state->password.len == 0) { | ||
99 | break; | ||
100 | } | ||
101 | |||
98 | state->auth_state = AUTH_STATE_VALIDATING; | 102 | state->auth_state = AUTH_STATE_VALIDATING; |
99 | damage_state(state); | 103 | damage_state(state); |
100 | while (wl_display_dispatch(state->display) != -1 && state->run_display) { | 104 | while (wl_display_dispatch(state->display) != -1 && state->run_display) { |
diff --git a/swaylock/render.c b/swaylock/render.c index ea23d0d8..66c55965 100644 --- a/swaylock/render.c +++ b/swaylock/render.c | |||
@@ -7,11 +7,22 @@ | |||
7 | #include "swaylock/swaylock.h" | 7 | #include "swaylock/swaylock.h" |
8 | 8 | ||
9 | #define M_PI 3.14159265358979323846 | 9 | #define M_PI 3.14159265358979323846 |
10 | const int ARC_RADIUS = 50; | ||
11 | const int ARC_THICKNESS = 10; | ||
12 | const float TYPE_INDICATOR_RANGE = M_PI / 3.0f; | 10 | const float TYPE_INDICATOR_RANGE = M_PI / 3.0f; |
13 | const float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f; | 11 | const float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f; |
14 | 12 | ||
13 | static void set_color_for_state(cairo_t *cairo, struct swaylock_state *state, | ||
14 | struct swaylock_colorset *colorset) { | ||
15 | if (state->auth_state == AUTH_STATE_VALIDATING) { | ||
16 | cairo_set_source_u32(cairo, colorset->verifying); | ||
17 | } else if (state->auth_state == AUTH_STATE_INVALID) { | ||
18 | cairo_set_source_u32(cairo, colorset->wrong); | ||
19 | } else if (state->auth_state == AUTH_STATE_CLEAR) { | ||
20 | cairo_set_source_u32(cairo, colorset->cleared); | ||
21 | } else { | ||
22 | cairo_set_source_u32(cairo, colorset->input); | ||
23 | } | ||
24 | } | ||
25 | |||
15 | void render_frame(struct swaylock_surface *surface) { | 26 | void render_frame(struct swaylock_surface *surface) { |
16 | struct swaylock_state *state = surface->state; | 27 | struct swaylock_state *state = surface->state; |
17 | 28 | ||
@@ -33,7 +44,7 @@ void render_frame(struct swaylock_surface *surface) { | |||
33 | cairo_save(cairo); | 44 | cairo_save(cairo); |
34 | cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); | 45 | cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); |
35 | if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR || !surface->image) { | 46 | if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR || !surface->image) { |
36 | cairo_set_source_u32(cairo, state->args.color); | 47 | cairo_set_source_u32(cairo, state->args.colors.background); |
37 | cairo_paint(cairo); | 48 | cairo_paint(cairo); |
38 | } else { | 49 | } else { |
39 | render_background_image(cairo, surface->image, | 50 | render_background_image(cairo, surface->image, |
@@ -42,49 +53,25 @@ void render_frame(struct swaylock_surface *surface) { | |||
42 | cairo_restore(cairo); | 53 | cairo_restore(cairo); |
43 | cairo_identity_matrix(cairo); | 54 | cairo_identity_matrix(cairo); |
44 | 55 | ||
45 | int arc_radius = ARC_RADIUS * surface->scale; | 56 | int arc_radius = state->args.radius * surface->scale; |
46 | int arc_thickness = ARC_THICKNESS * surface->scale; | 57 | int arc_thickness = state->args.thickness * surface->scale; |
47 | float type_indicator_border_thickness = | 58 | float type_indicator_border_thickness = |
48 | TYPE_INDICATOR_BORDER_THICKNESS * surface->scale; | 59 | TYPE_INDICATOR_BORDER_THICKNESS * surface->scale; |
49 | 60 | ||
50 | if (state->args.show_indicator && state->auth_state != AUTH_STATE_IDLE) { | 61 | if (state->args.show_indicator && state->auth_state != AUTH_STATE_IDLE) { |
51 | // Draw circle | 62 | // Draw circle |
52 | cairo_set_line_width(cairo, arc_thickness); | 63 | cairo_set_line_width(cairo, arc_thickness); |
53 | cairo_arc(cairo, buffer_width / 2, buffer_height / 2, arc_radius, 0, 2 * M_PI); | 64 | cairo_arc(cairo, buffer_width / 2, buffer_height / 2, arc_radius, |
54 | switch (state->auth_state) { | 65 | 0, 2 * M_PI); |
55 | case AUTH_STATE_INPUT: | 66 | set_color_for_state(cairo, state, &state->args.colors.inside); |
56 | case AUTH_STATE_INPUT_NOP: | 67 | cairo_fill_preserve(cairo); |
57 | case AUTH_STATE_BACKSPACE: { | 68 | set_color_for_state(cairo, state, &state->args.colors.ring); |
58 | cairo_set_source_rgba(cairo, 0, 0, 0, 0.75); | 69 | cairo_stroke(cairo); |
59 | cairo_fill_preserve(cairo); | ||
60 | cairo_set_source_rgb(cairo, 51.0 / 255, 125.0 / 255, 0); | ||
61 | cairo_stroke(cairo); | ||
62 | } break; | ||
63 | case AUTH_STATE_VALIDATING: { | ||
64 | cairo_set_source_rgba(cairo, 0, 114.0 / 255, 255.0 / 255, 0.75); | ||
65 | cairo_fill_preserve(cairo); | ||
66 | cairo_set_source_rgb(cairo, 51.0 / 255, 0, 250.0 / 255); | ||
67 | cairo_stroke(cairo); | ||
68 | } break; | ||
69 | case AUTH_STATE_INVALID: { | ||
70 | cairo_set_source_rgba(cairo, 250.0 / 255, 0, 0, 0.75); | ||
71 | cairo_fill_preserve(cairo); | ||
72 | cairo_set_source_rgb(cairo, 125.0 / 255, 51.0 / 255, 0); | ||
73 | cairo_stroke(cairo); | ||
74 | } break; | ||
75 | case AUTH_STATE_CLEAR: { | ||
76 | cairo_set_source_rgba(cairo, 229.0/255, 164.0/255, 69.0/255, 0.75); | ||
77 | cairo_fill_preserve(cairo); | ||
78 | cairo_set_source_rgb(cairo, 229.0/255, 164.0/255, 69.0/255); | ||
79 | cairo_stroke(cairo); | ||
80 | } break; | ||
81 | default: break; | ||
82 | } | ||
83 | 70 | ||
84 | // Draw a message | 71 | // Draw a message |
85 | char *text = NULL; | 72 | char *text = NULL; |
86 | cairo_set_source_rgb(cairo, 0, 0, 0); | 73 | set_color_for_state(cairo, state, &state->args.colors.text); |
87 | cairo_select_font_face(cairo, "sans-serif", | 74 | cairo_select_font_face(cairo, state->args.font, |
88 | CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); | 75 | CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); |
89 | cairo_set_font_size(cairo, arc_radius / 3.0f); | 76 | cairo_set_font_size(cairo, arc_radius / 3.0f); |
90 | switch (state->auth_state) { | 77 | switch (state->auth_state) { |
@@ -101,9 +88,10 @@ void render_frame(struct swaylock_surface *surface) { | |||
101 | case AUTH_STATE_INPUT_NOP: | 88 | case AUTH_STATE_INPUT_NOP: |
102 | if (state->xkb.caps_lock) { | 89 | if (state->xkb.caps_lock) { |
103 | text = "Caps Lock"; | 90 | text = "Caps Lock"; |
104 | cairo_set_source_rgb(cairo, 229.0/255, 164.0/255, 69.0/255); | ||
105 | } | 91 | } |
106 | default: break; | 92 | break; |
93 | default: | ||
94 | break; | ||
107 | } | 95 | } |
108 | 96 | ||
109 | if (text) { | 97 | if (text) { |
@@ -131,14 +119,14 @@ void render_frame(struct swaylock_surface *surface) { | |||
131 | arc_radius, highlight_start, | 119 | arc_radius, highlight_start, |
132 | highlight_start + TYPE_INDICATOR_RANGE); | 120 | highlight_start + TYPE_INDICATOR_RANGE); |
133 | if (state->auth_state == AUTH_STATE_INPUT) { | 121 | if (state->auth_state == AUTH_STATE_INPUT) { |
134 | cairo_set_source_rgb(cairo, 51.0 / 255, 219.0 / 255, 0); | 122 | cairo_set_source_u32(cairo, state->args.colors.key_highlight); |
135 | } else { | 123 | } else { |
136 | cairo_set_source_rgb(cairo, 219.0 / 255, 51.0 / 255, 0); | 124 | cairo_set_source_u32(cairo, state->args.colors.bs_highlight); |
137 | } | 125 | } |
138 | cairo_stroke(cairo); | 126 | cairo_stroke(cairo); |
139 | 127 | ||
140 | // Draw borders | 128 | // Draw borders |
141 | cairo_set_source_rgb(cairo, 0, 0, 0); | 129 | cairo_set_source_u32(cairo, state->args.colors.separator); |
142 | cairo_arc(cairo, buffer_width / 2, buffer_height / 2, | 130 | cairo_arc(cairo, buffer_width / 2, buffer_height / 2, |
143 | arc_radius, highlight_start, | 131 | arc_radius, highlight_start, |
144 | highlight_start + type_indicator_border_thickness); | 132 | highlight_start + type_indicator_border_thickness); |
@@ -152,7 +140,7 @@ void render_frame(struct swaylock_surface *surface) { | |||
152 | } | 140 | } |
153 | 141 | ||
154 | // Draw inner + outer border of the circle | 142 | // Draw inner + outer border of the circle |
155 | cairo_set_source_rgb(cairo, 0, 0, 0); | 143 | set_color_for_state(cairo, state, &state->args.colors.line); |
156 | cairo_set_line_width(cairo, 2.0 * surface->scale); | 144 | cairo_set_line_width(cairo, 2.0 * surface->scale); |
157 | cairo_arc(cairo, buffer_width / 2, buffer_height / 2, | 145 | cairo_arc(cairo, buffer_width / 2, buffer_height / 2, |
158 | arc_radius - arc_thickness / 2, 0, 2 * M_PI); | 146 | arc_radius - arc_thickness / 2, 0, 2 * M_PI); |
diff --git a/swaylock/seat.c b/swaylock/seat.c index 6c66d220..c2630d87 100644 --- a/swaylock/seat.c +++ b/swaylock/seat.c | |||
@@ -12,13 +12,13 @@ static void keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, | |||
12 | struct swaylock_state *state = data; | 12 | struct swaylock_state *state = data; |
13 | if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { | 13 | if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { |
14 | close(fd); | 14 | close(fd); |
15 | wlr_log(L_ERROR, "Unknown keymap format %d, aborting", format); | 15 | wlr_log(WLR_ERROR, "Unknown keymap format %d, aborting", format); |
16 | exit(1); | 16 | exit(1); |
17 | } | 17 | } |
18 | char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); | 18 | char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); |
19 | if (map_shm == MAP_FAILED) { | 19 | if (map_shm == MAP_FAILED) { |
20 | close(fd); | 20 | close(fd); |
21 | wlr_log(L_ERROR, "Unable to initialize keymap shm, aborting"); | 21 | wlr_log(WLR_ERROR, "Unable to initialize keymap shm, aborting"); |
22 | exit(1); | 22 | exit(1); |
23 | } | 23 | } |
24 | struct xkb_keymap *keymap = xkb_keymap_new_from_string( | 24 | struct xkb_keymap *keymap = xkb_keymap_new_from_string( |
diff --git a/swaylock/swaylock.1.scd b/swaylock/swaylock.1.scd index 1b3366f0..3107124f 100644 --- a/swaylock/swaylock.1.scd +++ b/swaylock/swaylock.1.scd | |||
@@ -12,23 +12,34 @@ Locks your Wayland session. | |||
12 | 12 | ||
13 | # OPTIONS | 13 | # OPTIONS |
14 | 14 | ||
15 | *-h, --help* | 15 | *-C, --config* <path> |
16 | Show help message and quit. | 16 | The config file to use. By default, the following paths are checked: |
17 | _$HOME/.swaylock/config_, _$XDG\_CONFIG\_HOME/swaylock/config_, and | ||
18 | _SYSCONFDIR/swaylock/config_. All flags aside from this one are valid | ||
19 | options in the configuration file using the format _long-option=value_. | ||
20 | For options such as _ignore-empty-password_, just supply the _long-option_. | ||
21 | All leading dashes should be omitted and the equals sign is required for | ||
22 | flags that take an argument. | ||
17 | 23 | ||
18 | *-c, --color* <rrggbb[aa]> | 24 | *-c, --color* <rrggbb[aa]> |
19 | Turn the screen into the given color. If -i is used, this sets the | 25 | Turn the screen into the given color. If -i is used, this sets the |
20 | background of the image to the given color. Defaults to white (FFFFFF), or | 26 | background of the image to the given color. Defaults to white (FFFFFF), or |
21 | transparent (00000000) if an image is in use. | 27 | transparent (00000000) if an image is in use. |
22 | 28 | ||
29 | *-e, --ignore-empty-password* | ||
30 | When an empty password is provided by the user, do not validate it. | ||
31 | |||
23 | *-f, --daemonize* | 32 | *-f, --daemonize* |
24 | Fork into the background after spawning. Note: this is the default behavior | 33 | Detach from the controlling terminal after locking. |
25 | of i3lock. | 34 | |
35 | *-h, --help* | ||
36 | Show help message and quit. | ||
26 | 37 | ||
27 | *-i, --image* [<output>:]<path> | 38 | *-i, --image* [<output>:]<path> |
28 | Display the given image, optionally only on the given output. Use -c to set | 39 | Display the given image, optionally only on the given output. Use -c to set |
29 | a background color. | 40 | a background color. |
30 | 41 | ||
31 | *--scaling* | 42 | *-s, --scaling* |
32 | Scaling mode for images: _stretch_, _fill_, _fit_, _center_, or _tile_. | 43 | Scaling mode for images: _stretch_, _fill_, _fit_, _center_, or _tile_. |
33 | 44 | ||
34 | *-t, --tiling* | 45 | *-t, --tiling* |
@@ -37,37 +48,57 @@ Locks your Wayland session. | |||
37 | *-u, --no-unlock-indicator* | 48 | *-u, --no-unlock-indicator* |
38 | Disable the unlock indicator. | 49 | Disable the unlock indicator. |
39 | 50 | ||
40 | *-f, --daemonize* | ||
41 | Detach from the controlling terminal after locking. | ||
42 | |||
43 | *-v, --version* | 51 | *-v, --version* |
44 | Show the version number and quit. | 52 | Show the version number and quit. |
45 | 53 | ||
46 | # APPEARANCE | 54 | # APPEARANCE |
47 | 55 | ||
48 | *--bshlcolor* <rrggbb[aa]> | 56 | *--bs-hl-color* <rrggbb[aa]> |
49 | Sets the color of backspace highlight segments. | 57 | Sets the color of backspace highlight segments. |
50 | 58 | ||
51 | *--font* <font> | 59 | *--font* <font> |
52 | Sets the font of the text inside the indicator. | 60 | Sets the font of the text inside the indicator. |
53 | 61 | ||
54 | *--insidecolor* <rrggbb[aa]> | 62 | *--indicator-radius* <radius> |
63 | Sets the radius of the indicator to _radius_ pixels. The default value is | ||
64 | 50. | ||
65 | |||
66 | *--indicator-thickness* <thickness> | ||
67 | Sets the thickness of the indicator to _thickness_ pixels. The default value | ||
68 | is 10. | ||
69 | |||
70 | *--inside-color* <rrggbb[aa]> | ||
55 | Sets the color of the inside of the indicator when typing or idle. | 71 | Sets the color of the inside of the indicator when typing or idle. |
56 | 72 | ||
57 | *--insidevercolor* <rrggbb[aa]> | 73 | *--inside-clear-color* <rrggbb[aa]> |
74 | Sets the color of the inside of the indicator when cleared. | ||
75 | |||
76 | *--inside-ver-color* <rrggbb[aa]> | ||
58 | Sets the color of the inside of the indicator when verifying. | 77 | Sets the color of the inside of the indicator when verifying. |
59 | 78 | ||
60 | *--insidewrongcolor* <rrggbb[aa]> | 79 | *--inside-wrong-color* <rrggbb[aa]> |
61 | Sets the color of the inside of the indicator when invalid. | 80 | Sets the color of the inside of the indicator when invalid. |
62 | 81 | ||
63 | *--keyhlcolor* <rrggbb[aa]> | 82 | *--key-hl-color* <rrggbb[aa]> |
64 | Sets the color of keypress highlight segments. | 83 | Sets the color of key press highlight segments. |
84 | |||
85 | *--line-color* <rrggbb[aa]> | ||
86 | Sets the color of the lines that separate the inside and outside of the | ||
87 | indicator when typing or idle. | ||
88 | |||
89 | *--line-clear-color* <rrggbb[aa]> | ||
90 | Sets the color of the lines that separate the inside and outside of the | ||
91 | indicator when cleared. | ||
92 | |||
93 | *--line-ver-color* <rrggbb[aa]> | ||
94 | Sets the color of the lines that separate the inside and outside of the | ||
95 | indicator when verifying. | ||
65 | 96 | ||
66 | *--linecolor* <rrggbb[aa]> | 97 | *--line-wrong-color* <rrggbb[aa]> |
67 | Sets the color of the lines that separate the inside and outside of the | 98 | Sets the color of the lines that separate the inside and outside of the |
68 | indicator. | 99 | indicator when invalid. |
69 | 100 | ||
70 | *-s, --line-uses-inside* | 101 | *-n, --line-uses-inside* |
71 | Use the color of the inside of the indicator for the line separating the | 102 | Use the color of the inside of the indicator for the line separating the |
72 | inside and outside of the indicator. | 103 | inside and outside of the indicator. |
73 | 104 | ||
@@ -75,28 +106,32 @@ Locks your Wayland session. | |||
75 | Use the outer ring's color for the line separating the inside and outside of | 106 | Use the outer ring's color for the line separating the inside and outside of |
76 | the indicator. | 107 | the indicator. |
77 | 108 | ||
78 | *--ringcolor* <rrggbb[aa]> | 109 | *--ring-color* <rrggbb[aa]> |
79 | Sets the color of the outside of the indicator when typing or idle. | 110 | Sets the color of the outside of the indicator when typing or idle. |
80 | 111 | ||
81 | *--ringvercolor* <rrggbb[aa]> | 112 | *--ring-clear-color* <rrggbb[aa]> |
113 | Sets the color of the outside of the indicator when cleared. | ||
114 | |||
115 | *--ring-ver-color* <rrggbb[aa]> | ||
82 | Sets the color of the outside of the indicator when verifying. | 116 | Sets the color of the outside of the indicator when verifying. |
83 | 117 | ||
84 | *--ringwrongcolor* <rrggbb[aa]> | 118 | *--ring-wrong-color* <rrggbb[aa]> |
85 | Sets the color of the outside of the indicator when invalid. | 119 | Sets the color of the outside of the indicator when invalid. |
86 | 120 | ||
87 | *--separatorcolor* <rrggbb[aa]> | 121 | *--separator-color* <rrggbb[aa]> |
88 | Sets the color of the lines that seperate highlight segments. | 122 | Sets the color of the lines that separate highlight segments. |
89 | 123 | ||
90 | *--textcolor* <rrggbb[aa]> | 124 | *--text-color* <rrggbb[aa]> |
91 | Sets the color of the text inside the indicator. | 125 | Sets the color of the text inside the indicator when typing or idle. |
92 | 126 | ||
93 | *--indicator-radius* <radius> | 127 | *--text-clear-color* <rrggbb[aa]> |
94 | Sets the radius of the indicator to _radius_ pixels. The default value is | 128 | Sets the color of the text inside the indicator when cleared. |
95 | 50. | ||
96 | 129 | ||
97 | *--indicator-thickness* <thickness> | 130 | *--text-ver-color* <rrggbb[aa]> |
98 | Sets the thickness of the indicator to _thickness_ pixels. The default value | 131 | Sets the color of the text inside the indicator when verifying. |
99 | is 10. | 132 | |
133 | *--text-wrong-color* <rrggbb[aa]> | ||
134 | Sets the color of the text inside the indicator when invalid. | ||
100 | 135 | ||
101 | # AUTHORS | 136 | # AUTHORS |
102 | 137 | ||
diff --git a/swaymsg/main.c b/swaymsg/main.c index 4283bf00..c4141ca5 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c | |||
@@ -240,44 +240,17 @@ static void pretty_print_version(json_object *v) { | |||
240 | printf("sway version %s\n", json_object_get_string(ver)); | 240 | printf("sway version %s\n", json_object_get_string(ver)); |
241 | } | 241 | } |
242 | 242 | ||
243 | static void pretty_print_clipboard(json_object *v) { | 243 | static void pretty_print_config(json_object *c) { |
244 | if (success(v, true)) { | 244 | json_object *config; |
245 | if (json_object_is_type(v, json_type_array)) { | 245 | json_object_object_get_ex(c, "config", &config); |
246 | for (size_t i = 0; i < json_object_array_length(v); ++i) { | 246 | printf("%s\n", json_object_get_string(config)); |
247 | json_object *o = json_object_array_get_idx(v, i); | ||
248 | printf("%s\n", json_object_get_string(o)); | ||
249 | } | ||
250 | } else { | ||
251 | // NOTE: could be extended to print all received types | ||
252 | // instead just the first one when sways ipc server | ||
253 | // supports it | ||
254 | struct json_object_iterator iter = json_object_iter_begin(v); | ||
255 | struct json_object_iterator end = json_object_iter_end(v); | ||
256 | if (!json_object_iter_equal(&iter, &end)) { | ||
257 | json_object *obj = json_object_iter_peek_value(&iter); | ||
258 | if (success(obj, false)) { | ||
259 | json_object *content; | ||
260 | json_object_object_get_ex(obj, "content", &content); | ||
261 | printf("%s\n", json_object_get_string(content)); | ||
262 | } else { | ||
263 | json_object *error; | ||
264 | json_object_object_get_ex(obj, "error", &error); | ||
265 | printf("Error: %s\n", json_object_get_string(error)); | ||
266 | } | ||
267 | } | ||
268 | } | ||
269 | } else { | ||
270 | json_object *error; | ||
271 | json_object_object_get_ex(v, "error", &error); | ||
272 | printf("Error: %s\n", json_object_get_string(error)); | ||
273 | } | ||
274 | } | 247 | } |
275 | 248 | ||
276 | static void pretty_print(int type, json_object *resp) { | 249 | static void pretty_print(int type, json_object *resp) { |
277 | if (type != IPC_COMMAND && type != IPC_GET_WORKSPACES && | 250 | if (type != IPC_COMMAND && type != IPC_GET_WORKSPACES && |
278 | type != IPC_GET_INPUTS && type != IPC_GET_OUTPUTS && | 251 | type != IPC_GET_INPUTS && type != IPC_GET_OUTPUTS && |
279 | type != IPC_GET_VERSION && type != IPC_GET_CLIPBOARD && | 252 | type != IPC_GET_VERSION && type != IPC_GET_SEATS && |
280 | type != IPC_GET_SEATS) { | 253 | type != IPC_GET_CONFIG) { |
281 | printf("%s\n", json_object_to_json_string_ext(resp, | 254 | printf("%s\n", json_object_to_json_string_ext(resp, |
282 | JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED)); | 255 | JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED)); |
283 | return; | 256 | return; |
@@ -288,8 +261,8 @@ static void pretty_print(int type, json_object *resp) { | |||
288 | return; | 261 | return; |
289 | } | 262 | } |
290 | 263 | ||
291 | if (type == IPC_GET_CLIPBOARD) { | 264 | if (type == IPC_GET_CONFIG) { |
292 | pretty_print_clipboard(resp); | 265 | pretty_print_config(resp); |
293 | return; | 266 | return; |
294 | } | 267 | } |
295 | 268 | ||
@@ -323,7 +296,7 @@ int main(int argc, char **argv) { | |||
323 | char *socket_path = NULL; | 296 | char *socket_path = NULL; |
324 | char *cmdtype = NULL; | 297 | char *cmdtype = NULL; |
325 | 298 | ||
326 | wlr_log_init(L_INFO, NULL); | 299 | wlr_log_init(WLR_INFO, NULL); |
327 | 300 | ||
328 | static struct option long_options[] = { | 301 | static struct option long_options[] = { |
329 | {"help", no_argument, NULL, 'h'}, | 302 | {"help", no_argument, NULL, 'h'}, |
@@ -407,8 +380,10 @@ int main(int argc, char **argv) { | |||
407 | type = IPC_GET_BAR_CONFIG; | 380 | type = IPC_GET_BAR_CONFIG; |
408 | } else if (strcasecmp(cmdtype, "get_version") == 0) { | 381 | } else if (strcasecmp(cmdtype, "get_version") == 0) { |
409 | type = IPC_GET_VERSION; | 382 | type = IPC_GET_VERSION; |
410 | } else if (strcasecmp(cmdtype, "get_clipboard") == 0) { | 383 | } else if (strcasecmp(cmdtype, "get_binding_modes") == 0) { |
411 | type = IPC_GET_CLIPBOARD; | 384 | type = IPC_GET_BINDING_MODES; |
385 | } else if (strcasecmp(cmdtype, "get_config") == 0) { | ||
386 | type = IPC_GET_CONFIG; | ||
412 | } else { | 387 | } else { |
413 | sway_abort("Unknown message type %s", cmdtype); | 388 | sway_abort("Unknown message type %s", cmdtype); |
414 | } | 389 | } |
diff --git a/swaymsg/swaymsg.1.scd b/swaymsg/swaymsg.1.scd index 1aa6a1b0..a6e279da 100644 --- a/swaymsg/swaymsg.1.scd +++ b/swaymsg/swaymsg.1.scd | |||
@@ -59,8 +59,8 @@ _swaymsg_ [options...] [message] | |||
59 | *get\_version* | 59 | *get\_version* |
60 | Get JSON-encoded version information for the running instance of sway. | 60 | Get JSON-encoded version information for the running instance of sway. |
61 | 61 | ||
62 | *get\_clipboard* | 62 | *get\_binding\_modes* |
63 | Get JSON-encoded information about the clipboard. | 63 | Gets a JSON-encoded list of currently configured binding modes. |
64 | Returns the current clipboard mime-types if called without | 64 | |
65 | arguments, otherwise returns the clipboard data in the requested | 65 | *get\_config* |
66 | formats. Encodes the data using base64 for non-text mime types. | 66 | Gets a JSON-encoded copy of the current configuration. |