1 #define _POSIX_C_SOURCE 200809L
2 #include <assert.h>
3 #include <stdlib.h>
4 #include <strings.h>
5 #include <time.h>
6 #include <wayland-server-core.h>
7 #include <wlr/render/wlr_renderer.h>
8 #include <wlr/types/wlr_box.h>
9 #include <wlr/types/wlr_buffer.h>
10 #include <wlr/types/wlr_matrix.h>
11 #include <wlr/types/wlr_output_damage.h>
12 #include <wlr/types/wlr_output_layout.h>
13 #include <wlr/types/wlr_output.h>
14 #include <wlr/types/wlr_presentation_time.h>
15 #include <wlr/types/wlr_surface.h>
16 #include <wlr/util/region.h>
17 #include "config.h"
18 #include "log.h"
19 #include "sway/config.h"
20 #include "sway/desktop/transaction.h"
21 #include "sway/input/input-manager.h"
22 #include "sway/input/seat.h"
23 #include "sway/layers.h"
24 #include "sway/output.h"
25 #include "sway/server.h"
26 #include "sway/surface.h"
27 #include "sway/tree/arrange.h"
28 #include "sway/tree/container.h"
29 #include "sway/tree/root.h"
30 #include "sway/tree/view.h"
31 #include "sway/tree/workspace.h"
32
output_by_name_or_id(const char * name_or_id)33 struct sway_output *output_by_name_or_id(const char *name_or_id) {
34 for (int i = 0; i < root->outputs->length; ++i) {
35 struct sway_output *output = root->outputs->items[i];
36 char identifier[128];
37 output_get_identifier(identifier, sizeof(identifier), output);
38 if (strcasecmp(identifier, name_or_id) == 0
39 || strcasecmp(output->wlr_output->name, name_or_id) == 0) {
40 return output;
41 }
42 }
43 return NULL;
44 }
45
all_output_by_name_or_id(const char * name_or_id)46 struct sway_output *all_output_by_name_or_id(const char *name_or_id) {
47 struct sway_output *output;
48 wl_list_for_each(output, &root->all_outputs, link) {
49 char identifier[128];
50 output_get_identifier(identifier, sizeof(identifier), output);
51 if (strcasecmp(identifier, name_or_id) == 0
52 || strcasecmp(output->wlr_output->name, name_or_id) == 0) {
53 return output;
54 }
55 }
56 return NULL;
57 }
58
59 /**
60 * Rotate a child's position relative to a parent. The parent size is (pw, ph),
61 * the child position is (*sx, *sy) and its size is (sw, sh).
62 */
rotate_child_position(double * sx,double * sy,double sw,double sh,double pw,double ph,float rotation)63 static void rotate_child_position(double *sx, double *sy, double sw, double sh,
64 double pw, double ph, float rotation) {
65 if (rotation == 0.0f) {
66 return;
67 }
68
69 // Coordinates relative to the center of the subsurface
70 double ox = *sx - pw/2 + sw/2,
71 oy = *sy - ph/2 + sh/2;
72 // Rotated coordinates
73 double rx = cos(-rotation)*ox - sin(-rotation)*oy,
74 ry = cos(-rotation)*oy + sin(-rotation)*ox;
75 *sx = rx + pw/2 - sw/2;
76 *sy = ry + ph/2 - sh/2;
77 }
78
79 struct surface_iterator_data {
80 sway_surface_iterator_func_t user_iterator;
81 void *user_data;
82
83 struct sway_output *output;
84 struct sway_view *view;
85 double ox, oy;
86 int width, height;
87 float rotation;
88 };
89
get_surface_box(struct surface_iterator_data * data,struct wlr_surface * surface,int sx,int sy,struct wlr_box * surface_box)90 static bool get_surface_box(struct surface_iterator_data *data,
91 struct wlr_surface *surface, int sx, int sy,
92 struct wlr_box *surface_box) {
93 struct sway_output *output = data->output;
94
95 if (!wlr_surface_has_buffer(surface)) {
96 return false;
97 }
98
99 int sw = surface->current.width;
100 int sh = surface->current.height;
101
102 double _sx = sx + surface->sx;
103 double _sy = sy + surface->sy;
104 rotate_child_position(&_sx, &_sy, sw, sh, data->width, data->height,
105 data->rotation);
106
107 struct wlr_box box = {
108 .x = data->ox + _sx,
109 .y = data->oy + _sy,
110 .width = sw,
111 .height = sh,
112 };
113 if (surface_box != NULL) {
114 memcpy(surface_box, &box, sizeof(struct wlr_box));
115 }
116
117 struct wlr_box rotated_box;
118 wlr_box_rotated_bounds(&rotated_box, &box, data->rotation);
119
120 struct wlr_box output_box = {
121 .width = output->width,
122 .height = output->height,
123 };
124
125 struct wlr_box intersection;
126 return wlr_box_intersection(&intersection, &output_box, &rotated_box);
127 }
128
output_for_each_surface_iterator(struct wlr_surface * surface,int sx,int sy,void * _data)129 static void output_for_each_surface_iterator(struct wlr_surface *surface,
130 int sx, int sy, void *_data) {
131 struct surface_iterator_data *data = _data;
132
133 struct wlr_box box;
134 bool intersects = get_surface_box(data, surface, sx, sy, &box);
135 if (!intersects) {
136 return;
137 }
138
139 data->user_iterator(data->output, data->view, surface, &box, data->rotation,
140 data->user_data);
141 }
142
output_surface_for_each_surface(struct sway_output * output,struct wlr_surface * surface,double ox,double oy,sway_surface_iterator_func_t iterator,void * user_data)143 void output_surface_for_each_surface(struct sway_output *output,
144 struct wlr_surface *surface, double ox, double oy,
145 sway_surface_iterator_func_t iterator, void *user_data) {
146 struct surface_iterator_data data = {
147 .user_iterator = iterator,
148 .user_data = user_data,
149 .output = output,
150 .view = NULL,
151 .ox = ox,
152 .oy = oy,
153 .width = surface->current.width,
154 .height = surface->current.height,
155 .rotation = 0,
156 };
157
158 wlr_surface_for_each_surface(surface,
159 output_for_each_surface_iterator, &data);
160 }
161
output_view_for_each_surface(struct sway_output * output,struct sway_view * view,sway_surface_iterator_func_t iterator,void * user_data)162 void output_view_for_each_surface(struct sway_output *output,
163 struct sway_view *view, sway_surface_iterator_func_t iterator,
164 void *user_data) {
165 struct surface_iterator_data data = {
166 .user_iterator = iterator,
167 .user_data = user_data,
168 .output = output,
169 .view = view,
170 .ox = view->container->surface_x - output->lx
171 - view->geometry.x,
172 .oy = view->container->surface_y - output->ly
173 - view->geometry.y,
174 .width = view->container->current.content_width,
175 .height = view->container->current.content_height,
176 .rotation = 0, // TODO
177 };
178
179 view_for_each_surface(view, output_for_each_surface_iterator, &data);
180 }
181
output_view_for_each_popup(struct sway_output * output,struct sway_view * view,sway_surface_iterator_func_t iterator,void * user_data)182 void output_view_for_each_popup(struct sway_output *output,
183 struct sway_view *view, sway_surface_iterator_func_t iterator,
184 void *user_data) {
185 struct surface_iterator_data data = {
186 .user_iterator = iterator,
187 .user_data = user_data,
188 .output = output,
189 .view = view,
190 .ox = view->container->surface_x - output->lx
191 - view->geometry.x,
192 .oy = view->container->surface_y - output->ly
193 - view->geometry.y,
194 .width = view->container->current.content_width,
195 .height = view->container->current.content_height,
196 .rotation = 0, // TODO
197 };
198
199 view_for_each_popup(view, output_for_each_surface_iterator, &data);
200 }
201
output_layer_for_each_surface(struct sway_output * output,struct wl_list * layer_surfaces,sway_surface_iterator_func_t iterator,void * user_data)202 void output_layer_for_each_surface(struct sway_output *output,
203 struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator,
204 void *user_data) {
205 struct sway_layer_surface *layer_surface;
206 wl_list_for_each(layer_surface, layer_surfaces, link) {
207 struct wlr_layer_surface_v1 *wlr_layer_surface_v1 =
208 layer_surface->layer_surface;
209 output_surface_for_each_surface(output, wlr_layer_surface_v1->surface,
210 layer_surface->geo.x, layer_surface->geo.y, iterator,
211 user_data);
212
213 struct wlr_xdg_popup *state;
214 wl_list_for_each(state, &wlr_layer_surface_v1->popups, link) {
215 struct wlr_xdg_surface *popup = state->base;
216 if (!popup->configured) {
217 continue;
218 }
219
220 double popup_sx, popup_sy;
221 popup_sx = layer_surface->geo.x +
222 popup->popup->geometry.x - popup->geometry.x;
223 popup_sy = layer_surface->geo.y +
224 popup->popup->geometry.y - popup->geometry.y;
225
226 struct wlr_surface *surface = popup->surface;
227
228 struct surface_iterator_data data = {
229 .user_iterator = iterator,
230 .user_data = user_data,
231 .output = output,
232 .view = NULL,
233 .ox = popup_sx,
234 .oy = popup_sy,
235 .width = surface->current.width,
236 .height = surface->current.height,
237 .rotation = 0,
238 };
239
240 wlr_xdg_surface_for_each_surface(
241 popup, output_for_each_surface_iterator, &data);
242 }
243 }
244 }
245
output_layer_for_each_surface_toplevel(struct sway_output * output,struct wl_list * layer_surfaces,sway_surface_iterator_func_t iterator,void * user_data)246 void output_layer_for_each_surface_toplevel(struct sway_output *output,
247 struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator,
248 void *user_data) {
249 struct sway_layer_surface *layer_surface;
250 wl_list_for_each(layer_surface, layer_surfaces, link) {
251 struct wlr_layer_surface_v1 *wlr_layer_surface_v1 =
252 layer_surface->layer_surface;
253 output_surface_for_each_surface(output, wlr_layer_surface_v1->surface,
254 layer_surface->geo.x, layer_surface->geo.y, iterator,
255 user_data);
256 }
257 }
258
259
output_layer_for_each_surface_popup(struct sway_output * output,struct wl_list * layer_surfaces,sway_surface_iterator_func_t iterator,void * user_data)260 void output_layer_for_each_surface_popup(struct sway_output *output,
261 struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator,
262 void *user_data) {
263 struct sway_layer_surface *layer_surface;
264 wl_list_for_each(layer_surface, layer_surfaces, link) {
265 struct wlr_layer_surface_v1 *wlr_layer_surface_v1 =
266 layer_surface->layer_surface;
267
268 struct wlr_xdg_popup *state;
269 wl_list_for_each(state, &wlr_layer_surface_v1->popups, link) {
270 struct wlr_xdg_surface *popup = state->base;
271 if (!popup->configured) {
272 continue;
273 }
274
275 double popup_sx, popup_sy;
276 popup_sx = layer_surface->geo.x +
277 popup->popup->geometry.x - popup->geometry.x;
278 popup_sy = layer_surface->geo.y +
279 popup->popup->geometry.y - popup->geometry.y;
280
281 struct wlr_surface *surface = popup->surface;
282
283 struct surface_iterator_data data = {
284 .user_iterator = iterator,
285 .user_data = user_data,
286 .output = output,
287 .view = NULL,
288 .ox = popup_sx,
289 .oy = popup_sy,
290 .width = surface->current.width,
291 .height = surface->current.height,
292 .rotation = 0,
293 };
294
295 wlr_xdg_surface_for_each_surface(
296 popup, output_for_each_surface_iterator, &data);
297 }
298 }
299 }
300
301 #if HAVE_XWAYLAND
output_unmanaged_for_each_surface(struct sway_output * output,struct wl_list * unmanaged,sway_surface_iterator_func_t iterator,void * user_data)302 void output_unmanaged_for_each_surface(struct sway_output *output,
303 struct wl_list *unmanaged, sway_surface_iterator_func_t iterator,
304 void *user_data) {
305 struct sway_xwayland_unmanaged *unmanaged_surface;
306 wl_list_for_each(unmanaged_surface, unmanaged, link) {
307 struct wlr_xwayland_surface *xsurface =
308 unmanaged_surface->wlr_xwayland_surface;
309 double ox = unmanaged_surface->lx - output->lx;
310 double oy = unmanaged_surface->ly - output->ly;
311
312 output_surface_for_each_surface(output, xsurface->surface, ox, oy,
313 iterator, user_data);
314 }
315 }
316 #endif
317
output_drag_icons_for_each_surface(struct sway_output * output,struct wl_list * drag_icons,sway_surface_iterator_func_t iterator,void * user_data)318 void output_drag_icons_for_each_surface(struct sway_output *output,
319 struct wl_list *drag_icons, sway_surface_iterator_func_t iterator,
320 void *user_data) {
321 struct sway_drag_icon *drag_icon;
322 wl_list_for_each(drag_icon, drag_icons, link) {
323 double ox = drag_icon->x - output->lx;
324 double oy = drag_icon->y - output->ly;
325
326 if (drag_icon->wlr_drag_icon->mapped) {
327 output_surface_for_each_surface(output,
328 drag_icon->wlr_drag_icon->surface, ox, oy,
329 iterator, user_data);
330 }
331 }
332 }
333
for_each_surface_container_iterator(struct sway_container * con,void * _data)334 static void for_each_surface_container_iterator(struct sway_container *con,
335 void *_data) {
336 if (!con->view || !view_is_visible(con->view)) {
337 return;
338 }
339
340 struct surface_iterator_data *data = _data;
341 output_view_for_each_surface(data->output, con->view,
342 data->user_iterator, data->user_data);
343 }
344
output_for_each_surface(struct sway_output * output,sway_surface_iterator_func_t iterator,void * user_data)345 static void output_for_each_surface(struct sway_output *output,
346 sway_surface_iterator_func_t iterator, void *user_data) {
347 if (output_has_opaque_overlay_layer_surface(output)) {
348 goto overlay;
349 }
350
351 struct surface_iterator_data data = {
352 .user_iterator = iterator,
353 .user_data = user_data,
354 .output = output,
355 .view = NULL,
356 };
357
358 struct sway_workspace *workspace = output_get_active_workspace(output);
359 struct sway_container *fullscreen_con = root->fullscreen_global;
360 if (!fullscreen_con) {
361 if (!workspace) {
362 return;
363 }
364 fullscreen_con = workspace->current.fullscreen;
365 }
366 if (fullscreen_con) {
367 for_each_surface_container_iterator(fullscreen_con, &data);
368 container_for_each_child(fullscreen_con,
369 for_each_surface_container_iterator, &data);
370
371 // TODO: Show transient containers for fullscreen global
372 if (fullscreen_con == workspace->current.fullscreen) {
373 for (int i = 0; i < workspace->current.floating->length; ++i) {
374 struct sway_container *floater =
375 workspace->current.floating->items[i];
376 if (container_is_transient_for(floater, fullscreen_con)) {
377 for_each_surface_container_iterator(floater, &data);
378 }
379 }
380 }
381 #if HAVE_XWAYLAND
382 output_unmanaged_for_each_surface(output, &root->xwayland_unmanaged,
383 iterator, user_data);
384 #endif
385 } else {
386 output_layer_for_each_surface(output,
387 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
388 iterator, user_data);
389 output_layer_for_each_surface(output,
390 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
391 iterator, user_data);
392
393 workspace_for_each_container(workspace,
394 for_each_surface_container_iterator, &data);
395
396 #if HAVE_XWAYLAND
397 output_unmanaged_for_each_surface(output, &root->xwayland_unmanaged,
398 iterator, user_data);
399 #endif
400 output_layer_for_each_surface(output,
401 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
402 iterator, user_data);
403 }
404
405 overlay:
406 output_layer_for_each_surface(output,
407 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
408 iterator, user_data);
409 output_drag_icons_for_each_surface(output, &root->drag_icons,
410 iterator, user_data);
411 }
412
scale_length(int length,int offset,float scale)413 static int scale_length(int length, int offset, float scale) {
414 return round((offset + length) * scale) - round(offset * scale);
415 }
416
scale_box(struct wlr_box * box,float scale)417 void scale_box(struct wlr_box *box, float scale) {
418 box->width = scale_length(box->width, box->x, scale);
419 box->height = scale_length(box->height, box->y, scale);
420 box->x = round(box->x * scale);
421 box->y = round(box->y * scale);
422 }
423
output_get_active_workspace(struct sway_output * output)424 struct sway_workspace *output_get_active_workspace(struct sway_output *output) {
425 struct sway_seat *seat = input_manager_current_seat();
426 struct sway_node *focus = seat_get_active_tiling_child(seat, &output->node);
427 if (!focus) {
428 if (!output->workspaces->length) {
429 return NULL;
430 }
431 return output->workspaces->items[0];
432 }
433 return focus->sway_workspace;
434 }
435
output_has_opaque_overlay_layer_surface(struct sway_output * output)436 bool output_has_opaque_overlay_layer_surface(struct sway_output *output) {
437 struct sway_layer_surface *sway_layer_surface;
438 wl_list_for_each(sway_layer_surface,
439 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], link) {
440 struct wlr_surface *wlr_surface = sway_layer_surface->layer_surface->surface;
441 pixman_box32_t output_box = {
442 .x2 = output->width,
443 .y2 = output->height,
444 };
445 pixman_region32_t surface_opaque_box;
446 pixman_region32_init(&surface_opaque_box);
447 pixman_region32_copy(&surface_opaque_box, &wlr_surface->opaque_region);
448 pixman_region32_translate(&surface_opaque_box,
449 sway_layer_surface->geo.x, sway_layer_surface->geo.y);
450 pixman_region_overlap_t contains =
451 pixman_region32_contains_rectangle(&surface_opaque_box, &output_box);
452 pixman_region32_fini(&surface_opaque_box);
453
454 if (contains == PIXMAN_REGION_IN) {
455 return true;
456 }
457 }
458 return false;
459 }
460
461 struct send_frame_done_data {
462 struct timespec when;
463 int msec_until_refresh;
464 };
465
send_frame_done_iterator(struct sway_output * output,struct sway_view * view,struct wlr_surface * surface,struct wlr_box * box,float rotation,void * user_data)466 static void send_frame_done_iterator(struct sway_output *output, struct sway_view *view,
467 struct wlr_surface *surface, struct wlr_box *box, float rotation,
468 void *user_data) {
469 int view_max_render_time = 0;
470 if (view != NULL) {
471 view_max_render_time = view->max_render_time;
472 }
473
474 struct send_frame_done_data *data = user_data;
475
476 int delay = data->msec_until_refresh - output->max_render_time
477 - view_max_render_time;
478
479 if (output->max_render_time == 0 || view_max_render_time == 0 || delay < 1) {
480 wlr_surface_send_frame_done(surface, &data->when);
481 } else {
482 struct sway_surface *sway_surface = surface->data;
483 wl_event_source_timer_update(sway_surface->frame_done_timer, delay);
484 }
485 }
486
send_frame_done(struct sway_output * output,struct send_frame_done_data * data)487 static void send_frame_done(struct sway_output *output, struct send_frame_done_data *data) {
488 output_for_each_surface(output, send_frame_done_iterator, data);
489 }
490
count_surface_iterator(struct sway_output * output,struct sway_view * view,struct wlr_surface * surface,struct wlr_box * _box,float rotation,void * data)491 static void count_surface_iterator(struct sway_output *output, struct sway_view *view,
492 struct wlr_surface *surface, struct wlr_box *_box, float rotation,
493 void *data) {
494 size_t *n = data;
495 (*n)++;
496 }
497
scan_out_fullscreen_view(struct sway_output * output,struct sway_view * view)498 static bool scan_out_fullscreen_view(struct sway_output *output,
499 struct sway_view *view) {
500 struct wlr_output *wlr_output = output->wlr_output;
501 struct sway_workspace *workspace = output->current.active_workspace;
502 if (!sway_assert(workspace, "Expected an active workspace")) {
503 return false;
504 }
505
506 if (!wl_list_empty(&view->saved_buffers)) {
507 return false;
508 }
509
510 for (int i = 0; i < workspace->current.floating->length; ++i) {
511 struct sway_container *floater =
512 workspace->current.floating->items[i];
513 if (container_is_transient_for(floater, view->container)) {
514 return false;
515 }
516 }
517
518 #if HAVE_XWAYLAND
519 if (!wl_list_empty(&root->xwayland_unmanaged)) {
520 return false;
521 }
522 #endif
523
524 if (!wl_list_empty(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY])) {
525 return false;
526 }
527 if (!wl_list_empty(&root->drag_icons)) {
528 return false;
529 }
530
531 struct wlr_surface *surface = view->surface;
532 if (surface == NULL) {
533 return false;
534 }
535 size_t n_surfaces = 0;
536 output_view_for_each_surface(output, view,
537 count_surface_iterator, &n_surfaces);
538 if (n_surfaces != 1) {
539 return false;
540 }
541
542 if (surface->buffer == NULL) {
543 return false;
544 }
545
546 if ((float)surface->current.scale != wlr_output->scale ||
547 surface->current.transform != wlr_output->transform) {
548 return false;
549 }
550
551 wlr_presentation_surface_sampled_on_output(server.presentation, surface,
552 wlr_output);
553
554 wlr_output_attach_buffer(wlr_output, &surface->buffer->base);
555 return wlr_output_commit(wlr_output);
556 }
557
output_repaint_timer_handler(void * data)558 static int output_repaint_timer_handler(void *data) {
559 struct sway_output *output = data;
560 if (output->wlr_output == NULL) {
561 return 0;
562 }
563
564 output->wlr_output->frame_pending = false;
565
566 struct sway_workspace *workspace = output->current.active_workspace;
567 if (workspace == NULL) {
568 return 0;
569 }
570
571 struct sway_container *fullscreen_con = root->fullscreen_global;
572 if (!fullscreen_con) {
573 fullscreen_con = workspace->current.fullscreen;
574 }
575
576 if (fullscreen_con && fullscreen_con->view) {
577 // Try to scan-out the fullscreen view
578 static bool last_scanned_out = false;
579 bool scanned_out =
580 scan_out_fullscreen_view(output, fullscreen_con->view);
581
582 if (scanned_out && !last_scanned_out) {
583 sway_log(SWAY_DEBUG, "Scanning out fullscreen view");
584 }
585 if (last_scanned_out && !scanned_out) {
586 sway_log(SWAY_DEBUG, "Stopping fullscreen view scan out");
587 }
588 last_scanned_out = scanned_out;
589
590 if (scanned_out) {
591 return 0;
592 }
593 }
594
595 bool needs_frame;
596 pixman_region32_t damage;
597 pixman_region32_init(&damage);
598 if (!wlr_output_damage_attach_render(output->damage,
599 &needs_frame, &damage)) {
600 return 0;
601 }
602
603 if (needs_frame) {
604 struct timespec now;
605 clock_gettime(CLOCK_MONOTONIC, &now);
606
607 output_render(output, &now, &damage);
608 } else {
609 wlr_output_rollback(output->wlr_output);
610 }
611
612 pixman_region32_fini(&damage);
613
614 return 0;
615 }
616
damage_handle_frame(struct wl_listener * listener,void * user_data)617 static void damage_handle_frame(struct wl_listener *listener, void *user_data) {
618 struct sway_output *output =
619 wl_container_of(listener, output, damage_frame);
620 if (!output->enabled || !output->wlr_output->enabled) {
621 return;
622 }
623
624 // Compute predicted milliseconds until the next refresh. It's used for
625 // delaying both output rendering and surface frame callbacks.
626 int msec_until_refresh = 0;
627
628 if (output->max_render_time != 0) {
629 struct timespec now;
630 clockid_t presentation_clock
631 = wlr_backend_get_presentation_clock(server.backend);
632 clock_gettime(presentation_clock, &now);
633
634 const long NSEC_IN_SECONDS = 1000000000;
635 struct timespec predicted_refresh = output->last_presentation;
636 predicted_refresh.tv_nsec += output->refresh_nsec % NSEC_IN_SECONDS;
637 predicted_refresh.tv_sec += output->refresh_nsec / NSEC_IN_SECONDS;
638 if (predicted_refresh.tv_nsec >= NSEC_IN_SECONDS) {
639 predicted_refresh.tv_sec += 1;
640 predicted_refresh.tv_nsec -= NSEC_IN_SECONDS;
641 }
642
643 // If the predicted refresh time is before the current time then
644 // there's no point in delaying.
645 //
646 // We only check tv_sec because if the predicted refresh time is less
647 // than a second before the current time, then msec_until_refresh will
648 // end up slightly below zero, which will effectively disable the delay
649 // without potential disastrous negative overflows that could occur if
650 // tv_sec was not checked.
651 if (predicted_refresh.tv_sec >= now.tv_sec) {
652 long nsec_until_refresh
653 = (predicted_refresh.tv_sec - now.tv_sec) * NSEC_IN_SECONDS
654 + (predicted_refresh.tv_nsec - now.tv_nsec);
655
656 // We want msec_until_refresh to be conservative, that is, floored.
657 // If we have 7.9 msec until refresh, we better compute the delay
658 // as if we had only 7 msec, so that we don't accidentally delay
659 // more than necessary and miss a frame.
660 msec_until_refresh = nsec_until_refresh / 1000000;
661 }
662 }
663
664 int delay = msec_until_refresh - output->max_render_time;
665
666 // If the delay is less than 1 millisecond (which is the least we can wait)
667 // then just render right away.
668 if (delay < 1) {
669 output_repaint_timer_handler(output);
670 } else {
671 output->wlr_output->frame_pending = true;
672 wl_event_source_timer_update(output->repaint_timer, delay);
673 }
674
675 // Send frame done to all visible surfaces
676 struct send_frame_done_data data = {0};
677 clock_gettime(CLOCK_MONOTONIC, &data.when);
678 data.msec_until_refresh = msec_until_refresh;
679 send_frame_done(output, &data);
680 }
681
output_damage_whole(struct sway_output * output)682 void output_damage_whole(struct sway_output *output) {
683 // The output can exist with no wlr_output if it's just been disconnected
684 // and the transaction to evacuate it has't completed yet.
685 if (output && output->wlr_output && output->damage) {
686 wlr_output_damage_add_whole(output->damage);
687 }
688 }
689
damage_surface_iterator(struct sway_output * output,struct sway_view * view,struct wlr_surface * surface,struct wlr_box * _box,float rotation,void * _data)690 static void damage_surface_iterator(struct sway_output *output, struct sway_view *view,
691 struct wlr_surface *surface, struct wlr_box *_box, float rotation,
692 void *_data) {
693 bool *data = _data;
694 bool whole = *data;
695
696 struct wlr_box box = *_box;
697 scale_box(&box, output->wlr_output->scale);
698
699 int center_x = box.x + box.width/2;
700 int center_y = box.y + box.height/2;
701
702 if (pixman_region32_not_empty(&surface->buffer_damage)) {
703 pixman_region32_t damage;
704 pixman_region32_init(&damage);
705 wlr_surface_get_effective_damage(surface, &damage);
706 wlr_region_scale(&damage, &damage, output->wlr_output->scale);
707 if (ceil(output->wlr_output->scale) > surface->current.scale) {
708 // When scaling up a surface, it'll become blurry so we need to
709 // expand the damage region
710 wlr_region_expand(&damage, &damage,
711 ceil(output->wlr_output->scale) - surface->current.scale);
712 }
713 pixman_region32_translate(&damage, box.x, box.y);
714 wlr_region_rotated_bounds(&damage, &damage, rotation,
715 center_x, center_y);
716 wlr_output_damage_add(output->damage, &damage);
717 pixman_region32_fini(&damage);
718 }
719
720 if (whole) {
721 wlr_box_rotated_bounds(&box, &box, rotation);
722 wlr_output_damage_add_box(output->damage, &box);
723 }
724
725 if (!wl_list_empty(&surface->current.frame_callback_list)) {
726 wlr_output_schedule_frame(output->wlr_output);
727 }
728 }
729
output_damage_surface(struct sway_output * output,double ox,double oy,struct wlr_surface * surface,bool whole)730 void output_damage_surface(struct sway_output *output, double ox, double oy,
731 struct wlr_surface *surface, bool whole) {
732 output_surface_for_each_surface(output, surface, ox, oy,
733 damage_surface_iterator, &whole);
734 }
735
output_damage_from_view(struct sway_output * output,struct sway_view * view)736 void output_damage_from_view(struct sway_output *output,
737 struct sway_view *view) {
738 if (!view_is_visible(view)) {
739 return;
740 }
741 bool whole = false;
742 output_view_for_each_surface(output, view, damage_surface_iterator, &whole);
743 }
744
745 // Expecting an unscaled box in layout coordinates
output_damage_box(struct sway_output * output,struct wlr_box * _box)746 void output_damage_box(struct sway_output *output, struct wlr_box *_box) {
747 struct wlr_box box;
748 memcpy(&box, _box, sizeof(struct wlr_box));
749 box.x -= output->lx;
750 box.y -= output->ly;
751 scale_box(&box, output->wlr_output->scale);
752 wlr_output_damage_add_box(output->damage, &box);
753 }
754
damage_child_views_iterator(struct sway_container * con,void * data)755 static void damage_child_views_iterator(struct sway_container *con,
756 void *data) {
757 if (!con->view || !view_is_visible(con->view)) {
758 return;
759 }
760 struct sway_output *output = data;
761 bool whole = true;
762 output_view_for_each_surface(output, con->view, damage_surface_iterator,
763 &whole);
764 }
765
output_damage_whole_container(struct sway_output * output,struct sway_container * con)766 void output_damage_whole_container(struct sway_output *output,
767 struct sway_container *con) {
768 // Pad the box by 1px, because the width is a double and might be a fraction
769 struct wlr_box box = {
770 .x = con->current.x - output->lx - 1,
771 .y = con->current.y - output->ly - 1,
772 .width = con->current.width + 2,
773 .height = con->current.height + 2,
774 };
775 scale_box(&box, output->wlr_output->scale);
776 wlr_output_damage_add_box(output->damage, &box);
777 // Damage subsurfaces as well, which may extend outside the box
778 if (con->view) {
779 damage_child_views_iterator(con, output);
780 } else {
781 container_for_each_child(con, damage_child_views_iterator, output);
782 }
783 }
784
damage_handle_destroy(struct wl_listener * listener,void * data)785 static void damage_handle_destroy(struct wl_listener *listener, void *data) {
786 struct sway_output *output =
787 wl_container_of(listener, output, damage_destroy);
788 if (!output->enabled) {
789 return;
790 }
791 output_disable(output);
792
793 wl_list_remove(&output->damage_destroy.link);
794 wl_list_remove(&output->damage_frame.link);
795
796 transaction_commit_dirty();
797 }
798
update_output_manager_config(struct sway_server * server)799 static void update_output_manager_config(struct sway_server *server) {
800 struct wlr_output_configuration_v1 *config =
801 wlr_output_configuration_v1_create();
802
803 struct sway_output *output;
804 wl_list_for_each(output, &root->all_outputs, link) {
805 if (output == root->noop_output) {
806 continue;
807 }
808 struct wlr_output_configuration_head_v1 *config_head =
809 wlr_output_configuration_head_v1_create(config, output->wlr_output);
810 struct wlr_box *output_box = wlr_output_layout_get_box(
811 root->output_layout, output->wlr_output);
812 // We mark the output enabled even if it is switched off by DPMS
813 config_head->state.enabled = output->enabled;
814 config_head->state.mode = output->current_mode;
815 if (output_box) {
816 config_head->state.x = output_box->x;
817 config_head->state.y = output_box->y;
818 }
819 }
820
821 wlr_output_manager_v1_set_configuration(server->output_manager_v1, config);
822 }
823
handle_destroy(struct wl_listener * listener,void * data)824 static void handle_destroy(struct wl_listener *listener, void *data) {
825 struct sway_output *output = wl_container_of(listener, output, destroy);
826 struct sway_server *server = output->server;
827 wl_signal_emit(&output->events.destroy, output);
828
829 if (output->enabled) {
830 output_disable(output);
831 }
832 output_begin_destroy(output);
833
834 wl_list_remove(&output->destroy.link);
835 wl_list_remove(&output->mode.link);
836 wl_list_remove(&output->transform.link);
837 wl_list_remove(&output->scale.link);
838 wl_list_remove(&output->present.link);
839
840 transaction_commit_dirty();
841
842 update_output_manager_config(server);
843 }
844
handle_mode(struct wl_listener * listener,void * data)845 static void handle_mode(struct wl_listener *listener, void *data) {
846 struct sway_output *output = wl_container_of(listener, output, mode);
847 if (!output->enabled && !output->enabling) {
848 struct output_config *oc = find_output_config(output);
849 if (output->wlr_output->current_mode != NULL &&
850 (!oc || oc->enabled)) {
851 // We want to enable this output, but it didn't work last time,
852 // possibly because we hadn't enough CRTCs. Try again now that the
853 // output has a mode.
854 sway_log(SWAY_DEBUG, "Output %s has gained a CRTC, "
855 "trying to enable it", output->wlr_output->name);
856 apply_output_config(oc, output);
857 }
858 return;
859 }
860 if (!output->enabled) {
861 return;
862 }
863 arrange_layers(output);
864 arrange_output(output);
865 transaction_commit_dirty();
866
867 update_output_manager_config(output->server);
868 }
869
handle_transform(struct wl_listener * listener,void * data)870 static void handle_transform(struct wl_listener *listener, void *data) {
871 struct sway_output *output = wl_container_of(listener, output, transform);
872 if (!output->enabled) {
873 return;
874 }
875 arrange_layers(output);
876 arrange_output(output);
877 transaction_commit_dirty();
878
879 update_output_manager_config(output->server);
880 }
881
update_textures(struct sway_container * con,void * data)882 static void update_textures(struct sway_container *con, void *data) {
883 container_update_title_textures(con);
884 container_update_marks_textures(con);
885 }
886
handle_scale(struct wl_listener * listener,void * data)887 static void handle_scale(struct wl_listener *listener, void *data) {
888 struct sway_output *output = wl_container_of(listener, output, scale);
889 if (!output->enabled) {
890 return;
891 }
892 arrange_layers(output);
893 output_for_each_container(output, update_textures, NULL);
894 arrange_output(output);
895 transaction_commit_dirty();
896
897 update_output_manager_config(output->server);
898 }
899
handle_present(struct wl_listener * listener,void * data)900 static void handle_present(struct wl_listener *listener, void *data) {
901 struct sway_output *output = wl_container_of(listener, output, present);
902 struct wlr_output_event_present *output_event = data;
903
904 if (!output->enabled) {
905 return;
906 }
907
908 output->last_presentation = *output_event->when;
909 output->refresh_nsec = output_event->refresh;
910 }
911
handle_new_output(struct wl_listener * listener,void * data)912 void handle_new_output(struct wl_listener *listener, void *data) {
913 struct sway_server *server = wl_container_of(listener, server, new_output);
914 struct wlr_output *wlr_output = data;
915 sway_log(SWAY_DEBUG, "New output %p: %s", wlr_output, wlr_output->name);
916
917 struct sway_output *output = output_create(wlr_output);
918 if (!output) {
919 return;
920 }
921 output->server = server;
922 output->damage = wlr_output_damage_create(wlr_output);
923
924 wl_signal_add(&wlr_output->events.destroy, &output->destroy);
925 output->destroy.notify = handle_destroy;
926 wl_signal_add(&wlr_output->events.mode, &output->mode);
927 output->mode.notify = handle_mode;
928 wl_signal_add(&wlr_output->events.transform, &output->transform);
929 output->transform.notify = handle_transform;
930 wl_signal_add(&wlr_output->events.scale, &output->scale);
931 output->scale.notify = handle_scale;
932 wl_signal_add(&wlr_output->events.present, &output->present);
933 output->present.notify = handle_present;
934 wl_signal_add(&output->damage->events.frame, &output->damage_frame);
935 output->damage_frame.notify = damage_handle_frame;
936 wl_signal_add(&output->damage->events.destroy, &output->damage_destroy);
937 output->damage_destroy.notify = damage_handle_destroy;
938
939 output->repaint_timer = wl_event_loop_add_timer(server->wl_event_loop,
940 output_repaint_timer_handler, output);
941
942 struct output_config *oc = find_output_config(output);
943 apply_output_config(oc, output);
944 free_output_config(oc);
945
946 transaction_commit_dirty();
947
948 update_output_manager_config(server);
949 }
950
handle_output_layout_change(struct wl_listener * listener,void * data)951 void handle_output_layout_change(struct wl_listener *listener,
952 void *data) {
953 struct sway_server *server =
954 wl_container_of(listener, server, output_layout_change);
955 update_output_manager_config(server);
956 }
957
output_manager_apply(struct sway_server * server,struct wlr_output_configuration_v1 * config,bool test_only)958 static void output_manager_apply(struct sway_server *server,
959 struct wlr_output_configuration_v1 *config, bool test_only) {
960 // TODO: perform atomic tests on the whole backend atomically
961
962 struct wlr_output_configuration_head_v1 *config_head;
963 // First disable outputs we need to disable
964 bool ok = true;
965 wl_list_for_each(config_head, &config->heads, link) {
966 struct wlr_output *wlr_output = config_head->state.output;
967 struct sway_output *output = wlr_output->data;
968 if (!output->enabled || config_head->state.enabled) {
969 continue;
970 }
971 struct output_config *oc = new_output_config(output->wlr_output->name);
972 oc->enabled = false;
973
974 if (test_only) {
975 ok &= test_output_config(oc, output);
976 } else {
977 oc = store_output_config(oc);
978 ok &= apply_output_config(oc, output);
979 }
980 }
981
982 // Then enable outputs that need to
983 wl_list_for_each(config_head, &config->heads, link) {
984 struct wlr_output *wlr_output = config_head->state.output;
985 struct sway_output *output = wlr_output->data;
986 if (!config_head->state.enabled) {
987 continue;
988 }
989 struct output_config *oc = new_output_config(output->wlr_output->name);
990 oc->enabled = true;
991 if (config_head->state.mode != NULL) {
992 struct wlr_output_mode *mode = config_head->state.mode;
993 oc->width = mode->width;
994 oc->height = mode->height;
995 oc->refresh_rate = mode->refresh / 1000.f;
996 } else {
997 oc->width = config_head->state.custom_mode.width;
998 oc->height = config_head->state.custom_mode.height;
999 oc->refresh_rate = config_head->state.custom_mode.refresh;
1000 }
1001 oc->x = config_head->state.x;
1002 oc->y = config_head->state.y;
1003 oc->transform = config_head->state.transform;
1004 oc->scale = config_head->state.scale;
1005
1006 if (test_only) {
1007 ok &= test_output_config(oc, output);
1008 } else {
1009 oc = store_output_config(oc);
1010 ok &= apply_output_config(oc, output);
1011 }
1012 }
1013
1014 if (ok) {
1015 wlr_output_configuration_v1_send_succeeded(config);
1016 } else {
1017 wlr_output_configuration_v1_send_failed(config);
1018 }
1019 wlr_output_configuration_v1_destroy(config);
1020
1021 if (!test_only) {
1022 update_output_manager_config(server);
1023 }
1024 }
1025
handle_output_manager_apply(struct wl_listener * listener,void * data)1026 void handle_output_manager_apply(struct wl_listener *listener, void *data) {
1027 struct sway_server *server =
1028 wl_container_of(listener, server, output_manager_apply);
1029 struct wlr_output_configuration_v1 *config = data;
1030
1031 output_manager_apply(server, config, false);
1032 }
1033
handle_output_manager_test(struct wl_listener * listener,void * data)1034 void handle_output_manager_test(struct wl_listener *listener, void *data) {
1035 struct sway_server *server =
1036 wl_container_of(listener, server, output_manager_test);
1037 struct wlr_output_configuration_v1 *config = data;
1038
1039 output_manager_apply(server, config, true);
1040 }
1041
handle_output_power_manager_set_mode(struct wl_listener * listener,void * data)1042 void handle_output_power_manager_set_mode(struct wl_listener *listener,
1043 void *data) {
1044 struct wlr_output_power_v1_set_mode_event *event = data;
1045 struct sway_output *output = event->output->data;
1046
1047 struct output_config *oc = new_output_config(output->wlr_output->name);
1048 switch (event->mode) {
1049 case ZWLR_OUTPUT_POWER_V1_MODE_OFF:
1050 oc->dpms_state = DPMS_OFF;
1051 break;
1052 case ZWLR_OUTPUT_POWER_V1_MODE_ON:
1053 oc->dpms_state = DPMS_ON;
1054 break;
1055 }
1056 oc = store_output_config(oc);
1057 apply_output_config(oc, output);
1058 }
1059