aboutsummaryrefslogtreecommitdiff
path: root/sway/input/cursor.c
diff options
context:
space:
mode:
authorAlexander Orzechowski <alex@ozal.ski>2023-11-23 10:09:48 -0500
committerKirill Primak <vyivel@eclair.cafe>2024-01-18 18:36:54 +0300
commit5b8b505af5d5925ae9e617ee8f3c7a0f9c43409d (patch)
treef420022ad3a48215f9182505c0060d91edcd848e /sway/input/cursor.c
parent946fc8094559801bc4be629368ac31025d28165a (diff)
input: Query scene graph for relevant surface/node intersections
Diffstat (limited to 'sway/input/cursor.c')
-rw-r--r--sway/input/cursor.c184
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 = &current->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;
}