From 788118f1944ca23a7f9a7d19537b7756f3518f55 Mon Sep 17 00:00:00 2001 From: Daniel Hill <daniel@gluo.nz> Date: Fri, 17 Feb 2023 20:06:01 +1300 Subject: [PATCH 01/14] Fix map_to_output * turning off device Signed-off-by: Daniel Hill <daniel@gluo.nz> --- sway/input/libinput.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sway/input/libinput.c b/sway/input/libinput.c index 10bd0e35a..dd4fc0be9 100644 --- a/sway/input/libinput.c +++ b/sway/input/libinput.c @@ -220,7 +220,8 @@ bool sway_input_configure_libinput_device(struct sway_input_device *input_device bool changed = false; if (ic->mapped_to_output && - !output_by_name_or_id(ic->mapped_to_output)) { + strcmp("*", ic->mapped_to_output) != 0 && + !output_by_name_or_id(ic->mapped_to_output)) { sway_log(SWAY_DEBUG, "%s '%s' is mapped to offline output '%s'; disabling input", ic->input_type, ic->identifier, ic->mapped_to_output); From 633d409b8897aec48ad1e328cb04261faa2b1a0b Mon Sep 17 00:00:00 2001 From: Ronan Pigott <ronan@rjp.ie> Date: Sun, 19 Feb 2023 17:22:37 -0700 Subject: [PATCH 02/14] container: rehome the container_swap function into container.c This function was already declared in container.h but defined in commands/swap.c for some unknown reason. Everything in commands/ assumes the handler context has been set appropriately by the command preludes but this function snuck its way into seatop_* which doesn't set anything in the handler context. The fact that the seatop drag actions manipulate the focus without custody of the seat means they are definitely very broken in multiseat. --- sway/commands/swap.c | 175 +----------------------------------------- sway/tree/container.c | 174 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+), 174 deletions(-) diff --git a/sway/commands/swap.c b/sway/commands/swap.c index 9355944d9..b457f121c 100644 --- a/sway/commands/swap.c +++ b/sway/commands/swap.c @@ -5,6 +5,7 @@ #include "sway/commands.h" #include "sway/output.h" #include "sway/tree/arrange.h" +#include "sway/tree/container.h" #include "sway/tree/root.h" #include "sway/tree/view.h" #include "sway/tree/workspace.h" @@ -13,180 +14,6 @@ static const char expected_syntax[] = "Expected 'swap container with id|con_id|mark <arg>'"; -static void swap_places(struct sway_container *con1, - struct sway_container *con2) { - struct sway_container *temp = malloc(sizeof(struct sway_container)); - temp->pending.x = con1->pending.x; - temp->pending.y = con1->pending.y; - temp->pending.width = con1->pending.width; - temp->pending.height = con1->pending.height; - temp->width_fraction = con1->width_fraction; - temp->height_fraction = con1->height_fraction; - temp->pending.parent = con1->pending.parent; - temp->pending.workspace = con1->pending.workspace; - bool temp_floating = container_is_floating(con1); - - con1->pending.x = con2->pending.x; - con1->pending.y = con2->pending.y; - con1->pending.width = con2->pending.width; - con1->pending.height = con2->pending.height; - con1->width_fraction = con2->width_fraction; - con1->height_fraction = con2->height_fraction; - - con2->pending.x = temp->pending.x; - con2->pending.y = temp->pending.y; - con2->pending.width = temp->pending.width; - con2->pending.height = temp->pending.height; - con2->width_fraction = temp->width_fraction; - con2->height_fraction = temp->height_fraction; - - int temp_index = container_sibling_index(con1); - if (con2->pending.parent) { - container_insert_child(con2->pending.parent, con1, - container_sibling_index(con2)); - } else if (container_is_floating(con2)) { - workspace_add_floating(con2->pending.workspace, con1); - } else { - workspace_insert_tiling(con2->pending.workspace, con1, - container_sibling_index(con2)); - } - if (temp->pending.parent) { - container_insert_child(temp->pending.parent, con2, temp_index); - } else if (temp_floating) { - workspace_add_floating(temp->pending.workspace, con2); - } else { - workspace_insert_tiling(temp->pending.workspace, con2, temp_index); - } - - free(temp); -} - -static void swap_focus(struct sway_container *con1, - struct sway_container *con2, struct sway_seat *seat, - struct sway_container *focus) { - if (focus == con1 || focus == con2) { - struct sway_workspace *ws1 = con1->pending.workspace; - struct sway_workspace *ws2 = con2->pending.workspace; - enum sway_container_layout layout1 = container_parent_layout(con1); - enum sway_container_layout layout2 = container_parent_layout(con2); - if (focus == con1 && (layout2 == L_TABBED || layout2 == L_STACKED)) { - if (workspace_is_visible(ws2)) { - seat_set_focus(seat, &con2->node); - } - seat_set_focus_container(seat, ws1 != ws2 ? con2 : con1); - } else if (focus == con2 && (layout1 == L_TABBED - || layout1 == L_STACKED)) { - if (workspace_is_visible(ws1)) { - seat_set_focus(seat, &con1->node); - } - seat_set_focus_container(seat, ws1 != ws2 ? con1 : con2); - } else if (ws1 != ws2) { - seat_set_focus_container(seat, focus == con1 ? con2 : con1); - } else { - seat_set_focus_container(seat, focus); - } - } else { - seat_set_focus_container(seat, focus); - } - - if (root->fullscreen_global) { - seat_set_focus(seat, - seat_get_focus_inactive(seat, &root->fullscreen_global->node)); - } -} - -void container_swap(struct sway_container *con1, struct sway_container *con2) { - if (!sway_assert(con1 && con2, "Cannot swap with nothing")) { - return; - } - if (!sway_assert(!container_has_ancestor(con1, con2) - && !container_has_ancestor(con2, con1), - "Cannot swap ancestor and descendant")) { - return; - } - - sway_log(SWAY_DEBUG, "Swapping containers %zu and %zu", - con1->node.id, con2->node.id); - - bool scratch1 = con1->scratchpad; - bool hidden1 = container_is_scratchpad_hidden(con1); - bool scratch2 = con2->scratchpad; - bool hidden2 = container_is_scratchpad_hidden(con2); - if (scratch1) { - if (hidden1) { - root_scratchpad_show(con1); - } - root_scratchpad_remove_container(con1); - } - if (scratch2) { - if (hidden2) { - root_scratchpad_show(con2); - } - root_scratchpad_remove_container(con2); - } - - enum sway_fullscreen_mode fs1 = con1->pending.fullscreen_mode; - if (fs1) { - container_fullscreen_disable(con1); - } - enum sway_fullscreen_mode fs2 = con2->pending.fullscreen_mode; - if (fs2) { - container_fullscreen_disable(con2); - } - - struct sway_seat *seat = config->handler_context.seat; - struct sway_container *focus = seat_get_focused_container(seat); - struct sway_workspace *vis1 = - output_get_active_workspace(con1->pending.workspace->output); - struct sway_workspace *vis2 = - output_get_active_workspace(con2->pending.workspace->output); - if (!sway_assert(vis1 && vis2, "con1 or con2 are on an output without a" - "workspace. This should not happen")) { - return; - } - - char *stored_prev_name = NULL; - if (seat->prev_workspace_name) { - stored_prev_name = strdup(seat->prev_workspace_name); - } - - swap_places(con1, con2); - - if (!workspace_is_visible(vis1)) { - seat_set_focus(seat, seat_get_focus_inactive(seat, &vis1->node)); - } - if (!workspace_is_visible(vis2)) { - seat_set_focus(seat, seat_get_focus_inactive(seat, &vis2->node)); - } - - swap_focus(con1, con2, seat, focus); - - if (stored_prev_name) { - free(seat->prev_workspace_name); - seat->prev_workspace_name = stored_prev_name; - } - - if (scratch1) { - root_scratchpad_add_container(con2, NULL); - if (!hidden1) { - root_scratchpad_show(con2); - } - } - if (scratch2) { - root_scratchpad_add_container(con1, NULL); - if (!hidden2) { - root_scratchpad_show(con1); - } - } - - if (fs1) { - container_set_fullscreen(con2, fs1); - } - if (fs2) { - container_set_fullscreen(con1, fs2); - } -} - static bool test_con_id(struct sway_container *container, void *data) { size_t *con_id = data; return container->node.id == *con_id; diff --git a/sway/tree/container.c b/sway/tree/container.c index 207010814..335dae87c 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -1764,3 +1764,177 @@ int container_squash(struct sway_container *con) { } return change; } + +static void swap_places(struct sway_container *con1, + struct sway_container *con2) { + struct sway_container *temp = malloc(sizeof(struct sway_container)); + temp->pending.x = con1->pending.x; + temp->pending.y = con1->pending.y; + temp->pending.width = con1->pending.width; + temp->pending.height = con1->pending.height; + temp->width_fraction = con1->width_fraction; + temp->height_fraction = con1->height_fraction; + temp->pending.parent = con1->pending.parent; + temp->pending.workspace = con1->pending.workspace; + bool temp_floating = container_is_floating(con1); + + con1->pending.x = con2->pending.x; + con1->pending.y = con2->pending.y; + con1->pending.width = con2->pending.width; + con1->pending.height = con2->pending.height; + con1->width_fraction = con2->width_fraction; + con1->height_fraction = con2->height_fraction; + + con2->pending.x = temp->pending.x; + con2->pending.y = temp->pending.y; + con2->pending.width = temp->pending.width; + con2->pending.height = temp->pending.height; + con2->width_fraction = temp->width_fraction; + con2->height_fraction = temp->height_fraction; + + int temp_index = container_sibling_index(con1); + if (con2->pending.parent) { + container_insert_child(con2->pending.parent, con1, + container_sibling_index(con2)); + } else if (container_is_floating(con2)) { + workspace_add_floating(con2->pending.workspace, con1); + } else { + workspace_insert_tiling(con2->pending.workspace, con1, + container_sibling_index(con2)); + } + if (temp->pending.parent) { + container_insert_child(temp->pending.parent, con2, temp_index); + } else if (temp_floating) { + workspace_add_floating(temp->pending.workspace, con2); + } else { + workspace_insert_tiling(temp->pending.workspace, con2, temp_index); + } + + free(temp); +} + +static void swap_focus(struct sway_container *con1, + struct sway_container *con2, struct sway_seat *seat, + struct sway_container *focus) { + if (focus == con1 || focus == con2) { + struct sway_workspace *ws1 = con1->pending.workspace; + struct sway_workspace *ws2 = con2->pending.workspace; + enum sway_container_layout layout1 = container_parent_layout(con1); + enum sway_container_layout layout2 = container_parent_layout(con2); + if (focus == con1 && (layout2 == L_TABBED || layout2 == L_STACKED)) { + if (workspace_is_visible(ws2)) { + seat_set_focus(seat, &con2->node); + } + seat_set_focus_container(seat, ws1 != ws2 ? con2 : con1); + } else if (focus == con2 && (layout1 == L_TABBED + || layout1 == L_STACKED)) { + if (workspace_is_visible(ws1)) { + seat_set_focus(seat, &con1->node); + } + seat_set_focus_container(seat, ws1 != ws2 ? con1 : con2); + } else if (ws1 != ws2) { + seat_set_focus_container(seat, focus == con1 ? con2 : con1); + } else { + seat_set_focus_container(seat, focus); + } + } else { + seat_set_focus_container(seat, focus); + } + + if (root->fullscreen_global) { + seat_set_focus(seat, + seat_get_focus_inactive(seat, &root->fullscreen_global->node)); + } +} + +void container_swap(struct sway_container *con1, struct sway_container *con2) { + if (!sway_assert(con1 && con2, "Cannot swap with nothing")) { + return; + } + if (!sway_assert(!container_has_ancestor(con1, con2) + && !container_has_ancestor(con2, con1), + "Cannot swap ancestor and descendant")) { + return; + } + + sway_log(SWAY_DEBUG, "Swapping containers %zu and %zu", + con1->node.id, con2->node.id); + + bool scratch1 = con1->scratchpad; + bool hidden1 = container_is_scratchpad_hidden(con1); + bool scratch2 = con2->scratchpad; + bool hidden2 = container_is_scratchpad_hidden(con2); + if (scratch1) { + if (hidden1) { + root_scratchpad_show(con1); + } + root_scratchpad_remove_container(con1); + } + if (scratch2) { + if (hidden2) { + root_scratchpad_show(con2); + } + root_scratchpad_remove_container(con2); + } + + enum sway_fullscreen_mode fs1 = con1->pending.fullscreen_mode; + if (fs1) { + container_fullscreen_disable(con1); + } + enum sway_fullscreen_mode fs2 = con2->pending.fullscreen_mode; + if (fs2) { + container_fullscreen_disable(con2); + } + + struct sway_seat *seat = input_manager_current_seat(); + struct sway_container *focus = seat_get_focused_container(seat); + struct sway_workspace *vis1 = + output_get_active_workspace(con1->pending.workspace->output); + struct sway_workspace *vis2 = + output_get_active_workspace(con2->pending.workspace->output); + if (!sway_assert(vis1 && vis2, "con1 or con2 are on an output without a" + "workspace. This should not happen")) { + return; + } + + char *stored_prev_name = NULL; + if (seat->prev_workspace_name) { + stored_prev_name = strdup(seat->prev_workspace_name); + } + + swap_places(con1, con2); + + if (!workspace_is_visible(vis1)) { + seat_set_focus(seat, seat_get_focus_inactive(seat, &vis1->node)); + } + if (!workspace_is_visible(vis2)) { + seat_set_focus(seat, seat_get_focus_inactive(seat, &vis2->node)); + } + + swap_focus(con1, con2, seat, focus); + + if (stored_prev_name) { + free(seat->prev_workspace_name); + seat->prev_workspace_name = stored_prev_name; + } + + if (scratch1) { + root_scratchpad_add_container(con2, NULL); + if (!hidden1) { + root_scratchpad_show(con2); + } + } + if (scratch2) { + root_scratchpad_add_container(con1, NULL); + if (!hidden2) { + root_scratchpad_show(con1); + } + } + + if (fs1) { + container_set_fullscreen(con2, fs1); + } + if (fs2) { + container_set_fullscreen(con1, fs2); + } +} From 7a6c7d60d5dece586654d8855f34da25e92987fa Mon Sep 17 00:00:00 2001 From: Simon Ser <contact@emersion.fr> Date: Mon, 20 Feb 2023 10:15:07 +0100 Subject: [PATCH 03/14] Update surface fractional scale on output change Closes: https://github.com/swaywm/sway/issues/7464 --- include/sway/surface.h | 1 + sway/desktop/output.c | 7 +++++++ sway/desktop/surface.c | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/sway/surface.h b/include/sway/surface.h index 506818976..a7a8ec3ff 100644 --- a/include/sway/surface.h +++ b/include/sway/surface.h @@ -15,6 +15,7 @@ struct sway_surface { struct wl_event_source *frame_done_timer; }; +void surface_update_outputs(struct wlr_surface *surface); void surface_enter_output(struct wlr_surface *surface, struct sway_output *output); void surface_leave_output(struct wlr_surface *surface, diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 141edb491..302f9fdab 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -859,6 +859,12 @@ static void update_textures(struct sway_container *con, void *data) { container_update_marks_textures(con); } +static void update_output_scale_iterator(struct sway_output *output, + struct sway_view *view, struct wlr_surface *surface, + struct wlr_box *box, void *user_data) { + surface_update_outputs(surface); +} + static void handle_commit(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, commit); struct wlr_output_event_commit *event = data; @@ -873,6 +879,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { if (event->committed & WLR_OUTPUT_STATE_SCALE) { output_for_each_container(output, update_textures, NULL); + output_for_each_surface(output, update_output_scale_iterator, NULL); } if (event->committed & (WLR_OUTPUT_STATE_TRANSFORM | WLR_OUTPUT_STATE_SCALE)) { diff --git a/sway/desktop/surface.c b/sway/desktop/surface.c index 949cfdc26..68772ee0f 100644 --- a/sway/desktop/surface.c +++ b/sway/desktop/surface.c @@ -47,7 +47,7 @@ void handle_compositor_new_surface(struct wl_listener *listener, void *data) { } } -static void surface_update_outputs(struct wlr_surface *surface) { +void surface_update_outputs(struct wlr_surface *surface) { float scale = 1; struct wlr_surface_output *surface_output; wl_list_for_each(surface_output, &surface->current_outputs, link) { From 7d2e4a51063ac90f950cb44f141ab391cbcaff5f Mon Sep 17 00:00:00 2001 From: Simon Ser <contact@emersion.fr> Date: Mon, 20 Feb 2023 10:29:25 +0100 Subject: [PATCH 04/14] layer-shell: enter output before surface is mapped This sends fractional-scale-v1 events before the first configure event. That way clients have all of the metadata they need to render the first frame. --- sway/desktop/layer_shell.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 795eb4cd7..e16bee78d 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -383,7 +383,6 @@ static void handle_map(struct wl_listener *listener, void *data) { struct sway_output *output = wlr_output->data; output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y, sway_layer->layer_surface->surface, true); - surface_enter_output(sway_layer->layer_surface->surface, output); cursor_rebase_all(); } @@ -679,6 +678,8 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { wl_list_insert(&output->layers[layer_surface->pending.layer], &sway_layer->link); + surface_enter_output(layer_surface->surface, output); + // Temporarily set the layer's current state to pending // So that we can easily arrange it struct wlr_layer_surface_v1_state old_state = layer_surface->current; From 4666d1785bfb6635e6e8604de383c91714bceebc Mon Sep 17 00:00:00 2001 From: Stacy Harper <contact@stacyharper.net> Date: Sat, 21 Aug 2021 16:04:08 +0200 Subject: [PATCH 05/14] Implement seatop_touch Atm we got issue with the touch position sent to the clients. While holding contact, leaving the initial container will continue to send motion event to the client but with the new local position from the new container. This seatop goal is to send the position of the touch event, relatively to the initial container layout position. --- include/sway/input/cursor.h | 4 ++ include/sway/input/seat.h | 23 +++++++- sway/input/cursor.c | 45 ++------------- sway/input/seat.c | 20 +++++++ sway/input/seatop_default.c | 37 ++++++++++++- sway/input/seatop_down.c | 106 ++++++++++++++++++++++++++++++++++-- 6 files changed, 187 insertions(+), 48 deletions(-) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 828ac3704..4a3774d97 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -108,6 +108,10 @@ void cursor_unhide(struct sway_cursor *cursor); int cursor_get_timeout(struct sway_cursor *cursor); void cursor_notify_key_press(struct sway_cursor *cursor); +void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, + struct wlr_input_device *device, double dx, double dy, + double dx_unaccel, double dy_unaccel); + void dispatch_cursor_button(struct sway_cursor *cursor, struct wlr_input_device *device, uint32_t time_msec, uint32_t button, enum wlr_button_state state); diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 4abe91f71..227da78b6 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -4,6 +4,7 @@ #include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h> #include <wlr/types/wlr_layer_shell_v1.h> #include <wlr/types/wlr_seat.h> +#include <wlr/types/wlr_touch.h> #include <wlr/util/edges.h> #include "sway/config.h" #include "sway/input/input-manager.h" @@ -36,6 +37,12 @@ struct sway_seatop_impl { void (*swipe_end)(struct sway_seat *seat, struct wlr_pointer_swipe_end_event *event); void (*rebase)(struct sway_seat *seat, uint32_t time_msec); + void (*touch_motion)(struct sway_seat *seat, + struct wlr_touch_motion_event *event, double lx, double ly); + void (*touch_up)(struct sway_seat *seat, + struct wlr_touch_up_event *event); + void (*touch_down)(struct sway_seat *seat, + struct wlr_touch_down_event *event, double lx, double ly); void (*tablet_tool_motion)(struct sway_seat *seat, struct sway_tablet_tool *tool, uint32_t time_msec); void (*tablet_tool_tip)(struct sway_seat *seat, struct sway_tablet_tool *tool, @@ -256,10 +263,13 @@ enum wlr_edges find_resize_edge(struct sway_container *cont, void seatop_begin_default(struct sway_seat *seat); void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, - uint32_t time_msec, double sx, double sy); + double sx, double sy); void seatop_begin_down_on_surface(struct sway_seat *seat, - struct wlr_surface *surface, uint32_t time_msec, double sx, double sy); + struct wlr_surface *surface, double sx, double sy); + +void seatop_begin_touch_down(struct sway_seat *seat, struct wlr_surface *surface, + struct wlr_touch_down_event *event, double sx, double sy, double lx, double ly); void seatop_begin_move_floating(struct sway_seat *seat, struct sway_container *con); @@ -319,6 +329,15 @@ void seatop_swipe_update(struct sway_seat *seat, void seatop_swipe_end(struct sway_seat *seat, struct wlr_pointer_swipe_end_event *event); +void seatop_touch_motion(struct sway_seat *seat, + struct wlr_touch_motion_event *event, double lx, double ly); + +void seatop_touch_up(struct sway_seat *seat, + struct wlr_touch_up_event *event); + +void seatop_touch_down(struct sway_seat *seat, + struct wlr_touch_down_event *event, double lx, double ly); + void seatop_rebase(struct sway_seat *seat, uint32_t time_msec); /** diff --git a/sway/input/cursor.c b/sway/input/cursor.c index ad69e7c39..15687993b 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -364,7 +364,7 @@ void cursor_unhide(struct sway_cursor *cursor) { wl_event_source_timer_update(cursor->hide_source, cursor_get_timeout(cursor)); } -static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, +void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, struct wlr_input_device *device, double dx, double dy, double dx_unaccel, double dy_unaccel) { wlr_relative_pointer_manager_v1_send_relative_motion( @@ -479,43 +479,16 @@ static void handle_touch_down(struct wl_listener *listener, void *data) { cursor_hide(cursor); struct sway_seat *seat = cursor->seat; - struct wlr_seat *wlr_seat = seat->wlr_seat; - struct wlr_surface *surface = NULL; double lx, ly; wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base, event->x, event->y, &lx, &ly); - double sx, sy; - struct sway_node *focused_node = node_at_coords(seat, lx, ly, &surface, &sx, &sy); seat->touch_id = event->touch_id; seat->touch_x = lx; seat->touch_y = ly; - if (surface && wlr_surface_accepts_touch(wlr_seat, surface)) { - if (seat_is_input_allowed(seat, surface)) { - wlr_seat_touch_notify_down(wlr_seat, surface, event->time_msec, - event->touch_id, sx, sy); - - if (focused_node) { - seat_set_focus(seat, focused_node); - } - } - } else if (!cursor->simulating_pointer_from_touch && - (!surface || seat_is_input_allowed(seat, surface))) { - // Fallback to cursor simulation. - // The pointer_touch_id state is needed, so drags are not aborted when over - // a surface supporting touch and multi touch events don't interfere. - cursor->simulating_pointer_from_touch = true; - cursor->pointer_touch_id = seat->touch_id; - double dx, dy; - dx = lx - cursor->cursor->x; - dy = ly - cursor->cursor->y; - pointer_motion(cursor, event->time_msec, &event->touch->base, dx, dy, - dx, dy); - dispatch_cursor_button(cursor, &event->touch->base, event->time_msec, - BTN_LEFT, WLR_BUTTON_PRESSED); - } + seatop_touch_down(seat, event, lx, ly); } static void handle_touch_up(struct wl_listener *listener, void *data) { @@ -523,7 +496,7 @@ static void handle_touch_up(struct wl_listener *listener, void *data) { struct wlr_touch_up_event *event = data; cursor_handle_activity_from_device(cursor, &event->touch->base); - struct wlr_seat *wlr_seat = cursor->seat->wlr_seat; + struct sway_seat *seat = cursor->seat; if (cursor->simulating_pointer_from_touch) { if (cursor->pointer_touch_id == cursor->seat->touch_id) { @@ -532,7 +505,7 @@ static void handle_touch_up(struct wl_listener *listener, void *data) { event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED); } } else { - wlr_seat_touch_notify_up(wlr_seat, event->time_msec, event->touch_id); + seatop_touch_up(seat, event); } } @@ -543,19 +516,14 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { cursor_handle_activity_from_device(cursor, &event->touch->base); struct sway_seat *seat = cursor->seat; - struct wlr_seat *wlr_seat = seat->wlr_seat; - struct wlr_surface *surface = NULL; double lx, ly; wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base, event->x, event->y, &lx, &ly); - double sx, sy; - node_at_coords(cursor->seat, lx, ly, &surface, &sx, &sy); if (seat->touch_id == event->touch_id) { seat->touch_x = lx; seat->touch_y = ly; - struct sway_drag_icon *drag_icon; wl_list_for_each(drag_icon, &root->drag_icons, link) { if (drag_icon->seat == seat) { @@ -572,9 +540,8 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { pointer_motion(cursor, event->time_msec, &event->touch->base, dx, dy, dx, dy); } - } else if (surface) { - wlr_seat_touch_notify_motion(wlr_seat, event->time_msec, - event->touch_id, sx, sy); + } else { + seatop_touch_motion(seat, event, lx, ly); } } diff --git a/sway/input/seat.c b/sway/input/seat.c index 090a4d3ca..bff425ddc 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1618,6 +1618,26 @@ void seatop_pointer_axis(struct sway_seat *seat, } } +void seatop_touch_motion(struct sway_seat *seat, struct wlr_touch_motion_event *event, + double lx, double ly) { + if (seat->seatop_impl->touch_motion) { + seat->seatop_impl->touch_motion(seat, event, lx, ly); + } +} + +void seatop_touch_up(struct sway_seat *seat, struct wlr_touch_up_event *event) { + if (seat->seatop_impl->touch_up) { + seat->seatop_impl->touch_up(seat, event); + } +} + +void seatop_touch_down(struct sway_seat *seat, struct wlr_touch_down_event *event, + double lx, double ly) { + if (seat->seatop_impl->touch_down) { + seat->seatop_impl->touch_down(seat, event, lx, ly); + } +} + void seatop_tablet_tool_tip(struct sway_seat *seat, struct sway_tablet_tool *tool, uint32_t time_msec, enum wlr_tablet_tool_tip_state state) { diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index 0dcb87ab0..5a55c1866 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -261,7 +261,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, // Handle tapping on a container surface seat_set_focus_container(seat, cont); - seatop_begin_down(seat, node->sway_container, time_msec, sx, sy); + seatop_begin_down(seat, node->sway_container, sx, sy); } #if HAVE_XWAYLAND // Handle tapping on an xwayland unmanaged view @@ -374,7 +374,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, transaction_commit_dirty(); } if (state == WLR_BUTTON_PRESSED) { - seatop_begin_down_on_surface(seat, surface, time_msec, sx, sy); + seatop_begin_down_on_surface(seat, surface, sx, sy); } seat_pointer_notify_button(seat, time_msec, button, state); return; @@ -499,7 +499,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, // Handle mousedown on a container surface if (surface && cont && state == WLR_BUTTON_PRESSED) { - seatop_begin_down(seat, cont, time_msec, sx, sy); + seatop_begin_down(seat, cont, sx, sy); seat_pointer_notify_button(seat, time_msec, button, WLR_BUTTON_PRESSED); return; } @@ -649,6 +649,36 @@ static void handle_tablet_tool_motion(struct sway_seat *seat, e->previous_node = node; } +static void handle_touch_down(struct sway_seat *seat, + struct wlr_touch_down_event *event, double lx, double ly) { + struct wlr_surface *surface = NULL; + struct wlr_seat *wlr_seat = seat->wlr_seat; + struct sway_cursor *cursor = seat->cursor; + double sx, sy; + node_at_coords(seat, seat->touch_x, seat->touch_y, &surface, &sx, &sy); + + if (surface && wlr_surface_accepts_touch(wlr_seat, surface)) { + if (seat_is_input_allowed(seat, surface)) { + cursor->simulating_pointer_from_touch = false; + seatop_begin_touch_down(seat, surface, event, sx, sy, lx, ly); + } + } else if (!cursor->simulating_pointer_from_touch && + (!surface || seat_is_input_allowed(seat, surface))) { + // Fallback to cursor simulation. + // The pointer_touch_id state is needed, so drags are not aborted when over + // a surface supporting touch and multi touch events don't interfere. + cursor->simulating_pointer_from_touch = true; + cursor->pointer_touch_id = seat->touch_id; + double dx, dy; + dx = seat->touch_x - cursor->cursor->x; + dy = seat->touch_y - cursor->cursor->y; + pointer_motion(cursor, event->time_msec, &event->touch->base, dx, dy, + dx, dy); + dispatch_cursor_button(cursor, &event->touch->base, event->time_msec, + BTN_LEFT, WLR_BUTTON_PRESSED); + } +} + /*----------------------------------------\ * Functions used by handle_pointer_axis / *--------------------------------------*/ @@ -1096,6 +1126,7 @@ static const struct sway_seatop_impl seatop_impl = { .swipe_begin = handle_swipe_begin, .swipe_update = handle_swipe_update, .swipe_end = handle_swipe_end, + .touch_down = handle_touch_down, .rebase = handle_rebase, .allow_set_cursor = true, }; diff --git a/sway/input/seatop_down.c b/sway/input/seatop_down.c index 3f880ccf9..6447134ec 100644 --- a/sway/input/seatop_down.c +++ b/sway/input/seatop_down.c @@ -2,12 +2,20 @@ #include <float.h> #include <wlr/types/wlr_cursor.h> #include <wlr/types/wlr_tablet_v2.h> +#include <wlr/types/wlr_touch.h> #include "sway/input/cursor.h" #include "sway/input/seat.h" #include "sway/tree/view.h" #include "sway/desktop/transaction.h" #include "log.h" +struct seatop_touch_point_event { + double ref_lx, ref_ly; // touch's x/y at start of op + double ref_con_lx, ref_con_ly; // container's x/y at start of op + int32_t touch_id; + struct wl_list link; +}; + struct seatop_down_event { struct sway_container *con; struct sway_seat *seat; @@ -15,8 +23,87 @@ struct seatop_down_event { struct wlr_surface *surface; double ref_lx, ref_ly; // cursor's x/y at start of op double ref_con_lx, ref_con_ly; // container's x/y at start of op + struct wl_list point_events; // seatop_touch_point_event::link }; +static void handle_touch_motion(struct sway_seat *seat, + struct wlr_touch_motion_event *event, double lx, double ly) { + struct seatop_down_event *e = seat->seatop_data; + + struct seatop_touch_point_event *point_event; + bool found = false; + wl_list_for_each(point_event, &e->point_events, link) { + if (point_event->touch_id == event->touch_id) { + found = true; + break; + } + } + if (!found) { + return; // Probably not a point_event from this seatop_down + } + + double moved_x = lx - point_event->ref_lx; + double moved_y = ly - point_event->ref_ly; + double sx = point_event->ref_con_lx + moved_x; + double sy = point_event->ref_con_ly + moved_y; + + wlr_seat_touch_notify_motion(seat->wlr_seat, event->time_msec, + event->touch_id, sx, sy); +} + +static void handle_touch_up(struct sway_seat *seat, + struct wlr_touch_up_event *event) { + struct seatop_down_event *e = seat->seatop_data; + struct seatop_touch_point_event *point_event, *tmp; + + wl_list_for_each_safe(point_event, tmp, &e->point_events, link) { + if (point_event->touch_id == event->touch_id) { + wl_list_remove(&point_event->link); + free(point_event); + break; + } + } + + if (wl_list_empty(&e->point_events)) { + seatop_begin_default(seat); + } + + wlr_seat_touch_notify_up(seat->wlr_seat, event->time_msec, event->touch_id); +} + +static void handle_touch_down(struct sway_seat *seat, + struct wlr_touch_down_event *event, double lx, double ly) { + struct seatop_down_event *e = seat->seatop_data; + double sx, sy; + struct wlr_surface *surface = NULL; + struct sway_node *focused_node = node_at_coords(seat, seat->touch_x, + seat->touch_y, &surface, &sx, &sy); + + if (!surface || surface != e->surface) { // Must start from the initial surface + return; + } + + struct seatop_touch_point_event *point_event = + calloc(1, sizeof(struct seatop_touch_point_event)); + if (!sway_assert(point_event, "Unable to allocate point_event")) { + return; + } + point_event->touch_id = event->touch_id; + point_event->ref_lx = lx; + point_event->ref_ly = ly; + point_event->ref_con_lx = sx; + point_event->ref_con_ly = sy; + + wl_list_insert(&e->point_events, &point_event->link); + + wlr_seat_touch_notify_down(seat->wlr_seat, surface, event->time_msec, + event->touch_id, sx, sy); + + if (focused_node) { + seat_set_focus(seat, focused_node); + } +} + static void handle_pointer_axis(struct sway_seat *seat, struct wlr_pointer_axis_event *event) { struct sway_input_device *input_device = @@ -99,14 +186,17 @@ static const struct sway_seatop_impl seatop_impl = { .pointer_axis = handle_pointer_axis, .tablet_tool_tip = handle_tablet_tool_tip, .tablet_tool_motion = handle_tablet_tool_motion, + .touch_motion = handle_touch_motion, + .touch_up = handle_touch_up, + .touch_down = handle_touch_down, .unref = handle_unref, .end = handle_end, .allow_set_cursor = true, }; void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, - uint32_t time_msec, double sx, double sy) { - seatop_begin_down_on_surface(seat, con->view->surface, time_msec, sx, sy); + double sx, double sy) { + seatop_begin_down_on_surface(seat, con->view->surface, sx, sy); struct seatop_down_event *e = seat->seatop_data; e->con = con; @@ -114,13 +204,20 @@ void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, transaction_commit_dirty(); } +void seatop_begin_touch_down(struct sway_seat *seat, + struct wlr_surface *surface, struct wlr_touch_down_event *event, + double sx, double sy, double lx, double ly) { + seatop_begin_down_on_surface(seat, surface, sx, sy); + handle_touch_down(seat, event, lx, ly); +} + void seatop_begin_down_on_surface(struct sway_seat *seat, - struct wlr_surface *surface, uint32_t time_msec, double sx, double sy) { + struct wlr_surface *surface, double sx, double sy) { seatop_end(seat); struct seatop_down_event *e = calloc(1, sizeof(struct seatop_down_event)); - if (!e) { + if (!sway_assert(e, "Unable to allocate e")) { return; } e->con = NULL; @@ -132,6 +229,7 @@ void seatop_begin_down_on_surface(struct sway_seat *seat, e->ref_ly = seat->cursor->cursor->y; e->ref_con_lx = sx; e->ref_con_ly = sy; + wl_list_init(&e->point_events); seat->seatop_impl = &seatop_impl; seat->seatop_data = e; From 423459723bc488b69aa6fafcc9aa4e13fdf92717 Mon Sep 17 00:00:00 2001 From: Simon Ser <contact@emersion.fr> Date: Mon, 20 Feb 2023 18:56:43 +0100 Subject: [PATCH 06/14] Adjust scale for fractional-scale-v1 --- sway/config/output.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sway/config/output.c b/sway/config/output.c index e2e48e4cc..3b524433c 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -460,6 +460,16 @@ static void queue_output_config(struct output_config *oc, float scale; if (oc && oc->scale > 0) { scale = oc->scale; + + // The factional-scale-v1 protocol uses increments of 120ths to send + // the scale factor to the client. Adjust the scale so that we use the + // same value as the clients'. + float adjusted_scale = round(scale * 120) / 120; + if (scale != adjusted_scale) { + sway_log(SWAY_INFO, "Adjusting output scale from %f to %f", + scale, adjusted_scale); + scale = adjusted_scale; + } } else { scale = compute_default_scale(wlr_output, pending); sway_log(SWAY_DEBUG, "Auto-detected output scale: %f", scale); From d6cb4fa8de1e540c58b58d29d1520df296e46d1f Mon Sep 17 00:00:00 2001 From: Simon Ser <contact@emersion.fr> Date: Wed, 22 Feb 2023 18:34:08 +0100 Subject: [PATCH 07/14] Constify pixman_region32_t for rendering functions --- include/sway/input/seat.h | 4 +-- include/sway/output.h | 2 +- sway/desktop/render.c | 48 ++++++++++++++++----------------- sway/input/seat.c | 2 +- sway/input/seatop_move_tiling.c | 2 +- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 227da78b6..7b2d3d075 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -50,7 +50,7 @@ struct sway_seatop_impl { void (*end)(struct sway_seat *seat); void (*unref)(struct sway_seat *seat, struct sway_container *con); void (*render)(struct sway_seat *seat, struct sway_output *output, - pixman_region32_t *damage); + const pixman_region32_t *damage); bool allow_set_cursor; }; @@ -357,7 +357,7 @@ void seatop_unref(struct sway_seat *seat, struct sway_container *con); * (eg. dropzone for move-tiling) */ void seatop_render(struct sway_seat *seat, struct sway_output *output, - pixman_region32_t *damage); + const pixman_region32_t *damage); bool seatop_allows_set_cursor(struct sway_seat *seat); diff --git a/include/sway/output.h b/include/sway/output.h index 28be6a1e9..da6253158 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -167,7 +167,7 @@ enum sway_container_layout output_get_default_layout( struct sway_output *output); void render_rect(struct sway_output *output, - pixman_region32_t *output_damage, const struct wlr_box *_box, + const pixman_region32_t *output_damage, const struct wlr_box *_box, float color[static 4]); void premultiply_alpha(float color[4], float opacity); diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 2b7214c35..dedaa9679 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -32,7 +32,7 @@ #endif struct render_data { - pixman_region32_t *damage; + const pixman_region32_t *damage; float alpha; struct wlr_box *clip_box; }; @@ -102,7 +102,7 @@ static void set_scale_filter(struct wlr_output *wlr_output, } static void render_texture(struct wlr_output *wlr_output, - pixman_region32_t *output_damage, struct wlr_texture *texture, + const pixman_region32_t *output_damage, struct wlr_texture *texture, const struct wlr_fbox *src_box, const struct wlr_box *dst_box, const float matrix[static 9], float alpha) { struct wlr_renderer *renderer = wlr_output->renderer; @@ -139,7 +139,7 @@ static void render_surface_iterator(struct sway_output *output, struct wlr_box *_box, void *_data) { struct render_data *data = _data; struct wlr_output *wlr_output = output->wlr_output; - pixman_region32_t *output_damage = data->damage; + const pixman_region32_t *output_damage = data->damage; float alpha = data->alpha; struct wlr_texture *texture = wlr_surface_get_texture(surface); @@ -175,7 +175,7 @@ static void render_surface_iterator(struct sway_output *output, } static void render_layer_toplevel(struct sway_output *output, - pixman_region32_t *damage, struct wl_list *layer_surfaces) { + const pixman_region32_t *damage, struct wl_list *layer_surfaces) { struct render_data data = { .damage = damage, .alpha = 1.0f, @@ -185,7 +185,7 @@ static void render_layer_toplevel(struct sway_output *output, } static void render_layer_popups(struct sway_output *output, - pixman_region32_t *damage, struct wl_list *layer_surfaces) { + const pixman_region32_t *damage, struct wl_list *layer_surfaces) { struct render_data data = { .damage = damage, .alpha = 1.0f, @@ -196,7 +196,7 @@ static void render_layer_popups(struct sway_output *output, #if HAVE_XWAYLAND static void render_unmanaged(struct sway_output *output, - pixman_region32_t *damage, struct wl_list *unmanaged) { + const pixman_region32_t *damage, struct wl_list *unmanaged) { struct render_data data = { .damage = damage, .alpha = 1.0f, @@ -207,7 +207,7 @@ static void render_unmanaged(struct sway_output *output, #endif static void render_drag_icons(struct sway_output *output, - pixman_region32_t *damage, struct wl_list *drag_icons) { + const pixman_region32_t *damage, struct wl_list *drag_icons) { struct render_data data = { .damage = damage, .alpha = 1.0f, @@ -219,7 +219,7 @@ static void render_drag_icons(struct sway_output *output, // _box.x and .y are expected to be layout-local // _box.width and .height are expected to be output-buffer-local void render_rect(struct sway_output *output, - pixman_region32_t *output_damage, const struct wlr_box *_box, + const pixman_region32_t *output_damage, const struct wlr_box *_box, float color[static 4]) { struct wlr_output *wlr_output = output->wlr_output; struct wlr_renderer *renderer = wlr_output->renderer; @@ -259,7 +259,7 @@ void premultiply_alpha(float color[4], float opacity) { } static void render_view_toplevels(struct sway_view *view, - struct sway_output *output, pixman_region32_t *damage, float alpha) { + struct sway_output *output, const pixman_region32_t *damage, float alpha) { struct render_data data = { .damage = damage, .alpha = alpha, @@ -282,7 +282,7 @@ static void render_view_toplevels(struct sway_view *view, } static void render_view_popups(struct sway_view *view, - struct sway_output *output, pixman_region32_t *damage, float alpha) { + struct sway_output *output, const pixman_region32_t *damage, float alpha) { struct render_data data = { .damage = damage, .alpha = alpha, @@ -292,7 +292,7 @@ static void render_view_popups(struct sway_view *view, } static void render_saved_view(struct sway_view *view, - struct sway_output *output, pixman_region32_t *damage, float alpha) { + struct sway_output *output, const pixman_region32_t *damage, float alpha) { struct wlr_output *wlr_output = output->wlr_output; if (wl_list_empty(&view->saved_buffers)) { @@ -355,7 +355,7 @@ static void render_saved_view(struct sway_view *view, /** * Render a view's surface and left/bottom/right borders. */ -static void render_view(struct sway_output *output, pixman_region32_t *damage, +static void render_view(struct sway_output *output, const pixman_region32_t *damage, struct sway_container *con, struct border_colors *colors) { struct sway_view *view = con->view; if (!wl_list_empty(&view->saved_buffers)) { @@ -429,7 +429,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, * The left side is: 1px border, 2px padding, title */ static void render_titlebar(struct sway_output *output, - pixman_region32_t *output_damage, struct sway_container *con, + const pixman_region32_t *output_damage, struct sway_container *con, int x, int y, int width, struct border_colors *colors, struct wlr_texture *title_texture, struct wlr_texture *marks_texture) { @@ -684,7 +684,7 @@ static void render_titlebar(struct sway_output *output, * Render the top border line for a view using "border pixel". */ static void render_top_border(struct sway_output *output, - pixman_region32_t *output_damage, struct sway_container *con, + const pixman_region32_t *output_damage, struct sway_container *con, struct border_colors *colors) { struct sway_container_state *state = &con->current; if (!state->border_top) { @@ -714,7 +714,7 @@ struct parent_data { }; static void render_container(struct sway_output *output, - pixman_region32_t *damage, struct sway_container *con, bool parent_focused); + const pixman_region32_t *damage, struct sway_container *con, bool parent_focused); /** * Render a container's children using a L_HORIZ or L_VERT layout. @@ -723,7 +723,7 @@ static void render_container(struct sway_output *output, * they'll apply their own borders to their children. */ static void render_containers_linear(struct sway_output *output, - pixman_region32_t *damage, struct parent_data *parent) { + const pixman_region32_t *damage, struct parent_data *parent) { for (int i = 0; i < parent->children->length; ++i) { struct sway_container *child = parent->children->items[i]; @@ -779,7 +779,7 @@ static bool container_has_focused_child(struct sway_container *con) { * Render a container's children using the L_TABBED layout. */ static void render_containers_tabbed(struct sway_output *output, - pixman_region32_t *damage, struct parent_data *parent) { + const pixman_region32_t *damage, struct parent_data *parent) { if (!parent->children->length) { return; } @@ -848,7 +848,7 @@ static void render_containers_tabbed(struct sway_output *output, * Render a container's children using the L_STACKED layout. */ static void render_containers_stacked(struct sway_output *output, - pixman_region32_t *damage, struct parent_data *parent) { + const pixman_region32_t *damage, struct parent_data *parent) { if (!parent->children->length) { return; } @@ -908,7 +908,7 @@ static void render_containers_stacked(struct sway_output *output, } static void render_containers(struct sway_output *output, - pixman_region32_t *damage, struct parent_data *parent) { + const pixman_region32_t *damage, struct parent_data *parent) { if (config->hide_lone_tab && parent->children->length == 1) { struct sway_container *child = parent->children->items[0]; if (child->view) { @@ -933,7 +933,7 @@ static void render_containers(struct sway_output *output, } static void render_container(struct sway_output *output, - pixman_region32_t *damage, struct sway_container *con, bool focused) { + const pixman_region32_t *damage, struct sway_container *con, bool focused) { struct parent_data data = { .layout = con->current.layout, .box = { @@ -950,7 +950,7 @@ static void render_container(struct sway_output *output, } static void render_workspace(struct sway_output *output, - pixman_region32_t *damage, struct sway_workspace *ws, bool focused) { + const pixman_region32_t *damage, struct sway_workspace *ws, bool focused) { struct parent_data data = { .layout = ws->current.layout, .box = { @@ -967,7 +967,7 @@ static void render_workspace(struct sway_output *output, } static void render_floating_container(struct sway_output *soutput, - pixman_region32_t *damage, struct sway_container *con) { + const pixman_region32_t *damage, struct sway_container *con) { if (con->view) { struct sway_view *view = con->view; struct border_colors *colors; @@ -1002,7 +1002,7 @@ static void render_floating_container(struct sway_output *soutput, } static void render_floating(struct sway_output *soutput, - pixman_region32_t *damage) { + const pixman_region32_t *damage) { for (int i = 0; i < root->outputs->length; ++i) { struct sway_output *output = root->outputs->items[i]; for (int j = 0; j < output->current.workspaces->length; ++j) { @@ -1022,7 +1022,7 @@ static void render_floating(struct sway_output *soutput, } static void render_seatops(struct sway_output *output, - pixman_region32_t *damage) { + const pixman_region32_t *damage) { struct sway_seat *seat; wl_list_for_each(seat, &server.input->seats, link) { seatop_render(seat, output, damage); diff --git a/sway/input/seat.c b/sway/input/seat.c index bff425ddc..14931ce0f 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1727,7 +1727,7 @@ void seatop_end(struct sway_seat *seat) { } void seatop_render(struct sway_seat *seat, struct sway_output *output, - pixman_region32_t *damage) { + const pixman_region32_t *damage) { if (seat->seatop_impl->render) { seat->seatop_impl->render(seat, output, damage); } diff --git a/sway/input/seatop_move_tiling.c b/sway/input/seatop_move_tiling.c index 223c6c08c..5498e9092 100644 --- a/sway/input/seatop_move_tiling.c +++ b/sway/input/seatop_move_tiling.c @@ -32,7 +32,7 @@ struct seatop_move_tiling_event { }; static void handle_render(struct sway_seat *seat, - struct sway_output *output, pixman_region32_t *damage) { + struct sway_output *output, const pixman_region32_t *damage) { struct seatop_move_tiling_event *e = seat->seatop_data; if (!e->threshold_reached) { return; From c2ccc0c9d4726a2d1f23f1696c7b6aa0f6cb1a63 Mon Sep 17 00:00:00 2001 From: Simon Ser <contact@emersion.fr> Date: Wed, 22 Feb 2023 18:38:19 +0100 Subject: [PATCH 08/14] Move output commit out of output_render() That way output_render() only does what it says on the tin. --- include/sway/output.h | 3 +-- sway/desktop/output.c | 39 ++++++++++++++++++++++++++++++++++++--- sway/desktop/render.c | 29 +---------------------------- 3 files changed, 38 insertions(+), 33 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index da6253158..2aa1b2788 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -112,8 +112,7 @@ bool output_has_opaque_overlay_layer_surface(struct sway_output *output); struct sway_workspace *output_get_active_workspace(struct sway_output *output); -void output_render(struct sway_output *output, struct timespec *when, - pixman_region32_t *damage); +void output_render(struct sway_output *output, pixman_region32_t *damage); void output_surface_for_each_surface(struct sway_output *output, struct wlr_surface *surface, double ox, double oy, diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 302f9fdab..4b6e9122b 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -517,13 +517,34 @@ static bool scan_out_fullscreen_view(struct sway_output *output, return wlr_output_commit(wlr_output); } +static void get_frame_damage(struct sway_output *output, + pixman_region32_t *frame_damage) { + struct wlr_output *wlr_output = output->wlr_output; + + int width, height; + wlr_output_transformed_resolution(wlr_output, &width, &height); + + pixman_region32_init(frame_damage); + + enum wl_output_transform transform = + wlr_output_transform_invert(wlr_output->transform); + wlr_region_transform(frame_damage, &output->damage_ring.current, + transform, width, height); + + if (debug.damage != DAMAGE_DEFAULT) { + pixman_region32_union_rect(frame_damage, frame_damage, + 0, 0, wlr_output->width, wlr_output->height); + } +} + static int output_repaint_timer_handler(void *data) { struct sway_output *output = data; - if (output->wlr_output == NULL) { + struct wlr_output *wlr_output = output->wlr_output; + if (wlr_output == NULL) { return 0; } - output->wlr_output->frame_pending = false; + wlr_output->frame_pending = false; struct sway_workspace *workspace = output->current.active_workspace; if (workspace == NULL) { @@ -575,10 +596,22 @@ static int output_repaint_timer_handler(void *data) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - output_render(output, &now, &damage); + output_render(output, &damage); 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; + } + + wlr_damage_ring_rotate(&output->damage_ring); + output->last_frame = now; + return 0; } diff --git a/sway/desktop/render.c b/sway/desktop/render.c index dedaa9679..a4d633e09 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -1029,8 +1029,7 @@ static void render_seatops(struct sway_output *output, } } -void output_render(struct sway_output *output, struct timespec *when, - pixman_region32_t *damage) { +void output_render(struct sway_output *output, pixman_region32_t *damage) { struct wlr_output *wlr_output = output->wlr_output; struct wlr_renderer *renderer = output->server->renderer; @@ -1184,30 +1183,4 @@ renderer_end: wlr_renderer_scissor(renderer, NULL); wlr_output_render_software_cursors(wlr_output, damage); wlr_renderer_end(renderer); - - int width, height; - wlr_output_transformed_resolution(wlr_output, &width, &height); - - pixman_region32_t frame_damage; - pixman_region32_init(&frame_damage); - - enum wl_output_transform transform = - wlr_output_transform_invert(wlr_output->transform); - wlr_region_transform(&frame_damage, &output->damage_ring.current, - transform, width, height); - - if (debug.damage != DAMAGE_DEFAULT) { - pixman_region32_union_rect(&frame_damage, &frame_damage, - 0, 0, wlr_output->width, wlr_output->height); - } - - wlr_output_set_damage(wlr_output, &frame_damage); - pixman_region32_fini(&frame_damage); - - if (!wlr_output_commit(wlr_output)) { - return; - } - - wlr_damage_ring_rotate(&output->damage_ring); - output->last_frame = *when; } From 16b0afd4331dbd8ed6bb1df49e8309d05f4488dd Mon Sep 17 00:00:00 2001 From: Simon Ser <contact@emersion.fr> Date: Wed, 22 Feb 2023 18:43:20 +0100 Subject: [PATCH 09/14] Check for empty damage before attaching render buffer Check whether output->damage_ring.current is empty before calling wlr_output_attach_render(). Saves us from having to un-do that via wlr_output_rollback(). --- sway/desktop/output.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 4b6e9122b..1b9b5e67e 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -578,6 +578,11 @@ 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; @@ -586,12 +591,6 @@ static int output_repaint_timer_handler(void *data) { pixman_region32_t damage; pixman_region32_init(&damage); wlr_damage_ring_get_buffer_damage(&output->damage_ring, buffer_age, &damage); - if (!output->wlr_output->needs_frame && - !pixman_region32_not_empty(&output->damage_ring.current)) { - pixman_region32_fini(&damage); - wlr_output_rollback(output->wlr_output); - return 0; - } struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); From 9498e4d2614fce6b29b64fd8a3861c1fb5be4b87 Mon Sep 17 00:00:00 2001 From: Robin Jarry <robin@jarry.cc> Date: Wed, 25 Jan 2023 21:54:16 +0100 Subject: [PATCH 10/14] Allow windows in scratchpad to set the urgent flag When a window in the scratchpad container requests for xdg_activation_v1, it is ignored no matter what the value of focus_on_window_activation is. At least allow windows in the scratchpad to set the urgent flag. When focus_on_window_activation is set to "focus", show the parent scratchpad where the contained requested for xdg_activation_v1. --- sway/tree/view.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sway/tree/view.c b/sway/tree/view.c index fcb78de36..ec54fed81 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -369,16 +369,13 @@ void view_set_activated(struct sway_view *view, bool activated) { void view_request_activate(struct sway_view *view, struct sway_seat *seat) { struct sway_workspace *ws = view->container->pending.workspace; - if (!ws) { // hidden scratchpad container - return; - } if (!seat) { seat = input_manager_current_seat(); } switch (config->focus_on_window_activation) { case FOWA_SMART: - if (workspace_is_visible(ws)) { + if (ws && workspace_is_visible(ws)) { seat_set_focus_container(seat, view->container); container_raise_floating(view->container); } else { @@ -389,8 +386,12 @@ void view_request_activate(struct sway_view *view, struct sway_seat *seat) { view_set_urgent(view, true); break; case FOWA_FOCUS: - seat_set_focus_container(seat, view->container); - container_raise_floating(view->container); + if (container_is_scratchpad_hidden_or_child(view->container)) { + root_scratchpad_show(view->container); + } else { + seat_set_focus_container(seat, view->container); + container_raise_floating(view->container); + } break; case FOWA_NONE: break; From d63497698b2133d217267d3ab3e9c00927955e7b Mon Sep 17 00:00:00 2001 From: rj1 <rj1@riseup.net> Date: Sat, 4 Feb 2023 03:50:30 -0600 Subject: [PATCH 11/14] fix typo --- swaymsg/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swaymsg/main.c b/swaymsg/main.c index 4d3fa68c2..db9346c4b 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -60,7 +60,7 @@ static void pretty_print_cmd(json_object *r) { if (!success_object(r)) { json_object *error; if (!json_object_object_get_ex(r, "error", &error)) { - printf("An unknkown error occurred"); + printf("An unknown error occurred"); } else { printf("Error: %s\n", json_object_get_string(error)); } From b757ef94ef15093b8851598f85ef047379c341b5 Mon Sep 17 00:00:00 2001 From: llyyr <llyyr.public@gmail.com> Date: Sun, 26 Feb 2023 16:12:19 +0530 Subject: [PATCH 12/14] sway{,bar}: use default font hint style CAIRO_HINT_STYLE_FULL attempts to maximize contrast at the expense of fidelity, this makes most fonts that haven't been hand hinted, which makes up the majority of fonts out there, appear much worse. In the absence of explicitly set hint style, cairo will default to CAIRO_HINT_STYLE_SLIGHT, which attempts to improve contrast while retaining fidelity to the original shapes, which is what we want. --- sway/tree/container.c | 1 - swaybar/render.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 335dae87c..8222a5069 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -508,7 +508,6 @@ static void render_titlebar_text_texture(struct sway_output *output, cairo_t *c = cairo_create(dummy_surface); cairo_set_antialias(c, CAIRO_ANTIALIAS_BEST); cairo_font_options_t *fo = cairo_font_options_create(); - cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL); if (output->wlr_output->subpixel == WL_OUTPUT_SUBPIXEL_NONE) { cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_GRAY); } else { diff --git a/swaybar/render.c b/swaybar/render.c index ccf365637..6a983e97d 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -774,14 +774,12 @@ void render_frame(struct swaybar_output *output) { ctx.cairo = cairo; cairo_font_options_t *fo = cairo_font_options_create(); - cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL); cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_GRAY); ctx.textaa_safe = fo; if (output->subpixel == WL_OUTPUT_SUBPIXEL_NONE) { ctx.textaa_sharp = ctx.textaa_safe; } else { fo = cairo_font_options_create(); - cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL); cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL); cairo_font_options_set_subpixel_order(fo, to_cairo_subpixel_order(output->subpixel)); From b28e1b0d3c4ab90dc7e0516078e1e3f332981f37 Mon Sep 17 00:00:00 2001 From: novenary <streetwalkermc@gmail.com> Date: Tue, 28 Feb 2023 10:33:39 +0200 Subject: [PATCH 13/14] Disable direct scanout for surfaces with popups --- sway/desktop/output.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 1b9b5e67e..0c8a5fd41 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -496,6 +496,12 @@ static bool scan_out_fullscreen_view(struct sway_output *output, if (n_surfaces != 1) { return false; } + size_t n_popups = 0; + output_view_for_each_popup_surface(output, view, + count_surface_iterator, &n_popups); + if (n_popups > 0) { + return false; + } if (surface->buffer == NULL) { return false; From 51c9376c07639f7876fadc8522d8491d728c7c70 Mon Sep 17 00:00:00 2001 From: Simon Zeni <simon@bl4ckb0ne.ca> Date: Tue, 28 Feb 2023 17:19:33 -0500 Subject: [PATCH 14/14] ci: add libdisplay-info dependency --- .builds/alpine.yml | 1 + .builds/archlinux.yml | 1 + .builds/freebsd.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.builds/alpine.yml b/.builds/alpine.yml index 34f780e9e..59df7737c 100644 --- a/.builds/alpine.yml +++ b/.builds/alpine.yml @@ -4,6 +4,7 @@ packages: - eudev-dev - gdk-pixbuf-dev - json-c-dev + - libdisplay-info-dev - libevdev-dev - libinput-dev - libseat-dev diff --git a/.builds/archlinux.yml b/.builds/archlinux.yml index 19bd2e594..9972c01ad 100644 --- a/.builds/archlinux.yml +++ b/.builds/archlinux.yml @@ -3,6 +3,7 @@ packages: - cairo - gdk-pixbuf2 - json-c + - libdisplay-info - libegl - libinput - libxcb diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml index 861aa2553..29c6312af 100644 --- a/.builds/freebsd.yml +++ b/.builds/freebsd.yml @@ -20,6 +20,7 @@ packages: - devel/libudev-devd - graphics/libdrm - graphics/mesa-libs +- sysutils/libdisplay-info - sysutils/seatd - x11/libinput - x11/libX11