From 776136fcd7fbf4afe5d0980e7f10bffd7090eb0c Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 26 Aug 2024 15:09:44 -0400 Subject: [PATCH 1/9] scene_descriptor: Move sway_popup_desc to scene_descriptor.h We'll want to use the descriptor type for a helper soon and we don't want to pull all of view.h with us. --- include/sway/scene_descriptor.h | 8 ++++++++ include/sway/tree/view.h | 6 +----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/include/sway/scene_descriptor.h b/include/sway/scene_descriptor.h index 2649d7c29..9ffb2e5da 100644 --- a/include/sway/scene_descriptor.h +++ b/include/sway/scene_descriptor.h @@ -10,6 +10,14 @@ #define _SWAY_SCENE_DESCRIPTOR_H #include +struct sway_view; + +// used for SWAY_SCENE_DESC_POPUP +struct sway_popup_desc { + struct wlr_scene_node *relative; + struct sway_view *view; +}; + enum sway_scene_descriptor_type { SWAY_SCENE_DESC_BUFFER_TIMER, SWAY_SCENE_DESC_NON_INTERACTIVE, diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index d999b5024..42624000f 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -11,6 +11,7 @@ #endif #include "sway/input/input-manager.h" #include "sway/input/seat.h" +#include "sway/scene_descriptor.h" struct sway_container; struct sway_xdg_decoration; @@ -190,11 +191,6 @@ struct sway_xwayland_unmanaged { }; #endif -struct sway_popup_desc { - struct wlr_scene_node *relative; - struct sway_view *view; -}; - struct sway_xdg_popup { struct sway_view *view; struct wlr_xdg_popup *wlr_xdg_popup; From f55221ff40af945c393a1b81f840166c858dd40b Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 26 Aug 2024 15:36:31 -0400 Subject: [PATCH 2/9] scene_descriptor: Add scene_descriptor_find --- include/sway/scene_descriptor.h | 10 ++++++++++ sway/scene_descriptor.c | 25 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/include/sway/scene_descriptor.h b/include/sway/scene_descriptor.h index 9ffb2e5da..f29bb6b1d 100644 --- a/include/sway/scene_descriptor.h +++ b/include/sway/scene_descriptor.h @@ -38,4 +38,14 @@ void *scene_descriptor_try_get(struct wlr_scene_node *node, void scene_descriptor_destroy(struct wlr_scene_node *node, enum sway_scene_descriptor_type type); +/* + * Searches the scene node and all its parents for this scene descriptor. + * + * Note that while searching, SWAY_SCENE_DESC_POPUP types will start tracking + * its relative node. With popups, they are part of a seperate layer in the scene + * graph, but that's irrelavent to users of this function. + */ +void *scene_descriptor_find(struct wlr_scene_node *node, + enum sway_scene_descriptor_type type); + #endif diff --git a/sway/scene_descriptor.c b/sway/scene_descriptor.c index 92bdda00c..5768a8802 100644 --- a/sway/scene_descriptor.c +++ b/sway/scene_descriptor.c @@ -36,6 +36,31 @@ void *scene_descriptor_try_get(struct wlr_scene_node *node, return desc->data; } +void *scene_descriptor_find(struct wlr_scene_node *node, + enum sway_scene_descriptor_type type) { + while (node) { + struct scene_descriptor *desc = scene_node_get_descriptor(node, type); + if (desc) { + return desc->data; + } + + struct sway_popup_desc *popup = + scene_descriptor_try_get(node, SWAY_SCENE_DESC_POPUP); + if (popup) { + node = popup->relative; + continue; + } + + if (!node->parent) { + break; + } + + node = &node->parent->node; + } + + return NULL; +} + void scene_descriptor_destroy(struct wlr_scene_node *node, enum sway_scene_descriptor_type type) { struct scene_descriptor *desc = scene_node_get_descriptor(node, type); From b6cae6fc72fb3bae73ce92655e2f8d2f80fa8881 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 26 Aug 2024 15:31:17 -0400 Subject: [PATCH 3/9] output: Use scene_descriptor_find to compute max_render_time --- sway/desktop/output.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index eeb203ffc..4816bd332 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -158,20 +158,9 @@ static void send_frame_done_iterator(struct wlr_scene_buffer *buffer, return; } - struct wlr_scene_node *current = &buffer->node; - while (true) { - struct sway_view *view = scene_descriptor_try_get(current, - SWAY_SCENE_DESC_VIEW); - if (view) { - view_max_render_time = view->max_render_time; - break; - } - - if (!current->parent) { - break; - } - - current = ¤t->parent->node; + struct sway_view *view = scene_descriptor_find(&buffer->node, SWAY_SCENE_DESC_VIEW); + if (view) { + view_max_render_time = view->max_render_time; } int delay = data->msec_until_refresh - output->max_render_time From bd8f12915fc12e8d94cb408d86005043d0dcc5fe Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 26 Aug 2024 15:46:55 -0400 Subject: [PATCH 4/9] scene_descriptor: Add scene_descriptor_reassign Same as the assign variant, but lets us mutate an existing descriptor if it exists instead of asserting. --- include/sway/scene_descriptor.h | 3 +++ sway/scene_descriptor.c | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/include/sway/scene_descriptor.h b/include/sway/scene_descriptor.h index f29bb6b1d..e71b5c42a 100644 --- a/include/sway/scene_descriptor.h +++ b/include/sway/scene_descriptor.h @@ -32,6 +32,9 @@ enum sway_scene_descriptor_type { bool scene_descriptor_assign(struct wlr_scene_node *node, enum sway_scene_descriptor_type type, void *data); +bool scene_descriptor_reassign(struct wlr_scene_node *node, + enum sway_scene_descriptor_type type, void *data); + void *scene_descriptor_try_get(struct wlr_scene_node *node, enum sway_scene_descriptor_type type); diff --git a/sway/scene_descriptor.c b/sway/scene_descriptor.c index 5768a8802..ca0003058 100644 --- a/sway/scene_descriptor.c +++ b/sway/scene_descriptor.c @@ -92,3 +92,14 @@ bool scene_descriptor_assign(struct wlr_scene_node *node, desc->data = data; return true; } + +bool scene_descriptor_reassign(struct wlr_scene_node *node, + enum sway_scene_descriptor_type type, void *data) { + struct scene_descriptor *desc = scene_node_get_descriptor(node, type); + if (desc) { + desc->data = data; + return true; + } + + return scene_descriptor_assign(node, type, data); +} From e944e037517b79ae554157465fc1a601cfb1dd5b Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 26 Aug 2024 15:46:04 -0400 Subject: [PATCH 5/9] container: Assign container scene descriptor to view aswell We have to do with for fullscreen surfaces: Fullscreen surfaces technically aren't part of their container anymore visually (so the scene doesn't have it) but we want acknowledge the container it belongs to for input reasons. This will allow us to simplify node_at_coords later. --- sway/input/cursor.c | 8 -------- sway/tree/container.c | 1 + sway/tree/view.c | 2 ++ 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index aeab558cb..c40a088bc 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -76,14 +76,6 @@ struct sway_node *node_at_coords( struct sway_container *con = scene_descriptor_try_get(current, SWAY_SCENE_DESC_CONTAINER); - if (!con) { - struct sway_view *view = scene_descriptor_try_get(current, - SWAY_SCENE_DESC_VIEW); - if (view) { - con = view->container; - } - } - if (!con) { struct sway_popup_desc *popup = scene_descriptor_try_get(current, SWAY_SCENE_DESC_POPUP); diff --git a/sway/tree/container.c b/sway/tree/container.c index af68e22fd..50a84c228 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -556,6 +556,7 @@ void container_destroy(struct sway_container *con) { if (con->view && con->view->container == con) { con->view->container = NULL; + scene_descriptor_destroy(&con->view->scene_tree->node, SWAY_SCENE_DESC_CONTAINER); wlr_scene_node_destroy(&con->output_handler->node); } diff --git a/sway/tree/view.c b/sway/tree/view.c index d4f72211b..4c026b045 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -750,6 +750,8 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, view->surface = wlr_surface; view_populate_pid(view); view->container = container_create(view); + scene_descriptor_assign(&view->scene_tree->node, + SWAY_SCENE_DESC_CONTAINER, view->container); if (view->ctx == NULL) { struct launcher_ctx *ctx = launcher_ctx_find_pid(view->pid); From 021509589438b2adc8533ab06b7b5f7a78f862cc Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 26 Aug 2024 16:09:42 -0400 Subject: [PATCH 6/9] cursor: Simplify node_at_coords with scene_descriptor_find --- sway/input/cursor.c | 48 +++++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index c40a088bc..65e16348f 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -70,42 +70,30 @@ struct sway_node *node_at_coords( } } - // determine what container we clicked on - struct wlr_scene_node *current = scene_node; - while (true) { - struct sway_container *con = scene_descriptor_try_get(current, - SWAY_SCENE_DESC_CONTAINER); + struct sway_container *con = + scene_descriptor_find(scene_node, SWAY_SCENE_DESC_CONTAINER); - if (!con) { - struct sway_popup_desc *popup = - scene_descriptor_try_get(current, SWAY_SCENE_DESC_POPUP); - if (popup && popup->view) { - con = popup->view->container; - } - } - - if (con && (!con->view || con->view->surface)) { - return &con->node; - } - - if (scene_descriptor_try_get(current, SWAY_SCENE_DESC_LAYER_SHELL)) { - // We don't want to feed through the current workspace on - // layer shells + if (con) { + // If this condition succeeds, the container is currently in the + // process of being destroyed. In this case, ignore the container + if (con->view && !con->view->surface) { return NULL; } + return &con->node; + } + + // if we clicked on a layer shell or unmanaged xwayland we don't + // want to return the workspace node. + if (scene_descriptor_find(scene_node, SWAY_SCENE_DESC_LAYER_SHELL)) { + return NULL; + } + #if WLR_HAS_XWAYLAND - if (scene_descriptor_try_get(current, SWAY_SCENE_DESC_XWAYLAND_UNMANAGED)) { - return NULL; - } -#endif - - if (!current->parent) { - break; - } - - current = ¤t->parent->node; + if (scene_descriptor_find(scene_node, SWAY_SCENE_DESC_XWAYLAND_UNMANAGED)) { + return NULL; } +#endif } // if we aren't on a container, determine what workspace we are on From 1e373856ed6c307b19a9012c6eb9b45d1afc5b73 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 26 Aug 2024 16:19:18 -0400 Subject: [PATCH 7/9] cursor: Remove node_at_coords unused seat parameter --- include/sway/input/cursor.h | 3 +-- sway/commands/bind.c | 2 +- sway/input/cursor.c | 14 +++++--------- sway/input/seatop_default.c | 25 ++++++++++++------------- sway/input/seatop_down.c | 2 +- sway/input/seatop_move_tiling.c | 4 ++-- 6 files changed, 22 insertions(+), 28 deletions(-) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 527d03500..8b3ce941f 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -85,8 +85,7 @@ struct sway_cursor { struct sway_node; struct sway_node *node_at_coords( - struct sway_seat *seat, double lx, double ly, - struct wlr_surface **surface, double *sx, double *sy); + double lx, double ly, struct wlr_surface **surface, double *sx, double *sy); void sway_cursor_destroy(struct sway_cursor *cursor); struct sway_cursor *sway_cursor_create(struct sway_seat *seat); diff --git a/sway/commands/bind.c b/sway/commands/bind.c index 15373d5a8..e160d583b 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -620,7 +620,7 @@ void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) || binding->type == BINDING_MOUSECODE) { struct wlr_surface *surface = NULL; double sx, sy; - struct sway_node *node = node_at_coords(seat, + struct sway_node *node = node_at_coords( seat->cursor->cursor->x, seat->cursor->cursor->y, &surface, &sx, &sy); if (node && node->type == N_CONTAINER) { diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 65e16348f..f46cf6699 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -36,8 +36,7 @@ * Returns the node at the cursor's position. If there is a surface at that * location, it is stored in **surface (it may not be a view). */ -struct sway_node *node_at_coords( - struct sway_seat *seat, double lx, double ly, +struct sway_node *node_at_coords(double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { struct wlr_scene_node *scene_node = NULL; @@ -279,8 +278,7 @@ void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, if (cursor->active_constraint && device->type == WLR_INPUT_DEVICE_POINTER) { struct wlr_surface *surface = NULL; double sx, sy; - node_at_coords(cursor->seat, - cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); + node_at_coords(cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); if (cursor->active_constraint->surface != surface) { return; @@ -539,7 +537,7 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor, double sx, sy; struct wlr_surface *surface = NULL; struct sway_seat *seat = cursor->seat; - node_at_coords(seat, cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); + node_at_coords(cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); // The logic for whether we should send a tablet event or an emulated pointer // event is tricky. It comes down to: @@ -629,8 +627,7 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) { double sx, sy; struct wlr_surface *surface = NULL; - node_at_coords(seat, cursor->cursor->x, cursor->cursor->y, - &surface, &sx, &sy); + node_at_coords(cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); if (cursor->simulating_pointer_from_tool_tip && event->state == WLR_TABLET_TOOL_TIP_UP) { @@ -714,8 +711,7 @@ static void handle_tool_button(struct wl_listener *listener, void *data) { double sx, sy; struct wlr_surface *surface = NULL; - node_at_coords(cursor->seat, cursor->cursor->x, cursor->cursor->y, - &surface, &sx, &sy); + node_at_coords(cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); // TODO: floating resize should support graphics tablet events struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(cursor->seat->wlr_seat); diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index 19645b4c9..80cc457da 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -224,7 +224,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, struct sway_cursor *cursor = seat->cursor; struct wlr_surface *surface = NULL; double sx, sy; - struct sway_node *node = node_at_coords(seat, + struct sway_node *node = node_at_coords( cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); if (!sway_assert(surface, @@ -337,8 +337,8 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, // Determine what's under the cursor struct wlr_surface *surface = NULL; double sx, sy; - struct sway_node *node = node_at_coords(seat, - cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); + struct sway_node *node = node_at_coords( + cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); struct sway_container *cont = node && node->type == N_CONTAINER ? node->sway_container : NULL; @@ -550,8 +550,7 @@ static void check_focus_follows_mouse(struct sway_seat *seat, struct wlr_surface *surface = NULL; double sx, sy; - node_at_coords(seat, seat->cursor->cursor->x, seat->cursor->cursor->y, - &surface, &sx, &sy); + node_at_coords(seat->cursor->cursor->x, seat->cursor->cursor->y, &surface, &sx, &sy); // Focus topmost layer surface struct wlr_layer_surface_v1 *layer = NULL; @@ -605,8 +604,8 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { struct wlr_surface *surface = NULL; double sx, sy; - struct sway_node *node = node_at_coords(seat, - cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); + struct sway_node *node = node_at_coords( + cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); if (config->focus_follows_mouse != FOLLOWS_NO) { check_focus_follows_mouse(seat, e, node); @@ -634,8 +633,8 @@ static void handle_tablet_tool_motion(struct sway_seat *seat, struct wlr_surface *surface = NULL; double sx, sy; - struct sway_node *node = node_at_coords(seat, - cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); + struct sway_node *node = node_at_coords( + cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); if (config->focus_follows_mouse != FOLLOWS_NO) { check_focus_follows_mouse(seat, e, node); @@ -663,7 +662,7 @@ static void handle_touch_down(struct sway_seat *seat, 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); + node_at_coords(seat->touch_x, seat->touch_y, &surface, &sx, &sy); if (surface && wlr_surface_accepts_touch(surface, wlr_seat)) { if (seat_is_input_allowed(seat, surface)) { @@ -715,7 +714,7 @@ static void handle_pointer_axis(struct sway_seat *seat, // Determine what's under the cursor struct wlr_surface *surface = NULL; double sx, sy; - struct sway_node *node = node_at_coords(seat, + struct sway_node *node = node_at_coords( cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); struct sway_container *cont = node && node->type == N_CONTAINER ? node->sway_container : NULL; @@ -1107,8 +1106,8 @@ static void handle_rebase(struct sway_seat *seat, uint32_t time_msec) { struct sway_cursor *cursor = seat->cursor; struct wlr_surface *surface = NULL; double sx = 0.0, sy = 0.0; - e->previous_node = node_at_coords(seat, - cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); + e->previous_node = node_at_coords( + cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); if (surface) { if (seat_is_input_allowed(seat, surface)) { diff --git a/sway/input/seatop_down.c b/sway/input/seatop_down.c index f64e5a4f2..dd750f571 100644 --- a/sway/input/seatop_down.c +++ b/sway/input/seatop_down.c @@ -75,7 +75,7 @@ static void handle_touch_down(struct sway_seat *seat, 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, + struct sway_node *focused_node = node_at_coords(seat->touch_x, seat->touch_y, &surface, &sx, &sy); if (!surface || surface != e->surface) { // Must start from the initial surface diff --git a/sway/input/seatop_move_tiling.c b/sway/input/seatop_move_tiling.c index c525b77a9..eca243622 100644 --- a/sway/input/seatop_move_tiling.c +++ b/sway/input/seatop_move_tiling.c @@ -163,8 +163,8 @@ static void handle_motion_postthreshold(struct sway_seat *seat) { struct wlr_surface *surface = NULL; double sx, sy; struct sway_cursor *cursor = seat->cursor; - struct sway_node *node = node_at_coords(seat, - cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); + struct sway_node *node = node_at_coords( + cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); if (!node) { // Eg. hovered over a layer surface such as swaybar From 2dacfb7983f102212ddd209035eff204a43bd07e Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 26 Aug 2024 17:13:47 -0400 Subject: [PATCH 8/9] cursor: Split node_at_coords into smaller functions --- include/sway/input/cursor.h | 8 +++++ sway/input/cursor.c | 67 +++++++++++++++++++++++-------------- 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 8b3ce941f..527218dc8 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -84,6 +84,14 @@ struct sway_cursor { struct sway_node; +struct wlr_scene_node *scene_node_at_coords( + double lx, double ly, double *sx, double *sy); + +struct wlr_surface *surface_try_from_scene_node(struct wlr_scene_node *node); + +struct sway_node *sway_node_try_from_scene_node(struct wlr_scene_node *node, + double lx, double ly); + struct sway_node *node_at_coords( double lx, double ly, struct wlr_surface **surface, double *sx, double *sy); diff --git a/sway/input/cursor.c b/sway/input/cursor.c index f46cf6699..5afa6d248 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -32,14 +32,8 @@ #include "sway/tree/workspace.h" #include "wlr-layer-shell-unstable-v1-protocol.h" -/** - * Returns the node at the cursor's position. If there is a surface at that - * location, it is stored in **surface (it may not be a view). - */ -struct sway_node *node_at_coords(double lx, double ly, - struct wlr_surface **surface, double *sx, double *sy) { - struct wlr_scene_node *scene_node = NULL; - +struct wlr_scene_node *scene_node_at_coords( + double lx, double ly, double *sx, double *sy) { struct wlr_scene_node *node; wl_list_for_each_reverse(node, &root->layer_tree->children, link) { struct wlr_scene_tree *layer = wlr_scene_tree_from_node(node); @@ -50,28 +44,37 @@ struct sway_node *node_at_coords(double lx, double ly, continue; } - scene_node = wlr_scene_node_at(&layer->node, lx, ly, sx, sy); - if (scene_node) { - break; + struct wlr_scene_node *node = wlr_scene_node_at(&layer->node, lx, ly, sx, sy); + if (node) { + return node; } } - if (scene_node) { - // determine what wlr_surface we clicked on - if (scene_node->type == WLR_SCENE_NODE_BUFFER) { - struct wlr_scene_buffer *scene_buffer = - wlr_scene_buffer_from_node(scene_node); - struct wlr_scene_surface *scene_surface = - wlr_scene_surface_try_from_buffer(scene_buffer); + return NULL; +} - if (scene_surface) { - *surface = scene_surface->surface; - } - } +struct wlr_surface *surface_try_from_scene_node(struct wlr_scene_node *node) { + if (!node || node->type != WLR_SCENE_NODE_BUFFER) { + return NULL; + } + struct wlr_scene_buffer *scene_buffer = + wlr_scene_buffer_from_node(node); + struct wlr_scene_surface *scene_surface = + wlr_scene_surface_try_from_buffer(scene_buffer); + + if (scene_surface) { + return scene_surface->surface; + } + + return NULL; +} + +struct sway_node *sway_node_try_from_scene_node(struct wlr_scene_node *node, + double lx, double ly) { + if (node) { struct sway_container *con = - scene_descriptor_find(scene_node, SWAY_SCENE_DESC_CONTAINER); - + scene_descriptor_find(node, SWAY_SCENE_DESC_CONTAINER); if (con) { // If this condition succeeds, the container is currently in the // process of being destroyed. In this case, ignore the container @@ -84,12 +87,12 @@ struct sway_node *node_at_coords(double lx, double ly, // if we clicked on a layer shell or unmanaged xwayland we don't // want to return the workspace node. - if (scene_descriptor_find(scene_node, SWAY_SCENE_DESC_LAYER_SHELL)) { + if (scene_descriptor_find(node, SWAY_SCENE_DESC_LAYER_SHELL)) { return NULL; } #if WLR_HAS_XWAYLAND - if (scene_descriptor_find(scene_node, SWAY_SCENE_DESC_XWAYLAND_UNMANAGED)) { + if (scene_descriptor_find(node, SWAY_SCENE_DESC_XWAYLAND_UNMANAGED)) { return NULL; } #endif @@ -116,6 +119,18 @@ struct sway_node *node_at_coords(double lx, double ly, return &ws->node; } +/** + * Returns the node at the cursor's position. If there is a surface at that + * location, it is stored in **surface (it may not be a view). + */ +struct sway_node *node_at_coords(double lx, double ly, + struct wlr_surface **surface, double *sx, double *sy) { + struct wlr_scene_node *scene_node = scene_node_at_coords(lx, ly, sx, sy); + *surface = surface_try_from_scene_node(scene_node); + + return sway_node_try_from_scene_node(scene_node, lx, ly); +} + void cursor_rebase(struct sway_cursor *cursor) { uint32_t time_msec = get_current_time_in_msec(); seatop_rebase(cursor->seat, time_msec); From f317198c2cec07640395f24416a718de885c9bb3 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 26 Aug 2024 16:55:59 -0400 Subject: [PATCH 9/9] layer_shell: Replace toplevel_layer_surface_from_surface with scene_descriptor_find We can instead search the scene instead of hand rolling this logic --- include/sway/layers.h | 3 --- sway/desktop/layer_shell.c | 33 --------------------------------- sway/input/seatop_default.c | 29 +++++++++++++++-------------- 3 files changed, 15 insertions(+), 50 deletions(-) diff --git a/include/sway/layers.h b/include/sway/layers.h index fd6384e0e..7627c9091 100644 --- a/include/sway/layers.h +++ b/include/sway/layers.h @@ -36,9 +36,6 @@ struct sway_layer_popup { struct sway_output; -struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface( - struct wlr_surface *surface); - void arrange_layers(struct sway_output *output); #endif diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 08b5b1de2..dac86883c 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -20,39 +20,6 @@ #include "sway/tree/arrange.h" #include "sway/tree/workspace.h" -struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface( - struct wlr_surface *surface) { - struct wlr_layer_surface_v1 *layer; - do { - if (!surface) { - return NULL; - } - // Topmost layer surface - if ((layer = wlr_layer_surface_v1_try_from_wlr_surface(surface))) { - return layer; - } - // Layer subsurface - if (wlr_subsurface_try_from_wlr_surface(surface)) { - surface = wlr_surface_get_root_surface(surface); - continue; - } - - // Layer surface popup - struct wlr_xdg_surface *xdg_surface = NULL; - if ((xdg_surface = wlr_xdg_surface_try_from_wlr_surface(surface)) && - xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP && xdg_surface->popup != NULL) { - if (!xdg_surface->popup->parent) { - return NULL; - } - surface = wlr_surface_get_root_surface(xdg_surface->popup->parent); - continue; - } - - // Return early if the surface is not a layer/xdg_popup/sub surface - return NULL; - } while (true); -} - static void arrange_surface(struct sway_output *output, const struct wlr_box *full_area, struct wlr_box *usable_area, struct wlr_scene_tree *tree, bool exclusive) { struct wlr_scene_node *node; diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index 80cc457da..f158e3332 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -335,10 +335,12 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, struct sway_cursor *cursor = seat->cursor; // Determine what's under the cursor - struct wlr_surface *surface = NULL; double sx, sy; - struct sway_node *node = node_at_coords( - cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); + struct wlr_scene_node *scene_node = + scene_node_at_coords(cursor->cursor->x, cursor->cursor->y, &sx, &sy); + struct wlr_surface *surface = scene_node ? surface_try_from_scene_node(scene_node) : NULL; + struct sway_node *node = sway_node_try_from_scene_node(scene_node, + cursor->cursor->x, cursor->cursor->y); struct sway_container *cont = node && node->type == N_CONTAINER ? node->sway_container : NULL; @@ -380,10 +382,10 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, } // Handle clicking a layer surface and its popups/subsurfaces - struct wlr_layer_surface_v1 *layer = NULL; - if ((layer = toplevel_layer_surface_from_surface(surface))) { - if (layer->current.keyboard_interactive) { - seat_set_focus_layer(seat, layer); + struct sway_layer_surface *layer = NULL; + if ((layer = scene_descriptor_find(scene_node, SWAY_SCENE_DESC_LAYER_SHELL))) { + if (layer->layer_surface->current.keyboard_interactive) { + seat_set_focus_layer(seat, layer->layer_surface); transaction_commit_dirty(); } if (state == WL_POINTER_BUTTON_STATE_PRESSED) { @@ -548,15 +550,14 @@ static void check_focus_follows_mouse(struct sway_seat *seat, return; } - struct wlr_surface *surface = NULL; - double sx, sy; - node_at_coords(seat->cursor->cursor->x, seat->cursor->cursor->y, &surface, &sx, &sy); + struct wlr_scene_node *node = scene_node_at_coords( + seat->cursor->cursor->x, seat->cursor->cursor->y, NULL, NULL); // Focus topmost layer surface - struct wlr_layer_surface_v1 *layer = NULL; - if ((layer = toplevel_layer_surface_from_surface(surface)) && - layer->current.keyboard_interactive) { - seat_set_focus_layer(seat, layer); + struct sway_layer_surface *layer = NULL; + if ((layer = scene_descriptor_find(node, SWAY_SCENE_DESC_LAYER_SHELL)) && + layer->layer_surface->current.keyboard_interactive) { + seat_set_focus_layer(seat, layer->layer_surface); transaction_commit_dirty(); return; }