aboutsummaryrefslogtreecommitdiff
path: root/sway/tree
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/tree
parent946fc8094559801bc4be629368ac31025d28165a (diff)
input: Query scene graph for relevant surface/node intersections
Diffstat (limited to 'sway/tree')
-rw-r--r--sway/tree/container.c265
-rw-r--r--sway/tree/root.c21
-rw-r--r--sway/tree/view.c7
3 files changed, 27 insertions, 266 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 307bf963..8fca6a12 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -16,6 +16,7 @@
#include "sway/input/input-manager.h"
#include "sway/input/seat.h"
#include "sway/ipc-server.h"
+#include "sway/scene_descriptor.h"
#include "sway/output.h"
#include "sway/server.h"
#include "sway/surface.h"
@@ -94,6 +95,11 @@ struct sway_container *container_create(struct sway_view *view) {
c->border.right = alloc_rect_node(c->border.tree, &failed);
}
+ if (!failed && !scene_descriptor_assign(&c->scene_tree->node,
+ SWAY_SCENE_DESC_CONTAINER, c)) {
+ failed = true;
+ }
+
if (failed) {
wlr_scene_node_destroy(&c->scene_tree->node);
free(c);
@@ -239,265 +245,6 @@ struct sway_container *container_find_child(struct sway_container *container,
return NULL;
}
-static struct sway_container *surface_at_view(struct sway_container *con, double lx, double ly,
- struct wlr_surface **surface, double *sx, double *sy) {
- if (!sway_assert(con->view, "Expected a view")) {
- return NULL;
- }
- struct sway_view *view = con->view;
- double view_sx = lx - con->surface_x + view->geometry.x;
- double view_sy = ly - con->surface_y + view->geometry.y;
-
- double _sx, _sy;
- struct wlr_surface *_surface = NULL;
- switch (view->type) {
-#if HAVE_XWAYLAND
- case SWAY_VIEW_XWAYLAND:
- _surface = wlr_surface_surface_at(view->surface,
- view_sx, view_sy, &_sx, &_sy);
- break;
-#endif
- case SWAY_VIEW_XDG_SHELL:
- _surface = wlr_xdg_surface_surface_at(
- view->wlr_xdg_toplevel->base,
- view_sx, view_sy, &_sx, &_sy);
- break;
- }
- if (_surface) {
- *sx = _sx;
- *sy = _sy;
- *surface = _surface;
- return con;
- }
- return NULL;
-}
-
-/**
- * container_at for a container with layout L_TABBED.
- */
-static struct sway_container *container_at_tabbed(struct sway_node *parent,
- double lx, double ly,
- struct wlr_surface **surface, double *sx, double *sy) {
- struct wlr_box box;
- node_get_box(parent, &box);
- if (lx < box.x || lx > box.x + box.width ||
- ly < box.y || ly > box.y + box.height) {
- return NULL;
- }
- struct sway_seat *seat = input_manager_current_seat();
- list_t *children = node_get_children(parent);
- if (!children->length) {
- return NULL;
- }
-
- // Tab titles
- int title_height = container_titlebar_height();
- if (ly < box.y + title_height) {
- int tab_width = box.width / children->length;
- int child_index = (lx - box.x) / tab_width;
- if (child_index >= children->length) {
- child_index = children->length - 1;
- }
- struct sway_container *child = children->items[child_index];
- return child;
- }
-
- // Surfaces
- struct sway_node *current = seat_get_active_tiling_child(seat, parent);
- return current ? tiling_container_at(current, lx, ly, surface, sx, sy) : NULL;
-}
-
-/**
- * container_at for a container with layout L_STACKED.
- */
-static struct sway_container *container_at_stacked(struct sway_node *parent,
- double lx, double ly,
- struct wlr_surface **surface, double *sx, double *sy) {
- struct wlr_box box;
- node_get_box(parent, &box);
- if (lx < box.x || lx > box.x + box.width ||
- ly < box.y || ly > box.y + box.height) {
- return NULL;
- }
- struct sway_seat *seat = input_manager_current_seat();
- list_t *children = node_get_children(parent);
-
- // Title bars
- int title_height = container_titlebar_height();
- if (title_height > 0) {
- int child_index = (ly - box.y) / title_height;
- if (child_index < children->length) {
- struct sway_container *child = children->items[child_index];
- return child;
- }
- }
-
- // Surfaces
- struct sway_node *current = seat_get_active_tiling_child(seat, parent);
- return current ? tiling_container_at(current, lx, ly, surface, sx, sy) : NULL;
-}
-
-/**
- * container_at for a container with layout L_HORIZ or L_VERT.
- */
-static struct sway_container *container_at_linear(struct sway_node *parent,
- double lx, double ly,
- struct wlr_surface **surface, double *sx, double *sy) {
- list_t *children = node_get_children(parent);
- for (int i = 0; i < children->length; ++i) {
- struct sway_container *child = children->items[i];
- struct sway_container *container =
- tiling_container_at(&child->node, lx, ly, surface, sx, sy);
- if (container) {
- return container;
- }
- }
- return NULL;
-}
-
-static struct sway_container *floating_container_at(double lx, double ly,
- struct wlr_surface **surface, double *sx, double *sy) {
- // For outputs with floating containers that overhang the output bounds,
- // those at the end of the output list appear on top of floating
- // containers from other outputs, so iterate the list in reverse.
- for (int i = root->outputs->length - 1; i >= 0; --i) {
- struct sway_output *output = root->outputs->items[i];
- for (int j = 0; j < output->workspaces->length; ++j) {
- struct sway_workspace *ws = output->workspaces->items[j];
- if (!workspace_is_visible(ws)) {
- continue;
- }
- // Items at the end of the list are on top, so iterate the list in
- // reverse.
- for (int k = ws->floating->length - 1; k >= 0; --k) {
- struct sway_container *floater = ws->floating->items[k];
- struct sway_container *container =
- tiling_container_at(&floater->node, lx, ly, surface, sx, sy);
- if (container) {
- return container;
- }
- }
- }
- }
- return NULL;
-}
-
-static struct sway_container *view_container_content_at(struct sway_node *parent,
- double lx, double ly,
- struct wlr_surface **surface, double *sx, double *sy) {
- if (!sway_assert(node_is_view(parent), "Expected a view")) {
- return NULL;
- }
-
- struct sway_container *container = parent->sway_container;
- struct wlr_box box = {
- .x = container->pending.content_x,
- .y = container->pending.content_y,
- .width = container->pending.content_width,
- .height = container->pending.content_height,
- };
-
- if (wlr_box_contains_point(&box, lx, ly)) {
- surface_at_view(parent->sway_container, lx, ly, surface, sx, sy);
- return container;
- }
-
- return NULL;
-}
-
-static struct sway_container *view_container_at(struct sway_node *parent,
- double lx, double ly,
- struct wlr_surface **surface, double *sx, double *sy) {
- if (!sway_assert(node_is_view(parent), "Expected a view")) {
- return NULL;
- }
-
- struct sway_container *container = parent->sway_container;
- struct wlr_box box = {
- .x = container->pending.x,
- .y = container->pending.y,
- .width = container->pending.width,
- .height = container->pending.height,
- };
-
- if (wlr_box_contains_point(&box, lx, ly)) {
- surface_at_view(parent->sway_container, lx, ly, surface, sx, sy);
- return container;
- }
-
- return NULL;
-}
-
-struct sway_container *tiling_container_at(struct sway_node *parent,
- double lx, double ly,
- struct wlr_surface **surface, double *sx, double *sy) {
- if (node_is_view(parent)) {
- return view_container_at(parent, lx, ly, surface, sx, sy);
- }
- if (!node_get_children(parent)) {
- return NULL;
- }
- switch (node_get_layout(parent)) {
- case L_HORIZ:
- case L_VERT:
- return container_at_linear(parent, lx, ly, surface, sx, sy);
- case L_TABBED:
- return container_at_tabbed(parent, lx, ly, surface, sx, sy);
- case L_STACKED:
- return container_at_stacked(parent, lx, ly, surface, sx, sy);
- case L_NONE:
- return NULL;
- }
- return NULL;
-}
-
-static bool surface_is_popup(struct wlr_surface *surface) {
- while (wlr_xdg_surface_try_from_wlr_surface(surface) == NULL) {
- struct wlr_subsurface *subsurface =
- wlr_subsurface_try_from_wlr_surface(surface);
- if (subsurface == NULL) {
- return false;
- }
- surface = subsurface->parent;
- }
- struct wlr_xdg_surface *xdg_surface =
- wlr_xdg_surface_try_from_wlr_surface(surface);
- return xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP && xdg_surface->popup != NULL;
-}
-
-struct sway_container *container_at(struct sway_workspace *workspace,
- double lx, double ly,
- struct wlr_surface **surface, double *sx, double *sy) {
- struct sway_container *c;
-
- struct sway_seat *seat = input_manager_current_seat();
- struct sway_container *focus = seat_get_focused_container(seat);
- bool is_floating = focus && container_is_floating_or_child(focus);
- // Focused view's popups
- if (focus && focus->view) {
- c = surface_at_view(focus, lx, ly, surface, sx, sy);
- if (c && surface_is_popup(*surface)) {
- return c;
- }
- *surface = NULL;
- }
- // Floating
- if ((c = floating_container_at(lx, ly, surface ,sx ,sy))) {
- return c;
- }
- // Tiling (focused)
- if (focus && focus->view && !is_floating) {
- if ((c = view_container_content_at(&focus->node, lx, ly, surface, sx, sy))) {
- return c;
- }
- }
- // Tiling (non-focused)
- if ((c = tiling_container_at(&workspace->node, lx, ly, surface, sx, sy))) {
- return c;
- }
- return NULL;
-}
-
void container_for_each_child(struct sway_container *container,
void (*f)(struct sway_container *container, void *data),
void *data) {
diff --git a/sway/tree/root.c b/sway/tree/root.c
index e4941566..fbdd9a96 100644
--- a/sway/tree/root.c
+++ b/sway/tree/root.c
@@ -9,6 +9,7 @@
#include "sway/input/seat.h"
#include "sway/ipc-server.h"
#include "sway/output.h"
+#include "sway/scene_descriptor.h"
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
#include "sway/tree/root.h"
@@ -44,13 +45,19 @@ struct sway_root *root_create(struct wl_display *wl_display) {
bool failed = false;
root->staging = alloc_scene_tree(&root_scene->tree, &failed);
-
- root->layers.tiling = alloc_scene_tree(&root_scene->tree, &failed);
- root->layers.floating = alloc_scene_tree(&root_scene->tree, &failed);
- root->layers.fullscreen = alloc_scene_tree(&root_scene->tree, &failed);
- root->layers.fullscreen_global = alloc_scene_tree(&root_scene->tree, &failed);
- root->layers.seat = alloc_scene_tree(&root_scene->tree, &failed);
- root->layers.session_lock = alloc_scene_tree(&root_scene->tree, &failed);
+ root->layer_tree = alloc_scene_tree(&root_scene->tree, &failed);
+
+ root->layers.tiling = alloc_scene_tree(root->layer_tree, &failed);
+ root->layers.floating = alloc_scene_tree(root->layer_tree, &failed);
+ root->layers.fullscreen = alloc_scene_tree(root->layer_tree, &failed);
+ root->layers.fullscreen_global = alloc_scene_tree(root->layer_tree, &failed);
+ root->layers.seat = alloc_scene_tree(root->layer_tree, &failed);
+ root->layers.session_lock = alloc_scene_tree(root->layer_tree, &failed);
+
+ if (!failed && !scene_descriptor_assign(&root->layers.seat->node,
+ SWAY_SCENE_DESC_NON_INTERACTIVE, (void *)1)) {
+ failed = true;
+ }
if (failed) {
wlr_scene_node_destroy(&root_scene->tree.node);
diff --git a/sway/tree/view.c b/sway/tree/view.c
index bc968edc..d349e5fa 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -24,6 +24,7 @@
#include "sway/ipc-server.h"
#include "sway/output.h"
#include "sway/input/seat.h"
+#include "sway/scene_descriptor.h"
#include "sway/server.h"
#include "sway/surface.h"
#include "sway/tree/arrange.h"
@@ -40,6 +41,12 @@ bool view_init(struct sway_view *view, enum sway_view_type type,
bool failed = false;
view->scene_tree = alloc_scene_tree(root->staging, &failed);
view->content_tree = alloc_scene_tree(view->scene_tree, &failed);
+
+ if (!failed && !scene_descriptor_assign(&view->scene_tree->node,
+ SWAY_SCENE_DESC_VIEW, view)) {
+ failed = true;
+ }
+
if (failed) {
wlr_scene_node_destroy(&view->scene_tree->node);
return false;