From fa7b686e61dd86f6f26d562362917034de4753dd Mon Sep 17 00:00:00 2001 From: Erik Reider <35975961+ErikReider@users.noreply.github.com> Date: Thu, 6 Apr 2023 10:40:49 +0200 Subject: [PATCH 001/114] Fix damage-ring bounds not being set when unplugging -> plugging in monitor #7524 was a partial fix. Seems like this is still an issue when unplugging and plugging the monitor back in. Closes: https://github.com/swaywm/sway/issues/7528 --- sway/desktop/output.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 09fc64627..43cd70d01 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -999,9 +999,6 @@ void handle_new_output(struct wl_listener *listener, void *data) { } output->server = server; wlr_damage_ring_init(&output->damage_ring); - int width, height; - wlr_output_transformed_resolution(output->wlr_output, &width, &height); - wlr_damage_ring_set_bounds(&output->damage_ring, width, height); wl_signal_add(&wlr_output->events.destroy, &output->destroy); output->destroy.notify = handle_destroy; @@ -1027,6 +1024,9 @@ void handle_new_output(struct wl_listener *listener, void *data) { transaction_commit_dirty(); + int width, height; + wlr_output_transformed_resolution(output->wlr_output, &width, &height); + wlr_damage_ring_set_bounds(&output->damage_ring, width, height); update_output_manager_config(server); } From e8fb7f53b81fd3fc5d81f4e0f43d20499940e0fd Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 5 Apr 2023 12:14:14 +0200 Subject: [PATCH 002/114] Remove duplicate wlr_damage_ring_set_bounds() call We already do this in handle_commit(). --- sway/desktop/output.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 43cd70d01..5671ac59d 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -884,11 +884,6 @@ static void handle_mode(struct sway_output *output) { arrange_output(output); transaction_commit_dirty(); - int width, height; - wlr_output_transformed_resolution(output->wlr_output, &width, &height); - wlr_damage_ring_set_bounds(&output->damage_ring, width, height); - wlr_output_schedule_frame(output->wlr_output); - update_output_manager_config(output->server); } From dadf3e9b7865e7a907a6d95cbb94a2e1cd8cf67f Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 6 Apr 2023 22:03:52 +0200 Subject: [PATCH 003/114] Chase wlroots!4067 --- sway/desktop/output.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 5671ac59d..59319f629 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -512,6 +512,10 @@ static bool scan_out_fullscreen_view(struct sway_output *output, return false; } + if (!wlr_output_is_direct_scanout_allowed(wlr_output)) { + return false; + } + wlr_output_attach_buffer(wlr_output, &surface->buffer->base); if (!wlr_output_test(wlr_output)) { return false; From 5e847fe3c8bbb27f45ec6f4f6a8dbbe617867550 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 14 Apr 2023 17:26:03 +0200 Subject: [PATCH 004/114] Pass version to wlr_compositor_create() References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3696 --- sway/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/server.c b/sway/server.c index 244c7aec8..0cf767b7e 100644 --- a/sway/server.c +++ b/sway/server.c @@ -103,7 +103,7 @@ bool server_init(struct sway_server *server) { return false; } - server->compositor = wlr_compositor_create(server->wl_display, + server->compositor = wlr_compositor_create(server->wl_display, 5, server->renderer); server->compositor_new_surface.notify = handle_compositor_new_surface; wl_signal_add(&server->compositor->events.new_surface, From 777df223777f318f9b0173d12f2162f29d7517da Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 6 Mar 2023 16:56:19 +0100 Subject: [PATCH 005/114] Skip direct scan-out commit when damage is empty When there is no damage, no need to perform an output commit, even when direct scan-out is used. --- sway/desktop/output.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 59319f629..91a5936aa 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -556,6 +556,11 @@ static int output_repaint_timer_handler(void *data) { wlr_output->frame_pending = false; + if (!wlr_output->needs_frame && + !pixman_region32_not_empty(&output->damage_ring.current)) { + return 0; + } + struct sway_workspace *workspace = output->current.active_workspace; if (workspace == NULL) { return 0; @@ -588,11 +593,6 @@ static int output_repaint_timer_handler(void *data) { } } - if (!output->wlr_output->needs_frame && - !pixman_region32_not_empty(&output->damage_ring.current)) { - return 0; - } - int buffer_age; if (!wlr_output_attach_render(output->wlr_output, &buffer_age)) { return 0; From ab4f46059793cbdd7942b128db970de95af37ed3 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 6 Mar 2023 16:57:27 +0100 Subject: [PATCH 006/114] Set output damage during direct scan-out During direct scan-out, pass the damaged region to the wlroots backend. --- sway/desktop/output.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 91a5936aa..17bce123d 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -571,6 +571,11 @@ static int output_repaint_timer_handler(void *data) { fullscreen_con = workspace->current.fullscreen; } + pixman_region32_t frame_damage; + get_frame_damage(output, &frame_damage); + wlr_output_set_damage(wlr_output, &frame_damage); + pixman_region32_fini(&frame_damage); + if (fullscreen_con && fullscreen_con->view && !debug.noscanout) { // Try to scan-out the fullscreen view static bool last_scanned_out = false; @@ -609,11 +614,6 @@ static int output_repaint_timer_handler(void *data) { pixman_region32_fini(&damage); - pixman_region32_t frame_damage; - get_frame_damage(output, &frame_damage); - wlr_output_set_damage(wlr_output, &frame_damage); - pixman_region32_fini(&frame_damage); - if (!wlr_output_commit(wlr_output)) { return 0; } From 63f9bdf00126d4505235c533693c297722be57c8 Mon Sep 17 00:00:00 2001 From: Elyes Haouas Date: Sat, 25 Feb 2023 09:28:16 +0100 Subject: [PATCH 007/114] Fix old style function definitions Signed-off-by: Elyes Haouas --- sway/commands/split.c | 2 +- sway/desktop/launcher.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/commands/split.c b/sway/commands/split.c index c8a2cfc1f..500a497db 100644 --- a/sway/commands/split.c +++ b/sway/commands/split.c @@ -32,7 +32,7 @@ static struct cmd_results *do_split(int layout) { return cmd_results_new(CMD_SUCCESS, NULL); } -static struct cmd_results *do_unsplit() { +static struct cmd_results *do_unsplit(void) { struct sway_container *con = config->handler_context.container; struct sway_workspace *ws = config->handler_context.workspace; diff --git a/sway/desktop/launcher.c b/sway/desktop/launcher.c index b666da1eb..00a7e38a6 100644 --- a/sway/desktop/launcher.c +++ b/sway/desktop/launcher.c @@ -228,7 +228,7 @@ struct launcher_ctx *launcher_ctx_create(struct wlr_xdg_activation_token_v1 *tok } // Creates a context with a new token for the internal launcher -struct launcher_ctx *launcher_ctx_create_internal() { +struct launcher_ctx *launcher_ctx_create_internal(void) { struct sway_seat *seat = input_manager_current_seat(); struct sway_workspace *ws = seat_get_focused_workspace(seat); if (!ws) { From 8d95638df6450ef9aa726e7d058b10182f584dc9 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 28 Feb 2023 12:47:12 +0100 Subject: [PATCH 008/114] Introduce output_match_name_or_id() Reduces code duplication. --- sway/desktop/output.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 17bce123d..fe3cdaf13 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -36,13 +36,18 @@ #include #endif +static bool output_match_name_or_id(struct sway_output *output, + const char *name_or_id) { + char identifier[128]; + output_get_identifier(identifier, sizeof(identifier), output); + return strcasecmp(identifier, name_or_id) == 0 + || strcasecmp(output->wlr_output->name, name_or_id) == 0; +} + struct sway_output *output_by_name_or_id(const char *name_or_id) { for (int i = 0; i < root->outputs->length; ++i) { struct sway_output *output = root->outputs->items[i]; - char identifier[128]; - output_get_identifier(identifier, sizeof(identifier), output); - if (strcasecmp(identifier, name_or_id) == 0 - || strcasecmp(output->wlr_output->name, name_or_id) == 0) { + if (output_match_name_or_id(output, name_or_id)) { return output; } } @@ -52,10 +57,7 @@ struct sway_output *output_by_name_or_id(const char *name_or_id) { struct sway_output *all_output_by_name_or_id(const char *name_or_id) { struct sway_output *output; wl_list_for_each(output, &root->all_outputs, link) { - char identifier[128]; - output_get_identifier(identifier, sizeof(identifier), output); - if (strcasecmp(identifier, name_or_id) == 0 - || strcasecmp(output->wlr_output->name, name_or_id) == 0) { + if (output_match_name_or_id(output, name_or_id)) { return output; } } From 04904ab9a57ff397702d6736523abeaa25d5d05b Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 28 Feb 2023 12:47:40 +0100 Subject: [PATCH 009/114] Use all_output_by_name_or_id() in merge_id_on_name() No need to iterate over the outputs manually. --- sway/config/output.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/sway/config/output.c b/sway/config/output.c index 3b524433c..352d7f7cc 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -153,29 +153,23 @@ static void merge_wildcard_on_all(struct output_config *wildcard) { } static void merge_id_on_name(struct output_config *oc) { - char *id_on_name = NULL; - char id[128]; - char *name = NULL; - struct sway_output *output; - wl_list_for_each(output, &root->all_outputs, link) { - name = output->wlr_output->name; - output_get_identifier(id, sizeof(id), output); - if (strcmp(name, oc->name) == 0 || strcmp(id, oc->name) == 0) { - size_t length = snprintf(NULL, 0, "%s on %s", id, name) + 1; - id_on_name = malloc(length); - if (!id_on_name) { - sway_log(SWAY_ERROR, "Failed to allocate id on name string"); - return; - } - snprintf(id_on_name, length, "%s on %s", id, name); - break; - } - } - - if (!id_on_name) { + struct sway_output *output = all_output_by_name_or_id(oc->name); + if (output == NULL) { return; } + const char *name = output->wlr_output->name; + char id[128]; + output_get_identifier(id, sizeof(id), output); + + size_t size = snprintf(NULL, 0, "%s on %s", id, name) + 1; + char *id_on_name = malloc(size); + if (!id_on_name) { + sway_log(SWAY_ERROR, "Failed to allocate id on name string"); + return; + } + snprintf(id_on_name, size, "%s on %s", id, name); + int i = list_seq_find(config->output_configs, output_name_cmp, id_on_name); if (i >= 0) { sway_log(SWAY_DEBUG, "Merging on top of existing id on name config"); From fcec5817483ba279b714acf6d81f5d7a3688b092 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 28 Feb 2023 12:51:59 +0100 Subject: [PATCH 010/114] Use output_match_name_or_id() in apply_output_config_to_outputs() --- include/sway/output.h | 3 +++ sway/config/output.c | 7 +++---- sway/desktop/output.c | 6 +++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index 2aa1b2788..04202976c 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -96,6 +96,9 @@ void output_damage_box(struct sway_output *output, struct wlr_box *box); void output_damage_whole_container(struct sway_output *output, struct sway_container *con); +bool output_match_name_or_id(struct sway_output *output, + const char *name_or_id); + // this ONLY includes the enabled outputs struct sway_output *output_by_name_or_id(const char *name_or_id); diff --git a/sway/config/output.c b/sway/config/output.c index 352d7f7cc..45d2441b1 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -722,12 +722,11 @@ void apply_output_config_to_outputs(struct output_config *oc) { // this is during startup then there will be no container and config // will be applied during normal "new output" event from wlroots. bool wildcard = strcmp(oc->name, "*") == 0; - char id[128]; struct sway_output *sway_output, *tmp; wl_list_for_each_safe(sway_output, tmp, &root->all_outputs, link) { - char *name = sway_output->wlr_output->name; - output_get_identifier(id, sizeof(id), sway_output); - if (wildcard || !strcmp(name, oc->name) || !strcmp(id, oc->name)) { + if (output_match_name_or_id(sway_output, oc->name)) { + char id[128]; + output_get_identifier(id, sizeof(id), sway_output); struct output_config *current = get_output_config(id, sway_output); if (!current) { // No stored output config matched, apply oc directly diff --git a/sway/desktop/output.c b/sway/desktop/output.c index fe3cdaf13..2255b5518 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -36,8 +36,12 @@ #include #endif -static bool output_match_name_or_id(struct sway_output *output, +bool output_match_name_or_id(struct sway_output *output, const char *name_or_id) { + if (strcmp(name_or_id, "*") == 0) { + return true; + } + char identifier[128]; output_get_identifier(identifier, sizeof(identifier), output); return strcasecmp(identifier, name_or_id) == 0 From 4118c493499fc03fd2c77a061b4905cd7523d67c Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 28 Feb 2023 12:58:52 +0100 Subject: [PATCH 011/114] Use output_match_name_or_id() in workspace functions --- sway/tree/workspace.c | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index ee9404660..18218768b 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -176,22 +176,16 @@ void workspace_consider_destroy(struct sway_workspace *ws) { static bool workspace_valid_on_output(const char *output_name, const char *ws_name) { struct workspace_config *wsc = workspace_find_config(ws_name); - char identifier[128]; struct sway_output *output = output_by_name_or_id(output_name); if (!output) { return false; } - output_name = output->wlr_output->name; - output_get_identifier(identifier, sizeof(identifier), output); - if (!wsc) { return true; } for (int i = 0; i < wsc->outputs->length; i++) { - if (strcmp(wsc->outputs->items[i], "*") == 0 || - strcmp(wsc->outputs->items[i], output_name) == 0 || - strcmp(wsc->outputs->items[i], identifier) == 0) { + if (output_match_name_or_id(output, wsc->outputs->items[i])) { return true; } } @@ -286,13 +280,10 @@ char *workspace_next_name(const char *output_name) { // assignments primarily, falling back to bindings and numbers. struct sway_mode *mode = config->current_mode; - char identifier[128]; struct sway_output *output = output_by_name_or_id(output_name); if (!output) { return NULL; } - output_name = output->wlr_output->name; - output_get_identifier(identifier, sizeof(identifier), output); int order = INT_MAX; char *target = NULL; @@ -312,9 +303,7 @@ char *workspace_next_name(const char *output_name) { } bool found = false; for (int j = 0; j < wsc->outputs->length; ++j) { - if (strcmp(wsc->outputs->items[j], "*") == 0 || - strcmp(wsc->outputs->items[j], output_name) == 0 || - strcmp(wsc->outputs->items[j], identifier) == 0) { + if (output_match_name_or_id(output, wsc->outputs->items[j])) { found = true; free(target); target = strdup(wsc->workspace); @@ -654,15 +643,9 @@ void workspace_output_add_priority(struct sway_workspace *workspace, struct sway_output *workspace_output_get_highest_available( struct sway_workspace *ws, struct sway_output *exclude) { - char exclude_id[128] = {'\0'}; - if (exclude) { - output_get_identifier(exclude_id, sizeof(exclude_id), exclude); - } - for (int i = 0; i < ws->output_priority->length; i++) { - char *name = ws->output_priority->items[i]; - if (exclude && (strcmp(name, exclude->wlr_output->name) == 0 - || strcmp(name, exclude_id) == 0)) { + const char *name = ws->output_priority->items[i]; + if (exclude && output_match_name_or_id(exclude, name)) { continue; } From aab4c9da5fb4138ca5f07df8bd8b698d02242a62 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 28 Feb 2023 16:00:28 +0100 Subject: [PATCH 012/114] Add format_str() and vformat_str() Simple helpers to allocate and format a string. --- common/stringop.c | 33 +++++++++++++++++++++++++++++++++ include/stringop.h | 9 +++++++++ 2 files changed, 42 insertions(+) diff --git a/common/stringop.c b/common/stringop.c index 7fb3fe12a..c503143ae 100644 --- a/common/stringop.c +++ b/common/stringop.c @@ -1,5 +1,6 @@ #define _POSIX_C_SOURCE 200809L #include +#include #include #include #include @@ -328,3 +329,35 @@ bool expand_path(char **path) { wordfree(&p); return true; } + +char *vformat_str(const char *fmt, va_list args) { + char *str = NULL; + va_list args_copy; + va_copy(args_copy, args); + + int len = vsnprintf(NULL, 0, fmt, args); + if (len < 0) { + sway_log_errno(SWAY_ERROR, "vsnprintf(\"%s\") failed", fmt); + goto out; + } + + str = malloc(len + 1); + if (str == NULL) { + sway_log_errno(SWAY_ERROR, "malloc() failed"); + goto out; + } + + vsnprintf(str, len + 1, fmt, args_copy); + +out: + va_end(args_copy); + return str; +} + +char *format_str(const char *fmt, ...) { + va_list args; + va_start(args, fmt); + char *str = vformat_str(fmt, args); + va_end(args); + return str; +} diff --git a/include/stringop.h b/include/stringop.h index b29f59b27..19a50f237 100644 --- a/include/stringop.h +++ b/include/stringop.h @@ -5,6 +5,12 @@ #include #include "list.h" +#ifdef __GNUC__ +#define _SWAY_ATTRIB_PRINTF(start, end) __attribute__((format(printf, start, end))) +#else +#define _SWAY_ATTRIB_PRINTF(start, end) +#endif + void strip_whitespace(char *str); void strip_quotes(char *str); @@ -31,4 +37,7 @@ char *argsep(char **stringp, const char *delim, char *matched_delim); // Expand a path using shell replacements such as $HOME and ~ bool expand_path(char **path); +char *vformat_str(const char *fmt, va_list args) _SWAY_ATTRIB_PRINTF(1, 0); +char *format_str(const char *fmt, ...) _SWAY_ATTRIB_PRINTF(1, 2); + #endif From bd58df61efbb86cd43682acfd7cde8085b503590 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 28 Feb 2023 16:13:59 +0100 Subject: [PATCH 013/114] pango: add printf attribute This allows the compiler to catch mismatches between the format string and the arguments passed in. Need to add -Wno-format-zero-length because we pass an empty string on purpose in swaybar/render.c. --- include/pango.h | 5 +++-- meson.build | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/pango.h b/include/pango.h index 1db113c29..228e39cfa 100644 --- a/include/pango.h +++ b/include/pango.h @@ -5,6 +5,7 @@ #include #include #include +#include "stringop.h" /** * Utility function which escape characters a & < > ' ". @@ -16,9 +17,9 @@ size_t escape_markup_text(const char *src, char *dest); PangoLayout *get_pango_layout(cairo_t *cairo, const PangoFontDescription *desc, const char *text, double scale, bool markup); void get_text_size(cairo_t *cairo, const PangoFontDescription *desc, int *width, int *height, - int *baseline, double scale, bool markup, const char *fmt, ...); + int *baseline, double scale, bool markup, const char *fmt, ...) _SWAY_ATTRIB_PRINTF(8, 9); void get_text_metrics(const PangoFontDescription *desc, int *height, int *baseline); void render_text(cairo_t *cairo, PangoFontDescription *desc, - double scale, bool markup, const char *fmt, ...); + double scale, bool markup, const char *fmt, ...) _SWAY_ATTRIB_PRINTF(5, 6); #endif diff --git a/meson.build b/meson.build index d1fbfa38a..559ee962d 100644 --- a/meson.build +++ b/meson.build @@ -18,6 +18,7 @@ add_project_arguments( '-Wno-unused-parameter', '-Wno-unused-result', '-Wno-missing-braces', + '-Wno-format-zero-length', '-Wundef', '-Wvla', ], From d6915f642858c65c9225a07e96dd65be70806def Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 14 Apr 2023 18:14:21 +0200 Subject: [PATCH 014/114] commands/floating_minmax_size: fix error strings cmd_results_new() does not take the command name as argument. --- sway/commands/floating_minmax_size.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sway/commands/floating_minmax_size.c b/sway/commands/floating_minmax_size.c index 3a1d606a0..1c28c5363 100644 --- a/sway/commands/floating_minmax_size.c +++ b/sway/commands/floating_minmax_size.c @@ -23,16 +23,16 @@ static struct cmd_results *handle_command(int argc, char **argv, char *cmd_name, char *err; int width = (int)strtol(argv[0], &err, 10); if (*err) { - return cmd_results_new(CMD_INVALID, cmd_name, usage); + return cmd_results_new(CMD_INVALID, usage); } if (strcmp(argv[1], "x") != 0) { - return cmd_results_new(CMD_INVALID, cmd_name, usage); + return cmd_results_new(CMD_INVALID, usage); } int height = (int)strtol(argv[2], &err, 10); if (*err) { - return cmd_results_new(CMD_INVALID, cmd_name, usage); + return cmd_results_new(CMD_INVALID, usage); } *config_width = width; From a7b50f6c9cbded863475cc7b60d048636750ef6a Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 28 Feb 2023 16:24:03 +0100 Subject: [PATCH 015/114] commands: add printf attribute to cmd_results_new() And fix the resulting build failures. --- include/sway/commands.h | 3 ++- sway/commands.c | 11 +++++++---- sway/commands/assign.c | 2 +- sway/commands/bar/bind.c | 2 +- sway/commands/bar/tray_bind.c | 2 +- sway/commands/bind.c | 13 +++++++------ sway/commands/floating_minmax_size.c | 6 +++--- sway/commands/for_window.c | 2 +- sway/commands/hide_edge_borders.c | 4 ++-- sway/commands/input/map_to_region.c | 2 +- sway/commands/input/scroll_button.c | 2 +- sway/commands/layout.c | 2 +- sway/commands/move.c | 24 ++++++++++++------------ sway/commands/no_focus.c | 2 +- sway/commands/rename.c | 4 ++-- sway/commands/resize.c | 18 +++++++++--------- sway/commands/seat/cursor.c | 10 +++++----- sway/commands/swap.c | 4 ++-- sway/commands/workspace.c | 8 ++++---- 19 files changed, 63 insertions(+), 58 deletions(-) diff --git a/include/sway/commands.h b/include/sway/commands.h index fc6ce22e7..3212c2cf4 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -3,6 +3,7 @@ #include #include "config.h" +#include "stringop.h" struct sway_container; @@ -76,7 +77,7 @@ struct cmd_results *config_commands_command(char *exec); /** * Allocates a cmd_results object. */ -struct cmd_results *cmd_results_new(enum cmd_status status, const char *error, ...); +struct cmd_results *cmd_results_new(enum cmd_status status, const char *error, ...) _SWAY_ATTRIB_PRINTF(2, 3); /** * Frees a cmd_results object. */ diff --git a/sway/commands.c b/sway/commands.c index 28e9d8d20..0ea44129e 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -381,10 +381,13 @@ struct cmd_results *config_command(char *exec, char **new_block) { sway_log(SWAY_INFO, "Config command: %s", exec); const struct cmd_handler *handler = find_core_handler(argv[0]); if (!handler || !handler->handle) { - const char *error = handler - ? "Command '%s' is shimmed, but unimplemented" - : "Unknown/invalid command '%s'"; - results = cmd_results_new(CMD_INVALID, error, argv[0]); + if (handler) { + results = cmd_results_new(CMD_INVALID, + "Command '%s' is shimmed, but unimplemented", argv[0]); + } else { + results = cmd_results_new(CMD_INVALID, + "Unknown/invalid command '%s'", argv[0]); + } goto cleanup; } diff --git a/sway/commands/assign.c b/sway/commands/assign.c index 976bc3cc5..f7d911f77 100644 --- a/sway/commands/assign.c +++ b/sway/commands/assign.c @@ -17,7 +17,7 @@ struct cmd_results *cmd_assign(int argc, char **argv) { char *err_str = NULL; struct criteria *criteria = criteria_parse(argv[0], &err_str); if (!criteria) { - error = cmd_results_new(CMD_INVALID, err_str); + error = cmd_results_new(CMD_INVALID, "%s", err_str); free(err_str); return error; } diff --git a/sway/commands/bar/bind.c b/sway/commands/bar/bind.c index b4b5bc459..8a837e3f1 100644 --- a/sway/commands/bar/bind.c +++ b/sway/commands/bar/bind.c @@ -96,7 +96,7 @@ static struct cmd_results *bar_cmd_bind(int argc, char **argv, bool code, } if (message) { free_bar_binding(binding); - error = cmd_results_new(CMD_INVALID, message); + error = cmd_results_new(CMD_INVALID, "%s", message); free(message); return error; } else if (!binding->button) { diff --git a/sway/commands/bar/tray_bind.c b/sway/commands/bar/tray_bind.c index 243834bad..3dc9bc4cc 100644 --- a/sway/commands/bar/tray_bind.c +++ b/sway/commands/bar/tray_bind.c @@ -26,7 +26,7 @@ static struct cmd_results *tray_bind(int argc, char **argv, bool code) { } if (message) { free(binding); - error = cmd_results_new(CMD_INVALID, message); + error = cmd_results_new(CMD_INVALID, "%s", message); free(message); return error; } else if (!binding->button) { diff --git a/sway/commands/bind.c b/sway/commands/bind.c index c0b383db3..979e178fd 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -127,7 +127,7 @@ static struct cmd_results *identify_key(const char* name, bool first_key, if (!button) { if (message) { struct cmd_results *error = - cmd_results_new(CMD_INVALID, message); + cmd_results_new(CMD_INVALID, "%s", message); free(message); return error; } else { @@ -143,7 +143,7 @@ static struct cmd_results *identify_key(const char* name, bool first_key, if (!button) { if (message) { struct cmd_results *error = - cmd_results_new(CMD_INVALID, message); + cmd_results_new(CMD_INVALID, "%s", message); free(message); return error; } else { @@ -182,7 +182,7 @@ static struct cmd_results *identify_key(const char* name, bool first_key, uint32_t button = get_mouse_bindsym(name, &message); if (message) { struct cmd_results *error = - cmd_results_new(CMD_INVALID, message); + cmd_results_new(CMD_INVALID, "%s", message); free(message); return error; } else if (button) { @@ -539,7 +539,7 @@ struct cmd_results *cmd_bind_or_unbind_switch(int argc, char **argv, free_switch_binding(binding); return cmd_results_new(CMD_FAILURE, "Invalid %s command (expected binding with the form " - ":)", bindtype, argc); + ":)", bindtype); } if (strcmp(split->items[0], "tablet") == 0) { binding->type = WLR_SWITCH_TYPE_TABLET_MODE; @@ -549,7 +549,8 @@ struct cmd_results *cmd_bind_or_unbind_switch(int argc, char **argv, free_switch_binding(binding); return cmd_results_new(CMD_FAILURE, "Invalid %s command (expected switch binding: " - "unknown switch %s)", bindtype, split->items[0]); + "unknown switch %s)", bindtype, + (const char *)split->items[0]); } if (strcmp(split->items[1], "on") == 0) { binding->trigger = SWAY_SWITCH_TRIGGER_ON; @@ -562,7 +563,7 @@ struct cmd_results *cmd_bind_or_unbind_switch(int argc, char **argv, return cmd_results_new(CMD_FAILURE, "Invalid %s command " "(expected switch state: unknown state %s)", - bindtype, split->items[1]); + bindtype, (const char *)split->items[1]); } list_free_items_and_destroy(split); diff --git a/sway/commands/floating_minmax_size.c b/sway/commands/floating_minmax_size.c index 1c28c5363..e8c24ace2 100644 --- a/sway/commands/floating_minmax_size.c +++ b/sway/commands/floating_minmax_size.c @@ -23,16 +23,16 @@ static struct cmd_results *handle_command(int argc, char **argv, char *cmd_name, char *err; int width = (int)strtol(argv[0], &err, 10); if (*err) { - return cmd_results_new(CMD_INVALID, usage); + return cmd_results_new(CMD_INVALID, "%s", usage); } if (strcmp(argv[1], "x") != 0) { - return cmd_results_new(CMD_INVALID, usage); + return cmd_results_new(CMD_INVALID, "%s", usage); } int height = (int)strtol(argv[2], &err, 10); if (*err) { - return cmd_results_new(CMD_INVALID, usage); + return cmd_results_new(CMD_INVALID, "%s", usage); } *config_width = width; diff --git a/sway/commands/for_window.c b/sway/commands/for_window.c index ee9f46478..905e67767 100644 --- a/sway/commands/for_window.c +++ b/sway/commands/for_window.c @@ -14,7 +14,7 @@ struct cmd_results *cmd_for_window(int argc, char **argv) { char *err_str = NULL; struct criteria *criteria = criteria_parse(argv[0], &err_str); if (!criteria) { - error = cmd_results_new(CMD_INVALID, err_str); + error = cmd_results_new(CMD_INVALID, "%s", err_str); free(err_str); return error; } diff --git a/sway/commands/hide_edge_borders.c b/sway/commands/hide_edge_borders.c index 9a1d84458..43bd6dc86 100644 --- a/sway/commands/hide_edge_borders.c +++ b/sway/commands/hide_edge_borders.c @@ -20,7 +20,7 @@ struct cmd_results *cmd_hide_edge_borders(int argc, char **argv) { } if (!argc) { - return cmd_results_new(CMD_INVALID, expected_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_syntax); } if (strcmp(argv[0], "none") == 0) { @@ -38,7 +38,7 @@ struct cmd_results *cmd_hide_edge_borders(int argc, char **argv) { config->hide_edge_borders = E_NONE; config->hide_edge_borders_smart = ESMART_NO_GAPS; } else { - return cmd_results_new(CMD_INVALID, expected_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_syntax); } config->hide_lone_tab = hide_lone_tab; diff --git a/sway/commands/input/map_to_region.c b/sway/commands/input/map_to_region.c index 284b57d0c..ad535db23 100644 --- a/sway/commands/input/map_to_region.c +++ b/sway/commands/input/map_to_region.c @@ -49,5 +49,5 @@ struct cmd_results *input_cmd_map_to_region(int argc, char **argv) { error: free(ic->mapped_to_region); ic->mapped_to_region = NULL; - return cmd_results_new(CMD_FAILURE, errstr); + return cmd_results_new(CMD_FAILURE, "%s", errstr); } diff --git a/sway/commands/input/scroll_button.c b/sway/commands/input/scroll_button.c index 6b3314190..81f69a6df 100644 --- a/sway/commands/input/scroll_button.c +++ b/sway/commands/input/scroll_button.c @@ -21,7 +21,7 @@ struct cmd_results *input_cmd_scroll_button(int argc, char **argv) { char *message = NULL; uint32_t button = get_mouse_button(*argv, &message); if (message) { - error = cmd_results_new(CMD_INVALID, message); + error = cmd_results_new(CMD_INVALID, "%s", message); free(message); return error; } else if (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN diff --git a/sway/commands/layout.c b/sway/commands/layout.c index 2ba61b38e..12ce48398 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -153,7 +153,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) { workspace->output); } if (new_layout == L_NONE) { - return cmd_results_new(CMD_INVALID, expected_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_syntax); } if (new_layout != old_layout) { if (container) { diff --git a/sway/commands/move.c b/sway/commands/move.c index 9e40a3b47..69ed06c0b 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -470,7 +470,7 @@ static struct cmd_results *cmd_move_container(bool no_auto_back_and_forth, if (strcasecmp(argv[1], "number") == 0) { // move [window|container] [to] "workspace number x" if (argc < 3) { - return cmd_results_new(CMD_INVALID, expected_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_syntax); } if (!isdigit(argv[2][0])) { return cmd_results_new(CMD_INVALID, @@ -530,7 +530,7 @@ static struct cmd_results *cmd_move_container(bool no_auto_back_and_forth, } destination = &dest_con->node; } else { - return cmd_results_new(CMD_INVALID, expected_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_syntax); } if (destination->type == N_CONTAINER && @@ -829,7 +829,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) { } if (!argc) { - return cmd_results_new(CMD_INVALID, expected_position_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax); } bool absolute = false; @@ -839,19 +839,19 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) { ++argv; } if (!argc) { - return cmd_results_new(CMD_INVALID, expected_position_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax); } if (strcmp(argv[0], "position") == 0) { --argc; ++argv; } if (!argc) { - return cmd_results_new(CMD_INVALID, expected_position_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax); } if (strcmp(argv[0], "cursor") == 0 || strcmp(argv[0], "mouse") == 0 || strcmp(argv[0], "pointer") == 0) { if (absolute) { - return cmd_results_new(CMD_INVALID, expected_position_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax); } return cmd_move_to_position_pointer(container); } else if (strcmp(argv[0], "center") == 0) { @@ -873,7 +873,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) { } if (argc < 2) { - return cmd_results_new(CMD_FAILURE, expected_position_syntax); + return cmd_results_new(CMD_FAILURE, "%s", expected_position_syntax); } struct movement_amount lx = { .amount = 0, .unit = MOVEMENT_UNIT_INVALID }; @@ -886,7 +886,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) { } if (argc < 1) { - return cmd_results_new(CMD_FAILURE, expected_position_syntax); + return cmd_results_new(CMD_FAILURE, "%s", expected_position_syntax); } struct movement_amount ly = { .amount = 0, .unit = MOVEMENT_UNIT_INVALID }; @@ -895,7 +895,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) { argc -= num_consumed_args; argv += num_consumed_args; if (argc > 0) { - return cmd_results_new(CMD_INVALID, expected_position_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax); } if (ly.unit == MOVEMENT_UNIT_INVALID) { return cmd_results_new(CMD_INVALID, "Invalid y position specified"); @@ -1041,13 +1041,13 @@ struct cmd_results *cmd_move(int argc, char **argv) { } if (!argc) { - return cmd_results_new(CMD_INVALID, expected_full_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_full_syntax); } // Only `move [window|container] [to] workspace` supports // `--no-auto-back-and-forth` so treat others as invalid syntax if (no_auto_back_and_forth && strcasecmp(argv[0], "workspace") != 0) { - return cmd_results_new(CMD_INVALID, expected_full_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_full_syntax); } if (strcasecmp(argv[0], "workspace") == 0 || @@ -1061,5 +1061,5 @@ struct cmd_results *cmd_move(int argc, char **argv) { strcasecmp(argv[1], "position") == 0)) { return cmd_move_to_position(argc, argv); } - return cmd_results_new(CMD_INVALID, expected_full_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_full_syntax); } diff --git a/sway/commands/no_focus.c b/sway/commands/no_focus.c index 2001e04f0..ccfdec824 100644 --- a/sway/commands/no_focus.c +++ b/sway/commands/no_focus.c @@ -13,7 +13,7 @@ struct cmd_results *cmd_no_focus(int argc, char **argv) { char *err_str = NULL; struct criteria *criteria = criteria_parse(argv[0], &err_str); if (!criteria) { - error = cmd_results_new(CMD_INVALID, err_str); + error = cmd_results_new(CMD_INVALID, "%s", err_str); free(err_str); return error; } diff --git a/sway/commands/rename.c b/sway/commands/rename.c index 60a66d58a..0d36cc21e 100644 --- a/sway/commands/rename.c +++ b/sway/commands/rename.c @@ -26,7 +26,7 @@ struct cmd_results *cmd_rename(int argc, char **argv) { "Can't run this command while there's no outputs connected."); } if (strcasecmp(argv[0], "workspace") != 0) { - return cmd_results_new(CMD_INVALID, expected_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_syntax); } int argn = 1; @@ -65,7 +65,7 @@ struct cmd_results *cmd_rename(int argc, char **argv) { ++argn; // move past "to" if (argn >= argc) { - return cmd_results_new(CMD_INVALID, expected_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_syntax); } char *new_name = join_args(argv + argn, argc - argn); diff --git a/sway/commands/resize.c b/sway/commands/resize.c index 425069de3..e69e5506e 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c @@ -415,7 +415,7 @@ static struct cmd_results *cmd_resize_set(int argc, char **argv) { argc -= num_consumed_args; argv += num_consumed_args; if (width.unit == MOVEMENT_UNIT_INVALID) { - return cmd_results_new(CMD_INVALID, usage); + return cmd_results_new(CMD_INVALID, "%s", usage); } } @@ -427,10 +427,10 @@ static struct cmd_results *cmd_resize_set(int argc, char **argv) { } int num_consumed_args = parse_movement_amount(argc, argv, &height); if (argc > num_consumed_args) { - return cmd_results_new(CMD_INVALID, usage); + return cmd_results_new(CMD_INVALID, "%s", usage); } if (width.unit == MOVEMENT_UNIT_INVALID) { - return cmd_results_new(CMD_INVALID, usage); + return cmd_results_new(CMD_INVALID, "%s", usage); } } @@ -462,7 +462,7 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv, "[ px|ppt [or px|ppt]]'"; uint32_t axis = parse_resize_axis(*argv); if (axis == WLR_EDGE_NONE) { - return cmd_results_new(CMD_INVALID, usage); + return cmd_results_new(CMD_INVALID, "%s", usage); } --argc; ++argv; @@ -473,7 +473,7 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv, argc -= num_consumed_args; argv += num_consumed_args; if (first_amount.unit == MOVEMENT_UNIT_INVALID) { - return cmd_results_new(CMD_INVALID, usage); + return cmd_results_new(CMD_INVALID, "%s", usage); } } else { first_amount.amount = 10; @@ -483,7 +483,7 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv, // "or" if (argc) { if (strcmp(*argv, "or") != 0) { - return cmd_results_new(CMD_INVALID, usage); + return cmd_results_new(CMD_INVALID, "%s", usage); } --argc; ++argv; } @@ -493,10 +493,10 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv, if (argc) { int num_consumed_args = parse_movement_amount(argc, argv, &second_amount); if (argc > num_consumed_args) { - return cmd_results_new(CMD_INVALID, usage); + return cmd_results_new(CMD_INVALID, "%s", usage); } if (second_amount.unit == MOVEMENT_UNIT_INVALID) { - return cmd_results_new(CMD_INVALID, usage); + return cmd_results_new(CMD_INVALID, "%s", usage); } } else { second_amount.amount = 0; @@ -566,5 +566,5 @@ struct cmd_results *cmd_resize(int argc, char **argv) { const char usage[] = "Expected 'resize " " [] [px|ppt]'"; - return cmd_results_new(CMD_INVALID, usage); + return cmd_results_new(CMD_INVALID, "%s", usage); } diff --git a/sway/commands/seat/cursor.c b/sway/commands/seat/cursor.c index 504a9f5e5..5a8a3bc8f 100644 --- a/sway/commands/seat/cursor.c +++ b/sway/commands/seat/cursor.c @@ -18,7 +18,7 @@ static struct cmd_results *handle_command(struct sway_cursor *cursor, int argc, char **argv) { if (strcasecmp(argv[0], "move") == 0) { if (argc < 3) { - return cmd_results_new(CMD_INVALID, expected_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_syntax); } int delta_x = strtol(argv[1], NULL, 10); int delta_y = strtol(argv[2], NULL, 10); @@ -27,7 +27,7 @@ static struct cmd_results *handle_command(struct sway_cursor *cursor, wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); } else if (strcasecmp(argv[0], "set") == 0) { if (argc < 3) { - return cmd_results_new(CMD_INVALID, expected_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_syntax); } // map absolute coords (0..1,0..1) to root container coords float x = strtof(argv[1], NULL) / root->width; @@ -37,7 +37,7 @@ static struct cmd_results *handle_command(struct sway_cursor *cursor, wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); } else { if (argc < 2) { - return cmd_results_new(CMD_INVALID, expected_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_syntax); } struct cmd_results *error = NULL; if ((error = press_or_release(cursor, argv[0], argv[1]))) { @@ -92,14 +92,14 @@ static struct cmd_results *press_or_release(struct sway_cursor *cursor, } else if (strcasecmp(action, "release") == 0) { state = WLR_BUTTON_RELEASED; } else { - return cmd_results_new(CMD_INVALID, expected_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_syntax); } char *message = NULL; button = get_mouse_button(button_str, &message); if (message) { struct cmd_results *error = - cmd_results_new(CMD_INVALID, message); + cmd_results_new(CMD_INVALID, "%s", message); free(message); return error; } else if (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN diff --git a/sway/commands/swap.c b/sway/commands/swap.c index b457f121c..d44eb006c 100644 --- a/sway/commands/swap.c +++ b/sway/commands/swap.c @@ -46,7 +46,7 @@ struct cmd_results *cmd_swap(int argc, char **argv) { } if (strcasecmp(argv[0], "container") || strcasecmp(argv[1], "with")) { - return cmd_results_new(CMD_INVALID, expected_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_syntax); } struct sway_container *current = config->handler_context.container; @@ -65,7 +65,7 @@ struct cmd_results *cmd_swap(int argc, char **argv) { other = root_find_container(test_mark, value); } else { free(value); - return cmd_results_new(CMD_INVALID, expected_syntax); + return cmd_results_new(CMD_INVALID, "%s", expected_syntax); } if (!other) { diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index a6a0bedad..03e488ba9 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -61,7 +61,7 @@ static struct cmd_results *cmd_workspace_gaps(int argc, char **argv, const char expected[] = "Expected 'workspace gaps " "inner|outer|horizontal|vertical|top|right|bottom|left '"; if (gaps_location == 0) { - return cmd_results_new(CMD_INVALID, expected); + return cmd_results_new(CMD_INVALID, "%s", expected); } struct cmd_results *error = NULL; if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, @@ -79,7 +79,7 @@ static struct cmd_results *cmd_workspace_gaps(int argc, char **argv, char *end; int amount = strtol(argv[gaps_location + 2], &end, 10); if (strlen(end)) { - return cmd_results_new(CMD_FAILURE, expected); + return cmd_results_new(CMD_FAILURE, "%s", expected); } bool valid = false; @@ -110,7 +110,7 @@ static struct cmd_results *cmd_workspace_gaps(int argc, char **argv, } } if (!valid) { - return cmd_results_new(CMD_INVALID, expected); + return cmd_results_new(CMD_INVALID, "%s", expected); } // Prevent invalid gaps configurations. @@ -174,7 +174,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { } if (root->fullscreen_global) { - return cmd_results_new(CMD_FAILURE, "workspace", + return cmd_results_new(CMD_FAILURE, "Can't switch workspaces while fullscreen global"); } From 96cebb4fe65021660e467a2cda8c9c5c4c29b699 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 28 Feb 2023 16:27:44 +0100 Subject: [PATCH 016/114] config: add printf attribute to config_add_swaynag_warning() --- include/sway/config.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/sway/config.h b/include/sway/config.h index 8415627b4..aa58da531 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -12,6 +12,7 @@ #include "../include/config.h" #include "gesture.h" #include "list.h" +#include "stringop.h" #include "swaynag.h" #include "tree/container.h" #include "sway/input/tablet.h" @@ -625,7 +626,7 @@ void run_deferred_bindings(void); /** * Adds a warning entry to the swaynag instance used for errors. */ -void config_add_swaynag_warning(char *fmt, ...); +void config_add_swaynag_warning(char *fmt, ...) _SWAY_ATTRIB_PRINTF(1, 2); /** * Free config struct From ea279f4df3d9b08e65d5d8e241a57b7470fbd202 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 28 Feb 2023 16:36:42 +0100 Subject: [PATCH 017/114] swaynag: add printf attribute to swaynag_log() --- include/sway/swaynag.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/sway/swaynag.h b/include/sway/swaynag.h index 74d9ea18c..03bd52c33 100644 --- a/include/sway/swaynag.h +++ b/include/sway/swaynag.h @@ -1,6 +1,7 @@ #ifndef _SWAY_SWAYNAG_H #define _SWAY_SWAYNAG_H #include +#include "stringop.h" struct swaynag_instance { struct wl_client *client; @@ -21,7 +22,7 @@ bool swaynag_spawn(const char *swaynag_command, // Write a log message to swaynag->fd[1]. This will fail when swaynag->detailed // is false. void swaynag_log(const char *swaynag_command, struct swaynag_instance *swaynag, - const char *fmt, ...); + const char *fmt, ...) _SWAY_ATTRIB_PRINTF(3, 4); // If swaynag->detailed, close swaynag->fd[1] so swaynag displays void swaynag_show(struct swaynag_instance *swaynag); From ac8962eb626a8c715241ae91646f2d1bfcb61533 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 28 Feb 2023 16:13:40 +0100 Subject: [PATCH 018/114] common/gesture: use format_str() We already had a similar function in there. --- common/gesture.c | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/common/gesture.c b/common/gesture.c index 8c2efe992..58170443d 100644 --- a/common/gesture.c +++ b/common/gesture.c @@ -12,23 +12,6 @@ const uint8_t GESTURE_FINGERS_ANY = 0; -// Helper to easily allocate and format string -static char *strformat(const char *format, ...) { - va_list args; - va_start(args, format); - int length = vsnprintf(NULL, 0, format, args) + 1; - va_end(args); - - char *result = malloc(length); - if (result) { - va_start(args, format); - vsnprintf(result, length, format, args); - va_end(args); - } - - return result; -} - char *gesture_parse(const char *input, struct gesture *output) { // Clear output in case of failure output->type = GESTURE_TYPE_NONE; @@ -38,7 +21,7 @@ char *gesture_parse(const char *input, struct gesture *output) { // Split input type, fingers and directions list_t *split = split_string(input, ":"); if (split->length < 1 || split->length > 3) { - return strformat( + return format_str( "expected [:][:direction], got %s", input); } @@ -51,8 +34,8 @@ char *gesture_parse(const char *input, struct gesture *output) { } else if (strcmp(split->items[0], "swipe") == 0) { output->type = GESTURE_TYPE_SWIPE; } else { - return strformat("expected hold|pinch|swipe, got %s", - split->items[0]); + return format_str("expected hold|pinch|swipe, got %s", + (const char *)split->items[0]); } // Parse optional arguments @@ -67,7 +50,7 @@ char *gesture_parse(const char *input, struct gesture *output) { next = split->length == 3 ? split->items[2] : NULL; } else if (split->length == 3) { // Fail here if argument can only be finger count - return strformat("expected 1-9, got %s", next); + return format_str("expected 1-9, got %s", next); } // If there is an argument left, try to parse as direction @@ -95,7 +78,7 @@ char *gesture_parse(const char *input, struct gesture *output) { } else if (strcmp(item, "counterclockwise") == 0) { output->directions |= GESTURE_DIRECTION_COUNTERCLOCKWISE; } else { - return strformat("expected direction, got %s", item); + return format_str("expected direction, got %s", item); } } list_free_items_and_destroy(directions); @@ -163,7 +146,7 @@ static char *gesture_directions_to_string(uint32_t directions) { if (!result) { result = strdup(name); } else { - char *new = strformat("%s+%s", result, name); + char *new = format_str("%s+%s", result, name); free(result); result = new; } @@ -179,7 +162,7 @@ static char *gesture_directions_to_string(uint32_t directions) { char *gesture_to_string(struct gesture *gesture) { char *directions = gesture_directions_to_string(gesture->directions); - char *result = strformat("%s:%u:%s", + char *result = format_str("%s:%u:%s", gesture_type_string(gesture->type), gesture->fingers, directions); free(directions); From 08c1946d71039e583696842c3558b337aede1cbf Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 28 Feb 2023 16:43:05 +0100 Subject: [PATCH 019/114] Use format_str() throughout --- common/pango.c | 20 ++++---------------- sway/commands.c | 12 +----------- sway/commands/bar.c | 4 +--- sway/config.c | 15 +++++---------- sway/config/output.c | 9 ++------- sway/input/cursor.c | 15 +++------------ sway/input/input-manager.c | 10 +--------- sway/input/keyboard.c | 29 ++++++----------------------- sway/swaynag.c | 14 ++++---------- swaybar/tray/host.c | 10 +++------- swaybar/tray/icon.c | 26 ++++++-------------------- swaybar/tray/watcher.c | 9 +++------ 12 files changed, 39 insertions(+), 134 deletions(-) diff --git a/common/pango.c b/common/pango.c index e04bf80f3..288569b30 100644 --- a/common/pango.c +++ b/common/pango.c @@ -84,18 +84,11 @@ void get_text_size(cairo_t *cairo, const PangoFontDescription *desc, int *width, int *baseline, double scale, bool markup, const char *fmt, ...) { va_list args; va_start(args, fmt); - // Add one since vsnprintf excludes null terminator. - int length = vsnprintf(NULL, 0, fmt, args) + 1; + char *buf = vformat_str(fmt, args); va_end(args); - - char *buf = malloc(length); if (buf == NULL) { - sway_log(SWAY_ERROR, "Failed to allocate memory"); return; } - va_start(args, fmt); - vsnprintf(buf, length, fmt, args); - va_end(args); PangoLayout *layout = get_pango_layout(cairo, desc, buf, scale, markup); pango_cairo_update_layout(cairo, layout); @@ -104,6 +97,7 @@ void get_text_size(cairo_t *cairo, const PangoFontDescription *desc, int *width, *baseline = pango_layout_get_baseline(layout) / PANGO_SCALE; } g_object_unref(layout); + free(buf); } @@ -125,18 +119,11 @@ void render_text(cairo_t *cairo, const PangoFontDescription *desc, double scale, bool markup, const char *fmt, ...) { va_list args; va_start(args, fmt); - // Add one since vsnprintf excludes null terminator. - int length = vsnprintf(NULL, 0, fmt, args) + 1; + char *buf = vformat_str(fmt, args); va_end(args); - - char *buf = malloc(length); if (buf == NULL) { - sway_log(SWAY_ERROR, "Failed to allocate memory"); return; } - va_start(args, fmt); - vsnprintf(buf, length, fmt, args); - va_end(args); PangoLayout *layout = get_pango_layout(cairo, desc, buf, scale, markup); cairo_font_options_t *fo = cairo_font_options_create(); @@ -146,5 +133,6 @@ void render_text(cairo_t *cairo, const PangoFontDescription *desc, pango_cairo_update_layout(cairo, layout); pango_cairo_show_layout(cairo, layout); g_object_unref(layout); + free(buf); } diff --git a/sway/commands.c b/sway/commands.c index 0ea44129e..55eda183c 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -489,20 +489,10 @@ struct cmd_results *cmd_results_new(enum cmd_status status, } results->status = status; if (format) { - char *error = NULL; va_list args; va_start(args, format); - int slen = vsnprintf(NULL, 0, format, args); + results->error = vformat_str(format, args); va_end(args); - if (slen > 0) { - error = malloc(slen + 1); - if (error != NULL) { - va_start(args, format); - vsnprintf(error, slen + 1, format, args); - va_end(args); - } - } - results->error = error; } else { results->error = NULL; } diff --git a/sway/commands/bar.c b/sway/commands/bar.c index 8571d282c..22756acbf 100644 --- a/sway/commands/bar.c +++ b/sway/commands/bar.c @@ -73,12 +73,10 @@ struct cmd_results *cmd_bar(int argc, char **argv) { } ++argv; --argc; } else if (config->reading && !config->current_bar) { - int len = snprintf(NULL, 0, "bar-%d", config->bars->length) + 1; - id = malloc(len * sizeof(char)); + id = format_str("bar-%d", config->bars->length); if (!id) { return cmd_results_new(CMD_FAILURE, "Unable to allocate bar id"); } - snprintf(id, len, "bar-%d", config->bars->length); } else if (!config->reading && strcmp(argv[0], "mode") != 0 && strcmp(argv[0], "hidden_state") != 0) { if (is_subcommand(argv[0])) { diff --git a/sway/config.c b/sway/config.c index f5efa98a8..8c8c148d9 100644 --- a/sway/config.c +++ b/sway/config.c @@ -924,23 +924,18 @@ void config_add_swaynag_warning(char *fmt, ...) { if (config->reading && !config->validating) { va_list args; va_start(args, fmt); - size_t length = vsnprintf(NULL, 0, fmt, args) + 1; + char *str = vformat_str(fmt, args); va_end(args); - - char *temp = malloc(length + 1); - if (!temp) { - sway_log(SWAY_ERROR, "Failed to allocate buffer for warning."); + if (str == NULL) { return; } - va_start(args, fmt); - vsnprintf(temp, length, fmt, args); - va_end(args); - swaynag_log(config->swaynag_command, &config->swaynag_config_errors, "Warning on line %i (%s) '%s': %s", config->current_config_line_number, config->current_config_path, - config->current_config_line, temp); + config->current_config_line, str); + + free(str); } } diff --git a/sway/config/output.c b/sway/config/output.c index 45d2441b1..6fb29ded9 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -162,13 +162,10 @@ static void merge_id_on_name(struct output_config *oc) { char id[128]; output_get_identifier(id, sizeof(id), output); - size_t size = snprintf(NULL, 0, "%s on %s", id, name) + 1; - char *id_on_name = malloc(size); + char *id_on_name = format_str("%s on %s", id, name); if (!id_on_name) { - sway_log(SWAY_ERROR, "Failed to allocate id on name string"); return; } - snprintf(id_on_name, size, "%s on %s", id, name); int i = list_seq_find(config->output_configs, output_name_cmp, id_on_name); if (i >= 0) { @@ -633,9 +630,7 @@ static struct output_config *get_output_config(char *identifier, struct output_config *oc_name = NULL; struct output_config *oc_id = NULL; - size_t length = snprintf(NULL, 0, "%s on %s", identifier, name) + 1; - char *id_on_name = malloc(length); - snprintf(id_on_name, length, "%s on %s", identifier, name); + char *id_on_name = format_str("%s on %s", identifier, name); int i = list_seq_find(config->output_configs, output_name_cmp, id_on_name); if (i >= 0) { oc_id_on_name = config->output_configs->items[i]; diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 15687993b..75d055cd6 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -1273,11 +1273,7 @@ uint32_t get_mouse_bindsym(const char *name, char **error) { // Get event code from name int code = libevdev_event_code_from_name(EV_KEY, name); if (code == -1) { - size_t len = snprintf(NULL, 0, "Unknown event %s", name) + 1; - *error = malloc(len); - if (*error) { - snprintf(*error, len, "Unknown event %s", name); - } + *error = format_str("Unknown event %s", name); return 0; } return code; @@ -1299,13 +1295,8 @@ uint32_t get_mouse_bindcode(const char *name, char **error) { } const char *event = libevdev_event_code_get_name(EV_KEY, code); if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) { - size_t len = snprintf(NULL, 0, "Event code %d (%s) is not a button", - code, event ? event : "(null)") + 1; - *error = malloc(len); - if (*error) { - snprintf(*error, len, "Event code %d (%s) is not a button", - code, event ? event : "(null)"); - } + *error = format_str("Event code %d (%s) is not a button", + code, event ? event : "(null)"); return 0; } return code; diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index ea2cc0381..1115ba5ec 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -80,15 +80,7 @@ char *input_device_get_identifier(struct wlr_input_device *device) { } } - const char *fmt = "%d:%d:%s"; - int len = snprintf(NULL, 0, fmt, vendor, product, name) + 1; - char *identifier = malloc(len); - if (!identifier) { - sway_log(SWAY_ERROR, "Unable to allocate unique input device name"); - return NULL; - } - - snprintf(identifier, len, fmt, vendor, product, name); + char *identifier = format_str("%d:%d:%s", vendor, product, name); free(name); return identifier; } diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 45a588ecb..c3bf4fbbd 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -717,23 +717,11 @@ struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, static void handle_xkb_context_log(struct xkb_context *context, enum xkb_log_level level, const char *format, va_list args) { - va_list args_copy; - va_copy(args_copy, args); - size_t length = vsnprintf(NULL, 0, format, args_copy) + 1; - va_end(args_copy); + char *error = vformat_str(format, args); - char *error = malloc(length); - if (!error) { - sway_log(SWAY_ERROR, "Failed to allocate libxkbcommon log message"); - return; - } - - va_copy(args_copy, args); - vsnprintf(error, length, format, args_copy); - va_end(args_copy); - - if (error[length - 2] == '\n') { - error[length - 2] = '\0'; + size_t len = strlen(error); + if (error[len - 1] == '\n') { + error[len - 1] = '\0'; } sway_log_importance_t importance = SWAY_DEBUG; @@ -768,13 +756,8 @@ struct xkb_keymap *sway_keyboard_compile_keymap(struct input_config *ic, if (!keymap_file) { sway_log_errno(SWAY_ERROR, "cannot read xkb file %s", ic->xkb_file); if (error) { - size_t len = snprintf(NULL, 0, "cannot read xkb file %s: %s", - ic->xkb_file, strerror(errno)) + 1; - *error = malloc(len); - if (*error) { - snprintf(*error, len, "cannot read xkb_file %s: %s", - ic->xkb_file, strerror(errno)); - } + *error = format_str("cannot read xkb file %s: %s", + ic->xkb_file, strerror(errno)); } goto cleanup; } diff --git a/sway/swaynag.c b/sway/swaynag.c index 4a0a6d305..6031174d2 100644 --- a/sway/swaynag.c +++ b/sway/swaynag.c @@ -145,22 +145,16 @@ void swaynag_log(const char *swaynag_command, struct swaynag_instance *swaynag, va_list args; va_start(args, fmt); - size_t length = vsnprintf(NULL, 0, fmt, args) + 1; + char *str = vformat_str(fmt, args); va_end(args); - - char *temp = malloc(length + 1); - if (!temp) { + if (!str) { sway_log(SWAY_ERROR, "Failed to allocate buffer for swaynag log entry."); return; } - va_start(args, fmt); - vsnprintf(temp, length, fmt, args); - va_end(args); + write(swaynag->fd[1], str, strlen(str)); - write(swaynag->fd[1], temp, length); - - free(temp); + free(str); } void swaynag_show(struct swaynag_instance *swaynag) { diff --git a/swaybar/tray/host.c b/swaybar/tray/host.c index ddf2416d6..eea2caa59 100644 --- a/swaybar/tray/host.c +++ b/swaybar/tray/host.c @@ -10,6 +10,7 @@ #include "swaybar/tray/tray.h" #include "list.h" #include "log.h" +#include "stringop.h" static const char *watcher_path = "/StatusNotifierWatcher"; @@ -138,12 +139,10 @@ static int handle_new_watcher(sd_bus_message *msg, bool init_host(struct swaybar_host *host, char *protocol, struct swaybar_tray *tray) { - size_t len = snprintf(NULL, 0, "org.%s.StatusNotifierWatcher", protocol) + 1; - host->watcher_interface = malloc(len); + host->watcher_interface = format_str("org.%s.StatusNotifierWatcher", protocol); if (!host->watcher_interface) { return false; } - snprintf(host->watcher_interface, len, "org.%s.StatusNotifierWatcher", protocol); sd_bus_slot *reg_slot = NULL, *unreg_slot = NULL, *watcher_slot = NULL; int ret = sd_bus_match_signal(tray->bus, ®_slot, host->watcher_interface, @@ -173,13 +172,10 @@ bool init_host(struct swaybar_host *host, char *protocol, } pid_t pid = getpid(); - size_t service_len = snprintf(NULL, 0, "org.%s.StatusNotifierHost-%d", - protocol, pid) + 1; - host->service = malloc(service_len); + host->service = format_str("org.%s.StatusNotifierHost-%d", protocol, pid); if (!host->service) { goto error; } - snprintf(host->service, service_len, "org.%s.StatusNotifierHost-%d", protocol, pid); ret = sd_bus_request_name(tray->bus, host->service, 0); if (ret < 0) { sway_log(SWAY_DEBUG, "Failed to acquire service name: %s", strerror(-ret)); diff --git a/swaybar/tray/icon.c b/swaybar/tray/icon.c index c426c3d4a..b513dca55 100644 --- a/swaybar/tray/icon.c +++ b/swaybar/tray/icon.c @@ -40,9 +40,7 @@ static list_t *get_basedirs(void) { data_dirs = strdup(data_dirs); char *dir = strtok(data_dirs, ":"); do { - size_t path_len = snprintf(NULL, 0, "%s/icons", dir) + 1; - char *path = malloc(path_len); - snprintf(path, path_len, "%s/icons", dir); + char *path = format_str("%s/icons", dir); list_add(basedirs, path); } while ((dir = strtok(NULL, ":"))); free(data_dirs); @@ -206,13 +204,7 @@ static const char *entry_handler(char *group, char *key, char *value, */ static struct icon_theme *read_theme_file(char *basedir, char *theme_name) { // look for index.theme file - size_t path_len = snprintf(NULL, 0, "%s/%s/index.theme", basedir, - theme_name) + 1; - char *path = malloc(path_len); - if (!path) { - return NULL; - } - snprintf(path, path_len, "%s/%s/index.theme", basedir, theme_name); + char *path = format_str("%s/%s/index.theme", basedir, theme_name); FILE *theme_file = fopen(path, "r"); free(path); if (!theme_file) { @@ -416,26 +408,20 @@ static char *find_icon_in_subdir(char *name, char *basedir, char *theme, #endif }; - size_t path_len = snprintf(NULL, 0, "%s/%s/%s/%s.EXT", basedir, theme, - subdir, name) + 1; - char *path = malloc(path_len); - for (size_t i = 0; i < sizeof(extensions) / sizeof(*extensions); ++i) { - snprintf(path, path_len, "%s/%s/%s/%s.%s", basedir, theme, subdir, - name, extensions[i]); + char *path = format_str("%s/%s/%s/%s.%s", + basedir, theme, subdir, name, extensions[i]); if (access(path, R_OK) == 0) { return path; } + free(path); } - free(path); return NULL; } static bool theme_exists_in_basedir(char *theme, char *basedir) { - size_t path_len = snprintf(NULL, 0, "%s/%s", basedir, theme) + 1; - char *path = malloc(path_len); - snprintf(path, path_len, "%s/%s", basedir, theme); + char *path = format_str("%s/%s", basedir, theme); bool ret = dir_exists(path); free(path); return ret; diff --git a/swaybar/tray/watcher.c b/swaybar/tray/watcher.c index 16afc27ce..551e1d12c 100644 --- a/swaybar/tray/watcher.c +++ b/swaybar/tray/watcher.c @@ -6,6 +6,7 @@ #include #include "list.h" #include "log.h" +#include "stringop.h" #include "swaybar/tray/watcher.h" static const char *obj_path = "/StatusNotifierWatcher"; @@ -76,9 +77,7 @@ static int register_sni(sd_bus_message *msg, void *data, sd_bus_error *error) { service = service_or_path; path = "/StatusNotifierItem"; } - size_t id_len = snprintf(NULL, 0, "%s%s", service, path) + 1; - id = malloc(id_len); - snprintf(id, id_len, "%s%s", service, path); + id = format_str("%s%s", service, path); } if (list_seq_find(watcher->items, cmp_id, id) == -1) { @@ -159,9 +158,7 @@ struct swaybar_watcher *create_watcher(char *protocol, sd_bus *bus) { return NULL; } - size_t len = snprintf(NULL, 0, "org.%s.StatusNotifierWatcher", protocol) + 1; - watcher->interface = malloc(len); - snprintf(watcher->interface, len, "org.%s.StatusNotifierWatcher", protocol); + watcher->interface = format_str("org.%s.StatusNotifierWatcher", protocol); sd_bus_slot *signal_slot = NULL, *vtable_slot = NULL; int ret = sd_bus_add_object_vtable(bus, &vtable_slot, obj_path, From 33cfdbe886144e8515593d96a80d850a7c6e382e Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sun, 16 Apr 2023 19:40:39 +0200 Subject: [PATCH 020/114] xdg_shell: Fix crash if popup generates while toplevel is in the scratchpad --- sway/desktop/xdg_shell.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 8da922d50..9b6456da3 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -67,7 +67,13 @@ static void popup_unconstrain(struct sway_xdg_popup *popup) { struct sway_view *view = popup->child.view; struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_popup; - struct sway_output *output = view->container->pending.workspace->output; + struct sway_workspace *workspace = view->container->pending.workspace; + if (!workspace) { + // is null if in the scratchpad + return; + } + + struct sway_output *output = workspace->output; // the output box expressed in the coordinate system of the toplevel parent // of the popup From d5cc474aef6bf5a23694053ab9c8770ea3f21e6f Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 27 Apr 2023 11:19:58 +0200 Subject: [PATCH 021/114] render: pass rendering state together in a struct This lets us easily add rendering state that we need in the future --- include/sway/input/seat.h | 7 +- include/sway/output.h | 11 +- sway/desktop/output.c | 14 +- sway/desktop/render.c | 269 +++++++++++++++----------------- sway/input/seat.c | 5 +- sway/input/seatop_move_tiling.c | 9 +- 6 files changed, 156 insertions(+), 159 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 7b2d3d075..6d29cf3bf 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -12,6 +12,7 @@ #include "sway/input/text_input.h" struct sway_seat; +struct render_context; struct sway_seatop_impl { void (*button)(struct sway_seat *seat, uint32_t time_msec, @@ -49,8 +50,7 @@ struct sway_seatop_impl { uint32_t time_msec, enum wlr_tablet_tool_tip_state state); void (*end)(struct sway_seat *seat); void (*unref)(struct sway_seat *seat, struct sway_container *con); - void (*render)(struct sway_seat *seat, struct sway_output *output, - const pixman_region32_t *damage); + void (*render)(struct sway_seat *seat, struct render_context *ctx); bool allow_set_cursor; }; @@ -356,8 +356,7 @@ void seatop_unref(struct sway_seat *seat, struct sway_container *con); * Instructs a seatop to render anything that it needs to render * (eg. dropzone for move-tiling) */ -void seatop_render(struct sway_seat *seat, struct sway_output *output, - const pixman_region32_t *damage); +void seatop_render(struct sway_seat *seat, struct render_context *ctx); bool seatop_allows_set_cursor(struct sway_seat *seat); diff --git a/include/sway/output.h b/include/sway/output.h index 04202976c..b397c8e2d 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -65,6 +65,12 @@ struct sway_output_non_desktop { struct wl_listener destroy; }; +struct render_context { + struct sway_output *output; + struct wlr_renderer *renderer; + const pixman_region32_t *output_damage; +}; + struct sway_output *output_create(struct wlr_output *wlr_output); void output_destroy(struct sway_output *output); @@ -115,7 +121,7 @@ bool output_has_opaque_overlay_layer_surface(struct sway_output *output); struct sway_workspace *output_get_active_workspace(struct sway_output *output); -void output_render(struct sway_output *output, pixman_region32_t *damage); +void output_render(struct render_context *ctx); void output_surface_for_each_surface(struct sway_output *output, struct wlr_surface *surface, double ox, double oy, @@ -168,8 +174,7 @@ void output_get_box(struct sway_output *output, struct wlr_box *box); enum sway_container_layout output_get_default_layout( struct sway_output *output); -void render_rect(struct sway_output *output, - const pixman_region32_t *output_damage, const struct wlr_box *_box, +void render_rect(struct render_context *ctx, const struct wlr_box *_box, float color[static 4]); void premultiply_alpha(float color[4], float opacity); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 2255b5518..02e08bd2d 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -613,10 +613,22 @@ static int output_repaint_timer_handler(void *data) { pixman_region32_init(&damage); wlr_damage_ring_get_buffer_damage(&output->damage_ring, buffer_age, &damage); + if (debug.damage == DAMAGE_RERENDER) { + int width, height; + wlr_output_transformed_resolution(wlr_output, &width, &height); + pixman_region32_union_rect(&damage, &damage, 0, 0, width, height); + } + + struct render_context ctx = { + .output_damage = &damage, + .renderer = wlr_output->renderer, + .output = output, + }; + struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - output_render(output, &damage); + output_render(&ctx); pixman_region32_fini(&damage); diff --git a/sway/desktop/render.c b/sway/desktop/render.c index a4d633e09..f011e0ffe 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -32,6 +32,7 @@ #endif struct render_data { + struct render_context *ctx; const pixman_region32_t *damage; float alpha; struct wlr_box *clip_box; @@ -101,18 +102,17 @@ static void set_scale_filter(struct wlr_output *wlr_output, #endif } -static void render_texture(struct wlr_output *wlr_output, - const pixman_region32_t *output_damage, struct wlr_texture *texture, +static void render_texture(struct render_context *ctx, struct wlr_texture *texture, const struct wlr_fbox *src_box, const struct wlr_box *dst_box, const float matrix[static 9], float alpha) { - struct wlr_renderer *renderer = wlr_output->renderer; - struct sway_output *output = wlr_output->data; + struct wlr_renderer *renderer = ctx->renderer; + struct sway_output *output = ctx->output; pixman_region32_t damage; pixman_region32_init(&damage); pixman_region32_union_rect(&damage, &damage, dst_box->x, dst_box->y, dst_box->width, dst_box->height); - pixman_region32_intersect(&damage, &damage, output_damage); + pixman_region32_intersect(&damage, &damage, ctx->output_damage); bool damaged = pixman_region32_not_empty(&damage); if (!damaged) { goto damage_finish; @@ -121,8 +121,8 @@ static void render_texture(struct wlr_output *wlr_output, int nrects; pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); for (int i = 0; i < nrects; ++i) { - scissor_output(wlr_output, &rects[i]); - set_scale_filter(wlr_output, texture, output->scale_filter); + scissor_output(output->wlr_output, &rects[i]); + set_scale_filter(output->wlr_output, texture, output->scale_filter); if (src_box != NULL) { wlr_render_subtexture_with_matrix(renderer, texture, src_box, matrix, alpha); } else { @@ -139,7 +139,6 @@ static void render_surface_iterator(struct sway_output *output, struct wlr_box *_box, void *_data) { struct render_data *data = _data; struct wlr_output *wlr_output = output->wlr_output; - const pixman_region32_t *output_damage = data->damage; float alpha = data->alpha; struct wlr_texture *texture = wlr_surface_get_texture(surface); @@ -167,73 +166,68 @@ static void render_surface_iterator(struct sway_output *output, } scale_box(&dst_box, wlr_output->scale); - render_texture(wlr_output, output_damage, texture, + render_texture(data->ctx, texture, &src_box, &dst_box, matrix, alpha); wlr_presentation_surface_sampled_on_output(server.presentation, surface, wlr_output); } -static void render_layer_toplevel(struct sway_output *output, - const pixman_region32_t *damage, struct wl_list *layer_surfaces) { +static void render_layer_toplevel(struct render_context *ctx, struct wl_list *layer_surfaces) { struct render_data data = { - .damage = damage, .alpha = 1.0f, + .ctx = ctx, }; - output_layer_for_each_toplevel_surface(output, layer_surfaces, + output_layer_for_each_toplevel_surface(ctx->output, layer_surfaces, render_surface_iterator, &data); } -static void render_layer_popups(struct sway_output *output, - const pixman_region32_t *damage, struct wl_list *layer_surfaces) { +static void render_layer_popups(struct render_context *ctx, struct wl_list *layer_surfaces) { struct render_data data = { - .damage = damage, .alpha = 1.0f, + .ctx = ctx, }; - output_layer_for_each_popup_surface(output, layer_surfaces, + output_layer_for_each_popup_surface(ctx->output, layer_surfaces, render_surface_iterator, &data); } #if HAVE_XWAYLAND -static void render_unmanaged(struct sway_output *output, - const pixman_region32_t *damage, struct wl_list *unmanaged) { +static void render_unmanaged(struct render_context *ctx, struct wl_list *unmanaged) { struct render_data data = { - .damage = damage, .alpha = 1.0f, + .ctx = ctx, }; - output_unmanaged_for_each_surface(output, unmanaged, + output_unmanaged_for_each_surface(ctx->output, unmanaged, render_surface_iterator, &data); } #endif -static void render_drag_icons(struct sway_output *output, - const pixman_region32_t *damage, struct wl_list *drag_icons) { +static void render_drag_icons(struct render_context *ctx, struct wl_list *drag_icons) { struct render_data data = { - .damage = damage, .alpha = 1.0f, + .ctx = ctx, }; - output_drag_icons_for_each_surface(output, drag_icons, + output_drag_icons_for_each_surface(ctx->output, drag_icons, render_surface_iterator, &data); } // _box.x and .y are expected to be layout-local // _box.width and .height are expected to be output-buffer-local -void render_rect(struct sway_output *output, - const pixman_region32_t *output_damage, const struct wlr_box *_box, +void render_rect(struct render_context *ctx, const struct wlr_box *_box, float color[static 4]) { - struct wlr_output *wlr_output = output->wlr_output; - struct wlr_renderer *renderer = wlr_output->renderer; + struct wlr_output *wlr_output = ctx->output->wlr_output; + struct wlr_renderer *renderer = ctx->renderer; struct wlr_box box; memcpy(&box, _box, sizeof(struct wlr_box)); - box.x -= output->lx * wlr_output->scale; - box.y -= output->ly * wlr_output->scale; + box.x -= ctx->output->lx * wlr_output->scale; + box.y -= ctx->output->ly * wlr_output->scale; pixman_region32_t damage; pixman_region32_init(&damage); pixman_region32_union_rect(&damage, &damage, box.x, box.y, box.width, box.height); - pixman_region32_intersect(&damage, &damage, output_damage); + pixman_region32_intersect(&damage, &damage, ctx->output_damage); bool damaged = pixman_region32_not_empty(&damage); if (!damaged) { goto damage_finish; @@ -258,11 +252,11 @@ void premultiply_alpha(float color[4], float opacity) { color[2] *= color[3]; } -static void render_view_toplevels(struct sway_view *view, - struct sway_output *output, const pixman_region32_t *damage, float alpha) { +static void render_view_toplevels(struct render_context *ctx, + struct sway_view *view, float alpha) { struct render_data data = { - .damage = damage, .alpha = alpha, + .ctx = ctx, }; struct wlr_box clip_box; if (!container_is_current_floating(view->container)) { @@ -274,25 +268,26 @@ static void render_view_toplevels(struct sway_view *view, } // Render all toplevels without descending into popups double ox = view->container->surface_x - - output->lx - view->geometry.x; + ctx->output->lx - view->geometry.x; double oy = view->container->surface_y - - output->ly - view->geometry.y; - output_surface_for_each_surface(output, view->surface, ox, oy, + ctx->output->ly - view->geometry.y; + output_surface_for_each_surface(ctx->output, view->surface, ox, oy, render_surface_iterator, &data); } -static void render_view_popups(struct sway_view *view, - struct sway_output *output, const pixman_region32_t *damage, float alpha) { +static void render_view_popups(struct render_context *ctx, struct sway_view *view, + float alpha) { struct render_data data = { - .damage = damage, .alpha = alpha, + .ctx = ctx, }; - output_view_for_each_popup_surface(output, view, + output_view_for_each_popup_surface(ctx->output, view, render_surface_iterator, &data); } -static void render_saved_view(struct sway_view *view, - struct sway_output *output, const pixman_region32_t *damage, float alpha) { +static void render_saved_view(struct render_context *ctx, struct sway_view *view, + float alpha) { + struct sway_output *output = ctx->output; struct wlr_output *wlr_output = output->wlr_output; if (wl_list_empty(&view->saved_buffers)) { @@ -343,7 +338,7 @@ static void render_saved_view(struct sway_view *view, } scale_box(&dst_box, wlr_output->scale); - render_texture(wlr_output, damage, saved_buf->buffer->texture, + render_texture(ctx, saved_buf->buffer->texture, &saved_buf->source_box, &dst_box, matrix, alpha); } @@ -355,13 +350,13 @@ static void render_saved_view(struct sway_view *view, /** * Render a view's surface and left/bottom/right borders. */ -static void render_view(struct sway_output *output, const pixman_region32_t *damage, +static void render_view(struct render_context *ctx, struct sway_container *con, struct border_colors *colors) { struct sway_view *view = con->view; if (!wl_list_empty(&view->saved_buffers)) { - render_saved_view(view, output, damage, view->container->alpha); + render_saved_view(ctx, view, view->container->alpha); } else if (view->surface) { - render_view_toplevels(view, output, damage, view->container->alpha); + render_view_toplevels(ctx, view, view->container->alpha); } if (con->current.border == B_NONE || con->current.border == B_CSD) { @@ -369,7 +364,7 @@ static void render_view(struct sway_output *output, const pixman_region32_t *dam } struct wlr_box box; - float output_scale = output->wlr_output->scale; + float output_scale = ctx->output->wlr_output->scale; float color[4]; struct sway_container_state *state = &con->current; @@ -381,7 +376,7 @@ static void render_view(struct sway_output *output, const pixman_region32_t *dam box.width = state->border_thickness; box.height = state->content_height; scale_box(&box, output_scale); - render_rect(output, damage, &box, color); + render_rect(ctx, &box, color); } list_t *siblings = container_get_current_siblings(con); @@ -400,7 +395,7 @@ static void render_view(struct sway_output *output, const pixman_region32_t *dam box.width = state->border_thickness; box.height = state->content_height; scale_box(&box, output_scale); - render_rect(output, damage, &box, color); + render_rect(ctx, &box, color); } if (state->border_bottom) { @@ -415,7 +410,7 @@ static void render_view(struct sway_output *output, const pixman_region32_t *dam box.width = state->width; box.height = state->border_thickness; scale_box(&box, output_scale); - render_rect(output, damage, &box, color); + render_rect(ctx, &box, color); } } @@ -428,13 +423,13 @@ static void render_view(struct sway_output *output, const pixman_region32_t *dam * The height is: 1px border, 3px padding, font height, 3px padding, 1px border * The left side is: 1px border, 2px padding, title */ -static void render_titlebar(struct sway_output *output, - const pixman_region32_t *output_damage, struct sway_container *con, +static void render_titlebar(struct render_context *ctx, struct sway_container *con, int x, int y, int width, struct border_colors *colors, struct wlr_texture *title_texture, struct wlr_texture *marks_texture) { struct wlr_box box; float color[4]; + struct sway_output *output = ctx->output; float output_scale = output->wlr_output->scale; double output_x = output->lx; double output_y = output->ly; @@ -451,7 +446,7 @@ static void render_titlebar(struct sway_output *output, box.width = width; box.height = titlebar_border_thickness; scale_box(&box, output_scale); - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); // Single pixel bar below title box.x = x; @@ -459,7 +454,7 @@ static void render_titlebar(struct sway_output *output, box.width = width; box.height = titlebar_border_thickness; scale_box(&box, output_scale); - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); // Single pixel left edge box.x = x; @@ -467,7 +462,7 @@ static void render_titlebar(struct sway_output *output, box.width = titlebar_border_thickness; box.height = container_titlebar_height() - titlebar_border_thickness * 2; scale_box(&box, output_scale); - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); // Single pixel right edge box.x = x + width - titlebar_border_thickness; @@ -475,7 +470,7 @@ static void render_titlebar(struct sway_output *output, box.width = titlebar_border_thickness; box.height = container_titlebar_height() - titlebar_border_thickness * 2; scale_box(&box, output_scale); - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); int inner_x = x - output_x + titlebar_h_padding; int bg_y = y + titlebar_border_thickness; @@ -524,7 +519,7 @@ static void render_titlebar(struct sway_output *output, if (ob_inner_width < texture_box.width) { texture_box.width = ob_inner_width; } - render_texture(output->wlr_output, output_damage, marks_texture, + render_texture(ctx, marks_texture, NULL, &texture_box, matrix, con->alpha); // Padding above @@ -534,12 +529,12 @@ static void render_titlebar(struct sway_output *output, box.y = roundf((y + titlebar_border_thickness) * output_scale); box.width = texture_box.width; box.height = ob_padding_above; - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); // Padding below box.y += ob_padding_above + texture_box.height; box.height = ob_padding_below; - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); } // Title text @@ -600,7 +595,7 @@ static void render_titlebar(struct sway_output *output, texture_box.width = ob_inner_width - ob_marks_width; } - render_texture(output->wlr_output, output_damage, title_texture, + render_texture(ctx, title_texture, NULL, &texture_box, matrix, con->alpha); // Padding above @@ -610,12 +605,12 @@ static void render_titlebar(struct sway_output *output, box.y = roundf((y + titlebar_border_thickness) * output_scale); box.width = texture_box.width; box.height = ob_padding_above; - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); // Padding below box.y += ob_padding_above + texture_box.height; box.height = ob_padding_below; - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); } // Determine the left + right extends of the textures (output-buffer local) @@ -649,7 +644,7 @@ static void render_titlebar(struct sway_output *output, box.x = ob_left_x + ob_left_width + round(output_x * output_scale); box.y = roundf(bg_y * output_scale); box.height = ob_bg_height; - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); } // Padding on left side @@ -663,7 +658,7 @@ static void render_titlebar(struct sway_output *output, if (box.x + box.width < left_x) { box.width += left_x - box.x - box.width; } - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); // Padding on right side box.x = x + width - titlebar_h_padding; @@ -677,14 +672,13 @@ static void render_titlebar(struct sway_output *output, box.width += box.x - right_rx; box.x = right_rx; } - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); } /** * Render the top border line for a view using "border pixel". */ -static void render_top_border(struct sway_output *output, - const pixman_region32_t *output_damage, struct sway_container *con, +static void render_top_border(struct render_context *ctx, struct sway_container *con, struct border_colors *colors) { struct sway_container_state *state = &con->current; if (!state->border_top) { @@ -692,7 +686,7 @@ static void render_top_border(struct sway_output *output, } struct wlr_box box; float color[4]; - float output_scale = output->wlr_output->scale; + float output_scale = ctx->output->wlr_output->scale; // Child border - top edge memcpy(&color, colors->child_border, sizeof(float) * 4); @@ -702,7 +696,7 @@ static void render_top_border(struct sway_output *output, box.width = state->width; box.height = state->border_thickness; scale_box(&box, output_scale); - render_rect(output, output_damage, &box, color); + render_rect(ctx, &box, color); } struct parent_data { @@ -713,8 +707,8 @@ struct parent_data { struct sway_container *active_child; }; -static void render_container(struct sway_output *output, - const pixman_region32_t *damage, struct sway_container *con, bool parent_focused); +static void render_container(struct render_context *ctx, + struct sway_container *con, bool parent_focused); /** * Render a container's children using a L_HORIZ or L_VERT layout. @@ -722,8 +716,7 @@ static void render_container(struct sway_output *output, * Wrap child views in borders and leave child containers borderless because * they'll apply their own borders to their children. */ -static void render_containers_linear(struct sway_output *output, - const pixman_region32_t *damage, struct parent_data *parent) { +static void render_containers_linear(struct render_context *ctx, struct parent_data *parent) { for (int i = 0; i < parent->children->length; ++i) { struct sway_container *child = parent->children->items[i]; @@ -753,15 +746,15 @@ static void render_containers_linear(struct sway_output *output, } if (state->border == B_NORMAL) { - render_titlebar(output, damage, child, floor(state->x), + render_titlebar(ctx, child, floor(state->x), floor(state->y), state->width, colors, title_texture, marks_texture); } else if (state->border == B_PIXEL) { - render_top_border(output, damage, child, colors); + render_top_border(ctx, child, colors); } - render_view(output, damage, child, colors); + render_view(ctx, child, colors); } else { - render_container(output, damage, child, + render_container(ctx, child, parent->focused || child->current.focused); } } @@ -778,8 +771,7 @@ static bool container_has_focused_child(struct sway_container *con) { /** * Render a container's children using the L_TABBED layout. */ -static void render_containers_tabbed(struct sway_output *output, - const pixman_region32_t *damage, struct parent_data *parent) { +static void render_containers_tabbed(struct render_context *ctx, struct parent_data *parent) { if (!parent->children->length) { return; } @@ -827,7 +819,7 @@ static void render_containers_tabbed(struct sway_output *output, tab_width = parent->box.width - tab_width * i; } - render_titlebar(output, damage, child, x, parent->box.y, tab_width, + render_titlebar(ctx, child, x, parent->box.y, tab_width, colors, title_texture, marks_texture); if (child == current) { @@ -837,9 +829,9 @@ static void render_containers_tabbed(struct sway_output *output, // Render surface and left/right/bottom borders if (current->view) { - render_view(output, damage, current, current_colors); + render_view(ctx, current, current_colors); } else { - render_container(output, damage, current, + render_container(ctx, current, parent->focused || current->current.focused); } } @@ -847,8 +839,7 @@ static void render_containers_tabbed(struct sway_output *output, /** * Render a container's children using the L_STACKED layout. */ -static void render_containers_stacked(struct sway_output *output, - const pixman_region32_t *damage, struct parent_data *parent) { +static void render_containers_stacked(struct render_context *ctx, struct parent_data *parent) { if (!parent->children->length) { return; } @@ -890,7 +881,7 @@ static void render_containers_stacked(struct sway_output *output, } int y = parent->box.y + titlebar_height * i; - render_titlebar(output, damage, child, parent->box.x, y, + render_titlebar(ctx, child, parent->box.x, y, parent->box.width, colors, title_texture, marks_texture); if (child == current) { @@ -900,19 +891,18 @@ static void render_containers_stacked(struct sway_output *output, // Render surface and left/right/bottom borders if (current->view) { - render_view(output, damage, current, current_colors); + render_view(ctx, current, current_colors); } else { - render_container(output, damage, current, + render_container(ctx, current, parent->focused || current->current.focused); } } -static void render_containers(struct sway_output *output, - const pixman_region32_t *damage, struct parent_data *parent) { +static void render_containers(struct render_context *ctx, struct parent_data *parent) { if (config->hide_lone_tab && parent->children->length == 1) { struct sway_container *child = parent->children->items[0]; if (child->view) { - render_containers_linear(output,damage, parent); + render_containers_linear(ctx, parent); return; } } @@ -921,19 +911,19 @@ static void render_containers(struct sway_output *output, case L_NONE: case L_HORIZ: case L_VERT: - render_containers_linear(output, damage, parent); + render_containers_linear(ctx, parent); break; case L_STACKED: - render_containers_stacked(output, damage, parent); + render_containers_stacked(ctx, parent); break; case L_TABBED: - render_containers_tabbed(output, damage, parent); + render_containers_tabbed(ctx, parent); break; } } -static void render_container(struct sway_output *output, - const pixman_region32_t *damage, struct sway_container *con, bool focused) { +static void render_container(struct render_context *ctx, + struct sway_container *con, bool focused) { struct parent_data data = { .layout = con->current.layout, .box = { @@ -946,11 +936,11 @@ static void render_container(struct sway_output *output, .focused = focused, .active_child = con->current.focused_inactive_child, }; - render_containers(output, damage, &data); + render_containers(ctx, &data); } -static void render_workspace(struct sway_output *output, - const pixman_region32_t *damage, struct sway_workspace *ws, bool focused) { +static void render_workspace(struct render_context *ctx, + struct sway_workspace *ws, bool focused) { struct parent_data data = { .layout = ws->current.layout, .box = { @@ -963,11 +953,11 @@ static void render_workspace(struct sway_output *output, .focused = focused, .active_child = ws->current.focused_inactive_child, }; - render_containers(output, damage, &data); + render_containers(ctx, &data); } -static void render_floating_container(struct sway_output *soutput, - const pixman_region32_t *damage, struct sway_container *con) { +static void render_floating_container(struct render_context *ctx, + struct sway_container *con) { if (con->view) { struct sway_view *view = con->view; struct border_colors *colors; @@ -989,20 +979,19 @@ static void render_floating_container(struct sway_output *soutput, } if (con->current.border == B_NORMAL) { - render_titlebar(soutput, damage, con, floor(con->current.x), + render_titlebar(ctx, con, floor(con->current.x), floor(con->current.y), con->current.width, colors, title_texture, marks_texture); } else if (con->current.border == B_PIXEL) { - render_top_border(soutput, damage, con, colors); + render_top_border(ctx, con, colors); } - render_view(soutput, damage, con, colors); + render_view(ctx, con, colors); } else { - render_container(soutput, damage, con, con->current.focused); + render_container(ctx, con, con->current.focused); } } -static void render_floating(struct sway_output *soutput, - const pixman_region32_t *damage) { +static void render_floating(struct render_context *ctx) { for (int i = 0; i < root->outputs->length; ++i) { struct sway_output *output = root->outputs->items[i]; for (int j = 0; j < output->current.workspaces->length; ++j) { @@ -1015,23 +1004,24 @@ static void render_floating(struct sway_output *soutput, if (floater->current.fullscreen_mode != FULLSCREEN_NONE) { continue; } - render_floating_container(soutput, damage, floater); + render_floating_container(ctx, floater); } } } } -static void render_seatops(struct sway_output *output, - const pixman_region32_t *damage) { +static void render_seatops(struct render_context *ctx) { struct sway_seat *seat; wl_list_for_each(seat, &server.input->seats, link) { - seatop_render(seat, output, damage); + seatop_render(seat, ctx); } } -void output_render(struct sway_output *output, pixman_region32_t *damage) { - struct wlr_output *wlr_output = output->wlr_output; - struct wlr_renderer *renderer = output->server->renderer; +void output_render(struct render_context *ctx) { + struct wlr_output *wlr_output = ctx->output->wlr_output; + struct wlr_renderer *renderer = ctx->renderer; + struct sway_output *output = ctx->output; + const pixman_region32_t *damage = ctx->output_damage; struct sway_workspace *workspace = output->current.active_workspace; if (workspace == NULL) { @@ -1047,12 +1037,6 @@ void output_render(struct sway_output *output, pixman_region32_t *damage) { return; } - if (debug.damage == DAMAGE_RERENDER) { - int width, height; - wlr_output_transformed_resolution(wlr_output, &width, &height); - pixman_region32_union_rect(damage, damage, 0, 0, width, height); - } - if (!pixman_region32_not_empty(damage)) { // Output isn't damaged but needs buffer swap goto renderer_end; @@ -1077,8 +1061,8 @@ void output_render(struct sway_output *output, pixman_region32_t *damage) { if (server.session_lock.lock != NULL) { struct render_data data = { - .damage = damage, .alpha = 1.0f, + .ctx = ctx, }; struct wlr_session_lock_surface_v1 *lock_surface; @@ -1113,13 +1097,12 @@ void output_render(struct sway_output *output, pixman_region32_t *damage) { if (fullscreen_con->view) { if (!wl_list_empty(&fullscreen_con->view->saved_buffers)) { - render_saved_view(fullscreen_con->view, output, damage, 1.0f); + render_saved_view(ctx, fullscreen_con->view, 1.0f); } else if (fullscreen_con->view->surface) { - render_view_toplevels(fullscreen_con->view, - output, damage, 1.0f); + render_view_toplevels(ctx, fullscreen_con->view, 1.0f); } } else { - render_container(output, damage, fullscreen_con, + render_container(ctx, fullscreen_con, fullscreen_con->current.focused); } @@ -1127,11 +1110,11 @@ void output_render(struct sway_output *output, pixman_region32_t *damage) { struct sway_container *floater = workspace->current.floating->items[i]; if (container_is_transient_for(floater, fullscreen_con)) { - render_floating_container(output, damage, floater); + render_floating_container(ctx, floater); } } #if HAVE_XWAYLAND - render_unmanaged(output, damage, &root->xwayland_unmanaged); + render_unmanaged(ctx, &root->xwayland_unmanaged); #endif } else { float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; @@ -1143,41 +1126,41 @@ void output_render(struct sway_output *output, pixman_region32_t *damage) { wlr_renderer_clear(renderer, clear_color); } - render_layer_toplevel(output, damage, + render_layer_toplevel(ctx, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); - render_layer_toplevel(output, damage, + render_layer_toplevel(ctx, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); - render_workspace(output, damage, workspace, workspace->current.focused); - render_floating(output, damage); + render_workspace(ctx, workspace, workspace->current.focused); + render_floating(ctx); #if HAVE_XWAYLAND - render_unmanaged(output, damage, &root->xwayland_unmanaged); + render_unmanaged(ctx, &root->xwayland_unmanaged); #endif - render_layer_toplevel(output, damage, + render_layer_toplevel(ctx, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); - render_layer_popups(output, damage, + render_layer_popups(ctx, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); - render_layer_popups(output, damage, + render_layer_popups(ctx, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); - render_layer_popups(output, damage, + render_layer_popups(ctx, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); } - render_seatops(output, damage); + render_seatops(ctx); struct sway_seat *seat = input_manager_current_seat(); struct sway_container *focus = seat_get_focused_container(seat); if (focus && focus->view) { - render_view_popups(focus->view, output, damage, focus->alpha); + render_view_popups(ctx, focus->view, focus->alpha); } render_overlay: - render_layer_toplevel(output, damage, + render_layer_toplevel(ctx, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); - render_layer_popups(output, damage, + render_layer_popups(ctx, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); - render_drag_icons(output, damage, &root->drag_icons); + render_drag_icons(ctx, &root->drag_icons); renderer_end: wlr_renderer_scissor(renderer, NULL); diff --git a/sway/input/seat.c b/sway/input/seat.c index 14931ce0f..6b95e46aa 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1726,10 +1726,9 @@ void seatop_end(struct sway_seat *seat) { seat->seatop_impl = NULL; } -void seatop_render(struct sway_seat *seat, struct sway_output *output, - const pixman_region32_t *damage) { +void seatop_render(struct sway_seat *seat, struct render_context *ctx) { if (seat->seatop_impl->render) { - seat->seatop_impl->render(seat, output, damage); + seat->seatop_impl->render(seat, ctx); } } diff --git a/sway/input/seatop_move_tiling.c b/sway/input/seatop_move_tiling.c index 5498e9092..26704d0d9 100644 --- a/sway/input/seatop_move_tiling.c +++ b/sway/input/seatop_move_tiling.c @@ -31,21 +31,20 @@ struct seatop_move_tiling_event { bool insert_after_target; }; -static void handle_render(struct sway_seat *seat, - struct sway_output *output, const pixman_region32_t *damage) { +static void handle_render(struct sway_seat *seat, struct render_context *ctx) { struct seatop_move_tiling_event *e = seat->seatop_data; if (!e->threshold_reached) { return; } - if (e->target_node && node_get_output(e->target_node) == output) { + if (e->target_node && node_get_output(e->target_node) == ctx->output) { float color[4]; memcpy(&color, config->border_colors.focused.indicator, sizeof(float) * 4); premultiply_alpha(color, 0.5); struct wlr_box box; memcpy(&box, &e->drop_box, sizeof(struct wlr_box)); - scale_box(&box, output->wlr_output->scale); - render_rect(output, damage, &box, color); + scale_box(&box, ctx->output->wlr_output->scale); + render_rect(ctx, &box, color); } } From 07cdf6ccd06e7bf1a7b828ea2a80d9db6e25263b Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 27 Apr 2023 11:28:57 +0200 Subject: [PATCH 022/114] render: Don't pass matrix into render_texture --- sway/desktop/render.c | 39 +++++++++++++-------------------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index f011e0ffe..a3ae5efc2 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -104,10 +104,18 @@ static void set_scale_filter(struct wlr_output *wlr_output, static void render_texture(struct render_context *ctx, struct wlr_texture *texture, const struct wlr_fbox *src_box, const struct wlr_box *dst_box, - const float matrix[static 9], float alpha) { + enum wl_output_transform transform, float alpha) { struct wlr_renderer *renderer = ctx->renderer; struct sway_output *output = ctx->output; + struct wlr_box proj_box = *dst_box; + scale_box(&proj_box, output->wlr_output->scale); + + float matrix[9]; + enum wl_output_transform inv_transform = wlr_output_transform_invert(transform); + wlr_matrix_project_box(matrix, &proj_box, inv_transform, 0, + output->wlr_output->transform_matrix); + pixman_region32_t damage; pixman_region32_init(&damage); pixman_region32_union_rect(&damage, &damage, dst_box->x, dst_box->y, @@ -152,12 +160,6 @@ static void render_surface_iterator(struct sway_output *output, struct wlr_box proj_box = *_box; scale_box(&proj_box, wlr_output->scale); - float matrix[9]; - enum wl_output_transform transform = - wlr_output_transform_invert(surface->current.transform); - wlr_matrix_project_box(matrix, &proj_box, transform, 0.0, - wlr_output->transform_matrix); - struct wlr_box dst_box = *_box; struct wlr_box *clip_box = data->clip_box; if (clip_box != NULL) { @@ -167,7 +169,7 @@ static void render_surface_iterator(struct sway_output *output, scale_box(&dst_box, wlr_output->scale); render_texture(data->ctx, texture, - &src_box, &dst_box, matrix, alpha); + &src_box, &dst_box, surface->current.transform, alpha); wlr_presentation_surface_sampled_on_output(server.presentation, surface, wlr_output); @@ -323,11 +325,6 @@ static void render_saved_view(struct render_context *ctx, struct sway_view *view struct wlr_box dst_box = proj_box; scale_box(&proj_box, wlr_output->scale); - float matrix[9]; - enum wl_output_transform transform = wlr_output_transform_invert(saved_buf->transform); - wlr_matrix_project_box(matrix, &proj_box, transform, 0, - wlr_output->transform_matrix); - if (!floating) { dst_box.width = fmin(dst_box.width, view->container->current.content_width - @@ -339,7 +336,7 @@ static void render_saved_view(struct render_context *ctx, struct sway_view *view scale_box(&dst_box, wlr_output->scale); render_texture(ctx, saved_buf->buffer->texture, - &saved_buf->source_box, &dst_box, matrix, alpha); + &saved_buf->source_box, &dst_box, saved_buf->transform, alpha); } // FIXME: we should set the surface that this saved buffer originates from @@ -511,16 +508,11 @@ static void render_titlebar(struct render_context *ctx, struct sway_container *c texture_box.y = round((bg_y - output_y) * output_scale) + ob_padding_above; - float matrix[9]; - wlr_matrix_project_box(matrix, &texture_box, - WL_OUTPUT_TRANSFORM_NORMAL, - 0.0, output->wlr_output->transform_matrix); - if (ob_inner_width < texture_box.width) { texture_box.width = ob_inner_width; } render_texture(ctx, marks_texture, - NULL, &texture_box, matrix, con->alpha); + NULL, &texture_box, WL_OUTPUT_TRANSFORM_NORMAL, con->alpha); // Padding above memcpy(&color, colors->background, sizeof(float) * 4); @@ -586,17 +578,12 @@ static void render_titlebar(struct render_context *ctx, struct sway_container *c texture_box.y = round((bg_y - output_y) * output_scale) + ob_padding_above; - float matrix[9]; - wlr_matrix_project_box(matrix, &texture_box, - WL_OUTPUT_TRANSFORM_NORMAL, - 0.0, output->wlr_output->transform_matrix); - if (ob_inner_width - ob_marks_width < texture_box.width) { texture_box.width = ob_inner_width - ob_marks_width; } render_texture(ctx, title_texture, - NULL, &texture_box, matrix, con->alpha); + NULL, &texture_box, WL_OUTPUT_TRANSFORM_NORMAL, con->alpha); // Padding above memcpy(&color, colors->background, sizeof(float) * 4); From 029b99b4829148ef3e899f21bba4fe2a1d4d0db9 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Tue, 2 May 2023 11:43:44 -0400 Subject: [PATCH 023/114] render: Use wlr_render_pass --- include/sway/output.h | 2 + sway/desktop/output.c | 26 ++++++- sway/desktop/render.c | 171 ++++++++++++++++++++---------------------- 3 files changed, 109 insertions(+), 90 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index b397c8e2d..f6dc6af2b 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -69,6 +69,8 @@ struct render_context { struct sway_output *output; struct wlr_renderer *renderer; const pixman_region32_t *output_damage; + + struct wlr_render_pass *pass; }; struct sway_output *output_create(struct wlr_output *wlr_output); diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 02e08bd2d..01bc87bbb 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -604,9 +605,21 @@ static int output_repaint_timer_handler(void *data) { } } + if (!wlr_output_configure_primary_swapchain(wlr_output, NULL, &wlr_output->swapchain)) { + return false; + } + int buffer_age; - if (!wlr_output_attach_render(output->wlr_output, &buffer_age)) { - return 0; + struct wlr_buffer *buffer = wlr_swapchain_acquire(wlr_output->swapchain, &buffer_age); + if (buffer == NULL) { + return false; + } + + struct wlr_render_pass *render_pass = wlr_renderer_begin_buffer_pass( + wlr_output->renderer, buffer); + if (render_pass == NULL) { + wlr_buffer_unlock(buffer); + return false; } pixman_region32_t damage; @@ -623,6 +636,7 @@ static int output_repaint_timer_handler(void *data) { .output_damage = &damage, .renderer = wlr_output->renderer, .output = output, + .pass = render_pass, }; struct timespec now; @@ -632,6 +646,14 @@ static int output_repaint_timer_handler(void *data) { pixman_region32_fini(&damage); + if (!wlr_render_pass_submit(render_pass)) { + wlr_buffer_unlock(buffer); + return false; + } + + wlr_output_attach_buffer(wlr_output, buffer); + wlr_buffer_unlock(buffer); + if (!wlr_output_commit(wlr_output)) { return 0; } diff --git a/sway/desktop/render.c b/sway/desktop/render.c index a3ae5efc2..37e84647c 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -38,6 +38,23 @@ struct render_data { struct wlr_box *clip_box; }; +static void transform_output_damage(pixman_region32_t *damage, struct wlr_output *output) { + int ow, oh; + wlr_output_transformed_resolution(output, &ow, &oh); + enum wl_output_transform transform = + wlr_output_transform_invert(output->transform); + wlr_region_transform(damage, damage, transform, ow, oh); +} + +static void transform_output_box(struct wlr_box *box, struct wlr_output *output) { + int ow, oh; + wlr_output_transformed_resolution(output, &ow, &oh); + enum wl_output_transform transform = + wlr_output_transform_invert(output->transform); + wlr_box_transform(box, box, transform, ow, oh); +} + + /** * Apply scale to a width or height. * @@ -54,28 +71,6 @@ static int scale_length(int length, int offset, float scale) { return roundf((offset + length) * scale) - roundf(offset * scale); } -static void scissor_output(struct wlr_output *wlr_output, - pixman_box32_t *rect) { - struct wlr_renderer *renderer = wlr_output->renderer; - assert(renderer); - - struct wlr_box box = { - .x = rect->x1, - .y = rect->y1, - .width = rect->x2 - rect->x1, - .height = rect->y2 - rect->y1, - }; - - int ow, oh; - wlr_output_transformed_resolution(wlr_output, &ow, &oh); - - enum wl_output_transform transform = - wlr_output_transform_invert(wlr_output->transform); - wlr_box_transform(&box, &box, transform, ow, oh); - - wlr_renderer_scissor(renderer, &box); -} - static void set_scale_filter(struct wlr_output *wlr_output, struct wlr_texture *texture, enum scale_filter_mode scale_filter) { #if WLR_HAS_GLES2_RENDERER @@ -103,40 +98,39 @@ static void set_scale_filter(struct wlr_output *wlr_output, } static void render_texture(struct render_context *ctx, struct wlr_texture *texture, - const struct wlr_fbox *src_box, const struct wlr_box *dst_box, + const struct wlr_fbox *_src_box, const struct wlr_box *dst_box, enum wl_output_transform transform, float alpha) { - struct wlr_renderer *renderer = ctx->renderer; struct sway_output *output = ctx->output; struct wlr_box proj_box = *dst_box; - scale_box(&proj_box, output->wlr_output->scale); - float matrix[9]; - enum wl_output_transform inv_transform = wlr_output_transform_invert(transform); - wlr_matrix_project_box(matrix, &proj_box, inv_transform, 0, - output->wlr_output->transform_matrix); + struct wlr_fbox src_box = {0}; + if (_src_box) { + src_box = *_src_box; + } pixman_region32_t damage; - pixman_region32_init(&damage); - pixman_region32_union_rect(&damage, &damage, dst_box->x, dst_box->y, - dst_box->width, dst_box->height); + pixman_region32_init_rect(&damage, proj_box.x, proj_box.y, + proj_box.width, proj_box.height); pixman_region32_intersect(&damage, &damage, ctx->output_damage); bool damaged = pixman_region32_not_empty(&damage); if (!damaged) { goto damage_finish; } - int nrects; - pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); - for (int i = 0; i < nrects; ++i) { - scissor_output(output->wlr_output, &rects[i]); - set_scale_filter(output->wlr_output, texture, output->scale_filter); - if (src_box != NULL) { - wlr_render_subtexture_with_matrix(renderer, texture, src_box, matrix, alpha); - } else { - wlr_render_texture_with_matrix(renderer, texture, matrix, alpha); - } - } + transform_output_box(&proj_box, output->wlr_output); + transform_output_damage(&damage, output->wlr_output); + transform = wlr_output_transform_compose(transform, output->wlr_output->transform); + + set_scale_filter(output->wlr_output, texture, output->scale_filter); + wlr_render_pass_add_texture(ctx->pass, &(struct wlr_render_texture_options) { + .texture = texture, + .src_box = src_box, + .dst_box = proj_box, + .transform = transform, + .alpha = &alpha, + .clip = &damage, + }); damage_finish: pixman_region32_fini(&damage); @@ -218,16 +212,13 @@ static void render_drag_icons(struct render_context *ctx, struct wl_list *drag_i void render_rect(struct render_context *ctx, const struct wlr_box *_box, float color[static 4]) { struct wlr_output *wlr_output = ctx->output->wlr_output; - struct wlr_renderer *renderer = ctx->renderer; - struct wlr_box box; - memcpy(&box, _box, sizeof(struct wlr_box)); + struct wlr_box box = *_box; box.x -= ctx->output->lx * wlr_output->scale; box.y -= ctx->output->ly * wlr_output->scale; pixman_region32_t damage; - pixman_region32_init(&damage); - pixman_region32_union_rect(&damage, &damage, box.x, box.y, + pixman_region32_init_rect(&damage, box.x, box.y, box.width, box.height); pixman_region32_intersect(&damage, &damage, ctx->output_damage); bool damaged = pixman_region32_not_empty(&damage); @@ -235,13 +226,19 @@ void render_rect(struct render_context *ctx, const struct wlr_box *_box, goto damage_finish; } - int nrects; - pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); - for (int i = 0; i < nrects; ++i) { - scissor_output(wlr_output, &rects[i]); - wlr_render_rect(renderer, &box, color, - wlr_output->transform_matrix); - } + transform_output_damage(&damage, wlr_output); + transform_output_box(&box, wlr_output); + + wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){ + .box = box, + .color = { + .r = color[0], + .g = color[1], + .b = color[2], + .a = color[3], + }, + .clip = &damage, + }); damage_finish: pixman_region32_fini(&damage); @@ -1006,7 +1003,6 @@ static void render_seatops(struct render_context *ctx) { void output_render(struct render_context *ctx) { struct wlr_output *wlr_output = ctx->output->wlr_output; - struct wlr_renderer *renderer = ctx->renderer; struct sway_output *output = ctx->output; const pixman_region32_t *damage = ctx->output_damage; @@ -1020,32 +1016,38 @@ void output_render(struct render_context *ctx) { fullscreen_con = workspace->current.fullscreen; } - if (!wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height)) { - return; - } - if (!pixman_region32_not_empty(damage)) { // Output isn't damaged but needs buffer swap goto renderer_end; } if (debug.damage == DAMAGE_HIGHLIGHT) { - wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1}); + wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){ + .box = { .width = output->width, .height = output->height }, + .color = { .r = 1, .g = 1, .b = 0, .a = 1 }, + }); } + pixman_region32_t transformed_damage; + pixman_region32_init(&transformed_damage); + pixman_region32_copy(&transformed_damage, damage); + transform_output_damage(&transformed_damage, wlr_output); + if (server.session_lock.locked) { - float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; + struct wlr_render_color clear_color = { + .a = 1.0f + }; if (server.session_lock.lock == NULL) { // abandoned lock -> red BG - clear_color[0] = 1.f; - } - int nrects; - pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); - for (int i = 0; i < nrects; ++i) { - scissor_output(wlr_output, &rects[i]); - wlr_renderer_clear(renderer, clear_color); + clear_color.r = 1.f; } + wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){ + .box = { .width = output->width, .height = output->height }, + .color = clear_color, + .clip = &transformed_damage, + }); + if (server.session_lock.lock != NULL) { struct render_data data = { .alpha = 1.0f, @@ -1073,14 +1075,11 @@ void output_render(struct render_context *ctx) { } if (fullscreen_con) { - float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; - - int nrects; - pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); - for (int i = 0; i < nrects; ++i) { - scissor_output(wlr_output, &rects[i]); - wlr_renderer_clear(renderer, clear_color); - } + wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){ + .box = { .width = output->width, .height = output->height }, + .color = { .r = 0, .g = 0, .b = 0, .a = 1 }, + .clip = &transformed_damage, + }); if (fullscreen_con->view) { if (!wl_list_empty(&fullscreen_con->view->saved_buffers)) { @@ -1104,14 +1103,11 @@ void output_render(struct render_context *ctx) { render_unmanaged(ctx, &root->xwayland_unmanaged); #endif } else { - float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; - - int nrects; - pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); - for (int i = 0; i < nrects; ++i) { - scissor_output(wlr_output, &rects[i]); - wlr_renderer_clear(renderer, clear_color); - } + wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){ + .box = { .width = output->width, .height = output->height }, + .color = { .r = 0.25f, .g = 0.25f, .b = 0.25f, .a = 1 }, + .clip = &transformed_damage, + }); render_layer_toplevel(ctx, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); @@ -1150,7 +1146,6 @@ render_overlay: render_drag_icons(ctx, &root->drag_icons); renderer_end: - wlr_renderer_scissor(renderer, NULL); - wlr_output_render_software_cursors(wlr_output, damage); - wlr_renderer_end(renderer); + pixman_region32_fini(&transformed_damage); + wlr_output_add_software_cursors_to_render_pass(wlr_output, ctx->pass, damage); } From db7638a0e515635e3aa36fa8bef58f3e44b177d8 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Tue, 2 May 2023 17:12:21 -0400 Subject: [PATCH 024/114] Don't crash if there is no damage during render --- sway/desktop/render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 37e84647c..92ccfd099 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -1018,7 +1018,7 @@ void output_render(struct render_context *ctx) { if (!pixman_region32_not_empty(damage)) { // Output isn't damaged but needs buffer swap - goto renderer_end; + return; } if (debug.damage == DAMAGE_HIGHLIGHT) { From e8f7551e46052a8df04b630bf06565ca77f830fb Mon Sep 17 00:00:00 2001 From: hrdl <31923882+hrdl-github@users.noreply.github.com> Date: Thu, 4 May 2023 01:13:33 +0200 Subject: [PATCH 025/114] Add support for touch cancel events --- include/sway/input/cursor.h | 1 + include/sway/input/seat.h | 5 +++++ sway/input/cursor.c | 22 ++++++++++++++++++++++ sway/input/seat.c | 6 ++++++ sway/input/seatop_down.c | 19 +++++++++++++++++++ 5 files changed, 53 insertions(+) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 4a3774d97..c7da88293 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -53,6 +53,7 @@ struct sway_cursor { struct wl_listener touch_down; struct wl_listener touch_up; + struct wl_listener touch_cancel; struct wl_listener touch_motion; struct wl_listener touch_frame; bool simulating_pointer_from_touch; diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 6d29cf3bf..5ef8e2f39 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -44,6 +44,8 @@ struct sway_seatop_impl { struct wlr_touch_up_event *event); void (*touch_down)(struct sway_seat *seat, struct wlr_touch_down_event *event, double lx, double ly); + void (*touch_cancel)(struct sway_seat *seat, + struct wlr_touch_cancel_event *event); void (*tablet_tool_motion)(struct sway_seat *seat, struct sway_tablet_tool *tool, uint32_t time_msec); void (*tablet_tool_tip)(struct sway_seat *seat, struct sway_tablet_tool *tool, @@ -338,6 +340,9 @@ void seatop_touch_up(struct sway_seat *seat, void seatop_touch_down(struct sway_seat *seat, struct wlr_touch_down_event *event, double lx, double ly); +void seatop_touch_cancel(struct sway_seat *seat, + struct wlr_touch_cancel_event *event); + void seatop_rebase(struct sway_seat *seat, uint32_t time_msec); /** diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 75d055cd6..d8ec11ac2 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -509,6 +509,24 @@ static void handle_touch_up(struct wl_listener *listener, void *data) { } } +static void handle_touch_cancel(struct wl_listener *listener, void *data) { + struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_cancel); + struct wlr_touch_cancel_event *event = data; + cursor_handle_activity_from_device(cursor, &event->touch->base); + + struct sway_seat *seat = cursor->seat; + + if (cursor->simulating_pointer_from_touch) { + if (cursor->pointer_touch_id == cursor->seat->touch_id) { + cursor->pointer_touch_up = true; + dispatch_cursor_button(cursor, &event->touch->base, + event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED); + } + } else { + seatop_touch_cancel(seat, event); + } +} + static void handle_touch_motion(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_motion); @@ -1100,6 +1118,7 @@ void sway_cursor_destroy(struct sway_cursor *cursor) { wl_list_remove(&cursor->frame.link); wl_list_remove(&cursor->touch_down.link); wl_list_remove(&cursor->touch_up.link); + wl_list_remove(&cursor->touch_cancel.link); wl_list_remove(&cursor->touch_motion.link); wl_list_remove(&cursor->touch_frame.link); wl_list_remove(&cursor->tool_axis.link); @@ -1181,6 +1200,9 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { wl_signal_add(&wlr_cursor->events.touch_up, &cursor->touch_up); cursor->touch_up.notify = handle_touch_up; + wl_signal_add(&wlr_cursor->events.touch_cancel, &cursor->touch_cancel); + cursor->touch_cancel.notify = handle_touch_cancel; + wl_signal_add(&wlr_cursor->events.touch_motion, &cursor->touch_motion); cursor->touch_motion.notify = handle_touch_motion; diff --git a/sway/input/seat.c b/sway/input/seat.c index 6b95e46aa..bcb89b48b 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1638,6 +1638,12 @@ void seatop_touch_down(struct sway_seat *seat, struct wlr_touch_down_event *even } } +void seatop_touch_cancel(struct sway_seat *seat, struct wlr_touch_cancel_event *event) { + if (seat->seatop_impl->touch_cancel) { + seat->seatop_impl->touch_cancel(seat, event); + } +} + void seatop_tablet_tool_tip(struct sway_seat *seat, struct sway_tablet_tool *tool, uint32_t time_msec, enum wlr_tablet_tool_tip_state state) { diff --git a/sway/input/seatop_down.c b/sway/input/seatop_down.c index 6447134ec..c5901f6ae 100644 --- a/sway/input/seatop_down.c +++ b/sway/input/seatop_down.c @@ -104,6 +104,24 @@ static void handle_touch_down(struct sway_seat *seat, } } +static void handle_touch_cancel(struct sway_seat *seat, + struct wlr_touch_cancel_event *event) { + struct seatop_down_event *e = seat->seatop_data; + struct seatop_touch_point_event *point_event, *tmp; + + wl_list_for_each_safe(point_event, tmp, &e->point_events, link) { + if (point_event->touch_id == event->touch_id) { + wl_list_remove(&point_event->link); + free(point_event); + break; + } + } + + if (e->surface) { + wlr_seat_touch_notify_cancel(seat->wlr_seat, e->surface); + } +} + static void handle_pointer_axis(struct sway_seat *seat, struct wlr_pointer_axis_event *event) { struct sway_input_device *input_device = @@ -189,6 +207,7 @@ static const struct sway_seatop_impl seatop_impl = { .touch_motion = handle_touch_motion, .touch_up = handle_touch_up, .touch_down = handle_touch_down, + .touch_cancel = handle_touch_cancel, .unref = handle_unref, .end = handle_end, .allow_set_cursor = true, From 3cd7c7178079bf61bb7967690e7767442b369782 Mon Sep 17 00:00:00 2001 From: hrdl <31923882+hrdl-github@users.noreply.github.com> Date: Thu, 4 May 2023 17:26:15 +0200 Subject: [PATCH 026/114] handle_touch_cancel: fix begin default I forgot to call seatop_begin_default in e8f7551e46052a8df04b630bf06565ca77f830fb. --- sway/input/seatop_down.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/input/seatop_down.c b/sway/input/seatop_down.c index c5901f6ae..81e8d0a7f 100644 --- a/sway/input/seatop_down.c +++ b/sway/input/seatop_down.c @@ -117,6 +117,10 @@ static void handle_touch_cancel(struct sway_seat *seat, } } + if (wl_list_empty(&e->point_events)) { + seatop_begin_default(seat); + } + if (e->surface) { wlr_seat_touch_notify_cancel(seat->wlr_seat, e->surface); } From a79994e11961ae24d7a418a18d43bfdd48d1f44b Mon Sep 17 00:00:00 2001 From: Mukundan314 <30190448+Mukundan314@users.noreply.github.com> Date: Thu, 4 May 2023 14:57:20 +0530 Subject: [PATCH 027/114] swaybar: always subscribe to mode and workspace always subscribe to mode and workspace events, since we might need them after bar config updates even if we don't need them initially. --- swaybar/ipc.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 9d81a9fb2..33ae65448 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -426,12 +426,9 @@ bool ipc_initialize(struct swaybar *bar) { } free(res); - struct swaybar_config *config = bar->config; - char subscribe[128]; // suitably large buffer - len = snprintf(subscribe, 128, - "[ \"barconfig_update\" , \"bar_state_update\" %s %s ]", - config->binding_mode_indicator ? ", \"mode\"" : "", - config->workspace_buttons ? ", \"workspace\"" : ""); + char *subscribe = + "[ \"barconfig_update\", \"bar_state_update\", \"mode\", \"workspace\" ]"; + len = strlen(subscribe); free(ipc_single_command(bar->ipc_event_socketfd, IPC_SUBSCRIBE, subscribe, &len)); return true; From 393c29fc591b6e0fb85328b638607d8b5784a0e3 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Tue, 9 May 2023 15:08:47 +0200 Subject: [PATCH 028/114] render: Apply clip to rendered texture correctly The new wlr_render_pass API provides src_box, dst_box and clip parameters for texture rendition. Rather than clipping the dst_box, which control the projection matrix and leads to compression, intersect the damage and clip box and pass these as a clip parameter. Fixes: https://github.com/swaywm/sway/issues/7579 Regressed by: https://github.com/swaywm/sway/pull/7552 --- sway/desktop/render.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 92ccfd099..552502aa7 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -99,7 +99,7 @@ static void set_scale_filter(struct wlr_output *wlr_output, static void render_texture(struct render_context *ctx, struct wlr_texture *texture, const struct wlr_fbox *_src_box, const struct wlr_box *dst_box, - enum wl_output_transform transform, float alpha) { + const struct wlr_box *clip_box, enum wl_output_transform transform, float alpha) { struct sway_output *output = ctx->output; struct wlr_box proj_box = *dst_box; @@ -113,6 +113,12 @@ static void render_texture(struct render_context *ctx, struct wlr_texture *textu pixman_region32_init_rect(&damage, proj_box.x, proj_box.y, proj_box.width, proj_box.height); pixman_region32_intersect(&damage, &damage, ctx->output_damage); + + if (clip_box) { + pixman_region32_intersect_rect(&damage, &damage, + clip_box->x, clip_box->y, clip_box->width, clip_box->height); + } + bool damaged = pixman_region32_not_empty(&damage); if (!damaged) { goto damage_finish; @@ -151,19 +157,17 @@ static void render_surface_iterator(struct sway_output *output, struct wlr_fbox src_box; wlr_surface_get_buffer_source_box(surface, &src_box); - struct wlr_box proj_box = *_box; - scale_box(&proj_box, wlr_output->scale); - struct wlr_box dst_box = *_box; - struct wlr_box *clip_box = data->clip_box; - if (clip_box != NULL) { - dst_box.width = fmin(dst_box.width, clip_box->width); - dst_box.height = fmin(dst_box.height, clip_box->height); + struct wlr_box clip_box = *_box; + if (data->clip_box != NULL) { + clip_box.width = fmin(dst_box.width, data->clip_box->width); + clip_box.height = fmin(dst_box.height, data->clip_box->height); } scale_box(&dst_box, wlr_output->scale); + scale_box(&clip_box, wlr_output->scale); render_texture(data->ctx, texture, - &src_box, &dst_box, surface->current.transform, alpha); + &src_box, &dst_box, &clip_box, surface->current.transform, alpha); wlr_presentation_surface_sampled_on_output(server.presentation, surface, wlr_output); @@ -320,20 +324,20 @@ static void render_saved_view(struct render_context *ctx, struct sway_view *view } struct wlr_box dst_box = proj_box; - scale_box(&proj_box, wlr_output->scale); - + struct wlr_box clip_box = proj_box; if (!floating) { - dst_box.width = fmin(dst_box.width, + clip_box.width = fmin(dst_box.width, view->container->current.content_width - (saved_buf->x - view->container->current.content_x) + view->saved_geometry.x); - dst_box.height = fmin(dst_box.height, + clip_box.height = fmin(dst_box.height, view->container->current.content_height - (saved_buf->y - view->container->current.content_y) + view->saved_geometry.y); } scale_box(&dst_box, wlr_output->scale); + scale_box(&clip_box, wlr_output->scale); render_texture(ctx, saved_buf->buffer->texture, - &saved_buf->source_box, &dst_box, saved_buf->transform, alpha); + &saved_buf->source_box, &dst_box, &clip_box, saved_buf->transform, alpha); } // FIXME: we should set the surface that this saved buffer originates from @@ -509,7 +513,7 @@ static void render_titlebar(struct render_context *ctx, struct sway_container *c texture_box.width = ob_inner_width; } render_texture(ctx, marks_texture, - NULL, &texture_box, WL_OUTPUT_TRANSFORM_NORMAL, con->alpha); + NULL, &texture_box, NULL, WL_OUTPUT_TRANSFORM_NORMAL, con->alpha); // Padding above memcpy(&color, colors->background, sizeof(float) * 4); @@ -580,7 +584,7 @@ static void render_titlebar(struct render_context *ctx, struct sway_container *c } render_texture(ctx, title_texture, - NULL, &texture_box, WL_OUTPUT_TRANSFORM_NORMAL, con->alpha); + NULL, &texture_box, NULL, WL_OUTPUT_TRANSFORM_NORMAL, con->alpha); // Padding above memcpy(&color, colors->background, sizeof(float) * 4); From 0a951517aed2375b972bbd70cb164bf7acb25e00 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Tue, 9 May 2023 15:13:39 +0200 Subject: [PATCH 029/114] render: Clear using wlr_output dimensions Clear was done using sway_output's logical dimensions, instead of the wlr_output physical dimensions. This meant that when output scaling was applied, only a part of the screen would be cleared. Use the wlr_output dimensions instead. Regressed by: https://github.com/swaywm/sway/pull/7552 --- sway/desktop/render.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 552502aa7..edefa658a 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -1027,7 +1027,7 @@ void output_render(struct render_context *ctx) { if (debug.damage == DAMAGE_HIGHLIGHT) { wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){ - .box = { .width = output->width, .height = output->height }, + .box = { .width = wlr_output->width, .height = wlr_output->height }, .color = { .r = 1, .g = 1, .b = 0, .a = 1 }, }); } @@ -1047,7 +1047,7 @@ void output_render(struct render_context *ctx) { } wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){ - .box = { .width = output->width, .height = output->height }, + .box = { .width = wlr_output->width, .height = wlr_output->height }, .color = clear_color, .clip = &transformed_damage, }); @@ -1080,7 +1080,7 @@ void output_render(struct render_context *ctx) { if (fullscreen_con) { wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){ - .box = { .width = output->width, .height = output->height }, + .box = { .width = wlr_output->width, .height = wlr_output->height }, .color = { .r = 0, .g = 0, .b = 0, .a = 1 }, .clip = &transformed_damage, }); @@ -1108,7 +1108,7 @@ void output_render(struct render_context *ctx) { #endif } else { wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){ - .box = { .width = output->width, .height = output->height }, + .box = { .width = wlr_output->width, .height = wlr_output->height }, .color = { .r = 0.25f, .g = 0.25f, .b = 0.25f, .a = 1 }, .clip = &transformed_damage, }); From 19cc36accc0d5a9997fd264c98df92b8b0ed8bea Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 9 May 2023 16:39:48 +0200 Subject: [PATCH 030/114] render: fix titlebar texture clipping We need to provide an unclipped dst_box. Fixes: https://github.com/swaywm/sway/issues/7573 Regressed by: https://github.com/swaywm/sway/pull/7552 --- sway/desktop/render.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index edefa658a..223457b25 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -509,23 +509,24 @@ static void render_titlebar(struct render_context *ctx, struct sway_container *c texture_box.y = round((bg_y - output_y) * output_scale) + ob_padding_above; - if (ob_inner_width < texture_box.width) { - texture_box.width = ob_inner_width; + struct wlr_box clip_box = texture_box; + if (ob_inner_width < clip_box.width) { + clip_box.width = ob_inner_width; } render_texture(ctx, marks_texture, - NULL, &texture_box, NULL, WL_OUTPUT_TRANSFORM_NORMAL, con->alpha); + NULL, &texture_box, &clip_box, WL_OUTPUT_TRANSFORM_NORMAL, con->alpha); // Padding above memcpy(&color, colors->background, sizeof(float) * 4); premultiply_alpha(color, con->alpha); - box.x = texture_box.x + round(output_x * output_scale); + box.x = clip_box.x + round(output_x * output_scale); box.y = roundf((y + titlebar_border_thickness) * output_scale); - box.width = texture_box.width; + box.width = clip_box.width; box.height = ob_padding_above; render_rect(ctx, &box, color); // Padding below - box.y += ob_padding_above + texture_box.height; + box.y += ob_padding_above + clip_box.height; box.height = ob_padding_below; render_rect(ctx, &box, color); } @@ -579,24 +580,25 @@ static void render_titlebar(struct render_context *ctx, struct sway_container *c texture_box.y = round((bg_y - output_y) * output_scale) + ob_padding_above; - if (ob_inner_width - ob_marks_width < texture_box.width) { - texture_box.width = ob_inner_width - ob_marks_width; + struct wlr_box clip_box = texture_box; + if (ob_inner_width - ob_marks_width < clip_box.width) { + clip_box.width = ob_inner_width - ob_marks_width; } render_texture(ctx, title_texture, - NULL, &texture_box, NULL, WL_OUTPUT_TRANSFORM_NORMAL, con->alpha); + NULL, &texture_box, &clip_box, WL_OUTPUT_TRANSFORM_NORMAL, con->alpha); // Padding above memcpy(&color, colors->background, sizeof(float) * 4); premultiply_alpha(color, con->alpha); - box.x = texture_box.x + round(output_x * output_scale); + box.x = clip_box.x + round(output_x * output_scale); box.y = roundf((y + titlebar_border_thickness) * output_scale); - box.width = texture_box.width; + box.width = clip_box.width; box.height = ob_padding_above; render_rect(ctx, &box, color); // Padding below - box.y += ob_padding_above + texture_box.height; + box.y += ob_padding_above + clip_box.height; box.height = ob_padding_below; render_rect(ctx, &box, color); } From 01b0c11394b88fea2ec8ac691e30504f1e0800f5 Mon Sep 17 00:00:00 2001 From: hrdl <31923882+hrdl-github@users.noreply.github.com> Date: Thu, 11 May 2023 11:16:51 +0200 Subject: [PATCH 031/114] seatop_down: Call seatop_begin_default after sending touch events This is consistent with pointer tablet and button events. Fixes #7577. --- sway/input/seatop_down.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sway/input/seatop_down.c b/sway/input/seatop_down.c index 81e8d0a7f..36f9bb608 100644 --- a/sway/input/seatop_down.c +++ b/sway/input/seatop_down.c @@ -64,11 +64,11 @@ static void handle_touch_up(struct sway_seat *seat, } } + wlr_seat_touch_notify_up(seat->wlr_seat, event->time_msec, event->touch_id); + if (wl_list_empty(&e->point_events)) { seatop_begin_default(seat); } - - wlr_seat_touch_notify_up(seat->wlr_seat, event->time_msec, event->touch_id); } static void handle_touch_down(struct sway_seat *seat, @@ -117,13 +117,13 @@ static void handle_touch_cancel(struct sway_seat *seat, } } - if (wl_list_empty(&e->point_events)) { - seatop_begin_default(seat); - } - if (e->surface) { wlr_seat_touch_notify_cancel(seat->wlr_seat, e->surface); } + + if (wl_list_empty(&e->point_events)) { + seatop_begin_default(seat); + } } static void handle_pointer_axis(struct sway_seat *seat, From 48d6eda3cb0f79d2190756af44f01d028696bf0e Mon Sep 17 00:00:00 2001 From: Erik Reider <35975961+ErikReider@users.noreply.github.com> Date: Sat, 20 May 2023 15:04:11 +0200 Subject: [PATCH 032/114] Fix layer old damage not being offset by the monitor layout coords --- sway/desktop/layer_shell.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index e16bee78d..cf795dc70 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -312,6 +312,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { bool extent_changed = memcmp(&old_extent, &layer->extent, sizeof(struct wlr_box)) != 0; if (extent_changed || layer_changed) { + old_extent.x += output->lx; + old_extent.y += output->ly; output_damage_box(output, &old_extent); output_damage_surface(output, layer->geo.x, layer->geo.y, layer_surface->surface, true); From 72881b5d120442e3a6f9c5b022c8d9cc05cb27c0 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Thu, 9 Mar 2023 13:02:13 +0300 Subject: [PATCH 033/114] xwayland: don't rely on event source being data This pattern is being slowly removed from wlroots. --- sway/desktop/xwayland.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 9c29f66ba..bcefc4fde 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -125,7 +125,9 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) { } static void unmanaged_handle_request_activate(struct wl_listener *listener, void *data) { - struct wlr_xwayland_surface *xsurface = data; + struct sway_xwayland_unmanaged *surface = + wl_container_of(listener, surface, request_activate); + struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; if (!xsurface->mapped) { return; } @@ -495,8 +497,8 @@ static void handle_unmap(struct wl_listener *listener, void *data) { static void handle_map(struct wl_listener *listener, void *data) { struct sway_xwayland_view *xwayland_view = wl_container_of(listener, xwayland_view, map); - struct wlr_xwayland_surface *xsurface = data; struct sway_view *view = &xwayland_view->view; + struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; view->natural_width = xsurface->width; view->natural_height = xsurface->height; @@ -515,8 +517,8 @@ static void handle_map(struct wl_listener *listener, void *data) { static void handle_override_redirect(struct wl_listener *listener, void *data) { struct sway_xwayland_view *xwayland_view = wl_container_of(listener, xwayland_view, override_redirect); - struct wlr_xwayland_surface *xsurface = data; struct sway_view *view = &xwayland_view->view; + struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; bool mapped = xsurface->mapped; if (mapped) { From c9e1dab3187d22ada0232d699e759a628e0ed185 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Sun, 5 Mar 2023 23:49:45 +0300 Subject: [PATCH 034/114] chore: chase wlroots map logic unification --- include/sway/tree/view.h | 4 ++ sway/desktop/layer_shell.c | 22 +++++----- sway/desktop/output.c | 4 +- sway/desktop/render.c | 2 +- sway/desktop/xdg_shell.c | 10 ++--- sway/desktop/xwayland.c | 87 ++++++++++++++++++++++++++------------ sway/input/seat.c | 8 ++-- sway/lock.c | 2 +- sway/xdg_activation_v1.c | 2 +- 9 files changed, 90 insertions(+), 51 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 7fc2d95d8..960f9d71c 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -160,6 +160,8 @@ struct sway_xwayland_view { struct wl_listener set_window_type; struct wl_listener set_hints; struct wl_listener set_decorations; + struct wl_listener associate; + struct wl_listener dissociate; struct wl_listener map; struct wl_listener unmap; struct wl_listener destroy; @@ -177,6 +179,8 @@ struct sway_xwayland_unmanaged { struct wl_listener request_fullscreen; struct wl_listener commit; struct wl_listener set_geometry; + struct wl_listener associate; + struct wl_listener dissociate; struct wl_listener map; struct wl_listener unmap; struct wl_listener destroy; diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index cf795dc70..50aa69381 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -219,7 +219,7 @@ void arrange_layers(struct sway_output *output) { wl_list_for_each_reverse(layer, &output->layers[layers_above_shell[i]], link) { if (layer->layer_surface->current.keyboard_interactive && - layer->layer_surface->mapped) { + layer->layer_surface->surface->mapped) { topmost = layer; break; } @@ -253,7 +253,7 @@ static struct sway_layer_surface *find_mapped_layer_by_client( &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], link) { struct wl_resource *resource = lsurface->layer_surface->resource; if (wl_resource_get_client(resource) == client - && lsurface->layer_surface->mapped) { + && lsurface->layer_surface->surface->mapped) { return lsurface; } } @@ -293,8 +293,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { bool layer_changed = false; if (layer_surface->current.committed != 0 - || layer->mapped != layer_surface->mapped) { - layer->mapped = layer_surface->mapped; + || layer->mapped != layer_surface->surface->mapped) { + layer->mapped = layer_surface->surface->mapped; layer_changed = layer->layer != layer_surface->current.layer; if (layer_changed) { wl_list_remove(&layer->link); @@ -349,7 +349,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_container_of(listener, sway_layer, destroy); sway_log(SWAY_DEBUG, "Layer surface destroyed (%s)", sway_layer->layer_surface->namespace); - if (sway_layer->layer_surface->mapped) { + if (sway_layer->layer_surface->surface->mapped) { unmap(sway_layer); } @@ -454,9 +454,9 @@ static struct sway_layer_subsurface *create_subsurface( wl_list_insert(&layer_surface->subsurfaces, &subsurface->link); subsurface->map.notify = subsurface_handle_map; - wl_signal_add(&wlr_subsurface->events.map, &subsurface->map); + wl_signal_add(&wlr_subsurface->surface->events.map, &subsurface->map); subsurface->unmap.notify = subsurface_handle_unmap; - wl_signal_add(&wlr_subsurface->events.unmap, &subsurface->unmap); + wl_signal_add(&wlr_subsurface->surface->events.unmap, &subsurface->unmap); subsurface->destroy.notify = subsurface_handle_destroy; wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy); subsurface->commit.notify = subsurface_handle_commit; @@ -571,9 +571,9 @@ static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup, popup->parent_layer = parent; popup->map.notify = popup_handle_map; - wl_signal_add(&wlr_popup->base->events.map, &popup->map); + wl_signal_add(&wlr_popup->base->surface->events.map, &popup->map); popup->unmap.notify = popup_handle_unmap; - wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap); + wl_signal_add(&wlr_popup->base->surface->events.unmap, &popup->unmap); popup->destroy.notify = popup_handle_destroy; wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy); popup->commit.notify = popup_handle_commit; @@ -661,9 +661,9 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { sway_layer->destroy.notify = handle_destroy; wl_signal_add(&layer_surface->events.destroy, &sway_layer->destroy); sway_layer->map.notify = handle_map; - wl_signal_add(&layer_surface->events.map, &sway_layer->map); + wl_signal_add(&layer_surface->surface->events.map, &sway_layer->map); sway_layer->unmap.notify = handle_unmap; - wl_signal_add(&layer_surface->events.unmap, &sway_layer->unmap); + wl_signal_add(&layer_surface->surface->events.unmap, &sway_layer->unmap); sway_layer->new_popup.notify = handle_new_popup; wl_signal_add(&layer_surface->events.new_popup, &sway_layer->new_popup); sway_layer->new_subsurface.notify = handle_new_subsurface; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 01bc87bbb..fe1fa8af7 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -265,7 +265,7 @@ void output_drag_icons_for_each_surface(struct sway_output *output, double ox = drag_icon->x - output->lx; double oy = drag_icon->y - output->ly; - if (drag_icon->wlr_drag_icon->mapped) { + if (drag_icon->wlr_drag_icon->surface->mapped) { output_surface_for_each_surface(output, drag_icon->wlr_drag_icon->surface, ox, oy, iterator, user_data); @@ -295,7 +295,7 @@ static void output_for_each_surface(struct sway_output *output, if (lock_surface->output != output->wlr_output) { continue; } - if (!lock_surface->mapped) { + if (!lock_surface->surface->mapped) { continue; } diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 223457b25..210140424 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -1065,7 +1065,7 @@ void output_render(struct render_context *ctx) { if (lock_surface->output != wlr_output) { continue; } - if (!lock_surface->mapped) { + if (!lock_surface->surface->mapped) { continue; } diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 9b6456da3..377a0f1c9 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -104,8 +104,8 @@ static struct sway_xdg_popup *popup_create( wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); popup->destroy.notify = popup_handle_destroy; - wl_signal_add(&xdg_surface->events.map, &popup->child.surface_map); - wl_signal_add(&xdg_surface->events.unmap, &popup->child.surface_unmap); + wl_signal_add(&xdg_surface->surface->events.map, &popup->child.surface_map); + wl_signal_add(&xdg_surface->surface->events.unmap, &popup->child.surface_unmap); popup_unconstrain(popup); @@ -344,7 +344,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) struct wlr_xdg_toplevel *toplevel = xdg_shell_view->view.wlr_xdg_toplevel; struct sway_view *view = &xdg_shell_view->view; - if (!toplevel->base->mapped) { + if (!toplevel->base->surface->mapped) { return; } @@ -529,10 +529,10 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { xdg_shell_view->view.wlr_xdg_toplevel = xdg_surface->toplevel; xdg_shell_view->map.notify = handle_map; - wl_signal_add(&xdg_surface->events.map, &xdg_shell_view->map); + wl_signal_add(&xdg_surface->surface->events.map, &xdg_shell_view->map); xdg_shell_view->unmap.notify = handle_unmap; - wl_signal_add(&xdg_surface->events.unmap, &xdg_shell_view->unmap); + wl_signal_add(&xdg_surface->surface->events.unmap, &xdg_shell_view->unmap); xdg_shell_view->destroy.notify = handle_destroy; wl_signal_add(&xdg_surface->events.destroy, &xdg_shell_view->destroy); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index bcefc4fde..bb4340f10 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -128,7 +128,7 @@ static void unmanaged_handle_request_activate(struct wl_listener *listener, void struct sway_xwayland_unmanaged *surface = wl_container_of(listener, surface, request_activate); struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; - if (!xsurface->mapped) { + if (xsurface->surface == NULL || !xsurface->surface->mapped) { return; } struct sway_seat *seat = input_manager_current_seat(); @@ -140,12 +140,29 @@ static void unmanaged_handle_request_activate(struct wl_listener *listener, void seat_set_focus_surface(seat, xsurface->surface, false); } +static void unmanaged_handle_associate(struct wl_listener *listener, void *data) { + struct sway_xwayland_unmanaged *surface = + wl_container_of(listener, surface, associate); + struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; + wl_signal_add(&xsurface->surface->events.map, &surface->map); + surface->map.notify = unmanaged_handle_map; + wl_signal_add(&xsurface->surface->events.unmap, &surface->unmap); + surface->unmap.notify = unmanaged_handle_unmap; +} + +static void unmanaged_handle_dissociate(struct wl_listener *listener, void *data) { + struct sway_xwayland_unmanaged *surface = + wl_container_of(listener, surface, dissociate); + wl_list_remove(&surface->map.link); + wl_list_remove(&surface->unmap.link); +} + static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { struct sway_xwayland_unmanaged *surface = wl_container_of(listener, surface, destroy); wl_list_remove(&surface->request_configure.link); - wl_list_remove(&surface->map.link); - wl_list_remove(&surface->unmap.link); + wl_list_remove(&surface->associate.link); + wl_list_remove(&surface->dissociate.link); wl_list_remove(&surface->destroy.link); wl_list_remove(&surface->override_redirect.link); wl_list_remove(&surface->request_activate.link); @@ -161,7 +178,7 @@ static void unmanaged_handle_override_redirect(struct wl_listener *listener, voi wl_container_of(listener, surface, override_redirect); struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; - bool mapped = xsurface->mapped; + bool mapped = xsurface->surface != NULL || xsurface->surface->mapped; if (mapped) { unmanaged_handle_unmap(&surface->unmap, NULL); } @@ -188,10 +205,10 @@ static struct sway_xwayland_unmanaged *create_unmanaged( wl_signal_add(&xsurface->events.request_configure, &surface->request_configure); surface->request_configure.notify = unmanaged_handle_request_configure; - wl_signal_add(&xsurface->events.map, &surface->map); - surface->map.notify = unmanaged_handle_map; - wl_signal_add(&xsurface->events.unmap, &surface->unmap); - surface->unmap.notify = unmanaged_handle_unmap; + wl_signal_add(&xsurface->events.associate, &surface->associate); + surface->associate.notify = unmanaged_handle_associate; + wl_signal_add(&xsurface->events.dissociate, &surface->dissociate); + surface->dissociate.notify = unmanaged_handle_dissociate; wl_signal_add(&xsurface->events.destroy, &surface->destroy); surface->destroy.notify = unmanaged_handle_destroy; wl_signal_add(&xsurface->events.set_override_redirect, &surface->override_redirect); @@ -474,8 +491,8 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&xwayland_view->set_window_type.link); wl_list_remove(&xwayland_view->set_hints.link); wl_list_remove(&xwayland_view->set_decorations.link); - wl_list_remove(&xwayland_view->map.link); - wl_list_remove(&xwayland_view->unmap.link); + wl_list_remove(&xwayland_view->associate.link); + wl_list_remove(&xwayland_view->dissociate.link); wl_list_remove(&xwayland_view->override_redirect.link); view_begin_destroy(&xwayland_view->view); } @@ -520,7 +537,7 @@ static void handle_override_redirect(struct wl_listener *listener, void *data) { struct sway_view *view = &xwayland_view->view; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - bool mapped = xsurface->mapped; + bool mapped = xsurface->surface != NULL || xsurface->surface->mapped; if (mapped) { handle_unmap(&xwayland_view->unmap, NULL); } @@ -539,7 +556,7 @@ static void handle_request_configure(struct wl_listener *listener, void *data) { struct wlr_xwayland_surface_configure_event *ev = data; struct sway_view *view = &xwayland_view->view; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - if (!xsurface->mapped) { + if (xsurface->surface == NULL || !xsurface->surface->mapped) { wlr_xwayland_surface_configure(xsurface, ev->x, ev->y, ev->width, ev->height); return; @@ -568,7 +585,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) wl_container_of(listener, xwayland_view, request_fullscreen); struct sway_view *view = &xwayland_view->view; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - if (!xsurface->mapped) { + if (xsurface->surface == NULL || !xsurface->surface->mapped) { return; } container_set_fullscreen(view->container, xsurface->fullscreen); @@ -582,7 +599,7 @@ static void handle_request_minimize(struct wl_listener *listener, void *data) { wl_container_of(listener, xwayland_view, request_minimize); struct sway_view *view = &xwayland_view->view; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - if (!xsurface->mapped) { + if (xsurface->surface == NULL || !xsurface->surface->mapped) { return; } @@ -597,7 +614,7 @@ static void handle_request_move(struct wl_listener *listener, void *data) { wl_container_of(listener, xwayland_view, request_move); struct sway_view *view = &xwayland_view->view; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - if (!xsurface->mapped) { + if (xsurface->surface == NULL || !xsurface->surface->mapped) { return; } if (!container_is_floating(view->container) || @@ -613,7 +630,7 @@ static void handle_request_resize(struct wl_listener *listener, void *data) { wl_container_of(listener, xwayland_view, request_resize); struct sway_view *view = &xwayland_view->view; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - if (!xsurface->mapped) { + if (xsurface->surface == NULL || !xsurface->surface->mapped) { return; } if (!container_is_floating(view->container)) { @@ -629,7 +646,7 @@ static void handle_request_activate(struct wl_listener *listener, void *data) { wl_container_of(listener, xwayland_view, request_activate); struct sway_view *view = &xwayland_view->view; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - if (!xsurface->mapped) { + if (xsurface->surface == NULL || !xsurface->surface->mapped) { return; } view_request_activate(view, NULL); @@ -642,7 +659,7 @@ static void handle_set_title(struct wl_listener *listener, void *data) { wl_container_of(listener, xwayland_view, set_title); struct sway_view *view = &xwayland_view->view; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - if (!xsurface->mapped) { + if (xsurface->surface == NULL || !xsurface->surface->mapped) { return; } view_update_title(view, false); @@ -654,7 +671,7 @@ static void handle_set_class(struct wl_listener *listener, void *data) { wl_container_of(listener, xwayland_view, set_class); struct sway_view *view = &xwayland_view->view; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - if (!xsurface->mapped) { + if (xsurface->surface == NULL || !xsurface->surface->mapped) { return; } view_execute_criteria(view); @@ -665,7 +682,7 @@ static void handle_set_role(struct wl_listener *listener, void *data) { wl_container_of(listener, xwayland_view, set_role); struct sway_view *view = &xwayland_view->view; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - if (!xsurface->mapped) { + if (xsurface->surface == NULL || !xsurface->surface->mapped) { return; } view_execute_criteria(view); @@ -701,7 +718,7 @@ static void handle_set_window_type(struct wl_listener *listener, void *data) { wl_container_of(listener, xwayland_view, set_window_type); struct sway_view *view = &xwayland_view->view; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - if (!xsurface->mapped) { + if (xsurface->surface == NULL || !xsurface->surface->mapped) { return; } view_execute_criteria(view); @@ -712,7 +729,7 @@ static void handle_set_hints(struct wl_listener *listener, void *data) { wl_container_of(listener, xwayland_view, set_hints); struct sway_view *view = &xwayland_view->view; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - if (!xsurface->mapped) { + if (xsurface->surface == NULL || !xsurface->surface->mapped) { return; } const bool hints_urgency = xcb_icccm_wm_hints_get_urgency(xsurface->hints); @@ -727,6 +744,24 @@ static void handle_set_hints(struct wl_listener *listener, void *data) { } } +static void handle_associate(struct wl_listener *listener, void *data) { + struct sway_xwayland_view *xwayland_view = + wl_container_of(listener, xwayland_view, associate); + struct wlr_xwayland_surface *xsurface = + xwayland_view->view.wlr_xwayland_surface; + wl_signal_add(&xsurface->surface->events.unmap, &xwayland_view->unmap); + xwayland_view->unmap.notify = handle_unmap; + wl_signal_add(&xsurface->surface->events.map, &xwayland_view->map); + xwayland_view->map.notify = handle_map; +} + +static void handle_dissociate(struct wl_listener *listener, void *data) { + struct sway_xwayland_view *xwayland_view = + wl_container_of(listener, xwayland_view, dissociate); + wl_list_remove(&xwayland_view->map.link); + wl_list_remove(&xwayland_view->unmap.link); +} + struct sway_view *view_from_wlr_xwayland_surface( struct wlr_xwayland_surface *xsurface) { return xsurface->data; @@ -796,11 +831,11 @@ struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsu &xwayland_view->set_decorations); xwayland_view->set_decorations.notify = handle_set_decorations; - wl_signal_add(&xsurface->events.unmap, &xwayland_view->unmap); - xwayland_view->unmap.notify = handle_unmap; + wl_signal_add(&xsurface->events.associate, &xwayland_view->associate); + xwayland_view->associate.notify = handle_associate; - wl_signal_add(&xsurface->events.map, &xwayland_view->map); - xwayland_view->map.notify = handle_map; + wl_signal_add(&xsurface->events.dissociate, &xwayland_view->dissociate); + xwayland_view->dissociate.notify = handle_dissociate; wl_signal_add(&xsurface->events.set_override_redirect, &xwayland_view->override_redirect); diff --git a/sway/input/seat.c b/sway/input/seat.c index bcb89b48b..5795f40ff 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -367,7 +367,7 @@ static void handle_new_node(struct wl_listener *listener, void *data) { } static void drag_icon_damage_whole(struct sway_drag_icon *icon) { - if (!icon->wlr_drag_icon->mapped) { + if (!icon->wlr_drag_icon->surface->mapped) { return; } desktop_damage_surface(icon->wlr_drag_icon->surface, icon->x, icon->y, true); @@ -511,9 +511,9 @@ static void handle_start_drag(struct wl_listener *listener, void *data) { icon->surface_commit.notify = drag_icon_handle_surface_commit; wl_signal_add(&wlr_drag_icon->surface->events.commit, &icon->surface_commit); icon->unmap.notify = drag_icon_handle_unmap; - wl_signal_add(&wlr_drag_icon->events.unmap, &icon->unmap); + wl_signal_add(&wlr_drag_icon->surface->events.unmap, &icon->unmap); icon->map.notify = drag_icon_handle_map; - wl_signal_add(&wlr_drag_icon->events.map, &icon->map); + wl_signal_add(&wlr_drag_icon->surface->events.map, &icon->map); icon->destroy.notify = drag_icon_handle_destroy; wl_signal_add(&wlr_drag_icon->events.destroy, &icon->destroy); @@ -1350,7 +1350,7 @@ void seat_set_focus_layer(struct sway_seat *seat, } else if (!layer || seat->focused_layer == layer) { return; } - assert(layer->mapped); + assert(layer->surface->mapped); seat_set_focus_surface(seat, layer->surface, true); if (layer->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { seat->focused_layer = layer; diff --git a/sway/lock.c b/sway/lock.c index 6d9e991b3..ae44aa40b 100644 --- a/sway/lock.c +++ b/sway/lock.c @@ -60,7 +60,7 @@ static void destroy_lock_surface(struct sway_session_lock_surface *surf) { struct wlr_session_lock_surface_v1 *other; wl_list_for_each(other, &server.session_lock.lock->surfaces, link) { - if (other != surf->lock_surface && other->mapped) { + if (other != surf->lock_surface && other->surface->mapped) { next_focus = other->surface; break; } diff --git a/sway/xdg_activation_v1.c b/sway/xdg_activation_v1.c index e97989c83..c26ee19ab 100644 --- a/sway/xdg_activation_v1.c +++ b/sway/xdg_activation_v1.c @@ -17,7 +17,7 @@ void xdg_activation_v1_handle_request_activate(struct wl_listener *listener, return; } - if (!xdg_surface->mapped) { + if (!xdg_surface->surface->mapped) { // This is a startup notification. If we are tracking it, the data // field is a launcher_ctx. struct launcher_ctx *ctx = event->token->data; From c001a57e8bb2912bfce293e71d32fdbe246eae74 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Fri, 2 Jun 2023 23:18:39 +0300 Subject: [PATCH 035/114] lock: listen to the correct map signal --- sway/lock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/lock.c b/sway/lock.c index ae44aa40b..534561720 100644 --- a/sway/lock.c +++ b/sway/lock.c @@ -104,7 +104,7 @@ static void handle_new_surface(struct wl_listener *listener, void *data) { surf->surface = lock_surface->surface; surf->output = output; surf->map.notify = handle_surface_map; - wl_signal_add(&lock_surface->events.map, &surf->map); + wl_signal_add(&lock_surface->surface->events.map, &surf->map); surf->destroy.notify = handle_surface_destroy; wl_signal_add(&lock_surface->events.destroy, &surf->destroy); surf->surface_commit.notify = handle_surface_commit; From b5cb49bce90bd4d37f08da6a65aba6a99cb7c608 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Sat, 3 Jun 2023 07:43:13 +0300 Subject: [PATCH 036/114] xwayland: fix mapped state check in OR handlers --- sway/desktop/xwayland.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index bb4340f10..a52cf4ad1 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -178,7 +178,7 @@ static void unmanaged_handle_override_redirect(struct wl_listener *listener, voi wl_container_of(listener, surface, override_redirect); struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; - bool mapped = xsurface->surface != NULL || xsurface->surface->mapped; + bool mapped = xsurface->surface != NULL && xsurface->surface->mapped; if (mapped) { unmanaged_handle_unmap(&surface->unmap, NULL); } @@ -537,7 +537,7 @@ static void handle_override_redirect(struct wl_listener *listener, void *data) { struct sway_view *view = &xwayland_view->view; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - bool mapped = xsurface->surface != NULL || xsurface->surface->mapped; + bool mapped = xsurface->surface != NULL && xsurface->surface->mapped; if (mapped) { handle_unmap(&xwayland_view->unmap, NULL); } From 7ab8cb2ee6f11693987d9f24abec708144807b53 Mon Sep 17 00:00:00 2001 From: Artturin Date: Mon, 5 Jun 2023 23:52:11 +0300 Subject: [PATCH 037/114] chase wlroots wlr_renderer_begin_buffer_pass change https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4159 > ../sway/desktop/output.c:618:47: error: too few arguments to function 'wlr_renderer_begin_buffer_pass' > 618 | struct wlr_render_pass *render_pass = wlr_renderer_begin_buffer_pass( > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --- sway/desktop/output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index fe1fa8af7..43ce2d70d 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -616,7 +616,7 @@ static int output_repaint_timer_handler(void *data) { } struct wlr_render_pass *render_pass = wlr_renderer_begin_buffer_pass( - wlr_output->renderer, buffer); + wlr_output->renderer, buffer, NULL); if (render_pass == NULL) { wlr_buffer_unlock(buffer); return false; From 913a7679cbde98df0722b326d8c3cfc0f0576f6d Mon Sep 17 00:00:00 2001 From: Erik Reider <35975961+ErikReider@users.noreply.github.com> Date: Mon, 5 Jun 2023 15:31:16 +0200 Subject: [PATCH 038/114] Add support for wlr-layer-shell ON_DEMAND keyboard interactivity This allows for layer shell surfaces to receive focus while the surface is explicitly focused, i.e allowing text fields to receive keyboard input just like a regular surface. --- include/sway/input/seat.h | 3 ++- include/sway/layers.h | 4 ++++ sway/desktop/layer_shell.c | 40 +++++++++++++++++++++++++++++++++++-- sway/input/seat.c | 20 ++++++++++++++----- sway/input/seatop_default.c | 24 ++++++++++++++++++---- sway/server.c | 2 +- 6 files changed, 80 insertions(+), 13 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 5ef8e2f39..35a96ace9 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -104,8 +104,9 @@ struct sway_seat { struct sway_workspace *workspace; char *prev_workspace_name; // for workspace back_and_forth - // If the focused layer is set, views cannot receive keyboard focus struct wlr_layer_surface_v1 *focused_layer; + // If the exclusive layer is set, views cannot receive keyboard focus + bool has_exclusive_layer; // If exclusive_client is set, no other clients will receive input events struct wl_client *exclusive_client; diff --git a/include/sway/layers.h b/include/sway/layers.h index f85084934..9220bdb54 100644 --- a/include/sway/layers.h +++ b/include/sway/layers.h @@ -55,6 +55,10 @@ struct sway_layer_subsurface { }; struct sway_output; + +struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface( + struct wlr_surface *surface); + void arrange_layers(struct sway_output *output); struct sway_layer_surface *layer_from_wlr_layer_surface_v1( diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 50aa69381..d990d92af 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -17,6 +17,39 @@ #include "sway/tree/arrange.h" #include "sway/tree/workspace.h" +struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface( + struct wlr_surface *surface) { + struct wlr_layer_surface_v1 *layer; + do { + if (!surface) { + return NULL; + } + // Topmost layer surface + if ((layer = wlr_layer_surface_v1_try_from_wlr_surface(surface))) { + return layer; + } + // Layer subsurface + if (wlr_subsurface_try_from_wlr_surface(surface)) { + surface = wlr_surface_get_root_surface(surface); + continue; + } + + // Layer surface popup + struct wlr_xdg_surface * xdg_popup = NULL; + if ((xdg_popup = wlr_xdg_surface_try_from_wlr_surface(surface)) && + xdg_popup->role == WLR_XDG_SURFACE_ROLE_POPUP) { + if (!xdg_popup->popup->parent) { + return NULL; + } + surface = wlr_surface_get_root_surface(xdg_popup->popup->parent); + continue; + } + + // Return early if the surface is not a layer/xdg_popup/sub surface + return NULL; + } while (true); +} + static void apply_exclusive(struct wlr_box *usable_area, uint32_t anchor, int32_t exclusive, int32_t margin_top, int32_t margin_right, @@ -218,7 +251,8 @@ void arrange_layers(struct sway_output *output) { for (size_t i = 0; i < nlayers; ++i) { wl_list_for_each_reverse(layer, &output->layers[layers_above_shell[i]], link) { - if (layer->layer_surface->current.keyboard_interactive && + if (layer->layer_surface->current.keyboard_interactive + == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE && layer->layer_surface->surface->mapped) { topmost = layer; break; @@ -231,10 +265,12 @@ void arrange_layers(struct sway_output *output) { struct sway_seat *seat; wl_list_for_each(seat, &server.input->seats, link) { + seat->has_exclusive_layer = false; if (topmost != NULL) { seat_set_focus_layer(seat, topmost->layer_surface); } else if (seat->focused_layer && - !seat->focused_layer->current.keyboard_interactive) { + seat->focused_layer->current.keyboard_interactive + != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) { seat_set_focus_layer(seat, NULL); } } diff --git a/sway/input/seat.c b/sway/input/seat.c index 5795f40ff..fdd210575 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1295,11 +1295,15 @@ static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *n } void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { - if (seat->focused_layer) { + // Prevents the layer from losing focus if it has keyboard exclusivity + if (seat->has_exclusive_layer) { struct wlr_layer_surface_v1 *layer = seat->focused_layer; seat_set_focus_layer(seat, NULL); seat_set_workspace_focus(seat, node); seat_set_focus_layer(seat, layer); + } else if (seat->focused_layer) { + seat_set_focus_layer(seat, NULL); + seat_set_workspace_focus(seat, node); } else { seat_set_workspace_focus(seat, node); } @@ -1347,14 +1351,20 @@ void seat_set_focus_layer(struct sway_seat *seat, seat_set_focus(seat, previous); } return; - } else if (!layer || seat->focused_layer == layer) { + } else if (!layer) { return; } assert(layer->surface->mapped); - seat_set_focus_surface(seat, layer->surface, true); - if (layer->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { - seat->focused_layer = layer; + if (layer->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP && + layer->current.keyboard_interactive + == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) { + seat->has_exclusive_layer = true; } + if (seat->focused_layer == layer) { + return; + } + seat_set_focus_surface(seat, layer->surface, true); + seat->focused_layer = layer; } void seat_set_exclusive_client(struct sway_seat *seat, diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index 5a55c1866..f4c63808a 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include "gesture.h" @@ -9,6 +10,7 @@ #include "sway/input/cursor.h" #include "sway/input/seat.h" #include "sway/input/tablet.h" +#include "sway/layers.h" #include "sway/output.h" #include "sway/tree/view.h" #include "sway/tree/workspace.h" @@ -365,10 +367,9 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, return; } - // Handle clicking a layer surface - struct wlr_layer_surface_v1 *layer; - if (surface && - (layer = wlr_layer_surface_v1_try_from_wlr_surface(surface))) { + // Handle clicking a layer surface and its popups/subsurfaces + struct wlr_layer_surface_v1 *layer = NULL; + if ((layer = toplevel_layer_surface_from_surface(surface))) { if (layer->current.keyboard_interactive) { seat_set_focus_layer(seat, layer); transaction_commit_dirty(); @@ -544,6 +545,21 @@ static void check_focus_follows_mouse(struct sway_seat *seat, if (wlr_output == NULL) { return; } + + struct wlr_surface *surface = NULL; + double sx, sy; + node_at_coords(seat, seat->cursor->cursor->x, seat->cursor->cursor->y, + &surface, &sx, &sy); + + // Focus topmost layer surface + struct wlr_layer_surface_v1 *layer = NULL; + if ((layer = toplevel_layer_surface_from_surface(surface)) && + layer->current.keyboard_interactive) { + seat_set_focus_layer(seat, layer); + transaction_commit_dirty(); + return; + } + struct sway_output *hovered_output = wlr_output->data; if (focus && hovered_output != node_get_output(focus)) { struct sway_workspace *ws = output_get_active_workspace(hovered_output); diff --git a/sway/server.c b/sway/server.c index 0cf767b7e..c87e30fd4 100644 --- a/sway/server.c +++ b/sway/server.c @@ -55,7 +55,7 @@ #endif #define SWAY_XDG_SHELL_VERSION 2 -#define SWAY_LAYER_SHELL_VERSION 3 +#define SWAY_LAYER_SHELL_VERSION 4 #if WLR_HAS_DRM_BACKEND static void handle_drm_lease_request(struct wl_listener *listener, void *data) { From b1b3563d5483482e19616aec0e70de970a591580 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 6 Mar 2023 17:17:05 +0100 Subject: [PATCH 039/114] Handle gamma-control-v1 set_gamma events References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4046 --- include/sway/output.h | 3 +++ include/sway/server.h | 3 +++ sway/desktop/output.c | 25 +++++++++++++++++++++++++ sway/server.c | 6 +++++- 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/include/sway/output.h b/include/sway/output.h index f6dc6af2b..50d90d25d 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -57,6 +57,7 @@ struct sway_output { uint32_t refresh_nsec; int max_render_time; // In milliseconds struct wl_event_source *repaint_timer; + bool gamma_lut_changed; }; struct sway_output_non_desktop { @@ -187,6 +188,8 @@ enum wlr_direction opposite_direction(enum wlr_direction d); void handle_output_layout_change(struct wl_listener *listener, void *data); +void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data); + void handle_output_manager_apply(struct wl_listener *listener, void *data); void handle_output_manager_test(struct wl_listener *listener, void *data); diff --git a/include/sway/server.h b/include/sway/server.h index a65843ce8..aaa8781b9 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -91,6 +91,9 @@ struct sway_server { struct wl_listener output_manager_apply; struct wl_listener output_manager_test; + struct wlr_gamma_control_manager_v1 *gamma_control_manager_v1; + struct wl_listener gamma_control_set_gamma; + struct { bool locked; struct wlr_session_lock_manager_v1 *manager; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 43ce2d70d..09353c152 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -564,6 +565,7 @@ static int output_repaint_timer_handler(void *data) { wlr_output->frame_pending = false; if (!wlr_output->needs_frame && + !output->gamma_lut_changed && !pixman_region32_not_empty(&output->damage_ring.current)) { return 0; } @@ -578,6 +580,19 @@ static int output_repaint_timer_handler(void *data) { fullscreen_con = workspace->current.fullscreen; } + if (output->gamma_lut_changed) { + struct wlr_gamma_control_v1 *gamma_control = + wlr_gamma_control_manager_v1_get_control( + server.gamma_control_manager_v1, wlr_output); + if (!wlr_gamma_control_v1_apply(gamma_control, &wlr_output->pending)) { + return 0; + } + if (!wlr_output_test(wlr_output)) { + wlr_output_rollback(wlr_output); + wlr_gamma_control_v1_send_failed_and_destroy(gamma_control); + } + } + pixman_region32_t frame_damage; get_frame_damage(output, &frame_damage); wlr_output_set_damage(wlr_output, &frame_damage); @@ -1076,6 +1091,16 @@ void handle_output_layout_change(struct wl_listener *listener, update_output_manager_config(server); } +void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data) { + struct sway_server *server = + wl_container_of(listener, server, gamma_control_set_gamma); + const struct wlr_gamma_control_manager_v1_set_gamma_event *event = data; + + struct sway_output *output = event->output->data; + output->gamma_lut_changed = true; + wlr_output_schedule_frame(output->wlr_output); +} + static void output_manager_apply(struct sway_server *server, struct wlr_output_configuration_v1 *config, bool test_only) { // TODO: perform atomic tests on the whole backend atomically diff --git a/sway/server.c b/sway/server.c index c87e30fd4..9797cf60b 100644 --- a/sway/server.c +++ b/sway/server.c @@ -114,7 +114,11 @@ bool server_init(struct sway_server *server) { server->data_device_manager = wlr_data_device_manager_create(server->wl_display); - wlr_gamma_control_manager_v1_create(server->wl_display); + server->gamma_control_manager_v1 = + wlr_gamma_control_manager_v1_create(server->wl_display); + server->gamma_control_set_gamma.notify = handle_gamma_control_set_gamma; + wl_signal_add(&server->gamma_control_manager_v1->events.set_gamma, + &server->gamma_control_set_gamma); server->new_output.notify = handle_new_output; wl_signal_add(&server->backend->events.new_output, &server->new_output); From f3b8c9feeed9f79fc8f06e7f1dcfaadde522ce90 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 5 Jun 2023 14:35:15 +0200 Subject: [PATCH 040/114] desktop/output: use detached output state for page-flips This avoids relying on the implicit wlr_output.pending state. --- sway/desktop/output.c | 48 +++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 09353c152..9934576c0 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -458,7 +458,7 @@ static void count_surface_iterator(struct sway_output *output, } static bool scan_out_fullscreen_view(struct sway_output *output, - struct sway_view *view) { + struct wlr_output_state *pending, struct sway_view *view) { struct wlr_output *wlr_output = output->wlr_output; struct sway_workspace *workspace = output->current.active_workspace; if (!sway_assert(workspace, "Expected an active workspace")) { @@ -524,15 +524,16 @@ static bool scan_out_fullscreen_view(struct sway_output *output, return false; } - wlr_output_attach_buffer(wlr_output, &surface->buffer->base); - if (!wlr_output_test(wlr_output)) { + wlr_output_state_set_buffer(pending, &surface->buffer->base); + + if (!wlr_output_test_state(wlr_output, pending)) { return false; } wlr_presentation_surface_sampled_on_output(server.presentation, surface, wlr_output); - return wlr_output_commit(wlr_output); + return wlr_output_commit_state(wlr_output, pending); } static void get_frame_damage(struct sway_output *output, @@ -580,29 +581,30 @@ static int output_repaint_timer_handler(void *data) { fullscreen_con = workspace->current.fullscreen; } + struct wlr_output_state pending = {0}; + if (output->gamma_lut_changed) { struct wlr_gamma_control_v1 *gamma_control = wlr_gamma_control_manager_v1_get_control( server.gamma_control_manager_v1, wlr_output); - if (!wlr_gamma_control_v1_apply(gamma_control, &wlr_output->pending)) { - return 0; + if (!wlr_gamma_control_v1_apply(gamma_control, &pending)) { + goto out; } - if (!wlr_output_test(wlr_output)) { - wlr_output_rollback(wlr_output); + if (!wlr_output_test_state(wlr_output, &pending)) { + wlr_output_state_finish(&pending); + pending = (struct wlr_output_state){0}; wlr_gamma_control_v1_send_failed_and_destroy(gamma_control); } } - pixman_region32_t frame_damage; - get_frame_damage(output, &frame_damage); - wlr_output_set_damage(wlr_output, &frame_damage); - pixman_region32_fini(&frame_damage); + pending.committed |= WLR_OUTPUT_STATE_BUFFER; + get_frame_damage(output, &pending.damage); if (fullscreen_con && fullscreen_con->view && !debug.noscanout) { // Try to scan-out the fullscreen view static bool last_scanned_out = false; bool scanned_out = - scan_out_fullscreen_view(output, fullscreen_con->view); + scan_out_fullscreen_view(output, &pending, fullscreen_con->view); if (scanned_out && !last_scanned_out) { sway_log(SWAY_DEBUG, "Scanning out fullscreen view on %s", @@ -616,25 +618,25 @@ static int output_repaint_timer_handler(void *data) { last_scanned_out = scanned_out; if (scanned_out) { - return 0; + goto out; } } - if (!wlr_output_configure_primary_swapchain(wlr_output, NULL, &wlr_output->swapchain)) { - return false; + if (!wlr_output_configure_primary_swapchain(wlr_output, &pending, &wlr_output->swapchain)) { + goto out; } int buffer_age; struct wlr_buffer *buffer = wlr_swapchain_acquire(wlr_output->swapchain, &buffer_age); if (buffer == NULL) { - return false; + goto out; } struct wlr_render_pass *render_pass = wlr_renderer_begin_buffer_pass( wlr_output->renderer, buffer, NULL); if (render_pass == NULL) { wlr_buffer_unlock(buffer); - return false; + goto out; } pixman_region32_t damage; @@ -663,19 +665,21 @@ static int output_repaint_timer_handler(void *data) { if (!wlr_render_pass_submit(render_pass)) { wlr_buffer_unlock(buffer); - return false; + goto out; } - wlr_output_attach_buffer(wlr_output, buffer); + wlr_output_state_set_buffer(&pending, buffer); wlr_buffer_unlock(buffer); - if (!wlr_output_commit(wlr_output)) { - return 0; + if (!wlr_output_commit_state(wlr_output, &pending)) { + goto out; } wlr_damage_ring_rotate(&output->damage_ring); output->last_frame = now; +out: + wlr_output_state_finish(&pending); return 0; } From 65b1a6964c81efd84832c80ec9fc0273c8975225 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 9 Jun 2023 11:27:41 +0200 Subject: [PATCH 041/114] desktop/output: fix damage bitfield in wlr_output_state --- sway/desktop/output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 9934576c0..2bd8d6da7 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -597,7 +597,7 @@ static int output_repaint_timer_handler(void *data) { } } - pending.committed |= WLR_OUTPUT_STATE_BUFFER; + pending.committed |= WLR_OUTPUT_STATE_DAMAGE; get_frame_damage(output, &pending.damage); if (fullscreen_con && fullscreen_con->view && !debug.noscanout) { From 6a1c176d14232a235ec30ce67ce87f3e549a6121 Mon Sep 17 00:00:00 2001 From: Shaked Flur Date: Fri, 9 Jun 2023 11:23:05 +0100 Subject: [PATCH 042/114] man: add --inhibited and --no-repeat to bindsym and bindcode usage --- sway/sway.5.scd | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 25082c412..78d7d2316 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -389,8 +389,8 @@ runtime. for_window move container to output *bindsym* [--whole-window] [--border] [--exclude-titlebar] [--release] [--locked] \ -[--to-code] [--input-device=] [--no-warn] [--no-repeat] [Group<1-4>+] \ - +[--to-code] [--input-device=] [--no-warn] [--no-repeat] [--inhibited] \ +[Group<1-4>+] Binds _key combo_ to execute the sway command _command_ when pressed. You may use XKB key names here (*wev*(1) is a good tool for discovering these). With the flag _--release_, the command is executed when the key combo is @@ -454,7 +454,8 @@ runtime. ``` *bindcode* [--whole-window] [--border] [--exclude-titlebar] [--release] \ -[--locked] [--input-device=] [--no-warn] [Group<1-4>+] +[--locked] [--input-device=] [--no-warn] [--no-repeat] [--inhibited] \ +[Group<1-4>+] is also available for binding with key/button codes instead of key/button names. *bindswitch* [--locked] [--no-warn] [--reload] : From be14cd96cd81270b3a34742f9a25fe21adf4f595 Mon Sep 17 00:00:00 2001 From: 33KK Date: Sun, 11 Jun 2023 11:36:30 +0200 Subject: [PATCH 043/114] Fix `bindsym --to-code` not respecting input configs Fixes #7535 --- sway/input/input-manager.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 1115ba5ec..5f7dfb428 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -532,6 +532,18 @@ static void retranslate_keysyms(struct input_config *input_config) { return; } } + + for (int i = 0; i < config->input_type_configs->length; ++i) { + struct input_config *ic = config->input_type_configs->items[i]; + if (ic->xkb_layout || ic->xkb_file) { + // this is the first config with xkb_layout or xkb_file + if (ic->identifier == input_config->identifier) { + translate_keysyms(ic); + } + + return; + } + } } static void input_manager_configure_input( From 59c27c94d3981ae65136942288dbf0e9d28b3a24 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sun, 11 Jun 2023 10:11:38 -0400 Subject: [PATCH 044/114] gamma_control_v1: Reset dirty flag --- sway/desktop/output.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 2bd8d6da7..6b65768d2 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -584,6 +584,7 @@ static int output_repaint_timer_handler(void *data) { struct wlr_output_state pending = {0}; if (output->gamma_lut_changed) { + output->gamma_lut_changed = false; struct wlr_gamma_control_v1 *gamma_control = wlr_gamma_control_manager_v1_get_control( server.gamma_control_manager_v1, wlr_output); From 8b4b65d66552d782d2c38a17756baf928b90e670 Mon Sep 17 00:00:00 2001 From: Rouven Czerwinski Date: Wed, 14 Jun 2023 08:45:58 +0200 Subject: [PATCH 045/114] gamma_control_v1: handle destroyed output In case a display is unplugged, the sway output may be removed from the userdata before the gamma_control can be reset. In this case we can't schedule a commit on the output, simply return within the function. backtrace full: #0 handle_gamma_control_set_gamma (listener=0x4856a8 , data=0x7ffce1ed59c0) at ../sway/desktop/output.c:1105 server = 0x485440 event = 0x7ffce1ed59c0 output = 0x0 #1 0x00007f430d1dca0c in wl_signal_emit_mutable () from /nix/store/ky1g6ylzr2m4bq8fy0gzrnqmjr6948k5-wayland-1.22.0/lib/libwayland-server.so.0 No symbol table info available. #2 0x00007f430d142370 in gamma_control_destroy (gamma_control=0x29eb9b0) at ../types/wlr_gamma_control_v1.c:37 manager = 0x27e33e0 output = 0x2a10770 event = {output = 0x2a10770, control = 0x0} #3 0x00007f430d14239b in gamma_control_handle_output_destroy (listener=, data=) at ../types/wlr_gamma_control_v1.c:59 gamma_control = #4 0x00007f430d1dca0c in wl_signal_emit_mutable () from /nix/store/ky1g6ylzr2m4bq8fy0gzrnqmjr6948k5-wayland-1.22.0/lib/libwayland-server.so.0 No symbol table info available. #5 0x00007f430d12a0e0 in wlr_output_destroy (output=output@entry=0x2a10770) at ../types/output/output.c:384 cursor = tmp_cursor = layer = tmp_layer = #6 0x00007f430d114ecf in disconnect_drm_connector (conn=conn@entry=0x2a10770) at ../backend/drm/drm.c:1757 __PRETTY_FUNCTION__ = "disconnect_drm_connector" #7 0x00007f430d117078 in scan_drm_connectors (drm=drm@entry=0x1eebab0, event=event@entry=0x7ffce1ed5c1c) at ../backend/drm/drm.c:1597 c = wlr_conn = 0x2a10770 drm_conn = 0x2e760d0 conn_id = index = 4 i = 4 res = 0x2e761f0 seen_len = 5 seen = {true, true, true, true, true, false} new_outputs_len = 0 new_outputs = 0x7ffce1ed5ab0 conn = tmp_conn = index = #8 0x00007f430d113425 in handle_dev_change (listener=0x1eebbb0, data=0x7ffce1ed5c18) at ../backend/drm/backend.c:157 drm = 0x1eebab0 change = 0x7ffce1ed5c18 #9 0x00007f430d1dca0c in wl_signal_emit_mutable () from /nix/store/ky1g6ylzr2m4bq8fy0gzrnqmjr6948k5-wayland-1.22.0/lib/libwayland-server.so.0 No symbol table info available. #10 0x00007f430d111696 in handle_udev_event (fd=, mask=, data=) at ../backend/session/session.c:213 event = {type = WLR_DEVICE_HOTPLUG, {hotplug = {connector_id = 0, prop_id = 0}}} devnum = dev = 0x1ed9460 session = udev_dev = 0x2e70db0 sysname = 0x2e73c60 "card0" devnode = action = 0x7f430d6677b5 "change" seat = __PRETTY_FUNCTION__ = "handle_udev_event" #11 0x00007f430d1de8e2 in wl_event_loop_dispatch () from /nix/store/ky1g6ylzr2m4bq8fy0gzrnqmjr6948k5-wayland-1.22.0/lib/libwayland-server.so.0 No symbol table info available. #12 0x00007f430d1dc445 in wl_display_run () from /nix/store/ky1g6ylzr2m4bq8fy0gzrnqmjr6948k5-wayland-1.22.0/lib/libwayland-server.so.0 No symbol table info available. #13 0x000000000041daa5 in server_run (server=server@entry=0x485440 ) at ../sway/server.c:338 No locals. #14 0x000000000041cf4d in main (argc=, argv=0x7ffce1ed5fe8) at ../sway/main.c:415 verbose = false debug = false validate = false allow_unsupported_gpu = false config_path = 0x0 c = where event->output->data is NULL: (gdb) p event->output->data $5 = (void *) 0x0 --- sway/desktop/output.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 6b65768d2..476bfd252 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -1102,6 +1102,11 @@ void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data) { const struct wlr_gamma_control_manager_v1_set_gamma_event *event = data; struct sway_output *output = event->output->data; + + if(!output) { + return; + } + output->gamma_lut_changed = true; wlr_output_schedule_frame(output->wlr_output); } From c08762901e9840d8dca008dcc8d0b5602602fd0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cezary=20Dro=C5=BCak?= Date: Fri, 16 Jun 2023 11:28:30 +0200 Subject: [PATCH 046/114] input/libinput: add scroll_button_lock method Closes https://github.com/swaywm/sway/issues/6987 Co-authored-by: JJGadgets Co-authored-by: DeltaWhy --- include/sway/commands.h | 1 + include/sway/config.h | 1 + sway/commands/input.c | 1 + sway/commands/input/scroll_button_lock.c | 26 ++++++++++++++++++++++++ sway/config/input.c | 4 ++++ sway/input/libinput.c | 15 ++++++++++++++ sway/ipc-json.c | 11 ++++++++++ sway/meson.build | 1 + sway/sway-input.5.scd | 3 +++ sway/sway-ipc.7.scd | 3 +++ 10 files changed, 66 insertions(+) create mode 100644 sway/commands/input/scroll_button_lock.c diff --git a/include/sway/commands.h b/include/sway/commands.h index 3212c2cf4..270585870 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -266,6 +266,7 @@ sway_cmd input_cmd_scroll_factor; sway_cmd input_cmd_repeat_delay; sway_cmd input_cmd_repeat_rate; sway_cmd input_cmd_scroll_button; +sway_cmd input_cmd_scroll_button_lock; sway_cmd input_cmd_scroll_method; sway_cmd input_cmd_tap; sway_cmd input_cmd_tap_button_map; diff --git a/include/sway/config.h b/include/sway/config.h index aa58da531..f9da19675 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -161,6 +161,7 @@ struct input_config { int repeat_delay; int repeat_rate; int scroll_button; + int scroll_button_lock; int scroll_method; int send_events; int tap; diff --git a/sway/commands/input.c b/sway/commands/input.c index 3075b5f46..306c40f74 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c @@ -27,6 +27,7 @@ static const struct cmd_handler input_handlers[] = { { "repeat_rate", input_cmd_repeat_rate }, { "rotation_angle", input_cmd_rotation_angle }, { "scroll_button", input_cmd_scroll_button }, + { "scroll_button_lock", input_cmd_scroll_button_lock }, { "scroll_factor", input_cmd_scroll_factor }, { "scroll_method", input_cmd_scroll_method }, { "tap", input_cmd_tap }, diff --git a/sway/commands/input/scroll_button_lock.c b/sway/commands/input/scroll_button_lock.c new file mode 100644 index 000000000..f96b65145 --- /dev/null +++ b/sway/commands/input/scroll_button_lock.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include "sway/config.h" +#include "sway/commands.h" +#include "sway/input/input-manager.h" +#include "util.h" + +struct cmd_results *input_cmd_scroll_button_lock(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "scroll_button_lock", EXPECTED_AT_LEAST, 1))) { + return error; + } + struct input_config *ic = config->handler_context.input_config; + if (!ic) { + return cmd_results_new(CMD_FAILURE, "No input device defined."); + } + + if (parse_boolean(argv[0], true)) { + ic->scroll_button_lock = LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED; + } else { + ic->scroll_button_lock = LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED; + } + + return cmd_results_new(CMD_SUCCESS, NULL); +} diff --git a/sway/config/input.c b/sway/config/input.c index 2ee165c9d..44c2be289 100644 --- a/sway/config/input.c +++ b/sway/config/input.c @@ -35,6 +35,7 @@ struct input_config *new_input_config(const char* identifier) { input->pointer_accel = FLT_MIN; input->scroll_factor = FLT_MIN; input->scroll_button = INT_MIN; + input->scroll_button_lock = INT_MIN; input->scroll_method = INT_MIN; input->left_handed = INT_MIN; input->repeat_delay = INT_MIN; @@ -96,6 +97,9 @@ void merge_input_config(struct input_config *dst, struct input_config *src) { if (src->scroll_button != INT_MIN) { dst->scroll_button = src->scroll_button; } + if (src->scroll_button_lock != INT_MIN) { + dst->scroll_button_lock = src->scroll_button_lock; + } if (src->send_events != INT_MIN) { dst->send_events = src->send_events; } diff --git a/sway/input/libinput.c b/sway/input/libinput.c index dd4fc0be9..43875634f 100644 --- a/sway/input/libinput.c +++ b/sway/input/libinput.c @@ -166,6 +166,18 @@ static bool set_scroll_button(struct libinput_device *dev, uint32_t button) { return true; } +static bool set_scroll_button_lock(struct libinput_device *dev, + enum libinput_config_scroll_button_lock_state lock) { + uint32_t scroll = libinput_device_config_scroll_get_methods(dev); + if ((scroll & ~LIBINPUT_CONFIG_SCROLL_NO_SCROLL) == 0 || + libinput_device_config_scroll_get_button_lock(dev) == lock) { + return false; + } + sway_log(SWAY_DEBUG, "scroll_set_button_lock(%" PRIu32 ")", lock); + log_status(libinput_device_config_scroll_set_button_lock(dev, lock)); + return true; +} + static bool set_dwt(struct libinput_device *device, bool dwt) { if (!libinput_device_config_dwt_is_available(device) || libinput_device_config_dwt_get_enabled(device) == dwt) { @@ -276,6 +288,9 @@ bool sway_input_configure_libinput_device(struct sway_input_device *input_device if (ic->scroll_button != INT_MIN) { changed |= set_scroll_button(device, ic->scroll_button); } + if (ic->scroll_button_lock != INT_MIN) { + changed |= set_scroll_button_lock(device, ic->scroll_button_lock); + } if (ic->dwt != INT_MIN) { changed |= set_dwt(device, ic->dwt); } diff --git a/sway/ipc-json.c b/sway/ipc-json.c index c7cbea013..58356d4ea 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -1019,6 +1019,17 @@ static json_object *describe_libinput_device(struct libinput_device *device) { uint32_t button = libinput_device_config_scroll_get_button(device); json_object_object_add(object, "scroll_button", json_object_new_int(button)); + const char *lock = "unknown"; + switch (libinput_device_config_scroll_get_button_lock(device)) { + case LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED: + lock = "enabled"; + break; + case LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED: + lock = "disabled"; + break; + } + json_object_object_add(object, "scroll_button_lock", + json_object_new_string(lock)); } } diff --git a/sway/meson.build b/sway/meson.build index c6a274342..bc193bf94 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -171,6 +171,7 @@ sway_sources = files( 'commands/input/repeat_delay.c', 'commands/input/repeat_rate.c', 'commands/input/scroll_button.c', + 'commands/input/scroll_button_lock.c', 'commands/input/scroll_factor.c', 'commands/input/scroll_method.c', 'commands/input/tap.c', diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index 1662d55a3..082b68c23 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd @@ -185,6 +185,9 @@ The following commands may only be used in the configuration file. debug-events*, or as a x11 mouse button (button[1-3,8,9]). If set to _disable_, it disables the scroll_method on_button_down. +*input* scroll_button_lock enabled|disabled + Enables or disables scroll button lock for specified input device. + *input* scroll_factor Changes the scroll factor for the specified input device. Scroll speed will be scaled by the given value, which must be non-negative. diff --git a/sway/sway-ipc.7.scd b/sway/sway-ipc.7.scd index 42aaaab67..f4a5ccff2 100644 --- a/sway/sway-ipc.7.scd +++ b/sway/sway-ipc.7.scd @@ -1195,6 +1195,9 @@ following properties will be included for devices that support them: : int : The scroll button to use when _scroll_method_ is _on_button_down_. This will be given as an input event code +|- scroll_button_lock +: string +: Whether scroll button lock is enabled. It can be _enabled_ or _disabled_ |- dwt : string : Whether disable-while-typing is enabled. It can be _enabled_ or _disabled_ From 876687000d4de503cdb01fcd8fa14f1b05dd9a1e Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 19 Jun 2023 13:05:12 -0400 Subject: [PATCH 047/114] render: Use wlroots scale filter --- meson.build | 2 -- sway/desktop/render.c | 33 +++++++-------------------------- sway/meson.build | 1 - 3 files changed, 7 insertions(+), 29 deletions(-) diff --git a/meson.build b/meson.build index 559ee962d..eeee39cde 100644 --- a/meson.build +++ b/meson.build @@ -48,7 +48,6 @@ wlroots = dependency('wlroots', version: wlroots_version) wlroots_features = { 'xwayland': false, 'libinput_backend': false, - 'gles2_renderer': false, 'session': false, } foreach name, _ : wlroots_features @@ -75,7 +74,6 @@ pango = dependency('pango') pangocairo = dependency('pangocairo') gdk_pixbuf = dependency('gdk-pixbuf-2.0', required: get_option('gdk-pixbuf')) pixman = dependency('pixman-1') -glesv2 = wlroots_features['gles2_renderer'] ? dependency('glesv2') : null_dep libevdev = dependency('libevdev') libinput = wlroots_features['libinput_backend'] ? dependency('libinput', version: '>=1.21.0') : null_dep xcb = dependency('xcb', required: get_option('xwayland')) diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 210140424..f08e2c6c4 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -27,10 +27,6 @@ #include "sway/tree/view.h" #include "sway/tree/workspace.h" -#if WLR_HAS_GLES2_RENDERER -#include -#endif - struct render_data { struct render_context *ctx; const pixman_region32_t *damage; @@ -71,30 +67,15 @@ static int scale_length(int length, int offset, float scale) { return roundf((offset + length) * scale) - roundf(offset * scale); } -static void set_scale_filter(struct wlr_output *wlr_output, - struct wlr_texture *texture, enum scale_filter_mode scale_filter) { -#if WLR_HAS_GLES2_RENDERER - if (!wlr_texture_is_gles2(texture)) { - return; - } - - struct wlr_gles2_texture_attribs attribs; - wlr_gles2_texture_get_attribs(texture, &attribs); - - glBindTexture(attribs.target, attribs.tex); - - switch (scale_filter) { +static enum wlr_scale_filter_mode get_scale_filter(struct sway_output *output) { + switch (output->scale_filter) { case SCALE_FILTER_LINEAR: - glTexParameteri(attribs.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - break; + return WLR_SCALE_FILTER_BILINEAR; case SCALE_FILTER_NEAREST: - glTexParameteri(attribs.target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - break; - case SCALE_FILTER_DEFAULT: - case SCALE_FILTER_SMART: - assert(false); // unreachable + return WLR_SCALE_FILTER_NEAREST; + default: + abort(); // unreachable } -#endif } static void render_texture(struct render_context *ctx, struct wlr_texture *texture, @@ -128,7 +109,6 @@ static void render_texture(struct render_context *ctx, struct wlr_texture *textu transform_output_damage(&damage, output->wlr_output); transform = wlr_output_transform_compose(transform, output->wlr_output->transform); - set_scale_filter(output->wlr_output, texture, output->scale_filter); wlr_render_pass_add_texture(ctx->pass, &(struct wlr_render_texture_options) { .texture = texture, .src_box = src_box, @@ -136,6 +116,7 @@ static void render_texture(struct render_context *ctx, struct wlr_texture *textu .transform = transform, .alpha = &alpha, .clip = &damage, + .filter_mode = get_scale_filter(output), }); damage_finish: diff --git a/sway/meson.build b/sway/meson.build index bc193bf94..3abd778db 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -223,7 +223,6 @@ sway_deps = [ math, pango, pcre2, - glesv2, pixman, threads, wayland_server, From 6f1a3b6652b94b568b32f2875e5dc3c61a14d71c Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 15 Jun 2023 18:43:09 +0200 Subject: [PATCH 048/114] Use wlr_cursor_set_xcursor() wlr_xcursor_manager_set_cursor_image() is deprecated. References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4170 --- sway/input/cursor.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index d8ec11ac2..684bb1d3a 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -1070,8 +1070,7 @@ void cursor_set_image(struct sway_cursor *cursor, const char *image, if (!image) { wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0); } else if (!current_image || strcmp(current_image, image) != 0) { - wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, image, - cursor->cursor); + wlr_cursor_set_xcursor(cursor->cursor, cursor->xcursor_manager, image); } } From 5411ed4ef0fa84f0622149bbe2305910be9f0b67 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 15 Jun 2023 18:44:40 +0200 Subject: [PATCH 049/114] Use wlr_cursor_unset_image() A bit cleaner. References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4209 --- sway/input/cursor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 684bb1d3a..abc6c554d 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -252,7 +252,7 @@ void cursor_update_image(struct sway_cursor *cursor, } static void cursor_hide(struct sway_cursor *cursor) { - wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0); + wlr_cursor_unset_image(cursor->cursor); cursor->hidden = true; wlr_seat_pointer_notify_clear_focus(cursor->seat->wlr_seat); } @@ -1068,7 +1068,7 @@ void cursor_set_image(struct sway_cursor *cursor, const char *image, } if (!image) { - wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0); + wlr_cursor_unset_image(cursor->cursor); } else if (!current_image || strcmp(current_image, image) != 0) { wlr_cursor_set_xcursor(cursor->cursor, cursor->xcursor_manager, image); } From b762f455d942e81e076a4a4d475fb9926372da16 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 19 Jun 2023 21:16:23 +0200 Subject: [PATCH 050/114] idle-inhibit-v1: simplify with server global We only have a single running server, no need to keep track of multiple server instances. Also no need to support multiple idle inhibit managers. --- include/sway/desktop/idle_inhibit_v1.h | 11 ++---- include/sway/server.h | 3 +- sway/commands/inhibit_idle.c | 2 +- sway/desktop/idle_inhibit_v1.c | 46 +++++++++++--------------- sway/desktop/transaction.c | 2 +- sway/server.c | 3 +- 6 files changed, 28 insertions(+), 39 deletions(-) diff --git a/include/sway/desktop/idle_inhibit_v1.h b/include/sway/desktop/idle_inhibit_v1.h index 58d54c686..6dda1af97 100644 --- a/include/sway/desktop/idle_inhibit_v1.h +++ b/include/sway/desktop/idle_inhibit_v1.h @@ -2,7 +2,6 @@ #define _SWAY_DESKTOP_IDLE_INHIBIT_V1_H #include #include -#include "sway/server.h" enum sway_idle_inhibit_mode { INHIBIT_IDLE_APPLICATION, // Application set inhibitor (when visible) @@ -16,12 +15,9 @@ struct sway_idle_inhibit_manager_v1 { struct wlr_idle_inhibit_manager_v1 *wlr_manager; struct wl_listener new_idle_inhibitor_v1; struct wl_list inhibitors; - - struct wlr_idle *idle; }; struct sway_idle_inhibitor_v1 { - struct sway_idle_inhibit_manager_v1 *manager; struct wlr_idle_inhibitor_v1 *wlr_inhibitor; struct sway_view *view; enum sway_idle_inhibit_mode mode; @@ -33,8 +29,7 @@ struct sway_idle_inhibitor_v1 { bool sway_idle_inhibit_v1_is_active( struct sway_idle_inhibitor_v1 *inhibitor); -void sway_idle_inhibit_v1_check_active( - struct sway_idle_inhibit_manager_v1 *manager); +void sway_idle_inhibit_v1_check_active(void); void sway_idle_inhibit_v1_user_inhibitor_register(struct sway_view *view, enum sway_idle_inhibit_mode mode); @@ -48,6 +43,6 @@ struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_application_inhibitor_for_vi void sway_idle_inhibit_v1_user_inhibitor_destroy( struct sway_idle_inhibitor_v1 *inhibitor); -struct sway_idle_inhibit_manager_v1 *sway_idle_inhibit_manager_v1_create( - struct wl_display *wl_display, struct wlr_idle *idle); +bool sway_idle_inhibit_manager_v1_init(void); + #endif diff --git a/include/sway/server.h b/include/sway/server.h index aaa8781b9..0e4ec2be3 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -21,6 +21,7 @@ #include #include "config.h" #include "list.h" +#include "sway/desktop/idle_inhibit_v1.h" #if HAVE_XWAYLAND #include "sway/xwayland.h" #endif @@ -53,7 +54,7 @@ struct sway_server { struct wlr_idle *idle; struct wlr_idle_notifier_v1 *idle_notifier_v1; - struct sway_idle_inhibit_manager_v1 *idle_inhibit_manager_v1; + struct sway_idle_inhibit_manager_v1 idle_inhibit_manager_v1; struct wlr_layer_shell_v1 *layer_shell; struct wl_listener layer_shell_surface; diff --git a/sway/commands/inhibit_idle.c b/sway/commands/inhibit_idle.c index aebc2bf9f..6125736ac 100644 --- a/sway/commands/inhibit_idle.c +++ b/sway/commands/inhibit_idle.c @@ -41,7 +41,7 @@ struct cmd_results *cmd_inhibit_idle(int argc, char **argv) { sway_idle_inhibit_v1_user_inhibitor_destroy(inhibitor); } else { inhibitor->mode = mode; - sway_idle_inhibit_v1_check_active(server.idle_inhibit_manager_v1); + sway_idle_inhibit_v1_check_active(); } } else if (!clear) { sway_idle_inhibit_v1_user_inhibitor_register(con->view, mode); diff --git a/sway/desktop/idle_inhibit_v1.c b/sway/desktop/idle_inhibit_v1.c index 3a4d0b878..1fa058e3d 100644 --- a/sway/desktop/idle_inhibit_v1.c +++ b/sway/desktop/idle_inhibit_v1.c @@ -12,7 +12,7 @@ static void destroy_inhibitor(struct sway_idle_inhibitor_v1 *inhibitor) { wl_list_remove(&inhibitor->link); wl_list_remove(&inhibitor->destroy.link); - sway_idle_inhibit_v1_check_active(inhibitor->manager); + sway_idle_inhibit_v1_check_active(); free(inhibitor); } @@ -35,7 +35,6 @@ void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) { return; } - inhibitor->manager = manager; inhibitor->mode = INHIBIT_IDLE_APPLICATION; inhibitor->wlr_inhibitor = wlr_inhibitor; wl_list_insert(&manager->inhibitors, &inhibitor->link); @@ -43,33 +42,34 @@ void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) { inhibitor->destroy.notify = handle_destroy; wl_signal_add(&wlr_inhibitor->events.destroy, &inhibitor->destroy); - sway_idle_inhibit_v1_check_active(manager); + sway_idle_inhibit_v1_check_active(); } void sway_idle_inhibit_v1_user_inhibitor_register(struct sway_view *view, enum sway_idle_inhibit_mode mode) { + struct sway_idle_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1; + struct sway_idle_inhibitor_v1 *inhibitor = calloc(1, sizeof(struct sway_idle_inhibitor_v1)); if (!inhibitor) { return; } - inhibitor->manager = server.idle_inhibit_manager_v1; inhibitor->mode = mode; inhibitor->view = view; - wl_list_insert(&inhibitor->manager->inhibitors, &inhibitor->link); + wl_list_insert(&manager->inhibitors, &inhibitor->link); inhibitor->destroy.notify = handle_destroy; wl_signal_add(&view->events.unmap, &inhibitor->destroy); - sway_idle_inhibit_v1_check_active(inhibitor->manager); + sway_idle_inhibit_v1_check_active(); } struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_user_inhibitor_for_view( struct sway_view *view) { + struct sway_idle_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1; struct sway_idle_inhibitor_v1 *inhibitor; - wl_list_for_each(inhibitor, &server.idle_inhibit_manager_v1->inhibitors, - link) { + wl_list_for_each(inhibitor, &manager->inhibitors, link) { if (inhibitor->mode != INHIBIT_IDLE_APPLICATION && inhibitor->view == view) { return inhibitor; @@ -80,9 +80,9 @@ struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_user_inhibitor_for_view( struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_application_inhibitor_for_view( struct sway_view *view) { + struct sway_idle_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1; struct sway_idle_inhibitor_v1 *inhibitor; - wl_list_for_each(inhibitor, &server.idle_inhibit_manager_v1->inhibitors, - link) { + wl_list_for_each(inhibitor, &manager->inhibitors, link) { if (inhibitor->mode == INHIBIT_IDLE_APPLICATION && view_from_wlr_surface(inhibitor->wlr_inhibitor->surface) == view) { return inhibitor; @@ -131,8 +131,8 @@ bool sway_idle_inhibit_v1_is_active(struct sway_idle_inhibitor_v1 *inhibitor) { return false; } -void sway_idle_inhibit_v1_check_active( - struct sway_idle_inhibit_manager_v1 *manager) { +void sway_idle_inhibit_v1_check_active(void) { + struct sway_idle_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1; struct sway_idle_inhibitor_v1 *inhibitor; bool inhibited = false; wl_list_for_each(inhibitor, &manager->inhibitors, link) { @@ -140,28 +140,22 @@ void sway_idle_inhibit_v1_check_active( break; } } - wlr_idle_set_enabled(manager->idle, NULL, !inhibited); + wlr_idle_set_enabled(server.idle, NULL, !inhibited); wlr_idle_notifier_v1_set_inhibited(server.idle_notifier_v1, inhibited); } -struct sway_idle_inhibit_manager_v1 *sway_idle_inhibit_manager_v1_create( - struct wl_display *wl_display, struct wlr_idle *idle) { - struct sway_idle_inhibit_manager_v1 *manager = - calloc(1, sizeof(struct sway_idle_inhibit_manager_v1)); - if (!manager) { - return NULL; +bool sway_idle_inhibit_manager_v1_init(void) { + struct sway_idle_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1; + + manager->wlr_manager = wlr_idle_inhibit_v1_create(server.wl_display); + if (!manager->wlr_manager) { + return false; } - manager->wlr_manager = wlr_idle_inhibit_v1_create(wl_display); - if (!manager->wlr_manager) { - free(manager); - return NULL; - } - manager->idle = idle; wl_signal_add(&manager->wlr_manager->events.new_inhibitor, &manager->new_idle_inhibitor_v1); manager->new_idle_inhibitor_v1.notify = handle_idle_inhibitor_v1; wl_list_init(&manager->inhibitors); - return manager; + return true; } diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index f5a3a053f..6947e1384 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -344,7 +344,7 @@ static void transaction_progress(void) { server.queued_transaction = NULL; if (!server.pending_transaction) { - sway_idle_inhibit_v1_check_active(server.idle_inhibit_manager_v1); + sway_idle_inhibit_v1_check_active(); return; } diff --git a/sway/server.c b/sway/server.c index 9797cf60b..cc4719d72 100644 --- a/sway/server.c +++ b/sway/server.c @@ -130,8 +130,7 @@ bool server_init(struct sway_server *server) { server->idle = wlr_idle_create(server->wl_display); server->idle_notifier_v1 = wlr_idle_notifier_v1_create(server->wl_display); - server->idle_inhibit_manager_v1 = - sway_idle_inhibit_manager_v1_create(server->wl_display, server->idle); + sway_idle_inhibit_manager_v1_init(); server->layer_shell = wlr_layer_shell_v1_create(server->wl_display, SWAY_LAYER_SHELL_VERSION); From 7fbd9fbf2825f1c41468ac996aced9ba4b152992 Mon Sep 17 00:00:00 2001 From: Hodong <111117126+hodong-kim@users.noreply.github.com> Date: Sat, 24 Jun 2023 00:54:08 +0900 Subject: [PATCH 051/114] swaybar: remove the argument of StatusNotifierHostRegistered According to https://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/StatusNotifierWatcher/ there is no argument for the StatusNotifierHostRegistered signal. --- swaybar/tray/watcher.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swaybar/tray/watcher.c b/swaybar/tray/watcher.c index 551e1d12c..2458a8c2f 100644 --- a/swaybar/tray/watcher.c +++ b/swaybar/tray/watcher.c @@ -106,7 +106,7 @@ static int register_host(sd_bus_message *msg, void *data, sd_bus_error *error) { sway_log(SWAY_DEBUG, "Registering Status Notifier Host '%s'", service); list_add(watcher->hosts, strdup(service)); sd_bus_emit_signal(watcher->bus, obj_path, watcher->interface, - "StatusNotifierHostRegistered", "s", service); + "StatusNotifierHostRegistered", ""); } else { sway_log(SWAY_DEBUG, "Status Notifier Host '%s' already registered", service); } From 974a8629a8f0f403028332543e4bd31d98f611c1 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 23 Jun 2023 12:28:15 +0200 Subject: [PATCH 052/114] Use "default" XCursor instead of "left_ptr" "left_ptr" is the legacy XCursor name. "default" is the cursor spec name. --- sway/input/cursor.c | 4 ++-- sway/input/seat.c | 6 +++--- swaybar/input.c | 2 +- swaynag/swaynag.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index abc6c554d..7a4dd19f8 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -236,7 +236,7 @@ void cursor_update_image(struct sway_cursor *cursor, // Try a node's resize edge enum wlr_edges edge = find_resize_edge(node->sway_container, NULL, cursor); if (edge == WLR_EDGE_NONE) { - cursor_set_image(cursor, "left_ptr", NULL); + cursor_set_image(cursor, "default", NULL); } else if (container_is_floating(node->sway_container)) { cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL); } else { @@ -247,7 +247,7 @@ void cursor_update_image(struct sway_cursor *cursor, } } } else { - cursor_set_image(cursor, "left_ptr", NULL); + cursor_set_image(cursor, "default", NULL); } } diff --git a/sway/input/seat.c b/sway/input/seat.c index fdd210575..82f4eb5f0 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -671,7 +671,7 @@ static void seat_update_capabilities(struct sway_seat *seat) { } else { wlr_seat_set_capabilities(seat->wlr_seat, caps); if ((previous_caps & WL_SEAT_CAPABILITY_POINTER) == 0) { - cursor_set_image(seat->cursor, "left_ptr", NULL); + cursor_set_image(seat->cursor, "default", NULL); } } } @@ -1039,7 +1039,7 @@ void seat_configure_xcursor(struct sway_seat *seat) { wlr_xcursor_manager_load(server.xwayland.xcursor_manager, 1); struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor( - server.xwayland.xcursor_manager, "left_ptr", 1); + server.xwayland.xcursor_manager, "default", 1); if (xcursor != NULL) { struct wlr_xcursor_image *image = xcursor->images[0]; wlr_xwayland_set_cursor( @@ -1082,7 +1082,7 @@ void seat_configure_xcursor(struct sway_seat *seat) { // Reset the cursor so that we apply it to outputs that just appeared cursor_set_image(seat->cursor, NULL, NULL); - cursor_set_image(seat->cursor, "left_ptr", NULL); + cursor_set_image(seat->cursor, "default", NULL); wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, seat->cursor->cursor->y); } diff --git a/swaybar/input.c b/swaybar/input.c index 8eccf5420..f8f0672ef 100644 --- a/swaybar/input.c +++ b/swaybar/input.c @@ -82,7 +82,7 @@ void update_cursor(struct swaybar_seat *seat) { pointer->cursor_theme = wl_cursor_theme_load( cursor_theme, cursor_size * scale, seat->bar->shm); struct wl_cursor *cursor; - cursor = wl_cursor_theme_get_cursor(pointer->cursor_theme, "left_ptr"); + cursor = wl_cursor_theme_get_cursor(pointer->cursor_theme, "default"); pointer->cursor_image = cursor->images[0]; wl_surface_set_buffer_scale(pointer->cursor_surface, scale); wl_surface_attach(pointer->cursor_surface, diff --git a/swaynag/swaynag.c b/swaynag/swaynag.c index 08e26127c..1b114e28f 100644 --- a/swaynag/swaynag.c +++ b/swaynag/swaynag.c @@ -154,7 +154,7 @@ static void update_cursor(struct swaynag_seat *seat) { pointer->cursor_theme = wl_cursor_theme_load( cursor_theme, cursor_size * swaynag->scale, swaynag->shm); struct wl_cursor *cursor = - wl_cursor_theme_get_cursor(pointer->cursor_theme, "left_ptr"); + wl_cursor_theme_get_cursor(pointer->cursor_theme, "default"); pointer->cursor_image = cursor->images[0]; wl_surface_set_buffer_scale(pointer->cursor_surface, swaynag->scale); From 20c91335f6ba515e43b444fafd52b822bd460eda Mon Sep 17 00:00:00 2001 From: Mark Bolhuis Date: Mon, 26 Jun 2023 21:43:13 +0100 Subject: [PATCH 053/114] input: Move wlr_pointer_gestures_v1 to sway_input_manager On multi-seat configurations a zwp_pointer_gestures_v1 global was created for every seat. Instead, create the global once in the input manager, to be shared across all seats. --- include/sway/input/cursor.h | 1 - include/sway/input/input-manager.h | 1 + sway/input/cursor.c | 3 --- sway/input/input-manager.c | 2 ++ sway/input/seatop_default.c | 16 ++++++++-------- 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index c7da88293..1636588a4 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -35,7 +35,6 @@ struct sway_cursor { pixman_region32_t confine; // invalid if active_constraint == NULL bool active_confine_requires_warp; - struct wlr_pointer_gestures_v1 *pointer_gestures; struct wl_listener hold_begin; struct wl_listener hold_end; struct wl_listener pinch_begin; diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index c9bd08f0d..b651e3dd9 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -25,6 +25,7 @@ struct sway_input_manager { struct wlr_keyboard_shortcuts_inhibit_manager_v1 *keyboard_shortcuts_inhibit; struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard; struct wlr_virtual_pointer_manager_v1 *virtual_pointer; + struct wlr_pointer_gestures_v1 *pointer_gestures; struct wl_listener new_input; struct wl_listener inhibit_activate; diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 7a4dd19f8..f970e6a21 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -1154,9 +1154,6 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { wl_list_init(&cursor->image_surface_destroy.link); cursor->image_surface_destroy.notify = handle_image_surface_destroy; - // gesture events - cursor->pointer_gestures = wlr_pointer_gestures_v1_create(server.wl_display); - wl_signal_add(&wlr_cursor->events.hold_begin, &cursor->hold_begin); cursor->hold_begin.notify = handle_pointer_hold_begin; wl_signal_add(&wlr_cursor->events.hold_end, &cursor->hold_end); diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 5f7dfb428..db82bb4c8 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -495,6 +495,8 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) { wl_signal_add(&input->keyboard_shortcuts_inhibit->events.new_inhibitor, &input->keyboard_shortcuts_inhibit_new_inhibitor); + input->pointer_gestures = wlr_pointer_gestures_v1_create(server->wl_display); + return input; } diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index f4c63808a..1dce6dae2 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -949,7 +949,7 @@ static void handle_hold_begin(struct sway_seat *seat, // ... otherwise forward to client struct sway_cursor *cursor = seat->cursor; wlr_pointer_gestures_v1_send_hold_begin( - cursor->pointer_gestures, cursor->seat->wlr_seat, + server.input->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->fingers); } } @@ -961,7 +961,7 @@ static void handle_hold_end(struct sway_seat *seat, if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_HOLD)) { struct sway_cursor *cursor = seat->cursor; wlr_pointer_gestures_v1_send_hold_end( - cursor->pointer_gestures, cursor->seat->wlr_seat, + server.input->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->cancelled); return; } @@ -994,7 +994,7 @@ static void handle_pinch_begin(struct sway_seat *seat, // ... otherwise forward to client struct sway_cursor *cursor = seat->cursor; wlr_pointer_gestures_v1_send_pinch_begin( - cursor->pointer_gestures, cursor->seat->wlr_seat, + server.input->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->fingers); } } @@ -1010,7 +1010,7 @@ static void handle_pinch_update(struct sway_seat *seat, // ... otherwise forward to client struct sway_cursor *cursor = seat->cursor; wlr_pointer_gestures_v1_send_pinch_update( - cursor->pointer_gestures, + server.input->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->dx, event->dy, event->scale, event->rotation); @@ -1024,7 +1024,7 @@ static void handle_pinch_end(struct sway_seat *seat, if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_PINCH)) { struct sway_cursor *cursor = seat->cursor; wlr_pointer_gestures_v1_send_pinch_end( - cursor->pointer_gestures, cursor->seat->wlr_seat, + server.input->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->cancelled); return; } @@ -1057,7 +1057,7 @@ static void handle_swipe_begin(struct sway_seat *seat, // ... otherwise forward to client struct sway_cursor *cursor = seat->cursor; wlr_pointer_gestures_v1_send_swipe_begin( - cursor->pointer_gestures, cursor->seat->wlr_seat, + server.input->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->fingers); } } @@ -1074,7 +1074,7 @@ static void handle_swipe_update(struct sway_seat *seat, // ... otherwise forward to client struct sway_cursor *cursor = seat->cursor; wlr_pointer_gestures_v1_send_swipe_update( - cursor->pointer_gestures, cursor->seat->wlr_seat, + server.input->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->dx, event->dy); } } @@ -1085,7 +1085,7 @@ static void handle_swipe_end(struct sway_seat *seat, struct seatop_default_event *seatop = seat->seatop_data; if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_SWIPE)) { struct sway_cursor *cursor = seat->cursor; - wlr_pointer_gestures_v1_send_swipe_end(cursor->pointer_gestures, + wlr_pointer_gestures_v1_send_swipe_end(server.input->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->cancelled); return; } From 20ffe545bab3fe518d8d1be00949943f7d39cfe0 Mon Sep 17 00:00:00 2001 From: llyyr Date: Tue, 27 Jun 2023 22:50:25 +0530 Subject: [PATCH 054/114] swaybar: don't set current workspace as not visible When `wrap_scroll yes` is configured and there's only one workspace open, swaybar will mark it as not visible if the user scrolls on it and eventually incorrectly fail the `active->visible` assert. Fix this by making sure that new and current workspace aren't the same. --- swaybar/input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swaybar/input.c b/swaybar/input.c index f8f0672ef..358c69cbc 100644 --- a/swaybar/input.c +++ b/swaybar/input.c @@ -207,7 +207,7 @@ static void workspace_next(struct swaybar *bar, struct swaybar_output *output, } } - if (new) { + if (new && new != active) { ipc_send_workspace_command(bar, new->name); // Since we're asking Sway to switch to 'new', it should become visible. From 92244c87dbb85080c99eee10db9fed906117e169 Mon Sep 17 00:00:00 2001 From: Manuel Stoeckl Date: Fri, 7 Jul 2023 19:38:02 -0400 Subject: [PATCH 055/114] swaybar: handle wayland-cursor failures Updating the cursor is not essential, so this change prints a warning when wl_cursor_theme_load or wl_cursor_theme_get_cursor fail instead of crashing or exiting. --- swaybar/input.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/swaybar/input.c b/swaybar/input.c index 358c69cbc..1e6ace008 100644 --- a/swaybar/input.c +++ b/swaybar/input.c @@ -81,8 +81,16 @@ void update_cursor(struct swaybar_seat *seat) { int scale = pointer->current ? pointer->current->scale : 1; pointer->cursor_theme = wl_cursor_theme_load( cursor_theme, cursor_size * scale, seat->bar->shm); + if (!pointer->cursor_theme) { + sway_log(SWAY_ERROR, "Failed to load cursor theme"); + return; + } struct wl_cursor *cursor; cursor = wl_cursor_theme_get_cursor(pointer->cursor_theme, "default"); + if (!cursor) { + sway_log(SWAY_ERROR, "Failed to get default cursor from theme"); + return; + } pointer->cursor_image = cursor->images[0]; wl_surface_set_buffer_scale(pointer->cursor_surface, scale); wl_surface_attach(pointer->cursor_surface, From fc16fb65491bda0d059b8c9aeae3dc9962e5c690 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 8 Feb 2023 15:28:20 +0100 Subject: [PATCH 056/114] Send wl_surface.preferred_buffer_scale References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3696 --- sway/desktop/surface.c | 1 + sway/server.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sway/desktop/surface.c b/sway/desktop/surface.c index 68772ee0f..5932eaa23 100644 --- a/sway/desktop/surface.c +++ b/sway/desktop/surface.c @@ -56,6 +56,7 @@ void surface_update_outputs(struct wlr_surface *surface) { } } wlr_fractional_scale_v1_notify_scale(surface, scale); + wlr_surface_set_preferred_buffer_scale(surface, ceil(scale)); } void surface_enter_output(struct wlr_surface *surface, diff --git a/sway/server.c b/sway/server.c index cc4719d72..3a11088a7 100644 --- a/sway/server.c +++ b/sway/server.c @@ -103,7 +103,7 @@ bool server_init(struct sway_server *server) { return false; } - server->compositor = wlr_compositor_create(server->wl_display, 5, + server->compositor = wlr_compositor_create(server->wl_display, 6, server->renderer); server->compositor_new_surface.notify = handle_compositor_new_surface; wl_signal_add(&server->compositor->events.new_surface, From 6c234d013a7457cefd7938182088530d631b875e Mon Sep 17 00:00:00 2001 From: nukoseer Date: Mon, 5 Jun 2023 19:34:24 +0000 Subject: [PATCH 057/114] Calculate tiled resize amount relative to parent container sway should shrinks/grows tiled windows according to parent container for ppt unit for i3 compatibility. Resolves: #7593 --- sway/commands/resize.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/sway/commands/resize.c b/sway/commands/resize.c index e69e5506e..f59e2aeb2 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c @@ -253,12 +253,27 @@ static struct cmd_results *resize_adjust_tiled(uint32_t axis, amount->unit = MOVEMENT_UNIT_PPT; } if (amount->unit == MOVEMENT_UNIT_PPT) { + struct sway_container *parent = current->pending.parent; float pct = amount->amount / 100.0f; if (is_horizontal(axis)) { - amount->amount = (float)current->pending.width * pct; + while (parent && parent->pending.layout != L_HORIZ) { + parent = parent->pending.parent; + } + if (parent) { + amount->amount = (float)parent->pending.width * pct; + } else { + amount->amount = (float)current->pending.workspace->width * pct; + } } else { - amount->amount = (float)current->pending.height * pct; + while (parent && parent->pending.layout != L_VERT) { + parent = parent->pending.parent; + } + if (parent) { + amount->amount = (float)parent->pending.height * pct; + } else { + amount->amount = (float)current->pending.workspace->height * pct; + } } } From 91079079690c8832b22960403f0e60c63822d17a Mon Sep 17 00:00:00 2001 From: Artturin Date: Sat, 15 Jul 2023 15:43:37 +0300 Subject: [PATCH 058/114] chase wlroots 'presentation-time: add separate helper for zero-copy ' https://gitlab.freedesktop.org/wlroots/wlroots/-/commit/67447d6cb407ac5b6405b4dbae01a38567feb111 --- sway/desktop/output.c | 2 +- sway/desktop/render.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 476bfd252..f6ff90ef4 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -530,7 +530,7 @@ static bool scan_out_fullscreen_view(struct sway_output *output, return false; } - wlr_presentation_surface_sampled_on_output(server.presentation, surface, + wlr_presentation_surface_scanned_out_on_output(server.presentation, surface, wlr_output); return wlr_output_commit_state(wlr_output, pending); diff --git a/sway/desktop/render.c b/sway/desktop/render.c index f08e2c6c4..c4c0004e7 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -150,7 +150,7 @@ static void render_surface_iterator(struct sway_output *output, render_texture(data->ctx, texture, &src_box, &dst_box, &clip_box, surface->current.transform, alpha); - wlr_presentation_surface_sampled_on_output(server.presentation, surface, + wlr_presentation_surface_textured_on_output(server.presentation, surface, wlr_output); } From a34d785a26c9180de62530593b6693ca4c0b3615 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 13 Jul 2023 09:50:59 +0200 Subject: [PATCH 059/114] swaynag: handle wayland-cursor failures Same as 92244c87dbb8 ("swaybar: handle wayland-cursor failures") but for swaynag. Closes: https://github.com/swaywm/sway/issues/7671 --- swaynag/swaynag.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/swaynag/swaynag.c b/swaynag/swaynag.c index 1b114e28f..b45485f79 100644 --- a/swaynag/swaynag.c +++ b/swaynag/swaynag.c @@ -153,8 +153,16 @@ static void update_cursor(struct swaynag_seat *seat) { } pointer->cursor_theme = wl_cursor_theme_load( cursor_theme, cursor_size * swaynag->scale, swaynag->shm); + if (!pointer->cursor_theme) { + sway_log(SWAY_ERROR, "Failed to load cursor theme"); + return; + } struct wl_cursor *cursor = wl_cursor_theme_get_cursor(pointer->cursor_theme, "default"); + if (!cursor) { + sway_log(SWAY_ERROR, "Failed to get default cursor from theme"); + return; + } pointer->cursor_image = cursor->images[0]; wl_surface_set_buffer_scale(pointer->cursor_surface, swaynag->scale); From ee4637b086aed256c7698b9f68786e6de5d8da00 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 12 Jul 2023 10:14:15 +0200 Subject: [PATCH 060/114] Deprecate seat idle_wake Sway has two knobs to control idling: - seat idle_inhibit: when the seat is active (ie. not idle), this extends the active state. When the seat is idle, this is ignored. - seat idle_wake: when the seat is idle, this wakes up the seat. When the seat is active, this is ignored. The motivation for the deprecation is two-fold: - The concept of "seat idle state" is ill-defined. Each idle-notify-v1 client will pass a different idle timeout. With the old logic, a seat was declared idle if and only if all idle-notify-v1 timeouts have expired. However, if only a portion of the timeouts have expired, then some clients would wake up, and the rest would stay active. This is inconsistent with the definition of idle_inhibit/idle_wake: idle_inhibit was used for clients which are waking up. - It never worked properly with the new idle-notify-v1 protocol and no-one noticed. Only the legacy KDE idle protocol is taken into account, but that protocol is not used anymore. --- sway/commands/seat/idle.c | 6 ++++++ sway/input/seat.c | 19 ++++--------------- sway/sway-input.5.scd | 6 ------ 3 files changed, 10 insertions(+), 21 deletions(-) diff --git a/sway/commands/seat/idle.c b/sway/commands/seat/idle.c index 82428f2c9..62b94db21 100644 --- a/sway/commands/seat/idle.c +++ b/sway/commands/seat/idle.c @@ -3,6 +3,7 @@ #include #include #include +#include "log.h" #include "sway/commands.h" #include "sway/config.h" #include "sway/input/seat.h" @@ -69,5 +70,10 @@ struct cmd_results *seat_cmd_idle_wake(int argc, char **argv) { return cmd_results_new(CMD_FAILURE, "Invalid idle source"); } config->handler_context.seat_config->idle_wake_sources = sources; + sway_log(SWAY_INFO, "Warning: seat idle_wake is deprecated"); + if (config->reading) { + config_add_swaynag_warning("seat idle_wake is deprecated. " + "Only seat idle_inhibit is supported."); + } return cmd_results_new(CMD_SUCCESS, NULL); } diff --git a/sway/input/seat.c b/sway/input/seat.c index 82f4eb5f0..a84e4d52f 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -100,22 +100,11 @@ void seat_destroy(struct sway_seat *seat) { void seat_idle_notify_activity(struct sway_seat *seat, enum sway_input_idle_source source) { - uint32_t mask = seat->idle_inhibit_sources; - struct wlr_idle_timeout *timeout; - int ntimers = 0, nidle = 0; - wl_list_for_each(timeout, &server.idle->idle_timers, link) { - ++ntimers; - if (timeout->idle_state) { - ++nidle; - } - } - if (nidle == ntimers) { - mask = seat->idle_wake_sources; - } - if ((source & mask) > 0) { - wlr_idle_notify_activity(server.idle, seat->wlr_seat); - wlr_idle_notifier_v1_notify_activity(server.idle_notifier_v1, seat->wlr_seat); + if ((source & seat->idle_inhibit_sources) == 0) { + return; } + wlr_idle_notify_activity(server.idle, seat->wlr_seat); + wlr_idle_notifier_v1_notify_activity(server.idle_notifier_v1, seat->wlr_seat); } /** diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index 082b68c23..8a1f27001 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd @@ -268,12 +268,6 @@ correct seat. "keyboard", "pointer", "touchpad", "touch", "tablet_pad", "tablet_tool", and "switch". The default behavior is to prevent idle on any event. -*seat* idle_wake - Sets the set of input event sources which can wake the seat from - its idle state, as a space separated list of source names. Valid names are - "keyboard", "pointer", "touchpad", "touch", "tablet_pad", "tablet_tool", - and "switch". The default behavior is to wake from idle on any event. - *seat* keyboard_grouping none|smart Set how the keyboards in the seat are grouped together. Currently, there are two options. _none_ will disable all keyboard grouping. This will make From c3e6390073167bae8245d7fac9b455f9f06a5333 Mon Sep 17 00:00:00 2001 From: Nick Kipshidze <96648005+NickKipshidze@users.noreply.github.com> Date: Wed, 19 Jul 2023 21:26:53 +0400 Subject: [PATCH 061/114] Add Georgian README I am a native Georgian speaker. I have translated sway's README.md --- README.ge.md | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 3 ++- 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 README.ge.md diff --git a/README.ge.md b/README.ge.md new file mode 100644 index 000000000..ef4f67620 --- /dev/null +++ b/README.ge.md @@ -0,0 +1,67 @@ +# sway + +sway არის [i3]-თავსებადი [Wayland]-ის კომპოზიტორი. მეტი ინფორმაციისთვის იხილეთ +[FAQ]. დაუკავშირდით [IRC არხს][IRC channel] \(#sway irc.libera.chat-ზე). + +## გამოშვების ხელმოწერები + +გამოშვებები ხელმოწერილია [E88F5E48]-ით და გამოქვეყნებულია [GitHub-ზე][GitHub releases]. + +## ინსტალაცია + +### რეპოზიტორიიდან + +Sway არის ხელმისაწვდომი ბევრი დისტრიბუტაციისთვის. ცადეთ "sway" პაკეტის ინსტალაცია თქვენთვის. + +### კოდის კომპილაცია + +იხილეთ [ეს ვიკი გვერდი][Development setup] თუ გინდათ რომ ააწყოთ sway და wlroots სატესტოდ ან დეველოპმენტისთვის. + +დააინსტალირეთ დამოკიდებულებები: + +* meson \* +* [wlroots] +* wayland +* wayland-protocols \* +* pcre2 +* json-c +* pango +* cairo +* gdk-pixbuf2 (ასევე არჩევითია: system tray) +* [scdoc] (ასევე არჩევითია: man pages) \* +* git (ასევე არჩევითია: version info) \* + +_\* Compile-time dep_ + +გაუშვით ეს ბრძანებები: + + meson build/ + ninja -C build/ + sudo ninja -C build/ install + +სისტემებზე logind და seatd-ის გარეშე, გჭირდება suid გაუშვა sway binary-ზე: + + sudo chmod a+s /usr/local/bin/sway + +Sway შეწყვეტს root ნებართვებს მალევე ჩართვის შემდეგ. + +## კონფიგურაცია + +თუ უკვე იყენებთ i3-ს, მაშინ დააკოპირე i3 კონფიგურაცია და ჩასვი `~/.config/sway/config` +და უპრობლემოდ იმუშავებს პირდაპირ. წინააღმდეგ შემთხვევაში კონფიგურაციის ნიმუში ჩააკოპირეთ აქ: `~/.config/sway/config`. კომპიგურაციის ნიმუში ხშირ შემთხვევაში არის `/etc/sway/config`. +გაუშვი `man 5 sway` კონპიგურაციაზე ინფორმაციის მისაღებად. + +## გაშვება + +გაუშვი `sway` TTY-ისთვის. ზოგიერთმა ლოგინ მენეჯერმა შეიძლება იმუშავოს, მაგრამ არ +არის მხარდაჭერილი sway-სგან (როგორც წესი კარგად მუშაობს gdm). + +[i3]: https://i3wm.org/ +[Wayland]: http://wayland.freedesktop.org/ +[FAQ]: https://github.com/swaywm/sway/wiki +[IRC channel]: https://web.libera.chat/gamja/?channels=#sway +[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 +[GitHub releases]: https://github.com/swaywm/sway/releases +[Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup +[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots +[scdoc]: https://git.sr.ht/~sircmpwn/scdoc diff --git a/README.md b/README.md index e19169c6b..b3a518111 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # sway -**[English][en]** - [Česky][cs] - [Deutsch][de] - [Dansk][dk] - [Español][es] - [Français][fr] - [Ελληνικά][gr] - [हिन्दी][hi] - [Magyar][hu] - [فارسی][ir] - [Italiano][it] - [日本語][ja] - [한국어][ko] - [Nederlands][nl] - [Norsk][no] - [Polski][pl] - [Português][pt] - [Română][ro] - [Русский][ru] - [Svenska][sv] - [Türkçe][tr] - [Українська][uk] - [中文-简体][zh-CN] - [中文-繁體][zh-TW] +**[English][en]** - [Česky][cs] - [Deutsch][de] - [Dansk][dk] - [Español][es] - [Français][fr] - [ქართული][ge] - [Ελληνικά][gr] - [हिन्दी][hi] - [Magyar][hu] - [فارسی][ir] - [Italiano][it] - [日本語][ja] - [한국어][ko] - [Nederlands][nl] - [Norsk][no] - [Polski][pl] - [Português][pt] - [Română][ro] - [Русский][ru] - [Svenska][sv] - [Türkçe][tr] - [Українська][uk] - [中文-简体][zh-CN] - [中文-繁體][zh-TW] sway is an [i3]-compatible [Wayland] compositor. Read the [FAQ]. Join the [IRC channel] \(#sway on irc.libera.chat). @@ -67,6 +67,7 @@ sway (gdm is known to work fairly well). [dk]: README.dk.md [es]: README.es.md [fr]: README.fr.md +[ge]: README.ge.md [gr]: README.gr.md [hi]: README.hi.md [hu]: README.hu.md From dc634c4a1328668afe2b7c74e8b5828e187ebddd Mon Sep 17 00:00:00 2001 From: bretello Date: Mon, 17 Jul 2023 19:31:53 +0200 Subject: [PATCH 062/114] fix crash when resizing tiled scratchpad windows Splitting and then hiding a scratchpad container results in a segfault. fixes #6693 --- sway/commands/resize.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sway/commands/resize.c b/sway/commands/resize.c index f59e2aeb2..32b746eaf 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c @@ -75,6 +75,10 @@ void container_resize_tiled(struct sway_container *con, return; } + if (container_is_scratchpad_hidden_or_child(con)) { + return; + } + // For HORIZONTAL or VERTICAL, we are growing in two directions so select // both adjacent siblings. For RIGHT or DOWN, just select the next sibling. // For LEFT or UP, convert it to a RIGHT or DOWN resize and reassign con to @@ -249,6 +253,10 @@ static struct cmd_results *resize_adjust_tiled(uint32_t axis, struct movement_amount *amount) { struct sway_container *current = config->handler_context.container; + if (container_is_scratchpad_hidden_or_child(current)) { + return cmd_results_new(CMD_FAILURE, "Cannot resize a hidden scratchpad container"); + } + if (amount->unit == MOVEMENT_UNIT_DEFAULT) { amount->unit = MOVEMENT_UNIT_PPT; } @@ -292,6 +300,11 @@ static struct cmd_results *resize_adjust_tiled(uint32_t axis, */ static struct cmd_results *resize_set_tiled(struct sway_container *con, struct movement_amount *width, struct movement_amount *height) { + + if (container_is_scratchpad_hidden_or_child(con)) { + return cmd_results_new(CMD_FAILURE, "Cannot resize a hidden scratchpad container"); + } + if (width->amount) { if (width->unit == MOVEMENT_UNIT_PPT || width->unit == MOVEMENT_UNIT_DEFAULT) { From 6bd11ad0dfb11f8cf7e0ab5330cd2488851c5614 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 5 May 2023 16:34:35 +0200 Subject: [PATCH 063/114] Add support for cursor-shape-v1 References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4106 --- include/sway/input/cursor.h | 2 ++ include/sway/server.h | 2 ++ protocols/meson.build | 1 + sway/input/cursor.c | 24 ++++++++++++++++++++++++ sway/server.c | 7 +++++++ 5 files changed, 36 insertions(+) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 1636588a4..1e21c66fe 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -145,4 +145,6 @@ uint32_t get_mouse_button(const char *name, char **error); const char *get_mouse_button_name(uint32_t button); +void handle_request_set_cursor_shape(struct wl_listener *listener, void *data); + #endif diff --git a/include/sway/server.h b/include/sway/server.h index 0e4ec2be3..1eb308a4f 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -120,6 +120,8 @@ struct sway_server { struct wl_listener xdg_activation_v1_request_activate; struct wl_listener xdg_activation_v1_new_token; + struct wl_listener request_set_cursor_shape; + struct wl_list pending_launcher_ctxs; // launcher_ctx::link // The timeout for transactions, after which a transaction is applied diff --git a/protocols/meson.build b/protocols/meson.build index e6fdec7db..b6fdec8cc 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -13,6 +13,7 @@ protocols = [ wl_protocol_dir / 'unstable/tablet/tablet-unstable-v2.xml', wl_protocol_dir / 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml', wl_protocol_dir / 'staging/content-type/content-type-v1.xml', + wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml', 'wlr-layer-shell-unstable-v1.xml', 'idle.xml', 'wlr-input-inhibitor-unstable-v1.xml', diff --git a/sway/input/cursor.c b/sway/input/cursor.c index f970e6a21..62c74d040 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -1467,3 +1468,26 @@ void sway_cursor_constrain(struct sway_cursor *cursor, wl_signal_add(&constraint->surface->events.commit, &cursor->constraint_commit); } + +void handle_request_set_cursor_shape(struct wl_listener *listener, void *data) { + const struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data; + struct sway_seat *seat = event->seat_client->seat->data; + + if (!seatop_allows_set_cursor(seat)) { + return; + } + + struct wl_client *focused_client = NULL; + struct wlr_surface *focused_surface = seat->wlr_seat->pointer_state.focused_surface; + if (focused_surface != NULL) { + focused_client = wl_resource_get_client(focused_surface->resource); + } + + // TODO: check cursor mode + if (focused_client == NULL || event->seat_client->client != focused_client) { + sway_log(SWAY_DEBUG, "denying request to set cursor from unfocused client"); + return; + } + + cursor_set_image(seat->cursor, wlr_cursor_shape_v1_name(event->shape), focused_client); +} diff --git a/sway/server.c b/sway/server.c index 3a11088a7..50f0a7029 100644 --- a/sway/server.c +++ b/sway/server.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,7 @@ #include "sway/input/input-manager.h" #include "sway/output.h" #include "sway/server.h" +#include "sway/input/cursor.h" #include "sway/tree/root.h" #if HAVE_XWAYLAND @@ -235,6 +237,11 @@ bool server_init(struct sway_server *server) { wl_signal_add(&server->xdg_activation_v1->events.new_token, &server->xdg_activation_v1_new_token); + struct wlr_cursor_shape_manager_v1 *cursor_shape_manager = + wlr_cursor_shape_manager_v1_create(server->wl_display, 1); + server->request_set_cursor_shape.notify = handle_request_set_cursor_shape; + wl_signal_add(&cursor_shape_manager->events.request_set_shape, &server->request_set_cursor_shape); + wl_list_init(&server->pending_launcher_ctxs); // Avoid using "wayland-0" as display socket From f436de920097963a6c73e250ea4a01b89be31321 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sun, 30 Jul 2023 16:07:28 -0400 Subject: [PATCH 064/114] swaybar: Implement wp_cursor_shape_v1 --- include/swaybar/bar.h | 2 ++ swaybar/bar.c | 21 +++++++++++++-------- swaybar/input.c | 15 +++++++++++++-- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 3ad0bdf3c..197d21901 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -4,6 +4,7 @@ #include "config.h" #include "input.h" #include "pool-buffer.h" +#include "cursor-shape-v1-client-protocol.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" #include "xdg-output-unstable-v1-client-protocol.h" @@ -30,6 +31,7 @@ struct swaybar { struct wl_compositor *compositor; struct zwlr_layer_shell_v1 *layer_shell; struct zxdg_output_manager_v1 *xdg_output_manager; + struct wp_cursor_shape_manager_v1 *cursor_shape_manager; struct wl_shm *shm; struct swaybar_config *config; diff --git a/swaybar/bar.c b/swaybar/bar.c index 5e4ebd97c..021fc3bdb 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -362,6 +362,9 @@ static void handle_global(void *data, struct wl_registry *registry, } else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) { bar->xdg_output_manager = wl_registry_bind(registry, name, &zxdg_output_manager_v1_interface, 2); + } else if (strcmp(interface, wp_cursor_shape_manager_v1_interface.name) == 0) { + bar->cursor_shape_manager = wl_registry_bind(registry, name, + &wp_cursor_shape_manager_v1_interface, 1); } } @@ -425,15 +428,17 @@ bool bar_setup(struct swaybar *bar, const char *socket_path) { // Second roundtrip for xdg-output wl_display_roundtrip(bar->display); - struct swaybar_seat *seat; - wl_list_for_each(seat, &bar->seats, link) { - struct swaybar_pointer *pointer = &seat->pointer; - if (!pointer) { - continue; + if (!bar->cursor_shape_manager) { + struct swaybar_seat *seat; + wl_list_for_each(seat, &bar->seats, link) { + struct swaybar_pointer *pointer = &seat->pointer; + if (!pointer) { + continue; + } + pointer->cursor_surface = + wl_compositor_create_surface(bar->compositor); + assert(pointer->cursor_surface); } - pointer->cursor_surface = - wl_compositor_create_surface(bar->compositor); - assert(pointer->cursor_surface); } if (bar->config->status_command) { diff --git a/swaybar/input.c b/swaybar/input.c index 1e6ace008..ada4bc862 100644 --- a/swaybar/input.c +++ b/swaybar/input.c @@ -111,7 +111,7 @@ static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, struct swaybar_pointer *pointer = &seat->pointer; seat->pointer.x = wl_fixed_to_double(surface_x); seat->pointer.y = wl_fixed_to_double(surface_y); - pointer->serial = serial; + struct swaybar_output *output; wl_list_for_each(output, &seat->bar->outputs, link) { if (output->surface == surface) { @@ -119,7 +119,18 @@ static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, break; } } - update_cursor(seat); + + if (seat->bar->cursor_shape_manager) { + struct wp_cursor_shape_device_v1 *device = + wp_cursor_shape_manager_v1_get_pointer( + seat->bar->cursor_shape_manager, wl_pointer); + wp_cursor_shape_device_v1_set_shape(device, serial, + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT); + wp_cursor_shape_device_v1_destroy(device); + } else { + pointer->serial = serial; + update_cursor(seat); + } } static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, From df8aad9c5ab70ad646ec1742cc57473c6908a1be Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 29 Jul 2023 16:17:48 -0400 Subject: [PATCH 065/114] swaynag: Implement wp_cursor_shape_v1 --- include/swaynag/swaynag.h | 3 +++ swaynag/swaynag.c | 25 ++++++++++++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/include/swaynag/swaynag.h b/include/swaynag/swaynag.h index ccd313a02..fb9e9c218 100644 --- a/include/swaynag/swaynag.h +++ b/include/swaynag/swaynag.h @@ -4,6 +4,8 @@ #include #include "list.h" #include "pool-buffer.h" +#include "cursor-shape-v1-client-protocol.h" + #include "swaynag/types.h" #define SWAYNAG_MAX_HEIGHT 500 @@ -85,6 +87,7 @@ struct swaynag { struct swaynag_output *output; struct zwlr_layer_shell_v1 *layer_shell; struct zwlr_layer_surface_v1 *layer_surface; + struct wp_cursor_shape_manager_v1 *cursor_shape_manager; struct wl_surface *surface; uint32_t width; diff --git a/swaynag/swaynag.c b/swaynag/swaynag.c index b45485f79..6ea739e30 100644 --- a/swaynag/swaynag.c +++ b/swaynag/swaynag.c @@ -157,8 +157,7 @@ static void update_cursor(struct swaynag_seat *seat) { sway_log(SWAY_ERROR, "Failed to load cursor theme"); return; } - struct wl_cursor *cursor = - wl_cursor_theme_get_cursor(pointer->cursor_theme, "default"); + struct wl_cursor *cursor = wl_cursor_theme_get_cursor(pointer->cursor_theme, "default"); if (!cursor) { sway_log(SWAY_ERROR, "Failed to get default cursor from theme"); return; @@ -190,11 +189,22 @@ static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { struct swaynag_seat *seat = data; + struct swaynag_pointer *pointer = &seat->pointer; pointer->x = wl_fixed_to_int(surface_x); pointer->y = wl_fixed_to_int(surface_y); - pointer->serial = serial; - update_cursor(seat); + + if (seat->swaynag->cursor_shape_manager) { + struct wp_cursor_shape_device_v1 *device = + wp_cursor_shape_manager_v1_get_pointer( + seat->swaynag->cursor_shape_manager, wl_pointer); + wp_cursor_shape_device_v1_set_shape(device, serial, + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT); + wp_cursor_shape_device_v1_destroy(device); + } else { + pointer->serial = serial; + update_cursor(seat); + } } static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, @@ -386,6 +396,9 @@ static void handle_global(void *data, struct wl_registry *registry, } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { swaynag->layer_shell = wl_registry_bind( registry, name, &zwlr_layer_shell_v1_interface, 1); + } else if (strcmp(interface, wp_cursor_shape_manager_v1_interface.name) == 0) { + swaynag->cursor_shape_manager = wl_registry_bind( + registry, name, &wp_cursor_shape_manager_v1_interface, 1); } } @@ -464,7 +477,9 @@ void swaynag_setup(struct swaynag *swaynag) { exit(EXIT_FAILURE); } - swaynag_setup_cursors(swaynag); + if (!swaynag->cursor_shape_manager) { + swaynag_setup_cursors(swaynag); + } swaynag->surface = wl_compositor_create_surface(swaynag->compositor); assert(swaynag->surface); From d557b6876b53763d2e9e97c05ec4754f4e9aa984 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 31 Jul 2023 10:04:52 +0200 Subject: [PATCH 066/114] desktop/output: drop logic to handle backend-applied mode The wlroots backends no longer magically apply output modes behind the compositor's back. --- sway/desktop/output.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index f6ff90ef4..b5993d23d 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -927,19 +927,6 @@ static void handle_destroy(struct wl_listener *listener, void *data) { } static void handle_mode(struct sway_output *output) { - if (!output->enabled && !output->enabling) { - struct output_config *oc = find_output_config(output); - if (output->wlr_output->current_mode != NULL && - (!oc || oc->enabled)) { - // We want to enable this output, but it didn't work last time, - // possibly because we hadn't enough CRTCs. Try again now that the - // output has a mode. - sway_log(SWAY_DEBUG, "Output %s has gained a CRTC, " - "trying to enable it", output->wlr_output->name); - apply_output_config(oc, output); - } - return; - } if (!output->enabled) { return; } From d3626efe5ef96f056f72f320a6487947ff22f8d9 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 31 Jul 2023 10:07:17 +0200 Subject: [PATCH 067/114] desktop/output: drop handle_mode() We already perform the exact same logic on transform/scale change. --- sway/desktop/output.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index b5993d23d..f052e6f42 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -926,18 +926,6 @@ static void handle_destroy(struct wl_listener *listener, void *data) { update_output_manager_config(server); } -static void handle_mode(struct sway_output *output) { - if (!output->enabled) { - return; - } - - arrange_layers(output); - arrange_output(output); - transaction_commit_dirty(); - - update_output_manager_config(output->server); -} - static void update_textures(struct sway_container *con, void *data) { container_update_title_textures(con); container_update_marks_textures(con); @@ -953,10 +941,6 @@ static void handle_commit(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, commit); struct wlr_output_event_commit *event = data; - if (event->committed & WLR_OUTPUT_STATE_MODE) { - handle_mode(output); - } - if (!output->enabled) { return; } @@ -966,7 +950,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { output_for_each_surface(output, update_output_scale_iterator, NULL); } - if (event->committed & (WLR_OUTPUT_STATE_TRANSFORM | WLR_OUTPUT_STATE_SCALE)) { + if (event->committed & (WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_TRANSFORM | WLR_OUTPUT_STATE_SCALE)) { arrange_layers(output); arrange_output(output); transaction_commit_dirty(); From 170598d71b59b6cae767e20679369ac3250ef2e9 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 31 Jul 2023 10:09:40 +0200 Subject: [PATCH 068/114] desktop/output: fix output manager enabled state With recent wlroots changes, backends which don't support output modes can now support being disabled. We were always marking mode-less outputs as disabled. Stop doing that, check whether the output takes up some space in the layout instead. --- sway/desktop/output.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index f052e6f42..aed1fdeb0 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -883,12 +883,9 @@ static void update_output_manager_config(struct sway_server *server) { wlr_output_layout_get_box(root->output_layout, output->wlr_output, &output_box); // We mark the output enabled when it's switched off but not disabled - config_head->state.enabled = output->current_mode != NULL && output->enabled; - config_head->state.mode = output->current_mode; - if (!wlr_box_empty(&output_box)) { - config_head->state.x = output_box.x; - config_head->state.y = output_box.y; - } + config_head->state.enabled = !wlr_box_empty(&output_box); + config_head->state.x = output_box.x; + config_head->state.y = output_box.y; } wlr_output_manager_v1_set_configuration(server->output_manager_v1, config); From f8ddd97e0e5a72392e3dda34d03ef11c036d0234 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 31 Jul 2023 10:19:52 +0200 Subject: [PATCH 069/114] output: drop current_mode This is now unused. --- include/sway/output.h | 2 -- sway/config/output.c | 4 ---- sway/tree/output.c | 1 - 3 files changed, 7 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index 50d90d25d..62d866bc2 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -33,8 +33,6 @@ struct sway_output { int width, height; // transformed buffer size enum wl_output_subpixel detected_subpixel; enum scale_filter_mode scale_filter; - // last applied mode when the output is powered off - struct wlr_output_mode *current_mode; bool enabling, enabled; list_t *workspaces; diff --git a/sway/config/output.c b/sway/config/output.c index 6fb29ded9..0985b0e8a 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -510,10 +510,6 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) { struct wlr_output_state pending = {0}; queue_output_config(oc, output, &pending); - if (!oc || oc->power != 0) { - output->current_mode = pending.mode; - } - sway_log(SWAY_DEBUG, "Committing output %s", wlr_output->name); if (!wlr_output_commit_state(wlr_output, &pending)) { // Failed to commit output changes, maybe the output is missing a CRTC. diff --git a/sway/tree/output.c b/sway/tree/output.c index eccab2f72..0960f4135 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -271,7 +271,6 @@ void output_disable(struct sway_output *output) { list_del(root->outputs, index); output->enabled = false; - output->current_mode = NULL; arrange_root(); From eebbecc7801ea520dd5644b08e884fbe27c2eeda Mon Sep 17 00:00:00 2001 From: ookami Date: Sat, 29 Jul 2023 01:16:37 +0800 Subject: [PATCH 070/114] Rebase all cursors in handle_surface_map Fix swaylock showing transient cursor after locked. --- sway/lock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/lock.c b/sway/lock.c index 534561720..70ac39691 100644 --- a/sway/lock.c +++ b/sway/lock.c @@ -1,6 +1,7 @@ #define _POSIX_C_SOURCE 200809L #include #include "log.h" +#include "sway/input/cursor.h" #include "sway/input/keyboard.h" #include "sway/input/seat.h" #include "sway/output.h" @@ -32,6 +33,7 @@ static void handle_surface_map(struct wl_listener *listener, void *data) { if (server.session_lock.focused == NULL) { set_lock_focused_surface(surf->surface); } + cursor_rebase_all(); surface_enter_output(surf->surface, surf->output); output_damage_whole(surf->output); } From bb91b7f5fa7fddb582b8dddf208cc335d39da9e7 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 14 Apr 2023 19:04:51 +0200 Subject: [PATCH 071/114] Move contrib/ to separate repository User-contributed scripts are being moved over to this repository: https://github.com/OctopusET/sway-contrib --- contrib/autoname-workspaces.py | 124 ----------------- contrib/grimshot | 168 ----------------------- contrib/grimshot.1 | 109 --------------- contrib/grimshot.1.scd | 80 ----------- contrib/inactive-windows-transparency.py | 69 ---------- 5 files changed, 550 deletions(-) delete mode 100755 contrib/autoname-workspaces.py delete mode 100755 contrib/grimshot delete mode 100644 contrib/grimshot.1 delete mode 100644 contrib/grimshot.1.scd delete mode 100755 contrib/inactive-windows-transparency.py diff --git a/contrib/autoname-workspaces.py b/contrib/autoname-workspaces.py deleted file mode 100755 index 3ec399280..000000000 --- a/contrib/autoname-workspaces.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/python - -# This script requires i3ipc-python package (install it from a system package manager -# or pip). -# It adds icons to the workspace name for each open window. -# Set your keybindings like this: set $workspace1 workspace number 1 -# Add your icons to WINDOW_ICONS. -# Based on https://github.com/maximbaz/dotfiles/blob/master/bin/i3-autoname-workspaces - -import argparse -import i3ipc -import logging -import re -import signal -import sys - -WINDOW_ICONS = { - "firefox": "", -} - -DEFAULT_ICON = "󰀏" - - -def icon_for_window(window): - name = None - if window.app_id is not None and len(window.app_id) > 0: - name = window.app_id.lower() - elif window.window_class is not None and len(window.window_class) > 0: - name = window.window_class.lower() - - if name in WINDOW_ICONS: - return WINDOW_ICONS[name] - - logging.info("No icon available for window with name: %s" % str(name)) - return DEFAULT_ICON - -def rename_workspaces(ipc): - for workspace in ipc.get_tree().workspaces(): - name_parts = parse_workspace_name(workspace.name) - icon_tuple = () - for w in workspace: - if w.app_id is not None or w.window_class is not None: - icon = icon_for_window(w) - if not ARGUMENTS.duplicates and icon in icon_tuple: - continue - icon_tuple += (icon,) - name_parts["icons"] = " ".join(icon_tuple) + " " - new_name = construct_workspace_name(name_parts) - ipc.command('rename workspace "%s" to "%s"' % (workspace.name, new_name)) - - -def undo_window_renaming(ipc): - for workspace in ipc.get_tree().workspaces(): - name_parts = parse_workspace_name(workspace.name) - name_parts["icons"] = None - new_name = construct_workspace_name(name_parts) - ipc.command('rename workspace "%s" to "%s"' % (workspace.name, new_name)) - ipc.main_quit() - sys.exit(0) - - -def parse_workspace_name(name): - return re.match( - "(?P[0-9]+):?(?P\w+)? ?(?P.+)?", name - ).groupdict() - - -def construct_workspace_name(parts): - new_name = str(parts["num"]) - if parts["shortname"] or parts["icons"]: - new_name += ":" - - if parts["shortname"]: - new_name += parts["shortname"] - - if parts["icons"]: - new_name += " " + parts["icons"] - - return new_name - - -if __name__ == "__main__": - parser = argparse.ArgumentParser( - description="This script automatically changes the workspace name in sway depending on your open applications." - ) - parser.add_argument( - "--duplicates", - "-d", - action="store_true", - help="Set it when you want an icon for each instance of the same application per workspace.", - ) - parser.add_argument( - "--logfile", - "-l", - type=str, - default="/tmp/sway-autoname-workspaces.log", - help="Path for the logfile.", - ) - args = parser.parse_args() - global ARGUMENTS - ARGUMENTS = args - - logging.basicConfig( - level=logging.INFO, - filename=ARGUMENTS.logfile, - filemode="w", - format="%(message)s", - ) - - ipc = i3ipc.Connection() - - for sig in [signal.SIGINT, signal.SIGTERM]: - signal.signal(sig, lambda signal, frame: undo_window_renaming(ipc)) - - def window_event_handler(ipc, e): - if e.change in ["new", "close", "move"]: - rename_workspaces(ipc) - - ipc.on("window", window_event_handler) - - rename_workspaces(ipc) - - ipc.main() - diff --git a/contrib/grimshot b/contrib/grimshot deleted file mode 100755 index 1ec19def6..000000000 --- a/contrib/grimshot +++ /dev/null @@ -1,168 +0,0 @@ -#!/bin/sh - -## Grimshot: a helper for screenshots within sway -## Requirements: -## - `grim`: screenshot utility for wayland -## - `slurp`: to select an area -## - `swaymsg`: to read properties of current window -## - `wl-copy`: clipboard utility -## - `jq`: json utility to parse swaymsg output -## - `notify-send`: to show notifications -## Those are needed to be installed, if unsure, run `grimshot check` -## -## See `man 1 grimshot` or `grimshot usage` for further details. - -getTargetDirectory() { - test -f "${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs" && \ - . "${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs" - - echo "${XDG_SCREENSHOTS_DIR:-${XDG_PICTURES_DIR:-$HOME}}" -} - -NOTIFY=no -CURSOR= - -while [ $# -gt 0 ]; do - key="$1" - - case $key in - -n|--notify) - NOTIFY=yes - shift # past argument - ;; - -c|--cursor) - CURSOR=yes - shift # past argument - ;; - *) # unknown option - break # done with parsing --flags - ;; - esac -done - -ACTION=${1:-usage} -SUBJECT=${2:-screen} -FILE=${3:-$(getTargetDirectory)/$(date -Ins).png} - -if [ "$ACTION" != "save" ] && [ "$ACTION" != "copy" ] && [ "$ACTION" != "check" ]; then - echo "Usage:" - echo " grimshot [--notify] [--cursor] (copy|save) [active|screen|output|area|window] [FILE|-]" - echo " grimshot check" - echo " grimshot usage" - echo "" - echo "Commands:" - echo " copy: Copy the screenshot data into the clipboard." - echo " save: Save the screenshot to a regular file or '-' to pipe to STDOUT." - echo " check: Verify if required tools are installed and exit." - echo " usage: Show this message and exit." - echo "" - echo "Targets:" - echo " active: Currently active window." - echo " screen: All visible outputs." - echo " output: Currently active output." - echo " area: Manually select a region." - echo " window: Manually select a window." - exit -fi - -notify() { - notify-send -t 3000 -a grimshot "$@" -} -notifyOk() { - [ "$NOTIFY" = "no" ] && return - - TITLE=${2:-"Screenshot"} - MESSAGE=${1:-"OK"} - notify "$TITLE" "$MESSAGE" -} -notifyError() { - if [ $NOTIFY = "yes" ]; then - TITLE=${2:-"Screenshot"} - MESSAGE=${1:-"Error taking screenshot with grim"} - notify -u critical "$TITLE" "$MESSAGE" - else - echo "$1" - fi -} - -die() { - MSG=${1:-Bye} - notifyError "Error: $MSG" - exit 2 -} - -check() { - COMMAND=$1 - if command -v "$COMMAND" > /dev/null 2>&1; then - RESULT="OK" - else - RESULT="NOT FOUND" - fi - echo " $COMMAND: $RESULT" -} - -takeScreenshot() { - FILE=$1 - GEOM=$2 - OUTPUT=$3 - if [ -n "$OUTPUT" ]; then - grim ${CURSOR:+-c} -o "$OUTPUT" "$FILE" || die "Unable to invoke grim" - elif [ -z "$GEOM" ]; then - grim ${CURSOR:+-c} "$FILE" || die "Unable to invoke grim" - else - grim ${CURSOR:+-c} -g "$GEOM" "$FILE" || die "Unable to invoke grim" - fi -} - -if [ "$ACTION" = "check" ] ; then - echo "Checking if required tools are installed. If something is missing, install it to your system and make it available in PATH..." - check grim - check slurp - check swaymsg - check wl-copy - check jq - check notify-send - exit -elif [ "$SUBJECT" = "area" ] ; then - GEOM=$(slurp -d) - # Check if user exited slurp without selecting the area - if [ -z "$GEOM" ]; then - exit 1 - fi - WHAT="Area" -elif [ "$SUBJECT" = "active" ] ; then - FOCUSED=$(swaymsg -t get_tree | jq -r 'recurse(.nodes[]?, .floating_nodes[]?) | select(.focused)') - GEOM=$(echo "$FOCUSED" | jq -r '.rect | "\(.x),\(.y) \(.width)x\(.height)"') - APP_ID=$(echo "$FOCUSED" | jq -r '.app_id') - WHAT="$APP_ID window" -elif [ "$SUBJECT" = "screen" ] ; then - GEOM="" - WHAT="Screen" -elif [ "$SUBJECT" = "output" ] ; then - GEOM="" - OUTPUT=$(swaymsg -t get_outputs | jq -r '.[] | select(.focused)' | jq -r '.name') - WHAT="$OUTPUT" -elif [ "$SUBJECT" = "window" ] ; then - GEOM=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | .rect | "\(.x),\(.y) \(.width)x\(.height)"' | slurp) - # Check if user exited slurp without selecting the area - if [ -z "$GEOM" ]; then - exit 1 - fi - WHAT="Window" -else - die "Unknown subject to take a screen shot from" "$SUBJECT" -fi - -if [ "$ACTION" = "copy" ] ; then - takeScreenshot - "$GEOM" "$OUTPUT" | wl-copy --type image/png || die "Clipboard error" - notifyOk "$WHAT copied to buffer" -else - if takeScreenshot "$FILE" "$GEOM" "$OUTPUT"; then - TITLE="Screenshot of $SUBJECT" - MESSAGE=$(basename "$FILE") - notifyOk "$MESSAGE" "$TITLE" - echo "$FILE" - else - notifyError "Error taking screenshot with grim" - fi -fi diff --git a/contrib/grimshot.1 b/contrib/grimshot.1 deleted file mode 100644 index 2c4c6a958..000000000 --- a/contrib/grimshot.1 +++ /dev/null @@ -1,109 +0,0 @@ -.\" Generated by scdoc 1.11.2 -.\" Complete documentation for this program is not available as a GNU info page -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.nh -.ad l -.\" Begin generated content: -.TH "grimshot" "1" "2022-03-31" -.P -.SH NAME -.P -grimshot - a helper for screenshots within sway -.P -.SH SYNOPSIS -.P -\fBgrimshot\fR [--notify] [--cursor] (copy|save) [TARGET] [FILE] -.br -\fBgrimshot\fR check -.br -\fBgrimshot\fR usage -.P -.SH OPTIONS -.P -\fB--notify\fR -.RS 4 -Show notifications to the user that a screenshot has been taken.\& -.P -.RE -\fB--cursor\fR -.RS 4 -Include cursors in the screenshot.\& -.P -.RE -\fBsave\fR -.RS 4 -Save the screenshot into a regular file.\& Grimshot will write images -files to \fBXDG_SCREENSHOTS_DIR\fR if this is set (or defined -in \fBuser-dirs.\&dir\fR), or otherwise fall back to \fBXDG_PICTURES_DIR\fR.\& -Set FILE to '\&-'\& to pipe the output to STDOUT.\& -.P -.RE -\fBcopy\fR -.RS 4 -Copy the screenshot data (as image/png) into the clipboard.\& -.P -.RE -.SH DESCRIPTION -.P -Grimshot is an easy-to-use screenshot utility for sway.\& It provides a -convenient interface over grim, slurp and jq, and supports storing the -screenshot either directly to the clipboard using wl-copy or to a file.\& -.P -.SH EXAMPLES -.P -An example usage pattern is to add these bindings to your sway config: -.P -.nf -.RS 4 -# Screenshots: -# Super+P: Current window -# Super+Shift+p: Select area -# Super+Alt+p Current output -# Super+Ctrl+p Select a window - -bindsym Mod4+p exec grimshot save active -bindsym Mod4+Shift+p exec grimshot save area -bindsym Mod4+Mod1+p exec grimshot save output -bindsym Mod4+Ctrl+p exec grimshot save window -.fi -.RE -.P -.SH TARGETS -.P -grimshot can capture the following named targets: -.P -\fIactive\fR -.RS 4 -Captures the currently active window.\& -.P -.RE -\fIscreen\fR -.RS 4 -Captures the entire screen.\& This includes all visible outputs.\& -.P -.RE -\fIarea\fR -.RS 4 -Allows manually selecting a rectangular region, and captures that.\& -.P -.RE -\fIwindow\fR -.RS 4 -Allows manually selecting a single window (by clicking on it), and -captures it.\& -.P -.RE -\fIoutput\fR -.RS 4 -Captures the currently active output.\& -.P -.RE -.SH OUTPUT -.P -Grimshot will print the filename of the captured screenshot to stdout if called -with the \fIsave\fR subcommand.\& -.P -.SH SEE ALSO -.P -\fBgrim\fR(1) diff --git a/contrib/grimshot.1.scd b/contrib/grimshot.1.scd deleted file mode 100644 index e356f99d9..000000000 --- a/contrib/grimshot.1.scd +++ /dev/null @@ -1,80 +0,0 @@ -grimshot(1) - -# NAME - -grimshot - a helper for screenshots within sway - -# SYNOPSIS - -*grimshot* [--notify] [--cursor] (copy|save) [TARGET] [FILE]++ -*grimshot* check++ -*grimshot* usage - -# OPTIONS - -*--notify* - Show notifications to the user that a screenshot has been taken. - -*--cursor* - Include cursors in the screenshot. - -*save* - Save the screenshot into a regular file. Grimshot will write image - files to *XDG_SCREENSHOTS_DIR* if this is set (or defined - in *user-dirs.dir*), or otherwise fall back to *XDG_PICTURES_DIR*. - Set FILE to '-' to pipe the output to STDOUT. - -*copy* - Copy the screenshot data (as image/png) into the clipboard. - -# DESCRIPTION - -Grimshot is an easy-to-use screenshot utility for sway. It provides a -convenient interface over grim, slurp and jq, and supports storing the -screenshot either directly to the clipboard using wl-copy or to a file. - -# EXAMPLES - -An example usage pattern is to add these bindings to your sway config: - -``` -# Screenshots: -# Super+P: Current window -# Super+Shift+p: Select area -# Super+Alt+p Current output -# Super+Ctrl+p Select a window - -bindsym Mod4+p exec grimshot save active -bindsym Mod4+Shift+p exec grimshot save area -bindsym Mod4+Mod1+p exec grimshot save output -bindsym Mod4+Ctrl+p exec grimshot save window -``` - -# TARGETS - -grimshot can capture the following named targets: - -_active_ - Captures the currently active window. - -_screen_ - Captures the entire screen. This includes all visible outputs. - -_area_ - Allows manually selecting a rectangular region, and captures that. - -_window_ - Allows manually selecting a single window (by clicking on it), and - captures it. - -_output_ - Captures the currently active output. - -# OUTPUT - -Grimshot will print the filename of the captured screenshot to stdout if called -with the _save_ subcommand. - -# SEE ALSO - -*grim*(1) diff --git a/contrib/inactive-windows-transparency.py b/contrib/inactive-windows-transparency.py deleted file mode 100755 index b81134dd4..000000000 --- a/contrib/inactive-windows-transparency.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/python - -# This script requires i3ipc-python package (install it from a system package manager -# or pip). -# It makes inactive windows transparent. Use `transparency_val` variable to control -# transparency strength in range of 0…1 or use the command line argument -o. - -import argparse -import i3ipc -import signal -import sys -from functools import partial - -def on_window_focus(inactive_opacity, ipc, event): - global prev_focused - global prev_workspace - - focused_workspace = ipc.get_tree().find_focused() - - if focused_workspace == None: - return - - focused = event.container - workspace = focused_workspace.workspace().num - - if focused.id != prev_focused.id: # https://github.com/swaywm/sway/issues/2859 - focused.command("opacity 1") - if workspace == prev_workspace: - prev_focused.command("opacity " + inactive_opacity) - prev_focused = focused - prev_workspace = workspace - - -def remove_opacity(ipc): - for workspace in ipc.get_tree().workspaces(): - for w in workspace: - w.command("opacity 1") - ipc.main_quit() - sys.exit(0) - - -if __name__ == "__main__": - transparency_val = "0.80" - - parser = argparse.ArgumentParser( - description="This script allows you to set the transparency of unfocused windows in sway." - ) - parser.add_argument( - "--opacity", - "-o", - type=str, - default=transparency_val, - help="set opacity value in range 0...1", - ) - args = parser.parse_args() - - ipc = i3ipc.Connection() - prev_focused = None - prev_workspace = ipc.get_tree().find_focused().workspace().num - - for window in ipc.get_tree(): - if window.focused: - prev_focused = window - else: - window.command("opacity " + args.opacity) - for sig in [signal.SIGINT, signal.SIGTERM]: - signal.signal(sig, lambda signal, frame: remove_opacity(ipc)) - ipc.on("window::focus", partial(on_window_focus, args.opacity)) - ipc.main() \ No newline at end of file From 363c57984d08ff54bbf31f567ffcd4addad98753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Sat, 19 Aug 2023 14:30:17 -0600 Subject: [PATCH 072/114] chase wlroots!4316 References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4316 --- sway/xdg_decoration.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/xdg_decoration.c b/sway/xdg_decoration.c index ec9e8d689..f7f5f5ed8 100644 --- a/sway/xdg_decoration.c +++ b/sway/xdg_decoration.c @@ -53,7 +53,7 @@ static void xdg_decoration_handle_request_mode(struct wl_listener *listener, void handle_xdg_decoration(struct wl_listener *listener, void *data) { struct wlr_xdg_toplevel_decoration_v1 *wlr_deco = data; - struct sway_xdg_shell_view *xdg_shell_view = wlr_deco->surface->data; + struct sway_xdg_shell_view *xdg_shell_view = wlr_deco->toplevel->base->data; struct sway_xdg_decoration *deco = calloc(1, sizeof(*deco)); if (deco == NULL) { @@ -79,7 +79,7 @@ struct sway_xdg_decoration *xdg_decoration_from_surface( struct wlr_surface *surface) { struct sway_xdg_decoration *deco; wl_list_for_each(deco, &server.xdg_decorations, link) { - if (deco->wlr_xdg_decoration->surface->surface == surface) { + if (deco->wlr_xdg_decoration->toplevel->base->surface == surface) { return deco; } } From a9086518219c0ace4a5d81c2f7219dae3b6aa20c Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Wed, 26 Jul 2023 20:32:33 +0300 Subject: [PATCH 073/114] chore: chase wlroots xdg-surface role rework --- sway/desktop/layer_shell.c | 10 +++++----- sway/input/cursor.c | 3 ++- sway/tree/container.c | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index d990d92af..8c6cedfe9 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -35,13 +35,13 @@ struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface( } // Layer surface popup - struct wlr_xdg_surface * xdg_popup = NULL; - if ((xdg_popup = wlr_xdg_surface_try_from_wlr_surface(surface)) && - xdg_popup->role == WLR_XDG_SURFACE_ROLE_POPUP) { - if (!xdg_popup->popup->parent) { + struct wlr_xdg_surface *xdg_surface = NULL; + if ((xdg_surface = wlr_xdg_surface_try_from_wlr_surface(surface)) && + xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP && xdg_surface->popup != NULL) { + if (!xdg_surface->popup->parent) { return NULL; } - surface = wlr_surface_get_root_surface(xdg_popup->popup->parent); + surface = wlr_surface_get_root_surface(xdg_surface->popup->parent); continue; } diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 62c74d040..44a5d6f7b 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -56,7 +56,8 @@ static struct wlr_surface *layer_surface_at(struct sway_output *output, static bool surface_is_xdg_popup(struct wlr_surface *surface) { struct wlr_xdg_surface *xdg_surface = wlr_xdg_surface_try_from_wlr_surface(surface); - return xdg_surface != NULL && xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP; + return xdg_surface != NULL && xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP && + xdg_surface->popup != NULL; } static struct wlr_surface *layer_surface_popup_at(struct sway_output *output, diff --git a/sway/tree/container.c b/sway/tree/container.c index d2c4ffc44..8c344a6d4 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -394,7 +394,7 @@ static bool surface_is_popup(struct wlr_surface *surface) { } struct wlr_xdg_surface *xdg_surface = wlr_xdg_surface_try_from_wlr_surface(surface); - return xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP; + return xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP && xdg_surface->popup != NULL; } struct sway_container *container_at(struct sway_workspace *workspace, From d84b3832f4616ee2a18f3ad4c0cd9cd996458d2c Mon Sep 17 00:00:00 2001 From: luzpaz Date: Wed, 23 Aug 2023 18:11:13 +0000 Subject: [PATCH 074/114] Fix typo --- include/sway/input/text_input.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sway/input/text_input.h b/include/sway/input/text_input.h index 4de96d449..214e61d12 100644 --- a/include/sway/input/text_input.h +++ b/include/sway/input/text_input.h @@ -8,7 +8,7 @@ /** * The relay structure manages the relationship between text-input and * input_method interfaces on a given seat. Multiple text-input interfaces may - * be bound to a relay, but at most one will be focused (reveiving events) at + * be bound to a relay, but at most one will be focused (receiving events) at * a time. At most one input-method interface may be bound to the seat. The * relay manages life cycle of both sides. When both sides are present and * focused, the relay passes messages between them. From 4a2210577c7c4f84a99ca03386b8910d2f419ab6 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 22 Jun 2023 16:26:00 +0200 Subject: [PATCH 075/114] Hide xwayland_shell_v1 from regular clients Regular clients are not allowed to use this interface. wlroots already sends a protocol error if a non-Xwayland client tries to use this interface, but let's remove all temptation by hiding it completely. --- sway/server.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sway/server.c b/sway/server.c index 50f0a7029..db873dcae 100644 --- a/sway/server.c +++ b/sway/server.c @@ -49,6 +49,7 @@ #include "sway/tree/root.h" #if HAVE_XWAYLAND +#include #include "sway/xwayland.h" #endif @@ -73,11 +74,25 @@ static void handle_drm_lease_request(struct wl_listener *listener, void *data) { } #endif +static bool filter_global(const struct wl_client *client, + const struct wl_global *global, void *data) { +#if HAVE_XWAYLAND + struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; + if (global == xwayland->shell_v1->global) { + return xwayland->server != NULL && client == xwayland->server->client; + } +#endif + + return true; +} + bool server_init(struct sway_server *server) { sway_log(SWAY_DEBUG, "Initializing Wayland server"); server->wl_display = wl_display_create(); server->wl_event_loop = wl_display_get_event_loop(server->wl_display); + wl_display_set_global_filter(server->wl_display, filter_global, NULL); + server->backend = wlr_backend_autocreate(server->wl_display, &server->session); if (!server->backend) { sway_log(SWAY_ERROR, "Unable to create backend"); From bf44690ee8ce8438ffb1a84fbe6e8dbb6a851c04 Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Sat, 15 Jul 2023 22:44:10 -0500 Subject: [PATCH 076/114] view: update wlr_toplevel size on client resizes If a floating client resizes itself, sway updates several of its internal dimensions to match but not wlr_toplevel. This means that the next time wlroots sends a toplevel configure event, it can have wrong coordinates that resize the client back to its old size. To fix this, let's just use wlr_xdg_toplevel_set_size so the wlr_toplevel has the same dimensions as sway. Fixes #5266. --- sway/tree/view.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sway/tree/view.c b/sway/tree/view.c index ec54fed81..8cc94a059 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -931,6 +931,11 @@ void view_update_size(struct sway_view *view) { con->pending.content_width = view->geometry.width; con->pending.content_height = view->geometry.height; container_set_geometry_from_content(con); + + // Update the next scheduled width/height so correct coordinates + // are sent on the next toplevel configure from wlroots. + wlr_xdg_toplevel_set_size(view->wlr_xdg_toplevel, view->geometry.width, + view->geometry.height); } void view_center_surface(struct sway_view *view) { From 60a94b491689632b89ccc1b83c321503ed434dac Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Mon, 28 Aug 2023 10:45:43 -0500 Subject: [PATCH 077/114] Revert "view: update wlr_toplevel size on client resizes" This isn't the right fix for this issue because the xwayland code also uses this function and updating the wlr_toplevel there doesn't make sense and also causes problems. Fixes #7722. This reverts commit bf44690ee8ce8438ffb1a84fbe6e8dbb6a851c04. --- sway/tree/view.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sway/tree/view.c b/sway/tree/view.c index 8cc94a059..ec54fed81 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -931,11 +931,6 @@ void view_update_size(struct sway_view *view) { con->pending.content_width = view->geometry.width; con->pending.content_height = view->geometry.height; container_set_geometry_from_content(con); - - // Update the next scheduled width/height so correct coordinates - // are sent on the next toplevel configure from wlroots. - wlr_xdg_toplevel_set_size(view->wlr_xdg_toplevel, view->geometry.width, - view->geometry.height); } void view_center_surface(struct sway_view *view) { From 3d5ae9813d390ea747462fc0026ee43b7c77d0f2 Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Mon, 28 Aug 2023 10:49:24 -0500 Subject: [PATCH 078/114] xdg_shell: update wlr_toplevel size on client resizes If a floating client resizes itself, sway updates several of its internal dimensions to match but not wlr_toplevel. This means that the next time wlroots sends a toplevel configure event, it can have wrong coordinates that resize the client back to its old size. To fix this, let's just use wlr_xdg_toplevel_set_size so the wlr_toplevel has the same dimensions as sway. Exactly the same as 0183b9d35d0ce750588e700e536b7d2e367b0d0a but the logic is onlly applied to xdg_shell and not xwayland. --- sway/desktop/xdg_shell.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 377a0f1c9..c2a985ee2 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -294,6 +294,8 @@ static void handle_commit(struct wl_listener *listener, void *data) { memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); if (container_is_floating(view->container)) { view_update_size(view); + wlr_xdg_toplevel_set_size(view->wlr_xdg_toplevel, view->geometry.width, + view->geometry.height); transaction_commit_dirty_client(); } else { view_center_surface(view); From 89f85312687b7fd1777c936e169e6400cee0a4b4 Mon Sep 17 00:00:00 2001 From: denppa <71837206+denppa@users.noreply.github.com> Date: Wed, 30 Aug 2023 10:57:25 -0400 Subject: [PATCH 079/114] build: fix build with wayland-scanner subproject --- protocols/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/meson.build b/protocols/meson.build index b6fdec8cc..2992ac585 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -2,7 +2,7 @@ wl_protocol_dir = wayland_protos.get_variable('pkgdatadir') wayland_scanner_dep = dependency('wayland-scanner', native: true) wayland_scanner = find_program( - wayland_scanner_dep.get_variable(pkgconfig: 'wayland_scanner'), + wayland_scanner_dep.get_variable('wayland_scanner'), native: true, ) From 3dd2f4a67fb2ac45f336f075779cc3bccec2aac3 Mon Sep 17 00:00:00 2001 From: iff <98851855+iffse@users.noreply.github.com> Date: Thu, 7 Sep 2023 03:31:35 +0200 Subject: [PATCH 080/114] commands/input/map_from_region: don't treat 0x prefix as hex identifier When using the `map_from_region` for pen tables, we will usually make the available area as big as possible while maintaining the proportions with the screen. As most of the tablets uses a 16:10 ratios while the most popular screen ratios is still 16:9, the argument for most people should be `0x0 1x0.9` to have the maximum effective area. However, the argument above won't work because the current code will treat `0x...` as a hexadecimal number, instead of setting both `x` and `y` to `0`. This fix allows the use of the following syntax: ``` input type:tablet_tool { map_from_region 0x0 1x0.9 } ``` --- sway/commands/input/map_from_region.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/sway/commands/input/map_from_region.c b/sway/commands/input/map_from_region.c index de00b7141..4400e111c 100644 --- a/sway/commands/input/map_from_region.c +++ b/sway/commands/input/map_from_region.c @@ -11,11 +11,21 @@ static bool parse_coords(const char *str, double *x, double *y, bool *mm) { *mm = false; char *end; - *x = strtod(str, &end); - if (end[0] != 'x') { - return false; + + // Check for "0x" prefix to avoid strtod treating the string as hex + if (str[0] == '0' && str[1] == 'x') { + if (strlen(str) < 3) { + return false; + } + *x = 0; + end = (char *)str + 2; + } else { + *x = strtod(str, &end); + if (end[0] != 'x') { + return false; + } + ++end; } - ++end; *y = strtod(end, &end); if (end[0] == 'm') { From d952ce403e63a1d91f07b72d971500d583609223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Sk=C3=B6ld?= Date: Fri, 1 Sep 2023 21:28:09 -0700 Subject: [PATCH 081/114] i3 compat: Adding support for the `all` criteria Matches all views. i3 PR: https://github.com/i3/i3/pull/4460 Fixes #7110 --- include/sway/criteria.h | 1 + sway/criteria.c | 13 ++++++++++--- sway/sway.5.scd | 3 +++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/include/sway/criteria.h b/include/sway/criteria.h index 59f57f94f..8da345ea6 100644 --- a/include/sway/criteria.h +++ b/include/sway/criteria.h @@ -43,6 +43,7 @@ struct criteria { struct pattern *window_role; enum atom_name window_type; #endif + bool all; bool floating; bool tiling; char urgent; // 'l' for latest or 'o' for oldest diff --git a/sway/criteria.c b/sway/criteria.c index d7326beac..78ea8b8a4 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -19,6 +19,7 @@ bool criteria_is_empty(struct criteria *criteria) { return !criteria->title && !criteria->shell + && !criteria->all && !criteria->app_id && !criteria->con_mark && !criteria->con_id @@ -456,6 +457,7 @@ static enum atom_name parse_window_type(const char *type) { #endif enum criteria_token { + T_ALL, T_APP_ID, T_CON_ID, T_CON_MARK, @@ -478,7 +480,9 @@ enum criteria_token { }; static enum criteria_token token_from_name(char *name) { - if (strcmp(name, "app_id") == 0) { + if (strcmp(name, "all") == 0) { + return T_ALL; + } else if (strcmp(name, "app_id") == 0) { return T_APP_ID; } else if (strcmp(name, "con_id") == 0) { return T_CON_ID; @@ -524,8 +528,8 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) { return false; } - // Require value, unless token is floating or tiled - if (!value && token != T_FLOATING && token != T_TILING) { + // Require value, unless token is all, floating or tiled + if (!value && token != T_ALL && token != T_FLOATING && token != T_TILING) { const char *fmt = "Token '%s' requires a value"; int len = strlen(fmt) + strlen(name) - 1; error = malloc(len); @@ -535,6 +539,9 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) { char *endptr = NULL; switch (token) { + case T_ALL: + criteria->all = true; + break; case T_TITLE: pattern_create(&criteria->title, value); break; diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 78d7d2316..f064ad52f 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -962,6 +962,9 @@ properties in practice for your applications. The following attributes may be matched with: +*all* + Matches all windows. + *app_id* Compare value against the app id. Can be a regular expression. If value is \_\_focused\_\_, then the app id must be the same as that of the currently From 8edc48f6dd8f401ac36ee529facc6c6859d9b8d3 Mon Sep 17 00:00:00 2001 From: Manuel Stoeckl Date: Sat, 9 Sep 2023 17:02:55 -0400 Subject: [PATCH 082/114] sway/server: Fix null pointer crash when Xwayland disabled --- sway/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/server.c b/sway/server.c index db873dcae..ba5c2a0ce 100644 --- a/sway/server.c +++ b/sway/server.c @@ -78,7 +78,7 @@ static bool filter_global(const struct wl_client *client, const struct wl_global *global, void *data) { #if HAVE_XWAYLAND struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; - if (global == xwayland->shell_v1->global) { + if (xwayland && global == xwayland->shell_v1->global) { return xwayland->server != NULL && client == xwayland->server->client; } #endif From 68caa8deba08d2a24d73760d9f7808a94e3fe693 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Tue, 12 Sep 2023 04:27:04 +0200 Subject: [PATCH 083/114] readme: Stop recommending setuid bit for non-logind systems - Optional since Sway 1.6 per swaywm/wlroots@bad1e9afa8ea - Deprecated in Sway 1.7 per 67d3d952b6cd - Removed in Sway 1.8 per e5728052b59f - Ignored in future versions (keeps root priveleges) --- README.cs.md | 6 ------ README.de.md | 6 ------ README.dk.md | 6 ------ README.es.md | 6 ------ README.fr.md | 6 ------ README.ge.md | 6 ------ README.gr.md | 6 ------ README.hi.md | 7 ------- README.hu.md | 7 ------- README.ir.md | 6 ------ README.it.md | 7 ------- README.ko.md | 6 ------ README.md | 6 ------ README.nl.md | 6 ------ README.no.md | 6 ------ README.pl.md | 6 ------ README.pt.md | 6 ------ README.ro.md | 8 -------- README.ru.md | 6 ------ README.sv.md | 6 ------ README.tr.md | 6 ------ README.uk.md | 6 ------ README.zh-CN.md | 6 ------ README.zh-TW.md | 6 ------ 24 files changed, 149 deletions(-) diff --git a/README.cs.md b/README.cs.md index 8d17f9d67..41efba54a 100644 --- a/README.cs.md +++ b/README.cs.md @@ -43,12 +43,6 @@ Spusťte tyto příkazy: ninja -C build/ sudo ninja -C build/ install -Na systémech bez logind či seatd musíte binární soubor sway nastavit jako suid: - - sudo chmod a+s /usr/local/bin/sway - -Sway svá root oprávnění zruší krátce po spuštění. - ## Konfigurace Pokud již používáte i3, zkopírujte svou konfiguraci i3 do `~/.config/sway/config` diff --git a/README.de.md b/README.de.md index 059fda89f..e2a1e8781 100644 --- a/README.de.md +++ b/README.de.md @@ -34,12 +34,6 @@ Führe die folgenden Befehle aus: ninja -C build sudo ninja -C build install -Falls dein System nicht logind benutzt, musst du sway noch die passenden Berechtigungen geben: - - sudo chmod a+s /usr/local/bin/sway - -Sway läuft nur in der Startphase mit Root-Rechten. - ## Konfiguration Falls du von i3 migrierst, kannst du deine Konfigurationsdatei nach `~/.config/sway/config` kopieren und die Einstellungen sollten ohne Weiteres funktionieren. Ansonsten kannst du die Beispielkonfiguration, die normalerweise in `/etc/sway/config` liegt, nach `~/.config/sway/config` kopieren. Die Dokumentation zur Konfigurationsdatei findest du in `man 5 sway`. diff --git a/README.dk.md b/README.dk.md index 3a641295f..5ce94cdef 100644 --- a/README.dk.md +++ b/README.dk.md @@ -45,12 +45,6 @@ Kør følgende kommandoer: ninja -C build sudo ninja -C build install -På systemer uden logind eller seatd skal du sætte SUID bit på sway filen: - - sudo chmod a+s /usr/local/bin/sway - -Sway dropper 'root' tilladelser kort efter opstart. - ## Konfiguration Hvis du allerede bruger i3 kan du bare kopiere din i3 konfiguration til diff --git a/README.es.md b/README.es.md index 5e598e1a3..1f1657dfa 100644 --- a/README.es.md +++ b/README.es.md @@ -44,12 +44,6 @@ Desde su consola, ejecute las órdenes: ninja -C build sudo ninja -C build install -En sistemas sin `logind`, necesitará cambiar los permisos del archivo compilado de sway: - - sudo chmod a+s /usr/local/bin/sway - -Sway abandonará los permisos de super-usuario al poco de arrancar. - ## Configuración Si ya utiliza i3, copie su archivo de configuración de i3 a `~/.config/sway/config` y diff --git a/README.fr.md b/README.fr.md index e99160e84..7752fc70f 100644 --- a/README.fr.md +++ b/README.fr.md @@ -51,12 +51,6 @@ Exécutez ces commandes : ninja -C build sudo ninja -C build install -Sur les systèmes sans logind, vous devez suid le binaire de sway : - - sudo chmod a+s /usr/local/bin/sway - -Sway se débarassera des permissions *root* peu de temps après le démarrage. - ## Configuration Si vous utilisez déjà i3, copiez votre configuration i3 vers diff --git a/README.ge.md b/README.ge.md index ef4f67620..bb8b9a34c 100644 --- a/README.ge.md +++ b/README.ge.md @@ -39,12 +39,6 @@ _\* Compile-time dep_ ninja -C build/ sudo ninja -C build/ install -სისტემებზე logind და seatd-ის გარეშე, გჭირდება suid გაუშვა sway binary-ზე: - - sudo chmod a+s /usr/local/bin/sway - -Sway შეწყვეტს root ნებართვებს მალევე ჩართვის შემდეგ. - ## კონფიგურაცია თუ უკვე იყენებთ i3-ს, მაშინ დააკოპირე i3 კონფიგურაცია და ჩასვი `~/.config/sway/config` diff --git a/README.gr.md b/README.gr.md index f325cb887..d697f78e3 100644 --- a/README.gr.md +++ b/README.gr.md @@ -44,12 +44,6 @@ _\*Compile-time dep_ ninja -C build/ sudo ninja -C build/ install -Σε συστήματα χωρίς logind ή seatd, πρέπει να κάνετε suid το sway binary: - - sudo chmod a+s /usr/local/bin/sway - -Το Sway θα κάνει drop root δικαιώματα λίγο μετά την εκκίνηση. - ## Configuration Εάν ήδη χρησιμοποιήτε το i3, αντιγράψτε το i3 config σας στο `~/.config/sway/config` και diff --git a/README.hi.md b/README.hi.md index af64eadaf..eae5e90a5 100644 --- a/README.hi.md +++ b/README.hi.md @@ -48,13 +48,6 @@ _\* Compilation के समय आवश्यक_ ninja -C build/ sudo ninja -C build/ install -उन systems पर जिनमें ना तो logind है, ना ही seatd है, आपको sway की binary -को suid करना पडेगा: - - sudo chmod a+s /usr/local/bin/sway - -Sway अपनी root अनुमतियां प्रारंभ होने के कुछ ही देर बाद छोड़ देगी। - ## Configuration अगर आप पहले से ही i3 का उपयोग करते हैं तो अपने i3 config को diff --git a/README.hu.md b/README.hu.md index 9e3bc9e1f..82ca6785b 100644 --- a/README.hu.md +++ b/README.hu.md @@ -44,13 +44,6 @@ Futtasd ezeket a parancsokat: ninja -C build sudo ninja -C build install -Ha `logind` nélküli rendszert használsz, akkor be kell állítanod a `suid` bitet -a futtaható állományon: - - sudo chmod a+s /usr/local/bin/sway - -A Sway indulás után nem sokkal el fogja engedni a root jogosultságait. - ## Konfiguráció Ha előzőleg i3-mat használtál, akkor átmásolhatod az i3 beállításaidat a diff --git a/README.ir.md b/README.ir.md index 64956a9ea..a485a4059 100644 --- a/README.ir.md +++ b/README.ir.md @@ -45,12 +45,6 @@ _\*نیازمندی‌های زمان کامپایل برنامه_ ninja -C build sudo ninja -C build install -روی سیستم‌های بدون logind، باید فرمان زیر را برای suid کردن باینری sway اجرا کنید: - - sudo chmod a+s /usr/local/bin/sway - -‏sway پس از startup مجوزهای دسترسی root را رها می‌کند. - ### شخصی سازی و تنظیمات اگر در حال حاضر از i3 استفاده می‌کنید، تنظیمات i3 خودتان را در فایل ‪`~/.config/sway/config`‬ کپی کنید و بدون نیاز به تغییر کار خواهد کرد. در غیر این‌صورت، فایل نمونه تنظیمات را استفاده کنید. این فایل عموما در ‪`/etc/sway/config`‬ قرار دارد. برای آگاهی بیشتر `man 5 sway` را اجرا کنید. diff --git a/README.it.md b/README.it.md index b14b522d5..82bb57837 100644 --- a/README.it.md +++ b/README.it.md @@ -42,13 +42,6 @@ Esegui questi comandi: ninja -C build/ sudo ninja -C build/ install -Nei sistemi in cui non sono disponibili né logind né seatd, è necessario -impostare il permesso suid al binario di sway: - - sudo chmod a+s /usr/local/bin/sway - -Sway rinuncerà ai permessi di root poco dopo l'avvio. - ## Configurazione Se hai già usato i3, copia il tuo file di configurazione in diff --git a/README.ko.md b/README.ko.md index 7a1f4ce12..e086c174c 100644 --- a/README.ko.md +++ b/README.ko.md @@ -43,12 +43,6 @@ _\*컴파일 떄 필요_ ninja -C build sudo ninja -C build install -logind를 사용하고 있지 않는 시스템에서는, 바이너리에 suid를 설정할 필요가 있습니다: - - sudo chmod a+s /usr/local/bin/sway - -Sway는 시작 후에 root 권한을 drop할 것 입니다. - ## 설정 i3를 이미 사용 중이라면, i3 config을 `~/.config/sway/config`로 복사하세요. diff --git a/README.md b/README.md index b3a518111..1cf117c58 100644 --- a/README.md +++ b/README.md @@ -43,12 +43,6 @@ Run these commands: ninja -C build/ sudo ninja -C build/ install -On systems without logind nor seatd, you need to suid the sway binary: - - sudo chmod a+s /usr/local/bin/sway - -Sway will drop root permissions shortly after startup. - ## Configuration If you already use i3, then copy your i3 config to `~/.config/sway/config` and diff --git a/README.nl.md b/README.nl.md index 8a344f033..bf1ea9750 100644 --- a/README.nl.md +++ b/README.nl.md @@ -44,12 +44,6 @@ Voer deze opdrachten uit: ninja -C build sudo ninja -C build install -Op systemen zonder logind, moet je bij het binaire bestand het suid bit instellen: - - sudo chmod a+s /usr/local/bin/sway - -Sway zal root-rechten kort na het opstarten loslaten. - ## Configuratie Als je al i3 gebruikt, kopieer dan je i3-configuratie naar `~/.config/sway/config` en diff --git a/README.no.md b/README.no.md index 0bc268099..35d6e320f 100644 --- a/README.no.md +++ b/README.no.md @@ -45,12 +45,6 @@ Kjør følgende kommandoer: ninja -C build sudo ninja -C build install -På systemer uten logind eller seatd skal du sette SUID bit i sway filen: - - sudo chmod a+s /usr/local/bin/sway - -Sway slipper 'root' tillatelser kort etter oppstart. - ## Konfigurasjon Hvis du allerede bruker i3 kan du bare kopiere din i3 konfigurasjon til diff --git a/README.pl.md b/README.pl.md index ab99abb17..65b3c3a1b 100644 --- a/README.pl.md +++ b/README.pl.md @@ -44,12 +44,6 @@ Wykonaj następujące polecenia: ninja -C build sudo ninja -C build install -Na systemach bez logind należy wykonać polecenie suid na pliku wykonywalnym sway: - - sudo chmod a+s /usr/local/bin/sway - -Sway pozbędzie się uprawnień roota tuż po wystartowaniu. - ## Konfiguracja Jeśli już korzystasz z i3, skopiuj swoją konfigurację i3 do katalogu `~/.config/sway/config` i diff --git a/README.pt.md b/README.pt.md index b22948aa1..c1611a31c 100644 --- a/README.pt.md +++ b/README.pt.md @@ -46,12 +46,6 @@ Execute esses comandos: ninja -C build sudo ninja -C build install -Em sistemas sem logind, você precisa preparar o binário do sway: - - sudo chmod a+s /usr/local/bin/sway - -O sway perderá as privilégios de de root logo após o início do sistema. - ## Configuração Se você já utiliza o i3, então copie os seus arquivos de configuração para `~/.config/sway/config` e diff --git a/README.ro.md b/README.ro.md index 4ce05093a..a3559a8bb 100644 --- a/README.ro.md +++ b/README.ro.md @@ -43,14 +43,6 @@ Rulați aceste comenzi: sudo ninja -C build install ``` -Pe sisteme fără logind, trebuie să folosiți următoarea comandă pentru a marca binarul de Sway ca suid: - -``` - sudo chmod a+s /usr/local/bin/sway -``` - -Imediat după pornire, Sway va renunța la permisiunile de root. - ## Configurare Dacă folosiți deja i3, copiați fișierul de configurare din i3 în `~/.config/sway/config`, și va funcționa fără a necesita nici o modificare. In caz contrar, copiați exemplul de configurare (disponibil de obicei în `/etc/sway/config`) în `~/.config/sway/config`. diff --git a/README.ru.md b/README.ru.md index fb6f33441..edc0eda78 100644 --- a/README.ru.md +++ b/README.ru.md @@ -45,12 +45,6 @@ _\*Зависимости для сборки_ ninja -C build sudo ninja -C build install -На системах без logind вам понадобится добавить suid к файлу программы sway: - - sudo chmod a+s /usr/local/bin/sway - -sway сбросит root-права при запуске. - ## Настройка Если вы уже используете i3, скопируйте ваш конфигурационный файл i3 в `~/.config/sway/config`, и diff --git a/README.sv.md b/README.sv.md index 287242705..c50ca068c 100644 --- a/README.sv.md +++ b/README.sv.md @@ -41,12 +41,6 @@ Kör dessa kommandon: ninja -C build/ sudo ninja -C build/ install -På system utan logind eller seatd måste du ge sways exekverbara fil root-privilegier: - - sudo chmod a+s /usr/local/bin/sway - -Sway kommer att överge sina root-privilegier kort efter uppstart. - ## Konfiguration Ifall du redan använder i3 så kan du kopiera din konfigurationsfil till `~/.config/sway/config` och det kommer då att fungera som det ska. diff --git a/README.tr.md b/README.tr.md index e09d2eaff..40de14748 100644 --- a/README.tr.md +++ b/README.tr.md @@ -42,12 +42,6 @@ _\*Derleme-anı bağımlılıkları_ ninja -C build sudo ninja -C build install -logind olmayan sistemlerde, sway ikilisine (binary) izin vermeniz (suid) gerekir: - - sudo chmod a+s /usr/local/bin/sway - -Sway, başlangıçtan kısa bir süre sonra kök(root) izinlerini bırakacaktır. - ## Yapılandırma Zaten i3 kullanıyorsanız, i3 yapılandırmanızı `~/.config/sway/config` konumuna kopyalayın ve kutudan çıktığı gibi çalışacaktır. Aksi takdirde, örnek yapılandırma dosyasını `~/.config/sway/config` konumuna kopyalayın. Genellikle `/etc/sway/config` konumunda bulunur. diff --git a/README.uk.md b/README.uk.md index d9adcd134..33359cffc 100644 --- a/README.uk.md +++ b/README.uk.md @@ -55,12 +55,6 @@ _\*Лише для компіляції_ ninja -C build sudo ninja -C build install -На системах без logind, необхідно встановити біт SUID на виконуваний файл sway: - - sudo chmod a+s /usr/local/bin/sway - -Sway втратить права доступу root незабаром після запуску. - ## Налаштування Якщо ви вже використовуєте i3, скопіюйте свій файл налаштувань diff --git a/README.zh-CN.md b/README.zh-CN.md index b057bfb86..a6f4518ae 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -39,12 +39,6 @@ _\*编译时依赖_ ninja -C build/ sudo ninja -C build/ install -在没有logind或seatd的系统上, 你需要给sway二进制文件设置suid: - - sudo chmod a+s /usr/local/bin/sway - -启动后,Sway会尽快放弃root权限。 - ## 配置 如果你已经在使用i3,直接复制i3配置文件到 `~/.config/sway/config`,这是开箱即用的。或者,你可以复制配置样例到`~/.config/sway/config`。它通常位于 `/etc/sway/config`。 diff --git a/README.zh-TW.md b/README.zh-TW.md index a7168244d..2de2f63fc 100644 --- a/README.zh-TW.md +++ b/README.zh-TW.md @@ -44,12 +44,6 @@ _\*編譯時相依_ ninja -C build sudo ninja -C build install -在沒有 logind 的系統上,你需要為 sway 的執行檔加上 suid。 - - sudo chmod a+s /usr/local/bin/sway - -Sway 在啟動不久後就會放棄 root 權限。 - ## 設定檔 如果你已經在使用 i3,你可以直接將你的 i3 設定檔複製到 `~/.config/sway/config` 然後就能直接使用。 From b3519c2d2f269f34ff3712ebf1903905a56541a6 Mon Sep 17 00:00:00 2001 From: Ashraf Date: Thu, 14 Sep 2023 11:42:09 +0300 Subject: [PATCH 084/114] Translate README to Arabic --- README.ar.md | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 3 +- 2 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 README.ar.md diff --git a/README.ar.md b/README.ar.md new file mode 100644 index 000000000..4f9bf828a --- /dev/null +++ b/README.ar.md @@ -0,0 +1,91 @@ +# sway + +sway + +هو مدير للمجموعات المركبة لـ[Wayland] متوافق مع [i3] - + +إقرأ [الأسئلة الشائعة](https://github.com/swaywm/sway/wiki) + + انضم الى [قناة IRC](https://web.libera.chat/gamja/?channels=#sway) + + +## تواقيع الإصدار + تٌوقع الإصدارات بـواسطة [E88F5E48] و تُنشر على [GitHub](https://github.com/swaywm/sway/releases) + +## التثبيت + +### بإستخدام الحزم + +يتوفر Sway للعديد من التوزيعات، حاول تثبيت حزمة "sway" لتوزيعتك +### التجميع من المصدر +إطلع على [صفحة الويكي هذه](https://github.com/swaywm/sway/wiki/Development-Setup) إذا أردت بناء الـHEAD من sway و wlroots لأغراض الفحص والتطوير + +تثبيت اللوازم: +* meson \* +* [wlroots] +* wayland +* wayland-protocols \* +* pcre2 +* json-c +* pango +* cairo +* gdk-pixbuf2 (optional: system tray) +* [scdoc] (optional: man pages) \* +* git (optional: version info) \* + +_\* Compile-time dep_ + +نفذ هذه الأوامر: + + meson build/ + ninja -C build/ + sudo ninja -C build/ install + +## الإعدادات + +إذا كنت بالفعل تستخدم i3، فعليك نسخ إعدادات i3 لديك إلى `~/.config/sway/config` وسوف تعمل تلقائياً. + +و إلا عليك نسخ ملف الإعدادات النموذج إلى `config/sway/config` الموجود عادةً في `/etc/sway/config.` + + +## التشغيل + +شغل `sway` بإستخدام أمر TTY. +قد يعمل بعض مدراء العرض مع أنهم غير مدعومون من sway +(gdm مثلاً يعمل بشكل جيد إلى حد ما) + +[en]: https://github.com/swaywm/sway#readme +[ar]: README.ar.md +[cs]: README.cs.md +[de]: README.de.md +[dk]: README.dk.md +[es]: README.es.md +[fr]: README.fr.md +[ge]: README.ge.md +[gr]: README.gr.md +[hi]: README.hi.md +[hu]: README.hu.md +[ir]: README.ir.md +[it]: README.it.md +[ja]: README.ja.md +[ko]: README.ko.md +[nl]: README.nl.md +[no]: README.no.md +[pl]: README.pl.md +[pt]: README.pt.md +[ro]: README.ro.md +[ru]: README.ru.md +[sv]: README.sv.md +[tr]: README.tr.md +[uk]: README.uk.md +[zh-CN]: README.zh-CN.md +[zh-TW]: README.zh-TW.md +[i3]: https://i3wm.org/ +[Wayland]: http://wayland.freedesktop.org/ +[FAQ]: https://github.com/swaywm/sway/wiki +[IRC channel]: https://web.libera.chat/gamja/?channels=#sway +[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 +[GitHub releases]: https://github.com/swaywm/sway/releases +[Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup +[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots +[scdoc]: https://git.sr.ht/~sircmpwn/scdoc diff --git a/README.md b/README.md index 1cf117c58..87e74b146 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # sway -**[English][en]** - [Česky][cs] - [Deutsch][de] - [Dansk][dk] - [Español][es] - [Français][fr] - [ქართული][ge] - [Ελληνικά][gr] - [हिन्दी][hi] - [Magyar][hu] - [فارسی][ir] - [Italiano][it] - [日本語][ja] - [한국어][ko] - [Nederlands][nl] - [Norsk][no] - [Polski][pl] - [Português][pt] - [Română][ro] - [Русский][ru] - [Svenska][sv] - [Türkçe][tr] - [Українська][uk] - [中文-简体][zh-CN] - [中文-繁體][zh-TW] +**[English][en]** - [عربي][ar] - [Česky][cs] - [Deutsch][de] - [Dansk][dk] - [Español][es] - [Français][fr] - [ქართული][ge] - [Ελληνικά][gr] - [हिन्दी][hi] - [Magyar][hu] - [فارسی][ir] - [Italiano][it] - [日本語][ja] - [한국어][ko] - [Nederlands][nl] - [Norsk][no] - [Polski][pl] - [Português][pt] - [Română][ro] - [Русский][ru] - [Svenska][sv] - [Türkçe][tr] - [Українська][uk] - [中文-简体][zh-CN] - [中文-繁體][zh-TW] sway is an [i3]-compatible [Wayland] compositor. Read the [FAQ]. Join the [IRC channel] \(#sway on irc.libera.chat). @@ -56,6 +56,7 @@ Run `sway` from a TTY. Some display managers may work but are not supported by sway (gdm is known to work fairly well). [en]: https://github.com/swaywm/sway#readme +[ar]: README.ar.md [cs]: README.cs.md [de]: README.de.md [dk]: README.dk.md From 7cf4e1d5c68d764037f78cbffb167a4cc763c6c1 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 19 Jun 2023 21:22:23 +0200 Subject: [PATCH 085/114] Drop support for KDE's idle protocol We support the standard idle-notify protocol since Sway 1.8. --- include/sway/desktop/idle_inhibit_v1.h | 1 - include/sway/server.h | 1 - sway/desktop/idle_inhibit_v1.c | 2 -- sway/input/cursor.c | 1 - sway/input/keyboard.c | 1 - sway/input/seat.c | 2 -- sway/input/switch.c | 1 - sway/server.c | 2 -- 8 files changed, 11 deletions(-) diff --git a/include/sway/desktop/idle_inhibit_v1.h b/include/sway/desktop/idle_inhibit_v1.h index 6dda1af97..84cc666d0 100644 --- a/include/sway/desktop/idle_inhibit_v1.h +++ b/include/sway/desktop/idle_inhibit_v1.h @@ -1,7 +1,6 @@ #ifndef _SWAY_DESKTOP_IDLE_INHIBIT_V1_H #define _SWAY_DESKTOP_IDLE_INHIBIT_V1_H #include -#include enum sway_idle_inhibit_mode { INHIBIT_IDLE_APPLICATION, // Application set inhibitor (when visible) diff --git a/include/sway/server.h b/include/sway/server.h index 1eb308a4f..108561e65 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -52,7 +52,6 @@ struct sway_server { struct wl_listener new_output; struct wl_listener output_layout_change; - struct wlr_idle *idle; struct wlr_idle_notifier_v1 *idle_notifier_v1; struct sway_idle_inhibit_manager_v1 idle_inhibit_manager_v1; diff --git a/sway/desktop/idle_inhibit_v1.c b/sway/desktop/idle_inhibit_v1.c index 1fa058e3d..f3af7aa1b 100644 --- a/sway/desktop/idle_inhibit_v1.c +++ b/sway/desktop/idle_inhibit_v1.c @@ -1,5 +1,4 @@ #include -#include #include #include "log.h" #include "sway/desktop/idle_inhibit_v1.h" @@ -140,7 +139,6 @@ void sway_idle_inhibit_v1_check_active(void) { break; } } - wlr_idle_set_enabled(server.idle, NULL, !inhibited); wlr_idle_notifier_v1_set_inhibited(server.idle_notifier_v1, inhibited); } diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 44a5d6f7b..36aab93e2 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index c3bf4fbbd..8927287fb 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include diff --git a/sway/input/seat.c b/sway/input/seat.c index a84e4d52f..f56de137a 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -103,7 +102,6 @@ void seat_idle_notify_activity(struct sway_seat *seat, if ((source & seat->idle_inhibit_sources) == 0) { return; } - wlr_idle_notify_activity(server.idle, seat->wlr_seat); wlr_idle_notifier_v1_notify_activity(server.idle_notifier_v1, seat->wlr_seat); } diff --git a/sway/input/switch.c b/sway/input/switch.c index fc7dfaff7..7a5398014 100644 --- a/sway/input/switch.c +++ b/sway/input/switch.c @@ -1,6 +1,5 @@ #include "sway/config.h" #include "sway/input/switch.h" -#include #include "log.h" struct sway_switch *sway_switch_create(struct sway_seat *seat, diff --git a/sway/server.c b/sway/server.c index ba5c2a0ce..fd0ab585e 100644 --- a/sway/server.c +++ b/sway/server.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -145,7 +144,6 @@ bool server_init(struct sway_server *server) { wlr_xdg_output_manager_v1_create(server->wl_display, root->output_layout); - server->idle = wlr_idle_create(server->wl_display); server->idle_notifier_v1 = wlr_idle_notifier_v1_create(server->wl_display); sway_idle_inhibit_manager_v1_init(); From 8a8fb76ec1d0b9a269b86688cff419201d1e6f62 Mon Sep 17 00:00:00 2001 From: iff <98851855+iffse@users.noreply.github.com> Date: Sun, 10 Sep 2023 21:28:07 +0200 Subject: [PATCH 086/114] Update sway-input.5.scd --- sway/sway-input.5.scd | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index 8a1f27001..442311bb9 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd @@ -121,11 +121,16 @@ The following commands may only be used in the configuration file. *input* map_from_region Ignores inputs from this device that do not occur within the specified - region. Can be in millimeters (e.g. 10x20mm 20x40mm) or in terms of 0..1 - (e.g. 0.5x0.5 0.7x0.7). Not all devices support millimeters. Only meaningful - if the device is not a keyboard and provides events in absolute terms (such - as a drawing tablet or touch screen - most pointers provide events relative - to the previous frame). + region. Can be in millimeters (e.g. 10x20mm 20x40mm) or the fraction of the + full available space in terms of 0..1 (e.g. 0.5x0.5 0.7x0.7). Not all + devices support millimeters. Only meaningful if the device is not a + keyboard and provides events in absolute terms (such as a drawing tablet + or touch screen - most pointers provide events relative to the previous + frame). + + Commonly used to maintain the aspect ratio of the input device and screen. + Cropping a 16:10 input region to match a 16:9 display can use 0x0 1x0.9 as + the argument. ## LIBINPUT CONFIGURATION From 4326a26ad6fb64b8f8de7d32c1e7b6423e1f84f3 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Fri, 6 Oct 2023 07:29:01 -0400 Subject: [PATCH 087/114] Chase wlroots!4331 --- sway/desktop/output.c | 11 ++++++++--- sway/lock.c | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index aed1fdeb0..0670b3dd5 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -942,12 +942,15 @@ static void handle_commit(struct wl_listener *listener, void *data) { return; } - if (event->committed & WLR_OUTPUT_STATE_SCALE) { + if (event->state->committed & WLR_OUTPUT_STATE_SCALE) { output_for_each_container(output, update_textures, NULL); output_for_each_surface(output, update_output_scale_iterator, NULL); } - if (event->committed & (WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_TRANSFORM | WLR_OUTPUT_STATE_SCALE)) { + if (event->state->committed & ( + WLR_OUTPUT_STATE_MODE | + WLR_OUTPUT_STATE_TRANSFORM | + WLR_OUTPUT_STATE_SCALE)) { arrange_layers(output); arrange_output(output); transaction_commit_dirty(); @@ -955,7 +958,9 @@ static void handle_commit(struct wl_listener *listener, void *data) { update_output_manager_config(output->server); } - if (event->committed & (WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_TRANSFORM)) { + if (event->state->committed & ( + WLR_OUTPUT_STATE_MODE | + WLR_OUTPUT_STATE_TRANSFORM)) { int width, height; wlr_output_transformed_resolution(output->wlr_output, &width, &height); wlr_damage_ring_set_bounds(&output->damage_ring, width, height); diff --git a/sway/lock.c b/sway/lock.c index 70ac39691..199624fc4 100644 --- a/sway/lock.c +++ b/sway/lock.c @@ -46,7 +46,7 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { static void handle_output_commit(struct wl_listener *listener, void *data) { struct wlr_output_event_commit *event = data; struct sway_session_lock_surface *surf = wl_container_of(listener, surf, output_commit); - if (event->committed & ( + if (event->state->committed & ( WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_SCALE | WLR_OUTPUT_STATE_TRANSFORM)) { From f2425b516309aae7b6458365e53c850701b055c0 Mon Sep 17 00:00:00 2001 From: Tamino Bauknecht Date: Wed, 18 Oct 2023 16:29:02 +0200 Subject: [PATCH 088/114] gitignore: Ignore clangd-generated directory .cache/ --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 1ec0cb523..167960e2e 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ bin/ test/ build/ build-*/ +.cache/ .lvimrc config-debug wayland-*-protocol.* From 0dfaf7ea639570ed8fcbc8c1592740b0791b7705 Mon Sep 17 00:00:00 2001 From: Tamino Bauknecht Date: Wed, 18 Oct 2023 22:30:10 +0200 Subject: [PATCH 089/114] config/output: Allow approximation of output refresh rate Previous behavior was that only if resolution and refresh rate match exactly, the mode was accepted. As fallback, the mode with the highest refresh rate and the same resolution was chosen. New behavior is that the mode with the closest match for the refresh rate is used with a limit of up to 1Hz. The fallback behavior stays the same. Additionally, the logging was made more verbose. --- sway/config/output.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/sway/config/output.c b/sway/config/output.c index 0985b0e8a..eefde22b6 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -249,6 +249,8 @@ static void set_mode(struct wlr_output *output, struct wlr_output_state *pending // as (int)(1000 * mHz / 1000.f) // round() the result to avoid any error int mhz = (int)roundf(refresh_rate * 1000); + // If no target refresh rate is given, match highest available + mhz = mhz <= 0 ? INT_MAX : mhz; if (wl_list_empty(&output->modes) || custom) { sway_log(SWAY_DEBUG, "Assigning custom mode to %s", output->name); @@ -258,23 +260,28 @@ static void set_mode(struct wlr_output *output, struct wlr_output_state *pending } struct wlr_output_mode *mode, *best = NULL; + int best_diff_mhz = INT_MAX; wl_list_for_each(mode, &output->modes, link) { if (mode->width == width && mode->height == height) { - if (mode->refresh == mhz) { - best = mode; - break; - } - if (best == NULL || mode->refresh > best->refresh) { + int diff_mhz = abs(mode->refresh - mhz); + if (diff_mhz < best_diff_mhz) { + best_diff_mhz = diff_mhz; best = mode; + if (best_diff_mhz == 0) { + break; + } } } } - if (!best) { - sway_log(SWAY_ERROR, "Configured mode for %s not available", output->name); - sway_log(SWAY_INFO, "Picking preferred mode instead"); - best = wlr_output_preferred_mode(output); + if (best) { + sway_log(SWAY_INFO, "Assigning configured mode (%dx%d@%.3fHz) to %s", + best->width, best->height, best->refresh / 1000.f, output->name); } else { - sway_log(SWAY_DEBUG, "Assigning configured mode to %s", output->name); + best = wlr_output_preferred_mode(output); + sway_log(SWAY_INFO, "Configured mode (%dx%d@%.3fHz) not available, " + "applying preferred mode (%dx%d@%.3fHz)", + width, height, refresh_rate, + best->width, best->height, best->refresh / 1000.f); } wlr_output_state_set_mode(pending, best); } From 47263aca289ab4d89ba69a543357603e64719ff6 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 24 Oct 2023 15:24:51 +0300 Subject: [PATCH 090/114] view: check if the buffer was uploaded on save wlr_surface_has_buffer() is insufficient; if a client has committed a buffer but it couldn't be applied, NULL deref happens in the next line. --- sway/tree/view.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/tree/view.c b/sway/tree/view.c index ec54fed81..a9035de7e 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1422,7 +1422,7 @@ static void view_save_buffer_iterator(struct wlr_surface *surface, int sx, int sy, void *data) { struct sway_view *view = data; - if (surface && wlr_surface_has_buffer(surface)) { + if (surface && surface->buffer) { wlr_buffer_lock(&surface->buffer->base); struct sway_saved_buffer *saved_buffer = calloc(1, sizeof(struct sway_saved_buffer)); saved_buffer->buffer = surface->buffer; From 647521244a99f7dbda8fa7c21d7eee781692dc22 Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Sat, 7 Oct 2023 11:28:07 -0500 Subject: [PATCH 091/114] xdg_shell: don't update wlr_toplevel if the container has no size yet 3d5ae9813d390ea747462fc0026ee43b7c77d0f2 added logic to change the underlying wlr_toplevel size for floating containers, but it does it even if the container has no actual coordinates yet. This doesn't really make sense to update the toplevel size in this case since there's many things that could affect the initial coordinates (sway commands, fullscreen state, etc.). Skip this by doing a crude check to see if the current container state has any width. --- sway/desktop/xdg_shell.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index c2a985ee2..7c01bf168 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -294,8 +294,11 @@ static void handle_commit(struct wl_listener *listener, void *data) { memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); if (container_is_floating(view->container)) { view_update_size(view); - wlr_xdg_toplevel_set_size(view->wlr_xdg_toplevel, view->geometry.width, - view->geometry.height); + // Only set the toplevel size the current container actually has a size. + if (view->container->current.width) { + wlr_xdg_toplevel_set_size(view->wlr_xdg_toplevel, view->geometry.width, + view->geometry.height); + } transaction_commit_dirty_client(); } else { view_center_surface(view); From f2425b4fd64314394aa962cee12b617fb7e5b10f Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Sun, 29 Oct 2023 18:59:25 +0300 Subject: [PATCH 092/114] xdg-shell: send maximized if tiled isn't supported wlroots doesn't do it automatically anymore. --- sway/desktop/xdg_shell.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 7c01bf168..4c59b42a2 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -169,12 +169,19 @@ static void set_tiled(struct sway_view *view, bool tiled) { if (xdg_shell_view_from_view(view) == NULL) { return; } - enum wlr_edges edges = WLR_EDGE_NONE; - if (tiled) { - edges = WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | - WLR_EDGE_BOTTOM; + if (wl_resource_get_version(view->wlr_xdg_toplevel->resource) >= + XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION) { + enum wlr_edges edges = WLR_EDGE_NONE; + if (tiled) { + edges = WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | + WLR_EDGE_BOTTOM; + } + wlr_xdg_toplevel_set_tiled(view->wlr_xdg_toplevel, edges); + } else { + // The version is too low for the tiled state; configure as maximized instead + // to stop the client from drawing decorations outside of the toplevel geometry. + wlr_xdg_toplevel_set_maximized(view->wlr_xdg_toplevel, tiled); } - wlr_xdg_toplevel_set_tiled(view->wlr_xdg_toplevel, edges); } static void set_fullscreen(struct sway_view *view, bool fullscreen) { From 6f6b82793d95e3c10d54bcf21ca3f0c76c44b882 Mon Sep 17 00:00:00 2001 From: Bill Li Date: Tue, 31 Oct 2023 11:11:02 +0800 Subject: [PATCH 093/114] chase wlroots!4411 References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4411 fix #7802 --- sway/desktop/output.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 0670b3dd5..f2bc4a678 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -706,9 +706,7 @@ static void handle_frame(struct wl_listener *listener, void *user_data) { if (output->max_render_time != 0) { struct timespec now; - clockid_t presentation_clock - = wlr_backend_get_presentation_clock(server.backend); - clock_gettime(presentation_clock, &now); + clock_gettime(CLOCK_MONOTONIC, &now); const long NSEC_IN_SECONDS = 1000000000; struct timespec predicted_refresh = output->last_presentation; From 020a572ed615b8fe272c7566a27ee0abe73a58d7 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Fri, 3 Nov 2023 12:17:39 +0000 Subject: [PATCH 094/114] swaynag/config.c: fix build against gcc-14 (-Walloc-size) `gcc-14` added a new `-Walloc-size` warning that makes sure that size of an individual element matches size of a pointed type: https://gcc.gnu.org/PR71219 `sway` triggers it on `calloc()` calls where member size is used as `1` (instead of member count): swaynag/config.c:169:65: error: allocation of insufficient size '1' for type 'struct swaynag_button' with size '48' [-Werror=alloc-size] 169 | struct swaynag_button *button = calloc(sizeof(struct swaynag_button), 1); --- swaynag/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swaynag/config.c b/swaynag/config.c index 6d39f3425..cff3930f1 100644 --- a/swaynag/config.c +++ b/swaynag/config.c @@ -166,7 +166,7 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag, fprintf(stderr, "Missing action for button %s\n", optarg); return EXIT_FAILURE; } - struct swaynag_button *button = calloc(sizeof(struct swaynag_button), 1); + struct swaynag_button *button = calloc(1, sizeof(struct swaynag_button)); if (!button) { perror("calloc"); return EXIT_FAILURE; From 01dcad80e170cdca02f7195c6f55502c74ac313c Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 16 Nov 2023 14:49:52 +0100 Subject: [PATCH 095/114] input/seat: don't configure mappings for switches Switch devices cannot be mapped to an output/region, stop trying to do so. --- sway/input/seat.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index f56de137a..6c0e85bdf 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -834,7 +834,6 @@ static void seat_configure_switch(struct sway_seat *seat, if (!seat_device->switch_device) { sway_switch_create(seat, seat_device); } - seat_apply_input_config(seat, seat_device); sway_switch_configure(seat_device->switch_device); } From caa92ddee81b4af121773abc048ab79ea6df0a98 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 16 Nov 2023 14:50:52 +0100 Subject: [PATCH 096/114] input/seat: rename seat_apply_input_config seat_apply_input_mapping is a lot more descriptive. --- sway/input/seat.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index 6c0e85bdf..bafdbcf3e 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -705,12 +705,12 @@ static bool is_touch_or_tablet_tool(struct sway_seat_device *seat_device) { } } -static void seat_apply_input_config(struct sway_seat *seat, +static void seat_apply_input_mapping(struct sway_seat *seat, struct sway_seat_device *sway_device) { struct input_config *ic = input_device_get_config(sway_device->input_device); - sway_log(SWAY_DEBUG, "Applying input config to %s", + sway_log(SWAY_DEBUG, "Applying input mapping to %s", sway_device->input_device->identifier); const char *mapped_to_output = ic == NULL ? NULL : ic->mapped_to_output; @@ -799,7 +799,7 @@ static void seat_configure_pointer(struct sway_seat *seat, } wlr_cursor_attach_input_device(seat->cursor->cursor, sway_device->input_device->wlr_device); - seat_apply_input_config(seat, sway_device); + seat_apply_input_mapping(seat, sway_device); wl_event_source_timer_update( seat->cursor->hide_source, cursor_get_timeout(seat->cursor)); } @@ -841,7 +841,7 @@ static void seat_configure_touch(struct sway_seat *seat, struct sway_seat_device *sway_device) { wlr_cursor_attach_input_device(seat->cursor->cursor, sway_device->input_device->wlr_device); - seat_apply_input_config(seat, sway_device); + seat_apply_input_mapping(seat, sway_device); } static void seat_configure_tablet_tool(struct sway_seat *seat, @@ -852,7 +852,7 @@ static void seat_configure_tablet_tool(struct sway_seat *seat, sway_configure_tablet(sway_device->tablet); wlr_cursor_attach_input_device(seat->cursor->cursor, sway_device->input_device->wlr_device); - seat_apply_input_config(seat, sway_device); + seat_apply_input_mapping(seat, sway_device); } static void seat_configure_tablet_pad(struct sway_seat *seat, From 7036769bea886ab1f9d627785f14cea9e25b16f7 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 16 Nov 2023 14:56:46 +0100 Subject: [PATCH 097/114] Only reconfigure input mappings on output change Fully reconfiguring all input devices on output change takes a loooong time. Let's just reconfigure what we need: only mappings depend on outputs. --- include/sway/input/input-manager.h | 2 ++ include/sway/input/seat.h | 3 +++ sway/config/output.c | 2 +- sway/input/input-manager.c | 10 ++++++++++ sway/input/seat.c | 24 +++++++++++++++++++++--- sway/tree/output.c | 2 +- 6 files changed, 38 insertions(+), 5 deletions(-) diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index b651e3dd9..6652d60cb 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -47,6 +47,8 @@ void input_manager_apply_input_config(struct input_config *input_config); void input_manager_configure_all_inputs(void); +void input_manager_configure_all_input_mappings(void); + void input_manager_reset_input(struct sway_input_device *input_device); void input_manager_reset_all_inputs(void); diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 35a96ace9..97e81c190 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -168,6 +168,9 @@ void seat_add_device(struct sway_seat *seat, void seat_configure_device(struct sway_seat *seat, struct sway_input_device *device); +void seat_configure_device_mapping(struct sway_seat *seat, + struct sway_input_device *input_device); + void seat_reset_device(struct sway_seat *seat, struct sway_input_device *input_device); diff --git a/sway/config/output.c b/sway/config/output.c index eefde22b6..3316085a7 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -590,7 +590,7 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) { // Reconfigure all devices, since input config may have been applied before // this output came online, and some config items (like map_to_output) are // dependent on an output being present. - input_manager_configure_all_inputs(); + input_manager_configure_all_input_mappings(); // Reconfigure the cursor images, since the scale may have changed. input_manager_configure_xcursor(); return true; diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index db82bb4c8..5300919aa 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -571,6 +571,16 @@ void input_manager_configure_all_inputs(void) { } } +void input_manager_configure_all_input_mappings(void) { + struct sway_input_device *input_device; + wl_list_for_each(input_device, &server.input->devices, link) { + struct sway_seat *seat; + wl_list_for_each(seat, &server.input->seats, link) { + seat_configure_device_mapping(seat, input_device); + } + } +} + void input_manager_apply_input_config(struct input_config *input_config) { struct sway_input_device *input_device = NULL; bool wildcard = strcmp(input_config->identifier, "*") == 0; diff --git a/sway/input/seat.c b/sway/input/seat.c index bafdbcf3e..f73946b14 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -710,6 +710,15 @@ static void seat_apply_input_mapping(struct sway_seat *seat, struct input_config *ic = input_device_get_config(sway_device->input_device); + switch (sway_device->input_device->wlr_device->type) { + case WLR_INPUT_DEVICE_POINTER: + case WLR_INPUT_DEVICE_TOUCH: + case WLR_INPUT_DEVICE_TABLET_TOOL: + break; + default: + return; // these devices don't support mappings + } + sway_log(SWAY_DEBUG, "Applying input mapping to %s", sway_device->input_device->identifier); @@ -799,7 +808,6 @@ static void seat_configure_pointer(struct sway_seat *seat, } wlr_cursor_attach_input_device(seat->cursor->cursor, sway_device->input_device->wlr_device); - seat_apply_input_mapping(seat, sway_device); wl_event_source_timer_update( seat->cursor->hide_source, cursor_get_timeout(seat->cursor)); } @@ -841,7 +849,6 @@ static void seat_configure_touch(struct sway_seat *seat, struct sway_seat_device *sway_device) { wlr_cursor_attach_input_device(seat->cursor->cursor, sway_device->input_device->wlr_device); - seat_apply_input_mapping(seat, sway_device); } static void seat_configure_tablet_tool(struct sway_seat *seat, @@ -852,7 +859,6 @@ static void seat_configure_tablet_tool(struct sway_seat *seat, sway_configure_tablet(sway_device->tablet); wlr_cursor_attach_input_device(seat->cursor->cursor, sway_device->input_device->wlr_device); - seat_apply_input_mapping(seat, sway_device); } static void seat_configure_tablet_pad(struct sway_seat *seat, @@ -909,6 +915,18 @@ void seat_configure_device(struct sway_seat *seat, seat_configure_tablet_pad(seat, seat_device); break; } + + seat_apply_input_mapping(seat, seat_device); +} + +void seat_configure_device_mapping(struct sway_seat *seat, + struct sway_input_device *input_device) { + struct sway_seat_device *seat_device = seat_get_device(seat, input_device); + if (!seat_device) { + return; + } + + seat_apply_input_mapping(seat, seat_device); } void seat_reset_device(struct sway_seat *seat, diff --git a/sway/tree/output.c b/sway/tree/output.c index 0960f4135..4aa3a7fea 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -277,7 +277,7 @@ void output_disable(struct sway_output *output) { // Reconfigure all devices, since devices with map_to_output directives for // an output that goes offline should stop sending events as long as the // output remains offline. - input_manager_configure_all_inputs(); + input_manager_configure_all_input_mappings(); } void output_begin_destroy(struct sway_output *output) { From 5c99b98805e8171d590d466b2eb21402aaf8de6b Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 16 Nov 2023 15:40:16 +0100 Subject: [PATCH 098/114] input/input-manager: drop input_manager_configure_all_inputs This is now unused. --- include/sway/input/input-manager.h | 2 -- sway/input/input-manager.c | 7 ------- 2 files changed, 9 deletions(-) diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index 6652d60cb..4bd517093 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -45,8 +45,6 @@ void input_manager_configure_xcursor(void); void input_manager_apply_input_config(struct input_config *input_config); -void input_manager_configure_all_inputs(void); - void input_manager_configure_all_input_mappings(void); void input_manager_reset_input(struct sway_input_device *input_device); diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 5300919aa..dcaeb056e 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -564,13 +564,6 @@ static void input_manager_configure_input( } } -void input_manager_configure_all_inputs(void) { - struct sway_input_device *input_device = NULL; - wl_list_for_each(input_device, &server.input->devices, link) { - input_manager_configure_input(input_device); - } -} - void input_manager_configure_all_input_mappings(void) { struct sway_input_device *input_device; wl_list_for_each(input_device, &server.input->devices, link) { From f7a40cfa2fd89d41afd596e7bbfbdd66a4a0e4da Mon Sep 17 00:00:00 2001 From: Lina Banik Date: Mon, 6 Jun 2022 17:16:29 +0200 Subject: [PATCH 099/114] seat: Fix reloading cursor theme after change This reverts commit afde6369 "seat: avoid unneeded reloading xcursor theme". Always avoiding to reload the xcursor theme prevents reloading the cursor even when this is desired. Instead seat_configure_xcursor can determine whether a full reload is necessary. To stay with the spirit of the reverted change, cursors are only fully reloaded, if the theme has changed. Fixes #6931 --- sway/input/seat.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index f73946b14..0fd0e8e65 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -803,9 +803,7 @@ static void seat_apply_input_mapping(struct sway_seat *seat, static void seat_configure_pointer(struct sway_seat *seat, struct sway_seat_device *sway_device) { - if ((seat->wlr_seat->capabilities & WL_SEAT_CAPABILITY_POINTER) == 0) { - seat_configure_xcursor(seat); - } + seat_configure_xcursor(seat); wlr_cursor_attach_input_device(seat->cursor->cursor, sway_device->input_device->wlr_device); wl_event_source_timer_update( @@ -1069,26 +1067,27 @@ void seat_configure_xcursor(struct sway_seat *seat) { sway_log(SWAY_ERROR, "Cannot create XCursor manager for theme '%s'", cursor_theme); } - } - for (int i = 0; i < root->outputs->length; ++i) { - struct sway_output *sway_output = root->outputs->items[i]; - struct wlr_output *output = sway_output->wlr_output; - bool result = - wlr_xcursor_manager_load(seat->cursor->xcursor_manager, - output->scale); - if (!result) { - sway_log(SWAY_ERROR, - "Cannot load xcursor theme for output '%s' with scale %f", - output->name, output->scale); + + for (int i = 0; i < root->outputs->length; ++i) { + struct sway_output *sway_output = root->outputs->items[i]; + struct wlr_output *output = sway_output->wlr_output; + bool result = + wlr_xcursor_manager_load(seat->cursor->xcursor_manager, + output->scale); + if (!result) { + sway_log(SWAY_ERROR, + "Cannot load xcursor theme for output '%s' with scale %f", + output->name, output->scale); + } } - } - // Reset the cursor so that we apply it to outputs that just appeared - cursor_set_image(seat->cursor, NULL, NULL); - cursor_set_image(seat->cursor, "default", NULL); - wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, - seat->cursor->cursor->y); + // Reset the cursor so that we apply it to outputs that just appeared + cursor_set_image(seat->cursor, NULL, NULL); + cursor_set_image(seat->cursor, "default", NULL); + wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, + seat->cursor->cursor->y); + } } bool seat_is_input_allowed(struct sway_seat *seat, From c3ec141b3445b37b938c504341c7856d61a34cb9 Mon Sep 17 00:00:00 2001 From: NemuiBanila <67269576+nemuibanila@users.noreply.github.com> Date: Tue, 26 Sep 2023 13:12:57 +0200 Subject: [PATCH 100/114] seat: Fix cursor theme reload for tablet tool --- sway/input/tablet.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sway/input/tablet.c b/sway/input/tablet.c index f979bc68d..902cb7eda 100644 --- a/sway/input/tablet.c +++ b/sway/input/tablet.c @@ -58,9 +58,7 @@ void sway_configure_tablet(struct sway_tablet *tablet) { tablet->seat_device->input_device->wlr_device; struct sway_seat *seat = tablet->seat_device->sway_seat; - if ((seat->wlr_seat->capabilities & WL_SEAT_CAPABILITY_POINTER) == 0) { - seat_configure_xcursor(seat); - } + seat_configure_xcursor(seat); if (!tablet->tablet_v2) { tablet->tablet_v2 = From 86f96a786bac957f5195e894c94b1ce7eb93ef09 Mon Sep 17 00:00:00 2001 From: EBADBEEF Date: Fri, 20 Oct 2023 10:29:06 -0700 Subject: [PATCH 101/114] view: re-apply criteria when window gets unmapped Remove any existing executed criteria items at unmap time. If a window gets unmapped but not destroyed, we want to reapply 'for_window' criteria. Fixes #6905. --- sway/tree/view.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sway/tree/view.c b/sway/tree/view.c index a9035de7e..00dc47215 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -882,6 +882,8 @@ void view_unmap(struct sway_view *view) { wl_list_remove(&view->surface_new_subsurface.link); + view->executed_criteria->length = 0; + if (view->urgent_timer) { wl_event_source_remove(view->urgent_timer); view->urgent_timer = NULL; From 5bdd6085148d8eddf0ae8f9a25ec32eb5bfd48ad Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 5 Oct 2023 10:41:15 +0200 Subject: [PATCH 102/114] Apply gamma LUT when an output re-enabled References: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3679 --- sway/desktop/output.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index f2bc4a678..53730073f 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -964,6 +964,11 @@ static void handle_commit(struct wl_listener *listener, void *data) { wlr_damage_ring_set_bounds(&output->damage_ring, width, height); wlr_output_schedule_frame(output->wlr_output); } + + // Next time the output is enabled, try to re-apply the gamma LUT + if ((event->committed & WLR_OUTPUT_STATE_ENABLED) && !output->wlr_output->enabled) { + output->gamma_lut_changed = true; + } } static void handle_present(struct wl_listener *listener, void *data) { From 072fa60cb401acb2e257a03baf41c8ae63f4753d Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 22 Jun 2023 17:06:10 +0200 Subject: [PATCH 103/114] Add support for security-context-v1 As a first step, deny access to privileged protocols to sandboxed apps. References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3589 --- include/sway/server.h | 4 ++++ sway/server.c | 38 ++++++++++++++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/include/sway/server.h b/include/sway/server.h index 108561e65..be5c8d72c 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -114,6 +114,10 @@ struct sway_server { struct wlr_text_input_manager_v3 *text_input; struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager; struct wlr_content_type_manager_v1 *content_type_manager_v1; + struct wlr_data_control_manager_v1 *data_control_manager_v1; + struct wlr_screencopy_manager_v1 *screencopy_manager_v1; + struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager_v1; + struct wlr_security_context_manager_v1 *security_context_manager_v1; struct wlr_xdg_activation_v1 *xdg_activation_v1; struct wl_listener xdg_activation_v1_request_activate; diff --git a/sway/server.c b/sway/server.c index fd0ab585e..217c9ac94 100644 --- a/sway/server.c +++ b/sway/server.c @@ -24,8 +24,9 @@ #include #include #include -#include +#include #include +#include #include #include #include @@ -73,6 +74,25 @@ static void handle_drm_lease_request(struct wl_listener *listener, void *data) { } #endif +static bool is_privileged(const struct wl_global *global) { + return + global == server.output_manager_v1->global || + global == server.output_power_manager_v1->global || + global == server.input_method->global || + global == server.foreign_toplevel_manager->global || + global == server.data_control_manager_v1->global || + global == server.screencopy_manager_v1->global || + global == server.export_dmabuf_manager_v1->global || + global == server.security_context_manager_v1->global || + global == server.gamma_control_manager_v1->global || + global == server.layer_shell->global || + global == server.session_lock.manager->global || + global == server.input->inhibit->global || + global == server.input->keyboard_shortcuts_inhibit->global || + global == server.input->virtual_keyboard->global || + global == server.input->virtual_pointer->global; +} + static bool filter_global(const struct wl_client *client, const struct wl_global *global, void *data) { #if HAVE_XWAYLAND @@ -82,6 +102,15 @@ static bool filter_global(const struct wl_client *client, } #endif + // Restrict usage of privileged protocols to unsandboxed clients + // TODO: add a way for users to configure an allow-list + const struct wlr_security_context_v1_state *security_context = + wlr_security_context_manager_v1_lookup_client( + server.security_context_manager_v1, (struct wl_client *)client); + if (is_privileged(global)) { + return security_context == NULL; + } + return true; } @@ -226,9 +255,10 @@ bool server_init(struct sway_server *server) { } #endif - wlr_export_dmabuf_manager_v1_create(server->wl_display); - wlr_screencopy_manager_v1_create(server->wl_display); - wlr_data_control_manager_v1_create(server->wl_display); + server->export_dmabuf_manager_v1 = wlr_export_dmabuf_manager_v1_create(server->wl_display); + server->screencopy_manager_v1 = wlr_screencopy_manager_v1_create(server->wl_display); + server->data_control_manager_v1 = wlr_data_control_manager_v1_create(server->wl_display); + server->security_context_manager_v1 = wlr_security_context_manager_v1_create(server->wl_display); wlr_viewporter_create(server->wl_display); wlr_single_pixel_buffer_manager_v1_create(server->wl_display); server->content_type_manager_v1 = From 9d666a08e1ec77680890a08f63e71ce6bb53b9a9 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 21 Nov 2023 16:52:19 +0100 Subject: [PATCH 104/114] Fix reference to wlr_output_event_commit.committed This has been dropped from wlroots. Previous commit missed that. --- sway/desktop/output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 53730073f..e02ab32d0 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -966,7 +966,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { } // Next time the output is enabled, try to re-apply the gamma LUT - if ((event->committed & WLR_OUTPUT_STATE_ENABLED) && !output->wlr_output->enabled) { + if ((event->state->committed & WLR_OUTPUT_STATE_ENABLED) && !output->wlr_output->enabled) { output->gamma_lut_changed = true; } } From bff991dfdc63ca3785a810ff4d913ddfd71677a1 Mon Sep 17 00:00:00 2001 From: Matt Fellenz Date: Mon, 23 Oct 2023 18:49:50 -0700 Subject: [PATCH 105/114] Use locale time format for default bar command --- config.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.in b/config.in index 48ba1f1e4..a5173165b 100644 --- a/config.in +++ b/config.in @@ -205,7 +205,7 @@ bar { # When the status_command prints a new line to stdout, swaybar updates. # The default just shows the current date and time. - status_command while date +'%Y-%m-%d %I:%M:%S %p'; do sleep 1; done + status_command while date +'%Y-%m-%d %X'; do sleep 1; done colors { statusline #ffffff From 4ad15a4015feef2ecfba311c13e64e3976cc611c Mon Sep 17 00:00:00 2001 From: llyyr Date: Tue, 21 Nov 2023 23:55:19 +0530 Subject: [PATCH 106/114] meson: bump wlroots version after 0.17.0 release --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index eeee39cde..adf49c196 100644 --- a/meson.build +++ b/meson.build @@ -37,7 +37,7 @@ if is_freebsd endif # Execute the wlroots subproject, if any -wlroots_version = ['>=0.17.0', '<0.18.0'] +wlroots_version = ['>=0.18.0', '<0.19.0'] subproject( 'wlroots', default_options: ['examples=false'], From a946b1aecfa3f32a3bfae66d66df0bdf77440d69 Mon Sep 17 00:00:00 2001 From: llyyr Date: Wed, 22 Nov 2023 00:05:03 +0530 Subject: [PATCH 107/114] Chase wlroots!4440 References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4440 --- include/sway/input/input-manager.h | 2 - protocols/meson.build | 1 - protocols/wlr-input-inhibitor-unstable-v1.xml | 67 ------------------- sway/input/input-manager.c | 37 ---------- sway/server.c | 1 - 5 files changed, 108 deletions(-) delete mode 100644 protocols/wlr-input-inhibitor-unstable-v1.xml diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h index 4bd517093..145edd4b6 100644 --- a/include/sway/input/input-manager.h +++ b/include/sway/input/input-manager.h @@ -1,7 +1,6 @@ #ifndef _SWAY_INPUT_INPUT_MANAGER_H #define _SWAY_INPUT_INPUT_MANAGER_H #include -#include #include #include #include @@ -21,7 +20,6 @@ struct sway_input_manager { struct wl_list devices; struct wl_list seats; - struct wlr_input_inhibit_manager *inhibit; struct wlr_keyboard_shortcuts_inhibit_manager_v1 *keyboard_shortcuts_inhibit; struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard; struct wlr_virtual_pointer_manager_v1 *virtual_pointer; diff --git a/protocols/meson.build b/protocols/meson.build index 2992ac585..81edb5841 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -16,7 +16,6 @@ protocols = [ wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml', 'wlr-layer-shell-unstable-v1.xml', 'idle.xml', - 'wlr-input-inhibitor-unstable-v1.xml', 'wlr-output-power-management-unstable-v1.xml', ] diff --git a/protocols/wlr-input-inhibitor-unstable-v1.xml b/protocols/wlr-input-inhibitor-unstable-v1.xml deleted file mode 100644 index b62d1bb44..000000000 --- a/protocols/wlr-input-inhibitor-unstable-v1.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - Copyright © 2018 Drew DeVault - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that copyright notice and this permission - notice appear in supporting documentation, and that the name of - the copyright holders not be used in advertising or publicity - pertaining to distribution of the software without specific, - written prior permission. The copyright holders make no - representations about the suitability of this software for any - purpose. It is provided "as is" without express or implied - warranty. - - THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - THIS SOFTWARE. - - - - - Clients can use this interface to prevent input events from being sent to - any surfaces but its own, which is useful for example in lock screen - software. It is assumed that access to this interface will be locked down - to whitelisted clients by the compositor. - - - - - Activates the input inhibitor. As long as the inhibitor is active, the - compositor will not send input events to other clients. - - - - - - - - - - - - While this resource exists, input to clients other than the owner of the - inhibitor resource will not receive input events. The client that owns - this resource will receive all input events normally. The compositor will - also disable all of its own input processing (such as keyboard shortcuts) - while the inhibitor is active. - - The compositor may continue to send input events to selected clients, - such as an on-screen keyboard (via the input-method protocol). - - - - - Destroy the inhibitor and allow other clients to receive input. - - - - diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index dcaeb056e..4febc3334 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include "sway/config.h" @@ -284,34 +283,6 @@ static void handle_new_input(struct wl_listener *listener, void *data) { } } -static void handle_inhibit_activate(struct wl_listener *listener, void *data) { - struct sway_input_manager *input_manager = wl_container_of( - listener, input_manager, inhibit_activate); - struct sway_seat *seat; - wl_list_for_each(seat, &input_manager->seats, link) { - seat_set_exclusive_client(seat, input_manager->inhibit->active_client); - } -} - -static void handle_inhibit_deactivate(struct wl_listener *listener, void *data) { - struct sway_input_manager *input_manager = wl_container_of( - listener, input_manager, inhibit_deactivate); - struct sway_seat *seat; - if (server.session_lock.locked) { - // Don't deactivate the grab of a screenlocker - return; - } - wl_list_for_each(seat, &input_manager->seats, link) { - seat_set_exclusive_client(seat, NULL); - struct sway_node *previous = seat_get_focus(seat); - if (previous) { - // Hack to get seat to re-focus the return value of get_focus - seat_set_focus(seat, NULL); - seat_set_focus(seat, previous); - } - } -} - static void handle_keyboard_shortcuts_inhibitor_destroy( struct wl_listener *listener, void *data) { struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor = @@ -480,14 +451,6 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) { &input->virtual_pointer_new); input->virtual_pointer_new.notify = handle_virtual_pointer; - input->inhibit = wlr_input_inhibit_manager_create(server->wl_display); - input->inhibit_activate.notify = handle_inhibit_activate; - wl_signal_add(&input->inhibit->events.activate, - &input->inhibit_activate); - input->inhibit_deactivate.notify = handle_inhibit_deactivate; - wl_signal_add(&input->inhibit->events.deactivate, - &input->inhibit_deactivate); - input->keyboard_shortcuts_inhibit = wlr_keyboard_shortcuts_inhibit_v1_create(server->wl_display); input->keyboard_shortcuts_inhibit_new_inhibitor.notify = diff --git a/sway/server.c b/sway/server.c index 217c9ac94..de70e0abc 100644 --- a/sway/server.c +++ b/sway/server.c @@ -87,7 +87,6 @@ static bool is_privileged(const struct wl_global *global) { global == server.gamma_control_manager_v1->global || global == server.layer_shell->global || global == server.session_lock.manager->global || - global == server.input->inhibit->global || global == server.input->keyboard_shortcuts_inhibit->global || global == server.input->virtual_keyboard->global || global == server.input->virtual_pointer->global; From fd6d6f1d97deea2fc94aaeb58c85c99a498d905b Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 23 Nov 2023 13:08:09 +0100 Subject: [PATCH 108/114] Add wlr/util/transform.h includes References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4097 Closes: https://github.com/swaywm/sway/issues/7830 --- sway/commands/output/transform.c | 1 + sway/desktop/output.c | 1 + sway/desktop/render.c | 1 + sway/tree/root.c | 1 + 4 files changed, 4 insertions(+) diff --git a/sway/commands/output/transform.c b/sway/commands/output/transform.c index f4fcc8c99..8db71bb30 100644 --- a/sway/commands/output/transform.c +++ b/sway/commands/output/transform.c @@ -1,4 +1,5 @@ #include +#include #include "sway/commands.h" #include "sway/config.h" #include "log.h" diff --git a/sway/desktop/output.c b/sway/desktop/output.c index e02ab32d0..d9328701c 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "config.h" #include "log.h" #include "sway/config.h" diff --git a/sway/desktop/render.c b/sway/desktop/render.c index c4c0004e7..9cfdea842 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "log.h" #include "config.h" #include "sway/config.h" diff --git a/sway/tree/root.c b/sway/tree/root.c index 831c75a58..66008d30d 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "sway/desktop/transaction.h" #include "sway/input/seat.h" #include "sway/ipc-server.h" From 128b6253a924c30e8e4fd1f09ce19e21a826c5ad Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 23 Nov 2023 13:08:53 +0100 Subject: [PATCH 109/114] Pass wl_display to wlr_output_layout References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4310 --- include/sway/tree/root.h | 2 +- sway/main.c | 2 -- sway/server.c | 2 ++ sway/tree/root.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/sway/tree/root.h b/include/sway/tree/root.h index a2c088e76..b3dda12f9 100644 --- a/include/sway/tree/root.h +++ b/include/sway/tree/root.h @@ -41,7 +41,7 @@ struct sway_root { } events; }; -struct sway_root *root_create(void); +struct sway_root *root_create(struct wl_display *display); void root_destroy(struct sway_root *root); diff --git a/sway/main.c b/sway/main.c index 85bc2f1c9..23689757e 100644 --- a/sway/main.c +++ b/sway/main.c @@ -375,8 +375,6 @@ int main(int argc, char **argv) { sway_log(SWAY_INFO, "Starting sway version " SWAY_VERSION); - root = root_create(); - if (!server_init(&server)) { return 1; } diff --git a/sway/server.c b/sway/server.c index de70e0abc..e4f8a7c8c 100644 --- a/sway/server.c +++ b/sway/server.c @@ -120,6 +120,8 @@ bool server_init(struct sway_server *server) { wl_display_set_global_filter(server->wl_display, filter_global, NULL); + root = root_create(server->wl_display); + server->backend = wlr_backend_autocreate(server->wl_display, &server->session); if (!server->backend) { sway_log(SWAY_ERROR, "Unable to create backend"); diff --git a/sway/tree/root.c b/sway/tree/root.c index 66008d30d..478df00cb 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c @@ -24,14 +24,14 @@ static void output_layout_handle_change(struct wl_listener *listener, transaction_commit_dirty(); } -struct sway_root *root_create(void) { +struct sway_root *root_create(struct wl_display *wl_display) { struct sway_root *root = calloc(1, sizeof(struct sway_root)); if (!root) { sway_log(SWAY_ERROR, "Unable to allocate sway_root"); return NULL; } node_init(&root->node, N_ROOT, root); - root->output_layout = wlr_output_layout_create(); + root->output_layout = wlr_output_layout_create(wl_display); wl_list_init(&root->all_outputs); #if HAVE_XWAYLAND wl_list_init(&root->xwayland_unmanaged); From 47e6a1164c25b5b49bfb919a681b88641d2ce37c Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 11 Jul 2023 15:09:14 +0300 Subject: [PATCH 110/114] xdg-shell: chase events update --- include/sway/server.h | 4 +- include/sway/tree/view.h | 1 + include/sway/xdg_decoration.h | 2 + sway/desktop/layer_shell.c | 65 +++++++++++++------------- sway/desktop/xdg_shell.c | 87 ++++++++++++++++++++--------------- sway/server.c | 6 +-- sway/xdg_decoration.c | 77 ++++++++++++++++--------------- 7 files changed, 133 insertions(+), 109 deletions(-) diff --git a/include/sway/server.h b/include/sway/server.h index be5c8d72c..1b3166cec 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -59,7 +59,7 @@ struct sway_server { struct wl_listener layer_shell_surface; struct wlr_xdg_shell *xdg_shell; - struct wl_listener xdg_shell_surface; + struct wl_listener xdg_shell_toplevel; struct wlr_tablet_manager_v2 *tablet_v2; @@ -176,7 +176,7 @@ void handle_new_output(struct wl_listener *listener, void *data); void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data); void handle_layer_shell_surface(struct wl_listener *listener, void *data); void sway_session_lock_init(void); -void handle_xdg_shell_surface(struct wl_listener *listener, void *data); +void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data); #if HAVE_XWAYLAND void handle_xwayland_surface(struct wl_listener *listener, void *data); #endif diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 960f9d71c..856651a52 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -226,6 +226,7 @@ struct sway_xdg_popup { struct wlr_xdg_popup *wlr_xdg_popup; + struct wl_listener surface_commit; struct wl_listener new_popup; struct wl_listener destroy; }; diff --git a/include/sway/xdg_decoration.h b/include/sway/xdg_decoration.h index 8bef4c6d4..2388ebcbb 100644 --- a/include/sway/xdg_decoration.h +++ b/include/sway/xdg_decoration.h @@ -16,4 +16,6 @@ struct sway_xdg_decoration { struct sway_xdg_decoration *xdg_decoration_from_surface( struct wlr_surface *surface); +void set_xdg_decoration_mode(struct sway_xdg_decoration *deco); + #endif diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 8c6cedfe9..979c44497 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -542,36 +542,6 @@ static void popup_damage(struct sway_layer_popup *layer_popup, bool whole) { output_damage_surface(output, ox, oy, surface, whole); } -static void popup_handle_map(struct wl_listener *listener, void *data) { - struct sway_layer_popup *popup = wl_container_of(listener, popup, map); - struct sway_layer_surface *layer = popup_get_layer(popup); - struct wlr_output *wlr_output = layer->layer_surface->output; - sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); - surface_enter_output(popup->wlr_popup->base->surface, wlr_output->data); - popup_damage(popup, true); -} - -static void popup_handle_unmap(struct wl_listener *listener, void *data) { - struct sway_layer_popup *popup = wl_container_of(listener, popup, unmap); - popup_damage(popup, true); -} - -static void popup_handle_commit(struct wl_listener *listener, void *data) { - struct sway_layer_popup *popup = wl_container_of(listener, popup, commit); - popup_damage(popup, false); -} - -static void popup_handle_destroy(struct wl_listener *listener, void *data) { - struct sway_layer_popup *popup = - wl_container_of(listener, popup, destroy); - - wl_list_remove(&popup->map.link); - wl_list_remove(&popup->unmap.link); - wl_list_remove(&popup->destroy.link); - wl_list_remove(&popup->commit.link); - free(popup); -} - static void popup_unconstrain(struct sway_layer_popup *popup) { struct sway_layer_surface *layer = popup_get_layer(popup); struct wlr_xdg_popup *wlr_popup = popup->wlr_popup; @@ -592,6 +562,39 @@ static void popup_unconstrain(struct sway_layer_popup *popup) { wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); } +static void popup_handle_map(struct wl_listener *listener, void *data) { + struct sway_layer_popup *popup = wl_container_of(listener, popup, map); + struct sway_layer_surface *layer = popup_get_layer(popup); + struct wlr_output *wlr_output = layer->layer_surface->output; + sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); + surface_enter_output(popup->wlr_popup->base->surface, wlr_output->data); + popup_damage(popup, true); +} + +static void popup_handle_unmap(struct wl_listener *listener, void *data) { + struct sway_layer_popup *popup = wl_container_of(listener, popup, unmap); + popup_damage(popup, true); +} + +static void popup_handle_commit(struct wl_listener *listener, void *data) { + struct sway_layer_popup *popup = wl_container_of(listener, popup, commit); + if (popup->wlr_popup->base->initial_commit) { + popup_unconstrain(popup); + } + popup_damage(popup, false); +} + +static void popup_handle_destroy(struct wl_listener *listener, void *data) { + struct sway_layer_popup *popup = + wl_container_of(listener, popup, destroy); + + wl_list_remove(&popup->map.link); + wl_list_remove(&popup->unmap.link); + wl_list_remove(&popup->destroy.link); + wl_list_remove(&popup->commit.link); + free(popup); +} + static void popup_handle_new_popup(struct wl_listener *listener, void *data); static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup, @@ -617,8 +620,6 @@ static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup, popup->new_popup.notify = popup_handle_new_popup; wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup); - popup_unconstrain(popup); - return popup; } diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 4c59b42a2..63a0835bf 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -38,6 +38,7 @@ static void popup_destroy(struct sway_view_child *child) { return; } struct sway_xdg_popup *popup = (struct sway_xdg_popup *)child; + wl_list_remove(&popup->surface_commit.link); wl_list_remove(&popup->new_popup.link); wl_list_remove(&popup->destroy.link); free(popup); @@ -51,18 +52,6 @@ static const struct sway_view_child_impl popup_impl = { static struct sway_xdg_popup *popup_create( struct wlr_xdg_popup *wlr_popup, struct sway_view *view); -static void popup_handle_new_popup(struct wl_listener *listener, void *data) { - struct sway_xdg_popup *popup = - wl_container_of(listener, popup, new_popup); - struct wlr_xdg_popup *wlr_popup = data; - popup_create(wlr_popup, popup->child.view); -} - -static void popup_handle_destroy(struct wl_listener *listener, void *data) { - struct sway_xdg_popup *popup = wl_container_of(listener, popup, destroy); - view_child_destroy(&popup->child); -} - static void popup_unconstrain(struct sway_xdg_popup *popup) { struct sway_view *view = popup->child.view; struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_popup; @@ -87,6 +76,25 @@ static void popup_unconstrain(struct sway_xdg_popup *popup) { wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); } +static void popup_handle_surface_commit(struct wl_listener *listener, void *data) { + struct sway_xdg_popup *popup = wl_container_of(listener, popup, surface_commit); + if (popup->wlr_xdg_popup->base->initial_commit) { + popup_unconstrain(popup); + } +} + +static void popup_handle_new_popup(struct wl_listener *listener, void *data) { + struct sway_xdg_popup *popup = + wl_container_of(listener, popup, new_popup); + struct wlr_xdg_popup *wlr_popup = data; + popup_create(wlr_popup, popup->child.view); +} + +static void popup_handle_destroy(struct wl_listener *listener, void *data) { + struct sway_xdg_popup *popup = wl_container_of(listener, popup, destroy); + view_child_destroy(&popup->child); +} + static struct sway_xdg_popup *popup_create( struct wlr_xdg_popup *wlr_popup, struct sway_view *view) { struct wlr_xdg_surface *xdg_surface = wlr_popup->base; @@ -97,22 +105,21 @@ static struct sway_xdg_popup *popup_create( return NULL; } view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); - popup->wlr_xdg_popup = xdg_surface->popup; + popup->wlr_xdg_popup = wlr_popup; + wl_signal_add(&xdg_surface->surface->events.commit, &popup->surface_commit); + popup->surface_commit.notify = popup_handle_surface_commit; wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); popup->new_popup.notify = popup_handle_new_popup; - wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); + wl_signal_add(&wlr_popup->events.destroy, &popup->destroy); popup->destroy.notify = popup_handle_destroy; wl_signal_add(&xdg_surface->surface->events.map, &popup->child.surface_map); wl_signal_add(&xdg_surface->surface->events.unmap, &popup->child.surface_unmap); - popup_unconstrain(popup); - return popup; } - static struct sway_xdg_shell_view *xdg_shell_view_from_view( struct sway_view *view) { if (!sway_assert(view->type == SWAY_VIEW_XDG_SHELL, @@ -286,6 +293,19 @@ static void handle_commit(struct wl_listener *listener, void *data) { struct sway_view *view = &xdg_shell_view->view; struct wlr_xdg_surface *xdg_surface = view->wlr_xdg_toplevel->base; + if (xdg_surface->initial_commit) { + if (view->xdg_decoration != NULL) { + set_xdg_decoration_mode(view->xdg_decoration); + } + // XXX: https://github.com/swaywm/sway/issues/2176 + wlr_xdg_surface_schedule_configure(xdg_surface); + return; + } + + if (!xdg_surface->surface->mapped) { + return; + } + struct wlr_box new_geo; wlr_xdg_surface_get_geometry(xdg_surface, &new_geo); bool new_size = new_geo.width != view->geometry.width || @@ -421,7 +441,6 @@ static void handle_unmap(struct wl_listener *listener, void *data) { view_unmap(view); - wl_list_remove(&xdg_shell_view->commit.link); wl_list_remove(&xdg_shell_view->new_popup.link); wl_list_remove(&xdg_shell_view->request_maximize.link); wl_list_remove(&xdg_shell_view->request_fullscreen.link); @@ -464,10 +483,6 @@ static void handle_map(struct wl_listener *listener, void *data) { transaction_commit_dirty(); - xdg_shell_view->commit.notify = handle_commit; - wl_signal_add(&toplevel->base->surface->events.commit, - &xdg_shell_view->commit); - xdg_shell_view->new_popup.notify = handle_new_popup; wl_signal_add(&toplevel->base->events.new_popup, &xdg_shell_view->new_popup); @@ -507,6 +522,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&xdg_shell_view->destroy.link); wl_list_remove(&xdg_shell_view->map.link); wl_list_remove(&xdg_shell_view->unmap.link); + wl_list_remove(&xdg_shell_view->commit.link); view->wlr_xdg_toplevel = NULL; if (view->xdg_decoration) { view->xdg_decoration->view = NULL; @@ -519,17 +535,12 @@ struct sway_view *view_from_wlr_xdg_surface( return xdg_surface->data; } -void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { - struct wlr_xdg_surface *xdg_surface = data; - - if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { - sway_log(SWAY_DEBUG, "New xdg_shell popup"); - return; - } +void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data) { + struct wlr_xdg_toplevel *xdg_toplevel = data; sway_log(SWAY_DEBUG, "New xdg_shell toplevel title='%s' app_id='%s'", - xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); - wlr_xdg_surface_ping(xdg_surface); + xdg_toplevel->title, xdg_toplevel->app_id); + wlr_xdg_surface_ping(xdg_toplevel->base); struct sway_xdg_shell_view *xdg_shell_view = calloc(1, sizeof(struct sway_xdg_shell_view)); @@ -538,16 +549,20 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { } view_init(&xdg_shell_view->view, SWAY_VIEW_XDG_SHELL, &view_impl); - xdg_shell_view->view.wlr_xdg_toplevel = xdg_surface->toplevel; + xdg_shell_view->view.wlr_xdg_toplevel = xdg_toplevel; xdg_shell_view->map.notify = handle_map; - wl_signal_add(&xdg_surface->surface->events.map, &xdg_shell_view->map); + wl_signal_add(&xdg_toplevel->base->surface->events.map, &xdg_shell_view->map); xdg_shell_view->unmap.notify = handle_unmap; - wl_signal_add(&xdg_surface->surface->events.unmap, &xdg_shell_view->unmap); + wl_signal_add(&xdg_toplevel->base->surface->events.unmap, &xdg_shell_view->unmap); + + xdg_shell_view->commit.notify = handle_commit; + wl_signal_add(&xdg_toplevel->base->surface->events.commit, + &xdg_shell_view->commit); xdg_shell_view->destroy.notify = handle_destroy; - wl_signal_add(&xdg_surface->events.destroy, &xdg_shell_view->destroy); + wl_signal_add(&xdg_toplevel->events.destroy, &xdg_shell_view->destroy); - xdg_surface->data = xdg_shell_view; + xdg_toplevel->base->data = xdg_shell_view; } diff --git a/sway/server.c b/sway/server.c index e4f8a7c8c..be5216217 100644 --- a/sway/server.c +++ b/sway/server.c @@ -185,9 +185,9 @@ bool server_init(struct sway_server *server) { server->xdg_shell = wlr_xdg_shell_create(server->wl_display, SWAY_XDG_SHELL_VERSION); - wl_signal_add(&server->xdg_shell->events.new_surface, - &server->xdg_shell_surface); - server->xdg_shell_surface.notify = handle_xdg_shell_surface; + wl_signal_add(&server->xdg_shell->events.new_toplevel, + &server->xdg_shell_toplevel); + server->xdg_shell_toplevel.notify = handle_xdg_shell_toplevel; server->tablet_v2 = wlr_tablet_v2_create(server->wl_display); diff --git a/sway/xdg_decoration.c b/sway/xdg_decoration.c index f7f5f5ed8..fa8c6279c 100644 --- a/sway/xdg_decoration.c +++ b/sway/xdg_decoration.c @@ -23,6 +23,45 @@ static void xdg_decoration_handle_request_mode(struct wl_listener *listener, void *data) { struct sway_xdg_decoration *deco = wl_container_of(listener, deco, request_mode); + set_xdg_decoration_mode(deco); +} + +void handle_xdg_decoration(struct wl_listener *listener, void *data) { + struct wlr_xdg_toplevel_decoration_v1 *wlr_deco = data; + struct sway_xdg_shell_view *xdg_shell_view = wlr_deco->toplevel->base->data; + + struct sway_xdg_decoration *deco = calloc(1, sizeof(*deco)); + if (deco == NULL) { + return; + } + + deco->view = &xdg_shell_view->view; + deco->view->xdg_decoration = deco; + deco->wlr_xdg_decoration = wlr_deco; + + wl_signal_add(&wlr_deco->events.destroy, &deco->destroy); + deco->destroy.notify = xdg_decoration_handle_destroy; + + wl_signal_add(&wlr_deco->events.request_mode, &deco->request_mode); + deco->request_mode.notify = xdg_decoration_handle_request_mode; + + wl_list_insert(&server.xdg_decorations, &deco->link); + + set_xdg_decoration_mode(deco); +} + +struct sway_xdg_decoration *xdg_decoration_from_surface( + struct wlr_surface *surface) { + struct sway_xdg_decoration *deco; + wl_list_for_each(deco, &server.xdg_decorations, link) { + if (deco->wlr_xdg_decoration->toplevel->base->surface == surface) { + return deco; + } + } + return NULL; +} + +void set_xdg_decoration_mode(struct sway_xdg_decoration *deco) { struct sway_view *view = deco->view; enum wlr_xdg_toplevel_decoration_v1_mode mode = WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE; @@ -47,41 +86,7 @@ static void xdg_decoration_handle_request_mode(struct wl_listener *listener, mode = client_mode; } - wlr_xdg_toplevel_decoration_v1_set_mode(deco->wlr_xdg_decoration, - mode); -} - -void handle_xdg_decoration(struct wl_listener *listener, void *data) { - struct wlr_xdg_toplevel_decoration_v1 *wlr_deco = data; - struct sway_xdg_shell_view *xdg_shell_view = wlr_deco->toplevel->base->data; - - struct sway_xdg_decoration *deco = calloc(1, sizeof(*deco)); - if (deco == NULL) { - return; + if (view->wlr_xdg_toplevel->base->initialized) { + wlr_xdg_toplevel_decoration_v1_set_mode(deco->wlr_xdg_decoration, mode); } - - deco->view = &xdg_shell_view->view; - deco->view->xdg_decoration = deco; - deco->wlr_xdg_decoration = wlr_deco; - - wl_signal_add(&wlr_deco->events.destroy, &deco->destroy); - deco->destroy.notify = xdg_decoration_handle_destroy; - - wl_signal_add(&wlr_deco->events.request_mode, &deco->request_mode); - deco->request_mode.notify = xdg_decoration_handle_request_mode; - - wl_list_insert(&server.xdg_decorations, &deco->link); - - xdg_decoration_handle_request_mode(&deco->request_mode, wlr_deco); -} - -struct sway_xdg_decoration *xdg_decoration_from_surface( - struct wlr_surface *surface) { - struct sway_xdg_decoration *deco; - wl_list_for_each(deco, &server.xdg_decorations, link) { - if (deco->wlr_xdg_decoration->toplevel->base->surface == surface) { - return deco; - } - } - return NULL; } From 39b9c0d6baeda0609dfe248fc5b86fb65ff69c2c Mon Sep 17 00:00:00 2001 From: Manuel Stoeckl Date: Thu, 23 Nov 2023 07:54:23 -0500 Subject: [PATCH 111/114] common: Drop unused render_background_image And the associated background_mode enum. --- common/background-image.c | 88 +------------------------------------- include/background-image.h | 15 +------ 2 files changed, 3 insertions(+), 100 deletions(-) diff --git a/common/background-image.c b/common/background-image.c index 994a08052..d94346c8b 100644 --- a/common/background-image.c +++ b/common/background-image.c @@ -1,29 +1,12 @@ #include #include "background-image.h" -#include "cairo_util.h" +#include "config.h" #include "log.h" + #if HAVE_GDK_PIXBUF #include #endif -enum background_mode parse_background_mode(const char *mode) { - if (strcmp(mode, "stretch") == 0) { - return BACKGROUND_MODE_STRETCH; - } else if (strcmp(mode, "fill") == 0) { - return BACKGROUND_MODE_FILL; - } else if (strcmp(mode, "fit") == 0) { - return BACKGROUND_MODE_FIT; - } else if (strcmp(mode, "center") == 0) { - return BACKGROUND_MODE_CENTER; - } else if (strcmp(mode, "tile") == 0) { - return BACKGROUND_MODE_TILE; - } else if (strcmp(mode, "solid_color") == 0) { - return BACKGROUND_MODE_SOLID_COLOR; - } - sway_log(SWAY_ERROR, "Unsupported background mode: %s", mode); - return BACKGROUND_MODE_INVALID; -} - #if HAVE_GDK_PIXBUF static cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf( const GdkPixbuf *gdkbuf) { @@ -151,70 +134,3 @@ cairo_surface_t *load_background_image(const char *path) { } return image; } - -void render_background_image(cairo_t *cairo, cairo_surface_t *image, - enum background_mode mode, int buffer_width, int buffer_height) { - double width = cairo_image_surface_get_width(image); - double height = cairo_image_surface_get_height(image); - - cairo_save(cairo); - switch (mode) { - case BACKGROUND_MODE_STRETCH: - cairo_scale(cairo, - (double)buffer_width / width, - (double)buffer_height / height); - cairo_set_source_surface(cairo, image, 0, 0); - break; - case BACKGROUND_MODE_FILL: { - double window_ratio = (double)buffer_width / buffer_height; - double bg_ratio = width / height; - - if (window_ratio > bg_ratio) { - double scale = (double)buffer_width / width; - cairo_scale(cairo, scale, scale); - cairo_set_source_surface(cairo, image, - 0, (double)buffer_height / 2 / scale - height / 2); - } else { - double scale = (double)buffer_height / height; - cairo_scale(cairo, scale, scale); - cairo_set_source_surface(cairo, image, - (double)buffer_width / 2 / scale - width / 2, 0); - } - break; - } - case BACKGROUND_MODE_FIT: { - double window_ratio = (double)buffer_width / buffer_height; - double bg_ratio = width / height; - - if (window_ratio > bg_ratio) { - double scale = (double)buffer_height / height; - cairo_scale(cairo, scale, scale); - cairo_set_source_surface(cairo, image, - (double)buffer_width / 2 / scale - width / 2, 0); - } else { - double scale = (double)buffer_width / width; - cairo_scale(cairo, scale, scale); - cairo_set_source_surface(cairo, image, - 0, (double)buffer_height / 2 / scale - height / 2); - } - break; - } - case BACKGROUND_MODE_CENTER: - cairo_set_source_surface(cairo, image, - (double)buffer_width / 2 - width / 2, - (double)buffer_height / 2 - height / 2); - break; - case BACKGROUND_MODE_TILE: { - cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); - cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); - cairo_set_source(cairo, pattern); - break; - } - case BACKGROUND_MODE_SOLID_COLOR: - case BACKGROUND_MODE_INVALID: - assert(0); - break; - } - cairo_paint(cairo); - cairo_restore(cairo); -} diff --git a/include/background-image.h b/include/background-image.h index a97ef3752..5ecd4c536 100644 --- a/include/background-image.h +++ b/include/background-image.h @@ -1,20 +1,7 @@ #ifndef _SWAY_BACKGROUND_IMAGE_H #define _SWAY_BACKGROUND_IMAGE_H -#include "cairo_util.h" +#include -enum background_mode { - BACKGROUND_MODE_STRETCH, - BACKGROUND_MODE_FILL, - BACKGROUND_MODE_FIT, - BACKGROUND_MODE_CENTER, - BACKGROUND_MODE_TILE, - BACKGROUND_MODE_SOLID_COLOR, - BACKGROUND_MODE_INVALID, -}; - -enum background_mode parse_background_mode(const char *mode); cairo_surface_t *load_background_image(const char *path); -void render_background_image(cairo_t *cairo, cairo_surface_t *image, - enum background_mode mode, int buffer_width, int buffer_height); #endif From 439122e887d8d90991a06cf4877d5dd19bb21692 Mon Sep 17 00:00:00 2001 From: Manuel Stoeckl Date: Thu, 23 Nov 2023 08:01:48 -0500 Subject: [PATCH 112/114] common: rename load_background_image to load_image --- common/background-image.c | 2 +- include/background-image.h | 2 +- swaybar/tray/item.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/background-image.c b/common/background-image.c index d94346c8b..2df10dd27 100644 --- a/common/background-image.c +++ b/common/background-image.c @@ -104,7 +104,7 @@ static cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf( } #endif // HAVE_GDK_PIXBUF -cairo_surface_t *load_background_image(const char *path) { +cairo_surface_t *load_image(const char *path) { cairo_surface_t *image; #if HAVE_GDK_PIXBUF GError *err = NULL; diff --git a/include/background-image.h b/include/background-image.h index 5ecd4c536..67c27c844 100644 --- a/include/background-image.h +++ b/include/background-image.h @@ -2,6 +2,6 @@ #define _SWAY_BACKGROUND_IMAGE_H #include -cairo_surface_t *load_background_image(const char *path); +cairo_surface_t *load_image(const char *path); #endif diff --git a/swaybar/tray/item.c b/swaybar/tray/item.c index 1f18b8bb3..c7938a350 100644 --- a/swaybar/tray/item.c +++ b/swaybar/tray/item.c @@ -431,7 +431,7 @@ static void reload_sni(struct swaybar_sni *sni, char *icon_theme, list_free(icon_search_paths); if (icon_path) { cairo_surface_destroy(sni->icon); - sni->icon = load_background_image(icon_path); + sni->icon = load_image(icon_path); free(icon_path); return; } From e633fe0b4081f249e9708f95da972138c86838ca Mon Sep 17 00:00:00 2001 From: Manuel Stoeckl Date: Thu, 23 Nov 2023 08:40:41 -0500 Subject: [PATCH 113/114] common: move load_image to swaybar swaynag, swaymsg, and sway do not use this function and are unlikely to in the future. --- common/meson.build | 2 -- include/{background-image.h => swaybar/image.h} | 4 ++-- common/background-image.c => swaybar/image.c | 2 +- swaybar/meson.build | 1 + swaybar/tray/item.c | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) rename include/{background-image.h => swaybar/image.h} (53%) rename common/background-image.c => swaybar/image.c (99%) diff --git a/common/meson.build b/common/meson.build index 3756075a9..c0ce1f681 100644 --- a/common/meson.build +++ b/common/meson.build @@ -1,7 +1,6 @@ lib_sway_common = static_library( 'sway-common', files( - 'background-image.c', 'cairo.c', 'gesture.c', 'ipc-client.c', @@ -14,7 +13,6 @@ lib_sway_common = static_library( ), dependencies: [ cairo, - gdk_pixbuf, pango, pangocairo, wayland_client.partial_dependency(compile_args: true) diff --git a/include/background-image.h b/include/swaybar/image.h similarity index 53% rename from include/background-image.h rename to include/swaybar/image.h index 67c27c844..53a210dd7 100644 --- a/include/background-image.h +++ b/include/swaybar/image.h @@ -1,5 +1,5 @@ -#ifndef _SWAY_BACKGROUND_IMAGE_H -#define _SWAY_BACKGROUND_IMAGE_H +#ifndef _SWAYBAR_IMAGE_H +#define _SWAYBAR_IMAGE_H #include cairo_surface_t *load_image(const char *path); diff --git a/common/background-image.c b/swaybar/image.c similarity index 99% rename from common/background-image.c rename to swaybar/image.c index 2df10dd27..ed24b9f99 100644 --- a/common/background-image.c +++ b/swaybar/image.c @@ -1,7 +1,7 @@ #include -#include "background-image.h" #include "config.h" #include "log.h" +#include "swaybar/image.h" #if HAVE_GDK_PIXBUF #include diff --git a/swaybar/meson.build b/swaybar/meson.build index e5f1811eb..34bbdeea9 100644 --- a/swaybar/meson.build +++ b/swaybar/meson.build @@ -26,6 +26,7 @@ executable( 'bar.c', 'config.c', 'i3bar.c', + 'image.c', 'input.c', 'ipc.c', 'main.c', diff --git a/swaybar/tray/item.c b/swaybar/tray/item.c index c7938a350..d5fe50b15 100644 --- a/swaybar/tray/item.c +++ b/swaybar/tray/item.c @@ -7,12 +7,12 @@ #include #include "swaybar/bar.h" #include "swaybar/config.h" +#include "swaybar/image.h" #include "swaybar/input.h" #include "swaybar/tray/host.h" #include "swaybar/tray/icon.h" #include "swaybar/tray/item.h" #include "swaybar/tray/tray.h" -#include "background-image.h" #include "cairo_util.h" #include "list.h" #include "log.h" From bc7d15d64da1d8b97d52928b8f9ce5688c8dbdd0 Mon Sep 17 00:00:00 2001 From: apreiml Date: Fri, 24 Nov 2023 09:54:43 +0100 Subject: [PATCH 114/114] Update README.de.md to match the EN one --- README.de.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.de.md b/README.de.md index e2a1e8781..68b411d95 100644 --- a/README.de.md +++ b/README.de.md @@ -2,13 +2,13 @@ Sway ist ein [i3](https://i3wm.org/)-kompatibler [Wayland](http://wayland.freedesktop.org/)-Compositor. Lies die [FAQ](https://github.com/swaywm/sway/wiki). Tritt dem [IRC Channel](https://web.libera.chat/gamja/?channels=#sway) bei (#sway on irc.libera.chat; Englisch). ## Signaturen -Jedes Release wird mit dem PGP-Schlüssel [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) signiert und auf GitHub veröffentlicht. +Jedes Release wird mit dem PGP-Schlüssel [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) signiert und [auf GitHub](https://github.com/swaywm/sway/releases) veröffentlicht. ## Installation -### Mit der Paketverwaltung -Sway kann in vielen Distributionen direkt durch die Paketverwaltung installiert werden. Das Paket sollte "sway" heißen. Falls es kein solches Paket gibt, kannst du im [Wiki](https://github.com/swaywm/sway/wiki/Unsupported-packages) (englisch) nach mehr Informationen bezüglich deiner Distribution suchen. -Falls du sway für deine eigene Distribution als Paket bereitstellen möchtest, solltest du die Entwickler per IRC oder E-Mail (sir@cmpwn.com) kontaktieren. +### Über die Paketverwaltung + +Sway kann in vielen Distributionen direkt durch die Paketverwaltung installiert werden. Versuche einfach das Packet "sway" zu installieren. ### Quellcode selbst kompilieren @@ -23,8 +23,8 @@ sway benötigt die folgenden Pakete: * pango * cairo * gdk-pixbuf2 (Optional, wird für das Benachrichtigungsfeld (System Tray) benötigt) -* [scdoc](https://git.sr.ht/~sircmpwn/scdoc)\* (Optional, wird für die Dokumentation (Man Pages) benötigt) -* git\* +* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (Optional, wird für die Dokumentation (Man Pages) benötigt)\* +* git (Optional: Versionsinfo)\* _\*Werden nur während des Kompilierens benötigt_