From d3f0929f7959b3ee3d1ebe0358fa204bbca50c92 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 2649d7c296..9ffb2e5da4 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 14aad1a183..22efbfc640 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; @@ -187,11 +188,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; From 1a9b3ce0d04073faff0bcf1d0480cc1c0fe5b830 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 9ffb2e5da4..f29bb6b1df 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 a30d466466..68cd6e7fe6 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 93961e988b51c5a9648ff0c53fe96532abc01443 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 a71430fe52..ae49b649ba 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -151,20 +151,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 bdcffbd6118c91471eb8050d16de87fd116a8c17 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 f29bb6b1df..e71b5c42a8 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 68cd6e7fe6..2f03fc59c8 100644 --- a/sway/scene_descriptor.c +++ b/sway/scene_descriptor.c @@ -89,3 +89,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 3e7306489f8d259b2df7e793b4ff743ce3ecfa37 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 | 2 ++ sway/tree/view.c | 2 ++ 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index bbd16717ff..f0ee2f92ae 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -82,14 +82,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 46c388b3ee..8f1607217d 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -506,6 +506,8 @@ 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); if (con->view->destroying) { view_destroy(con->view); diff --git a/sway/tree/view.c b/sway/tree/view.c index d25a09c2a2..a287e81c44 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -723,6 +723,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 4a3c13f1baaa881750f4d76d4bd4a23618f66ede 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 | 46 +++++++++++++++++---------------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index f0ee2f92ae..4a0846d523 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -76,42 +76,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); - - 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; - } + struct sway_container *con = + scene_descriptor_find(scene_node, SWAY_SCENE_DESC_CONTAINER); - 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; } -#if WLR_HAS_XWAYLAND - if (scene_descriptor_try_get(current, SWAY_SCENE_DESC_XWAYLAND_UNMANAGED)) { - return NULL; - } -#endif + return &con->node; + } - if (!current->parent) { - break; - } + // 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; + } - current = ¤t->parent->node; +#if WLR_HAS_XWAYLAND + 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 6ceade3ad2e12926d7840772294a3ae3a8f897f9 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 527d03500c..8b3ce941f9 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 268f285537..8361a06f6b 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -621,7 +621,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 4a0846d523..fff6067e1f 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -42,8 +42,7 @@ static uint32_t get_current_time_msec(void) { * 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; @@ -285,8 +284,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; @@ -545,7 +543,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: @@ -635,8 +633,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) { @@ -720,8 +717,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 42ce333b86..4b8200e810 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -223,7 +223,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, @@ -336,8 +336,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; @@ -552,8 +552,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; @@ -607,8 +606,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); @@ -636,8 +635,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); @@ -665,7 +664,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)) { @@ -717,7 +716,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; @@ -1109,8 +1108,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 340e334bfd..b79888de11 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 c525b77a9e..eca2436221 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 1ee209dc56446fd53e82d6854ad1bd0634eae022 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 8b3ce941f9..527218dc89 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 fff6067e1f..068390f9f3 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -38,14 +38,8 @@ static uint32_t get_current_time_msec(void) { return now.tv_sec * 1000 + now.tv_nsec / 1000000; } -/** - * 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); @@ -56,28 +50,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 sway_container *con = - scene_descriptor_find(scene_node, SWAY_SCENE_DESC_CONTAINER); + 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(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 @@ -90,12 +93,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 @@ -122,6 +125,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_msec(); seatop_rebase(cursor->seat, time_msec); From eadc380a307b7975fea8dafc9bfe0a766f9ed279 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 fd6384e0ee..7627c9091e 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 b136a24e7b..f52db2e418 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) { struct wlr_scene_node *node; diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index 4b8200e810..fb58db8afe 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -334,10 +334,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; @@ -372,10 +374,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) { @@ -550,15 +552,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; }