From ebeed7e303110403cc0134a1927008998caa8d96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanislav=20Ochotnick=C3=BD?= Date: Mon, 6 Feb 2023 15:58:29 +0100 Subject: [PATCH 01/29] man: add warning for hide_cursor configuration See https://github.com/swaywm/sway/issues/6297 --- sway/sway-input.5.scd | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index 91c978d6..7f51b866 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd @@ -251,6 +251,10 @@ correct seat. If _when-typing_ is enabled, then the cursor will be hidden whenever a key is pressed. + Be aware that this setting can interfere with input handling in games and + certain types of software (Gimp, Blender etc) that rely on simultaneous + input from mouse and keyboard. + *seat* idle_inhibit Sets the set of input event sources which can prevent the seat from becoming idle, as a space separated list of source names. Valid names are From 90c2d631e2dc4c7633bb8fcd92f300a4a2dffb86 Mon Sep 17 00:00:00 2001 From: Ankit Pandey Date: Sun, 11 Dec 2022 16:44:48 -0800 Subject: [PATCH 02/29] root: Try to preserve relative positions of floating containers This makes the behavior of floating containers more consistent with i3. The coordinates of the container are scaled when the size of the workspace it is on changes or when the container is moved between workspaces on different outputs. For scratchpad containers, add a new state that preserves the dimensions of the last output the window appeared on. This is necessary because after a container is hidden in the scratchpad, we expect it to be in the same relative position on the output when it reappears. We can't just use the container's attached workspace because that workspace's dimensions might have been changed or the workspace as a whole could have been destroyed. --- include/sway/tree/container.h | 8 ++++++++ sway/commands/move.c | 12 ++++++++++-- sway/tree/arrange.c | 14 +++++++++----- sway/tree/container.c | 22 ++++++++++++++++++++++ sway/tree/root.c | 27 +++++++++++++++++++-------- 5 files changed, 68 insertions(+), 15 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 751612e2..fe3ee8a8 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -113,6 +113,11 @@ struct sway_container { // Hidden scratchpad containers have a NULL parent. bool scratchpad; + // Stores last output size and position for adjusting coordinates of + // scratchpad windows. + // Unused for non-scratchpad windows. + struct wlr_box transform; + float alpha; struct wlr_texture *title_focused; @@ -196,6 +201,9 @@ size_t container_titlebar_height(void); void floating_calculate_constraints(int *min_width, int *max_width, int *min_height, int *max_height); +void floating_fix_coordinates(struct sway_container *con, + struct wlr_box *old, struct wlr_box *new); + void container_floating_resize_and_center(struct sway_container *con); void container_floating_set_default_size(struct sway_container *con); diff --git a/sway/commands/move.c b/sway/commands/move.c index 7bd1fe3e..9e40a3b4 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -206,9 +206,17 @@ static void container_move_to_workspace(struct sway_container *container, container_detach(container); workspace_add_floating(workspace, container); container_handle_fullscreen_reparent(container); - // If changing output, center it within the workspace + // If changing output, adjust the coordinates of the window. if (old_output != workspace->output && !container->pending.fullscreen_mode) { - container_floating_move_to_center(container); + struct wlr_box workspace_box, old_workspace_box; + workspace_get_box(workspace, &workspace_box); + workspace_get_box(old_workspace, &old_workspace_box); + floating_fix_coordinates(container, &old_workspace_box, &workspace_box); + if (container->scratchpad && workspace->output) { + struct wlr_box output_box; + output_get_box(workspace->output, &output_box); + container->transform = workspace_box; + } } } else { container_detach(container); diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c index 9c1a11e5..af925d05 100644 --- a/sway/tree/arrange.c +++ b/sway/tree/arrange.c @@ -264,6 +264,9 @@ void arrange_workspace(struct sway_workspace *workspace) { area->width, area->height, area->x, area->y); bool first_arrange = workspace->width == 0 && workspace->height == 0; + struct wlr_box prev_box; + workspace_get_box(workspace, &prev_box); + double prev_x = workspace->x - workspace->current_gaps.left; double prev_y = workspace->y - workspace->current_gaps.top; workspace->width = area->width; @@ -277,13 +280,14 @@ void arrange_workspace(struct sway_workspace *workspace) { if (!first_arrange && (diff_x != 0 || diff_y != 0)) { for (int i = 0; i < workspace->floating->length; ++i) { struct sway_container *floater = workspace->floating->items[i]; - container_floating_translate(floater, diff_x, diff_y); - double center_x = floater->pending.x + floater->pending.width / 2; - double center_y = floater->pending.y + floater->pending.height / 2; struct wlr_box workspace_box; workspace_get_box(workspace, &workspace_box); - if (!wlr_box_contains_point(&workspace_box, center_x, center_y)) { - container_floating_move_to_center(floater); + floating_fix_coordinates(floater, &prev_box, &workspace_box); + // Set transformation for scratchpad windows. + if (floater->scratchpad) { + struct wlr_box output_box; + output_get_box(output, &output_box); + floater->transform = output_box; } } } diff --git a/sway/tree/container.c b/sway/tree/container.c index 8222a506..d2c4ffc4 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -712,6 +712,21 @@ void floating_calculate_constraints(int *min_width, int *max_width, } +void floating_fix_coordinates(struct sway_container *con, struct wlr_box *old, struct wlr_box *new) { + if (!old->width || !old->height) { + // Fall back to centering on the workspace. + container_floating_move_to_center(con); + } else { + int rel_x = con->pending.x - old->x + (con->pending.width / 2); + int rel_y = con->pending.y - old->y + (con->pending.height / 2); + + con->pending.x = new->x + (double)(rel_x * new->width) / old->width - (con->pending.width / 2); + con->pending.y = new->y + (double)(rel_y * new->height) / old->height - (con->pending.height / 2); + + sway_log(SWAY_DEBUG, "Transformed container %p to coords (%f, %f)", con, con->pending.x, con->pending.y); + } +} + static void floating_natural_resize(struct sway_container *con) { int min_width, max_width, min_height, max_height; floating_calculate_constraints(&min_width, &max_width, @@ -1025,6 +1040,13 @@ void container_floating_move_to(struct sway_container *con, workspace_add_floating(new_workspace, con); arrange_workspace(old_workspace); arrange_workspace(new_workspace); + // If the moved container was a visible scratchpad container, then + // update its transform. + if (con->scratchpad) { + struct wlr_box output_box; + output_get_box(new_output, &output_box); + con->transform = output_box; + } workspace_detect_urgent(old_workspace); workspace_detect_urgent(new_workspace); } diff --git a/sway/tree/root.c b/sway/tree/root.c index 95129a88..233358d2 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c @@ -56,6 +56,16 @@ void root_destroy(struct sway_root *root) { free(root); } +static void set_container_transform(struct sway_workspace *ws, + struct sway_container *con) { + struct sway_output *output = ws->output; + struct wlr_box box = {0}; + if (output) { + output_get_box(output, &box); + } + con->transform = box; +} + void root_scratchpad_add_container(struct sway_container *con, struct sway_workspace *ws) { if (!sway_assert(!con->scratchpad, "Container is already in scratchpad")) { return; @@ -64,6 +74,8 @@ void root_scratchpad_add_container(struct sway_container *con, struct sway_works struct sway_container *parent = con->pending.parent; struct sway_workspace *workspace = con->pending.workspace; + set_container_transform(workspace, con); + // Clear the fullscreen mode when sending to the scratchpad if (con->pending.fullscreen_mode != FULLSCREEN_NONE) { container_fullscreen_disable(con); @@ -142,15 +154,12 @@ void root_scratchpad_show(struct sway_container *con) { } workspace_add_floating(new_ws, con); - // Make sure the container's center point overlaps this workspace - double center_lx = con->pending.x + con->pending.width / 2; - double center_ly = con->pending.y + con->pending.height / 2; - - struct wlr_box workspace_box; - workspace_get_box(new_ws, &workspace_box); - if (!wlr_box_contains_point(&workspace_box, center_lx, center_ly)) { - container_floating_resize_and_center(con); + if (new_ws->output) { + struct wlr_box output_box; + output_get_box(new_ws->output, &output_box); + floating_fix_coordinates(con, &con->transform, &output_box); } + set_container_transform(new_ws, con); arrange_workspace(new_ws); seat_set_focus(seat, seat_get_focus_inactive(seat, &con->node)); @@ -173,6 +182,8 @@ void root_scratchpad_hide(struct sway_container *con) { return; } + set_container_transform(con->pending.workspace, con); + disable_fullscreen(con, NULL); container_for_each_child(con, disable_fullscreen, NULL); container_detach(con); From f21090f97870af2592f801fef316984200aa6678 Mon Sep 17 00:00:00 2001 From: Ankit Pandey Date: Sat, 18 Mar 2023 04:58:53 -0700 Subject: [PATCH 03/29] root: Set inactive focus when scratchpad is moved to new workspace Fixes an issue where an already visible scratchpad window being moved due to 'scratchpad show' leaves the entire workspace at the top of the focus stack in the old workspace. Moving by 'focus output' back to the old workspace would focus the entire workspace instead of just the last active container. --- sway/tree/root.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sway/tree/root.c b/sway/tree/root.c index 233358d2..831c75a5 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c @@ -145,7 +145,10 @@ void root_scratchpad_show(struct sway_container *con) { // Show the container if (old_ws) { container_detach(con); - workspace_consider_destroy(old_ws); + // Make sure the last inactive container on the old workspace is above + // the workspace itself in the focus stack. + struct sway_node *node = seat_get_focus_inactive(seat, &old_ws->node); + seat_set_raw_focus(seat, node); } else { // Act on the ancestor of scratchpad hidden split containers while (con->pending.parent) { @@ -163,6 +166,9 @@ void root_scratchpad_show(struct sway_container *con) { arrange_workspace(new_ws); seat_set_focus(seat, seat_get_focus_inactive(seat, &con->node)); + if (old_ws) { + workspace_consider_destroy(old_ws); + } } static void disable_fullscreen(struct sway_container *con, void *data) { From ac1ed638e991c9f5639176ce4ee07059b4f2e1ce Mon Sep 17 00:00:00 2001 From: Erik Reider <35975961+ErikReider@users.noreply.github.com> Date: Sun, 26 Mar 2023 15:47:26 +0200 Subject: [PATCH 04/29] Init the damage_ring bounds on output creation Otherwise the initial bounds would be `INT_MAX` until `handle_mode` or `handle_commit` is called :) --- sway/desktop/output.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 0c8a5fd4..09fc6462 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -999,6 +999,9 @@ 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; From 4f6e559dec071acbb5e104ed2e383439e8b23779 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 17 Mar 2023 22:24:37 +0100 Subject: [PATCH 05/29] man: deprecate seat cursor move/set/press/release The Wayland protocol better serves this purpose, and is supported by more compositors. --- sway/sway-input.5.scd | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index 7f51b866..1662d55a 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd @@ -228,6 +228,8 @@ correct seat. absolute coordinates (with respect to the global coordinate space). Specifying either value as 0 will not update that coordinate. + Deprecated: use the virtual-pointer Wayland protocol instead. + *seat* cursor press|release button[1-9]| Simulate pressing (or releasing) the specified mouse button on the specified seat. The button can either be provided as a button event name or @@ -236,6 +238,8 @@ correct seat. event will be simulated, however _press_ and _release_ will be ignored and both will occur. + Deprecated: use the virtual-pointer Wayland protocol instead. + *seat* fallback true|false Set this seat as the fallback seat. A fallback seat will attach any device not explicitly attached to another seat (similar to a "default" seat). From 6701b90c556f506784c4dfc23da08ae63d02e67a Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Tue, 7 Mar 2023 00:41:55 -0700 Subject: [PATCH 06/29] Add a .mailmap file --- .mailmap | 1 + 1 file changed, 1 insertion(+) create mode 100644 .mailmap diff --git a/.mailmap b/.mailmap new file mode 100644 index 00000000..35ee25b0 --- /dev/null +++ b/.mailmap @@ -0,0 +1 @@ +Ronan Pigott From dee032d0a0ecd958c902b88302dc59703d703c7f Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 26 Mar 2023 23:27:40 +0200 Subject: [PATCH 07/29] ipc: add LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM entry This was introduced in the last libinput release. Fixes the following error: ../sway/ipc-json.c:928:17: error: enumeration value 'LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM' not handled in switch [-Werror=switch] 928 | switch (libinput_device_config_accel_get_profile(device)) { | ^~~~~~ --- meson.build | 5 +++++ sway/ipc-json.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/meson.build b/meson.build index 84e7c6c5..d1fbfa38 100644 --- a/meson.build +++ b/meson.build @@ -117,6 +117,11 @@ conf_data.set10('HAVE_LIBSYSTEMD', sdbus.found() and sdbus.name() == 'libsystemd conf_data.set10('HAVE_LIBELOGIND', sdbus.found() and sdbus.name() == 'libelogind') conf_data.set10('HAVE_BASU', sdbus.found() and sdbus.name() == 'basu') conf_data.set10('HAVE_TRAY', have_tray) +conf_data.set10('HAVE_LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM', cc.has_header_symbol( + 'libinput.h', + 'LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM', + dependencies: libinput, +)) scdoc = dependency('scdoc', version: '>=1.9.2', native: true, required: get_option('man-pages')) if scdoc.found() diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 51e6a995..c7cbea01 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -935,6 +935,11 @@ static json_object *describe_libinput_device(struct libinput_device *device) { case LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE: accel_profile = "adaptive"; break; +#if HAVE_LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM + case LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM: + accel_profile = "custom"; + break; +#endif } json_object_object_add(object, "accel_profile", json_object_new_string(accel_profile)); From 5d5b21dcce0fa6416a7639a6cc0e3edf4311b0cf Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 27 Mar 2023 05:54:13 +0200 Subject: [PATCH 08/29] swaybar: Set opaque region properly The opaque region is set incorrectly if updated on-the-fly if switching from an opaque to a non opaque background. --- swaybar/render.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/swaybar/render.c b/swaybar/render.c index 6a983e97..a296112a 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -841,6 +841,8 @@ void render_frame(struct swaybar_output *output) { wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX); wl_surface_set_opaque_region(output->surface, region); wl_region_destroy(region); + } else { + wl_surface_set_opaque_region(output->surface, NULL); } struct wl_callback *frame_callback = wl_surface_frame(output->surface); From 9cf66e8c7cfc06680a1af055bafd7e5cc01d6fe2 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 27 Mar 2023 08:50:44 +0200 Subject: [PATCH 09/29] swaybar: Lift background clearing out of main rendering function This avoids us from using a bogus background_color value that mutates as swaybar renders things and deciding opacity depending on that. Also remove a redundant full surface clear. Just directly write our desired background color. --- swaybar/render.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/swaybar/render.c b/swaybar/render.c index a296112a..1113ca44 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -693,15 +693,6 @@ static uint32_t render_to_cairo(struct render_context *ctx) { struct swaybar_output *output = ctx->output; struct swaybar *bar = output->bar; struct swaybar_config *config = bar->config; - cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); - if (output->focused) { - ctx->background_color = config->colors.focused_background; - } else { - ctx->background_color = config->colors.background; - } - - cairo_set_source_u32(cairo, ctx->background_color); - cairo_paint(cairo); int th; get_text_size(cairo, config->font_description, NULL, &th, NULL, 1, false, ""); @@ -763,8 +754,17 @@ void render_frame(struct swaybar_output *output) { free_hotspots(&output->hotspots); + uint32_t background_color; + if (output->focused) { + background_color = output->bar->config->colors.focused_background; + } else { + background_color = output->bar->config->colors.background; + } + struct render_context ctx = { 0 }; ctx.output = output; + // initial background color used for deciding the best way to antialias text + ctx.background_color = background_color; cairo_surface_t *recorder = cairo_recording_surface_create( CAIRO_CONTENT_COLOR_ALPHA, NULL); @@ -786,10 +786,11 @@ void render_frame(struct swaybar_output *output) { ctx.textaa_sharp = fo; } - cairo_save(cairo); - cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); + + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); + cairo_set_source_u32(cairo, background_color); cairo_paint(cairo); - cairo_restore(cairo); + uint32_t height = render_to_cairo(&ctx); int config_height = output->bar->config->height; if (config_height > 0) { @@ -834,7 +835,7 @@ void render_frame(struct swaybar_output *output) { wl_surface_damage(output->surface, 0, 0, output->width, output->height); - uint32_t bg_alpha = ctx.background_color & 0xFF; + uint32_t bg_alpha = background_color & 0xFF; if (bg_alpha == 0xFF) { struct wl_region *region = wl_compositor_create_region(output->bar->compositor); 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 10/29] 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 09fc6462..43cd70d0 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 11/29] 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 43cd70d0..5671ac59 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 12/29] 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 5671ac59..59319f62 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 13/29] 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 244c7aec..0cf767b7 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 14/29] 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 59319f62..91a5936a 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 15/29] 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 91a5936a..17bce123 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 16/29] 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 c8a2cfc1..500a497d 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 b666da1e..00a7e38a 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 17/29] 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 17bce123..fe3cdaf1 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 18/29] 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 3b524433..352d7f7c 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 19/29] 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 2aa1b278..04202976 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 352d7f7c..45d2441b 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 fe3cdaf1..2255b551 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 20/29] 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 ee940466..18218768 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 21/29] 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 7fb3fe12..c503143a 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 b29f59b2..19a50f23 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 22/29] 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 1db113c2..228e39cf 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 d1fbfa38..559ee962 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 23/29] 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 3a1d606a..1c28c536 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 24/29] 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 fc6ce22e..3212c2cf 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 28e9d8d2..0ea44129 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 976bc3cc..f7d911f7 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 b4b5bc45..8a837e3f 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 243834ba..3dc9bc4c 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 c0b383db..979e178f 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 1c28c536..e8c24ace 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 ee9f4647..905e6776 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 9a1d8445..43bd6dc8 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 284b57d0..ad535db2 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 6b331419..81f69a6d 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 2ba61b38..12ce4839 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 9e40a3b4..69ed06c0 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 2001e04f..ccfdec82 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 60a66d58..0d36cc21 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 425069de..e69e5506 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 504a9f5e..5a8a3bc8 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 b457f121..d44eb006 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 a6a0beda..03e488ba 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 25/29] 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 8415627b..aa58da53 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 26/29] 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 74d9ea18..03bd52c3 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 27/29] 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 8c2efe99..58170443 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 28/29] 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 e04bf80f..288569b3 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 0ea44129..55eda183 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 8571d282..22756acb 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 f5efa98a..8c8c148d 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 45d2441b..6fb29ded 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 15687993..75d055cd 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 ea2cc038..1115ba5e 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 45a588ec..c3bf4fbb 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 4a0a6d30..6031174d 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 ddf2416d..eea2caa5 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 c426c3d4..b513dca5 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 16afc27c..551e1d12 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 29/29] 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 8da922d5..9b6456da 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