1#include "layer_shell.h"
2
3#include "compositor.h"
4#include "internal.h"
5#include "keyboard.h"
6#include "output.h"
7#include "screen.h"
8#include "seat.h"
9#include "surface.h"
10#include "util.h"
11#include "view.h"
12
13#include "wlr-layer-shell-unstable-v1-server-protocol.h"
14#include <assert.h>
15#include <inttypes.h>
16#include <stdlib.h>
17
18struct layer_surface {
19 struct wl_resource *resource;
20 struct wl_listener surface_destroy_listener;
21 struct wl_listener surface_commit_listener;
22 struct compositor_view *view;
23 struct view_handler view_handler;
24 struct screen *screen;
25 struct screen_modifier modifier;
26 struct layer_surface_state {
27 uint32_t layer;
28 uint32_t anchor;
29 int32_t exclusive_zone;
30 uint32_t exclusive_edge;
31 uint32_t keyboard_interactivity;
32 struct {
33 int32_t top, right, bottom, left;
34 } margin;
35 uint32_t desired_width, desired_height;
36 } current, pending;
37 uint32_t configure_serial;
38 bool configured;
39 bool mapped;
40};
41
42static bool
43state_equal(const struct layer_surface_state *a,
44 const struct layer_surface_state *b)
45{
46 return a->layer == b->layer && a->anchor == b->anchor &&
47 a->exclusive_zone == b->exclusive_zone &&
48 a->exclusive_edge == b->exclusive_edge &&
49 a->keyboard_interactivity == b->keyboard_interactivity &&
50 a->margin.top == b->margin.top &&
51 a->margin.right == b->margin.right &&
52 a->margin.bottom == b->margin.bottom &&
53 a->margin.left == b->margin.left &&
54 a->desired_width == b->desired_width &&
55 a->desired_height == b->desired_height;
56}
57
58static int32_t
59available_size(uint32_t size, int32_t start_margin, int32_t end_margin)
60{
61 int32_t available = (int32_t)size - start_margin - end_margin;
62
63 return MAX(available, 0);
64}
65
66static uint32_t
67configure_size(uint32_t desired, uint32_t anchor, uint32_t first_anchor,
68 uint32_t second_anchor, uint32_t total_size, int32_t start_margin,
69 int32_t end_margin)
70{
71 if (desired != 0) {
72 return desired;
73 }
74
75 if ((anchor & first_anchor) && (anchor & second_anchor)) {
76 return available_size(total_size, start_margin, end_margin);
77 }
78
79 return 0;
80}
81
82static uint32_t
83exclusive_edge(struct layer_surface *surface)
84{
85 if (surface->current.exclusive_edge != 0) {
86 return surface->current.exclusive_edge;
87 }
88
89 switch (surface->current.anchor) {
90 case ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
91 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
92 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT:
93 case ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP:
94 return ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
95 case ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
96 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
97 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT:
98 case ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM:
99 return ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
100 case ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
101 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
102 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM:
103 case ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT:
104 return ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT;
105 case ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
106 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
107 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM:
108 case ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT:
109 return ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
110 default:
111 return 0;
112 }
113}
114
115static int32_t
116exclusive_size(struct layer_surface *surface)
117{
118 switch (surface->current.exclusive_zone) {
119 case 0:
120 return 0;
121 case -1:
122 switch (exclusive_edge(surface)) {
123 case ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP:
124 return (int32_t)surface->view->base.geometry.height +
125 surface->current.margin.top;
126 case ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM:
127 return (int32_t)surface->view->base.geometry.height +
128 surface->current.margin.bottom;
129 case ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT:
130 return (int32_t)surface->view->base.geometry.width +
131 surface->current.margin.left;
132 case ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT:
133 return (int32_t)surface->view->base.geometry.width +
134 surface->current.margin.right;
135 default:
136 return 0;
137 }
138 default:
139 return MAX(surface->current.exclusive_zone, 0);
140 }
141}
142
143static void
144update_usable_geometry(struct layer_surface *surface)
145{
146 if (!surface->screen) {
147 return;
148 }
149
150 screen_update_usable_geometry(surface->screen);
151}
152
153static void
154restack_layer(struct layer_surface *surface)
155{
156 uint32_t stack_layer = STACK_LAYER_NORMAL;
157 bool always_top = false;
158
159 switch (surface->current.layer) {
160 case ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND:
161 stack_layer = STACK_LAYER_BACKGROUND;
162 break;
163 case ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM:
164 stack_layer = STACK_LAYER_BOTTOM;
165 break;
166 case ZWLR_LAYER_SHELL_V1_LAYER_TOP:
167 stack_layer = STACK_LAYER_TOP;
168 always_top = true;
169 break;
170 case ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY:
171 stack_layer = STACK_LAYER_OVERLAY;
172 always_top = true;
173 break;
174 default:
175 break;
176 }
177
178 surface->view->always_top = always_top;
179 compositor_view_set_stack_layer(surface->view, stack_layer, true);
180}
181
182static void
183update_position(struct layer_surface *surface)
184{
185 struct swc_rectangle *screen = &surface->screen->base.geometry;
186 struct swc_rectangle *view = &surface->view->base.geometry;
187 int32_t x, y;
188
189 if ((surface->current.anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT) &&
190 !(surface->current.anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
191 x = screen->x + surface->current.margin.left;
192 } else if ((surface->current.anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT) &&
193 !(surface->current.anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
194 x = screen->x + (int32_t)screen->width - (int32_t)view->width -
195 surface->current.margin.right;
196 } else {
197 x = screen->x + ((int32_t)screen->width - (int32_t)view->width +
198 surface->current.margin.left -
199 surface->current.margin.right) /
200 2;
201 }
202
203 if ((surface->current.anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP) &&
204 !(surface->current.anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
205 y = screen->y + surface->current.margin.top;
206 } else if ((surface->current.anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM) &&
207 !(surface->current.anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
208 y = screen->y + (int32_t)screen->height - (int32_t)view->height -
209 surface->current.margin.bottom;
210 } else {
211 y = screen->y + ((int32_t)screen->height - (int32_t)view->height +
212 surface->current.margin.top -
213 surface->current.margin.bottom) /
214 2;
215 }
216
217 view_move(&surface->view->base, x, y);
218}
219
220static void
221send_configure(struct layer_surface *surface)
222{
223 uint32_t width, height;
224
225 if (!surface->screen) {
226 return;
227 }
228
229 width = configure_size(surface->current.desired_width, surface->current.anchor,
230 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT,
231 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT,
232 surface->screen->base.geometry.width,
233 surface->current.margin.left,
234 surface->current.margin.right);
235 height =
236 configure_size(surface->current.desired_height, surface->current.anchor,
237 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP,
238 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
239 surface->screen->base.geometry.height,
240 surface->current.margin.top,
241 surface->current.margin.bottom);
242 surface->configure_serial = wl_display_next_serial(swc.display);
243 zwlr_layer_surface_v1_send_configure(surface->resource,
244 surface->configure_serial, width,
245 height);
246}
247
248static void
249set_size(struct wl_client *client, struct wl_resource *resource, uint32_t width,
250 uint32_t height)
251{
252 struct layer_surface *surface = wl_resource_get_user_data(resource);
253
254 (void)client;
255
256 surface->pending.desired_width = width;
257 surface->pending.desired_height = height;
258}
259
260static void
261set_anchor(struct wl_client *client, struct wl_resource *resource,
262 uint32_t anchor)
263{
264 struct layer_surface *surface = wl_resource_get_user_data(resource);
265
266 (void)client;
267
268 surface->pending.anchor = anchor;
269}
270
271static void
272set_exclusive_zone(struct wl_client *client, struct wl_resource *resource,
273 int32_t zone)
274{
275 struct layer_surface *surface = wl_resource_get_user_data(resource);
276
277 (void)client;
278
279 surface->pending.exclusive_zone = zone;
280}
281
282static void
283set_margin(struct wl_client *client, struct wl_resource *resource, int32_t top,
284 int32_t right, int32_t bottom, int32_t left)
285{
286 struct layer_surface *surface = wl_resource_get_user_data(resource);
287
288 (void)client;
289
290 surface->pending.margin.top = top;
291 surface->pending.margin.right = right;
292 surface->pending.margin.bottom = bottom;
293 surface->pending.margin.left = left;
294}
295
296static void
297set_keyboard_interactivity(struct wl_client *client, struct wl_resource *resource,
298 uint32_t keyboard_interactivity)
299{
300 struct layer_surface *surface = wl_resource_get_user_data(resource);
301
302 (void)client;
303
304 surface->pending.keyboard_interactivity = keyboard_interactivity;
305}
306
307static void
308get_popup(struct wl_client *client, struct wl_resource *resource,
309 struct wl_resource *popup)
310{
311 (void)client;
312 (void)resource;
313 (void)popup;
314}
315
316static void
317ack_configure(struct wl_client *client, struct wl_resource *resource,
318 uint32_t serial)
319{
320 struct layer_surface *surface = wl_resource_get_user_data(resource);
321
322 (void)client;
323
324 if (serial == surface->configure_serial) {
325 update_position(surface);
326 }
327}
328
329static void
330set_layer(struct wl_client *client, struct wl_resource *resource, uint32_t layer)
331{
332 struct layer_surface *surface = wl_resource_get_user_data(resource);
333
334 (void)client;
335
336 if (layer > ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY) {
337 wl_resource_post_error(resource,
338 ZWLR_LAYER_SHELL_V1_ERROR_INVALID_LAYER,
339 "invalid layer %" PRIu32, layer);
340 return;
341 }
342
343 surface->pending.layer = layer;
344}
345
346static void
347set_exclusive_edge(struct wl_client *client, struct wl_resource *resource,
348 uint32_t edge)
349{
350 struct layer_surface *surface = wl_resource_get_user_data(resource);
351
352 (void)client;
353
354 surface->pending.exclusive_edge = edge;
355}
356
357static const struct zwlr_layer_surface_v1_interface layer_surface_impl = {
358 .set_size = set_size,
359 .set_anchor = set_anchor,
360 .set_exclusive_zone = set_exclusive_zone,
361 .set_margin = set_margin,
362 .set_keyboard_interactivity = set_keyboard_interactivity,
363 .get_popup = get_popup,
364 .ack_configure = ack_configure,
365 .destroy = destroy_resource,
366 .set_layer = set_layer,
367 .set_exclusive_edge = set_exclusive_edge,
368};
369
370static void
371handle_attach(struct view_handler *handler)
372{
373 struct layer_surface *surface = wl_container_of(handler, surface, view_handler);
374 bool mapped = surface->view->base.buffer != NULL;
375
376 if (mapped) {
377 update_position(surface);
378 restack_layer(surface);
379 if (!surface->mapped) {
380 compositor_view_show(surface->view);
381 if (surface->current.keyboard_interactivity !=
382 ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE) {
383 keyboard_set_focus(swc.seat->keyboard, surface->view);
384 }
385 }
386 } else if (surface->mapped) {
387 compositor_view_hide(surface->view);
388 }
389
390 surface->mapped = mapped;
391 update_usable_geometry(surface);
392}
393
394static void
395handle_resize(struct view_handler *handler, uint32_t old_width,
396 uint32_t old_height)
397{
398 struct layer_surface *surface = wl_container_of(handler, surface, view_handler);
399
400 (void)old_width;
401 (void)old_height;
402
403 update_position(surface);
404 update_usable_geometry(surface);
405}
406
407static const struct view_handler_impl view_handler_impl = {
408 .attach = handle_attach,
409 .resize = handle_resize,
410};
411
412static void
413handle_surface_commit(struct wl_listener *listener, void *data)
414{
415 struct layer_surface *surface =
416 wl_container_of(listener, surface, surface_commit_listener);
417 bool state_changed = !state_equal(&surface->current, &surface->pending);
418
419 (void)data;
420
421 if (state_changed) {
422 surface->current = surface->pending;
423 restack_layer(surface);
424 update_usable_geometry(surface);
425 }
426
427 /* mke sure that the inital commit and also any later state change gets a fresh
428 * configure */
429 if (!surface->configured || state_changed) {
430 send_configure(surface);
431 surface->configured = true;
432 }
433}
434
435static void
436modify(struct screen_modifier *modifier, const struct swc_rectangle *geom,
437 pixman_region32_t *usable)
438{
439 struct layer_surface *surface = wl_container_of(modifier, surface, modifier);
440 pixman_box32_t box = {.x1 = geom->x,
441 .y1 = geom->y,
442 .x2 = geom->x + geom->width,
443 .y2 = geom->y + geom->height};
444 int32_t size;
445
446 if (!surface->mapped) {
447 pixman_region32_reset(usable, &box);
448 return;
449 }
450
451 size = exclusive_size(surface);
452 if (size <= 0) {
453 pixman_region32_reset(usable, &box);
454 return;
455 }
456
457 /* shrink usuable area*/
458 switch (exclusive_edge(surface)) {
459 case ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP:
460 box.y1 = MAX(box.y1, geom->y + size);
461 break;
462 case ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM:
463 box.y2 = MIN(box.y2, geom->y + geom->height - size);
464 break;
465 case ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT:
466 box.x1 = MAX(box.x1, geom->x + size);
467 break;
468 case ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT:
469 box.x2 = MIN(box.x2, geom->x + geom->width - size);
470 break;
471 default:
472 break;
473 }
474
475 pixman_region32_reset(usable, &box);
476}
477
478static void
479destroy_layer_surface(struct wl_resource *resource)
480{
481 struct layer_surface *surface = wl_resource_get_user_data(resource);
482 bool had_screen = surface->screen != NULL;
483
484 wl_list_remove(&surface->surface_destroy_listener.link);
485 wl_list_remove(&surface->surface_commit_listener.link);
486 wl_list_remove(&surface->modifier.link);
487 compositor_view_destroy(surface->view);
488 if (had_screen) {
489 screen_update_usable_geometry(surface->screen);
490 }
491 free(surface);
492}
493
494static void
495handle_surface_destroy(struct wl_listener *listener, void *data)
496{
497 struct layer_surface *surface =
498 wl_container_of(listener, surface, surface_destroy_listener);
499
500 (void)data;
501
502 wl_resource_destroy(surface->resource);
503}
504
505static struct layer_surface *
506layer_surface_new(struct wl_client *client, uint32_t version, uint32_t id,
507 struct surface *surface, struct screen *screen, uint32_t layer)
508{
509 struct layer_surface *layer_surface;
510
511 layer_surface = calloc(1, sizeof(*layer_surface));
512 if (!layer_surface) {
513 goto error0;
514 }
515
516 layer_surface->resource =
517 wl_resource_create(client, &zwlr_layer_surface_v1_interface, version, id);
518 if (!layer_surface->resource) {
519 goto error1;
520 }
521
522 if (!(layer_surface->view = compositor_create_view(surface))) {
523 goto error2;
524 }
525
526 if (!surface_set_role(surface, layer_surface->resource)) {
527 goto error3;
528 }
529
530 layer_surface->screen = screen;
531 layer_surface->current.layer = layer;
532 layer_surface->pending = layer_surface->current;
533 layer_surface->current.exclusive_zone = 0;
534 layer_surface->current.exclusive_edge = 0;
535 layer_surface->current.keyboard_interactivity =
536 ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE;
537 layer_surface->pending = layer_surface->current;
538 layer_surface->surface_destroy_listener.notify = handle_surface_destroy;
539 layer_surface->surface_commit_listener.notify = handle_surface_commit;
540 layer_surface->view_handler.impl = &view_handler_impl;
541 layer_surface->modifier.modify = modify;
542 wl_list_init(&layer_surface->modifier.link);
543 wl_resource_set_implementation(layer_surface->resource, &layer_surface_impl,
544 layer_surface, destroy_layer_surface);
545 wl_resource_add_destroy_listener(surface->resource,
546 &layer_surface->surface_destroy_listener);
547 wl_signal_add(&surface->signal.commit, &layer_surface->surface_commit_listener);
548 wl_list_insert(&layer_surface->view->base.handlers,
549 &layer_surface->view_handler.link);
550 wl_list_insert(&screen->modifiers, &layer_surface->modifier.link);
551 restack_layer(layer_surface);
552
553 return layer_surface;
554
555error3:
556 compositor_view_destroy(layer_surface->view);
557error2:
558 wl_resource_destroy(layer_surface->resource);
559error1:
560 free(layer_surface);
561error0:
562 return NULL;
563}
564
565static void
566get_layer_surface(struct wl_client *client, struct wl_resource *resource,
567 uint32_t id, struct wl_resource *surface_resource,
568 struct wl_resource *output_resource, uint32_t layer,
569 const char *namespace_)
570{
571 struct surface *surface = wl_resource_get_user_data(surface_resource);
572 struct output *output;
573 struct screen *screen;
574
575 (void)namespace_;
576
577 if (layer > ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY) {
578 wl_resource_post_error(resource,
579 ZWLR_LAYER_SHELL_V1_ERROR_INVALID_LAYER,
580 "invalid layer %" PRIu32, layer);
581 return;
582 }
583
584 if (surface->role) {
585 wl_resource_post_error(resource, ZWLR_LAYER_SHELL_V1_ERROR_ROLE,
586 "surface already has a role");
587 return;
588 }
589
590 if (surface_has_buffer(surface)) {
591 wl_resource_post_error(resource,
592 ZWLR_LAYER_SHELL_V1_ERROR_ALREADY_CONSTRUCTED,
593 "surface already has a buffer");
594 return;
595 }
596
597 if (output_resource) {
598 output = wl_resource_get_user_data(output_resource);
599 screen = output ? output->screen : NULL;
600 } else if (!wl_list_empty(&swc.screens)) {
601 screen = wl_container_of(swc.screens.next, screen, link);
602 } else {
603 screen = NULL;
604 }
605
606 if (!screen ||
607 !layer_surface_new(client, wl_resource_get_version(resource), id, surface,
608 screen, layer)) {
609 wl_client_post_no_memory(client);
610 }
611}
612
613static const struct zwlr_layer_shell_v1_interface layer_shell_impl = {
614 .get_layer_surface = get_layer_surface,
615 .destroy = destroy_resource,
616};
617
618static void
619bind_layer_shell(struct wl_client *client, void *data, uint32_t version,
620 uint32_t id)
621{
622 struct wl_resource *resource;
623
624 (void)data;
625
626 resource =
627 wl_resource_create(client, &zwlr_layer_shell_v1_interface, version, id);
628 if (!resource) {
629 wl_client_post_no_memory(client);
630 return;
631 }
632
633 wl_resource_set_implementation(resource, &layer_shell_impl, NULL, NULL);
634}
635
636struct wl_global *
637layer_shell_create(struct wl_display *display)
638{
639 return wl_global_create(display, &zwlr_layer_shell_v1_interface, 5, NULL,
640 bind_layer_shell);
641}