summaryrefslogtreecommitdiffstats
path: root/sway/desktop/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r--sway/desktop/output.c339
1 files changed, 181 insertions, 158 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index a9808406..66747a3f 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -14,6 +14,7 @@
14#include <wlr/types/wlr_surface.h> 14#include <wlr/types/wlr_surface.h>
15#include <wlr/util/region.h> 15#include <wlr/util/region.h>
16#include "log.h" 16#include "log.h"
17#include "config.h"
17#include "sway/config.h" 18#include "sway/config.h"
18#include "sway/input/input-manager.h" 19#include "sway/input/input-manager.h"
19#include "sway/input/seat.h" 20#include "sway/input/seat.h"
@@ -56,9 +57,21 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh,
56 *sy = ry + ph/2 - sh/2; 57 *sy = ry + ph/2 - sh/2;
57} 58}
58 59
59bool output_get_surface_box(struct root_geometry *geo, 60struct surface_iterator_data {
60 struct sway_output *output, struct wlr_surface *surface, int sx, int sy, 61 sway_surface_iterator_func_t user_iterator;
62 void *user_data;
63
64 struct sway_output *output;
65 double ox, oy;
66 int width, height;
67 float rotation;
68};
69
70static bool get_surface_box(struct surface_iterator_data *data,
71 struct wlr_surface *surface, int sx, int sy,
61 struct wlr_box *surface_box) { 72 struct wlr_box *surface_box) {
73 struct sway_output *output = data->output;
74
62 if (!wlr_surface_has_buffer(surface)) { 75 if (!wlr_surface_has_buffer(surface)) {
63 return false; 76 return false;
64 } 77 }
@@ -67,12 +80,12 @@ bool output_get_surface_box(struct root_geometry *geo,
67 int sh = surface->current.height; 80 int sh = surface->current.height;
68 81
69 double _sx = sx, _sy = sy; 82 double _sx = sx, _sy = sy;
70 rotate_child_position(&_sx, &_sy, sw, sh, geo->width, geo->height, 83 rotate_child_position(&_sx, &_sy, sw, sh, data->width, data->height,
71 geo->rotation); 84 data->rotation);
72 85
73 struct wlr_box box = { 86 struct wlr_box box = {
74 .x = geo->x + _sx, 87 .x = data->ox + _sx,
75 .y = geo->y + _sy, 88 .y = data->oy + _sy,
76 .width = sw, 89 .width = sw,
77 .height = sh, 90 .height = sh,
78 }; 91 };
@@ -81,7 +94,7 @@ bool output_get_surface_box(struct root_geometry *geo,
81 } 94 }
82 95
83 struct wlr_box rotated_box; 96 struct wlr_box rotated_box;
84 wlr_box_rotated_bounds(&box, geo->rotation, &rotated_box); 97 wlr_box_rotated_bounds(&box, data->rotation, &rotated_box);
85 98
86 struct wlr_box output_box = { 99 struct wlr_box output_box = {
87 .width = output->swayc->current.swayc_width, 100 .width = output->swayc->current.swayc_width,
@@ -92,46 +105,90 @@ bool output_get_surface_box(struct root_geometry *geo,
92 return wlr_box_intersection(&output_box, &rotated_box, &intersection); 105 return wlr_box_intersection(&output_box, &rotated_box, &intersection);
93} 106}
94 107
95void output_surface_for_each_surface(struct wlr_surface *surface, 108static void output_for_each_surface_iterator(struct wlr_surface *surface,
96 double ox, double oy, struct root_geometry *geo, 109 int sx, int sy, void *_data) {
97 wlr_surface_iterator_func_t iterator, void *user_data) { 110 struct surface_iterator_data *data = _data;
98 geo->x = ox;
99 geo->y = oy;
100 geo->width = surface->current.width;
101 geo->height = surface->current.height;
102 geo->rotation = 0;
103 111
104 wlr_surface_for_each_surface(surface, iterator, user_data); 112 struct wlr_box box;
113 bool intersects = get_surface_box(data, surface, sx, sy, &box);
114 if (!intersects) {
115 return;
116 }
117
118 data->user_iterator(data->output, surface, &box, data->rotation,
119 data->user_data);
120}
121
122void output_surface_for_each_surface(struct sway_output *output,
123 struct wlr_surface *surface, double ox, double oy,
124 sway_surface_iterator_func_t iterator, void *user_data) {
125 struct surface_iterator_data data = {
126 .user_iterator = iterator,
127 .user_data = user_data,
128 .output = output,
129 .ox = ox,
130 .oy = oy,
131 .width = surface->current.width,
132 .height = surface->current.height,
133 .rotation = 0,
134 };
135
136 wlr_surface_for_each_surface(surface,
137 output_for_each_surface_iterator, &data);
105} 138}
106 139
107void output_view_for_each_surface(struct sway_view *view, 140void output_view_for_each_surface(struct sway_output *output,
108 struct sway_output *output, struct root_geometry *geo, 141 struct sway_view *view, sway_surface_iterator_func_t iterator,
109 wlr_surface_iterator_func_t iterator, void *user_data) { 142 void *user_data) {
110 geo->x = view->swayc->current.view_x - output->swayc->current.swayc_x; 143 struct surface_iterator_data data = {
111 geo->y = view->swayc->current.view_y - output->swayc->current.swayc_y; 144 .user_iterator = iterator,
112 geo->width = view->swayc->current.view_width; 145 .user_data = user_data,
113 geo->height = view->swayc->current.view_height; 146 .output = output,
114 geo->rotation = 0; // TODO 147 .ox = view->swayc->current.view_x - output->swayc->current.swayc_x,
148 .oy = view->swayc->current.view_y - output->swayc->current.swayc_y,
149 .width = view->swayc->current.view_width,
150 .height = view->swayc->current.view_height,
151 .rotation = 0, // TODO
152 };
115 153
116 view_for_each_surface(view, iterator, user_data); 154 view_for_each_surface(view,
155 output_for_each_surface_iterator, &data);
117} 156}
118 157
119void output_layer_for_each_surface(struct wl_list *layer_surfaces, 158void output_view_for_each_popup(struct sway_output *output,
120 struct root_geometry *geo, wlr_surface_iterator_func_t iterator, 159 struct sway_view *view, sway_surface_iterator_func_t iterator,
160 void *user_data) {
161 struct surface_iterator_data data = {
162 .user_iterator = iterator,
163 .user_data = user_data,
164 .output = output,
165 .ox = view->swayc->current.view_x - output->swayc->current.swayc_x,
166 .oy = view->swayc->current.view_y - output->swayc->current.swayc_y,
167 .width = view->swayc->current.view_width,
168 .height = view->swayc->current.view_height,
169 .rotation = 0, // TODO
170 };
171
172 view_for_each_popup(view, output_for_each_surface_iterator, &data);
173}
174
175void output_layer_for_each_surface(struct sway_output *output,
176 struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator,
121 void *user_data) { 177 void *user_data) {
122 struct sway_layer_surface *layer_surface; 178 struct sway_layer_surface *layer_surface;
123 wl_list_for_each(layer_surface, layer_surfaces, link) { 179 wl_list_for_each(layer_surface, layer_surfaces, link) {
124 struct wlr_layer_surface *wlr_layer_surface = 180 struct wlr_layer_surface *wlr_layer_surface =
125 layer_surface->layer_surface; 181 layer_surface->layer_surface;
126 output_surface_for_each_surface(wlr_layer_surface->surface, 182 output_surface_for_each_surface(output, wlr_layer_surface->surface,
127 layer_surface->geo.x, layer_surface->geo.y, geo, iterator, 183 layer_surface->geo.x, layer_surface->geo.y, iterator,
128 user_data); 184 user_data);
129 } 185 }
130} 186}
131 187
132void output_unmanaged_for_each_surface(struct wl_list *unmanaged, 188#ifdef HAVE_XWAYLAND
133 struct sway_output *output, struct root_geometry *geo, 189void output_unmanaged_for_each_surface(struct sway_output *output,
134 wlr_surface_iterator_func_t iterator, void *user_data) { 190 struct wl_list *unmanaged, sway_surface_iterator_func_t iterator,
191 void *user_data) {
135 struct sway_xwayland_unmanaged *unmanaged_surface; 192 struct sway_xwayland_unmanaged *unmanaged_surface;
136 wl_list_for_each(unmanaged_surface, unmanaged, link) { 193 wl_list_for_each(unmanaged_surface, unmanaged, link) {
137 struct wlr_xwayland_surface *xsurface = 194 struct wlr_xwayland_surface *xsurface =
@@ -139,22 +196,24 @@ void output_unmanaged_for_each_surface(struct wl_list *unmanaged,
139 double ox = unmanaged_surface->lx - output->swayc->current.swayc_x; 196 double ox = unmanaged_surface->lx - output->swayc->current.swayc_x;
140 double oy = unmanaged_surface->ly - output->swayc->current.swayc_y; 197 double oy = unmanaged_surface->ly - output->swayc->current.swayc_y;
141 198
142 output_surface_for_each_surface(xsurface->surface, ox, oy, geo, 199 output_surface_for_each_surface(output, xsurface->surface, ox, oy,
143 iterator, user_data); 200 iterator, user_data);
144 } 201 }
145} 202}
203#endif
146 204
147void output_drag_icons_for_each_surface(struct wl_list *drag_icons, 205void output_drag_icons_for_each_surface(struct sway_output *output,
148 struct sway_output *output, struct root_geometry *geo, 206 struct wl_list *drag_icons, sway_surface_iterator_func_t iterator,
149 wlr_surface_iterator_func_t iterator, void *user_data) { 207 void *user_data) {
150 struct sway_drag_icon *drag_icon; 208 struct sway_drag_icon *drag_icon;
151 wl_list_for_each(drag_icon, drag_icons, link) { 209 wl_list_for_each(drag_icon, drag_icons, link) {
152 double ox = drag_icon->x - output->swayc->x; 210 double ox = drag_icon->x - output->swayc->x;
153 double oy = drag_icon->y - output->swayc->y; 211 double oy = drag_icon->y - output->swayc->y;
154 212
155 if (drag_icon->wlr_drag_icon->mapped) { 213 if (drag_icon->wlr_drag_icon->mapped) {
156 output_surface_for_each_surface(drag_icon->wlr_drag_icon->surface, 214 output_surface_for_each_surface(output,
157 ox, oy, geo, iterator, user_data); 215 drag_icon->wlr_drag_icon->surface, ox, oy,
216 iterator, user_data);
158 } 217 }
159 } 218 }
160} 219}
@@ -181,21 +240,14 @@ struct sway_container *output_get_active_workspace(struct sway_output *output) {
181 return workspace; 240 return workspace;
182} 241}
183 242
184bool output_has_opaque_lockscreen(struct sway_output *output, 243bool output_has_opaque_overlay_layer_surface(struct sway_output *output) {
185 struct sway_seat *seat) {
186 if (!seat->exclusive_client) {
187 return false;
188 }
189
190 struct wlr_layer_surface *wlr_layer_surface; 244 struct wlr_layer_surface *wlr_layer_surface;
191 wl_list_for_each(wlr_layer_surface, &server.layer_shell->surfaces, link) { 245 wl_list_for_each(wlr_layer_surface, &server.layer_shell->surfaces, link) {
192 if (wlr_layer_surface->output != output->wlr_output) { 246 if (wlr_layer_surface->output != output->wlr_output ||
247 wlr_layer_surface->layer != ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY) {
193 continue; 248 continue;
194 } 249 }
195 struct wlr_surface *wlr_surface = wlr_layer_surface->surface; 250 struct wlr_surface *wlr_surface = wlr_layer_surface->surface;
196 if (wlr_surface->resource->client != seat->exclusive_client) {
197 continue;
198 }
199 struct sway_layer_surface *sway_layer_surface = 251 struct sway_layer_surface *sway_layer_surface =
200 layer_from_wlr_layer_surface(wlr_layer_surface); 252 layer_from_wlr_layer_surface(wlr_layer_surface);
201 pixman_box32_t output_box = { 253 pixman_box32_t output_box = {
@@ -217,46 +269,38 @@ bool output_has_opaque_lockscreen(struct sway_output *output,
217 return false; 269 return false;
218} 270}
219 271
220struct send_frame_done_data { 272static void send_frame_done_iterator(struct sway_output *output,
221 struct root_geometry root_geo; 273 struct wlr_surface *surface, struct wlr_box *box, float rotation,
222 struct sway_output *output; 274 void *_data) {
223 struct timespec *when; 275 struct timespec *when = _data;
224 struct wl_client *exclusive_client; 276 wlr_surface_send_frame_done(surface, when);
225};
226
227static void send_frame_done_iterator(struct wlr_surface *surface,
228 int sx, int sy, void *_data) {
229 struct send_frame_done_data *data = _data;
230 if (data->exclusive_client &&
231 data->exclusive_client != surface->resource->client) {
232 return;
233 }
234
235 bool intersects = output_get_surface_box(&data->root_geo, data->output, surface,
236 sx, sy, NULL);
237 if (intersects) {
238 wlr_surface_send_frame_done(surface, data->when);
239 }
240} 277}
241 278
242static void send_frame_done_layer(struct send_frame_done_data *data, 279static void send_frame_done_layer(struct sway_output *output,
243 struct wl_list *layer_surfaces) { 280 struct wl_list *layer_surfaces, struct timespec *when) {
244 output_layer_for_each_surface(layer_surfaces, &data->root_geo, 281 output_layer_for_each_surface(output, layer_surfaces,
245 send_frame_done_iterator, data); 282 send_frame_done_iterator, when);
246} 283}
247 284
248static void send_frame_done_unmanaged(struct send_frame_done_data *data, 285#ifdef HAVE_XWAYLAND
249 struct wl_list *unmanaged) { 286static void send_frame_done_unmanaged(struct sway_output *output,
250 output_unmanaged_for_each_surface(unmanaged, data->output, &data->root_geo, 287 struct wl_list *unmanaged, struct timespec *when) {
251 send_frame_done_iterator, data); 288 output_unmanaged_for_each_surface(output, unmanaged,
289 send_frame_done_iterator, when);
252} 290}
291#endif
253 292
254static void send_frame_done_drag_icons(struct send_frame_done_data *data, 293static void send_frame_done_drag_icons(struct sway_output *output,
255 struct wl_list *drag_icons) { 294 struct wl_list *drag_icons, struct timespec *when) {
256 output_drag_icons_for_each_surface(drag_icons, data->output, &data->root_geo, 295 output_drag_icons_for_each_surface(output, drag_icons,
257 send_frame_done_iterator, data); 296 send_frame_done_iterator, when);
258} 297}
259 298
299struct send_frame_done_data {
300 struct sway_output *output;
301 struct timespec *when;
302};
303
260static void send_frame_done_container_iterator(struct sway_container *con, 304static void send_frame_done_container_iterator(struct sway_container *con,
261 void *_data) { 305 void *_data) {
262 struct send_frame_done_data *data = _data; 306 struct send_frame_done_data *data = _data;
@@ -268,52 +312,62 @@ static void send_frame_done_container_iterator(struct sway_container *con,
268 return; 312 return;
269 } 313 }
270 314
271 output_view_for_each_surface(con->sway_view, data->output, &data->root_geo, 315 output_view_for_each_surface(data->output, con->sway_view,
272 send_frame_done_iterator, data); 316 send_frame_done_iterator, data->when);
273}
274
275static void send_frame_done_container(struct send_frame_done_data *data,
276 struct sway_container *con) {
277 container_descendants(con, C_VIEW,
278 send_frame_done_container_iterator, data);
279} 317}
280 318
281static void send_frame_done(struct sway_output *output, struct timespec *when) { 319static void send_frame_done_container(struct sway_output *output,
282 struct sway_seat *seat = input_manager_current_seat(input_manager); 320 struct sway_container *con, struct timespec *when) {
283 struct send_frame_done_data data = { 321 struct send_frame_done_data data = {
284 .output = output, 322 .output = output,
285 .when = when, 323 .when = when,
286 .exclusive_client = output_has_opaque_lockscreen(output, seat) ?
287 seat->exclusive_client : NULL,
288 }; 324 };
325 container_descendants(con, C_VIEW,
326 send_frame_done_container_iterator, &data);
327}
328
329static void send_frame_done(struct sway_output *output, struct timespec *when) {
330 if (output_has_opaque_overlay_layer_surface(output)) {
331 goto send_frame_overlay;
332 }
289 333
290 struct sway_container *workspace = output_get_active_workspace(output); 334 struct sway_container *workspace = output_get_active_workspace(output);
291 if (workspace->current.ws_fullscreen) { 335 if (workspace->current.ws_fullscreen) {
292 send_frame_done_container_iterator( 336 if (workspace->current.ws_fullscreen->type == C_VIEW) {
293 workspace->current.ws_fullscreen->swayc, &data); 337 output_view_for_each_surface(output,
294 338 workspace->current.ws_fullscreen->sway_view,
295 if (workspace->current.ws_fullscreen->type == SWAY_VIEW_XWAYLAND) { 339 send_frame_done_iterator, when);
296 send_frame_done_unmanaged(&data, 340 } else {
297 &root_container.sway_root->xwayland_unmanaged); 341 send_frame_done_container(output, workspace->current.ws_fullscreen,
342 when);
298 } 343 }
344#ifdef HAVE_XWAYLAND
345 send_frame_done_unmanaged(output,
346 &root_container.sway_root->xwayland_unmanaged, when);
347#endif
299 } else { 348 } else {
300 send_frame_done_layer(&data, 349 send_frame_done_layer(output,
301 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); 350 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], when);
302 send_frame_done_layer(&data, 351 send_frame_done_layer(output,
303 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); 352 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], when);
304 353
305 send_frame_done_container(&data, workspace); 354 send_frame_done_container(output, workspace, when);
306 send_frame_done_container(&data, workspace->sway_workspace->floating); 355 send_frame_done_container(output, workspace->sway_workspace->floating,
307 356 when);
308 send_frame_done_unmanaged(&data, 357
309 &root_container.sway_root->xwayland_unmanaged); 358#ifdef HAVE_XWAYLAND
310 send_frame_done_layer(&data, 359 send_frame_done_unmanaged(output,
311 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); 360 &root_container.sway_root->xwayland_unmanaged, when);
361#endif
362 send_frame_done_layer(output,
363 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], when);
312 } 364 }
313 365
314 send_frame_done_layer(&data, 366send_frame_overlay:
315 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); 367 send_frame_done_layer(output,
316 send_frame_done_drag_icons(&data, &root_container.sway_root->drag_icons); 368 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], when);
369 send_frame_done_drag_icons(output, &root_container.sway_root->drag_icons,
370 when);
317} 371}
318 372
319static void damage_handle_frame(struct wl_listener *listener, void *data) { 373static void damage_handle_frame(struct wl_listener *listener, void *data) {
@@ -348,26 +402,13 @@ void output_damage_whole(struct sway_output *output) {
348 wlr_output_damage_add_whole(output->damage); 402 wlr_output_damage_add_whole(output->damage);
349} 403}
350 404
351struct damage_data { 405static void damage_surface_iterator(struct sway_output *output,
352 struct root_geometry root_geo; 406 struct wlr_surface *surface, struct wlr_box *_box, float rotation,
353 struct sway_output *output;
354 bool whole;
355};
356
357static void damage_surface_iterator(struct wlr_surface *surface, int sx, int sy,
358 void *_data) { 407 void *_data) {
359 struct damage_data *data = _data; 408 bool *data = _data;
360 struct sway_output *output = data->output; 409 bool whole = *data;
361 float rotation = data->root_geo.rotation;
362 bool whole = data->whole;
363
364 struct wlr_box box;
365 bool intersects = output_get_surface_box(&data->root_geo, data->output, surface,
366 sx, sy, &box);
367 if (!intersects) {
368 return;
369 }
370 410
411 struct wlr_box box = *_box;
371 scale_box(&box, output->wlr_output->scale); 412 scale_box(&box, output->wlr_output->scale);
372 413
373 int center_x = box.x + box.width/2; 414 int center_x = box.x + box.width/2;
@@ -407,13 +448,8 @@ static void damage_surface_iterator(struct wlr_surface *surface, int sx, int sy,
407 448
408void output_damage_surface(struct sway_output *output, double ox, double oy, 449void output_damage_surface(struct sway_output *output, double ox, double oy,
409 struct wlr_surface *surface, bool whole) { 450 struct wlr_surface *surface, bool whole) {
410 struct damage_data data = { 451 output_surface_for_each_surface(output, surface, ox, oy,
411 .output = output, 452 damage_surface_iterator, &whole);
412 .whole = whole,
413 };
414
415 output_surface_for_each_surface(surface, ox, oy, &data.root_geo,
416 damage_surface_iterator, &data);
417} 453}
418 454
419static void output_damage_view(struct sway_output *output, 455static void output_damage_view(struct sway_output *output,
@@ -426,13 +462,7 @@ static void output_damage_view(struct sway_output *output,
426 return; 462 return;
427 } 463 }
428 464
429 struct damage_data data = { 465 output_view_for_each_surface(output, view, damage_surface_iterator, &whole);
430 .output = output,
431 .whole = whole,
432 };
433
434 output_view_for_each_surface(view, output, &data.root_geo,
435 damage_surface_iterator, &data);
436} 466}
437 467
438void output_damage_from_view(struct sway_output *output, 468void output_damage_from_view(struct sway_output *output,
@@ -463,11 +493,12 @@ static void output_damage_whole_container_iterator(struct sway_container *con,
463 493
464void output_damage_whole_container(struct sway_output *output, 494void output_damage_whole_container(struct sway_output *output,
465 struct sway_container *con) { 495 struct sway_container *con) {
496 // Pad the box by 1px, because the width is a double and might be a fraction
466 struct wlr_box box = { 497 struct wlr_box box = {
467 .x = con->current.swayc_x - output->wlr_output->lx, 498 .x = con->current.swayc_x - output->wlr_output->lx - 1,
468 .y = con->current.swayc_y - output->wlr_output->ly, 499 .y = con->current.swayc_y - output->wlr_output->ly - 1,
469 .width = con->current.swayc_width, 500 .width = con->current.swayc_width + 2,
470 .height = con->current.swayc_height, 501 .height = con->current.swayc_height + 2,
471 }; 502 };
472 scale_box(&box, output->wlr_output->scale); 503 scale_box(&box, output->wlr_output->scale);
473 wlr_output_damage_add_box(output->damage, &box); 504 wlr_output_damage_add_box(output->damage, &box);
@@ -509,22 +540,14 @@ static void handle_transform(struct wl_listener *listener, void *data) {
509 transaction_commit_dirty(); 540 transaction_commit_dirty();
510} 541}
511 542
512static void handle_scale_iterator(struct sway_container *view, void *data) {
513 view_update_marks_textures(view->sway_view);
514}
515
516static void handle_scale(struct wl_listener *listener, void *data) { 543static void handle_scale(struct wl_listener *listener, void *data) {
517 struct sway_output *output = wl_container_of(listener, output, scale); 544 struct sway_output *output = wl_container_of(listener, output, scale);
518 arrange_layers(output); 545 arrange_layers(output);
519 container_descendants(output->swayc, C_VIEW, handle_scale_iterator, NULL); 546 container_update_textures_recursive(output->swayc);
520 arrange_windows(output->swayc); 547 arrange_windows(output->swayc);
521 transaction_commit_dirty(); 548 transaction_commit_dirty();
522} 549}
523 550
524struct sway_output *output_from_wlr_output(struct wlr_output *wlr_output) {
525 return wlr_output->data;
526}
527
528void handle_new_output(struct wl_listener *listener, void *data) { 551void handle_new_output(struct wl_listener *listener, void *data) {
529 struct sway_server *server = wl_container_of(listener, server, new_output); 552 struct sway_server *server = wl_container_of(listener, server, new_output);
530 struct wlr_output *wlr_output = data; 553 struct wlr_output *wlr_output = data;