aboutsummaryrefslogtreecommitdiffstats
path: root/sway/desktop/layer_shell.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/desktop/layer_shell.c')
-rw-r--r--sway/desktop/layer_shell.c759
1 files changed, 267 insertions, 492 deletions
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c
index d4ca4fb4..c71abce7 100644
--- a/sway/desktop/layer_shell.c
+++ b/sway/desktop/layer_shell.c
@@ -2,11 +2,11 @@
2#include <stdlib.h> 2#include <stdlib.h>
3#include <string.h> 3#include <string.h>
4#include <wayland-server-core.h> 4#include <wayland-server-core.h>
5#include <wlr/types/wlr_box.h>
6#include <wlr/types/wlr_layer_shell_v1.h> 5#include <wlr/types/wlr_layer_shell_v1.h>
7#include <wlr/types/wlr_output_damage.h>
8#include <wlr/types/wlr_output.h> 6#include <wlr/types/wlr_output.h>
7#include <wlr/types/wlr_subcompositor.h>
9#include "log.h" 8#include "log.h"
9#include "sway/scene_descriptor.h"
10#include "sway/desktop/transaction.h" 10#include "sway/desktop/transaction.h"
11#include "sway/input/cursor.h" 11#include "sway/input/cursor.h"
12#include "sway/input/input-manager.h" 12#include "sway/input/input-manager.h"
@@ -16,156 +16,57 @@
16#include "sway/server.h" 16#include "sway/server.h"
17#include "sway/tree/arrange.h" 17#include "sway/tree/arrange.h"
18#include "sway/tree/workspace.h" 18#include "sway/tree/workspace.h"
19#include <wlr/types/wlr_scene.h>
20
21struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface(
22 struct wlr_surface *surface) {
23 struct wlr_layer_surface_v1 *layer;
24 do {
25 if (!surface) {
26 return NULL;
27 }
28 // Topmost layer surface
29 if ((layer = wlr_layer_surface_v1_try_from_wlr_surface(surface))) {
30 return layer;
31 }
32 // Layer subsurface
33 if (wlr_subsurface_try_from_wlr_surface(surface)) {
34 surface = wlr_surface_get_root_surface(surface);
35 continue;
36 }
19 37
20static void apply_exclusive(struct wlr_box *usable_area, 38 // Layer surface popup
21 uint32_t anchor, int32_t exclusive, 39 struct wlr_xdg_surface *xdg_surface = NULL;
22 int32_t margin_top, int32_t margin_right, 40 if ((xdg_surface = wlr_xdg_surface_try_from_wlr_surface(surface)) &&
23 int32_t margin_bottom, int32_t margin_left) { 41 xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP && xdg_surface->popup != NULL) {
24 if (exclusive <= 0) { 42 if (!xdg_surface->popup->parent) {
25 return; 43 return NULL;
26 }
27 struct {
28 uint32_t singular_anchor;
29 uint32_t anchor_triplet;
30 int *positive_axis;
31 int *negative_axis;
32 int margin;
33 } edges[] = {
34 // Top
35 {
36 .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP,
37 .anchor_triplet =
38 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
39 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
40 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP,
41 .positive_axis = &usable_area->y,
42 .negative_axis = &usable_area->height,
43 .margin = margin_top,
44 },
45 // Bottom
46 {
47 .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
48 .anchor_triplet =
49 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
50 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
51 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
52 .positive_axis = NULL,
53 .negative_axis = &usable_area->height,
54 .margin = margin_bottom,
55 },
56 // Left
57 {
58 .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT,
59 .anchor_triplet =
60 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
61 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
62 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
63 .positive_axis = &usable_area->x,
64 .negative_axis = &usable_area->width,
65 .margin = margin_left,
66 },
67 // Right
68 {
69 .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT,
70 .anchor_triplet =
71 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
72 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
73 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
74 .positive_axis = NULL,
75 .negative_axis = &usable_area->width,
76 .margin = margin_right,
77 },
78 };
79 for (size_t i = 0; i < sizeof(edges) / sizeof(edges[0]); ++i) {
80 if ((anchor == edges[i].singular_anchor || anchor == edges[i].anchor_triplet)
81 && exclusive + edges[i].margin > 0) {
82 if (edges[i].positive_axis) {
83 *edges[i].positive_axis += exclusive + edges[i].margin;
84 } 44 }
85 if (edges[i].negative_axis) { 45 surface = wlr_surface_get_root_surface(xdg_surface->popup->parent);
86 *edges[i].negative_axis -= exclusive + edges[i].margin; 46 continue;
87 }
88 break;
89 } 47 }
90 } 48
49 // Return early if the surface is not a layer/xdg_popup/sub surface
50 return NULL;
51 } while (true);
91} 52}
92 53
93static void arrange_layer(struct sway_output *output, struct wl_list *list, 54static void arrange_surface(struct sway_output *output, const struct wlr_box *full_area,
94 struct wlr_box *usable_area, bool exclusive) { 55 struct wlr_box *usable_area, struct wlr_scene_tree *tree) {
95 struct sway_layer_surface *sway_layer; 56 struct wlr_scene_node *node;
96 struct wlr_box full_area = { 0 }; 57 wl_list_for_each(node, &tree->children, link) {
97 wlr_output_effective_resolution(output->wlr_output, 58 struct sway_layer_surface *surface = scene_descriptor_try_get(node,
98 &full_area.width, &full_area.height); 59 SWAY_SCENE_DESC_LAYER_SHELL);
99 wl_list_for_each(sway_layer, list, link) { 60 // surface could be null during destruction
100 struct wlr_layer_surface_v1 *layer = sway_layer->layer_surface; 61 if (!surface) {
101 struct wlr_layer_surface_v1_state *state = &layer->current;
102 if (exclusive != (state->exclusive_zone > 0)) {
103 continue; 62 continue;
104 } 63 }
105 struct wlr_box bounds; 64
106 if (state->exclusive_zone == -1) { 65 if (!surface->scene->layer_surface->initialized) {
107 bounds = full_area;
108 } else {
109 bounds = *usable_area;
110 }
111 struct wlr_box box = {
112 .width = state->desired_width,
113 .height = state->desired_height
114 };
115 // Horizontal axis
116 const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
117 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
118 if ((state->anchor & both_horiz) && box.width == 0) {
119 box.x = bounds.x;
120 box.width = bounds.width;
121 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
122 box.x = bounds.x;
123 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
124 box.x = bounds.x + (bounds.width - box.width);
125 } else {
126 box.x = bounds.x + ((bounds.width / 2) - (box.width / 2));
127 }
128 // Vertical axis
129 const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP
130 | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
131 if ((state->anchor & both_vert) && box.height == 0) {
132 box.y = bounds.y;
133 box.height = bounds.height;
134 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
135 box.y = bounds.y;
136 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
137 box.y = bounds.y + (bounds.height - box.height);
138 } else {
139 box.y = bounds.y + ((bounds.height / 2) - (box.height / 2));
140 }
141 // Margin
142 if ((state->anchor & both_horiz) == both_horiz) {
143 box.x += state->margin.left;
144 box.width -= state->margin.left + state->margin.right;
145 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
146 box.x += state->margin.left;
147 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
148 box.x -= state->margin.right;
149 }
150 if ((state->anchor & both_vert) == both_vert) {
151 box.y += state->margin.top;
152 box.height -= state->margin.top + state->margin.bottom;
153 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
154 box.y += state->margin.top;
155 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
156 box.y -= state->margin.bottom;
157 }
158 if (box.width < 0 || box.height < 0) {
159 // TODO: Bubble up a protocol error?
160 wlr_layer_surface_v1_close(layer);
161 continue; 66 continue;
162 } 67 }
163 // Apply 68
164 sway_layer->geo = box; 69 wlr_scene_layer_surface_v1_configure(surface->scene, full_area, usable_area);
165 apply_exclusive(usable_area, state->anchor, state->exclusive_zone,
166 state->margin.top, state->margin.right,
167 state->margin.bottom, state->margin.left);
168 wlr_layer_surface_v1_configure(layer, box.width, box.height);
169 } 70 }
170} 71}
171 72
@@ -173,81 +74,81 @@ void arrange_layers(struct sway_output *output) {
173 struct wlr_box usable_area = { 0 }; 74 struct wlr_box usable_area = { 0 };
174 wlr_output_effective_resolution(output->wlr_output, 75 wlr_output_effective_resolution(output->wlr_output,
175 &usable_area.width, &usable_area.height); 76 &usable_area.width, &usable_area.height);
77 const struct wlr_box full_area = usable_area;
78
79 arrange_surface(output, &full_area, &usable_area, output->layers.shell_background);
80 arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom);
81 arrange_surface(output, &full_area, &usable_area, output->layers.shell_top);
82 arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay);
176 83
177 // Arrange exclusive surfaces from top->bottom 84 if (!wlr_box_equal(&usable_area, &output->usable_area)) {
178 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
179 &usable_area, true);
180 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
181 &usable_area, true);
182 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
183 &usable_area, true);
184 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
185 &usable_area, true);
186
187 if (memcmp(&usable_area, &output->usable_area,
188 sizeof(struct wlr_box)) != 0) {
189 sway_log(SWAY_DEBUG, "Usable area changed, rearranging output"); 85 sway_log(SWAY_DEBUG, "Usable area changed, rearranging output");
190 memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); 86 output->usable_area = usable_area;
191 arrange_output(output); 87 arrange_output(output);
192 } 88 }
89}
193 90
194 // Arrange non-exlusive surfaces from top->bottom 91static struct wlr_scene_tree *sway_layer_get_scene(struct sway_output *output,
195 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], 92 enum zwlr_layer_shell_v1_layer type) {
196 &usable_area, false); 93 switch (type) {
197 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], 94 case ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND:
198 &usable_area, false); 95 return output->layers.shell_background;
199 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], 96 case ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM:
200 &usable_area, false); 97 return output->layers.shell_bottom;
201 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], 98 case ZWLR_LAYER_SHELL_V1_LAYER_TOP:
202 &usable_area, false); 99 return output->layers.shell_top;
203 100 case ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY:
204 // Find topmost keyboard interactive layer, if such a layer exists 101 return output->layers.shell_overlay;
205 uint32_t layers_above_shell[] = {
206 ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY,
207 ZWLR_LAYER_SHELL_V1_LAYER_TOP,
208 };
209 size_t nlayers = sizeof(layers_above_shell) / sizeof(layers_above_shell[0]);
210 struct sway_layer_surface *layer, *topmost = NULL;
211 for (size_t i = 0; i < nlayers; ++i) {
212 wl_list_for_each_reverse(layer,
213 &output->layers[layers_above_shell[i]], link) {
214 if (layer->layer_surface->current.keyboard_interactive &&
215 layer->layer_surface->mapped) {
216 topmost = layer;
217 break;
218 }
219 }
220 if (topmost != NULL) {
221 break;
222 }
223 } 102 }
224 103
225 struct sway_seat *seat; 104 sway_assert(false, "unreachable");
226 wl_list_for_each(seat, &server.input->seats, link) { 105 return NULL;
227 if (topmost != NULL) { 106}
228 seat_set_focus_layer(seat, topmost->layer_surface); 107
229 } else if (seat->focused_layer && 108static struct sway_layer_surface *sway_layer_surface_create(
230 !seat->focused_layer->current.keyboard_interactive) { 109 struct wlr_scene_layer_surface_v1 *scene) {
231 seat_set_focus_layer(seat, NULL); 110 struct sway_layer_surface *surface = calloc(1, sizeof(*surface));
232 } 111 if (!surface) {
112 sway_log(SWAY_ERROR, "Could not allocate a scene_layer surface");
113 return NULL;
114 }
115
116 struct wlr_scene_tree *popups = wlr_scene_tree_create(root->layers.popup);
117 if (!popups) {
118 sway_log(SWAY_ERROR, "Could not allocate a scene_layer popup node");
119 free(surface);
120 return NULL;
233 } 121 }
122
123 surface->tree = scene->tree;
124 surface->scene = scene;
125 surface->layer_surface = scene->layer_surface;
126 surface->popups = popups;
127
128 return surface;
234} 129}
235 130
236static struct sway_layer_surface *find_mapped_layer_by_client( 131static struct sway_layer_surface *find_mapped_layer_by_client(
237 struct wl_client *client, struct wlr_output *ignore_output) { 132 struct wl_client *client, struct sway_output *ignore_output) {
238 for (int i = 0; i < root->outputs->length; ++i) { 133 for (int i = 0; i < root->outputs->length; ++i) {
239 struct sway_output *output = root->outputs->items[i]; 134 struct sway_output *output = root->outputs->items[i];
240 if (output->wlr_output == ignore_output) { 135 if (output == ignore_output) {
241 continue; 136 continue;
242 } 137 }
243 // For now we'll only check the overlay layer 138 // For now we'll only check the overlay layer
244 struct sway_layer_surface *lsurface; 139 struct wlr_scene_node *node;
245 wl_list_for_each(lsurface, 140 wl_list_for_each (node, &output->layers.shell_overlay->children, link) {
246 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], link) { 141 struct sway_layer_surface *surface = scene_descriptor_try_get(node,
247 struct wl_resource *resource = lsurface->layer_surface->resource; 142 SWAY_SCENE_DESC_LAYER_SHELL);
143 if (!surface) {
144 continue;
145 }
146
147 struct wlr_layer_surface_v1 *layer_surface = surface->layer_surface;
148 struct wl_resource *resource = layer_surface->resource;
248 if (wl_resource_get_client(resource) == client 149 if (wl_resource_get_client(resource) == client
249 && lsurface->layer_surface->mapped) { 150 && layer_surface->surface->mapped) {
250 return lsurface; 151 return surface;
251 } 152 }
252 } 153 }
253 } 154 }
@@ -255,280 +156,144 @@ static struct sway_layer_surface *find_mapped_layer_by_client(
255} 156}
256 157
257static void handle_output_destroy(struct wl_listener *listener, void *data) { 158static void handle_output_destroy(struct wl_listener *listener, void *data) {
258 struct sway_layer_surface *sway_layer = 159 struct sway_layer_surface *layer =
259 wl_container_of(listener, sway_layer, output_destroy); 160 wl_container_of(listener, layer, output_destroy);
260 // Determine if this layer is being used by an exclusive client. If it is,
261 // try and find another layer owned by this client to pass focus to.
262 struct sway_seat *seat = input_manager_get_default_seat();
263 struct wl_client *client =
264 wl_resource_get_client(sway_layer->layer_surface->resource);
265 bool set_focus = seat->exclusive_client == client;
266
267 wl_list_remove(&sway_layer->output_destroy.link);
268 wl_list_remove(&sway_layer->link);
269 wl_list_init(&sway_layer->link);
270
271 if (set_focus) {
272 struct sway_layer_surface *layer =
273 find_mapped_layer_by_client(client, sway_layer->layer_surface->output);
274 if (layer) {
275 seat_set_focus_layer(seat, layer->layer_surface);
276 }
277 }
278 161
279 sway_layer->layer_surface->output = NULL; 162 layer->output = NULL;
280 wlr_layer_surface_v1_close(sway_layer->layer_surface); 163 wlr_scene_node_destroy(&layer->scene->tree->node);
281} 164}
282 165
283static void handle_surface_commit(struct wl_listener *listener, void *data) { 166static void handle_node_destroy(struct wl_listener *listener, void *data) {
284 struct sway_layer_surface *layer = 167 struct sway_layer_surface *layer =
285 wl_container_of(listener, layer, surface_commit); 168 wl_container_of(listener, layer, node_destroy);
286 struct wlr_layer_surface_v1 *layer_surface = layer->layer_surface;
287 struct wlr_output *wlr_output = layer_surface->output;
288 if (wlr_output == NULL) {
289 return;
290 }
291
292 struct sway_output *output = wlr_output->data;
293 struct wlr_box old_geo = layer->geo;
294 arrange_layers(output);
295
296 bool geo_changed =
297 memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0;
298 bool layer_changed = layer->layer != layer_surface->current.layer;
299 if (layer_changed) {
300 wl_list_remove(&layer->link);
301 wl_list_insert(&output->layers[layer_surface->current.layer],
302 &layer->link);
303 layer->layer = layer_surface->current.layer;
304 }
305 if (geo_changed || layer_changed) {
306 output_damage_surface(output, old_geo.x, old_geo.y,
307 layer_surface->surface, true);
308 output_damage_surface(output, layer->geo.x, layer->geo.y,
309 layer_surface->surface, true);
310 } else {
311 output_damage_surface(output, layer->geo.x, layer->geo.y,
312 layer_surface->surface, false);
313 }
314 169
315 transaction_commit_dirty(); 170 // destroy the scene descriptor straight away if it exists, otherwise
316} 171 // we will try to reflow still considering the destroyed node.
172 scene_descriptor_destroy(&layer->tree->node, SWAY_SCENE_DESC_LAYER_SHELL);
317 173
318static void unmap(struct sway_layer_surface *sway_layer) { 174 // Determine if this layer is being used by an exclusive client. If it is,
319 struct sway_seat *seat; 175 // try and find another layer owned by this client to pass focus to.
320 wl_list_for_each(seat, &server.input->seats, link) { 176 struct sway_seat *seat = input_manager_get_default_seat();
321 if (seat->focused_layer == sway_layer->layer_surface) { 177 struct wl_client *client =
322 seat_set_focus_layer(seat, NULL); 178 wl_resource_get_client(layer->layer_surface->resource);
179 if (!server.session_lock.lock) {
180 struct sway_layer_surface *consider_layer =
181 find_mapped_layer_by_client(client, layer->output);
182 if (consider_layer) {
183 seat_set_focus_layer(seat, consider_layer->layer_surface);
323 } 184 }
324 } 185 }
325 186
326 cursor_rebase_all(); 187 if (layer->output) {
327 188 arrange_layers(layer->output);
328 struct wlr_output *wlr_output = sway_layer->layer_surface->output; 189 transaction_commit_dirty();
329 if (wlr_output == NULL) {
330 return;
331 } 190 }
332 struct sway_output *output = wlr_output->data;
333 if (output == NULL) {
334 return;
335 }
336 output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y,
337 sway_layer->layer_surface->surface, true);
338}
339 191
340static void handle_destroy(struct wl_listener *listener, void *data) { 192 wlr_scene_node_destroy(&layer->popups->node);
341 struct sway_layer_surface *sway_layer =
342 wl_container_of(listener, sway_layer, destroy);
343 sway_log(SWAY_DEBUG, "Layer surface destroyed (%s)",
344 sway_layer->layer_surface->namespace);
345 if (sway_layer->layer_surface->mapped) {
346 unmap(sway_layer);
347 }
348 wl_list_remove(&sway_layer->link);
349 wl_list_remove(&sway_layer->destroy.link);
350 wl_list_remove(&sway_layer->map.link);
351 wl_list_remove(&sway_layer->unmap.link);
352 wl_list_remove(&sway_layer->surface_commit.link);
353 wl_list_remove(&sway_layer->new_popup.link);
354 wl_list_remove(&sway_layer->new_subsurface.link);
355 if (sway_layer->layer_surface->output != NULL) {
356 struct sway_output *output = sway_layer->layer_surface->output->data;
357 if (output != NULL) {
358 arrange_layers(output);
359 transaction_commit_dirty();
360 }
361 wl_list_remove(&sway_layer->output_destroy.link);
362 sway_layer->layer_surface->output = NULL;
363 }
364 free(sway_layer);
365}
366 193
367static void handle_map(struct wl_listener *listener, void *data) { 194 wl_list_remove(&layer->map.link);
368 struct sway_layer_surface *sway_layer = wl_container_of(listener, 195 wl_list_remove(&layer->unmap.link);
369 sway_layer, map); 196 wl_list_remove(&layer->surface_commit.link);
370 struct sway_output *output = sway_layer->layer_surface->output->data; 197 wl_list_remove(&layer->node_destroy.link);
371 output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y, 198 wl_list_remove(&layer->output_destroy.link);
372 sway_layer->layer_surface->surface, true);
373 wlr_surface_send_enter(sway_layer->layer_surface->surface,
374 sway_layer->layer_surface->output);
375 cursor_rebase_all();
376}
377 199
378static void handle_unmap(struct wl_listener *listener, void *data) { 200 free(layer);
379 struct sway_layer_surface *sway_layer = wl_container_of(
380 listener, sway_layer, unmap);
381 unmap(sway_layer);
382} 201}
383 202
384static void subsurface_damage(struct sway_layer_subsurface *subsurface, 203static void handle_surface_commit(struct wl_listener *listener, void *data) {
385 bool whole) { 204 struct sway_layer_surface *surface =
386 struct sway_layer_surface *layer = subsurface->layer_surface; 205 wl_container_of(listener, surface, surface_commit);
387 struct wlr_output *wlr_output = layer->layer_surface->output; 206
388 if (!wlr_output) { 207 struct wlr_layer_surface_v1 *layer_surface = surface->layer_surface;
208 if (!layer_surface->initialized) {
389 return; 209 return;
390 } 210 }
391 struct sway_output *output = wlr_output->data;
392 int ox = subsurface->wlr_subsurface->current.x + layer->geo.x;
393 int oy = subsurface->wlr_subsurface->current.y + layer->geo.y;
394 output_damage_surface(
395 output, ox, oy, subsurface->wlr_subsurface->surface, whole);
396}
397
398static void subsurface_handle_unmap(struct wl_listener *listener, void *data) {
399 struct sway_layer_subsurface *subsurface =
400 wl_container_of(listener, subsurface, unmap);
401 subsurface_damage(subsurface, true);
402}
403 211
404static void subsurface_handle_map(struct wl_listener *listener, void *data) { 212 uint32_t committed = layer_surface->current.committed;
405 struct sway_layer_subsurface *subsurface = 213 if (committed & WLR_LAYER_SURFACE_V1_STATE_LAYER) {
406 wl_container_of(listener, subsurface, map); 214 enum zwlr_layer_shell_v1_layer layer_type = layer_surface->current.layer;
407 subsurface_damage(subsurface, true); 215 struct wlr_scene_tree *output_layer = sway_layer_get_scene(
408} 216 surface->output, layer_type);
409 217 wlr_scene_node_reparent(&surface->scene->tree->node, output_layer);
410static void subsurface_handle_commit(struct wl_listener *listener, void *data) {
411 struct sway_layer_subsurface *subsurface =
412 wl_container_of(listener, subsurface, commit);
413 subsurface_damage(subsurface, false);
414}
415
416static void subsurface_handle_destroy(struct wl_listener *listener,
417 void *data) {
418 struct sway_layer_subsurface *subsurface =
419 wl_container_of(listener, subsurface, destroy);
420
421 wl_list_remove(&subsurface->map.link);
422 wl_list_remove(&subsurface->unmap.link);
423 wl_list_remove(&subsurface->destroy.link);
424 wl_list_remove(&subsurface->commit.link);
425 free(subsurface);
426}
427
428static struct sway_layer_subsurface *create_subsurface(
429 struct wlr_subsurface *wlr_subsurface,
430 struct sway_layer_surface *layer_surface) {
431 struct sway_layer_subsurface *subsurface =
432 calloc(1, sizeof(struct sway_layer_surface));
433 if (subsurface == NULL) {
434 return NULL;
435 } 218 }
436 219
437 subsurface->wlr_subsurface = wlr_subsurface; 220 if (layer_surface->initial_commit || committed || layer_surface->surface->mapped != surface->mapped) {
438 subsurface->layer_surface = layer_surface; 221 surface->mapped = layer_surface->surface->mapped;
439 222 arrange_layers(surface->output);
440 subsurface->map.notify = subsurface_handle_map; 223 transaction_commit_dirty();
441 wl_signal_add(&wlr_subsurface->events.map, &subsurface->map);
442 subsurface->unmap.notify = subsurface_handle_unmap;
443 wl_signal_add(&wlr_subsurface->events.unmap, &subsurface->unmap);
444 subsurface->destroy.notify = subsurface_handle_destroy;
445 wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy);
446 subsurface->commit.notify = subsurface_handle_commit;
447 wl_signal_add(&wlr_subsurface->surface->events.commit, &subsurface->commit);
448
449 return subsurface;
450}
451
452static void handle_new_subsurface(struct wl_listener *listener, void *data) {
453 struct sway_layer_surface *sway_layer_surface =
454 wl_container_of(listener, sway_layer_surface, new_subsurface);
455 struct wlr_subsurface *wlr_subsurface = data;
456 create_subsurface(wlr_subsurface, sway_layer_surface);
457}
458
459
460static struct sway_layer_surface *popup_get_layer(
461 struct sway_layer_popup *popup) {
462 while (popup->parent_type == LAYER_PARENT_POPUP) {
463 popup = popup->parent_popup;
464 } 224 }
465 return popup->parent_layer; 225
226 int lx, ly;
227 wlr_scene_node_coords(&surface->scene->tree->node, &lx, &ly);
228 wlr_scene_node_set_position(&surface->popups->node, lx, ly);
466} 229}
467 230
468static void popup_damage(struct sway_layer_popup *layer_popup, bool whole) { 231static void handle_map(struct wl_listener *listener, void *data) {
469 struct wlr_xdg_popup *popup = layer_popup->wlr_popup; 232 struct sway_layer_surface *surface = wl_container_of(listener,
470 struct wlr_surface *surface = popup->base->surface; 233 surface, map);
471 int popup_sx = popup->geometry.x - popup->base->geometry.x; 234
472 int popup_sy = popup->geometry.y - popup->base->geometry.y; 235 struct wlr_layer_surface_v1 *layer_surface =
473 int ox = popup_sx, oy = popup_sy; 236 surface->scene->layer_surface;
474 struct sway_layer_surface *layer; 237
475 while (true) { 238 // focus on new surface
476 if (layer_popup->parent_type == LAYER_PARENT_POPUP) { 239 if (layer_surface->current.keyboard_interactive &&
477 layer_popup = layer_popup->parent_popup; 240 (layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY ||
478 ox += layer_popup->wlr_popup->geometry.x; 241 layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP)) {
479 oy += layer_popup->wlr_popup->geometry.y; 242 struct sway_seat *seat;
480 } else { 243 wl_list_for_each(seat, &server.input->seats, link) {
481 layer = layer_popup->parent_layer; 244 // but only if the currently focused layer has a lower precedence
482 ox += layer->geo.x; 245 if (!seat->focused_layer ||
483 oy += layer->geo.y; 246 seat->focused_layer->current.layer >= layer_surface->current.layer) {
484 break; 247 seat_set_focus_layer(seat, layer_surface);
248 }
485 } 249 }
250 arrange_layers(surface->output);
486 } 251 }
487 struct wlr_output *wlr_output = layer->layer_surface->output;
488 struct sway_output *output = wlr_output->data;
489 output_damage_surface(output, ox, oy, surface, whole);
490}
491 252
492static void popup_handle_map(struct wl_listener *listener, void *data) { 253 cursor_rebase_all();
493 struct sway_layer_popup *popup = wl_container_of(listener, popup, map);
494 struct sway_layer_surface *layer = popup_get_layer(popup);
495 struct wlr_output *wlr_output = layer->layer_surface->output;
496 wlr_surface_send_enter(popup->wlr_popup->base->surface, wlr_output);
497 popup_damage(popup, true);
498} 254}
499 255
500static void popup_handle_unmap(struct wl_listener *listener, void *data) { 256static void handle_unmap(struct wl_listener *listener, void *data) {
501 struct sway_layer_popup *popup = wl_container_of(listener, popup, unmap); 257 struct sway_layer_surface *surface = wl_container_of(
502 popup_damage(popup, true); 258 listener, surface, unmap);
503} 259 struct sway_seat *seat;
260 wl_list_for_each(seat, &server.input->seats, link) {
261 if (seat->focused_layer == surface->layer_surface) {
262 seat_set_focus_layer(seat, NULL);
263 }
264 }
504 265
505static void popup_handle_commit(struct wl_listener *listener, void *data) { 266 cursor_rebase_all();
506 struct sway_layer_popup *popup = wl_container_of(listener, popup, commit);
507 popup_damage(popup, false);
508} 267}
509 268
510static void popup_handle_destroy(struct wl_listener *listener, void *data) { 269static void popup_handle_destroy(struct wl_listener *listener, void *data) {
511 struct sway_layer_popup *popup = 270 struct sway_layer_popup *popup =
512 wl_container_of(listener, popup, destroy); 271 wl_container_of(listener, popup, destroy);
513 272
514 wl_list_remove(&popup->map.link);
515 wl_list_remove(&popup->unmap.link);
516 wl_list_remove(&popup->destroy.link); 273 wl_list_remove(&popup->destroy.link);
274 wl_list_remove(&popup->new_popup.link);
517 wl_list_remove(&popup->commit.link); 275 wl_list_remove(&popup->commit.link);
518 free(popup); 276 free(popup);
519} 277}
520 278
521static void popup_unconstrain(struct sway_layer_popup *popup) { 279static void popup_unconstrain(struct sway_layer_popup *popup) {
522 struct sway_layer_surface *layer = popup_get_layer(popup);
523 struct wlr_xdg_popup *wlr_popup = popup->wlr_popup; 280 struct wlr_xdg_popup *wlr_popup = popup->wlr_popup;
281 struct sway_output *output = popup->toplevel->output;
524 282
525 struct sway_output *output = layer->layer_surface->output->data; 283 // if a client tries to create a popup while we are in the process of destroying
284 // its output, don't crash.
285 if (!output) {
286 return;
287 }
288
289 int lx, ly;
290 wlr_scene_node_coords(&popup->toplevel->scene->tree->node, &lx, &ly);
526 291
527 // the output box expressed in the coordinate system of the toplevel parent 292 // the output box expressed in the coordinate system of the toplevel parent
528 // of the popup 293 // of the popup
529 struct wlr_box output_toplevel_sx_box = { 294 struct wlr_box output_toplevel_sx_box = {
530 .x = -layer->geo.x, 295 .x = output->lx - lx,
531 .y = -layer->geo.y, 296 .y = output->ly - ly,
532 .width = output->width, 297 .width = output->width,
533 .height = output->height, 298 .height = output->height,
534 }; 299 };
@@ -536,32 +301,38 @@ static void popup_unconstrain(struct sway_layer_popup *popup) {
536 wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); 301 wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box);
537} 302}
538 303
304static void popup_handle_commit(struct wl_listener *listener, void *data) {
305 struct sway_layer_popup *popup = wl_container_of(listener, popup, commit);
306 if (popup->wlr_popup->base->initial_commit) {
307 popup_unconstrain(popup);
308 }
309}
310
539static void popup_handle_new_popup(struct wl_listener *listener, void *data); 311static void popup_handle_new_popup(struct wl_listener *listener, void *data);
540 312
541static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup, 313static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup,
542 enum layer_parent parent_type, void *parent) { 314 struct sway_layer_surface *toplevel, struct wlr_scene_tree *parent) {
543 struct sway_layer_popup *popup = 315 struct sway_layer_popup *popup = calloc(1, sizeof(*popup));
544 calloc(1, sizeof(struct sway_layer_popup));
545 if (popup == NULL) { 316 if (popup == NULL) {
546 return NULL; 317 return NULL;
547 } 318 }
548 319
320 popup->toplevel = toplevel;
549 popup->wlr_popup = wlr_popup; 321 popup->wlr_popup = wlr_popup;
550 popup->parent_type = parent_type; 322 popup->scene = wlr_scene_xdg_surface_create(parent,
551 popup->parent_layer = parent; 323 wlr_popup->base);
324
325 if (!popup->scene) {
326 free(popup);
327 return NULL;
328 }
552 329
553 popup->map.notify = popup_handle_map;
554 wl_signal_add(&wlr_popup->base->events.map, &popup->map);
555 popup->unmap.notify = popup_handle_unmap;
556 wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap);
557 popup->destroy.notify = popup_handle_destroy; 330 popup->destroy.notify = popup_handle_destroy;
558 wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy); 331 wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
559 popup->commit.notify = popup_handle_commit;
560 wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit);
561 popup->new_popup.notify = popup_handle_new_popup; 332 popup->new_popup.notify = popup_handle_new_popup;
562 wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup); 333 wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
563 334 popup->commit.notify = popup_handle_commit;
564 popup_unconstrain(popup); 335 wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit);
565 336
566 return popup; 337 return popup;
567} 338}
@@ -570,19 +341,14 @@ static void popup_handle_new_popup(struct wl_listener *listener, void *data) {
570 struct sway_layer_popup *sway_layer_popup = 341 struct sway_layer_popup *sway_layer_popup =
571 wl_container_of(listener, sway_layer_popup, new_popup); 342 wl_container_of(listener, sway_layer_popup, new_popup);
572 struct wlr_xdg_popup *wlr_popup = data; 343 struct wlr_xdg_popup *wlr_popup = data;
573 create_popup(wlr_popup, LAYER_PARENT_POPUP, sway_layer_popup); 344 create_popup(wlr_popup, sway_layer_popup->toplevel, sway_layer_popup->scene);
574} 345}
575 346
576static void handle_new_popup(struct wl_listener *listener, void *data) { 347static void handle_new_popup(struct wl_listener *listener, void *data) {
577 struct sway_layer_surface *sway_layer_surface = 348 struct sway_layer_surface *sway_layer_surface =
578 wl_container_of(listener, sway_layer_surface, new_popup); 349 wl_container_of(listener, sway_layer_surface, new_popup);
579 struct wlr_xdg_popup *wlr_popup = data; 350 struct wlr_xdg_popup *wlr_popup = data;
580 create_popup(wlr_popup, LAYER_PARENT_LAYER, sway_layer_surface); 351 create_popup(wlr_popup, sway_layer_surface, sway_layer_surface->popups);
581}
582
583struct sway_layer_surface *layer_from_wlr_layer_surface_v1(
584 struct wlr_layer_surface_v1 *layer_surface) {
585 return layer_surface->data;
586} 352}
587 353
588void handle_layer_shell_surface(struct wl_listener *listener, void *data) { 354void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
@@ -590,14 +356,14 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
590 sway_log(SWAY_DEBUG, "new layer surface: namespace %s layer %d anchor %" PRIu32 356 sway_log(SWAY_DEBUG, "new layer surface: namespace %s layer %d anchor %" PRIu32
591 " size %" PRIu32 "x%" PRIu32 " margin %" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",", 357 " size %" PRIu32 "x%" PRIu32 " margin %" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",",
592 layer_surface->namespace, 358 layer_surface->namespace,
593 layer_surface->client_pending.layer, 359 layer_surface->pending.layer,
594 layer_surface->client_pending.anchor, 360 layer_surface->pending.anchor,
595 layer_surface->client_pending.desired_width, 361 layer_surface->pending.desired_width,
596 layer_surface->client_pending.desired_height, 362 layer_surface->pending.desired_height,
597 layer_surface->client_pending.margin.top, 363 layer_surface->pending.margin.top,
598 layer_surface->client_pending.margin.right, 364 layer_surface->pending.margin.right,
599 layer_surface->client_pending.margin.bottom, 365 layer_surface->pending.margin.bottom,
600 layer_surface->client_pending.margin.left); 366 layer_surface->pending.margin.left);
601 367
602 if (!layer_surface->output) { 368 if (!layer_surface->output) {
603 // Assign last active output 369 // Assign last active output
@@ -609,12 +375,12 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
609 output = ws->output; 375 output = ws->output;
610 } 376 }
611 } 377 }
612 if (!output || output == root->noop_output) { 378 if (!output || output == root->fallback_output) {
613 if (!root->outputs->length) { 379 if (!root->outputs->length) {
614 sway_log(SWAY_ERROR, 380 sway_log(SWAY_ERROR,
615 "no output to auto-assign layer surface '%s' to", 381 "no output to auto-assign layer surface '%s' to",
616 layer_surface->namespace); 382 layer_surface->namespace);
617 wlr_layer_surface_v1_close(layer_surface); 383 wlr_layer_surface_v1_destroy(layer_surface);
618 return; 384 return;
619 } 385 }
620 output = root->outputs->items[0]; 386 output = root->outputs->items[0];
@@ -622,42 +388,51 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
622 layer_surface->output = output->wlr_output; 388 layer_surface->output = output->wlr_output;
623 } 389 }
624 390
625 struct sway_layer_surface *sway_layer = 391 struct sway_output *output = layer_surface->output->data;
626 calloc(1, sizeof(struct sway_layer_surface)); 392
627 if (!sway_layer) { 393 enum zwlr_layer_shell_v1_layer layer_type = layer_surface->pending.layer;
394 struct wlr_scene_tree *output_layer = sway_layer_get_scene(
395 output, layer_type);
396 struct wlr_scene_layer_surface_v1 *scene_surface =
397 wlr_scene_layer_surface_v1_create(output_layer, layer_surface);
398 if (!scene_surface) {
399 sway_log(SWAY_ERROR, "Could not allocate a layer_surface_v1");
628 return; 400 return;
629 } 401 }
630 402
631 sway_layer->surface_commit.notify = handle_surface_commit; 403 struct sway_layer_surface *surface =
632 wl_signal_add(&layer_surface->surface->events.commit, 404 sway_layer_surface_create(scene_surface);
633 &sway_layer->surface_commit); 405 if (!surface) {
634 406 wlr_layer_surface_v1_destroy(layer_surface);
635 sway_layer->destroy.notify = handle_destroy;
636 wl_signal_add(&layer_surface->events.destroy, &sway_layer->destroy);
637 sway_layer->map.notify = handle_map;
638 wl_signal_add(&layer_surface->events.map, &sway_layer->map);
639 sway_layer->unmap.notify = handle_unmap;
640 wl_signal_add(&layer_surface->events.unmap, &sway_layer->unmap);
641 sway_layer->new_popup.notify = handle_new_popup;
642 wl_signal_add(&layer_surface->events.new_popup, &sway_layer->new_popup);
643 sway_layer->new_subsurface.notify = handle_new_subsurface;
644 wl_signal_add(&layer_surface->surface->events.new_subsurface,
645 &sway_layer->new_subsurface);
646
647 sway_layer->layer_surface = layer_surface;
648 layer_surface->data = sway_layer;
649 407
650 struct sway_output *output = layer_surface->output->data; 408 sway_log(SWAY_ERROR, "Could not allocate a sway_layer_surface");
651 sway_layer->output_destroy.notify = handle_output_destroy; 409 return;
652 wl_signal_add(&output->events.destroy, &sway_layer->output_destroy); 410 }
653 411
654 wl_list_insert(&output->layers[layer_surface->client_pending.layer], 412 if (!scene_descriptor_assign(&scene_surface->tree->node,
655 &sway_layer->link); 413 SWAY_SCENE_DESC_LAYER_SHELL, surface)) {
656 414 sway_log(SWAY_ERROR, "Failed to allocate a layer surface descriptor");
657 // Temporarily set the layer's current state to client_pending 415 // destroying the layer_surface will also destroy its corresponding
658 // So that we can easily arrange it 416 // scene node
659 struct wlr_layer_surface_v1_state old_state = layer_surface->current; 417 wlr_layer_surface_v1_destroy(layer_surface);
660 layer_surface->current = layer_surface->client_pending; 418 return;
661 arrange_layers(output); 419 }
662 layer_surface->current = old_state; 420
421 surface->output = output;
422
423 surface->surface_commit.notify = handle_surface_commit;
424 wl_signal_add(&layer_surface->surface->events.commit,
425 &surface->surface_commit);
426 surface->map.notify = handle_map;
427 wl_signal_add(&layer_surface->surface->events.map, &surface->map);
428 surface->unmap.notify = handle_unmap;
429 wl_signal_add(&layer_surface->surface->events.unmap, &surface->unmap);
430 surface->new_popup.notify = handle_new_popup;
431 wl_signal_add(&layer_surface->events.new_popup, &surface->new_popup);
432
433 surface->output_destroy.notify = handle_output_destroy;
434 wl_signal_add(&output->events.disable, &surface->output_destroy);
435
436 surface->node_destroy.notify = handle_node_destroy;
437 wl_signal_add(&scene_surface->tree->node.events.destroy, &surface->node_destroy);
663} 438}