diff options
Diffstat (limited to 'sway/desktop/layer_shell.c')
-rw-r--r-- | sway/desktop/layer_shell.c | 78 |
1 files changed, 45 insertions, 33 deletions
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index d4ca4fb4..2b4b2027 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c | |||
@@ -2,7 +2,6 @@ | |||
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> | 6 | #include <wlr/types/wlr_output_damage.h> |
8 | #include <wlr/types/wlr_output.h> | 7 | #include <wlr/types/wlr_output.h> |
@@ -115,9 +114,10 @@ static void arrange_layer(struct sway_output *output, struct wl_list *list, | |||
115 | // Horizontal axis | 114 | // Horizontal axis |
116 | const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | 115 | const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
117 | | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; | 116 | | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; |
118 | if ((state->anchor & both_horiz) && box.width == 0) { | 117 | if (box.width == 0) { |
119 | box.x = bounds.x; | 118 | box.x = bounds.x; |
120 | box.width = bounds.width; | 119 | } else if ((state->anchor & both_horiz) == both_horiz) { |
120 | box.x = bounds.x + ((bounds.width / 2) - (box.width / 2)); | ||
121 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { | 121 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { |
122 | box.x = bounds.x; | 122 | box.x = bounds.x; |
123 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { | 123 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { |
@@ -128,9 +128,10 @@ static void arrange_layer(struct sway_output *output, struct wl_list *list, | |||
128 | // Vertical axis | 128 | // Vertical axis |
129 | const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | 129 | const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
130 | | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; | 130 | | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; |
131 | if ((state->anchor & both_vert) && box.height == 0) { | 131 | if (box.height == 0) { |
132 | box.y = bounds.y; | 132 | box.y = bounds.y; |
133 | box.height = bounds.height; | 133 | } else if ((state->anchor & both_vert) == both_vert) { |
134 | box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); | ||
134 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { | 135 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { |
135 | box.y = bounds.y; | 136 | box.y = bounds.y; |
136 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { | 137 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { |
@@ -139,29 +140,37 @@ static void arrange_layer(struct sway_output *output, struct wl_list *list, | |||
139 | box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); | 140 | box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); |
140 | } | 141 | } |
141 | // Margin | 142 | // Margin |
142 | if ((state->anchor & both_horiz) == both_horiz) { | 143 | if (box.width == 0) { |
143 | box.x += state->margin.left; | 144 | box.x += state->margin.left; |
144 | box.width -= state->margin.left + state->margin.right; | 145 | box.width = bounds.width - |
146 | (state->margin.left + state->margin.right); | ||
147 | } else if ((state->anchor & both_horiz) == both_horiz) { | ||
148 | // don't apply margins | ||
145 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { | 149 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { |
146 | box.x += state->margin.left; | 150 | box.x += state->margin.left; |
147 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { | 151 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { |
148 | box.x -= state->margin.right; | 152 | box.x -= state->margin.right; |
149 | } | 153 | } |
150 | if ((state->anchor & both_vert) == both_vert) { | 154 | if (box.height == 0) { |
151 | box.y += state->margin.top; | 155 | box.y += state->margin.top; |
152 | box.height -= state->margin.top + state->margin.bottom; | 156 | box.height = bounds.height - |
157 | (state->margin.top + state->margin.bottom); | ||
158 | } else if ((state->anchor & both_vert) == both_vert) { | ||
159 | // don't apply margins | ||
153 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { | 160 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { |
154 | box.y += state->margin.top; | 161 | box.y += state->margin.top; |
155 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { | 162 | } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { |
156 | box.y -= state->margin.bottom; | 163 | box.y -= state->margin.bottom; |
157 | } | 164 | } |
158 | if (box.width < 0 || box.height < 0) { | 165 | if (!sway_assert(box.width >= 0 && box.height >= 0, |
159 | // TODO: Bubble up a protocol error? | 166 | "Expected layer surface to have positive size")) { |
160 | wlr_layer_surface_v1_close(layer); | ||
161 | continue; | 167 | continue; |
162 | } | 168 | } |
163 | // Apply | 169 | // Apply |
164 | sway_layer->geo = box; | 170 | sway_layer->geo = box; |
171 | wlr_surface_get_extends(layer->surface, &sway_layer->extent); | ||
172 | sway_layer->extent.x += box.x; | ||
173 | sway_layer->extent.y += box.y; | ||
165 | apply_exclusive(usable_area, state->anchor, state->exclusive_zone, | 174 | apply_exclusive(usable_area, state->anchor, state->exclusive_zone, |
166 | state->margin.top, state->margin.right, | 175 | state->margin.top, state->margin.right, |
167 | state->margin.bottom, state->margin.left); | 176 | state->margin.bottom, state->margin.left); |
@@ -191,7 +200,7 @@ void arrange_layers(struct sway_output *output) { | |||
191 | arrange_output(output); | 200 | arrange_output(output); |
192 | } | 201 | } |
193 | 202 | ||
194 | // Arrange non-exlusive surfaces from top->bottom | 203 | // Arrange non-exclusive surfaces from top->bottom |
195 | arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], | 204 | arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], |
196 | &usable_area, false); | 205 | &usable_area, false); |
197 | arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], | 206 | arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], |
@@ -277,7 +286,7 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) { | |||
277 | } | 286 | } |
278 | 287 | ||
279 | sway_layer->layer_surface->output = NULL; | 288 | sway_layer->layer_surface->output = NULL; |
280 | wlr_layer_surface_v1_close(sway_layer->layer_surface); | 289 | wlr_layer_surface_v1_destroy(sway_layer->layer_surface); |
281 | } | 290 | } |
282 | 291 | ||
283 | static void handle_surface_commit(struct wl_listener *listener, void *data) { | 292 | static void handle_surface_commit(struct wl_listener *listener, void *data) { |
@@ -288,13 +297,17 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { | |||
288 | if (wlr_output == NULL) { | 297 | if (wlr_output == NULL) { |
289 | return; | 298 | return; |
290 | } | 299 | } |
300 | if (layer_surface->current.committed == 0) { | ||
301 | // The layer surface state didn't change | ||
302 | return; | ||
303 | } | ||
291 | 304 | ||
292 | struct sway_output *output = wlr_output->data; | 305 | struct sway_output *output = wlr_output->data; |
293 | struct wlr_box old_geo = layer->geo; | 306 | struct wlr_box old_extent = layer->extent; |
294 | arrange_layers(output); | 307 | arrange_layers(output); |
295 | 308 | ||
296 | bool geo_changed = | 309 | bool extent_changed = |
297 | memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0; | 310 | memcmp(&old_extent, &layer->extent, sizeof(struct wlr_box)) != 0; |
298 | bool layer_changed = layer->layer != layer_surface->current.layer; | 311 | bool layer_changed = layer->layer != layer_surface->current.layer; |
299 | if (layer_changed) { | 312 | if (layer_changed) { |
300 | wl_list_remove(&layer->link); | 313 | wl_list_remove(&layer->link); |
@@ -302,9 +315,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { | |||
302 | &layer->link); | 315 | &layer->link); |
303 | layer->layer = layer_surface->current.layer; | 316 | layer->layer = layer_surface->current.layer; |
304 | } | 317 | } |
305 | if (geo_changed || layer_changed) { | 318 | if (extent_changed || layer_changed) { |
306 | output_damage_surface(output, old_geo.x, old_geo.y, | 319 | output_damage_box(output, &old_extent); |
307 | layer_surface->surface, true); | ||
308 | output_damage_surface(output, layer->geo.x, layer->geo.y, | 320 | output_damage_surface(output, layer->geo.x, layer->geo.y, |
309 | layer_surface->surface, true); | 321 | layer_surface->surface, true); |
310 | } else { | 322 | } else { |
@@ -429,7 +441,7 @@ static struct sway_layer_subsurface *create_subsurface( | |||
429 | struct wlr_subsurface *wlr_subsurface, | 441 | struct wlr_subsurface *wlr_subsurface, |
430 | struct sway_layer_surface *layer_surface) { | 442 | struct sway_layer_surface *layer_surface) { |
431 | struct sway_layer_subsurface *subsurface = | 443 | struct sway_layer_subsurface *subsurface = |
432 | calloc(1, sizeof(struct sway_layer_surface)); | 444 | calloc(1, sizeof(struct sway_layer_subsurface)); |
433 | if (subsurface == NULL) { | 445 | if (subsurface == NULL) { |
434 | return NULL; | 446 | return NULL; |
435 | } | 447 | } |
@@ -590,14 +602,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 | 602 | sway_log(SWAY_DEBUG, "new layer surface: namespace %s layer %d anchor %" PRIu32 |
591 | " size %" PRIu32 "x%" PRIu32 " margin %" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",", | 603 | " size %" PRIu32 "x%" PRIu32 " margin %" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",", |
592 | layer_surface->namespace, | 604 | layer_surface->namespace, |
593 | layer_surface->client_pending.layer, | 605 | layer_surface->pending.layer, |
594 | layer_surface->client_pending.anchor, | 606 | layer_surface->pending.anchor, |
595 | layer_surface->client_pending.desired_width, | 607 | layer_surface->pending.desired_width, |
596 | layer_surface->client_pending.desired_height, | 608 | layer_surface->pending.desired_height, |
597 | layer_surface->client_pending.margin.top, | 609 | layer_surface->pending.margin.top, |
598 | layer_surface->client_pending.margin.right, | 610 | layer_surface->pending.margin.right, |
599 | layer_surface->client_pending.margin.bottom, | 611 | layer_surface->pending.margin.bottom, |
600 | layer_surface->client_pending.margin.left); | 612 | layer_surface->pending.margin.left); |
601 | 613 | ||
602 | if (!layer_surface->output) { | 614 | if (!layer_surface->output) { |
603 | // Assign last active output | 615 | // Assign last active output |
@@ -614,7 +626,7 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { | |||
614 | sway_log(SWAY_ERROR, | 626 | sway_log(SWAY_ERROR, |
615 | "no output to auto-assign layer surface '%s' to", | 627 | "no output to auto-assign layer surface '%s' to", |
616 | layer_surface->namespace); | 628 | layer_surface->namespace); |
617 | wlr_layer_surface_v1_close(layer_surface); | 629 | wlr_layer_surface_v1_destroy(layer_surface); |
618 | return; | 630 | return; |
619 | } | 631 | } |
620 | output = root->outputs->items[0]; | 632 | output = root->outputs->items[0]; |
@@ -651,13 +663,13 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { | |||
651 | sway_layer->output_destroy.notify = handle_output_destroy; | 663 | sway_layer->output_destroy.notify = handle_output_destroy; |
652 | wl_signal_add(&output->events.destroy, &sway_layer->output_destroy); | 664 | wl_signal_add(&output->events.destroy, &sway_layer->output_destroy); |
653 | 665 | ||
654 | wl_list_insert(&output->layers[layer_surface->client_pending.layer], | 666 | wl_list_insert(&output->layers[layer_surface->pending.layer], |
655 | &sway_layer->link); | 667 | &sway_layer->link); |
656 | 668 | ||
657 | // Temporarily set the layer's current state to client_pending | 669 | // Temporarily set the layer's current state to pending |
658 | // So that we can easily arrange it | 670 | // So that we can easily arrange it |
659 | struct wlr_layer_surface_v1_state old_state = layer_surface->current; | 671 | struct wlr_layer_surface_v1_state old_state = layer_surface->current; |
660 | layer_surface->current = layer_surface->client_pending; | 672 | layer_surface->current = layer_surface->pending; |
661 | arrange_layers(output); | 673 | arrange_layers(output); |
662 | layer_surface->current = old_state; | 674 | layer_surface->current = old_state; |
663 | } | 675 | } |