main neuswc / libswc / layer_shell.c
  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}