From a6d4f4d3b51a46cb4b79e30708592527b981a6c5 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 30 Apr 2022 00:00:25 -0400 Subject: [PATCH] scene_graph: Port seat drag icons --- include/sway/input/seat.h | 22 +++++--- include/sway/output.h | 4 -- include/sway/scene_descriptor.h | 1 + include/sway/tree/root.h | 2 +- sway/desktop/output.c | 16 ------ sway/desktop/render.c | 11 ---- sway/input/cursor.c | 14 +++-- sway/input/seat.c | 99 +++++++++++++++++---------------- sway/input/seatop_default.c | 26 +++++---- sway/tree/root.c | 1 - 10 files changed, 90 insertions(+), 106 deletions(-) diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index e3a468726..a2becbde3 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "sway/config.h" #include "sway/input/input-manager.h" #include "sway/input/tablet.h" @@ -67,16 +68,12 @@ struct sway_seat_node { }; struct sway_drag_icon { - struct sway_seat *seat; struct wlr_drag_icon *wlr_drag_icon; - struct wl_list link; // sway_root::drag_icons + struct wlr_scene_tree *tree; + struct wlr_scene_tree *surface_tree; - double x, y; // in layout-local coordinates - - struct wl_listener surface_commit; - struct wl_listener map; - struct wl_listener unmap; struct wl_listener destroy; + struct wl_listener commit; }; struct sway_drag { @@ -89,6 +86,15 @@ struct sway_seat { struct wlr_seat *wlr_seat; struct sway_cursor *cursor; + // Seat scene tree structure + // - scene_tree + // - drag icons + // - drag icon 1 + // - drag icon 2 + // - seatop specific stuff + struct wlr_scene_tree *scene_tree; + struct wlr_scene_tree *drag_icons; + bool has_focus; struct wl_list focus_stack; // list of containers in focus order struct sway_workspace *workspace; @@ -247,7 +253,7 @@ void seat_idle_notify_activity(struct sway_seat *seat, bool seat_is_input_allowed(struct sway_seat *seat, struct wlr_surface *surface); -void drag_icon_update_position(struct sway_drag_icon *icon); +void drag_icon_update_position(struct sway_seat *seat, struct sway_drag_icon *icon); enum wlr_edges find_resize_edge(struct sway_container *cont, struct wlr_surface *surface, struct sway_cursor *cursor); diff --git a/include/sway/output.h b/include/sway/output.h index c399b5c37..e91968933 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -159,10 +159,6 @@ void output_unmanaged_for_each_surface(struct sway_output *output, void *user_data); #endif -void output_drag_icons_for_each_surface(struct sway_output *output, - struct wl_list *drag_icons, sway_surface_iterator_func_t iterator, - void *user_data); - void output_for_each_workspace(struct sway_output *output, void (*f)(struct sway_workspace *ws, void *data), void *data); diff --git a/include/sway/scene_descriptor.h b/include/sway/scene_descriptor.h index cf0d4a34d..de54d133a 100644 --- a/include/sway/scene_descriptor.h +++ b/include/sway/scene_descriptor.h @@ -4,6 +4,7 @@ enum sway_scene_descriptor_type { SWAY_SCENE_DESC_BUFFER_TIMER, + SWAY_SCENE_DESC_DRAG_ICON, }; struct sway_scene_descriptor { diff --git a/include/sway/tree/root.h b/include/sway/tree/root.h index 200f1c73a..f87b03259 100644 --- a/include/sway/tree/root.h +++ b/include/sway/tree/root.h @@ -40,12 +40,12 @@ struct sway_root { struct wlr_scene_tree *floating; struct wlr_scene_tree *fullscreen; struct wlr_scene_tree *fullscreen_global; + struct wlr_scene_tree *seat; } layers; #if HAVE_XWAYLAND struct wl_list xwayland_unmanaged; // sway_xwayland_unmanaged::link #endif - struct wl_list drag_icons; // sway_drag_icon::link // Includes disabled outputs struct wl_list all_outputs; // sway_output::link diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 21b3f3604..a3efcd70e 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -246,22 +246,6 @@ void output_unmanaged_for_each_surface(struct sway_output *output, } #endif -void output_drag_icons_for_each_surface(struct sway_output *output, - struct wl_list *drag_icons, sway_surface_iterator_func_t iterator, - void *user_data) { - struct sway_drag_icon *drag_icon; - wl_list_for_each(drag_icon, drag_icons, link) { - double ox = drag_icon->x - output->lx; - double oy = drag_icon->y - output->ly; - - if (drag_icon->wlr_drag_icon->mapped) { - output_surface_for_each_surface(output, - drag_icon->wlr_drag_icon->surface, ox, oy, - iterator, user_data); - } - } -} - static int scale_length(int length, int offset, float scale) { return round((offset + length) * scale) - round(offset * scale); } diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 4a398df78..079f4f39f 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -201,16 +201,6 @@ 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) { - struct render_data data = { - .damage = damage, - .alpha = 1.0f, - }; - output_drag_icons_for_each_surface(output, drag_icons, - render_surface_iterator, &data); -} - // _box.x and .y are expected to be layout-local // _box.width and .height are expected to be output-buffer-local void render_rect(struct sway_output *output, @@ -1171,7 +1161,6 @@ render_overlay: &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); render_layer_popups(output, damage, &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); - render_drag_icons(output, damage, &root->drag_icons); renderer_end: wlr_renderer_scissor(renderer, NULL); diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 4a8efb0fb..8db513e37 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -19,12 +19,12 @@ #include "log.h" #include "util.h" #include "sway/commands.h" -#include "sway/desktop.h" #include "sway/input/cursor.h" #include "sway/input/keyboard.h" #include "sway/input/tablet.h" #include "sway/layers.h" #include "sway/output.h" +#include "sway/scene_descriptor.h" #include "sway/tree/container.h" #include "sway/tree/root.h" #include "sway/tree/view.h" @@ -541,11 +541,13 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { 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) { - drag_icon_update_position(drag_icon); - } + struct wlr_scene_node *node; + wl_list_for_each(node, &seat->drag_icons->children, link) { + struct sway_scene_descriptor *desc = node->data; + + sway_assert(desc && desc->type == SWAY_SCENE_DESC_DRAG_ICON, + "Corrupted scene tree: expected a drag icon"); + drag_icon_update_position(seat, desc->data); } } diff --git a/sway/input/seat.c b/sway/input/seat.c index 43b207799..a723f22e9 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -18,7 +18,7 @@ #include "list.h" #include "log.h" #include "sway/config.h" -#include "sway/desktop.h" +#include "sway/scene_descriptor.h" #include "sway/input/cursor.h" #include "sway/input/input-manager.h" #include "sway/input/keyboard.h" @@ -92,6 +92,7 @@ void seat_destroy(struct sway_seat *seat) { for (int i = 0; i < seat->deferred_bindings->length; i++) { free_sway_binding(seat->deferred_bindings->items[i]); } + wlr_scene_node_destroy(&seat->scene_tree->node); list_free(seat->deferred_bindings); free(seat->prev_workspace_name); free(seat); @@ -365,25 +366,15 @@ static void handle_new_node(struct wl_listener *listener, void *data) { seat_node_from_node(seat, node); } -static void drag_icon_damage_whole(struct sway_drag_icon *icon) { - if (!icon->wlr_drag_icon->mapped) { - return; - } - desktop_damage_surface(icon->wlr_drag_icon->surface, icon->x, icon->y, true); -} - -void drag_icon_update_position(struct sway_drag_icon *icon) { - drag_icon_damage_whole(icon); - +void drag_icon_update_position(struct sway_seat *seat, struct sway_drag_icon *icon) { struct wlr_drag_icon *wlr_icon = icon->wlr_drag_icon; - struct sway_seat *seat = icon->seat; struct wlr_cursor *cursor = seat->cursor->cursor; + switch (wlr_icon->drag->grab_type) { case WLR_DRAG_GRAB_KEYBOARD: return; case WLR_DRAG_GRAB_KEYBOARD_POINTER: - icon->x = cursor->x + wlr_icon->surface->sx; - icon->y = cursor->y + wlr_icon->surface->sy; + wlr_scene_node_set_position(&icon->tree->node, cursor->x, cursor->y); break; case WLR_DRAG_GRAB_KEYBOARD_TOUCH:; struct wlr_touch_point *point = @@ -391,38 +382,23 @@ void drag_icon_update_position(struct sway_drag_icon *icon) { if (point == NULL) { return; } - icon->x = seat->touch_x + wlr_icon->surface->sx; - icon->y = seat->touch_y + wlr_icon->surface->sy; + wlr_scene_node_set_position(&icon->tree->node, seat->touch_x, seat->touch_y); } - - drag_icon_damage_whole(icon); } -static void drag_icon_handle_surface_commit(struct wl_listener *listener, - void *data) { - struct sway_drag_icon *icon = - wl_container_of(listener, icon, surface_commit); - drag_icon_update_position(icon); -} - -static void drag_icon_handle_map(struct wl_listener *listener, void *data) { - struct sway_drag_icon *icon = wl_container_of(listener, icon, map); - drag_icon_damage_whole(icon); -} - -static void drag_icon_handle_unmap(struct wl_listener *listener, void *data) { - struct sway_drag_icon *icon = wl_container_of(listener, icon, unmap); - drag_icon_damage_whole(icon); +static void drag_icon_handle_commit(struct wl_listener *listener, void *data) { + struct sway_drag_icon *icon = wl_container_of(listener, icon, commit); + struct wlr_surface *surface = icon->wlr_drag_icon->surface; + wlr_scene_node_set_position(&icon->surface_tree->node, + surface->sx, surface->sy); } static void drag_icon_handle_destroy(struct wl_listener *listener, void *data) { struct sway_drag_icon *icon = wl_container_of(listener, icon, destroy); icon->wlr_drag_icon->data = NULL; - wl_list_remove(&icon->link); - wl_list_remove(&icon->surface_commit.link); - wl_list_remove(&icon->unmap.link); - wl_list_remove(&icon->map.link); + wl_list_remove(&icon->commit.link); wl_list_remove(&icon->destroy.link); + wlr_scene_node_destroy(&icon->tree->node); free(icon); } @@ -500,22 +476,40 @@ static void handle_start_drag(struct wl_listener *listener, void *data) { sway_log(SWAY_ERROR, "Allocation failed"); return; } - icon->seat = seat; + + icon->tree = wlr_scene_tree_create(seat->drag_icons); + if (!icon->tree) { + sway_log(SWAY_ERROR, "Failed to allocate a drag icon scene tree"); + free(icon); + return; + } + + icon->surface_tree = wlr_scene_subsurface_tree_create(icon->tree, + wlr_drag_icon->surface); + if (!icon->surface_tree) { + sway_log(SWAY_ERROR, "Failed to allocate a drag icon surface"); + wlr_scene_node_destroy(&icon->tree->node); + free(icon); + return; + } + + scene_descriptor_assign(&icon->tree->node, SWAY_SCENE_DESC_DRAG_ICON, icon); + if (!icon->tree->node.data) { + wlr_scene_node_destroy(&icon->tree->node); + free(icon); + return; + } + icon->wlr_drag_icon = wlr_drag_icon; wlr_drag_icon->data = icon; - icon->surface_commit.notify = drag_icon_handle_surface_commit; - wl_signal_add(&wlr_drag_icon->surface->events.commit, &icon->surface_commit); - icon->unmap.notify = drag_icon_handle_unmap; - wl_signal_add(&wlr_drag_icon->events.unmap, &icon->unmap); - icon->map.notify = drag_icon_handle_map; - wl_signal_add(&wlr_drag_icon->events.map, &icon->map); + icon->commit.notify = drag_icon_handle_commit; + wl_signal_add(&wlr_drag_icon->surface->events.commit, &icon->commit); + icon->destroy.notify = drag_icon_handle_destroy; wl_signal_add(&wlr_drag_icon->events.destroy, &icon->destroy); - wl_list_insert(&root->drag_icons, &icon->link); - - drag_icon_update_position(icon); + drag_icon_update_position(seat, icon); } seatop_begin_default(seat); } @@ -562,8 +556,18 @@ struct sway_seat *seat_create(const char *seat_name) { return NULL; } + bool alloc_failure = false; + seat->scene_tree = alloc_scene_tree(root->layers.seat, &alloc_failure); + seat->drag_icons = alloc_scene_tree(seat->scene_tree, &alloc_failure); + if (alloc_failure) { + wlr_scene_node_destroy(&seat->scene_tree->node); + free(seat); + return NULL; + } + seat->wlr_seat = wlr_seat_create(server.wl_display, seat_name); if (!sway_assert(seat->wlr_seat, "could not allocate seat")) { + wlr_scene_node_destroy(&seat->scene_tree->node); free(seat); return NULL; } @@ -571,6 +575,7 @@ struct sway_seat *seat_create(const char *seat_name) { seat->cursor = sway_cursor_create(seat); if (!seat->cursor) { + wlr_scene_node_destroy(&seat->scene_tree->node); wlr_seat_destroy(seat->wlr_seat); free(seat); return NULL; diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index 84acefdf6..286bbeba5 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -10,6 +10,7 @@ #include "sway/input/seat.h" #include "sway/input/tablet.h" #include "sway/output.h" +#include "sway/scene_descriptor.h" #include "sway/tree/view.h" #include "sway/tree/workspace.h" #include "log.h" @@ -585,6 +586,17 @@ static void check_focus_follows_mouse(struct sway_seat *seat, } } +static void drag_icons_update_position(struct sway_seat *seat) { + struct wlr_scene_node *node; + wl_list_for_each(node, &seat->drag_icons->children, link) { + struct sway_scene_descriptor *desc = node->data; + + sway_assert(desc && desc->type == SWAY_SCENE_DESC_DRAG_ICON, + "Corrupted scene tree: expected drag icon"); + drag_icon_update_position(seat, desc->data); + } +} + static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { struct seatop_default_event *e = seat->seatop_data; struct sway_cursor *cursor = seat->cursor; @@ -608,12 +620,7 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { wlr_seat_pointer_notify_clear_focus(seat->wlr_seat); } - struct sway_drag_icon *drag_icon; - wl_list_for_each(drag_icon, &root->drag_icons, link) { - if (drag_icon->seat == seat) { - drag_icon_update_position(drag_icon); - } - } + drag_icons_update_position(seat); e->previous_node = node; } @@ -643,12 +650,7 @@ static void handle_tablet_tool_motion(struct sway_seat *seat, wlr_tablet_v2_tablet_tool_notify_proximity_out(tool->tablet_v2_tool); } - struct sway_drag_icon *drag_icon; - wl_list_for_each(drag_icon, &root->drag_icons, link) { - if (drag_icon->seat == seat) { - drag_icon_update_position(drag_icon); - } - } + drag_icons_update_position(seat); e->previous_node = node; } diff --git a/sway/tree/root.c b/sway/tree/root.c index b7dbf2490..faa6a478e 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c @@ -63,7 +63,6 @@ struct sway_root *root_create(void) { #if HAVE_XWAYLAND wl_list_init(&root->xwayland_unmanaged); #endif - wl_list_init(&root->drag_icons); wl_signal_init(&root->events.new_node); root->outputs = create_list(); root->non_desktop_outputs = create_list();