summaryrefslogtreecommitdiffstats
path: root/sway
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2018-03-28 16:38:11 -0400
committerLibravatar Drew DeVault <sir@cmpwn.com>2018-03-28 16:42:13 -0400
commit68cfa7ef6705c530ff28d9754c5b6cab7b429150 (patch)
tree0c25eb44f1285f2522b6a5f014276239cfa6ae3f /sway
parentAdd initial layer shell skeleton (diff)
downloadsway-68cfa7ef6705c530ff28d9754c5b6cab7b429150.tar.gz
sway-68cfa7ef6705c530ff28d9754c5b6cab7b429150.tar.zst
sway-68cfa7ef6705c530ff28d9754c5b6cab7b429150.zip
Render layer surfaces and respect exclusive zone
Diffstat (limited to 'sway')
-rw-r--r--sway/commands/output.c2
-rw-r--r--sway/config/output.c31
-rw-r--r--sway/desktop/layer_shell.c239
-rw-r--r--sway/desktop/output.c53
-rw-r--r--sway/desktop/xwayland.c4
-rw-r--r--sway/tree/container.c4
-rw-r--r--sway/tree/layout.c11
7 files changed, 312 insertions, 32 deletions
diff --git a/sway/commands/output.c b/sway/commands/output.c
index e747eb4e..35bc8099 100644
--- a/sway/commands/output.c
+++ b/sway/commands/output.c
@@ -188,7 +188,7 @@ static struct cmd_results *cmd_output_background(struct output_config *output,
188 } 188 }
189 189
190 wordexp_t p; 190 wordexp_t p;
191 char *src = join_args(argv + *i - 1, j); 191 char *src = join_args(argv + *i, j);
192 if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) { 192 if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) {
193 return cmd_results_new(CMD_INVALID, "output", 193 return cmd_results_new(CMD_INVALID, "output",
194 "Invalid syntax (%s).", src); 194 "Invalid syntax (%s).", src);
diff --git a/sway/config/output.c b/sway/config/output.c
index 69e883f1..c4168b4f 100644
--- a/sway/config/output.c
+++ b/sway/config/output.c
@@ -1,9 +1,12 @@
1#define _XOPEN_SOURCE 700 1#define _XOPEN_SOURCE 700
2#include <assert.h>
2#include <stdbool.h> 3#include <stdbool.h>
3#include <string.h> 4#include <string.h>
4#include <assert.h> 5#include <signal.h>
6#include <sys/wait.h>
5#include <wlr/types/wlr_output.h> 7#include <wlr/types/wlr_output.h>
6#include <wlr/types/wlr_output_layout.h> 8#include <wlr/types/wlr_output_layout.h>
9#include <unistd.h>
7#include "sway/config.h" 10#include "sway/config.h"
8#include "sway/output.h" 11#include "sway/output.h"
9#include "log.h" 12#include "log.h"
@@ -107,6 +110,16 @@ static void set_mode(struct wlr_output *output, int width, int height,
107 } 110 }
108} 111}
109 112
113void terminate_swaybg(pid_t pid) {
114 int ret = kill(pid, SIGTERM);
115 if (ret != 0) {
116 wlr_log(L_ERROR, "Unable to terminate swaybg [pid: %d]", pid);
117 } else {
118 int status;
119 waitpid(pid, &status, 0);
120 }
121}
122
110void apply_output_config(struct output_config *oc, swayc_t *output) { 123void apply_output_config(struct output_config *oc, swayc_t *output) {
111 assert(output->type == C_OUTPUT); 124 assert(output->type == C_OUTPUT);
112 125
@@ -160,12 +173,12 @@ void apply_output_config(struct output_config *oc, swayc_t *output) {
160 } 173 }
161 174
162 if (oc && oc->background) { 175 if (oc && oc->background) {
163 // TODO swaybg 176 if (output->sway_output->bg_pid != 0) {
164 /*if (output->bg_pid != 0) { 177 terminate_swaybg(output->sway_output->bg_pid);
165 terminate_swaybg(output->bg_pid);
166 } 178 }
167 179
168 wlr_log(L_DEBUG, "Setting background for output %d to %s", output_i, oc->background); 180 wlr_log(L_DEBUG, "Setting background for output %d to %s",
181 output_i, oc->background);
169 182
170 size_t bufsize = 12; 183 size_t bufsize = 12;
171 char output_id[bufsize]; 184 char output_id[bufsize];
@@ -173,17 +186,17 @@ void apply_output_config(struct output_config *oc, swayc_t *output) {
173 output_id[bufsize-1] = 0; 186 output_id[bufsize-1] = 0;
174 187
175 char *const cmd[] = { 188 char *const cmd[] = {
176 "swaybg", 189 "./swaybg/swaybg",
177 output_id, 190 output_id,
178 oc->background, 191 oc->background,
179 oc->background_option, 192 oc->background_option,
180 NULL, 193 NULL,
181 }; 194 };
182 195
183 output->bg_pid = fork(); 196 output->sway_output->bg_pid = fork();
184 if (output->bg_pid == 0) { 197 if (output->sway_output->bg_pid == 0) {
185 execvp(cmd[0], cmd); 198 execvp(cmd[0], cmd);
186 }*/ 199 }
187 } 200 }
188} 201}
189 202
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c
index 3cf171bd..a2506d21 100644
--- a/sway/desktop/layer_shell.c
+++ b/sway/desktop/layer_shell.c
@@ -1,40 +1,261 @@
1#include <stdbool.h>
1#include <stdlib.h> 2#include <stdlib.h>
3#include <string.h>
2#include <wayland-server.h> 4#include <wayland-server.h>
5#include <wlr/types/wlr_box.h>
6#include <wlr/types/wlr_layer_shell.h>
7#include <wlr/types/wlr_output.h>
3#include <wlr/util/log.h> 8#include <wlr/util/log.h>
4#include "sway/layers.h" 9#include "sway/layers.h"
10#include "sway/layout.h"
5#include "sway/output.h" 11#include "sway/output.h"
6#include "sway/server.h" 12#include "sway/server.h"
7 13
8static void arrange_layers(struct sway_output *output) { 14static void apply_exclusive(struct wlr_box *usable_area,
9 // TODO 15 uint32_t anchor, int32_t exclusive,
16 int32_t margin_top, int32_t margin_right,
17 int32_t margin_bottom, int32_t margin_left) {
18 if (exclusive <= 0) {
19 return;
20 }
21 struct {
22 uint32_t anchors;
23 int *positive_axis;
24 int *negative_axis;
25 int margin;
26 } edges[] = {
27 {
28 .anchors =
29 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
30 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
31 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP,
32 .positive_axis = &usable_area->y,
33 .negative_axis = &usable_area->height,
34 .margin = margin_top,
35 },
36 {
37 .anchors =
38 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
39 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
40 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
41 .positive_axis = NULL,
42 .negative_axis = &usable_area->height,
43 .margin = margin_bottom,
44 },
45 {
46 .anchors =
47 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
48 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
49 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
50 .positive_axis = &usable_area->x,
51 .negative_axis = &usable_area->width,
52 .margin = margin_left,
53 },
54 {
55 .anchors =
56 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
57 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
58 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
59 .positive_axis = NULL,
60 .negative_axis = &usable_area->width,
61 .margin = margin_right,
62 },
63 };
64 for (size_t i = 0; i < sizeof(edges) / sizeof(edges[0]); ++i) {
65 if ((anchor & edges[i].anchors) == edges[i].anchors) {
66 if (edges[i].positive_axis) {
67 *edges[i].positive_axis += exclusive + edges[i].margin;
68 }
69 if (edges[i].negative_axis) {
70 *edges[i].negative_axis -= exclusive + edges[i].margin;
71 }
72 }
73 }
74}
75
76static void arrange_layer(struct sway_output *output, struct wl_list *list,
77 struct wlr_box *usable_area, bool exclusive) {
78 struct sway_layer_surface *sway_layer;
79 struct wlr_box full_area = { 0 };
80 wlr_output_effective_resolution(output->wlr_output,
81 &full_area.width, &full_area.height);
82 wl_list_for_each(sway_layer, list, link) {
83 struct wlr_layer_surface *layer = sway_layer->layer_surface;
84 struct wlr_layer_surface_state *state = &layer->current;
85 if (exclusive != (state->exclusive_zone > 0)) {
86 continue;
87 }
88 struct wlr_box bounds;
89 if (state->exclusive_zone == -1) {
90 bounds = full_area;
91 } else {
92 bounds = *usable_area;
93 }
94 struct wlr_box box = {
95 .width = state->desired_width,
96 .height = state->desired_height
97 };
98 // Horizontal axis
99 const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
100 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
101 if ((state->anchor & both_horiz) && box.width == 0) {
102 box.x = bounds.x;
103 box.width = bounds.width;
104 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
105 box.x = bounds.x;
106 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
107 box.x = bounds.x + (bounds.width - box.width);
108 } else {
109 box.x = bounds.x + ((bounds.width / 2) - (box.width / 2));
110 }
111 // Vertical axis
112 const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP
113 | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
114 if ((state->anchor & both_vert) && box.height == 0) {
115 box.y = bounds.y;
116 box.height = bounds.height;
117 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
118 box.y = bounds.y;
119 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
120 box.y = bounds.y + (bounds.height - box.height);
121 } else {
122 box.y = bounds.y + ((bounds.height / 2) - (box.height / 2));
123 }
124 // Margin
125 if ((state->anchor & both_horiz) == both_horiz) {
126 box.x += state->margin.left;
127 box.width -= state->margin.left + state->margin.right;
128 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
129 box.x += state->margin.left;
130 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
131 box.x -= state->margin.right;
132 }
133 if ((state->anchor & both_vert) == both_vert) {
134 box.y += state->margin.top;
135 box.height -= state->margin.top + state->margin.bottom;
136 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
137 box.y += state->margin.top;
138 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
139 box.y -= state->margin.bottom;
140 }
141 if (box.width < 0 || box.height < 0) {
142 // TODO: Bubble up a protocol error?
143 wlr_layer_surface_close(layer);
144 continue;
145 }
146 // Apply
147 sway_layer->geo = box;
148 apply_exclusive(usable_area, state->anchor, state->exclusive_zone,
149 state->margin.top, state->margin.right,
150 state->margin.bottom, state->margin.left);
151 wlr_layer_surface_configure(layer, box.width, box.height);
152 }
153}
154
155void arrange_layers(struct sway_output *output) {
156 struct wlr_box usable_area = { 0 };
157 wlr_output_effective_resolution(output->wlr_output,
158 &usable_area.width, &usable_area.height);
159 struct wlr_box usable_area_before = output->usable_area;
160
161 // Arrange exclusive surfaces from top->bottom
162 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
163 &usable_area, true);
164 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
165 &usable_area, true);
166 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
167 &usable_area, true);
168 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
169 &usable_area, true);
170 memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box));
171
172 if (memcmp(&usable_area_before,
173 &usable_area, sizeof(struct wlr_box)) != 0) {
174 wlr_log(L_DEBUG, "arrange");
175 arrange_windows(output->swayc, -1, -1);
176 }
177
178 // Arrange non-exlusive surfaces from top->bottom
179 usable_area.x = usable_area.y = 0;
180 wlr_output_effective_resolution(output->wlr_output,
181 &usable_area.width, &usable_area.height);
182 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
183 &usable_area, false);
184 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
185 &usable_area, false);
186 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
187 &usable_area, false);
188 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
189 &usable_area, false);
10} 190}
11 191
12static void handle_output_destroy(struct wl_listener *listener, void *data) { 192static void handle_output_destroy(struct wl_listener *listener, void *data) {
13 // TODO 193 struct sway_layer_surface *sway_layer =
194 wl_container_of(listener, sway_layer, output_destroy);
195 sway_layer->layer_surface->output = NULL;
196 wl_list_remove(&sway_layer->output_destroy.link);
197 wl_list_remove(&sway_layer->output_mode.link);
198 wlr_layer_surface_close(sway_layer->layer_surface);
14} 199}
15 200
16static void handle_output_mode(struct wl_listener *listener, void *data) { 201static void handle_output_mode(struct wl_listener *listener, void *data) {
17 // TODO 202 struct wlr_output *output = data;
203 arrange_layers((struct sway_output *)output->data);
18} 204}
19 205
20static void handle_output_transform(struct wl_listener *listener, void *data) { 206static void handle_output_transform(struct wl_listener *listener, void *data) {
21 // TODO 207 struct wlr_output *output = data;
208 arrange_layers((struct sway_output *)output->data);
22} 209}
23 210
24static void handle_surface_commit(struct wl_listener *listener, void *data) { 211static void handle_surface_commit(struct wl_listener *listener, void *data) {
25 // TODO 212 struct sway_layer_surface *layer =
213 wl_container_of(listener, layer, surface_commit);
214 struct wlr_layer_surface *layer_surface = layer->layer_surface;
215 struct wlr_output *wlr_output = layer_surface->output;
216 if (wlr_output != NULL) {
217 struct sway_output *output = wlr_output->data;
218 struct wlr_box old_geo = layer->geo;
219 arrange_layers(output);
220 if (memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0) {
221 // TODO DAMAGE apply whole surface from previous and new geos
222 } else {
223 // TODO DAMAGE from surface damage
224 }
225 }
226}
227
228static void unmap(struct wlr_layer_surface *layer_surface) {
229 // TODO DAMAGE
26} 230}
27 231
28static void handle_destroy(struct wl_listener *listener, void *data) { 232static void handle_destroy(struct wl_listener *listener, void *data) {
29 // TODO 233 struct sway_layer_surface *sway_layer = wl_container_of(
234 listener, sway_layer, destroy);
235 if (sway_layer->layer_surface->mapped) {
236 unmap(sway_layer->layer_surface);
237 }
238 wl_list_remove(&sway_layer->link);
239 wl_list_remove(&sway_layer->destroy.link);
240 wl_list_remove(&sway_layer->map.link);
241 wl_list_remove(&sway_layer->unmap.link);
242 wl_list_remove(&sway_layer->surface_commit.link);
243 wl_list_remove(&sway_layer->output_destroy.link);
244 wl_list_remove(&sway_layer->output_mode.link);
245 wl_list_remove(&sway_layer->output_transform.link);
246 struct sway_output *output = sway_layer->layer_surface->output->data;
247 arrange_layers(output);
248 free(sway_layer);
30} 249}
31 250
32static void handle_map(struct wl_listener *listener, void *data) { 251static void handle_map(struct wl_listener *listener, void *data) {
33 // TODO 252 // TODO DAMAGE
34} 253}
35 254
36static void handle_unmap(struct wl_listener *listener, void *data) { 255static void handle_unmap(struct wl_listener *listener, void *data) {
37 // TODO 256 struct sway_layer_surface *sway_layer = wl_container_of(
257 listener, sway_layer, unmap);
258 unmap(sway_layer->layer_surface);
38} 259}
39 260
40void handle_layer_shell_surface(struct wl_listener *listener, void *data) { 261void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index a9aa47a6..59f79a81 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -4,14 +4,17 @@
4#include <time.h> 4#include <time.h>
5#include <wayland-server.h> 5#include <wayland-server.h>
6#include <wlr/render/wlr_renderer.h> 6#include <wlr/render/wlr_renderer.h>
7#include <wlr/types/wlr_box.h>
7#include <wlr/types/wlr_matrix.h> 8#include <wlr/types/wlr_matrix.h>
8#include <wlr/types/wlr_output.h> 9#include <wlr/types/wlr_output.h>
10#include <wlr/types/wlr_output_layout.h>
9#include <wlr/types/wlr_surface.h> 11#include <wlr/types/wlr_surface.h>
10#include <wlr/types/wlr_wl_shell.h> 12#include <wlr/types/wlr_wl_shell.h>
11#include "log.h" 13#include "log.h"
12#include "sway/container.h" 14#include "sway/container.h"
13#include "sway/input/input-manager.h" 15#include "sway/input/input-manager.h"
14#include "sway/input/seat.h" 16#include "sway/input/seat.h"
17#include "sway/layers.h"
15#include "sway/layout.h" 18#include "sway/layout.h"
16#include "sway/output.h" 19#include "sway/output.h"
17#include "sway/server.h" 20#include "sway/server.h"
@@ -177,6 +180,20 @@ static void output_frame_view(swayc_t *view, void *data) {
177 } 180 }
178} 181}
179 182
183static void render_layer(struct sway_output *output,
184 const struct wlr_box *output_layout_box,
185 struct timespec *when,
186 struct wl_list *layer) {
187 struct sway_layer_surface *sway_layer;
188 wl_list_for_each(sway_layer, layer, link) {
189 struct wlr_layer_surface *layer = sway_layer->layer_surface;
190 render_surface(layer->surface, output->wlr_output, when,
191 sway_layer->geo.x + output_layout_box->x,
192 sway_layer->geo.y + output_layout_box->y, 0);
193 wlr_surface_send_frame_done(layer->surface, when);
194 }
195}
196
180static void output_frame_notify(struct wl_listener *listener, void *data) { 197static void output_frame_notify(struct wl_listener *listener, void *data) {
181 struct sway_output *soutput = wl_container_of(listener, soutput, frame); 198 struct sway_output *soutput = wl_container_of(listener, soutput, frame);
182 struct wlr_output *wlr_output = data; 199 struct wlr_output *wlr_output = data;
@@ -189,6 +206,18 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
189 wlr_output_make_current(wlr_output, &buffer_age); 206 wlr_output_make_current(wlr_output, &buffer_age);
190 wlr_renderer_begin(server->renderer, wlr_output->width, wlr_output->height); 207 wlr_renderer_begin(server->renderer, wlr_output->width, wlr_output->height);
191 208
209 struct timespec now;
210 clock_gettime(CLOCK_MONOTONIC, &now);
211
212 struct wlr_output_layout *layout = root_container.sway_root->output_layout;
213 const struct wlr_box *output_box = wlr_output_layout_get_box(
214 layout, wlr_output);
215
216 render_layer(soutput, output_box, &now,
217 &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]);
218 render_layer(soutput, output_box, &now,
219 &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]);
220
192 struct sway_seat *seat = input_manager_current_seat(input_manager); 221 struct sway_seat *seat = input_manager_current_seat(input_manager);
193 swayc_t *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); 222 swayc_t *focus = sway_seat_get_focus_inactive(seat, soutput->swayc);
194 swayc_t *workspace = (focus->type == C_WORKSPACE ? 223 swayc_t *workspace = (focus->type == C_WORKSPACE ?
@@ -210,22 +239,32 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
210 } 239 }
211 } 240 }
212 241
242 // TODO: Consider revising this when fullscreen windows are supported
243 render_layer(soutput, output_box, &now,
244 &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]);
245 render_layer(soutput, output_box, &now,
246 &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]);
247
213 wlr_renderer_end(server->renderer); 248 wlr_renderer_end(server->renderer);
214 wlr_output_swap_buffers(wlr_output, &soutput->last_frame, NULL); 249 wlr_output_swap_buffers(wlr_output, &soutput->last_frame, NULL);
215 250
216 struct timespec now;
217 clock_gettime(CLOCK_MONOTONIC, &now);
218 soutput->last_frame = now; 251 soutput->last_frame = now;
219} 252}
220 253
221static void handle_output_destroy(struct wl_listener *listener, void *data) { 254static void handle_output_destroy(struct wl_listener *listener, void *data) {
222 struct sway_output *output = wl_container_of(listener, output, output_destroy); 255 struct sway_output *output = wl_container_of(listener, output, destroy);
223 struct wlr_output *wlr_output = data; 256 struct wlr_output *wlr_output = data;
224 wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); 257 wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name);
225 258
226 destroy_output(output->swayc); 259 destroy_output(output->swayc);
227} 260}
228 261
262static void handle_output_mode(struct wl_listener *listener, void *data) {
263 struct sway_output *output = wl_container_of(listener, output, mode);
264 arrange_layers(output);
265 arrange_windows(output->swayc, -1, -1);
266}
267
229void handle_new_output(struct wl_listener *listener, void *data) { 268void handle_new_output(struct wl_listener *listener, void *data) {
230 struct sway_server *server = wl_container_of(listener, server, new_output); 269 struct sway_server *server = wl_container_of(listener, server, new_output);
231 struct wlr_output *wlr_output = data; 270 struct wlr_output *wlr_output = data;
@@ -260,9 +299,11 @@ void handle_new_output(struct wl_listener *listener, void *data) {
260 299
261 wl_signal_add(&wlr_output->events.frame, &output->frame); 300 wl_signal_add(&wlr_output->events.frame, &output->frame);
262 output->frame.notify = output_frame_notify; 301 output->frame.notify = output_frame_notify;
302 wl_signal_add(&wlr_output->events.destroy, &output->destroy);
303 output->destroy.notify = handle_output_destroy;
304 wl_signal_add(&wlr_output->events.mode, &output->mode);
305 output->mode.notify = handle_output_mode;
263 306
264 wl_signal_add(&wlr_output->events.destroy, &output->output_destroy); 307 arrange_layers(output);
265 output->output_destroy.notify = handle_output_destroy;
266
267 arrange_windows(&root_container, -1, -1); 308 arrange_windows(&root_container, -1, -1);
268} 309}
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 6b5e03f9..f9b5242b 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -84,7 +84,7 @@ static void set_activated(struct sway_view *view, bool activated) {
84 wlr_xwayland_surface_activate(surface, activated); 84 wlr_xwayland_surface_activate(surface, activated);
85} 85}
86 86
87static void close(struct sway_view *view) { 87static void close_view(struct sway_view *view) {
88 if (!assert_xwayland(view)) { 88 if (!assert_xwayland(view)) {
89 return; 89 return;
90 } 90 }
@@ -203,7 +203,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
203 sway_view->iface.set_size = set_size; 203 sway_view->iface.set_size = set_size;
204 sway_view->iface.set_position = set_position; 204 sway_view->iface.set_position = set_position;
205 sway_view->iface.set_activated = set_activated; 205 sway_view->iface.set_activated = set_activated;
206 sway_view->iface.close = close; 206 sway_view->iface.close = close_view;
207 sway_view->wlr_xwayland_surface = xsurface; 207 sway_view->wlr_xwayland_surface = xsurface;
208 sway_view->sway_xwayland_surface = sway_surface; 208 sway_view->sway_xwayland_surface = sway_surface;
209 sway_view->surface = xsurface->surface; 209 sway_view->surface = xsurface->surface;
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 705221d7..bbafe9ec 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -254,7 +254,9 @@ swayc_t *destroy_output(swayc_t *output) {
254 } 254 }
255 } 255 }
256 256
257 wl_list_remove(&output->sway_output->output_destroy.link); 257 wl_list_remove(&output->sway_output->frame.link);
258 wl_list_remove(&output->sway_output->destroy.link);
259 wl_list_remove(&output->sway_output->mode.link);
258 260
259 wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); 261 wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name);
260 free_swayc(output); 262 free_swayc(output);
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
index 3d04a1a7..de9e7b58 100644
--- a/sway/tree/layout.c
+++ b/sway/tree/layout.c
@@ -204,10 +204,13 @@ void arrange_windows(swayc_t *container, double width, double height) {
204 case C_WORKSPACE: 204 case C_WORKSPACE:
205 { 205 {
206 swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); 206 swayc_t *output = swayc_parent_by_type(container, C_OUTPUT);
207 container->width = output->width; 207 struct wlr_box *area = &output->sway_output->usable_area;
208 container->height = output->height; 208 wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d",
209 container->x = x; 209 area->width, area->height, area->x, area->y);
210 container->y = y; 210 container->width = area->width;
211 container->height = area->height;
212 container->x = x = area->x;
213 container->y = y = area->y;
211 wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", 214 wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f",
212 container->name, container->x, container->y); 215 container->name, container->x, container->y);
213 } 216 }