8000 surface: allow placing subsurfaces below parent · swaywm/wlroots@9e58301 · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 9e58301

Browse files
committed
surface: allow placing subsurfaces below parent
Prior to this commit, subsurfaces could only be placed above their parent. Any place_{above,below} request involving the parent would fail with a protocol error. However the Wayland protocol allows using the parent surface in the place_{above,below} requests, and allows subsurfaces to be placed below their parent. Weston's implementation adds a dummy wl_list node in the subsurface list. However this is potentially dangerous: iterating the list requires making sure the dummy wl_list node is checked for, otherwise memory corruption will happen. Instead, split the list in two: one for subsurfaces above the parent, the other for subsurfaces below. Tested with wleird's subsurfaces demo client. Closes: #1865
1 parent 11040d4 commit 9e58301

File tree

2 files changed

+104
-40
lines changed

2 files changed

+104
-40
lines changed

include/wlr/types/wlr_surface.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,13 @@ struct wlr_surface {
139139
struct wl_signal destroy;
140140
} events;
141141

142-
struct wl_list subsurfaces; // wlr_subsurface::parent_link
142+
// wlr_subsurface.parent_link
143+
struct wl_list subsurfaces_below;
144+
struct wl_list subsurfaces_above;
143145

144-
// wlr_subsurface::parent_pending_link
145-
struct wl_list subsurface_pending_list;
146+
// wlr_subsurface.parent_pending_link
147+
struct wl_list subsurfaces_pending_below;
148+
struct wl_list subsurfaces_pending_above;
146149

147150
struct wl_list current_outputs; // wlr_surface_output::link
148151

types/wlr_surface.c

