diff options
author | Alexander Orzechowski <alex@ozal.ski> | 2023-11-23 10:09:48 -0500 |
---|---|---|
committer | Kirill Primak <vyivel@eclair.cafe> | 2024-01-18 18:36:54 +0300 |
commit | 5b8b505af5d5925ae9e617ee8f3c7a0f9c43409d (patch) | |
tree | f420022ad3a48215f9182505c0060d91edcd848e /sway/input/cursor.c | |
parent | 946fc8094559801bc4be629368ac31025d28165a (diff) |
input: Query scene graph for relevant surface/node intersections
Diffstat (limited to 'sway/input/cursor.c')
-rw-r--r-- | sway/input/cursor.c | 184 |
1 files changed, 55 insertions, 129 deletions
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 107424c9..79373e40 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -37,43 +37,6 @@ static uint32_t get_current_time_msec(void) { return now.tv_sec * 1000 + now.tv_nsec / 1000000; } -static struct wlr_surface *layer_surface_at(struct sway_output *output, - struct wl_list *layer, double ox, double oy, double *sx, double *sy) { - struct sway_layer_surface *sway_layer; - wl_list_for_each_reverse(sway_layer, layer, link) { - double _sx = ox - sway_layer->geo.x; - double _sy = oy - sway_layer->geo.y; - struct wlr_surface *sub = wlr_layer_surface_v1_surface_at( - sway_layer->layer_surface, _sx, _sy, sx, sy); - if (sub) { - return sub; - } - } - return NULL; -} - -static bool surface_is_xdg_popup(struct wlr_surface *surface) { - struct wlr_xdg_surface *xdg_surface = - wlr_xdg_surface_try_from_wlr_surface(surface); - return xdg_surface != NULL && xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP && - xdg_surface->popup != NULL; -} - -static struct wlr_surface *layer_surface_popup_at(struct sway_output *output, - struct wl_list *layer, double ox, double oy, double *sx, double *sy) { - struct sway_layer_surface *sway_layer; - wl_list_for_each_reverse(sway_layer, layer, link) { - double _sx = ox - sway_layer->geo.x; - double _sy = oy - sway_layer->geo.y; - struct wlr_surface *sub = wlr_layer_surface_v1_surface_at( - sway_layer->layer_surface, _sx, _sy, sx, sy); - if (sub && surface_is_xdg_popup(sub)) { - return sub; - } - } - return NULL; -} - /** * 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). @@ -81,116 +44,79 @@ static struct wlr_surface *layer_surface_popup_at(struct sway_output *output, struct sway_node *node_at_coords( struct sway_seat *seat, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { - // find the output the cursor is on - struct wlr_output *wlr_output = wlr_output_layout_output_at( - root->output_layout, lx, ly); - if (wlr_output == NULL) { - return NULL; - } - struct sway_output *output = wlr_output->data; - if (!output || !output->enabled) { - // output is being destroyed or is being enabled - return NULL; - } - double ox = lx, oy = ly; - wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy); + struct wlr_scene_node *scene_node = NULL; - // layer surfaces on the overlay layer are rendered on top - if ((*surface = layer_surface_at(output, - &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], - ox, oy, sx, sy))) { - return NULL; - } + 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); - // check for unmanaged views -#if HAVE_XWAYLAND - struct wl_list *unmanaged = &root->xwayland_unmanaged; - struct sway_xwayland_unmanaged *unmanaged_surface; - wl_list_for_each_reverse(unmanaged_surface, unmanaged, link) { - struct wlr_xwayland_surface *xsurface = - unmanaged_surface->wlr_xwayland_surface; - - double _sx = lx - unmanaged_surface->lx; - double _sy = ly - unmanaged_surface->ly; - if (wlr_surface_point_accepts_input(xsurface->surface, _sx, _sy)) { - *surface = xsurface->surface; - *sx = _sx; - *sy = _sy; - return NULL; + bool non_interactive = scene_descriptor_try_get(&layer->node, + SWAY_SCENE_DESC_NON_INTERACTIVE); + if (non_interactive) { + continue; } - } -#endif - if (root->fullscreen_global) { - // Try fullscreen container - struct sway_container *con = tiling_container_at( - &root->fullscreen_global->node, lx, ly, surface, sx, sy); - if (con) { - return &con->node; + scene_node = wlr_scene_node_at(&layer->node, lx, ly, sx, sy); + if (scene_node) { + break; } - return NULL; } - // find the focused workspace on the output for this seat - struct sway_workspace *ws = output_get_active_workspace(output); - if (!ws) { - return NULL; - } + 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); + + if (scene_surface) { + *surface = scene_surface->surface; + } + } - if (ws->fullscreen) { - // Try transient containers - for (int i = 0; i < ws->floating->length; ++i) { - struct sway_container *floater = ws->floating->items[i]; - if (container_is_transient_for(floater, ws->fullscreen)) { - struct sway_container *con = tiling_container_at( - &floater->node, lx, ly, surface, sx, sy); - if (con) { + // 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_view *view = scene_descriptor_try_get(current, + SWAY_SCENE_DESC_VIEW); + if (view) { + con = view->container; + } + } + + if (con) { + if (!con->view || con->view->surface) { return &con->node; } } + + if (!current->parent) { + break; + } + + current = ¤t->parent->node; } - // Try fullscreen container - struct sway_container *con = - tiling_container_at(&ws->fullscreen->node, lx, ly, surface, sx, sy); - if (con) { - return &con->node; - } - return NULL; - } - if ((*surface = layer_surface_popup_at(output, - &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], - ox, oy, sx, sy))) { - return NULL; - } - if ((*surface = layer_surface_popup_at(output, - &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], - ox, oy, sx, sy))) { - return NULL; - } - if ((*surface = layer_surface_popup_at(output, - &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], - ox, oy, sx, sy))) { - return NULL; - } - if ((*surface = layer_surface_at(output, - &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], - ox, oy, sx, sy))) { - return NULL; } - struct sway_container *c; - if ((c = container_at(ws, lx, ly, surface, sx, sy))) { - return &c->node; + // if we aren't on a container, determine what workspace we are on + struct wlr_output *wlr_output = wlr_output_layout_output_at( + root->output_layout, lx, ly); + if (wlr_output == NULL) { + return NULL; } - if ((*surface = layer_surface_at(output, - &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], - ox, oy, sx, sy))) { + struct sway_output *output = wlr_output->data; + if (!output || !output->enabled) { + // output is being destroyed or is being enabled return NULL; } - if ((*surface = layer_surface_at(output, - &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], - ox, oy, sx, sy))) { + + struct sway_workspace *ws = output_get_active_workspace(output); + if (!ws) { return NULL; } |