aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-07-31 18:41:30 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-07-31 18:41:30 +1000
commitde86d65627e96cffe77f4abf11c4a0b982326ff9 (patch)
tree1a3a914fdf561884b1bb0425d51d15684b629b3a
parentMerge pull request #2390 from emersion/fix-fullscreen-segfault (diff)
downloadsway-de86d65627e96cffe77f4abf11c4a0b982326ff9.tar.gz
sway-de86d65627e96cffe77f4abf11c4a0b982326ff9.tar.zst
sway-de86d65627e96cffe77f4abf11c4a0b982326ff9.zip
Fix popups
Fixes the render and container_at order for popups. Fixes #2210 For rendering: * render_view_surfaces has been renamed to render_view_toplevels * render_view_toplevels now uses output_surface_for_each_surface (which is now public), as that function uses wlr_surface_for_each_surface which doesn't descend into popups * Views now have a for_each_popup iterator, which is used by the renderer to render the focused view's popups * When rendering a popup, toplevels (xdg subsurfaces) of that popup are also rendered For sending frame done, the logic has been updated to match the rendering logic: * send_frame_done_container no longer descends into popups * for_each_popup is used to send frame done to the focused view's popups and their child toplevels For container_at: * floating_container_at is now static, which means it had to be moved higher in the file. * container_at now considers popups for the focused view before checking containers. * tiling_container_at has been introduced, so that it doesn't call container_at recursively (it would check popups recursively if it did)
-rw-r--r--include/sway/output.h8
-rw-r--r--include/sway/tree/container.h11
-rw-r--r--include/sway/tree/view.h11
-rw-r--r--sway/desktop/output.c52
-rw-r--r--sway/desktop/render.c37
-rw-r--r--sway/desktop/xdg_shell.c9
-rw-r--r--sway/desktop/xdg_shell_v6.c10
-rw-r--r--sway/input/cursor.c3
-rw-r--r--sway/tree/container.c134
-rw-r--r--sway/tree/view.c10
10 files changed, 228 insertions, 57 deletions
diff --git a/include/sway/output.h b/include/sway/output.h
index 6283db68..80dcd37b 100644
--- a/include/sway/output.h
+++ b/include/sway/output.h
@@ -67,10 +67,18 @@ struct sway_container *output_get_active_workspace(struct sway_output *output);
67void output_render(struct sway_output *output, struct timespec *when, 67void output_render(struct sway_output *output, struct timespec *when,
68 pixman_region32_t *damage); 68 pixman_region32_t *damage);
69 69
70void output_surface_for_each_surface(struct sway_output *output,
71 struct wlr_surface *surface, double ox, double oy,
72 sway_surface_iterator_func_t iterator, void *user_data);
73
70void output_view_for_each_surface(struct sway_output *output, 74void output_view_for_each_surface(struct sway_output *output,
71 struct sway_view *view, sway_surface_iterator_func_t iterator, 75 struct sway_view *view, sway_surface_iterator_func_t iterator,
72 void *user_data); 76 void *user_data);
73 77
78void output_view_for_each_popup(struct sway_output *output,
79 struct sway_view *view, sway_surface_iterator_func_t iterator,
80 void *user_data);
81
74void output_layer_for_each_surface(struct sway_output *output, 82void output_layer_for_each_surface(struct sway_output *output,
75 struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, 83 struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator,
76 void *user_data); 84 void *user_data);
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h
index d4a42a71..12ff8a5a 100644
--- a/include/sway/tree/container.h
+++ b/include/sway/tree/container.h
@@ -230,18 +230,11 @@ struct sway_container *container_parent(struct sway_container *container,
230 * surface-local coordinates of the given layout coordinates if the container 230 * surface-local coordinates of the given layout coordinates if the container
231 * is a view and the view contains a surface at those coordinates. 231 * is a view and the view contains a surface at those coordinates.
232 */ 232 */
233struct sway_container *container_at(struct sway_container *container, 233struct sway_container *container_at(struct sway_container *workspace,
234 double ox, double oy, struct wlr_surface **surface, 234 double lx, double ly, struct wlr_surface **surface,
235 double *sx, double *sy); 235 double *sx, double *sy);
236 236
237/** 237/**
238 * Same as container_at, but only checks floating views and expects coordinates
239 * to be layout coordinates, as that's what floating views use.
240 */
241struct sway_container *floating_container_at(double lx, double ly,
242 struct wlr_surface **surface, double *sx, double *sy);
243
244/**
245 * Apply the function for each descendant of the container breadth first. 238 * Apply the function for each descendant of the container breadth first.
246 */ 239 */
247void container_for_each_descendant_bfs(struct sway_container *container, 240void container_for_each_descendant_bfs(struct sway_container *container,
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
index 0152ed55..9f6d36fe 100644
--- a/include/sway/tree/view.h
+++ b/include/sway/tree/view.h
@@ -47,6 +47,8 @@ struct sway_view_impl {
47 bool (*has_client_side_decorations)(struct sway_view *view); 47 bool (*has_client_side_decorations)(struct sway_view *view);
48 void (*for_each_surface)(struct sway_view *view, 48 void (*for_each_surface)(struct sway_view *view,
49 wlr_surface_iterator_func_t iterator, void *user_data); 49 wlr_surface_iterator_func_t iterator, void *user_data);
50 void (*for_each_popup)(struct sway_view *view,
51 wlr_surface_iterator_func_t iterator, void *user_data);
50 void (*close)(struct sway_view *view); 52 void (*close)(struct sway_view *view);
51 void (*destroy)(struct sway_view *view); 53 void (*destroy)(struct sway_view *view);
52}; 54};
@@ -248,9 +250,18 @@ void view_close(struct sway_view *view);
248 250
249void view_damage_from(struct sway_view *view); 251void view_damage_from(struct sway_view *view);
250 252
253/**
254 * Iterate all surfaces of a view (toplevels + popups).
255 */
251void view_for_each_surface(struct sway_view *view, 256void view_for_each_surface(struct sway_view *view,
252 wlr_surface_iterator_func_t iterator, void *user_data); 257 wlr_surface_iterator_func_t iterator, void *user_data);
253 258
259/**
260 * Iterate all popups recursively.
261 */
262void view_for_each_popup(struct sway_view *view,
263 wlr_surface_iterator_func_t iterator, void *user_data);
264
254// view implementation 265// view implementation
255 266
256void view_init(struct sway_view *view, enum sway_view_type type, 267void view_init(struct sway_view *view, enum sway_view_type type,
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 31b53213..4c9d978c 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -119,7 +119,7 @@ static void output_for_each_surface_iterator(struct wlr_surface *surface,
119 data->user_data); 119 data->user_data);
120} 120}
121 121
122static void output_surface_for_each_surface(struct sway_output *output, 122void output_surface_for_each_surface(struct sway_output *output,
123 struct wlr_surface *surface, double ox, double oy, 123 struct wlr_surface *surface, double ox, double oy,
124 sway_surface_iterator_func_t iterator, void *user_data) { 124 sway_surface_iterator_func_t iterator, void *user_data) {
125 struct surface_iterator_data data = { 125 struct surface_iterator_data data = {
@@ -155,6 +155,23 @@ void output_view_for_each_surface(struct sway_output *output,
155 output_for_each_surface_iterator, &data); 155 output_for_each_surface_iterator, &data);
156} 156}
157 157
158void output_view_for_each_popup(struct sway_output *output,
159 struct sway_view *view, sway_surface_iterator_func_t iterator,
160 void *user_data) {
161 struct surface_iterator_data data = {
162 .user_iterator = iterator,
163 .user_data = user_data,
164 .output = output,
165 .ox = view->swayc->current.view_x - output->swayc->current.swayc_x,
166 .oy = view->swayc->current.view_y - output->swayc->current.swayc_y,
167 .width = view->swayc->current.view_width,
168 .height = view->swayc->current.view_height,
169 .rotation = 0, // TODO
170 };
171
172 view_for_each_popup(view, output_for_each_surface_iterator, &data);
173}
174
158void output_layer_for_each_surface(struct sway_output *output, 175void output_layer_for_each_surface(struct sway_output *output,
159 struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, 176 struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator,
160 void *user_data) { 177 void *user_data) {
@@ -295,8 +312,9 @@ static void send_frame_done_container_iterator(struct sway_container *con,
295 return; 312 return;
296 } 313 }
297 314
298 output_view_for_each_surface(data->output, con->sway_view, 315 // Toplevels only
299 send_frame_done_iterator, data->when); 316 output_surface_for_each_surface(data->output, con->sway_view->surface,
317 con->x, con->y, send_frame_done_iterator, data->when);
300} 318}
301 319
302static void send_frame_done_container(struct sway_output *output, 320static void send_frame_done_container(struct sway_output *output,
@@ -309,6 +327,27 @@ static void send_frame_done_container(struct sway_output *output,
309 send_frame_done_container_iterator, &data); 327 send_frame_done_container_iterator, &data);
310} 328}
311 329
330static void send_frame_done_popup_iterator(struct sway_output *output,
331 struct wlr_surface *surface, struct wlr_box *box, float rotation,
332 void *data) {
333 // Send frame done to this popup's surface
334 send_frame_done_iterator(output, surface, box, rotation, data);
335
336 // Send frame done to this popup's child toplevels
337 output_surface_for_each_surface(output, surface, box->x, box->y,
338 send_frame_done_iterator, data);
339}
340
341static void send_frame_done_popups(struct sway_output *output,
342 struct sway_view *view, struct timespec *when) {
343 struct send_frame_done_data data = {
344 .output = output,
345 .when = when,
346 };
347 output_view_for_each_popup(output, view,
348 send_frame_done_popup_iterator, &data);
349}
350
312static void send_frame_done(struct sway_output *output, struct timespec *when) { 351static void send_frame_done(struct sway_output *output, struct timespec *when) {
313 if (output_has_opaque_overlay_layer_surface(output)) { 352 if (output_has_opaque_overlay_layer_surface(output)) {
314 goto send_frame_overlay; 353 goto send_frame_overlay;
@@ -346,6 +385,13 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) {
346 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], when); 385 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], when);
347 } 386 }
348 387
388 struct sway_seat *seat = input_manager_current_seat(input_manager);
389 struct sway_container *focus = seat_get_focus(seat);
390 if (focus && focus->type == C_VIEW) {
391 send_frame_done_popups(output, focus->sway_view, when);
392 }
393
394
349send_frame_overlay: 395send_frame_overlay:
350 send_frame_done_layer(output, 396 send_frame_done_layer(output,
351 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], when); 397 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], when);
diff --git a/sway/desktop/render.c b/sway/desktop/render.c
index f25055b8..ea4361f2 100644
--- a/sway/desktop/render.c
+++ b/sway/desktop/render.c
@@ -186,13 +186,36 @@ static void premultiply_alpha(float color[4], float opacity) {
186 color[2] *= color[3]; 186 color[2] *= color[3];
187} 187}
188 188
189static void render_view_surfaces(struct sway_view *view, 189static void render_view_toplevels(struct sway_view *view,
190 struct sway_output *output, pixman_region32_t *damage, float alpha) { 190 struct sway_output *output, pixman_region32_t *damage, float alpha) {
191 struct render_data data = { 191 struct render_data data = {
192 .damage = damage, 192 .damage = damage,
193 .alpha = alpha, 193 .alpha = alpha,
194 }; 194 };
195 output_view_for_each_surface(output, view, render_surface_iterator, &data); 195 // Render all toplevels without descending into popups
196 output_surface_for_each_surface(output, view->surface,
197 view->swayc->current.view_x, view->swayc->current.view_y,
198 render_surface_iterator, &data);
199}
200
201static void render_popup_iterator(struct sway_output *output,
202 struct wlr_surface *surface, struct wlr_box *box, float rotation,
203 void *data) {
204 // Render this popup's surface
205 render_surface_iterator(output, surface, box, rotation, data);
206
207 // Render this popup's child toplevels
208 output_surface_for_each_surface(output, surface, box->x, box->y,
209 render_surface_iterator, data);
210}
211
212static void render_view_popups(struct sway_view *view,
213 struct sway_output *output, pixman_region32_t *damage, float alpha) {
214 struct render_data data = {
215 .damage = damage,
216 .alpha = alpha,
217 };
218 output_view_for_each_popup(output, view, render_popup_iterator, &data);
196} 219}
197 220
198static void render_saved_view(struct sway_view *view, 221static void render_saved_view(struct sway_view *view,
@@ -241,7 +264,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,
241 if (view->swayc->instructions->length) { 264 if (view->swayc->instructions->length) {
242 render_saved_view(view, output, damage, view->swayc->alpha); 265 render_saved_view(view, output, damage, view->swayc->alpha);
243 } else { 266 } else {
244 render_view_surfaces(view, output, damage, view->swayc->alpha); 267 render_view_toplevels(view, output, damage, view->swayc->alpha);
245 } 268 }
246 269
247 if (view->using_csd) { 270 if (view->using_csd) {
@@ -845,7 +868,7 @@ void output_render(struct sway_output *output, struct timespec *when,
845 render_saved_view(fullscreen_con->sway_view, 868 render_saved_view(fullscreen_con->sway_view,
846 output, damage, 1.0f); 869 output, damage, 1.0f);
847 } else { 870 } else {
848 render_view_surfaces(fullscreen_con->sway_view, 871 render_view_toplevels(fullscreen_con->sway_view,
849 output, damage, 1.0f); 872 output, damage, 1.0f);
850 } 873 }
851 } else { 874 } else {
@@ -881,6 +904,12 @@ void output_render(struct sway_output *output, struct timespec *when,
881 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); 904 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]);
882 } 905 }
883 906
907 struct sway_seat *seat = input_manager_current_seat(input_manager);
908 struct sway_container *focus = seat_get_focus(seat);
909 if (focus && focus->type == C_VIEW) {
910 render_view_popups(focus->sway_view, output, damage, focus->alpha);
911 }
912
884render_overlay: 913render_overlay:
885 render_layer(output, damage, 914 render_layer(output, damage,
886 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); 915 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]);
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c
index e6e1527e..9f94bd74 100644
--- a/sway/desktop/xdg_shell.c
+++ b/sway/desktop/xdg_shell.c
@@ -179,6 +179,14 @@ static void for_each_surface(struct sway_view *view,
179 user_data); 179 user_data);
180} 180}
181 181
182static void for_each_popup(struct sway_view *view,
183 wlr_surface_iterator_func_t iterator, void *user_data) {
184 if (xdg_shell_view_from_view(view) == NULL) {
185 return;
186 }
187 wlr_xdg_surface_for_each_popup(view->wlr_xdg_surface, iterator, user_data);
188}
189
182static void _close(struct sway_view *view) { 190static void _close(struct sway_view *view) {
183 if (xdg_shell_view_from_view(view) == NULL) { 191 if (xdg_shell_view_from_view(view) == NULL) {
184 return; 192 return;
@@ -207,6 +215,7 @@ static const struct sway_view_impl view_impl = {
207 .set_fullscreen = set_fullscreen, 215 .set_fullscreen = set_fullscreen,
208 .wants_floating = wants_floating, 216 .wants_floating = wants_floating,
209 .for_each_surface = for_each_surface, 217 .for_each_surface = for_each_surface,
218 .for_each_popup = for_each_popup,
210 .close = _close, 219 .close = _close,
211 .destroy = destroy, 220 .destroy = destroy,
212}; 221};
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index 5feee3e4..4502c386 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -175,6 +175,15 @@ static void for_each_surface(struct sway_view *view,
175 user_data); 175 user_data);
176} 176}
177 177
178static void for_each_popup(struct sway_view *view,
179 wlr_surface_iterator_func_t iterator, void *user_data) {
180 if (xdg_shell_v6_view_from_view(view) == NULL) {
181 return;
182 }
183 wlr_xdg_surface_v6_for_each_popup(view->wlr_xdg_surface_v6, iterator,
184 user_data);
185}
186
178static void _close(struct sway_view *view) { 187static void _close(struct sway_view *view) {
179 if (xdg_shell_v6_view_from_view(view) == NULL) { 188 if (xdg_shell_v6_view_from_view(view) == NULL) {
180 return; 189 return;
@@ -203,6 +212,7 @@ static const struct sway_view_impl view_impl = {
203 .set_fullscreen = set_fullscreen, 212 .set_fullscreen = set_fullscreen,
204 .wants_floating = wants_floating, 213 .wants_floating = wants_floating,
205 .for_each_surface = for_each_surface, 214 .for_each_surface = for_each_surface,
215 .for_each_popup = for_each_popup,
206 .close = _close, 216 .close = _close,
207 .destroy = destroy, 217 .destroy = destroy,
208}; 218};
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 96ac7b33..ad4b1718 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -109,9 +109,6 @@ static struct sway_container *container_at_coords(
109 } 109 }
110 110
111 struct sway_container *c; 111 struct sway_container *c;
112 if ((c = floating_container_at(lx, ly, surface, sx, sy))) {
113 return c;
114 }
115 if ((c = container_at(ws, lx, ly, surface, sx, sy))) { 112 if ((c = container_at(ws, lx, ly, surface, sx, sy))) {
116 return c; 113 return c;
117 } 114 }
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 4e85021d..b5fefd17 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -561,10 +561,15 @@ static struct sway_container *container_at_view(struct sway_container *swayc,
561 *sx = _sx; 561 *sx = _sx;
562 *sy = _sy; 562 *sy = _sy;
563 *surface = _surface; 563 *surface = _surface;
564 return swayc;
564 } 565 }
565 return swayc; 566 return NULL;
566} 567}
567 568
569static struct sway_container *tiling_container_at(
570 struct sway_container *con, double lx, double ly,
571 struct wlr_surface **surface, double *sx, double *sy);
572
568/** 573/**
569 * container_at for a container with layout L_TABBED. 574 * container_at for a container with layout L_TABBED.
570 */ 575 */
@@ -591,7 +596,7 @@ static struct sway_container *container_at_tabbed(struct sway_container *parent,
591 // Surfaces 596 // Surfaces
592 struct sway_container *current = seat_get_active_child(seat, parent); 597 struct sway_container *current = seat_get_active_child(seat, parent);
593 598
594 return container_at(current, lx, ly, surface, sx, sy); 599 return tiling_container_at(current, lx, ly, surface, sx, sy);
595} 600}
596 601
597/** 602/**
@@ -616,7 +621,7 @@ static struct sway_container *container_at_stacked(
616 // Surfaces 621 // Surfaces
617 struct sway_container *current = seat_get_active_child(seat, parent); 622 struct sway_container *current = seat_get_active_child(seat, parent);
618 623
619 return container_at(current, lx, ly, surface, sx, sy); 624 return tiling_container_at(current, lx, ly, surface, sx, sy);
620} 625}
621 626
622/** 627/**
@@ -634,45 +639,13 @@ static struct sway_container *container_at_linear(struct sway_container *parent,
634 .height = child->height, 639 .height = child->height,
635 }; 640 };
636 if (wlr_box_contains_point(&box, lx, ly)) { 641 if (wlr_box_contains_point(&box, lx, ly)) {
637 return container_at(child, lx, ly, surface, sx, sy); 642 return tiling_container_at(child, lx, ly, surface, sx, sy);
638 } 643 }
639 } 644 }
640 return NULL; 645 return NULL;
641} 646}
642 647
643struct sway_container *container_at(struct sway_container *parent, 648static struct sway_container *floating_container_at(double lx, double ly,
644 double lx, double ly,
645 struct wlr_surface **surface, double *sx, double *sy) {
646 if (!sway_assert(parent->type >= C_WORKSPACE,
647 "Expected workspace or deeper")) {
648 return NULL;
649 }
650 if (parent->type == C_VIEW) {
651 return container_at_view(parent, lx, ly, surface, sx, sy);
652 }
653 if (!parent->children->length) {
654 return NULL;
655 }
656
657 switch (parent->layout) {
658 case L_HORIZ:
659 case L_VERT:
660 return container_at_linear(parent, lx, ly, surface, sx, sy);
661 case L_TABBED:
662 return container_at_tabbed(parent, lx, ly, surface, sx, sy);
663 case L_STACKED:
664 return container_at_stacked(parent, lx, ly, surface, sx, sy);
665 case L_FLOATING:
666 sway_assert(false, "Didn't expect to see floating here");
667 return NULL;
668 case L_NONE:
669 return NULL;
670 }
671
672 return NULL;
673}
674
675struct sway_container *floating_container_at(double lx, double ly,
676 struct wlr_surface **surface, double *sx, double *sy) { 649 struct wlr_surface **surface, double *sx, double *sy) {
677 for (int i = 0; i < root_container.children->length; ++i) { 650 for (int i = 0; i < root_container.children->length; ++i) {
678 struct sway_container *output = root_container.children->items[i]; 651 struct sway_container *output = root_container.children->items[i];
@@ -694,7 +667,8 @@ struct sway_container *floating_container_at(double lx, double ly,
694 .height = floater->height, 667 .height = floater->height,
695 }; 668 };
696 if (wlr_box_contains_point(&box, lx, ly)) { 669 if (wlr_box_contains_point(&box, lx, ly)) {
697 return container_at(floater, lx, ly, surface, sx, sy); 670 return tiling_container_at(floater, lx, ly,
671 surface, sx, sy);
698 } 672 }
699 } 673 }
700 } 674 }
@@ -702,6 +676,90 @@ struct sway_container *floating_container_at(double lx, double ly,
702 return NULL; 676 return NULL;
703} 677}
704 678
679static struct sway_container *tiling_container_at(
680 struct sway_container *con, double lx, double ly,
681 struct wlr_surface **surface, double *sx, double *sy) {
682 if (con->type == C_VIEW) {
683 return container_at_view(con, lx, ly, surface, sx, sy);
684 }
685 if (!con->children->length) {
686 return NULL;
687 }
688
689 switch (con->layout) {
690 case L_HORIZ:
691 case L_VERT:
692 return container_at_linear(con, lx, ly, surface, sx, sy);
693 case L_TABBED:
694 return container_at_tabbed(con, lx, ly, surface, sx, sy);
695 case L_STACKED:
696 return container_at_stacked(con, lx, ly, surface, sx, sy);
697 case L_FLOATING:
698 sway_assert(false, "Didn't expect to see floating here");
699 return NULL;
700 case L_NONE:
701 return NULL;
702 }
703 return NULL;
704}
705
706static bool surface_is_popup(struct wlr_surface *surface) {
707 if (wlr_surface_is_xdg_surface(surface)) {
708 struct wlr_xdg_surface *xdg_surface =
709 wlr_xdg_surface_from_wlr_surface(surface);
710 while (xdg_surface) {
711 if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
712 return true;
713 }
714 xdg_surface = xdg_surface->toplevel->parent;
715 }
716 return false;
717 }
718
719 if (wlr_surface_is_xdg_surface_v6(surface)) {
720 struct wlr_xdg_surface_v6 *xdg_surface_v6 =
721 wlr_xdg_surface_v6_from_wlr_surface(surface);
722 while (xdg_surface_v6) {
723 if (xdg_surface_v6->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) {
724 return true;
725 }
726 xdg_surface_v6 = xdg_surface_v6->toplevel->parent;
727 }
728 return false;
729 }
730
731 return false;
732}
733
734struct sway_container *container_at(struct sway_container *workspace,
735 double lx, double ly,
736 struct wlr_surface **surface, double *sx, double *sy) {
737 if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) {
738 return NULL;
739 }
740 struct sway_container *c;
741 // Focused view's popups
742 struct sway_seat *seat = input_manager_current_seat(input_manager);
743 struct sway_container *focus =
744 seat_get_focus_inactive(seat, &root_container);
745 if (focus && focus->type == C_VIEW) {
746 container_at_view(focus, lx, ly, surface, sx, sy);
747 if (*surface && surface_is_popup(*surface)) {
748 return focus;
749 }
750 *surface = NULL;
751 }
752 // Floating
753 if ((c = floating_container_at(lx, ly, surface, sx, sy))) {
754 return c;
755 }
756 // Tiling
757 if ((c = tiling_container_at(workspace, lx, ly, surface, sx, sy))) {
758 return c;
759 }
760 return NULL;
761}
762
705void container_for_each_descendant_dfs(struct sway_container *container, 763void container_for_each_descendant_dfs(struct sway_container *container,
706 void (*f)(struct sway_container *container, void *data), 764 void (*f)(struct sway_container *container, void *data),
707 void *data) { 765 void *data) {
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 8f54cc11..c1207821 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -332,6 +332,16 @@ void view_for_each_surface(struct sway_view *view,
332 } 332 }
333} 333}
334 334
335void view_for_each_popup(struct sway_view *view,
336 wlr_surface_iterator_func_t iterator, void *user_data) {
337 if (!view->surface) {
338 return;
339 }
340 if (view->impl->for_each_popup) {
341 view->impl->for_each_popup(view, iterator, user_data);
342 }
343}
344
335static void view_subsurface_create(struct sway_view *view, 345static void view_subsurface_create(struct sway_view *view,
336 struct wlr_subsurface *subsurface); 346 struct wlr_subsurface *subsurface);
337 347