+98-37
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,10 @@ static void surface_damage_subsurfaces(struct wlr_subsurface *subsurface) {
341341
subsurface->reordered = false;
342342

343343
struct wlr_subsurface *child;
344-
wl_list_for_each(child, &subsurface->surface->subsurfaces, parent_link) {
344+
wl_list_for_each(child, &subsurface->surface->subsurfaces_below, parent_link) {
345+
surface_damage_subsurfaces(child);
346+
}
347+
wl_list_for_each(child, &subsurface->surface->subsurfaces_above, parent_link) {
345348
surface_damage_subsurfaces(child);
346349
}
347350
}
@@ -440,10 +443,20 @@ static void surface_commit_state(struct wlr_surface *surface,
440443

441444
// commit subsurface order
442445
struct wlr_subsurface *subsurface;
443-
wl_list_for_each_reverse(subsurface, &surface->subsurface_pending_list,
446+
wl_list_for_each_reverse(subsurface, &surface->subsurfaces_pending_above,
447+
parent_pending_link) {
448+
wl_list_remove(&subsurface->parent_link);
449+
wl_list_insert(&surface->subsurfaces_above, &subsurface->parent_link);
450+
451+
if (subsurface->reordered) {
452+
// TODO: damage all the subsurfaces
453+
surface_damage_subsurfaces(subsurface);
454+
}
455+
}
456+
wl_list_for_each_reverse(subsurface, &surface->subsurfaces_pending_below,
444457
parent_pending_link) {
445458
wl_list_remove(&subsurface->parent_link);
446-
wl_list_insert(&surface->subsurfaces, &subsurface->parent_link);
459+
wl_list_insert(&surface->subsurfaces_below, &subsurface->parent_link);
447460

448461
if (subsurface->reordered) {
449462
// TODO: damage all the subsurfaces
@@ -509,7 +522,10 @@ static void subsurface_parent_commit(struct wlr_subsurface *subsurface,
509522
}
510523

511524
struct wlr_subsurface *subsurface;
512-
wl_list_for_each(subsurface, &surface->subsurfaces, parent_link) {
525+
wl_list_for_each(subsurface, &surface->subsurfaces_below, parent_link) {
526+
subsurface_parent_commit(subsurface, true);
527+
}
528+
wl_list_for_each(subsurface, &surface->subsurfaces_above, parent_link) {
513529
subsurface_parent_commit(subsurface, true);
514530
}
515531
}
@@ -541,7 +557,10 @@ static void surface_commit(struct wl_client *client,
541557

542558
surface_commit_pending(surface);
543559

544-
wl_list_for_each(subsurface, &surface->subsurfaces, parent_link) {
560+
wl_list_for_each(subsurface, &surface->subsurfaces_below, parent_link) {
561+
subsurface_parent_commit(subsurface, false);
562+
}
563+
wl_list_for_each(subsurface, &surface->subsurfaces_above, parent_link) {
545564
subsurface_parent_commit(subsurface, false);
546565
}
547566
}
@@ -732,8 +751,10 @@ struct wlr_surface *surface_create(struct wl_client *client,
732751
wl_signal_init(&surface->events.commit);
733752
wl_signal_init(&surface->events.destroy);
734753
wl_signal_init(&surface->events.new_subsurface);
735-
wl_list_init(&surface->subsurfaces);
736-
wl_list_init(&surface->subsurface_pending_list);
754+
wl_list_init(&surface->subsurfaces_above);
755+
wl_list_init(&surface->subsurfaces_below);
756+
wl_list_init(&surface->subsurfaces_pending_above);
757+
wl_list_init(&surface->subsurfaces_pending_below);
737758
wl_list_init(&surface->current_outputs);
738759
wl_list_init(&surface->cached);
739760
pixman_region32_init(&surface->buffer_damage);
@@ -867,7 +888,12 @@ static struct wlr_subsurface *subsurface_find_sibling(
867888
struct wlr_surface *parent = subsurface->parent;
868889

869890
struct wlr_subsurface *sibling;
870-
wl_list_for_each(sibling, &parent->subsurfaces, parent_link) {
891+
wl_list_for_each(sibling, &parent->subsurfaces_below, parent_link) {
892+
if (sibling->surface == surface && sibling != subsurface) {
893+
return sibling;
894+
}
895+
}
896+
wl_list_for_each(sibling, &parent->subsurfaces_above, parent_link) {
871897
if (sibling->surface == surface && sibling != subsurface) {
872898
return sibling;
873899
}
@@ -885,20 +911,25 @@ static void subsurface_handle_place_above(struct wl_client *client,
885911

886912
struct wlr_surface *sibling_surface =
887913
wlr_surface_from_resource(sibling_resource);
888-
struct wlr_subsurface *sibling =
889-
subsurface_find_sibling(subsurface, sibling_surface);
890-
891-
if (!sibling) {
892-
wl_resource_post_error(subsurface->resource,
893-
WL_SUBSURFACE_ERROR_BAD_SURFACE,
894-
"%s: wl_surface@%" PRIu32 "is not a parent or sibling",
895-
"place_above", wl_resource_get_id(sibling_surface->resource));
896-
return;
914+
915+
struct wl_list *node;
916+
if (sibling_surface == subsurface->parent) {
917+
node = &subsurface->parent->subsurfaces_pending_above;
918+
} else {
919+
struct wlr_subsurface *sibling =
920+
subsurface_find_sibling(subsurface, sibling_surface);
921+
if (!sibling) {
922+
wl_resource_post_error(subsurface->resource,
923+
WL_SUBSURFACE_ERROR_BAD_SURFACE,
924+
"%s: wl_surface@%" PRIu32 "is not a parent or sibling",
925+
"place_above", wl_resource_get_id(sibling_resource));
926+
return;
927+
}
928+
node = &sibling->parent_pending_link;
897929
}
898930

899931
wl_list_remove(&subsurface->parent_pending_link);
900-
wl_list_insert(&sibling->parent_pending_link,
901-
&subsurface->parent_pending_link);
932+
wl_list_insert(node, &subsurface->parent_pending_link);
902933

903934
subsurface->reordered = true;
904935
}
@@ -912,20 +943,25 @@ static void subsurface_handle_place_below(struct wl_client *client,
912943

913944
struct wlr_surface *sibling_surface =
914945
wlr_surface_from_resource(sibling_resource);
915-
struct wlr_subsurface *sibling =
916-
subsurface_find_sibling(subsurface, sibling_surface);
917-
918-
if (!sibling) {
919-
wl_resource_post_error(subsurface->resource,
920-
WL_SUBSURFACE_ERROR_BAD_SURFACE,
921-
"%s: wl_surface@%" PRIu32 " is not a parent or sibling",
922-
"place_below", wl_resource_get_id(sibling_surface->resource));
923-
return;
946+
947+
struct wl_list *node;
948+
if (sibling_surface == subsurface->parent) {
949+
node = subsurface->parent->subsurfaces_pending_below.prev;
950+
} else {
951+
struct wlr_subsurface *sibling =
952+
subsurface_find_sibling(subsurface, sibling_surface);
953+
if (!sibling) {
954+
wl_resource_post_error(subsurface->resource,
955+
WL_SUBSURFACE_ERROR_BAD_SURFACE,
956+
"%s: wl_surface@%" PRIu32 " is not a parent or sibling",
957+
"place_below", wl_resource_get_id(sibling_resource));
958+
return;
959+
}
960+
node = sibling->parent_pending_link.prev;
924961
}
925962

926963
wl_list_remove(&subsurface->parent_pending_link);
927-
wl_list_insert(sibling->parent_pending_link.prev,
928-
&subsurface->parent_pending_link);
964+
wl_list_insert(node, &subsurface->parent_pending_link);
929965

930966
subsurface->reordered = true;
931967
}
@@ -1002,7 +1038,10 @@ static void subsurface_consider_map(struct wlr_subsurface *subsurface,
10021038

10031039
// Try mapping all children too
10041040
struct wlr_subsurface *child;
1005-
wl_list_for_each(child, &subsurface->surface->subsurfaces, parent_link) {
1041+
wl_list_for_each(child, &subsurface->surface->subsurfaces_below, parent_link) {
1042+
subsurface_consider_map(child, false);
1043+
}
1044+
wl_list_for_each(child, &subsurface->surface->subsurfaces_above, parent_link) {
10061045
subsurface_consider_map(child, false);
10071046
}
10081047
}
@@ -1017,7 +1056,10 @@ static void subsurface_unmap(struct wlr_subsurface *subsurface) {
10171056

10181057
// Unmap all children
10191058
struct wlr_subsurface *child;
1020-
wl_list_for_each(child, &subsurface->surface->subsurfaces, parent_link) {
1059+
wl_list_for_each(child, &subsurface->surface->subsurfaces_below, parent_link) {
1060+
subsurface_unmap(child);
1061+
}
1062+
wl_list_for_each(child, &subsurface->surface->subsurfaces_above, parent_link) {
10211063
subsurface_unmap(child);
10221064
}
10231065
}
@@ -1131,8 +1173,8 @@ struct wlr_subsurface *wlr_subsurface_create(struct wlr_surface *surface,
11311173
subsurface->parent = parent;
11321174
wl_signal_add(&parent->events.destroy, &subsurface->parent_destroy);
11331175
subsurface->parent_destroy.notify = subsurface_handle_parent_destroy;
1134-
wl_list_insert(parent->subsurfaces.prev, &subsurface->parent_link);
1135-
wl_list_insert(parent->subsurface_pending_list.prev,
1176+
wl_list_insert(parent->subsurfaces_above.prev, &subsurface->parent_link);
1177+
wl_list_insert(parent->subsurfaces_pending_above.prev,
11361178
&subsurface->parent_pending_link);
11371179

11381180
surface->role_data = subsurface;
@@ -1175,7 +1217,7 @@ bool wlr_surface_point_accepts_input(struct wlr_surface *surface,
11751217
struct wlr_surface *wlr_surface_surface_at(struct wlr_surface *surface,
11761218
double sx, double sy, double *sub_x, double *sub_y) {
11771219
struct wlr_subsurface *subsurface;
1178-
wl_list_for_each_reverse(subsurface, &surface->subsurfaces, parent_link) {
1220+
wl_list_for_each_reverse(subsurface, &surface->subsurfaces_above, parent_link) {
11791221
double _sub_x = subsurface->current.x;
11801222
double _sub_y = subsurface->current.y;
11811223
struct wlr_surface *sub = wlr_surface_surface_at(subsurface->surface,
@@ -1195,6 +1237,16 @@ struct wlr_surface *wlr_surface_surface_at(struct wlr_surface *surface,
11951237
return surface;
11961238
}
11971239

1240+
wl_list_for_each_reverse(subsurface, &surface->subsurfaces_below, parent_link) {
1241+
double _sub_x = subsurface->current.x;
1242+
double _sub_y = subsurface->current.y;
1243+
struct wlr_surface *sub = wlr_surface_surface_at(subsurface->surface,
1244+
sx - _sub_x, sy - _sub_y, sub_x, sub_y);
1245+
if (sub != NULL) {
1246+
return sub;
1247+
}
1248+
}
1249+
11981250
return NULL;
11991251
}
12001252

@@ -1290,10 +1342,19 @@ void wlr_surface_send_frame_done(struct wlr_surface *surface,
12901342

12911343
static void surface_for_each_surface(struct wlr_surface *surface, int x, int y,
12921344
wlr_surface_iterator_func_t iterator, void *user_data) {
1345+
struct wlr_subsurface *subsurface;
1346+
wl_list_for_each(subsurface, &surface->subsurfaces_below, parent_link) {
1347+
struct wlr_subsurface_state *state = &subsurface->current;
1348+
int sx = state->x;
1349+
int sy = state->y;
1350+
1351+
surface_for_each_surface(subsurface->surface, x + sx, y + sy,
1352+
iterator, user_data);
1353+
}
1354+
12931355
iterator(surface, x, y, user_data);
12941356

1295-
struct wlr_subsurface *subsurface;
1296-
wl_list_for_each(subsurface, &surface->subsurfaces, parent_link) {
1357+
wl_list_for_each(subsurface, &surface->subsurfaces_above, parent_link) {
12971358
struct wlr_subsurface_state *state = &subsurface->current;
12981359
int sx = state->x;
12991360
int sy = state->y;

0 commit comments

Comments
 (0)
0