aboutsummaryrefslogtreecommitdiffstats
path: root/sway/desktop/output.c
diff options
context:
space:
mode:
authorLibravatar emersion <contact@emersion.fr>2018-07-27 19:16:36 +0100
committerLibravatar emersion <contact@emersion.fr>2018-07-29 14:33:26 +0100
commit8d5cc8625ce04c657eab6bd5f242a02e97ddd647 (patch)
treecf6ce6cf223a508361139b223fe72d4fe2c79065 /sway/desktop/output.c
parentwip: redesign output_view_for_each_surface iterator (diff)
downloadsway-8d5cc8625ce04c657eab6bd5f242a02e97ddd647.tar.gz
sway-8d5cc8625ce04c657eab6bd5f242a02e97ddd647.tar.zst
sway-8d5cc8625ce04c657eab6bd5f242a02e97ddd647.zip
Completely switch over to new iterators
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r--sway/desktop/output.c243
1 files changed, 74 insertions, 169 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 31033ee3..e1d85b10 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -57,9 +57,21 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh,
57 *sy = ry + ph/2 - sh/2; 57 *sy = ry + ph/2 - sh/2;
58} 58}
59 59
60bool output_get_surface_box(struct root_geometry *geo, 60struct surface_iterator_data {
61 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,
62 struct wlr_box *surface_box) { 72 struct wlr_box *surface_box) {
73 struct sway_output *output = data->output;
74
63 if (!wlr_surface_has_buffer(surface)) { 75 if (!wlr_surface_has_buffer(surface)) {
64 return false; 76 return false;
65 } 77 }
@@ -68,12 +80,12 @@ bool output_get_surface_box(struct root_geometry *geo,
68 int sh = surface->current.height; 80 int sh = surface->current.height;
69 81
70 double _sx = sx, _sy = sy; 82 double _sx = sx, _sy = sy;
71 rotate_child_position(&_sx, &_sy, sw, sh, geo->width, geo->height, 83 rotate_child_position(&_sx, &_sy, sw, sh, data->width, data->height,
72 geo->rotation); 84 data->rotation);
73 85
74 struct wlr_box box = { 86 struct wlr_box box = {
75 .x = geo->x + _sx, 87 .x = data->ox + _sx,
76 .y = geo->y + _sy, 88 .y = data->oy + _sy,
77 .width = sw, 89 .width = sw,
78 .height = sh, 90 .height = sh,
79 }; 91 };
@@ -82,7 +94,7 @@ bool output_get_surface_box(struct root_geometry *geo,
82 } 94 }
83 95
84 struct wlr_box rotated_box; 96 struct wlr_box rotated_box;
85 wlr_box_rotated_bounds(&box, geo->rotation, &rotated_box); 97 wlr_box_rotated_bounds(&box, data->rotation, &rotated_box);
86 98
87 struct wlr_box output_box = { 99 struct wlr_box output_box = {
88 .width = output->swayc->current.swayc_width, 100 .width = output->swayc->current.swayc_width,
@@ -93,42 +105,12 @@ bool output_get_surface_box(struct root_geometry *geo,
93 return wlr_box_intersection(&output_box, &rotated_box, &intersection); 105 return wlr_box_intersection(&output_box, &rotated_box, &intersection);
94} 106}
95 107
96void output_surface_for_each_surface(struct wlr_surface *surface, 108void output_surface_for_each_surface_iterator(struct wlr_surface *surface,
97 double ox, double oy, struct root_geometry *geo,
98 wlr_surface_iterator_func_t iterator, void *user_data) {
99 geo->x = ox;
100 geo->y = oy;
101 geo->width = surface->current.width;
102 geo->height = surface->current.height;
103 geo->rotation = 0;
104
105 wlr_surface_for_each_surface(surface, iterator, user_data);
106}
107
108struct surface_iterator_data {
109 sway_surface_iterator_func_t user_iterator;
110 void *user_data;
111
112 struct sway_output *output;
113 double ox, oy;
114 int width, height;
115 float rotation;
116};
117
118void output_surface_for_each_surface2_iterator(struct wlr_surface *surface,
119 int sx, int sy, void *_data) { 109 int sx, int sy, void *_data) {
120 struct surface_iterator_data *data = _data; 110 struct surface_iterator_data *data = _data;
121 111
122 struct root_geometry geo = {
123 .x = data->ox,
124 .y = data->oy,
125 .width = data->width,
126 .height = data->height,
127 .rotation = data->rotation,
128 };
129 struct wlr_box box; 112 struct wlr_box box;
130 bool intersects = output_get_surface_box(&geo, data->output, 113 bool intersects = get_surface_box(data, surface, sx, sy, &box);
131 surface, sx, sy, &box);
132 if (!intersects) { 114 if (!intersects) {
133 return; 115 return;
134 } 116 }
@@ -137,7 +119,7 @@ void output_surface_for_each_surface2_iterator(struct wlr_surface *surface,
137 data->user_data); 119 data->user_data);
138} 120}
139 121
140void output_surface_for_each_surface2(struct sway_output *output, 122void output_surface_for_each_surface(struct sway_output *output,
141 struct wlr_surface *surface, double ox, double oy, float rotation, 123 struct wlr_surface *surface, double ox, double oy, float rotation,
142 sway_surface_iterator_func_t iterator, void *user_data) { 124 sway_surface_iterator_func_t iterator, void *user_data) {
143 struct surface_iterator_data data = { 125 struct surface_iterator_data data = {
@@ -152,7 +134,7 @@ void output_surface_for_each_surface2(struct sway_output *output,
152 }; 134 };
153 135
154 wlr_surface_for_each_surface(surface, 136 wlr_surface_for_each_surface(surface,
155 output_surface_for_each_surface2_iterator, &data); 137 output_surface_for_each_surface_iterator, &data);
156} 138}
157 139
158void output_view_for_each_surface(struct sway_output *output, 140void output_view_for_each_surface(struct sway_output *output,
@@ -170,7 +152,7 @@ void output_view_for_each_surface(struct sway_output *output,
170 }; 152 };
171 153
172 view_for_each_surface(view, 154 view_for_each_surface(view,
173 output_surface_for_each_surface2_iterator, &data); 155 output_surface_for_each_surface_iterator, &data);
174} 156}
175 157
176void output_layer_for_each_surface(struct sway_output *output, 158void output_layer_for_each_surface(struct sway_output *output,
@@ -180,7 +162,7 @@ void output_layer_for_each_surface(struct sway_output *output,
180 wl_list_for_each(layer_surface, layer_surfaces, link) { 162 wl_list_for_each(layer_surface, layer_surfaces, link) {
181 struct wlr_layer_surface *wlr_layer_surface = 163 struct wlr_layer_surface *wlr_layer_surface =
182 layer_surface->layer_surface; 164 layer_surface->layer_surface;
183 output_surface_for_each_surface2(output, wlr_layer_surface->surface, 165 output_surface_for_each_surface(output, wlr_layer_surface->surface,
184 layer_surface->geo.x, layer_surface->geo.y, 0, iterator, 166 layer_surface->geo.x, layer_surface->geo.y, 0, iterator,
185 user_data); 167 user_data);
186 } 168 }
@@ -197,7 +179,7 @@ void output_unmanaged_for_each_surface(struct sway_output *output,
197 double ox = unmanaged_surface->lx - output->swayc->current.swayc_x; 179 double ox = unmanaged_surface->lx - output->swayc->current.swayc_x;
198 double oy = unmanaged_surface->ly - output->swayc->current.swayc_y; 180 double oy = unmanaged_surface->ly - output->swayc->current.swayc_y;
199 181
200 output_surface_for_each_surface2(output, xsurface->surface, ox, oy, 0, 182 output_surface_for_each_surface(output, xsurface->surface, ox, oy, 0,
201 iterator, user_data); 183 iterator, user_data);
202 } 184 }
203} 185}
@@ -212,7 +194,7 @@ void output_drag_icons_for_each_surface(struct sway_output *output,
212 double oy = drag_icon->y - output->swayc->y; 194 double oy = drag_icon->y - output->swayc->y;
213 195
214 if (drag_icon->wlr_drag_icon->mapped) { 196 if (drag_icon->wlr_drag_icon->mapped) {
215 output_surface_for_each_surface2(output, 197 output_surface_for_each_surface(output,
216 drag_icon->wlr_drag_icon->surface, ox, oy, 0, 198 drag_icon->wlr_drag_icon->surface, ox, oy, 0,
217 iterator, user_data); 199 iterator, user_data);
218 } 200 }
@@ -270,50 +252,38 @@ bool output_has_opaque_overlay_layer_surface(struct sway_output *output) {
270 return false; 252 return false;
271} 253}
272 254
273struct send_frame_done_data { 255static void send_frame_done_iterator(struct sway_output *output,
274 struct root_geometry root_geo;
275 struct sway_output *output;
276 struct timespec *when;
277};
278
279static void send_frame_done_iterator(struct wlr_surface *surface,
280 int sx, int sy, void *_data) {
281 struct send_frame_done_data *data = _data;
282
283 bool intersects = output_get_surface_box(&data->root_geo, data->output, surface,
284 sx, sy, NULL);
285 if (intersects) {
286 wlr_surface_send_frame_done(surface, data->when);
287 }
288}
289
290static void send_frame_done_iterator2(struct sway_output *output,
291 struct wlr_surface *surface, struct wlr_box *box, float rotation, 256 struct wlr_surface *surface, struct wlr_box *box, float rotation,
292 void *_data) { 257 void *_data) {
293 struct send_frame_done_data *data = _data; 258 struct timespec *when = _data;
294 wlr_surface_send_frame_done(surface, data->when); 259 wlr_surface_send_frame_done(surface, when);
295} 260}
296 261
297static void send_frame_done_layer(struct sway_output *output, 262static void send_frame_done_layer(struct sway_output *output,
298 struct wl_list *layer_surfaces, struct send_frame_done_data *data) { 263 struct wl_list *layer_surfaces, struct timespec *when) {
299 output_layer_for_each_surface(output, layer_surfaces, 264 output_layer_for_each_surface(output, layer_surfaces,
300 send_frame_done_iterator2, data); 265 send_frame_done_iterator, when);
301} 266}
302 267
303#ifdef HAVE_XWAYLAND 268#ifdef HAVE_XWAYLAND
304static void send_frame_done_unmanaged(struct send_frame_done_data *data, 269static void send_frame_done_unmanaged(struct sway_output *output,
305 struct wl_list *unmanaged) { 270 struct wl_list *unmanaged, struct timespec *when) {
306 output_unmanaged_for_each_surface(data->output, unmanaged, 271 output_unmanaged_for_each_surface(output, unmanaged,
307 send_frame_done_iterator2, data); 272 send_frame_done_iterator, when);
308} 273}
309#endif 274#endif
310 275
311static void send_frame_done_drag_icons(struct send_frame_done_data *data, 276static void send_frame_done_drag_icons(struct sway_output *output,
312 struct wl_list *drag_icons) { 277 struct wl_list *drag_icons, struct timespec *when) {
313 output_drag_icons_for_each_surface(data->output, drag_icons, 278 output_drag_icons_for_each_surface(output, drag_icons,
314 send_frame_done_iterator2, data); 279 send_frame_done_iterator, when);
315} 280}
316 281
282struct send_frame_done_data {
283 struct sway_output *output;
284 struct timespec *when;
285};
286
317static void send_frame_done_container_iterator(struct sway_container *con, 287static void send_frame_done_container_iterator(struct sway_container *con,
318 void *_data) { 288 void *_data) {
319 struct send_frame_done_data *data = _data; 289 struct send_frame_done_data *data = _data;
@@ -326,21 +296,20 @@ static void send_frame_done_container_iterator(struct sway_container *con,
326 } 296 }
327 297
328 output_view_for_each_surface(data->output, con->sway_view, 298 output_view_for_each_surface(data->output, con->sway_view,
329 send_frame_done_iterator2, data); 299 send_frame_done_iterator, data->when);
330}
331
332static void send_frame_done_container(struct send_frame_done_data *data,
333 struct sway_container *con) {
334 container_descendants(con, C_VIEW,
335 send_frame_done_container_iterator, data);
336} 300}
337 301
338static void send_frame_done(struct sway_output *output, struct timespec *when) { 302static void send_frame_done_container(struct sway_output *output,
303 struct sway_container *con, struct timespec *when) {
339 struct send_frame_done_data data = { 304 struct send_frame_done_data data = {
340 .output = output, 305 .output = output,
341 .when = when, 306 .when = when,
342 }; 307 };
308 container_descendants(con, C_VIEW,
309 send_frame_done_container_iterator, &data);
310}
343 311
312static void send_frame_done(struct sway_output *output, struct timespec *when) {
344 if (output_has_opaque_overlay_layer_surface(output)) { 313 if (output_has_opaque_overlay_layer_surface(output)) {
345 goto send_frame_overlay; 314 goto send_frame_overlay;
346 } 315 }
@@ -349,35 +318,38 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) {
349 if (workspace->current.ws_fullscreen) { 318 if (workspace->current.ws_fullscreen) {
350 if (workspace->current.ws_fullscreen->type == C_VIEW) { 319 if (workspace->current.ws_fullscreen->type == C_VIEW) {
351 send_frame_done_container_iterator( 320 send_frame_done_container_iterator(
352 workspace->current.ws_fullscreen, &data); 321 workspace->current.ws_fullscreen, when);
353 } else { 322 } else {
354 send_frame_done_container(&data, workspace->current.ws_fullscreen); 323 send_frame_done_container(output, workspace->current.ws_fullscreen,
324 when);
355 } 325 }
356#ifdef HAVE_XWAYLAND 326#ifdef HAVE_XWAYLAND
357 send_frame_done_unmanaged(&data, 327 send_frame_done_unmanaged(output,
358 &root_container.sway_root->xwayland_unmanaged); 328 &root_container.sway_root->xwayland_unmanaged, when);
359#endif 329#endif
360 } else { 330 } else {
361 send_frame_done_layer(output, 331 send_frame_done_layer(output,
362 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &data); 332 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], when);
363 send_frame_done_layer(output, 333 send_frame_done_layer(output,
364 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &data); 334 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], when);
365 335
366 send_frame_done_container(&data, workspace); 336 send_frame_done_container(output, workspace, when);
367 send_frame_done_container(&data, workspace->sway_workspace->floating); 337 send_frame_done_container(output, workspace->sway_workspace->floating,
338 when);
368 339
369#ifdef HAVE_XWAYLAND 340#ifdef HAVE_XWAYLAND
370 send_frame_done_unmanaged(&data, 341 send_frame_done_unmanaged(output,
371 &root_container.sway_root->xwayland_unmanaged); 342 &root_container.sway_root->xwayland_unmanaged, when);
372#endif 343#endif
373 send_frame_done_layer(output, 344 send_frame_done_layer(output,
374 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &data); 345 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], when);
375 } 346 }
376 347
377send_frame_overlay: 348send_frame_overlay:
378 send_frame_done_layer(output, 349 send_frame_done_layer(output,
379 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &data); 350 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], when);
380 send_frame_done_drag_icons(&data, &root_container.sway_root->drag_icons); 351 send_frame_done_drag_icons(output, &root_container.sway_root->drag_icons,
352 when);
381} 353}
382 354
383static void damage_handle_frame(struct wl_listener *listener, void *data) { 355static void damage_handle_frame(struct wl_listener *listener, void *data) {
@@ -412,68 +384,11 @@ void output_damage_whole(struct sway_output *output) {
412 wlr_output_damage_add_whole(output->damage); 384 wlr_output_damage_add_whole(output->damage);
413} 385}
414 386
415struct damage_data { 387static void damage_surface_iterator(struct sway_output *output,
416 struct root_geometry root_geo;
417 struct sway_output *output;
418 bool whole;
419};
420
421static void damage_surface_iterator(struct wlr_surface *surface, int sx, int sy,
422 void *_data) {
423 struct damage_data *data = _data;
424 struct sway_output *output = data->output;
425 float rotation = data->root_geo.rotation;
426 bool whole = data->whole;
427
428 struct wlr_box box;
429 bool intersects = output_get_surface_box(&data->root_geo, data->output, surface,
430 sx, sy, &box);
431 if (!intersects) {
432 return;
433 }
434
435 scale_box(&box, output->wlr_output->scale);
436
437 int center_x = box.x + box.width/2;
438 int center_y = box.y + box.height/2;
439
440 if (pixman_region32_not_empty(&surface->buffer_damage)) {
441 enum wl_output_transform transform =
442 wlr_output_transform_invert(surface->current.transform);
443
444 pixman_region32_t damage;
445 pixman_region32_init(&damage);
446 pixman_region32_copy(&damage, &surface->buffer_damage);
447 wlr_region_transform(&damage, &damage, transform,
448 surface->current.buffer_width, surface->current.buffer_height);
449 wlr_region_scale(&damage, &damage,
450 output->wlr_output->scale / (float)surface->current.scale);
451 if (ceil(output->wlr_output->scale) > surface->current.scale) {
452 // When scaling up a surface, it'll become blurry so we need to
453 // expand the damage region
454 wlr_region_expand(&damage, &damage,
455 ceil(output->wlr_output->scale) - surface->current.scale);
456 }
457 pixman_region32_translate(&damage, box.x, box.y);
458 wlr_region_rotated_bounds(&damage, &damage, rotation,
459 center_x, center_y);
460 wlr_output_damage_add(output->damage, &damage);
461 pixman_region32_fini(&damage);
462 }
463
464 if (whole) {
465 wlr_box_rotated_bounds(&box, rotation, &box);
466 wlr_output_damage_add_box(output->damage, &box);
467 }
468
469 wlr_output_schedule_frame(output->wlr_output);
470}
471
472static void damage_surface_iterator2(struct sway_output *output,
473 struct wlr_surface *surface, struct wlr_box *_box, float rotation, 388 struct wlr_surface *surface, struct wlr_box *_box, float rotation,
474 void *_data) { 389 void *_data) {
475 struct damage_data *data = _data; 390 bool *data = _data;
476 bool whole = data->whole; 391 bool whole = *data;
477 392
478 struct wlr_box box = *_box; 393 struct wlr_box box = *_box;
479 scale_box(&box, output->wlr_output->scale); 394 scale_box(&box, output->wlr_output->scale);
@@ -515,13 +430,8 @@ static void damage_surface_iterator2(struct sway_output *output,
515 430
516void output_damage_surface(struct sway_output *output, double ox, double oy, 431void output_damage_surface(struct sway_output *output, double ox, double oy,
517 struct wlr_surface *surface, bool whole) { 432 struct wlr_surface *surface, bool whole) {
518 struct damage_data data = { 433 output_surface_for_each_surface(output, surface, ox, oy, 0,
519 .output = output, 434 damage_surface_iterator, &whole);
520 .whole = whole,
521 };
522
523 output_surface_for_each_surface(surface, ox, oy, &data.root_geo,
524 damage_surface_iterator, &data);
525} 435}
526 436
527static void output_damage_view(struct sway_output *output, 437static void output_damage_view(struct sway_output *output,
@@ -534,12 +444,7 @@ static void output_damage_view(struct sway_output *output,
534 return; 444 return;
535 } 445 }
536 446
537 struct damage_data data = { 447 output_view_for_each_surface(output, view, damage_surface_iterator, &whole);
538 .output = output,
539 .whole = whole,
540 };
541
542 output_view_for_each_surface(output, view, damage_surface_iterator2, &data);
543} 448}
544 449
545void output_damage_from_view(struct sway_output *output, 450void output_damage_from_view(struct sway_output *output,