@@ -341,7 +341,10 @@ static void surface_damage_subsurfaces(struct wlr_subsurface *subsurface) {
341
341
subsurface -> reordered = false;
342
342
343
343
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 ) {
345
348
surface_damage_subsurfaces (child );
346
349
}
347
350
}
@@ -440,10 +443,20 @@ static void surface_commit_state(struct wlr_surface *surface,
440
443
441
444
// commit subsurface order
442
445
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 ,
444
457
parent_pending_link ) {
445
458
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 );
447
460
448
461
if (subsurface -> reordered ) {
449
462
// TODO: damage all the subsurfaces
@@ -509,7 +522,10 @@ static void subsurface_parent_commit(struct wlr_subsurface *subsurface,
509
522
}
510
523
511
524
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 ) {
513
529
subsurface_parent_commit (subsurface , true);
514
530
}
515
531
}
@@ -541,7 +557,10 @@ static void surface_commit(struct wl_client *client,
541
557
542
558
surface_commit_pending (surface );
543
559
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 ) {
545
564
subsurface_parent_commit (subsurface , false);
546
565
}
547
566
}
@@ -732,8 +751,10 @@ struct wlr_surface *surface_create(struct wl_client *client,
732
751
wl_signal_init (& surface -> events .commit );
733
752
wl_signal_init (& surface -> events .destroy );
734
753
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 );
737
758
wl_list_init (& surface -> current_outputs );
738
759
wl_list_init (& surface -> cached );
739
760
pixman_region32_init (& surface -> buffer_damage );
@@ -867,7 +888,12 @@ static struct wlr_subsurface *subsurface_find_sibling(
867
888
struct wlr_surface * parent = subsurface -> parent ;
868
889
869
890
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 ) {
871
897
if (sibling -> surface == surface && sibling != subsurface ) {
872
898
return sibling ;
873
899
}
@@ -885,20 +911,25 @@ static void subsurface_handle_place_above(struct wl_client *client,
885
911
886
912
struct wlr_surface * sibling_surface =
887
913
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 ;
897
929
}
898
930
899
931
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 );
902
933
903
934
subsurface -> reordered = true;
904
935
}
@@ -912,20 +943,25 @@ static void subsurface_handle_place_below(struct wl_client *client,
912
943
913
944
struct wlr_surface * sibling_surface =
914
945
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 ;
924
961
}
925
962
926
963
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 );
929
965
930
966
subsurface -> reordered = true;
931
967
}
@@ -1002,7 +1038,10 @@ static void subsurface_consider_map(struct wlr_subsurface *subsurface,
1002
1038
1003
1039
// Try mapping all children too
1004
1040
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 ) {
1006
1045
subsurface_consider_map (child , false);
1007
1046
}
1008
1047
}
@@ -1017,7 +1056,10 @@ static void subsurface_unmap(struct wlr_subsurface *subsurface) {
1017
1056
1018
1057
// Unmap all children
1019
1058
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 ) {
1021
1063
subsurface_unmap (child );
1022
1064
}
1023
1065
}
@@ -1131,8 +1173,8 @@ struct wlr_subsurface *wlr_subsurface_create(struct wlr_surface *surface,
1131
1173
subsurface -> parent = parent ;
1132
1174
wl_signal_add (& parent -> events .destroy , & subsurface -> parent_destroy );
1133
1175
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 ,
1136
1178
& subsurface -> parent_pending_link );
1137
1179
1138
1180
surface -> role_data = subsurface ;
@@ -1175,7 +1217,7 @@ bool wlr_surface_point_accepts_input(struct wlr_surface *surface,
1175
1217
struct wlr_surface * wlr_surface_surface_at (struct wlr_surface * surface ,
1176
1218
double sx , double sy , double * sub_x , double * sub_y ) {
1177
1219
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 ) {
1179
1221
double _sub_x = subsurface -> current .x ;
1180
1222
double _sub_y = subsurface -> current .y ;
1181
1223
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,
1195
1237
return surface ;
1196
1238
}
1197
1239
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
+
1198
1250
return NULL ;
1199
1251
}
1200
1252
@@ -1290,10 +1342,19 @@ void wlr_surface_send_frame_done(struct wlr_surface *surface,
1290
1342
1291
1343
static void surface_for_each_surface (struct wlr_surface * surface , int x , int y ,
1292
1344
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
+
1293
1355
iterator (surface , x , y , user_data );
1294
1356
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 ) {
1297
1358
struct wlr_subsurface_state * state = & subsurface -> current ;
1298
1359
int sx = state -> x ;
1299
1360
int sy = state -> y ;
0 commit comments