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 1/9] 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 2/9] 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 3/9] 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 4/9] 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 5/9] 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 6/9] 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 7/9] 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 8/9] 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 9/9] 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);