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