blob: 2581b09f1f40db6de83670509b6b2c94d24692ec [file] [log] [blame]
Pekka Paalanene844bf22013-04-25 13:57:43 +03001/*
2 * Copyright © 2012 Collabora, Ltd.
3 *
Bryce Harrington2cc92972015-06-11 15:39:40 -07004 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
Pekka Paalanene844bf22013-04-25 13:57:43 +030011 *
Bryce Harrington2cc92972015-06-11 15:39:40 -070012 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
Pekka Paalanene844bf22013-04-25 13:57:43 +030024 */
25
Andrew Wedgbury9cd661e2014-04-07 12:40:35 +010026#include "config.h"
27
Bryce Harringtona7680262014-11-19 17:18:34 -080028#include <stdio.h>
Pekka Paalanene844bf22013-04-25 13:57:43 +030029#include <string.h>
30
31#include "weston-test-client-helper.h"
Pekka Paalanen701676d2019-11-13 15:45:10 +020032#include "weston-test-fixture-compositor.h"
33
34static enum test_result_code
35fixture_setup(struct weston_test_harness *harness)
36{
37 struct compositor_setup setup;
38
39 compositor_setup_defaults(&setup);
40
41 return weston_test_harness_execute_as_client(harness, &setup);
42}
43DECLARE_FIXTURE_SETUP(fixture_setup);
Pekka Paalanene844bf22013-04-25 13:57:43 +030044
45#define NUM_SUBSURFACES 3
46
47struct compound_surface {
48 struct wl_subcompositor *subco;
49 struct wl_surface *parent;
50 struct wl_surface *child[NUM_SUBSURFACES];
51 struct wl_subsurface *sub[NUM_SUBSURFACES];
52};
53
54static struct wl_subcompositor *
55get_subcompositor(struct client *client)
56{
57 struct global *g;
58 struct global *global_sub = NULL;
59 struct wl_subcompositor *sub;
60
61 wl_list_for_each(g, &client->global_list, link) {
62 if (strcmp(g->interface, "wl_subcompositor"))
63 continue;
64
65 if (global_sub)
66 assert(0 && "multiple wl_subcompositor objects");
67
68 global_sub = g;
69 }
70
71 assert(global_sub && "no wl_subcompositor found");
72
73 assert(global_sub->version == 1);
74
75 sub = wl_registry_bind(client->wl_registry, global_sub->name,
76 &wl_subcompositor_interface, 1);
77 assert(sub);
78
79 return sub;
80}
81
82static void
83populate_compound_surface(struct compound_surface *com, struct client *client)
84{
85 int i;
86
87 com->subco = get_subcompositor(client);
88
89 com->parent = wl_compositor_create_surface(client->wl_compositor);
90
91 for (i = 0; i < NUM_SUBSURFACES; i++) {
92 com->child[i] =
93 wl_compositor_create_surface(client->wl_compositor);
94 com->sub[i] =
95 wl_subcompositor_get_subsurface(com->subco,
96 com->child[i],
97 com->parent);
98 }
99}
100
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300101static void
102fini_compound_surface(struct compound_surface *com)
103{
104 int i;
105
106 for (i = 0; i < NUM_SUBSURFACES; i++) {
107 if (com->sub[i])
108 wl_subsurface_destroy(com->sub[i]);
109 if (com->child[i])
110 wl_surface_destroy(com->child[i]);
111 }
112
113 wl_surface_destroy(com->parent);
114 wl_subcompositor_destroy(com->subco);
115}
116
Pekka Paalanene844bf22013-04-25 13:57:43 +0300117TEST(test_subsurface_basic_protocol)
118{
119 struct client *client;
120 struct compound_surface com1;
121 struct compound_surface com2;
122
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200123 client = create_client_and_test_surface(100, 50, 123, 77);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300124 assert(client);
125
126 populate_compound_surface(&com1, client);
127 populate_compound_surface(&com2, client);
128
129 client_roundtrip(client);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300130
131 fini_compound_surface(&com1);
132 fini_compound_surface(&com2);
133 client_destroy(client);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300134}
135
136TEST(test_subsurface_position_protocol)
137{
138 struct client *client;
139 struct compound_surface com;
140 int i;
141
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200142 client = create_client_and_test_surface(100, 50, 123, 77);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300143 assert(client);
144
145 populate_compound_surface(&com, client);
146 for (i = 0; i < NUM_SUBSURFACES; i++)
147 wl_subsurface_set_position(com.sub[i],
148 (i + 2) * 20, (i + 2) * 10);
149
150 client_roundtrip(client);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300151
152 fini_compound_surface(&com);
153 client_destroy(client);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300154}
155
156TEST(test_subsurface_placement_protocol)
157{
158 struct client *client;
159 struct compound_surface com;
160
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200161 client = create_client_and_test_surface(100, 50, 123, 77);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300162 assert(client);
163
164 populate_compound_surface(&com, client);
165
166 wl_subsurface_place_above(com.sub[0], com.child[1]);
167 wl_subsurface_place_above(com.sub[1], com.parent);
168 wl_subsurface_place_below(com.sub[2], com.child[0]);
169 wl_subsurface_place_below(com.sub[1], com.parent);
170
171 client_roundtrip(client);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300172
173 fini_compound_surface(&com);
174 client_destroy(client);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300175}
176
Marek Chalupacfff3122014-07-16 11:40:25 +0200177TEST(test_subsurface_paradox)
Pekka Paalanene844bf22013-04-25 13:57:43 +0300178{
179 struct client *client;
180 struct wl_surface *parent;
181 struct wl_subcompositor *subco;
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300182 struct wl_subsurface *sub;
Pekka Paalanene844bf22013-04-25 13:57:43 +0300183
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200184 client = create_client_and_test_surface(100, 50, 123, 77);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300185 assert(client);
186
187 subco = get_subcompositor(client);
188 parent = wl_compositor_create_surface(client->wl_compositor);
189
190 /* surface is its own parent */
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300191 sub = wl_subcompositor_get_subsurface(subco, parent, parent);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300192
Marek Chalupacfff3122014-07-16 11:40:25 +0200193 expect_protocol_error(client, &wl_subcompositor_interface,
194 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300195
196 wl_subsurface_destroy(sub);
197 wl_surface_destroy(parent);
198 wl_subcompositor_destroy(subco);
199 client_destroy(client);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300200}
201
Marek Chalupacfff3122014-07-16 11:40:25 +0200202TEST(test_subsurface_identical_link)
Pekka Paalanene844bf22013-04-25 13:57:43 +0300203{
204 struct client *client;
205 struct compound_surface com;
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300206 struct wl_subsurface *sub;
Pekka Paalanene844bf22013-04-25 13:57:43 +0300207
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200208 client = create_client_and_test_surface(100, 50, 123, 77);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300209 assert(client);
210
211 populate_compound_surface(&com, client);
212
213 /* surface is already a subsurface */
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300214 sub = wl_subcompositor_get_subsurface(com.subco, com.child[0], com.parent);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300215
Marek Chalupacfff3122014-07-16 11:40:25 +0200216 expect_protocol_error(client, &wl_subcompositor_interface,
217 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300218
219 wl_subsurface_destroy(sub);
220 fini_compound_surface(&com);
221 client_destroy(client);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300222}
223
Marek Chalupacfff3122014-07-16 11:40:25 +0200224TEST(test_subsurface_change_link)
Pekka Paalanene844bf22013-04-25 13:57:43 +0300225{
226 struct client *client;
227 struct compound_surface com;
228 struct wl_surface *stranger;
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300229 struct wl_subsurface *sub;
Pekka Paalanene844bf22013-04-25 13:57:43 +0300230
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200231 client = create_client_and_test_surface(100, 50, 123, 77);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300232 assert(client);
233
234 stranger = wl_compositor_create_surface(client->wl_compositor);
235 populate_compound_surface(&com, client);
236
237 /* surface is already a subsurface */
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300238 sub = wl_subcompositor_get_subsurface(com.subco, com.child[0], stranger);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300239
Marek Chalupacfff3122014-07-16 11:40:25 +0200240 expect_protocol_error(client, &wl_subcompositor_interface,
241 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300242
243 fini_compound_surface(&com);
244 wl_subsurface_destroy(sub);
245 wl_surface_destroy(stranger);
246 client_destroy(client);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300247}
248
249TEST(test_subsurface_nesting)
250{
251 struct client *client;
252 struct compound_surface com;
253 struct wl_surface *stranger;
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300254 struct wl_subsurface *sub;
Pekka Paalanene844bf22013-04-25 13:57:43 +0300255
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200256 client = create_client_and_test_surface(100, 50, 123, 77);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300257 assert(client);
258
259 stranger = wl_compositor_create_surface(client->wl_compositor);
260 populate_compound_surface(&com, client);
261
262 /* parent is a sub-surface */
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300263 sub = wl_subcompositor_get_subsurface(com.subco, stranger, com.child[0]);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300264
265 client_roundtrip(client);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300266
267 wl_subsurface_destroy(sub);
268 wl_surface_destroy(stranger);
269 fini_compound_surface(&com);
270 client_destroy(client);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300271}
272
273TEST(test_subsurface_nesting_parent)
274{
275 struct client *client;
276 struct compound_surface com;
277 struct wl_surface *stranger;
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300278 struct wl_subsurface *sub;
Pekka Paalanene844bf22013-04-25 13:57:43 +0300279
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200280 client = create_client_and_test_surface(100, 50, 123, 77);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300281 assert(client);
282
283 stranger = wl_compositor_create_surface(client->wl_compositor);
284 populate_compound_surface(&com, client);
285
286 /* surface is already a parent */
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300287 sub = wl_subcompositor_get_subsurface(com.subco, com.parent, stranger);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300288
289 client_roundtrip(client);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300290
291 wl_subsurface_destroy(sub);
292 fini_compound_surface(&com);
293 wl_surface_destroy(stranger);
294 client_destroy(client);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300295}
296
Marek Chalupacfff3122014-07-16 11:40:25 +0200297TEST(test_subsurface_loop_paradox)
Pekka Paalanen5e9bedb2013-05-17 16:46:06 +0300298{
299 struct client *client;
300 struct wl_surface *surface[3];
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300301 struct wl_subsurface *sub[3];
Pekka Paalanen5e9bedb2013-05-17 16:46:06 +0300302 struct wl_subcompositor *subco;
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300303 unsigned i;
Pekka Paalanen5e9bedb2013-05-17 16:46:06 +0300304
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200305 client = create_client_and_test_surface(100, 50, 123, 77);
Pekka Paalanen5e9bedb2013-05-17 16:46:06 +0300306 assert(client);
307
308 subco = get_subcompositor(client);
309 surface[0] = wl_compositor_create_surface(client->wl_compositor);
310 surface[1] = wl_compositor_create_surface(client->wl_compositor);
311 surface[2] = wl_compositor_create_surface(client->wl_compositor);
312
313 /* create a nesting loop */
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300314 sub[0] = wl_subcompositor_get_subsurface(subco, surface[1], surface[0]);
315 sub[1] = wl_subcompositor_get_subsurface(subco, surface[2], surface[1]);
316 sub[2] = wl_subcompositor_get_subsurface(subco, surface[0], surface[2]);
Pekka Paalanen5e9bedb2013-05-17 16:46:06 +0300317
Marek Chalupacfff3122014-07-16 11:40:25 +0200318 expect_protocol_error(client, &wl_subcompositor_interface,
319 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300320
321 for (i = 0; i < ARRAY_LENGTH(sub); i++) {
322 wl_subsurface_destroy(sub[i]);
323 wl_surface_destroy(surface[i]);
324 }
325
326 wl_subcompositor_destroy(subco);
327 client_destroy(client);
Pekka Paalanen5e9bedb2013-05-17 16:46:06 +0300328}
329
Arnaud Vracb8c16c92016-06-08 18:37:57 +0200330TEST(test_subsurface_place_above_nested_parent)
331{
332 struct client *client;
333 struct compound_surface com;
334 struct wl_surface *grandchild;
335 struct wl_subcompositor *subco;
336 struct wl_subsurface *sub;
337
338 client = create_client_and_test_surface(100, 50, 123, 77);
339 assert(client);
340
341 populate_compound_surface(&com, client);
342
343 subco = get_subcompositor(client);
344 grandchild = wl_compositor_create_surface(client->wl_compositor);
345 sub = wl_subcompositor_get_subsurface(subco, grandchild, com.child[0]);
346
347 wl_subsurface_place_above(sub, com.child[0]);
348
349 client_roundtrip(client);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300350
351 wl_subsurface_destroy(sub);
352 wl_surface_destroy(grandchild);
353 wl_subcompositor_destroy(subco);
354 fini_compound_surface(&com);
355 client_destroy(client);
Arnaud Vracb8c16c92016-06-08 18:37:57 +0200356}
357
Daniel Stone99834002016-11-22 12:40:34 +0000358TEST(test_subsurface_place_above_grandparent)
359{
360 struct client *client;
361 struct compound_surface com;
362 struct wl_surface *grandchild;
363 struct wl_subsurface *sub;
364 struct wl_subcompositor *subco;
365
366 client = create_client_and_test_surface(100, 50, 123, 77);
367 assert(client);
368
369 populate_compound_surface(&com, client);
370
371 subco = get_subcompositor(client);
372 grandchild = wl_compositor_create_surface(client->wl_compositor);
373 sub = wl_subcompositor_get_subsurface(subco, grandchild, com.child[0]);
374
375 /* can't place a subsurface above its grandparent */
376 wl_subsurface_place_above(sub, com.parent);
377
378 expect_protocol_error(client, &wl_subsurface_interface,
379 WL_SUBSURFACE_ERROR_BAD_SURFACE);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300380
381 wl_subsurface_destroy(sub);
382 wl_surface_destroy(grandchild);
383 wl_subcompositor_destroy(subco);
384 fini_compound_surface(&com);
385 client_destroy(client);
Daniel Stone99834002016-11-22 12:40:34 +0000386}
387
388TEST(test_subsurface_place_above_great_aunt)
389{
390 struct client *client;
391 struct compound_surface com;
392 struct wl_surface *grandchild;
393 struct wl_subsurface *sub;
394 struct wl_subcompositor *subco;
395
396 client = create_client_and_test_surface(100, 50, 123, 77);
397 assert(client);
398
399 populate_compound_surface(&com, client);
400
401 subco = get_subcompositor(client);
402 grandchild = wl_compositor_create_surface(client->wl_compositor);
403 sub = wl_subcompositor_get_subsurface(subco, grandchild, com.child[0]);
404
405 /* can't place a subsurface above its parents' siblings */
406 wl_subsurface_place_above(sub, com.child[1]);
407
408 expect_protocol_error(client, &wl_subsurface_interface,
409 WL_SUBSURFACE_ERROR_BAD_SURFACE);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300410
411 wl_subsurface_destroy(sub);
412 wl_surface_destroy(grandchild);
413 wl_subcompositor_destroy(subco);
414 fini_compound_surface(&com);
415 client_destroy(client);
Daniel Stone99834002016-11-22 12:40:34 +0000416}
417
418TEST(test_subsurface_place_above_child)
419{
420 struct client *client;
421 struct compound_surface com;
422 struct wl_surface *grandchild;
423 struct wl_subcompositor *subco;
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300424 struct wl_subsurface *sub;
Daniel Stone99834002016-11-22 12:40:34 +0000425
426 client = create_client_and_test_surface(100, 50, 123, 77);
427 assert(client);
428
429 populate_compound_surface(&com, client);
430
431 subco = get_subcompositor(client);
432 grandchild = wl_compositor_create_surface(client->wl_compositor);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300433 sub = wl_subcompositor_get_subsurface(subco, grandchild, com.child[0]);
Daniel Stone99834002016-11-22 12:40:34 +0000434
435 /* can't place a subsurface above its own child subsurface */
436 wl_subsurface_place_above(com.sub[0], grandchild);
437
438 expect_protocol_error(client, &wl_subsurface_interface,
439 WL_SUBSURFACE_ERROR_BAD_SURFACE);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300440
441 wl_subsurface_destroy(sub);
442 wl_surface_destroy(grandchild);
443 wl_subcompositor_destroy(subco);
444 fini_compound_surface(&com);
445 client_destroy(client);
Daniel Stone99834002016-11-22 12:40:34 +0000446}
447
Arnaud Vracb8c16c92016-06-08 18:37:57 +0200448TEST(test_subsurface_place_below_nested_parent)
449{
450 struct client *client;
451 struct compound_surface com;
452 struct wl_subcompositor *subco;
453 struct wl_surface *grandchild;
454 struct wl_subsurface *sub;
455
456 client = create_client_and_test_surface(100, 50, 123, 77);
457 assert(client);
458
459 populate_compound_surface(&com, client);
460
461 subco = get_subcompositor(client);
462 grandchild = wl_compositor_create_surface(client->wl_compositor);
463 sub = wl_subcompositor_get_subsurface(subco, grandchild, com.child[0]);
464
465 wl_subsurface_place_below(sub, com.child[0]);
466
467 client_roundtrip(client);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300468
469 wl_subsurface_destroy(sub);
470 wl_surface_destroy(grandchild);
471 wl_subcompositor_destroy(subco);
472 fini_compound_surface(&com);
473 client_destroy(client);
Arnaud Vracb8c16c92016-06-08 18:37:57 +0200474}
475
Daniel Stone99834002016-11-22 12:40:34 +0000476TEST(test_subsurface_place_below_grandparent)
477{
478 struct client *client;
479 struct compound_surface com;
480 struct wl_surface *grandchild;
481 struct wl_subsurface *sub;
482 struct wl_subcompositor *subco;
483
484 client = create_client_and_test_surface(100, 50, 123, 77);
485 assert(client);
486
487 populate_compound_surface(&com, client);
488
489 subco = get_subcompositor(client);
490 grandchild = wl_compositor_create_surface(client->wl_compositor);
491 sub = wl_subcompositor_get_subsurface(subco, grandchild, com.child[0]);
492
493 /* can't place a subsurface below its grandparent */
494 wl_subsurface_place_below(sub, com.parent);
495
496 expect_protocol_error(client, &wl_subsurface_interface,
497 WL_SUBSURFACE_ERROR_BAD_SURFACE);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300498
499 wl_subsurface_destroy(sub);
500 wl_surface_destroy(grandchild);
501 wl_subcompositor_destroy(subco);
502 fini_compound_surface(&com);
503 client_destroy(client);
Daniel Stone99834002016-11-22 12:40:34 +0000504}
505
506TEST(test_subsurface_place_below_great_aunt)
507{
508 struct client *client;
509 struct compound_surface com;
510 struct wl_surface *grandchild;
511 struct wl_subsurface *sub;
512 struct wl_subcompositor *subco;
513
514 client = create_client_and_test_surface(100, 50, 123, 77);
515 assert(client);
516
517 populate_compound_surface(&com, client);
518
519 subco = get_subcompositor(client);
520 grandchild = wl_compositor_create_surface(client->wl_compositor);
521 sub = wl_subcompositor_get_subsurface(subco, grandchild, com.child[0]);
522
523 /* can't place a subsurface below its parents' siblings */
524 wl_subsurface_place_below(sub, com.child[1]);
525
526 expect_protocol_error(client, &wl_subsurface_interface,
527 WL_SUBSURFACE_ERROR_BAD_SURFACE);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300528
529 wl_subsurface_destroy(sub);
530 wl_surface_destroy(grandchild);
531 wl_subcompositor_destroy(subco);
532 fini_compound_surface(&com);
533 client_destroy(client);
Daniel Stone99834002016-11-22 12:40:34 +0000534}
535
536TEST(test_subsurface_place_below_child)
537{
538 struct client *client;
539 struct compound_surface com;
540 struct wl_surface *grandchild;
541 struct wl_subcompositor *subco;
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300542 struct wl_subsurface *sub;
Daniel Stone99834002016-11-22 12:40:34 +0000543
544 client = create_client_and_test_surface(100, 50, 123, 77);
545 assert(client);
546
547 populate_compound_surface(&com, client);
548
549 subco = get_subcompositor(client);
550 grandchild = wl_compositor_create_surface(client->wl_compositor);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300551 sub = wl_subcompositor_get_subsurface(subco, grandchild, com.child[0]);
Daniel Stone99834002016-11-22 12:40:34 +0000552
553 /* can't place a subsurface below its own child subsurface */
554 wl_subsurface_place_below(com.sub[0], grandchild);
555
556 expect_protocol_error(client, &wl_subsurface_interface,
557 WL_SUBSURFACE_ERROR_BAD_SURFACE);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300558
559 wl_subsurface_destroy(sub);
560 wl_surface_destroy(grandchild);
561 wl_subcompositor_destroy(subco);
562 fini_compound_surface(&com);
563 client_destroy(client);
Daniel Stone99834002016-11-22 12:40:34 +0000564}
565
Marek Chalupacfff3122014-07-16 11:40:25 +0200566TEST(test_subsurface_place_above_stranger)
Pekka Paalanene844bf22013-04-25 13:57:43 +0300567{
568 struct client *client;
569 struct compound_surface com;
570 struct wl_surface *stranger;
571
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200572 client = create_client_and_test_surface(100, 50, 123, 77);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300573 assert(client);
574
575 stranger = wl_compositor_create_surface(client->wl_compositor);
576 populate_compound_surface(&com, client);
577
578 /* bad sibling */
579 wl_subsurface_place_above(com.sub[0], stranger);
580
Marek Chalupacfff3122014-07-16 11:40:25 +0200581 expect_protocol_error(client, &wl_subsurface_interface,
582 WL_SUBSURFACE_ERROR_BAD_SURFACE);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300583
584 wl_surface_destroy(stranger);
585 fini_compound_surface(&com);
586 client_destroy(client);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300587}
588
Marek Chalupacfff3122014-07-16 11:40:25 +0200589TEST(test_subsurface_place_below_stranger)
Pekka Paalanene844bf22013-04-25 13:57:43 +0300590{
591 struct client *client;
592 struct compound_surface com;
593 struct wl_surface *stranger;
594
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200595 client = create_client_and_test_surface(100, 50, 123, 77);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300596 assert(client);
597
598 stranger = wl_compositor_create_surface(client->wl_compositor);
599 populate_compound_surface(&com, client);
600
601 /* bad sibling */
602 wl_subsurface_place_below(com.sub[0], stranger);
603
Marek Chalupacfff3122014-07-16 11:40:25 +0200604 expect_protocol_error(client, &wl_subsurface_interface,
605 WL_SUBSURFACE_ERROR_BAD_SURFACE);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300606
607 wl_surface_destroy(stranger);
608 fini_compound_surface(&com);
609 client_destroy(client);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300610}
611
Marek Chalupacfff3122014-07-16 11:40:25 +0200612TEST(test_subsurface_place_above_foreign)
Pekka Paalanene844bf22013-04-25 13:57:43 +0300613{
614 struct client *client;
615 struct compound_surface com1;
616 struct compound_surface com2;
617
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200618 client = create_client_and_test_surface(100, 50, 123, 77);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300619 assert(client);
620
621 populate_compound_surface(&com1, client);
622 populate_compound_surface(&com2, client);
623
624 /* bad sibling */
625 wl_subsurface_place_above(com1.sub[0], com2.child[0]);
626
Marek Chalupacfff3122014-07-16 11:40:25 +0200627 expect_protocol_error(client, &wl_subsurface_interface,
628 WL_SUBSURFACE_ERROR_BAD_SURFACE);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300629
630 fini_compound_surface(&com1);
631 fini_compound_surface(&com2);
632 client_destroy(client);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300633}
634
Marek Chalupacfff3122014-07-16 11:40:25 +0200635TEST(test_subsurface_place_below_foreign)
Pekka Paalanene844bf22013-04-25 13:57:43 +0300636{
637 struct client *client;
638 struct compound_surface com1;
639 struct compound_surface com2;
640
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200641 client = create_client_and_test_surface(100, 50, 123, 77);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300642 assert(client);
643
644 populate_compound_surface(&com1, client);
645 populate_compound_surface(&com2, client);
646
647 /* bad sibling */
648 wl_subsurface_place_below(com1.sub[0], com2.child[0]);
649
Marek Chalupacfff3122014-07-16 11:40:25 +0200650 expect_protocol_error(client, &wl_subsurface_interface,
651 WL_SUBSURFACE_ERROR_BAD_SURFACE);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300652
653 fini_compound_surface(&com1);
654 fini_compound_surface(&com2);
655 client_destroy(client);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300656}
657
658TEST(test_subsurface_destroy_protocol)
659{
660 struct client *client;
661 struct compound_surface com;
662
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200663 client = create_client_and_test_surface(100, 50, 123, 77);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300664 assert(client);
665
666 populate_compound_surface(&com, client);
667
668 /* not needed anymore */
669 wl_subcompositor_destroy(com.subco);
670
671 /* detach child from parent */
672 wl_subsurface_destroy(com.sub[0]);
673
674 /* destroy: child, parent */
675 wl_surface_destroy(com.child[1]);
676 wl_surface_destroy(com.parent);
677
678 /* destroy: parent, child */
679 wl_surface_destroy(com.child[2]);
680
681 /* destroy: sub, child */
682 wl_surface_destroy(com.child[0]);
683
684 /* 2x destroy: child, sub */
685 wl_subsurface_destroy(com.sub[2]);
686 wl_subsurface_destroy(com.sub[1]);
687
688 client_roundtrip(client);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300689
690 client_destroy(client);
Pekka Paalanene844bf22013-04-25 13:57:43 +0300691}
Pekka Paalanenbeb080e2013-05-17 16:46:04 +0300692
693static void
694create_subsurface_tree(struct client *client, struct wl_surface **surfs,
695 struct wl_subsurface **subs, int n)
696{
697 struct wl_subcompositor *subco;
698 int i;
699
700 subco = get_subcompositor(client);
701
702 for (i = 0; i < n; i++)
703 surfs[i] = wl_compositor_create_surface(client->wl_compositor);
704
705 /*
706 * The tree of sub-surfaces:
707 * 0
708 * / \
709 * 1 2 - 10
710 * / \ |\
711 * 3 5 9 6
712 * / / \
713 * 4 7 8
714 * Surface 0 has no wl_subsurface, others do.
715 */
716
717 switch (n) {
718 default:
719 assert(0);
720 break;
721
722#define SUB_LINK(s,p) \
723 subs[s] = wl_subcompositor_get_subsurface(subco, surfs[s], surfs[p])
724
725 case 11:
726 SUB_LINK(10, 2);
Daniel Stone2ef9b1a2017-03-13 16:31:36 +0000727 /* fallthrough */
Pekka Paalanenbeb080e2013-05-17 16:46:04 +0300728 case 10:
729 SUB_LINK(9, 2);
Daniel Stone2ef9b1a2017-03-13 16:31:36 +0000730 /* fallthrough */
Pekka Paalanenbeb080e2013-05-17 16:46:04 +0300731 case 9:
732 SUB_LINK(8, 6);
Daniel Stone2ef9b1a2017-03-13 16:31:36 +0000733 /* fallthrough */
Pekka Paalanenbeb080e2013-05-17 16:46:04 +0300734 case 8:
735 SUB_LINK(7, 6);
Daniel Stone2ef9b1a2017-03-13 16:31:36 +0000736 /* fallthrough */
Pekka Paalanenbeb080e2013-05-17 16:46:04 +0300737 case 7:
738 SUB_LINK(6, 2);
Daniel Stone2ef9b1a2017-03-13 16:31:36 +0000739 /* fallthrough */
Pekka Paalanenbeb080e2013-05-17 16:46:04 +0300740 case 6:
741 SUB_LINK(5, 1);
Daniel Stone2ef9b1a2017-03-13 16:31:36 +0000742 /* fallthrough */
Pekka Paalanenbeb080e2013-05-17 16:46:04 +0300743 case 5:
744 SUB_LINK(4, 3);
Daniel Stone2ef9b1a2017-03-13 16:31:36 +0000745 /* fallthrough */
Pekka Paalanenbeb080e2013-05-17 16:46:04 +0300746 case 4:
747 SUB_LINK(3, 1);
Daniel Stone2ef9b1a2017-03-13 16:31:36 +0000748 /* fallthrough */
Pekka Paalanenbeb080e2013-05-17 16:46:04 +0300749 case 3:
750 SUB_LINK(2, 0);
Daniel Stone2ef9b1a2017-03-13 16:31:36 +0000751 /* fallthrough */
Pekka Paalanenbeb080e2013-05-17 16:46:04 +0300752 case 2:
753 SUB_LINK(1, 0);
754
755#undef SUB_LINK
756 };
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300757
758 wl_subcompositor_destroy(subco);
Pekka Paalanenbeb080e2013-05-17 16:46:04 +0300759}
760
761static void
762destroy_subsurface_tree(struct wl_surface **surfs,
763 struct wl_subsurface **subs, int n)
764{
765 int i;
766
767 for (i = n; i-- > 0; ) {
768 if (surfs[i])
769 wl_surface_destroy(surfs[i]);
770
771 if (subs[i])
772 wl_subsurface_destroy(subs[i]);
773 }
774}
775
776static int
777has_dupe(int *cnt, int n)
778{
779 int i;
780
781 for (i = 0; i < n; i++)
782 if (cnt[i] == cnt[n])
783 return 1;
784
785 return 0;
786}
787
788/* Note: number of permutations to test is: set_size! / (set_size - NSTEPS)!
789 */
790#define NSTEPS 3
791
792struct permu_state {
793 int set_size;
794 int cnt[NSTEPS];
795};
796
797static void
798permu_init(struct permu_state *s, int set_size)
799{
800 int i;
801
802 s->set_size = set_size;
803 for (i = 0; i < NSTEPS; i++)
804 s->cnt[i] = 0;
805}
806
807static int
808permu_next(struct permu_state *s)
809{
810 int k;
811
812 s->cnt[NSTEPS - 1]++;
813
814 while (1) {
815 if (s->cnt[0] >= s->set_size) {
816 return -1;
817 }
818
819 for (k = 1; k < NSTEPS; k++) {
820 if (s->cnt[k] >= s->set_size) {
821 s->cnt[k - 1]++;
822 s->cnt[k] = 0;
823 break;
824 }
825
826 if (has_dupe(s->cnt, k)) {
827 s->cnt[k]++;
828 break;
829 }
830 }
831
832 if (k == NSTEPS)
833 return 0;
834 }
835}
836
837static void
838destroy_permu_object(struct wl_surface **surfs,
839 struct wl_subsurface **subs, int i)
840{
841 int h = (i + 1) / 2;
842
843 if (i & 1) {
Pekka Paalanen12a138d2019-11-06 15:59:33 +0200844 testlog(" [sub %2d]", h);
Pekka Paalanenbeb080e2013-05-17 16:46:04 +0300845 wl_subsurface_destroy(subs[h]);
846 subs[h] = NULL;
847 } else {
Pekka Paalanen12a138d2019-11-06 15:59:33 +0200848 testlog(" [surf %2d]", h);
Pekka Paalanenbeb080e2013-05-17 16:46:04 +0300849 wl_surface_destroy(surfs[h]);
850 surfs[h] = NULL;
851 }
852}
853
854TEST(test_subsurface_destroy_permutations)
855{
856 /*
857 * Test wl_surface and wl_subsurface destruction orders in a
858 * complex tree of sub-surfaces.
859 *
860 * In the tree of sub-surfaces, go through every possible
861 * permutation of destroying all wl_surface and wl_subsurface
862 * objects. Execpt, to limit running time to a reasonable level,
863 * execute only the first NSTEPS destructions from each
864 * permutation, and ignore identical cases.
865 */
866
867 const int test_size = 11;
868 struct client *client;
869 struct wl_surface *surfs[test_size];
870 struct wl_subsurface *subs[test_size];
871 struct permu_state per;
872 int counter = 0;
873 int i;
874
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200875 client = create_client_and_test_surface(100, 50, 123, 77);
Pekka Paalanenbeb080e2013-05-17 16:46:04 +0300876 assert(client);
877
878 permu_init(&per, test_size * 2 - 1);
879 while (permu_next(&per) != -1) {
880 /* for each permutation of NSTEPS out of test_size */
881 memset(surfs, 0, sizeof surfs);
882 memset(subs, 0, sizeof subs);
883
884 create_subsurface_tree(client, surfs, subs, test_size);
885
Pekka Paalanen12a138d2019-11-06 15:59:33 +0200886 testlog("permu");
Pekka Paalanenbeb080e2013-05-17 16:46:04 +0300887
888 for (i = 0; i < NSTEPS; i++)
Pekka Paalanen12a138d2019-11-06 15:59:33 +0200889 testlog(" %2d", per.cnt[i]);
Pekka Paalanenbeb080e2013-05-17 16:46:04 +0300890
891 for (i = 0; i < NSTEPS; i++)
892 destroy_permu_object(surfs, subs, per.cnt[i]);
893
Pekka Paalanen12a138d2019-11-06 15:59:33 +0200894 testlog("\n");
Pekka Paalanenbeb080e2013-05-17 16:46:04 +0300895 client_roundtrip(client);
896
897 destroy_subsurface_tree(surfs, subs, test_size);
898 counter++;
899 }
900
901 client_roundtrip(client);
Pekka Paalanen12a138d2019-11-06 15:59:33 +0200902 testlog("tried %d destroy permutations\n", counter);
Pekka Paalanenecbf1db2021-06-17 17:46:55 +0300903
904 client_destroy(client);
Pekka Paalanenbeb080e2013-05-17 16:46:04 +0300905}