From e4d0ec9ee104044dec69c81990b7a0cd5cf039f3 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 10 Aug 2021 11:26:34 +0200 Subject: [PATCH] scene: add wlr_scene_node_surface_at --- include/wlr/types/wlr_scene.h | 7 +++++++ types/wlr_scene.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 282685a7..8a327262 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -97,6 +97,13 @@ void wlr_scene_node_place_below(struct wlr_scene_node *node, */ void wlr_scene_node_for_each_surface(struct wlr_scene_node *node, wlr_surface_iterator_func_t iterator, void *user_data); +/** + * Find a surface in this scene-graph that accepts input events at the given + * layout-local coordinates. Returns the surface and coordinates relative to + * the returned surface, or NULL if no surface is found at that location. + */ +struct wlr_surface *wlr_scene_node_surface_at(struct wlr_scene_node *node, + double lx, double ly, double *sx, double *sy); /** * Create a new scene-graph. diff --git a/types/wlr_scene.c b/types/wlr_scene.c index b2039feb..7e8c332b 100644 --- a/types/wlr_scene.c +++ b/types/wlr_scene.c @@ -159,6 +159,41 @@ void wlr_scene_node_for_each_surface(struct wlr_scene_node *node, scene_node_for_each_surface(node, 0, 0, user_iterator, user_data); } +struct wlr_surface *wlr_scene_node_surface_at(struct wlr_scene_node *node, + double lx, double ly, double *sx, double *sy) { + if (!node->state.enabled) { + return NULL; + } + + // TODO: optimize by storing a bounding box in each node? + lx -= node->state.x; + ly -= node->state.y; + + struct wlr_scene_node *child; + wl_list_for_each_reverse(child, &node->state.children, state.link) { + struct wlr_surface *surface = + wlr_scene_node_surface_at(child, lx, ly, sx, sy); + if (surface != NULL) { + return surface; + } + } + + if (node->type == WLR_SCENE_NODE_SURFACE) { + struct wlr_scene_surface *scene_surface = scene_surface_from_node(node); + if (wlr_surface_point_accepts_input(scene_surface->surface, lx, ly)) { + if (sx != NULL) { + *sx = lx; + } + if (sy != NULL) { + *sy = ly; + } + return scene_surface->surface; + } + } + + return NULL; +} + static int scale_length(int length, int offset, float scale) { return round((offset + length) * scale) - round(offset * scale); }