aboutsummaryrefslogtreecommitdiffstats
path: root/sway/desktop
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2018-03-28 19:27:52 -0400
committerLibravatar GitHub <noreply@github.com>2018-03-28 19:27:52 -0400
commitca809d25199b229b3da7d69f427eb67539dc7bc0 (patch)
treeb28c55c464feb85c61f314a26487404fd63f4fb3 /sway/desktop
parentMerge pull request #1638 from swaywm/swaybg-layers (diff)
parentAddress review feedback (diff)
downloadsway-ca809d25199b229b3da7d69f427eb67539dc7bc0.tar.gz
sway-ca809d25199b229b3da7d69f427eb67539dc7bc0.tar.zst
sway-ca809d25199b229b3da7d69f427eb67539dc7bc0.zip
Merge pull request #1642 from swaywm/layer-shell
Implement layer shell (rendering)
Diffstat (limited to 'sway/desktop')
-rw-r--r--sway/desktop/layer_shell.c320
-rw-r--r--sway/desktop/output.c95
-rw-r--r--sway/desktop/xwayland.c4
3 files changed, 394 insertions, 25 deletions
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c
new file mode 100644
index 00000000..bd62f84a
--- /dev/null
+++ b/sway/desktop/layer_shell.c
@@ -0,0 +1,320 @@
1#include <stdbool.h>
2#include <stdlib.h>
3#include <string.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>
8#include <wlr/util/log.h>
9#include "sway/layers.h"
10#include "sway/layout.h"
11#include "sway/output.h"
12#include "sway/server.h"
13
14static void apply_exclusive(struct wlr_box *usable_area,
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);
190}
191
192static void handle_output_destroy(struct wl_listener *listener, void *data) {
193 struct sway_layer_surface *sway_layer =
194 wl_container_of(listener, sway_layer, output_destroy);
195 wl_list_remove(&sway_layer->output_destroy.link);
196 wl_list_remove(&sway_layer->output_mode.link);
197 wl_list_remove(&sway_layer->output_transform.link);
198 sway_layer->layer_surface->output = NULL;
199 wlr_layer_surface_close(sway_layer->layer_surface);
200}
201
202static void handle_output_mode(struct wl_listener *listener, void *data) {
203 struct wlr_output *output = data;
204 arrange_layers((struct sway_output *)output->data);
205}
206
207static void handle_output_transform(struct wl_listener *listener, void *data) {
208 struct wlr_output *output = data;
209 arrange_layers((struct sway_output *)output->data);
210}
211
212static void handle_surface_commit(struct wl_listener *listener, void *data) {
213 struct sway_layer_surface *layer =
214 wl_container_of(listener, layer, surface_commit);
215 struct wlr_layer_surface *layer_surface = layer->layer_surface;
216 struct wlr_output *wlr_output = layer_surface->output;
217 if (wlr_output != NULL) {
218 struct sway_output *output = wlr_output->data;
219 struct wlr_box old_geo = layer->geo;
220 arrange_layers(output);
221 if (memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0) {
222 // TODO DAMAGE apply whole surface from previous and new geos
223 } else {
224 // TODO DAMAGE from surface damage
225 }
226 }
227}
228
229static void unmap(struct wlr_layer_surface *layer_surface) {
230 // TODO DAMAGE
231}
232
233static void handle_destroy(struct wl_listener *listener, void *data) {
234 struct sway_layer_surface *sway_layer = wl_container_of(
235 listener, sway_layer, destroy);
236 if (sway_layer->layer_surface->mapped) {
237 unmap(sway_layer->layer_surface);
238 }
239 wl_list_remove(&sway_layer->link);
240 wl_list_remove(&sway_layer->destroy.link);
241 wl_list_remove(&sway_layer->map.link);
242 wl_list_remove(&sway_layer->unmap.link);
243 wl_list_remove(&sway_layer->surface_commit.link);
244 if (sway_layer->layer_surface->output != NULL) {
245 wl_list_remove(&sway_layer->output_destroy.link);
246 wl_list_remove(&sway_layer->output_mode.link);
247 wl_list_remove(&sway_layer->output_transform.link);
248 }
249 struct sway_output *output = sway_layer->layer_surface->output->data;
250 arrange_layers(output);
251 free(sway_layer);
252}
253
254static void handle_map(struct wl_listener *listener, void *data) {
255 // TODO DAMAGE
256}
257
258static void handle_unmap(struct wl_listener *listener, void *data) {
259 struct sway_layer_surface *sway_layer = wl_container_of(
260 listener, sway_layer, unmap);
261 unmap(sway_layer->layer_surface);
262}
263
264void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
265 struct wlr_layer_surface *layer_surface = data;
266 struct sway_server *server =
267 wl_container_of(listener, server, layer_shell_surface);
268 wlr_log(L_DEBUG, "new layer surface: namespace %s layer %d anchor %d "
269 "size %dx%d margin %d,%d,%d,%d",
270 layer_surface->namespace, layer_surface->layer, layer_surface->layer,
271 layer_surface->client_pending.desired_width,
272 layer_surface->client_pending.desired_height,
273 layer_surface->client_pending.margin.top,
274 layer_surface->client_pending.margin.right,
275 layer_surface->client_pending.margin.bottom,
276 layer_surface->client_pending.margin.left);
277
278 struct sway_layer_surface *sway_layer =
279 calloc(1, sizeof(struct sway_layer_surface));
280 if (!sway_layer) {
281 return;
282 }
283
284 sway_layer->surface_commit.notify = handle_surface_commit;
285 wl_signal_add(&layer_surface->surface->events.commit,
286 &sway_layer->surface_commit);
287
288 sway_layer->output_destroy.notify = handle_output_destroy;
289 wl_signal_add(&layer_surface->output->events.destroy,
290 &sway_layer->output_destroy);
291
292 sway_layer->output_mode.notify = handle_output_mode;
293 wl_signal_add(&layer_surface->output->events.mode,
294 &sway_layer->output_mode);
295
296 sway_layer->output_transform.notify = handle_output_transform;
297 wl_signal_add(&layer_surface->output->events.transform,
298 &sway_layer->output_transform);
299
300 sway_layer->destroy.notify = handle_destroy;
301 wl_signal_add(&layer_surface->events.destroy, &sway_layer->destroy);
302 sway_layer->map.notify = handle_map;
303 wl_signal_add(&layer_surface->events.map, &sway_layer->map);
304 sway_layer->unmap.notify = handle_unmap;
305 wl_signal_add(&layer_surface->events.unmap, &sway_layer->unmap);
306 // TODO: Listen for subsurfaces
307
308 sway_layer->layer_surface = layer_surface;
309 layer_surface->data = sway_layer;
310
311 struct sway_output *output = layer_surface->output->data;
312 wl_list_insert(&output->layers[layer_surface->layer], &sway_layer->link);
313
314 // Temporarily set the layer's current state to client_pending
315 // So that we can easily arrange it
316 struct wlr_layer_surface_state old_state = layer_surface->current;
317 layer_surface->current = layer_surface->client_pending;
318 arrange_layers(output);
319 layer_surface->current = old_state;
320}
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 6c990c47..9e7fbcc6 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"
@@ -78,9 +81,7 @@ static void render_surface(struct wlr_surface *surface,
78 rotate_child_position(&sx, &sy, sw, sh, width, height, rotation); 81 rotate_child_position(&sx, &sy, sw, sh, width, height, rotation);
79 82
80 render_surface(subsurface->surface, wlr_output, when, 83 render_surface(subsurface->surface, wlr_output, when,
81 lx + sx, 84 lx + sx, ly + sy, rotation);
82 ly + sy,
83 rotation);
84 } 85 }
85} 86}
86 87
@@ -139,9 +140,15 @@ static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface,
139 } 140 }
140} 141}
141 142
143struct render_data {
144 struct sway_output *output;
145 struct timespec *now;
146};
142 147
143static void output_frame_view(swayc_t *view, void *data) { 148static void output_frame_view(swayc_t *view, void *data) {
144 struct sway_output *output = data; 149 struct render_data *rdata = data;
150 struct sway_output *output = rdata->output;
151 struct timespec *now = rdata->now;
145 struct wlr_output *wlr_output = output->wlr_output; 152 struct wlr_output *wlr_output = output->wlr_output;
146 struct sway_view *sway_view = view->sway_view; 153 struct sway_view *sway_view = view->sway_view;
147 struct wlr_surface *surface = sway_view->surface; 154 struct wlr_surface *surface = sway_view->surface;
@@ -154,29 +161,38 @@ static void output_frame_view(swayc_t *view, void *data) {
154 case SWAY_XDG_SHELL_V6_VIEW: { 161 case SWAY_XDG_SHELL_V6_VIEW: {
155 int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x; 162 int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x;
156 int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y; 163 int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y;
157 render_surface(surface, wlr_output, &output->last_frame, 164 render_surface(surface, wlr_output, now,
158 view->x - window_offset_x, 165 view->x - window_offset_x, view->y - window_offset_y, 0);
159 view->y - window_offset_y,
160 0);
161 render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, 166 render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output,
162 &output->last_frame, 167 now, view->x - window_offset_x, view->y - window_offset_y, 0);
163 view->x - window_offset_x, view->y - window_offset_y,
164 0);
165 break; 168 break;
166 } 169 }
167 case SWAY_WL_SHELL_VIEW: 170 case SWAY_WL_SHELL_VIEW:
168 render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output, 171 render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output,
169 &output->last_frame, view->x, view->y, 0, false); 172 now, view->x, view->y, 0, false);
170 break; 173 break;
171 case SWAY_XWAYLAND_VIEW: 174 case SWAY_XWAYLAND_VIEW:
172 render_surface(surface, wlr_output, &output->last_frame, view->x, 175 render_surface(surface, wlr_output, now, view->x, view->y, 0);
173 view->y, 0);
174 break; 176 break;
175 default: 177 default:
176 break; 178 break;
177 } 179 }
178} 180}
179 181
182static void render_layer(struct sway_output *output,
183 const struct wlr_box *output_layout_box,
184 struct timespec *when,
185 struct wl_list *layer) {
186 struct sway_layer_surface *sway_layer;
187 wl_list_for_each(sway_layer, layer, link) {
188 struct wlr_layer_surface *layer = sway_layer->layer_surface;
189 render_surface(layer->surface, output->wlr_output, when,
190 sway_layer->geo.x + output_layout_box->x,
191 sway_layer->geo.y + output_layout_box->y, 0);
192 wlr_surface_send_frame_done(layer->surface, when);
193 }
194}
195
180static void output_frame_notify(struct wl_listener *listener, void *data) { 196static void output_frame_notify(struct wl_listener *listener, void *data) {
181 struct sway_output *soutput = wl_container_of(listener, soutput, frame); 197 struct sway_output *soutput = wl_container_of(listener, soutput, frame);
182 struct wlr_output *wlr_output = data; 198 struct wlr_output *wlr_output = data;
@@ -189,13 +205,29 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
189 wlr_output_make_current(wlr_output, &buffer_age); 205 wlr_output_make_current(wlr_output, &buffer_age);
190 wlr_renderer_begin(server->renderer, wlr_output->width, wlr_output->height); 206 wlr_renderer_begin(server->renderer, wlr_output->width, wlr_output->height);
191 207
208 struct timespec now;
209 clock_gettime(CLOCK_MONOTONIC, &now);
210
211 struct wlr_output_layout *layout = root_container.sway_root->output_layout;
212 const struct wlr_box *output_box = wlr_output_layout_get_box(
213 layout, wlr_output);
214
215 render_layer(soutput, output_box, &now,
216 &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]);
217 render_layer(soutput, output_box, &now,
218 &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]);
219
192 struct sway_seat *seat = input_manager_current_seat(input_manager); 220 struct sway_seat *seat = input_manager_current_seat(input_manager);
193 swayc_t *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); 221 swayc_t *focus = sway_seat_get_focus_inactive(seat, soutput->swayc);
194 swayc_t *workspace = (focus->type == C_WORKSPACE ? 222 swayc_t *workspace = (focus->type == C_WORKSPACE ?
195 focus : 223 focus :
196 swayc_parent_by_type(focus, C_WORKSPACE)); 224 swayc_parent_by_type(focus, C_WORKSPACE));
197 225
198 swayc_descendants_of_type(workspace, C_VIEW, output_frame_view, soutput); 226 struct render_data rdata = {
227 .output = soutput,
228 .now = &now,
229 };
230 swayc_descendants_of_type(workspace, C_VIEW, output_frame_view, &rdata);
199 231
200 // render unmanaged views on top 232 // render unmanaged views on top
201 struct sway_view *view; 233 struct sway_view *view;
@@ -210,22 +242,31 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
210 } 242 }
211 } 243 }
212 244
213 wlr_renderer_end(server->renderer); 245 // TODO: Consider revising this when fullscreen windows are supported
214 wlr_output_swap_buffers(wlr_output, &soutput->last_frame, NULL); 246 render_layer(soutput, output_box, &now,
247 &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]);
248 render_layer(soutput, output_box, &now,
249 &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]);
215 250
216 struct timespec now; 251 wlr_renderer_end(server->renderer);
217 clock_gettime(CLOCK_MONOTONIC, &now); 252 wlr_output_swap_buffers(wlr_output, &now, NULL);
218 soutput->last_frame = now; 253 soutput->last_frame = now;
219} 254}
220 255
221static void handle_output_destroy(struct wl_listener *listener, void *data) { 256static void handle_output_destroy(struct wl_listener *listener, void *data) {
222 struct sway_output *output = wl_container_of(listener, output, output_destroy); 257 struct sway_output *output = wl_container_of(listener, output, destroy);
223 struct wlr_output *wlr_output = data; 258 struct wlr_output *wlr_output = data;
224 wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); 259 wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name);
225 260
226 destroy_output(output->swayc); 261 destroy_output(output->swayc);
227} 262}
228 263
264static void handle_output_mode(struct wl_listener *listener, void *data) {
265 struct sway_output *output = wl_container_of(listener, output, mode);
266 arrange_layers(output);
267 arrange_windows(output->swayc, -1, -1);
268}
269
229void handle_new_output(struct wl_listener *listener, void *data) { 270void handle_new_output(struct wl_listener *listener, void *data) {
230 struct sway_server *server = wl_container_of(listener, server, new_output); 271 struct sway_server *server = wl_container_of(listener, server, new_output);
231 struct wlr_output *wlr_output = data; 272 struct wlr_output *wlr_output = data;
@@ -236,6 +277,7 @@ void handle_new_output(struct wl_listener *listener, void *data) {
236 return; 277 return;
237 } 278 }
238 output->wlr_output = wlr_output; 279 output->wlr_output = wlr_output;
280 wlr_output->data = output;
239 output->server = server; 281 output->server = server;
240 282
241 if (!wl_list_empty(&wlr_output->modes)) { 283 if (!wl_list_empty(&wlr_output->modes)) {
@@ -250,13 +292,20 @@ void handle_new_output(struct wl_listener *listener, void *data) {
250 return; 292 return;
251 } 293 }
252 294
295 size_t len = sizeof(output->layers) / sizeof(output->layers[0]);
296 for (size_t i = 0; i < len; ++i) {
297 wl_list_init(&output->layers[i]);
298 }
299
253 sway_input_manager_configure_xcursor(input_manager); 300 sway_input_manager_configure_xcursor(input_manager);
254 301
255 wl_signal_add(&wlr_output->events.frame, &output->frame); 302 wl_signal_add(&wlr_output->events.frame, &output->frame);
256 output->frame.notify = output_frame_notify; 303 output->frame.notify = output_frame_notify;
304 wl_signal_add(&wlr_output->events.destroy, &output->destroy);
305 output->destroy.notify = handle_output_destroy;
306 wl_signal_add(&wlr_output->events.mode, &output->mode);
307 output->mode.notify = handle_output_mode;
257 308
258 wl_signal_add(&wlr_output->events.destroy, &output->output_destroy); 309 arrange_layers(output);
259 output->output_destroy.notify = handle_output_destroy;
260
261 arrange_windows(&root_container, -1, -1); 310 arrange_windows(&root_container, -1, -1);
262} 311}
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;