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 | |
parent | Introduce sway_text_node (diff) | |
download | sway-5b8b505af5d5925ae9e617ee8f3c7a0f9c43409d.tar.gz sway-5b8b505af5d5925ae9e617ee8f3c7a0f9c43409d.tar.zst sway-5b8b505af5d5925ae9e617ee8f3c7a0f9c43409d.zip |
input: Query scene graph for relevant surface/node intersections
-rw-r--r-- | include/sway/scene_descriptor.h | 3 | ||||
-rw-r--r-- | include/sway/tree/container.h | 13 | ||||
-rw-r--r-- | include/sway/tree/root.h | 4 | ||||
-rw-r--r-- | sway/input/cursor.c | 184 | ||||
-rw-r--r-- | sway/tree/container.c | 265 | ||||
-rw-r--r-- | sway/tree/root.c | 21 | ||||
-rw-r--r-- | sway/tree/view.c | 7 |
7 files changed, 89 insertions, 408 deletions
diff --git a/include/sway/scene_descriptor.h b/include/sway/scene_descriptor.h index 057993ec..8af81219 100644 --- a/include/sway/scene_descriptor.h +++ b/include/sway/scene_descriptor.h | |||
@@ -12,6 +12,9 @@ | |||
12 | 12 | ||
13 | enum sway_scene_descriptor_type { | 13 | enum sway_scene_descriptor_type { |
14 | SWAY_SCENE_DESC_BUFFER_TIMER, | 14 | SWAY_SCENE_DESC_BUFFER_TIMER, |
15 | SWAY_SCENE_DESC_NON_INTERACTIVE, | ||
16 | SWAY_SCENE_DESC_CONTAINER, | ||
17 | SWAY_SCENE_DESC_VIEW, | ||
15 | SWAY_SCENE_DESC_DRAG_ICON, | 18 | SWAY_SCENE_DESC_DRAG_ICON, |
16 | }; | 19 | }; |
17 | 20 | ||
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index ee22a0d0..6f72439c 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h | |||
@@ -172,19 +172,6 @@ void container_begin_destroy(struct sway_container *con); | |||
172 | struct sway_container *container_find_child(struct sway_container *container, | 172 | struct sway_container *container_find_child(struct sway_container *container, |
173 | bool (*test)(struct sway_container *view, void *data), void *data); | 173 | bool (*test)(struct sway_container *view, void *data), void *data); |
174 | 174 | ||
175 | /** | ||
176 | * Find a container at the given coordinates. Returns the surface and | ||
177 | * surface-local coordinates of the given layout coordinates if the container | ||
178 | * is a view and the view contains a surface at those coordinates. | ||
179 | */ | ||
180 | struct sway_container *container_at(struct sway_workspace *workspace, | ||
181 | double lx, double ly, struct wlr_surface **surface, | ||
182 | double *sx, double *sy); | ||
183 | |||
184 | struct sway_container *tiling_container_at( | ||
185 | struct sway_node *parent, double lx, double ly, | ||
186 | struct wlr_surface **surface, double *sx, double *sy); | ||
187 | |||
188 | void container_for_each_child(struct sway_container *container, | 175 | void container_for_each_child(struct sway_container *container, |
189 | void (*f)(struct sway_container *container, void *data), void *data); | 176 | void (*f)(struct sway_container *container, void *data), void *data); |
190 | 177 | ||
diff --git a/include/sway/tree/root.h b/include/sway/tree/root.h index 0aae8938..003606aa 100644 --- a/include/sway/tree/root.h +++ b/include/sway/tree/root.h | |||
@@ -35,6 +35,10 @@ struct sway_root { | |||
35 | // staging node will be visible. | 35 | // staging node will be visible. |
36 | struct wlr_scene_tree *staging; | 36 | struct wlr_scene_tree *staging; |
37 | 37 | ||
38 | // tree containing all layers the compositor will render. Cursor handling | ||
39 | // will end up iterating this tree. | ||
40 | struct wlr_scene_tree *layer_tree; | ||
41 | |||
38 | struct { | 42 | struct { |
39 | struct wlr_scene_tree *tiling; | 43 | struct wlr_scene_tree *tiling; |
40 | struct wlr_scene_tree *floating; | 44 | struct wlr_scene_tree *floating; |
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) { | |||
37 | return now.tv_sec * 1000 + now.tv_nsec / 1000000; | 37 | return now.tv_sec * 1000 + now.tv_nsec / 1000000; |
38 | } | 38 | } |
39 | 39 | ||
40 | static struct wlr_surface *layer_surface_at(struct sway_output *output, | ||
41 | struct wl_list *layer, double ox, double oy, double *sx, double *sy) { | ||
42 | struct sway_layer_surface *sway_layer; | ||
43 | wl_list_for_each_reverse(sway_layer, layer, link) { | ||
44 | double _sx = ox - sway_layer->geo.x; | ||
45 | double _sy = oy - sway_layer->geo.y; | ||
46 | struct wlr_surface *sub = wlr_layer_surface_v1_surface_at( | ||
47 | sway_layer->layer_surface, _sx, _sy, sx, sy); | ||
48 | if (sub) { | ||
49 | return sub; | ||
50 | } | ||
51 | } | ||
52 | return NULL; | ||
53 | } | ||
54 | |||
55 | static bool surface_is_xdg_popup(struct wlr_surface *surface) { | ||
56 | struct wlr_xdg_surface *xdg_surface = | ||
57 | wlr_xdg_surface_try_from_wlr_surface(surface); | ||
58 | return xdg_surface != NULL && xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP && | ||
59 | xdg_surface->popup != NULL; | ||
60 | } | ||
61 | |||
62 | static struct wlr_surface *layer_surface_popup_at(struct sway_output *output, | ||
63 | struct wl_list *layer, double ox, double oy, double *sx, double *sy) { | ||
64 | struct sway_layer_surface *sway_layer; | ||
65 | wl_list_for_each_reverse(sway_layer, layer, link) { | ||
66 | double _sx = ox - sway_layer->geo.x; | ||
67 | double _sy = oy - sway_layer->geo.y; | ||
68 | struct wlr_surface *sub = wlr_layer_surface_v1_surface_at( | ||
69 | sway_layer->layer_surface, _sx, _sy, sx, sy); | ||
70 | if (sub && surface_is_xdg_popup(sub)) { | ||
71 | return sub; | ||
72 | } | ||
73 | } | ||
74 | return NULL; | ||
75 | } | ||
76 | |||
77 | /** | 40 | /** |
78 | * Returns the node at the cursor's position. If there is a surface at that | 41 | * Returns the node at the cursor's position. If there is a surface at that |
79 | * location, it is stored in **surface (it may not be a view). | 42 | * 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, | |||
81 | struct sway_node *node_at_coords( | 44 | struct sway_node *node_at_coords( |
82 | struct sway_seat *seat, double lx, double ly, | 45 | struct sway_seat *seat, double lx, double ly, |
83 | struct wlr_surface **surface, double *sx, double *sy) { | 46 | struct wlr_surface **surface, double *sx, double *sy) { |
84 | // find the output the cursor is on | 47 | struct wlr_scene_node *scene_node = NULL; |
85 | struct wlr_output *wlr_output = wlr_output_layout_output_at( | ||
86 | root->output_layout, lx, ly); | ||
87 | if (wlr_output == NULL) { | ||
88 | return NULL; | ||
89 | } | ||
90 | struct sway_output *output = wlr_output->data; | ||
91 | if (!output || !output->enabled) { | ||
92 | // output is being destroyed or is being enabled | ||
93 | return NULL; | ||
94 | } | ||
95 | double ox = lx, oy = ly; | ||
96 | wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy); | ||
97 | 48 | ||
98 | // layer surfaces on the overlay layer are rendered on top | 49 | struct wlr_scene_node *node; |
99 | if ((*surface = layer_surface_at(output, | 50 | wl_list_for_each_reverse(node, &root->layer_tree->children, link) { |
100 | &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], | 51 | struct wlr_scene_tree *layer = wlr_scene_tree_from_node(node); |
101 | ox, oy, sx, sy))) { | ||
102 | return NULL; | ||
103 | } | ||
104 | 52 | ||
105 | // check for unmanaged views | 53 | bool non_interactive = scene_descriptor_try_get(&layer->node, |
106 | #if HAVE_XWAYLAND | 54 | SWAY_SCENE_DESC_NON_INTERACTIVE); |
107 | struct wl_list *unmanaged = &root->xwayland_unmanaged; | 55 | if (non_interactive) { |
108 | struct sway_xwayland_unmanaged *unmanaged_surface; | 56 | continue; |
109 | wl_list_for_each_reverse(unmanaged_surface, unmanaged, link) { | ||
110 | struct wlr_xwayland_surface *xsurface = | ||
111 | unmanaged_surface->wlr_xwayland_surface; | ||
112 | |||
113 | double _sx = lx - unmanaged_surface->lx; | ||
114 | double _sy = ly - unmanaged_surface->ly; | ||
115 | if (wlr_surface_point_accepts_input(xsurface->surface, _sx, _sy)) { | ||
116 | *surface = xsurface->surface; | ||
117 | *sx = _sx; | ||
118 | *sy = _sy; | ||
119 | return NULL; | ||
120 | } | 57 | } |
121 | } | ||
122 | #endif | ||
123 | 58 | ||
124 | if (root->fullscreen_global) { | 59 | scene_node = wlr_scene_node_at(&layer->node, lx, ly, sx, sy); |
125 | // Try fullscreen container | 60 | if (scene_node) { |
126 | struct sway_container *con = tiling_container_at( | 61 | break; |
127 | &root->fullscreen_global->node, lx, ly, surface, sx, sy); | ||
128 | if (con) { | ||
129 | return &con->node; | ||
130 | } | 62 | } |
131 | return NULL; | ||
132 | } | 63 | } |
133 | 64 | ||
134 | // find the focused workspace on the output for this seat | 65 | if (scene_node) { |
135 | struct sway_workspace *ws = output_get_active_workspace(output); | 66 | // determine what wlr_surface we clicked on |
136 | if (!ws) { | 67 | if (scene_node->type == WLR_SCENE_NODE_BUFFER) { |
137 | return NULL; | 68 | struct wlr_scene_buffer *scene_buffer = |
138 | } | 69 | wlr_scene_buffer_from_node(scene_node); |
70 | struct wlr_scene_surface *scene_surface = | ||
71 | wlr_scene_surface_try_from_buffer(scene_buffer); | ||
72 | |||
73 | if (scene_surface) { | ||
74 | *surface = scene_surface->surface; | ||
75 | } | ||
76 | } | ||
139 | 77 | ||
140 | if (ws->fullscreen) { | 78 | // determine what container we clicked on |
141 | // Try transient containers | 79 | struct wlr_scene_node *current = scene_node; |
142 | for (int i = 0; i < ws->floating->length; ++i) { | 80 | while (true) { |
143 | struct sway_container *floater = ws->floating->items[i]; | 81 | struct sway_container *con = scene_descriptor_try_get(current, |
144 | if (container_is_transient_for(floater, ws->fullscreen)) { | 82 | SWAY_SCENE_DESC_CONTAINER); |
145 | struct sway_container *con = tiling_container_at( | 83 | if (!con) { |
146 | &floater->node, lx, ly, surface, sx, sy); | 84 | struct sway_view *view = scene_descriptor_try_get(current, |
147 | if (con) { | 85 | SWAY_SCENE_DESC_VIEW); |
86 | if (view) { | ||
87 | con = view->container; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | if (con) { | ||
92 | if (!con->view || con->view->surface) { | ||
148 | return &con->node; | 93 | return &con->node; |
149 | } | 94 | } |
150 | } | 95 | } |
96 | |||
97 | if (!current->parent) { | ||
98 | break; | ||
99 | } | ||
100 | |||
101 | current = ¤t->parent->node; | ||
151 | } | 102 | } |
152 | // Try fullscreen container | ||
153 | struct sway_container *con = | ||
154 | tiling_container_at(&ws->fullscreen->node, lx, ly, surface, sx, sy); | ||
155 | if (con) { | ||
156 | return &con->node; | ||
157 | } | ||
158 | return NULL; | ||
159 | } | ||
160 | if ((*surface = layer_surface_popup_at(output, | ||
161 | &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], | ||
162 | ox, oy, sx, sy))) { | ||
163 | return NULL; | ||
164 | } | ||
165 | if ((*surface = layer_surface_popup_at(output, | ||
166 | &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], | ||
167 | ox, oy, sx, sy))) { | ||
168 | return NULL; | ||
169 | } | ||
170 | if ((*surface = layer_surface_popup_at(output, | ||
171 | &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], | ||
172 | ox, oy, sx, sy))) { | ||
173 | return NULL; | ||
174 | } | ||
175 | if ((*surface = layer_surface_at(output, | ||
176 | &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], | ||
177 | ox, oy, sx, sy))) { | ||
178 | return NULL; | ||
179 | } | 103 | } |
180 | 104 | ||
181 | struct sway_container *c; | 105 | // if we aren't on a container, determine what workspace we are on |
182 | if ((c = container_at(ws, lx, ly, surface, sx, sy))) { | 106 | struct wlr_output *wlr_output = wlr_output_layout_output_at( |
183 | return &c->node; | 107 | root->output_layout, lx, ly); |
108 | if (wlr_output == NULL) { | ||
109 | return NULL; | ||
184 | } | 110 | } |
185 | 111 | ||
186 | if ((*surface = layer_surface_at(output, | 112 | struct sway_output *output = wlr_output->data; |
187 | &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], | 113 | if (!output || !output->enabled) { |
188 | ox, oy, sx, sy))) { | 114 | // output is being destroyed or is being enabled |
189 | return NULL; | 115 | return NULL; |
190 | } | 116 | } |
191 | if ((*surface = layer_surface_at(output, | 117 | |
192 | &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], | 118 | struct sway_workspace *ws = output_get_active_workspace(output); |
193 | ox, oy, sx, sy))) { | 119 | if (!ws) { |
194 | return NULL; | 120 | return NULL; |
195 | } | 121 | } |
196 | 122 | ||
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 @@ | |||
16 | #include "sway/input/input-manager.h" | 16 | #include "sway/input/input-manager.h" |
17 | #include "sway/input/seat.h" | 17 | #include "sway/input/seat.h" |
18 | #include "sway/ipc-server.h" | 18 | #include "sway/ipc-server.h" |
19 | #include "sway/scene_descriptor.h" | ||
19 | #include "sway/output.h" | 20 | #include "sway/output.h" |
20 | #include "sway/server.h" | 21 | #include "sway/server.h" |
21 | #include "sway/surface.h" | 22 | #include "sway/surface.h" |
@@ -94,6 +95,11 @@ struct sway_container *container_create(struct sway_view *view) { | |||
94 | c->border.right = alloc_rect_node(c->border.tree, &failed); | 95 | c->border.right = alloc_rect_node(c->border.tree, &failed); |
95 | } | 96 | } |
96 | 97 | ||
98 | if (!failed && !scene_descriptor_assign(&c->scene_tree->node, | ||
99 | SWAY_SCENE_DESC_CONTAINER, c)) { | ||
100 | failed = true; | ||
101 | } | ||
102 | |||
97 | if (failed) { | 103 | if (failed) { |
98 | wlr_scene_node_destroy(&c->scene_tree->node); | 104 | wlr_scene_node_destroy(&c->scene_tree->node); |
99 | free(c); | 105 | free(c); |
@@ -239,265 +245,6 @@ struct sway_container *container_find_child(struct sway_container *container, | |||
239 | return NULL; | 245 | return NULL; |
240 | } | 246 | } |
241 | 247 | ||
242 | static struct sway_container *surface_at_view(struct sway_container *con, double lx, double ly, | ||
243 | struct wlr_surface **surface, double *sx, double *sy) { | ||
244 | if (!sway_assert(con->view, "Expected a view")) { | ||
245 | return NULL; | ||
246 | } | ||
247 | struct sway_view *view = con->view; | ||
248 | double view_sx = lx - con->surface_x + view->geometry.x; | ||
249 | double view_sy = ly - con->surface_y + view->geometry.y; | ||
250 | |||
251 | double _sx, _sy; | ||
252 | struct wlr_surface *_surface = NULL; | ||
253 | switch (view->type) { | ||
254 | #if HAVE_XWAYLAND | ||
255 | case SWAY_VIEW_XWAYLAND: | ||
256 | _surface = wlr_surface_surface_at(view->surface, | ||
257 | view_sx, view_sy, &_sx, &_sy); | ||
258 | break; | ||
259 | #endif | ||
260 | case SWAY_VIEW_XDG_SHELL: | ||
261 | _surface = wlr_xdg_surface_surface_at( | ||
262 | view->wlr_xdg_toplevel->base, | ||
263 | view_sx, view_sy, &_sx, &_sy); | ||
264 | break; | ||
265 | } | ||
266 | if (_surface) { | ||
267 | *sx = _sx; | ||
268 | *sy = _sy; | ||
269 | *surface = _surface; | ||
270 | return con; | ||
271 | } | ||
272 | return NULL; | ||
273 | } | ||
274 | |||
275 | /** | ||
276 | * container_at for a container with layout L_TABBED. | ||
277 | */ | ||
278 | static struct sway_container *container_at_tabbed(struct sway_node *parent, | ||
279 | double lx, double ly, | ||
280 | struct wlr_surface **surface, double *sx, double *sy) { | ||
281 | struct wlr_box box; | ||
282 | node_get_box(parent, &box); | ||
283 | if (lx < box.x || lx > box.x + box.width || | ||
284 | ly < box.y || ly > box.y + box.height) { | ||
285 | return NULL; | ||
286 | } | ||
287 | struct sway_seat *seat = input_manager_current_seat(); | ||
288 | list_t *children = node_get_children(parent); | ||
289 | if (!children->length) { | ||
290 | return NULL; | ||
291 | } | ||
292 | |||
293 | // Tab titles | ||
294 | int title_height = container_titlebar_height(); | ||
295 | if (ly < box.y + title_height) { | ||
296 | int tab_width = box.width / children->length; | ||
297 | int child_index = (lx - box.x) / tab_width; | ||
298 | if (child_index >= children->length) { | ||
299 | child_index = children->length - 1; | ||
300 | } | ||
301 | struct sway_container *child = children->items[child_index]; | ||
302 | return child; | ||
303 | } | ||
304 | |||
305 | // Surfaces | ||
306 | struct sway_node *current = seat_get_active_tiling_child(seat, parent); | ||
307 | return current ? tiling_container_at(current, lx, ly, surface, sx, sy) : NULL; | ||
308 | } | ||
309 | |||
310 | /** | ||
311 | * container_at for a container with layout L_STACKED. | ||
312 | */ | ||
313 | static struct sway_container *container_at_stacked(struct sway_node *parent, | ||
314 | double lx, double ly, | ||
315 | struct wlr_surface **surface, double *sx, double *sy) { | ||
316 | struct wlr_box box; | ||
317 | node_get_box(parent, &box); | ||
318 | if (lx < box.x || lx > box.x + box.width || | ||
319 | ly < box.y || ly > box.y + box.height) { | ||
320 | return NULL; | ||
321 | } | ||
322 | struct sway_seat *seat = input_manager_current_seat(); | ||
323 | list_t *children = node_get_children(parent); | ||
324 | |||
325 | // Title bars | ||
326 | int title_height = container_titlebar_height(); | ||
327 | if (title_height > 0) { | ||
328 | int child_index = (ly - box.y) / title_height; | ||
329 | if (child_index < children->length) { | ||
330 | struct sway_container *child = children->items[child_index]; | ||
331 | return child; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | // Surfaces | ||
336 | struct sway_node *current = seat_get_active_tiling_child(seat, parent); | ||
337 | return current ? tiling_container_at(current, lx, ly, surface, sx, sy) : NULL; | ||
338 | } | ||
339 | |||
340 | /** | ||
341 | * container_at for a container with layout L_HORIZ or L_VERT. | ||
342 | */ | ||
343 | static struct sway_container *container_at_linear(struct sway_node *parent, | ||
344 | double lx, double ly, | ||
345 | struct wlr_surface **surface, double *sx, double *sy) { | ||
346 | list_t *children = node_get_children(parent); | ||
347 | for (int i = 0; i < children->length; ++i) { | ||
348 | struct sway_container *child = children->items[i]; | ||
349 | struct sway_container *container = | ||
350 | tiling_container_at(&child->node, lx, ly, surface, sx, sy); | ||
351 | if (container) { | ||
352 | return container; | ||
353 | } | ||
354 | } | ||
355 | return NULL; | ||
356 | } | ||
357 | |||
358 | static struct sway_container *floating_container_at(double lx, double ly, | ||
359 | struct wlr_surface **surface, double *sx, double *sy) { | ||
360 | // For outputs with floating containers that overhang the output bounds, | ||
361 | // those at the end of the output list appear on top of floating | ||
362 | // containers from other outputs, so iterate the list in reverse. | ||
363 | for (int i = root->outputs->length - 1; i >= 0; --i) { | ||
364 | struct sway_output *output = root->outputs->items[i]; | ||
365 | for (int j = 0; j < output->workspaces->length; ++j) { | ||
366 | struct sway_workspace *ws = output->workspaces->items[j]; | ||
367 | if (!workspace_is_visible(ws)) { | ||
368 | continue; | ||
369 | } | ||
370 | // Items at the end of the list are on top, so iterate the list in | ||
371 | // reverse. | ||
372 | for (int k = ws->floating->length - 1; k >= 0; --k) { | ||
373 | struct sway_container *floater = ws->floating->items[k]; | ||
374 | struct sway_container *container = | ||
375 | tiling_container_at(&floater->node, lx, ly, surface, sx, sy); | ||
376 | if (container) { | ||
377 | return container; | ||
378 | } | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | return NULL; | ||
383 | } | ||
384 | |||
385 | static struct sway_container *view_container_content_at(struct sway_node *parent, | ||
386 | double lx, double ly, | ||
387 | struct wlr_surface **surface, double *sx, double *sy) { | ||
388 | if (!sway_assert(node_is_view(parent), "Expected a view")) { | ||
389 | return NULL; | ||
390 | } | ||
391 | |||
392 | struct sway_container *container = parent->sway_container; | ||
393 | struct wlr_box box = { | ||
394 | .x = container->pending.content_x, | ||
395 | .y = container->pending.content_y, | ||
396 | .width = container->pending.content_width, | ||
397 | .height = container->pending.content_height, | ||
398 | }; | ||
399 | |||
400 | if (wlr_box_contains_point(&box, lx, ly)) { | ||
401 | surface_at_view(parent->sway_container, lx, ly, surface, sx, sy); | ||
402 | return container; | ||
403 | } | ||
404 | |||
405 | return NULL; | ||
406 | } | ||
407 | |||
408 | static struct sway_container *view_container_at(struct sway_node *parent, | ||
409 | double lx, double ly, | ||
410 | struct wlr_surface **surface, double *sx, double *sy) { | ||
411 | if (!sway_assert(node_is_view(parent), "Expected a view")) { | ||
412 | return NULL; | ||
413 | } | ||
414 | |||
415 | struct sway_container *container = parent->sway_container; | ||
416 | struct wlr_box box = { | ||
417 | .x = container->pending.x, | ||
418 | .y = container->pending.y, | ||
419 | .width = container->pending.width, | ||
420 | .height = container->pending.height, | ||
421 | }; | ||
422 | |||
423 | if (wlr_box_contains_point(&box, lx, ly)) { | ||
424 | surface_at_view(parent->sway_container, lx, ly, surface, sx, sy); | ||
425 | return container; | ||
426 | } | ||
427 | |||
428 | return NULL; | ||
429 | } | ||
430 | |||
431 | struct sway_container *tiling_container_at(struct sway_node *parent, | ||
432 | double lx, double ly, | ||
433 | struct wlr_surface **surface, double *sx, double *sy) { | ||
434 | if (node_is_view(parent)) { | ||
435 | return view_container_at(parent, lx, ly, surface, sx, sy); | ||
436 | } | ||
437 | if (!node_get_children(parent)) { | ||
438 | return NULL; | ||
439 | } | ||
440 | switch (node_get_layout(parent)) { | ||
441 | case L_HORIZ: | ||
442 | case L_VERT: | ||
443 | return container_at_linear(parent, lx, ly, surface, sx, sy); | ||
444 | case L_TABBED: | ||
445 | return container_at_tabbed(parent, lx, ly, surface, sx, sy); | ||
446 | case L_STACKED: | ||
447 | return container_at_stacked(parent, lx, ly, surface, sx, sy); | ||
448 | case L_NONE: | ||
449 | return NULL; | ||
450 | } | ||
451 | return NULL; | ||
452 | } | ||
453 | |||
454 | static bool surface_is_popup(struct wlr_surface *surface) { | ||
455 | while (wlr_xdg_surface_try_from_wlr_surface(surface) == NULL) { | ||
456 | struct wlr_subsurface *subsurface = | ||
457 | wlr_subsurface_try_from_wlr_surface(surface); | ||
458 | if (subsurface == NULL) { | ||
459 | return false; | ||
460 | } | ||
461 | surface = subsurface->parent; | ||
462 | } | ||
463 | struct wlr_xdg_surface *xdg_surface = | ||
464 | wlr_xdg_surface_try_from_wlr_surface(surface); | ||
465 | return xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP && xdg_surface->popup != NULL; | ||
466 | } | ||
467 | |||
468 | struct sway_container *container_at(struct sway_workspace *workspace, | ||
469 | double lx, double ly, | ||
470 | struct wlr_surface **surface, double *sx, double *sy) { | ||
471 | struct sway_container *c; | ||
472 | |||
473 | struct sway_seat *seat = input_manager_current_seat(); | ||
474 | struct sway_container *focus = seat_get_focused_container(seat); | ||
475 | bool is_floating = focus && container_is_floating_or_child(focus); | ||
476 | // Focused view's popups | ||
477 | if (focus && focus->view) { | ||
478 | c = surface_at_view(focus, lx, ly, surface, sx, sy); | ||
479 | if (c && surface_is_popup(*surface)) { | ||
480 | return c; | ||
481 | } | ||
482 | *surface = NULL; | ||
483 | } | ||
484 | // Floating | ||
485 | if ((c = floating_container_at(lx, ly, surface ,sx ,sy))) { | ||
486 | return c; | ||
487 | } | ||
488 | // Tiling (focused) | ||
489 | if (focus && focus->view && !is_floating) { | ||
490 | if ((c = view_container_content_at(&focus->node, lx, ly, surface, sx, sy))) { | ||
491 | return c; | ||
492 | } | ||
493 | } | ||
494 | // Tiling (non-focused) | ||
495 | if ((c = tiling_container_at(&workspace->node, lx, ly, surface, sx, sy))) { | ||
496 | return c; | ||
497 | } | ||
498 | return NULL; | ||
499 | } | ||
500 | |||
501 | void container_for_each_child(struct sway_container *container, | 248 | void container_for_each_child(struct sway_container *container, |
502 | void (*f)(struct sway_container *container, void *data), | 249 | void (*f)(struct sway_container *container, void *data), |
503 | void *data) { | 250 | 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 @@ | |||
9 | #include "sway/input/seat.h" | 9 | #include "sway/input/seat.h" |
10 | #include "sway/ipc-server.h" | 10 | #include "sway/ipc-server.h" |
11 | #include "sway/output.h" | 11 | #include "sway/output.h" |
12 | #include "sway/scene_descriptor.h" | ||
12 | #include "sway/tree/arrange.h" | 13 | #include "sway/tree/arrange.h" |
13 | #include "sway/tree/container.h" | 14 | #include "sway/tree/container.h" |
14 | #include "sway/tree/root.h" | 15 | #include "sway/tree/root.h" |
@@ -44,13 +45,19 @@ struct sway_root *root_create(struct wl_display *wl_display) { | |||
44 | 45 | ||
45 | bool failed = false; | 46 | bool failed = false; |
46 | root->staging = alloc_scene_tree(&root_scene->tree, &failed); | 47 | root->staging = alloc_scene_tree(&root_scene->tree, &failed); |
47 | 48 | root->layer_tree = alloc_scene_tree(&root_scene->tree, &failed); | |
48 | root->layers.tiling = alloc_scene_tree(&root_scene->tree, &failed); | 49 | |
49 | root->layers.floating = alloc_scene_tree(&root_scene->tree, &failed); | 50 | root->layers.tiling = alloc_scene_tree(root->layer_tree, &failed); |
50 | root->layers.fullscreen = alloc_scene_tree(&root_scene->tree, &failed); | 51 | root->layers.floating = alloc_scene_tree(root->layer_tree, &failed); |
51 | root->layers.fullscreen_global = alloc_scene_tree(&root_scene->tree, &failed); | 52 | root->layers.fullscreen = alloc_scene_tree(root->layer_tree, &failed); |
52 | root->layers.seat = alloc_scene_tree(&root_scene->tree, &failed); | 53 | root->layers.fullscreen_global = alloc_scene_tree(root->layer_tree, &failed); |
53 | root->layers.session_lock = alloc_scene_tree(&root_scene->tree, &failed); | 54 | root->layers.seat = alloc_scene_tree(root->layer_tree, &failed); |
55 | root->layers.session_lock = alloc_scene_tree(root->layer_tree, &failed); | ||
56 | |||
57 | if (!failed && !scene_descriptor_assign(&root->layers.seat->node, | ||
58 | SWAY_SCENE_DESC_NON_INTERACTIVE, (void *)1)) { | ||
59 | failed = true; | ||
60 | } | ||
54 | 61 | ||
55 | if (failed) { | 62 | if (failed) { |
56 | wlr_scene_node_destroy(&root_scene->tree.node); | 63 | 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 @@ | |||
24 | #include "sway/ipc-server.h" | 24 | #include "sway/ipc-server.h" |
25 | #include "sway/output.h" | 25 | #include "sway/output.h" |
26 | #include "sway/input/seat.h" | 26 | #include "sway/input/seat.h" |
27 | #include "sway/scene_descriptor.h" | ||
27 | #include "sway/server.h" | 28 | #include "sway/server.h" |
28 | #include "sway/surface.h" | 29 | #include "sway/surface.h" |
29 | #include "sway/tree/arrange.h" | 30 | #include "sway/tree/arrange.h" |
@@ -40,6 +41,12 @@ bool view_init(struct sway_view *view, enum sway_view_type type, | |||
40 | bool failed = false; | 41 | bool failed = false; |
41 | view->scene_tree = alloc_scene_tree(root->staging, &failed); | 42 | view->scene_tree = alloc_scene_tree(root->staging, &failed); |
42 | view->content_tree = alloc_scene_tree(view->scene_tree, &failed); | 43 | view->content_tree = alloc_scene_tree(view->scene_tree, &failed); |
44 | |||
45 | if (!failed && !scene_descriptor_assign(&view->scene_tree->node, | ||
46 | SWAY_SCENE_DESC_VIEW, view)) { | ||
47 | failed = true; | ||
48 | } | ||
49 | |||
43 | if (failed) { | 50 | if (failed) { |
44 | wlr_scene_node_destroy(&view->scene_tree->node); | 51 | wlr_scene_node_destroy(&view->scene_tree->node); |
45 | return false; | 52 | return false; |