commit 8a2d575
shrub
·
2026-03-19 20:39:24 +0000 UTC
parent a77b61b
feat: implement wlr-layer-shell
14 files changed,
+1178,
-26
+1,
-0
1@@ -47,6 +47,7 @@ struct swc {
2 struct swc_drm *const drm;
3 struct wl_global *data_device_manager;
4 struct wl_global *kde_decoration_manager;
5+ struct wl_global *layer_shell;
6 struct wl_global *panel_manager;
7 struct wl_global *shell;
8 struct wl_global *snap_manager;
+624,
-0
1@@ -0,0 +1,624 @@
2+#include "layer_shell.h"
3+
4+#include "compositor.h"
5+#include "internal.h"
6+#include "keyboard.h"
7+#include "output.h"
8+#include "screen.h"
9+#include "seat.h"
10+#include "surface.h"
11+#include "util.h"
12+#include "view.h"
13+
14+#include "wlr-layer-shell-unstable-v1-server-protocol.h"
15+#include <assert.h>
16+#include <inttypes.h>
17+#include <stdlib.h>
18+
19+struct layer_surface {
20+ struct wl_resource *resource;
21+ struct wl_listener surface_destroy_listener;
22+ struct wl_listener surface_commit_listener;
23+ struct compositor_view *view;
24+ struct view_handler view_handler;
25+ struct screen *screen;
26+ struct screen_modifier modifier;
27+ struct layer_surface_state {
28+ uint32_t layer;
29+ uint32_t anchor;
30+ int32_t exclusive_zone;
31+ uint32_t exclusive_edge;
32+ uint32_t keyboard_interactivity;
33+ struct {
34+ int32_t top, right, bottom, left;
35+ } margin;
36+ uint32_t desired_width, desired_height;
37+ } current, pending;
38+ uint32_t configure_serial;
39+ bool configured;
40+ bool mapped;
41+};
42+
43+static bool
44+state_equal(const struct layer_surface_state *a,
45+ const struct layer_surface_state *b)
46+{
47+ return a->layer == b->layer && a->anchor == b->anchor &&
48+ a->exclusive_zone == b->exclusive_zone &&
49+ a->exclusive_edge == b->exclusive_edge &&
50+ a->keyboard_interactivity == b->keyboard_interactivity &&
51+ a->margin.top == b->margin.top &&
52+ a->margin.right == b->margin.right &&
53+ a->margin.bottom == b->margin.bottom &&
54+ a->margin.left == b->margin.left &&
55+ a->desired_width == b->desired_width &&
56+ a->desired_height == b->desired_height;
57+}
58+
59+static int32_t
60+available_size(uint32_t size, int32_t start_margin, int32_t end_margin)
61+{
62+ int32_t available = (int32_t)size - start_margin - end_margin;
63+
64+ return MAX(available, 0);
65+}
66+
67+static uint32_t
68+configure_size(uint32_t desired, uint32_t anchor, uint32_t first_anchor,
69+ uint32_t second_anchor, uint32_t total_size, int32_t start_margin,
70+ int32_t end_margin)
71+{
72+ if (desired != 0) {
73+ return desired;
74+ }
75+
76+ if ((anchor & first_anchor) && (anchor & second_anchor)) {
77+ return available_size(total_size, start_margin, end_margin);
78+ }
79+
80+ return 0;
81+}
82+
83+static uint32_t
84+exclusive_edge(struct layer_surface *surface)
85+{
86+ if (surface->current.exclusive_edge != 0) {
87+ return surface->current.exclusive_edge;
88+ }
89+
90+ switch (surface->current.anchor) {
91+ case ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
92+ ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
93+ ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT:
94+ case ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP:
95+ return ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
96+ case ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
97+ ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
98+ ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT:
99+ case ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM:
100+ return ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
101+ case ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
102+ ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
103+ ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM:
104+ case ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT:
105+ return ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT;
106+ case ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
107+ ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
108+ ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM:
109+ case ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT:
110+ return ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
111+ default:
112+ return 0;
113+ }
114+}
115+
116+static int32_t
117+exclusive_size(struct layer_surface *surface)
118+{
119+ switch (surface->current.exclusive_zone) {
120+ case 0:
121+ return 0;
122+ case -1:
123+ switch (exclusive_edge(surface)) {
124+ case ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP:
125+ return (int32_t)surface->view->base.geometry.height +
126+ surface->current.margin.top;
127+ case ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM:
128+ return (int32_t)surface->view->base.geometry.height +
129+ surface->current.margin.bottom;
130+ case ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT:
131+ return (int32_t)surface->view->base.geometry.width +
132+ surface->current.margin.left;
133+ case ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT:
134+ return (int32_t)surface->view->base.geometry.width +
135+ surface->current.margin.right;
136+ default:
137+ return 0;
138+ }
139+ default:
140+ return MAX(surface->current.exclusive_zone, 0);
141+ }
142+}
143+
144+static void
145+update_usable_geometry(struct layer_surface *surface)
146+{
147+ if (!surface->screen) {
148+ return;
149+ }
150+
151+ screen_update_usable_geometry(surface->screen);
152+}
153+
154+static void
155+restack_layer(struct layer_surface *surface)
156+{
157+ bool always_top = surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP ||
158+ surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY;
159+
160+ surface->view->always_top = always_top;
161+ if (always_top) {
162+ raise_window_top(surface->view);
163+ }
164+}
165+
166+static void
167+update_position(struct layer_surface *surface)
168+{
169+ struct swc_rectangle *screen = &surface->screen->base.geometry;
170+ struct swc_rectangle *view = &surface->view->base.geometry;
171+ int32_t x, y;
172+
173+ if ((surface->current.anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT) &&
174+ !(surface->current.anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
175+ x = screen->x + surface->current.margin.left;
176+ } else if ((surface->current.anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT) &&
177+ !(surface->current.anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
178+ x = screen->x + (int32_t)screen->width - (int32_t)view->width -
179+ surface->current.margin.right;
180+ } else {
181+ x = screen->x + ((int32_t)screen->width - (int32_t)view->width +
182+ surface->current.margin.left -
183+ surface->current.margin.right) /
184+ 2;
185+ }
186+
187+ if ((surface->current.anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP) &&
188+ !(surface->current.anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
189+ y = screen->y + surface->current.margin.top;
190+ } else if ((surface->current.anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM) &&
191+ !(surface->current.anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
192+ y = screen->y + (int32_t)screen->height - (int32_t)view->height -
193+ surface->current.margin.bottom;
194+ } else {
195+ y = screen->y + ((int32_t)screen->height - (int32_t)view->height +
196+ surface->current.margin.top -
197+ surface->current.margin.bottom) /
198+ 2;
199+ }
200+
201+ view_move(&surface->view->base, x, y);
202+}
203+
204+static void
205+send_configure(struct layer_surface *surface)
206+{
207+ uint32_t width, height;
208+
209+ if (!surface->screen) {
210+ return;
211+ }
212+
213+ width = configure_size(surface->current.desired_width, surface->current.anchor,
214+ ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT,
215+ ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT,
216+ surface->screen->base.geometry.width,
217+ surface->current.margin.left,
218+ surface->current.margin.right);
219+ height =
220+ configure_size(surface->current.desired_height, surface->current.anchor,
221+ ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP,
222+ ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
223+ surface->screen->base.geometry.height,
224+ surface->current.margin.top,
225+ surface->current.margin.bottom);
226+ surface->configure_serial = wl_display_next_serial(swc.display);
227+ zwlr_layer_surface_v1_send_configure(surface->resource,
228+ surface->configure_serial, width,
229+ height);
230+}
231+
232+static void
233+set_size(struct wl_client *client, struct wl_resource *resource, uint32_t width,
234+ uint32_t height)
235+{
236+ struct layer_surface *surface = wl_resource_get_user_data(resource);
237+
238+ (void)client;
239+
240+ surface->pending.desired_width = width;
241+ surface->pending.desired_height = height;
242+}
243+
244+static void
245+set_anchor(struct wl_client *client, struct wl_resource *resource,
246+ uint32_t anchor)
247+{
248+ struct layer_surface *surface = wl_resource_get_user_data(resource);
249+
250+ (void)client;
251+
252+ surface->pending.anchor = anchor;
253+}
254+
255+static void
256+set_exclusive_zone(struct wl_client *client, struct wl_resource *resource,
257+ int32_t zone)
258+{
259+ struct layer_surface *surface = wl_resource_get_user_data(resource);
260+
261+ (void)client;
262+
263+ surface->pending.exclusive_zone = zone;
264+}
265+
266+static void
267+set_margin(struct wl_client *client, struct wl_resource *resource, int32_t top,
268+ int32_t right, int32_t bottom, int32_t left)
269+{
270+ struct layer_surface *surface = wl_resource_get_user_data(resource);
271+
272+ (void)client;
273+
274+ surface->pending.margin.top = top;
275+ surface->pending.margin.right = right;
276+ surface->pending.margin.bottom = bottom;
277+ surface->pending.margin.left = left;
278+}
279+
280+static void
281+set_keyboard_interactivity(struct wl_client *client, struct wl_resource *resource,
282+ uint32_t keyboard_interactivity)
283+{
284+ struct layer_surface *surface = wl_resource_get_user_data(resource);
285+
286+ (void)client;
287+
288+ surface->pending.keyboard_interactivity = keyboard_interactivity;
289+}
290+
291+static void
292+get_popup(struct wl_client *client, struct wl_resource *resource,
293+ struct wl_resource *popup)
294+{
295+ (void)client;
296+ (void)resource;
297+ (void)popup;
298+}
299+
300+static void
301+ack_configure(struct wl_client *client, struct wl_resource *resource,
302+ uint32_t serial)
303+{
304+ struct layer_surface *surface = wl_resource_get_user_data(resource);
305+
306+ (void)client;
307+
308+ if (serial == surface->configure_serial) {
309+ update_position(surface);
310+ }
311+}
312+
313+static void
314+set_layer(struct wl_client *client, struct wl_resource *resource, uint32_t layer)
315+{
316+ struct layer_surface *surface = wl_resource_get_user_data(resource);
317+
318+ (void)client;
319+
320+ if (layer > ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY) {
321+ wl_resource_post_error(resource,
322+ ZWLR_LAYER_SHELL_V1_ERROR_INVALID_LAYER,
323+ "invalid layer %" PRIu32, layer);
324+ return;
325+ }
326+
327+ surface->pending.layer = layer;
328+}
329+
330+static void
331+set_exclusive_edge(struct wl_client *client, struct wl_resource *resource,
332+ uint32_t edge)
333+{
334+ struct layer_surface *surface = wl_resource_get_user_data(resource);
335+
336+ (void)client;
337+
338+ surface->pending.exclusive_edge = edge;
339+}
340+
341+static const struct zwlr_layer_surface_v1_interface layer_surface_impl = {
342+ .set_size = set_size,
343+ .set_anchor = set_anchor,
344+ .set_exclusive_zone = set_exclusive_zone,
345+ .set_margin = set_margin,
346+ .set_keyboard_interactivity = set_keyboard_interactivity,
347+ .get_popup = get_popup,
348+ .ack_configure = ack_configure,
349+ .destroy = destroy_resource,
350+ .set_layer = set_layer,
351+ .set_exclusive_edge = set_exclusive_edge,
352+};
353+
354+static void
355+handle_attach(struct view_handler *handler)
356+{
357+ struct layer_surface *surface = wl_container_of(handler, surface, view_handler);
358+ bool mapped = surface->view->base.buffer != NULL;
359+
360+ if (mapped) {
361+ update_position(surface);
362+ restack_layer(surface);
363+ if (!surface->mapped) {
364+ compositor_view_show(surface->view);
365+ if (surface->current.keyboard_interactivity !=
366+ ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE) {
367+ keyboard_set_focus(swc.seat->keyboard, surface->view);
368+ }
369+ }
370+ } else if (surface->mapped) {
371+ compositor_view_hide(surface->view);
372+ }
373+
374+ surface->mapped = mapped;
375+ update_usable_geometry(surface);
376+}
377+
378+static void
379+handle_resize(struct view_handler *handler, uint32_t old_width,
380+ uint32_t old_height)
381+{
382+ struct layer_surface *surface = wl_container_of(handler, surface, view_handler);
383+
384+ (void)old_width;
385+ (void)old_height;
386+
387+ update_position(surface);
388+ update_usable_geometry(surface);
389+}
390+
391+static const struct view_handler_impl view_handler_impl = {
392+ .attach = handle_attach,
393+ .resize = handle_resize,
394+};
395+
396+static void
397+handle_surface_commit(struct wl_listener *listener, void *data)
398+{
399+ struct layer_surface *surface =
400+ wl_container_of(listener, surface, surface_commit_listener);
401+ bool state_changed = !state_equal(&surface->current, &surface->pending);
402+
403+ (void)data;
404+
405+ if (state_changed) {
406+ surface->current = surface->pending;
407+ restack_layer(surface);
408+ update_usable_geometry(surface);
409+ }
410+
411+ /* mke sure that the inital commit and also any later state change gets a fresh
412+ * configure */
413+ if (!surface->configured || state_changed) {
414+ send_configure(surface);
415+ surface->configured = true;
416+ }
417+}
418+
419+static void
420+modify(struct screen_modifier *modifier, const struct swc_rectangle *geom,
421+ pixman_region32_t *usable)
422+{
423+ struct layer_surface *surface = wl_container_of(modifier, surface, modifier);
424+ pixman_box32_t box = {.x1 = geom->x,
425+ .y1 = geom->y,
426+ .x2 = geom->x + geom->width,
427+ .y2 = geom->y + geom->height};
428+ int32_t size;
429+
430+ if (!surface->mapped) {
431+ pixman_region32_reset(usable, &box);
432+ return;
433+ }
434+
435+ size = exclusive_size(surface);
436+ if (size <= 0) {
437+ pixman_region32_reset(usable, &box);
438+ return;
439+ }
440+
441+ /* shrink usuable area*/
442+ switch (exclusive_edge(surface)) {
443+ case ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP:
444+ box.y1 = MAX(box.y1, geom->y + size);
445+ break;
446+ case ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM:
447+ box.y2 = MIN(box.y2, geom->y + geom->height - size);
448+ break;
449+ case ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT:
450+ box.x1 = MAX(box.x1, geom->x + size);
451+ break;
452+ case ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT:
453+ box.x2 = MIN(box.x2, geom->x + geom->width - size);
454+ break;
455+ default:
456+ break;
457+ }
458+
459+ pixman_region32_reset(usable, &box);
460+}
461+
462+static void
463+destroy_layer_surface(struct wl_resource *resource)
464+{
465+ struct layer_surface *surface = wl_resource_get_user_data(resource);
466+ bool had_screen = surface->screen != NULL;
467+
468+ wl_list_remove(&surface->surface_destroy_listener.link);
469+ wl_list_remove(&surface->surface_commit_listener.link);
470+ wl_list_remove(&surface->modifier.link);
471+ compositor_view_destroy(surface->view);
472+ if (had_screen) {
473+ screen_update_usable_geometry(surface->screen);
474+ }
475+ free(surface);
476+}
477+
478+static void
479+handle_surface_destroy(struct wl_listener *listener, void *data)
480+{
481+ struct layer_surface *surface =
482+ wl_container_of(listener, surface, surface_destroy_listener);
483+
484+ (void)data;
485+
486+ wl_resource_destroy(surface->resource);
487+}
488+
489+static struct layer_surface *
490+layer_surface_new(struct wl_client *client, uint32_t version, uint32_t id,
491+ struct surface *surface, struct screen *screen, uint32_t layer)
492+{
493+ struct layer_surface *layer_surface;
494+
495+ layer_surface = calloc(1, sizeof(*layer_surface));
496+ if (!layer_surface) {
497+ goto error0;
498+ }
499+
500+ layer_surface->resource =
501+ wl_resource_create(client, &zwlr_layer_surface_v1_interface, version, id);
502+ if (!layer_surface->resource) {
503+ goto error1;
504+ }
505+
506+ if (!(layer_surface->view = compositor_create_view(surface))) {
507+ goto error2;
508+ }
509+
510+ if (!surface_set_role(surface, layer_surface->resource)) {
511+ goto error3;
512+ }
513+
514+ layer_surface->screen = screen;
515+ layer_surface->current.layer = layer;
516+ layer_surface->pending = layer_surface->current;
517+ layer_surface->current.exclusive_zone = 0;
518+ layer_surface->current.exclusive_edge = 0;
519+ layer_surface->current.keyboard_interactivity =
520+ ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE;
521+ layer_surface->pending = layer_surface->current;
522+ layer_surface->surface_destroy_listener.notify = handle_surface_destroy;
523+ layer_surface->surface_commit_listener.notify = handle_surface_commit;
524+ layer_surface->view_handler.impl = &view_handler_impl;
525+ layer_surface->modifier.modify = modify;
526+ wl_list_init(&layer_surface->modifier.link);
527+ wl_resource_set_implementation(layer_surface->resource, &layer_surface_impl,
528+ layer_surface, destroy_layer_surface);
529+ wl_resource_add_destroy_listener(surface->resource,
530+ &layer_surface->surface_destroy_listener);
531+ wl_signal_add(&surface->signal.commit, &layer_surface->surface_commit_listener);
532+ wl_list_insert(&layer_surface->view->base.handlers,
533+ &layer_surface->view_handler.link);
534+ wl_list_insert(&screen->modifiers, &layer_surface->modifier.link);
535+ restack_layer(layer_surface);
536+
537+ return layer_surface;
538+
539+error3:
540+ compositor_view_destroy(layer_surface->view);
541+error2:
542+ wl_resource_destroy(layer_surface->resource);
543+error1:
544+ free(layer_surface);
545+error0:
546+ return NULL;
547+}
548+
549+static void
550+get_layer_surface(struct wl_client *client, struct wl_resource *resource,
551+ uint32_t id, struct wl_resource *surface_resource,
552+ struct wl_resource *output_resource, uint32_t layer,
553+ const char *namespace_)
554+{
555+ struct surface *surface = wl_resource_get_user_data(surface_resource);
556+ struct output *output;
557+ struct screen *screen;
558+
559+ (void)namespace_;
560+
561+ if (layer > ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY) {
562+ wl_resource_post_error(resource,
563+ ZWLR_LAYER_SHELL_V1_ERROR_INVALID_LAYER,
564+ "invalid layer %" PRIu32, layer);
565+ return;
566+ }
567+
568+ if (surface->role) {
569+ wl_resource_post_error(resource, ZWLR_LAYER_SHELL_V1_ERROR_ROLE,
570+ "surface already has a role");
571+ return;
572+ }
573+
574+ if (surface_has_buffer(surface)) {
575+ wl_resource_post_error(resource,
576+ ZWLR_LAYER_SHELL_V1_ERROR_ALREADY_CONSTRUCTED,
577+ "surface already has a buffer");
578+ return;
579+ }
580+
581+ if (output_resource) {
582+ output = wl_resource_get_user_data(output_resource);
583+ screen = output ? output->screen : NULL;
584+ } else if (!wl_list_empty(&swc.screens)) {
585+ screen = wl_container_of(swc.screens.next, screen, link);
586+ } else {
587+ screen = NULL;
588+ }
589+
590+ if (!screen ||
591+ !layer_surface_new(client, wl_resource_get_version(resource), id, surface,
592+ screen, layer)) {
593+ wl_client_post_no_memory(client);
594+ }
595+}
596+
597+static const struct zwlr_layer_shell_v1_interface layer_shell_impl = {
598+ .get_layer_surface = get_layer_surface,
599+ .destroy = destroy_resource,
600+};
601+
602+static void
603+bind_layer_shell(struct wl_client *client, void *data, uint32_t version,
604+ uint32_t id)
605+{
606+ struct wl_resource *resource;
607+
608+ (void)data;
609+
610+ resource =
611+ wl_resource_create(client, &zwlr_layer_shell_v1_interface, version, id);
612+ if (!resource) {
613+ wl_client_post_no_memory(client);
614+ return;
615+ }
616+
617+ wl_resource_set_implementation(resource, &layer_shell_impl, NULL, NULL);
618+}
619+
620+struct wl_global *
621+layer_shell_create(struct wl_display *display)
622+{
623+ return wl_global_create(display, &zwlr_layer_shell_v1_interface, 5, NULL,
624+ bind_layer_shell);
625+}
+10,
-0
1@@ -0,0 +1,10 @@
2+#ifndef SWC_LAYER_SHELL_H
3+#define SWC_LAYER_SHELL_H
4+
5+struct wl_display;
6+struct wl_global;
7+
8+struct wl_global *
9+layer_shell_create(struct wl_display *display);
10+
11+#endif
+1,
-0
1@@ -11,6 +11,7 @@ libswc_src = files(
2 'input.c',
3 'kde_decoration.c',
4 'keyboard.c',
5+ 'layer_shell.c',
6 'launch.c',
7 'mode.c',
8 'output.c',
+8,
-4
1@@ -258,13 +258,17 @@ panel_new(struct wl_client *client, uint32_t version, uint32_t id,
2 wl_resource_create(client, &swc_panel_interface, version, id);
3
4 if (!panel->resource) {
5- goto error1;
6+ goto error0;
7 }
8
9- if (!(panel->view = compositor_create_view(surface))) {
10+ if (!surface_set_role(surface, panel->resource)) {
11 goto error2;
12 }
13
14+ if (!(panel->view = compositor_create_view(surface))) {
15+ goto error3;
16+ }
17+
18 wl_resource_set_implementation(panel->resource, &panel_impl, panel,
19 &destroy_panel);
20 panel->surface_destroy_listener.notify = &handle_surface_destroy;
21@@ -282,9 +286,9 @@ panel_new(struct wl_client *client, uint32_t version, uint32_t id,
22
23 return panel;
24
25-error2:
26+error3:
27 wl_resource_destroy(panel->resource);
28-error1:
29+error2:
30 free(panel);
31 error0:
32 return NULL;
+7,
-0
1@@ -23,6 +23,7 @@
2
3 #include "shell.h"
4 #include "internal.h"
5+#include "surface.h"
6 #include "shell_surface.h"
7
8 #include <wayland-server.h>
9@@ -34,6 +35,12 @@ get_shell_surface(struct wl_client *client, struct wl_resource *resource,
10 struct surface *surface = wl_resource_get_user_data(surface_resource);
11 struct shell_surface *shell_surface;
12
13+ if (surface->role) {
14+ wl_resource_post_error(resource, WL_SHELL_ERROR_ROLE,
15+ "surface already has a role");
16+ return;
17+ }
18+
19 shell_surface = shell_surface_new(client, wl_resource_get_version(resource),
20 id, surface);
21
+9,
-2
1@@ -249,19 +249,26 @@ shell_surface_new(struct wl_client *client, uint32_t version, uint32_t id,
2 if (!shell_surface->resource) {
3 goto error1;
4 }
5+ if (!surface_set_role(surface, shell_surface->resource)) {
6+ goto error2;
7+ }
8
9+ if (!window_initialize(&shell_surface->window, &window_impl, surface)) {
10+ goto error2;
11+ }
12 wl_resource_set_implementation(shell_surface->resource,
13 &shell_surface_implementation, shell_surface,
14 &destroy_shell_surface);
15- window_initialize(&shell_surface->window, &window_impl, surface);
16 shell_surface->surface_destroy_listener.notify = &handle_surface_destroy;
17 wl_resource_add_destroy_listener(surface->resource,
18 &shell_surface->surface_destroy_listener);
19
20 return shell_surface;
21
22-error1:
23+error2:
24+ wl_resource_destroy(shell_surface->resource);
25 free(shell_surface);
26+error1:
27 error0:
28 return NULL;
29 }
+40,
-0
1@@ -46,12 +46,25 @@ handle_buffer_destroy(struct wl_listener *listener, void *data)
2
3 state = wl_container_of(listener, state, buffer_destroy_listener);
4 state->buffer = NULL;
5+ state->buffer_resource = NULL;
6+}
7+
8+static void
9+handle_role_destroy(struct wl_listener *listener, void *data)
10+{
11+ struct surface *surface = wl_container_of(listener, surface, role_destroy_listener);
12+
13+ (void)data;
14+
15+ surface->role = NULL;
16 }
17
18 static void
19 state_initialize(struct surface_state *state)
20 {
21 state->buffer = NULL;
22+ /*layer-shell rejects surfaces with a pre-existing buffer */
23+ state->buffer_resource = NULL;
24 state->buffer_destroy_listener.notify = &handle_buffer_destroy;
25
26 pixman_region32_init(&state->damage);
27@@ -304,6 +317,7 @@ surface_apply_pending(struct surface *surface, bool flush_children)
28 }
29
30 subsurface_parent_commit(surface);
31+ wl_signal_emit(&surface->signal.commit, surface);
32
33 if (flush_children) {
34 struct subsurface *child;
35@@ -385,6 +399,9 @@ surface_destroy(struct wl_resource *resource)
36 if (surface->view) {
37 wl_list_remove(&surface->view_handler.link);
38 }
39+ if (surface->role) {
40+ wl_list_remove(&surface->role_destroy_listener.link);
41+ }
42
43 free(surface);
44 }
45@@ -416,8 +433,11 @@ surface_new(struct wl_client *client, uint32_t version, uint32_t id)
46
47 /* Initialize the surface. */
48 surface->pending.commit = 0;
49+ wl_signal_init(&surface->signal.commit);
50 surface->view = NULL;
51 surface->view_handler.impl = &view_handler_impl;
52+ surface->role = NULL;
53+ surface->role_destroy_listener.notify = handle_role_destroy;
54 surface->subsurface = NULL;
55 wl_list_init(&surface->subsurfaces);
56 surface->has_window_geometry = false;
57@@ -458,6 +478,26 @@ surface_set_view(struct surface *surface, struct view *view)
58 }
59 }
60
61+bool
62+surface_set_role(struct surface *surface, struct wl_resource *role)
63+{
64+ if (surface->role) {
65+ return false;
66+ }
67+
68+ surface->role = role;
69+ wl_resource_add_destroy_listener(role, &surface->role_destroy_listener);
70+ return true;
71+}
72+
73+bool
74+surface_has_buffer(struct surface *surface)
75+{
76+ return surface->state.buffer_resource ||
77+ ((surface->pending.commit & SURFACE_COMMIT_ATTACH) &&
78+ surface->pending.state.buffer_resource);
79+}
80+
81 void
82 surface_commit_pending(struct surface *surface)
83 {
+9,
-0
1@@ -62,6 +62,9 @@ struct surface_state {
2
3 struct surface {
4 struct wl_resource *resource;
5+ struct {
6+ struct wl_signal commit;
7+ } signal;
8
9 struct surface_state state;
10
11@@ -73,6 +76,8 @@ struct surface {
12
13 struct view *view;
14 struct view_handler view_handler;
15+ struct wl_resource *role;
16+ struct wl_listener role_destroy_listener;
17
18 struct subsurface *subsurface;
19 struct wl_list subsurfaces;
20@@ -86,6 +91,10 @@ struct surface *
21 surface_new(struct wl_client *client, uint32_t version, uint32_t id);
22 void
23 surface_set_view(struct surface *surface, struct view *view);
24+bool
25+surface_set_role(struct surface *surface, struct wl_resource *role);
26+bool
27+surface_has_buffer(struct surface *surface);
28 void
29 surface_commit_pending(struct surface *surface);
30
+20,
-10
1@@ -31,6 +31,7 @@
2 #include "kde_decoration.h"
3 #include "keyboard.h"
4 #include "launch.h"
5+#include "layer_shell.h"
6 #include "panel_manager.h"
7 #include "pointer.h"
8 #include "screen.h"
9@@ -228,57 +229,65 @@ swc_initialize(struct wl_display *display, struct wl_event_loop *event_loop,
10 goto error12;
11 }
12
13+ swc.layer_shell = layer_shell_create(display);
14+ if (!swc.layer_shell) {
15+ ERROR("Could not initialize layer shell\n");
16+ goto error13;
17+ }
18+
19 swc.panel_manager = panel_manager_create(display);
20 if (!swc.panel_manager) {
21 ERROR("Could not initialize panel manager\n");
22- goto error13;
23+ goto error14;
24 }
25
26 swc.snap_manager = snap_manager_create(display);
27 if (!swc.snap_manager) {
28 ERROR("Could not initialize snap manager\n");
29- goto error14;
30+ goto error15;
31 }
32
33 swc.wallpaper_manager = swc_wallpaper_manager_create(display);
34 if (!swc.wallpaper_manager) {
35 ERROR("Could not initialize wallpaper manager\n");
36- goto error15;
37+ goto error16;
38 }
39
40 #ifdef ENABLE_XWAYLAND
41 if (!xserver_initialize()) {
42 ERROR("Could not initialize xwayland\n");
43- goto error16;
44+ goto error17;
45 }
46 #endif
47
48 swc.select_manager = select_manager_create(display);
49 if (!swc.select_manager) {
50 ERROR("Could not initialize select manager\n");
51- goto error17;
52+ goto error18;
53 }
54
55 swc.xdg_output_manager = xdg_output_manager_create(display);
56 if (!swc.xdg_output_manager) {
57 ERROR("Could not initialize XDG output manager\n");
58- goto error17;
59+ goto error18;
60 }
61
62 setup_compositor();
63
64 return true;
65
66-error17:
67+error18:
68 wl_global_destroy(swc.select_manager);
69 #ifdef ENABLE_XWAYLAND
70-error16:
71+error17:
72 wl_global_destroy(swc.wallpaper_manager);
73 #endif
74-error15:
75+error16:
76 wl_global_destroy(swc.snap_manager);
77-error14:
78+error15:
79 wl_global_destroy(swc.panel_manager);
80+error14:
81+ wl_global_destroy(swc.layer_shell);
82 error13:
83 wl_global_destroy(swc.kde_decoration_manager);
84 error12:
85@@ -320,6 +329,7 @@ swc_finalize(void)
86 wl_global_destroy(swc.snap_manager);
87 wl_global_destroy(swc.select_manager);
88 wl_global_destroy(swc.panel_manager);
89+ wl_global_destroy(swc.layer_shell);
90 wl_global_destroy(swc.xdg_decoration_manager);
91 wl_global_destroy(swc.xdg_shell);
92 wl_global_destroy(swc.shell);
+12,
-2
1@@ -38,6 +38,7 @@ get_output(struct wl_client *client, struct wl_resource *resource, uint32_t id,
2 struct output *output =
3 wl_resource_get_user_data(output_resource);
4 struct swc_rectangle *geom = &output->screen->base.geometry;
5+ struct wl_resource *wl_output_resource;
6
7 resource = wl_resource_create(client, &zxdg_output_v1_interface, wl_resource_get_version(resource), id);
8 if (!resource) {
9@@ -48,8 +49,17 @@ get_output(struct wl_client *client, struct wl_resource *resource, uint32_t id,
10 wl_resource_set_implementation(resource, &output_impl, NULL, NULL);
11 zxdg_output_v1_send_logical_position(resource, geom->x, geom->y);
12 zxdg_output_v1_send_logical_size(resource, geom->width, geom->height);
13- zxdg_output_v1_send_name(resource, output->name);
14- wl_output_send_done(output->resource);
15+ if (wl_resource_get_version(resource) >= 2) {
16+ zxdg_output_v1_send_name(resource, output->name);
17+ zxdg_output_v1_send_description(resource, output->name);
18+ }
19+ zxdg_output_v1_send_done(resource);
20+
21+ wl_output_resource =
22+ wl_resource_find_for_client(&output->resources, client);
23+ if (wl_output_resource && wl_resource_get_version(wl_output_resource) >= 2) {
24+ wl_output_send_done(wl_output_resource);
25+ }
26 }
27
28 static const struct zxdg_output_manager_v1_interface output_manager_impl = {
+29,
-8
1@@ -498,8 +498,13 @@ xdg_toplevel_new(struct wl_client *client, uint32_t version, uint32_t id,
2 if (!toplevel->resource) {
3 goto error1;
4 }
5- window_initialize(&toplevel->window, &toplevel_window_impl,
6- xdg_surface->surface);
7+ if (!surface_set_role(xdg_surface->surface, toplevel->resource)) {
8+ goto error2;
9+ }
10+ if (!window_initialize(&toplevel->window, &toplevel_window_impl,
11+ xdg_surface->surface)) {
12+ goto error2;
13+ }
14 wl_array_init(&toplevel->states);
15 wl_resource_set_implementation(toplevel->resource, &toplevel_impl, toplevel,
16 &destroy_toplevel);
17@@ -507,8 +512,10 @@ xdg_toplevel_new(struct wl_client *client, uint32_t version, uint32_t id,
18
19 return toplevel;
20
21-error1:
22+error2:
23+ wl_resource_destroy(toplevel->resource);
24 free(toplevel);
25+error1:
26 error0:
27 return NULL;
28 }
29@@ -559,12 +566,15 @@ xdg_popup_new(struct wl_client *client, uint32_t version, uint32_t id,
30 if (!popup->resource) {
31 goto error1;
32 }
33- wl_resource_set_implementation(popup->resource, &popup_impl, popup,
34- &destroy_popup);
35+ if (!surface_set_role(xdg_surface->surface, popup->resource)) {
36+ goto error2;
37+ }
38 popup->view = compositor_create_view(xdg_surface->surface);
39 if (!popup->view) {
40- goto error2;
41+ goto error3;
42 }
43+ wl_resource_set_implementation(popup->resource, &popup_impl, popup,
44+ &destroy_popup);
45
46 rect = calculate_position(positioner);
47 compositor_view_set_parent(popup->view, parent_view);
48@@ -576,10 +586,11 @@ xdg_popup_new(struct wl_client *client, uint32_t version, uint32_t id,
49
50 return popup;
51
52-error2:
53+error3:
54 wl_resource_destroy(popup->resource);
55-error1:
56+error2:
57 free(popup);
58+error1:
59 error0:
60 return NULL;
61 }
62@@ -597,6 +608,11 @@ get_toplevel(struct wl_client *client, struct wl_resource *resource,
63 "surface already has a role");
64 return;
65 }
66+ if (xdg_surface->surface->role) {
67+ wl_resource_post_error(resource, XDG_WM_BASE_ERROR_ROLE,
68+ "surface already has a role");
69+ return;
70+ }
71 toplevel = xdg_toplevel_new(client, wl_resource_get_version(resource), id,
72 xdg_surface);
73 if (!toplevel) {
74@@ -624,6 +640,11 @@ get_popup(struct wl_client *client, struct wl_resource *resource, uint32_t id,
75 "surface already has a role");
76 return;
77 }
78+ if (xdg_surface->surface->role) {
79+ wl_resource_post_error(resource, XDG_WM_BASE_ERROR_ROLE,
80+ "surface already has a role");
81+ return;
82+ }
83 popup = xdg_popup_new(client, wl_resource_get_version(resource), id,
84 xdg_surface, parent, positioner);
85 if (!popup) {
+1,
-0
1@@ -8,6 +8,7 @@ foreach proto : [
2 'swc_snap.xml',
3 'swc_select.xml',
4 'swc_wallpaper.xml',
5+ 'wlr-layer-shell-unstable-v1.xml',
6 'wayland-drm.xml',
7 wl.find_protocol('xdg-shell', state: 'stable'),
8 wl.find_protocol('linux-dmabuf', state: 'unstable', version: 1),
+407,
-0
1@@ -0,0 +1,407 @@
2+<?xml version="1.0" encoding="UTF-8"?>
3+<protocol name="wlr_layer_shell_unstable_v1">
4+ <copyright>
5+ Copyright © 2017 Drew DeVault
6+
7+ Permission to use, copy, modify, distribute, and sell this
8+ software and its documentation for any purpose is hereby granted
9+ without fee, provided that the above copyright notice appear in
10+ all copies and that both that copyright notice and this permission
11+ notice appear in supporting documentation, and that the name of
12+ the copyright holders not be used in advertising or publicity
13+ pertaining to distribution of the software without specific,
14+ written prior permission. The copyright holders make no
15+ representations about the suitability of this software for any
16+ purpose. It is provided "as is" without express or implied
17+ warranty.
18+
19+ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
20+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
21+ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
22+ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
24+ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
25+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
26+ THIS SOFTWARE.
27+ </copyright>
28+
29+ <interface name="zwlr_layer_shell_v1" version="5">
30+ <description summary="create surfaces that are layers of the desktop">
31+ Clients can use this interface to assign the surface_layer role to
32+ wl_surfaces. Such surfaces are assigned to a "layer" of the output and
33+ rendered with a defined z-depth respective to each other. They may also be
34+ anchored to the edges and corners of a screen and specify input handling
35+ semantics. This interface should be suitable for the implementation of
36+ many desktop shell components, and a broad number of other applications
37+ that interact with the desktop.
38+ </description>
39+
40+ <request name="get_layer_surface">
41+ <description summary="create a layer_surface from a surface">
42+ Create a layer surface for an existing surface. This assigns the role of
43+ layer_surface, or raises a protocol error if another role is already
44+ assigned.
45+
46+ Creating a layer surface from a wl_surface which has a buffer attached
47+ or committed is a client error, and any attempts by a client to attach
48+ or manipulate a buffer prior to the first layer_surface.configure call
49+ must also be treated as errors.
50+
51+ After creating a layer_surface object and setting it up, the client
52+ must perform an initial commit without any buffer attached.
53+ The compositor will reply with a layer_surface.configure event.
54+ The client must acknowledge it and is then allowed to attach a buffer
55+ to map the surface.
56+
57+ You may pass NULL for output to allow the compositor to decide which
58+ output to use. Generally this will be the one that the user most
59+ recently interacted with.
60+
61+ Clients can specify a namespace that defines the purpose of the layer
62+ surface.
63+ </description>
64+ <arg name="id" type="new_id" interface="zwlr_layer_surface_v1"/>
65+ <arg name="surface" type="object" interface="wl_surface"/>
66+ <arg name="output" type="object" interface="wl_output" allow-null="true"/>
67+ <arg name="layer" type="uint" enum="layer" summary="layer to add this surface to"/>
68+ <arg name="namespace" type="string" summary="namespace for the layer surface"/>
69+ </request>
70+
71+ <enum name="error">
72+ <entry name="role" value="0" summary="wl_surface has another role"/>
73+ <entry name="invalid_layer" value="1" summary="layer value is invalid"/>
74+ <entry name="already_constructed" value="2" summary="wl_surface has a buffer attached or committed"/>
75+ </enum>
76+
77+ <enum name="layer">
78+ <description summary="available layers for surfaces">
79+ These values indicate which layers a surface can be rendered in. They
80+ are ordered by z depth, bottom-most first. Traditional shell surfaces
81+ will typically be rendered between the bottom and top layers.
82+ Fullscreen shell surfaces are typically rendered at the top layer.
83+ Multiple surfaces can share a single layer, and ordering within a
84+ single layer is undefined.
85+ </description>
86+
87+ <entry name="background" value="0"/>
88+ <entry name="bottom" value="1"/>
89+ <entry name="top" value="2"/>
90+ <entry name="overlay" value="3"/>
91+ </enum>
92+
93+ <!-- Version 3 additions -->
94+
95+ <request name="destroy" type="destructor" since="3">
96+ <description summary="destroy the layer_shell object">
97+ This request indicates that the client will not use the layer_shell
98+ object any more. Objects that have been created through this instance
99+ are not affected.
100+ </description>
101+ </request>
102+ </interface>
103+
104+ <interface name="zwlr_layer_surface_v1" version="5">
105+ <description summary="layer metadata interface">
106+ An interface that may be implemented by a wl_surface, for surfaces that
107+ are designed to be rendered as a layer of a stacked desktop-like
108+ environment.
109+
110+ Layer surface state (layer, size, anchor, exclusive zone,
111+ margin, interactivity) is double-buffered, and will be applied at the
112+ time wl_surface.commit of the corresponding wl_surface is called.
113+
114+ Attaching a null buffer to a layer surface unmaps it.
115+
116+ Unmapping a layer_surface means that the surface cannot be shown by the
117+ compositor until it is explicitly mapped again. The layer_surface
118+ returns to the state it had right after layer_shell.get_layer_surface.
119+ The client can re-map the surface by performing a commit without any
120+ buffer attached, waiting for a configure event and handling it as usual.
121+ </description>
122+
123+ <request name="set_size">
124+ <description summary="sets the size of the surface">
125+ Sets the size of the surface in surface-local coordinates. The
126+ compositor will display the surface centered with respect to its
127+ anchors.
128+
129+ If you pass 0 for either value, the compositor will assign it and
130+ inform you of the assignment in the configure event. You must set your
131+ anchor to opposite edges in the dimensions you omit; not doing so is a
132+ protocol error. Both values are 0 by default.
133+
134+ Size is double-buffered, see wl_surface.commit.
135+ </description>
136+ <arg name="width" type="uint"/>
137+ <arg name="height" type="uint"/>
138+ </request>
139+
140+ <request name="set_anchor">
141+ <description summary="configures the anchor point of the surface">
142+ Requests that the compositor anchor the surface to the specified edges
143+ and corners. If two orthogonal edges are specified (e.g. 'top' and
144+ 'left'), then the anchor point will be the intersection of the edges
145+ (e.g. the top left corner of the output); otherwise the anchor point
146+ will be centered on that edge, or in the center if none is specified.
147+
148+ Anchor is double-buffered, see wl_surface.commit.
149+ </description>
150+ <arg name="anchor" type="uint" enum="anchor"/>
151+ </request>
152+
153+ <request name="set_exclusive_zone">
154+ <description summary="configures the exclusive geometry of this surface">
155+ Requests that the compositor avoids occluding an area with other
156+ surfaces. The compositor's use of this information is
157+ implementation-dependent - do not assume that this region will not
158+ actually be occluded.
159+
160+ A positive value is only meaningful if the surface is anchored to one
161+ edge or an edge and both perpendicular edges. If the surface is not
162+ anchored, anchored to only two perpendicular edges (a corner), anchored
163+ to only two parallel edges or anchored to all edges, a positive value
164+ will be treated the same as zero.
165+
166+ A positive zone is the distance from the edge in surface-local
167+ coordinates to consider exclusive.
168+
169+ Surfaces that do not wish to have an exclusive zone may instead specify
170+ how they should interact with surfaces that do. If set to zero, the
171+ surface indicates that it would like to be moved to avoid occluding
172+ surfaces with a positive exclusive zone. If set to -1, the surface
173+ indicates that it would not like to be moved to accommodate for other
174+ surfaces, and the compositor should extend it all the way to the edges
175+ it is anchored to.
176+
177+ For example, a panel might set its exclusive zone to 10, so that
178+ maximized shell surfaces are not shown on top of it. A notification
179+ might set its exclusive zone to 0, so that it is moved to avoid
180+ occluding the panel, but shell surfaces are shown underneath it. A
181+ wallpaper or lock screen might set their exclusive zone to -1, so that
182+ they stretch below or over the panel.
183+
184+ The default value is 0.
185+
186+ Exclusive zone is double-buffered, see wl_surface.commit.
187+ </description>
188+ <arg name="zone" type="int"/>
189+ </request>
190+
191+ <request name="set_margin">
192+ <description summary="sets a margin from the anchor point">
193+ Requests that the surface be placed some distance away from the anchor
194+ point on the output, in surface-local coordinates. Setting this value
195+ for edges you are not anchored to has no effect.
196+
197+ The exclusive zone includes the margin.
198+
199+ Margin is double-buffered, see wl_surface.commit.
200+ </description>
201+ <arg name="top" type="int"/>
202+ <arg name="right" type="int"/>
203+ <arg name="bottom" type="int"/>
204+ <arg name="left" type="int"/>
205+ </request>
206+
207+ <enum name="keyboard_interactivity">
208+ <description summary="types of keyboard interaction possible for a layer shell surface">
209+ Types of keyboard interaction possible for layer shell surfaces. The
210+ rationale for this is twofold: (1) some applications are not interested
211+ in keyboard events and not allowing them to be focused can improve the
212+ desktop experience; (2) some applications will want to take exclusive
213+ keyboard focus.
214+ </description>
215+
216+ <entry name="none" value="0">
217+ <description summary="no keyboard focus is possible">
218+ This value indicates that this surface is not interested in keyboard
219+ events and the compositor should never assign it the keyboard focus.
220+
221+ This is the default value, set for newly created layer shell surfaces.
222+
223+ This is useful for e.g. desktop widgets that display information or
224+ only have interaction with non-keyboard input devices.
225+ </description>
226+ </entry>
227+ <entry name="exclusive" value="1">
228+ <description summary="request exclusive keyboard focus">
229+ Request exclusive keyboard focus if this surface is above the shell surface layer.
230+
231+ For the top and overlay layers, the seat will always give
232+ exclusive keyboard focus to the top-most layer which has keyboard
233+ interactivity set to exclusive. If this layer contains multiple
234+ surfaces with keyboard interactivity set to exclusive, the compositor
235+ determines the one receiving keyboard events in an implementation-
236+ defined manner. In this case, no guarantee is made when this surface
237+ will receive keyboard focus (if ever).
238+
239+ For the bottom and background layers, the compositor is allowed to use
240+ normal focus semantics.
241+
242+ This setting is mainly intended for applications that need to ensure
243+ they receive all keyboard events, such as a lock screen or a password
244+ prompt.
245+ </description>
246+ </entry>
247+ <entry name="on_demand" value="2" since="4">
248+ <description summary="request regular keyboard focus semantics">
249+ This requests the compositor to allow this surface to be focused and
250+ unfocused by the user in an implementation-defined manner. The user
251+ should be able to unfocus this surface even regardless of the layer
252+ it is on.
253+
254+ Typically, the compositor will want to use its normal mechanism to
255+ manage keyboard focus between layer shell surfaces with this setting
256+ and regular toplevels on the desktop layer (e.g. click to focus).
257+ Nevertheless, it is possible for a compositor to require a special
258+ interaction to focus or unfocus layer shell surfaces (e.g. requiring
259+ a click even if focus follows the mouse normally, or providing a
260+ keybinding to switch focus between layers).
261+
262+ This setting is mainly intended for desktop shell components (e.g.
263+ panels) that allow keyboard interaction. Using this option can allow
264+ implementing a desktop shell that can be fully usable without the
265+ mouse.
266+ </description>
267+ </entry>
268+ </enum>
269+
270+ <request name="set_keyboard_interactivity">
271+ <description summary="requests keyboard events">
272+ Set how keyboard events are delivered to this surface. By default,
273+ layer shell surfaces do not receive keyboard events; this request can
274+ be used to change this.
275+
276+ This setting is inherited by child surfaces set by the get_popup
277+ request.
278+
279+ Layer surfaces receive pointer, touch, and tablet events normally. If
280+ you do not want to receive them, set the input region on your surface
281+ to an empty region.
282+
283+ Keyboard interactivity is double-buffered, see wl_surface.commit.
284+ </description>
285+ <arg name="keyboard_interactivity" type="uint" enum="keyboard_interactivity"/>
286+ </request>
287+
288+ <request name="get_popup">
289+ <description summary="assign this layer_surface as an xdg_popup parent">
290+ This assigns an xdg_popup's parent to this layer_surface. This popup
291+ should have been created via xdg_surface::get_popup with the parent set
292+ to NULL, and this request must be invoked before committing the popup's
293+ initial state.
294+
295+ See the documentation of xdg_popup for more details about what an
296+ xdg_popup is and how it is used.
297+ </description>
298+ <arg name="popup" type="object" interface="xdg_popup"/>
299+ </request>
300+
301+ <request name="ack_configure">
302+ <description summary="ack a configure event">
303+ When a configure event is received, if a client commits the
304+ surface in response to the configure event, then the client
305+ must make an ack_configure request sometime before the commit
306+ request, passing along the serial of the configure event.
307+
308+ If the client receives multiple configure events before it
309+ can respond to one, it only has to ack the last configure event.
310+
311+ A client is not required to commit immediately after sending
312+ an ack_configure request - it may even ack_configure several times
313+ before its next surface commit.
314+
315+ A client may send multiple ack_configure requests before committing, but
316+ only the last request sent before a commit indicates which configure
317+ event the client really is responding to.
318+ </description>
319+ <arg name="serial" type="uint" summary="the serial from the configure event"/>
320+ </request>
321+
322+ <request name="destroy" type="destructor">
323+ <description summary="destroy the layer_surface">
324+ This request destroys the layer surface.
325+ </description>
326+ </request>
327+
328+ <event name="configure">
329+ <description summary="suggest a surface change">
330+ The configure event asks the client to resize its surface.
331+
332+ Clients should arrange their surface for the new states, and then send
333+ an ack_configure request with the serial sent in this configure event at
334+ some point before committing the new surface.
335+
336+ The client is free to dismiss all but the last configure event it
337+ received.
338+
339+ The width and height arguments specify the size of the window in
340+ surface-local coordinates.
341+
342+ The size is a hint, in the sense that the client is free to ignore it if
343+ it doesn't resize, pick a smaller size (to satisfy aspect ratio or
344+ resize in steps of NxM pixels). If the client picks a smaller size and
345+ is anchored to two opposite anchors (e.g. 'top' and 'bottom'), the
346+ surface will be centered on this axis.
347+
348+ If the width or height arguments are zero, it means the client should
349+ decide its own window dimension.
350+ </description>
351+ <arg name="serial" type="uint"/>
352+ <arg name="width" type="uint"/>
353+ <arg name="height" type="uint"/>
354+ </event>
355+
356+ <event name="closed">
357+ <description summary="surface should be closed">
358+ The closed event is sent by the compositor when the surface will no
359+ longer be shown. The output may have been destroyed or the user may
360+ have asked for it to be removed. Further changes to the surface will be
361+ ignored. The client should destroy the resource after receiving this
362+ event, and create a new surface if they so choose.
363+ </description>
364+ </event>
365+
366+ <enum name="error">
367+ <entry name="invalid_surface_state" value="0" summary="provided surface state is invalid"/>
368+ <entry name="invalid_size" value="1" summary="size is invalid"/>
369+ <entry name="invalid_anchor" value="2" summary="anchor bitfield is invalid"/>
370+ <entry name="invalid_keyboard_interactivity" value="3" summary="keyboard interactivity is invalid"/>
371+ <entry name="invalid_exclusive_edge" value="4" summary="exclusive edge is invalid given the surface anchors"/>
372+ </enum>
373+
374+ <enum name="anchor" bitfield="true">
375+ <entry name="top" value="1" summary="the top edge of the anchor rectangle"/>
376+ <entry name="bottom" value="2" summary="the bottom edge of the anchor rectangle"/>
377+ <entry name="left" value="4" summary="the left edge of the anchor rectangle"/>
378+ <entry name="right" value="8" summary="the right edge of the anchor rectangle"/>
379+ </enum>
380+
381+ <!-- Version 2 additions -->
382+
383+ <request name="set_layer" since="2">
384+ <description summary="change the layer of the surface">
385+ Change the layer that the surface is rendered on.
386+
387+ Layer is double-buffered, see wl_surface.commit.
388+ </description>
389+ <arg name="layer" type="uint" enum="zwlr_layer_shell_v1.layer" summary="layer to move this surface to"/>
390+ </request>
391+
392+ <!-- Version 5 additions -->
393+
394+ <request name="set_exclusive_edge" since="5">
395+ <description summary="set the edge the exclusive zone will be applied to">
396+ Requests an edge for the exclusive zone to apply. The exclusive
397+ edge will be automatically deduced from anchor points when possible,
398+ but when the surface is anchored to a corner, it will be necessary
399+ to set it explicitly to disambiguate, as it is not possible to deduce
400+ which one of the two corner edges should be used.
401+
402+ The edge must be one the surface is anchored to, otherwise the
403+ invalid_exclusive_edge protocol error will be raised.
404+ </description>
405+ <arg name="edge" type="uint" enum="anchor"/>
406+ </request>
407+ </interface>
408+</protocol>