aboutsummaryrefslogtreecommitdiffstats
path: root/sway/desktop/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r--sway/desktop/output.c175
1 files changed, 55 insertions, 120 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 5edc8f96..8cdd47f5 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -4,9 +4,10 @@
4#include <strings.h> 4#include <strings.h>
5#include <time.h> 5#include <time.h>
6#include <wayland-server-core.h> 6#include <wayland-server-core.h>
7#include <wlr/backend/drm.h>
7#include <wlr/render/wlr_renderer.h> 8#include <wlr/render/wlr_renderer.h>
8#include <wlr/types/wlr_box.h>
9#include <wlr/types/wlr_buffer.h> 9#include <wlr/types/wlr_buffer.h>
10#include <wlr/types/wlr_drm_lease_v1.h>
10#include <wlr/types/wlr_matrix.h> 11#include <wlr/types/wlr_matrix.h>
11#include <wlr/types/wlr_output_damage.h> 12#include <wlr/types/wlr_output_damage.h>
12#include <wlr/types/wlr_output_layout.h> 13#include <wlr/types/wlr_output_layout.h>
@@ -56,26 +57,6 @@ struct sway_output *all_output_by_name_or_id(const char *name_or_id) {
56 return NULL; 57 return NULL;
57} 58}
58 59
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 */
63static 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
79struct surface_iterator_data { 60struct surface_iterator_data {
80 sway_surface_iterator_func_t user_iterator; 61 sway_surface_iterator_func_t user_iterator;
81 void *user_data; 62 void *user_data;
@@ -84,7 +65,6 @@ struct surface_iterator_data {
84 struct sway_view *view; 65 struct sway_view *view;
85 double ox, oy; 66 double ox, oy;
86 int width, height; 67 int width, height;
87 float rotation;
88}; 68};
89 69
90static bool get_surface_box(struct surface_iterator_data *data, 70static bool get_surface_box(struct surface_iterator_data *data,
@@ -99,14 +79,9 @@ static bool get_surface_box(struct surface_iterator_data *data,
99 int sw = surface->current.width; 79 int sw = surface->current.width;
100 int sh = surface->current.height; 80 int sh = surface->current.height;
101 81
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 = { 82 struct wlr_box box = {
108 .x = data->ox + _sx, 83 .x = floor(data->ox + sx),
109 .y = data->oy + _sy, 84 .y = floor(data->oy + sy),
110 .width = sw, 85 .width = sw,
111 .height = sh, 86 .height = sh,
112 }; 87 };
@@ -114,16 +89,13 @@ static bool get_surface_box(struct surface_iterator_data *data,
114 memcpy(surface_box, &box, sizeof(struct wlr_box)); 89 memcpy(surface_box, &box, sizeof(struct wlr_box));
115 } 90 }
116 91
117 struct wlr_box rotated_box;
118 wlr_box_rotated_bounds(&rotated_box, &box, data->rotation);
119
120 struct wlr_box output_box = { 92 struct wlr_box output_box = {
121 .width = output->width, 93 .width = output->width,
122 .height = output->height, 94 .height = output->height,
123 }; 95 };
124 96
125 struct wlr_box intersection; 97 struct wlr_box intersection;
126 return wlr_box_intersection(&intersection, &output_box, &rotated_box); 98 return wlr_box_intersection(&intersection, &output_box, &box);
127} 99}
128 100
129static void output_for_each_surface_iterator(struct wlr_surface *surface, 101static void output_for_each_surface_iterator(struct wlr_surface *surface,
@@ -136,7 +108,7 @@ static void output_for_each_surface_iterator(struct wlr_surface *surface,
136 return; 108 return;
137 } 109 }
138 110
139 data->user_iterator(data->output, data->view, surface, &box, data->rotation, 111 data->user_iterator(data->output, data->view, surface, &box,
140 data->user_data); 112 data->user_data);
141} 113}
142 114
@@ -152,7 +124,6 @@ void output_surface_for_each_surface(struct sway_output *output,
152 .oy = oy, 124 .oy = oy,
153 .width = surface->current.width, 125 .width = surface->current.width,
154 .height = surface->current.height, 126 .height = surface->current.height,
155 .rotation = 0,
156 }; 127 };
157 128
158 wlr_surface_for_each_surface(surface, 129 wlr_surface_for_each_surface(surface,
@@ -173,7 +144,6 @@ void output_view_for_each_surface(struct sway_output *output,
173 - view->geometry.y, 144 - view->geometry.y,
174 .width = view->container->current.content_width, 145 .width = view->container->current.content_width,
175 .height = view->container->current.content_height, 146 .height = view->container->current.content_height,
176 .rotation = 0, // TODO
177 }; 147 };
178 148
179 view_for_each_surface(view, output_for_each_surface_iterator, &data); 149 view_for_each_surface(view, output_for_each_surface_iterator, &data);
@@ -193,7 +163,6 @@ void output_view_for_each_popup_surface(struct sway_output *output,
193 - view->geometry.y, 163 - view->geometry.y,
194 .width = view->container->current.content_width, 164 .width = view->container->current.content_width,
195 .height = view->container->current.content_height, 165 .height = view->container->current.content_height,
196 .rotation = 0, // TODO
197 }; 166 };
198 167
199 view_for_each_popup_surface(view, output_for_each_surface_iterator, &data); 168 view_for_each_popup_surface(view, output_for_each_surface_iterator, &data);
@@ -206,40 +175,19 @@ void output_layer_for_each_surface(struct sway_output *output,
206 wl_list_for_each(layer_surface, layer_surfaces, link) { 175 wl_list_for_each(layer_surface, layer_surfaces, link) {
207 struct wlr_layer_surface_v1 *wlr_layer_surface_v1 = 176 struct wlr_layer_surface_v1 *wlr_layer_surface_v1 =
208 layer_surface->layer_surface; 177 layer_surface->layer_surface;
209 output_surface_for_each_surface(output, wlr_layer_surface_v1->surface, 178 struct wlr_surface *surface = wlr_layer_surface_v1->surface;
210 layer_surface->geo.x, layer_surface->geo.y, iterator, 179 struct surface_iterator_data data = {
211 user_data); 180 .user_iterator = iterator,
212 181 .user_data = user_data,
213 struct wlr_xdg_popup *state; 182 .output = output,
214 wl_list_for_each(state, &wlr_layer_surface_v1->popups, link) { 183 .view = NULL,
215 struct wlr_xdg_surface *popup = state->base; 184 .ox = layer_surface->geo.x,
216 if (!popup->configured) { 185 .oy = layer_surface->geo.y,
217 continue; 186 .width = surface->current.width,
218 } 187 .height = surface->current.height,
219 188 };
220 double popup_sx, popup_sy; 189 wlr_layer_surface_v1_for_each_surface(wlr_layer_surface_v1,
221 popup_sx = layer_surface->geo.x + 190 output_for_each_surface_iterator, &data);
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 } 191 }
244} 192}
245 193
@@ -264,37 +212,19 @@ void output_layer_for_each_popup_surface(struct sway_output *output,
264 wl_list_for_each(layer_surface, layer_surfaces, link) { 212 wl_list_for_each(layer_surface, layer_surfaces, link) {
265 struct wlr_layer_surface_v1 *wlr_layer_surface_v1 = 213 struct wlr_layer_surface_v1 *wlr_layer_surface_v1 =
266 layer_surface->layer_surface; 214 layer_surface->layer_surface;
267 215 struct wlr_surface *surface = wlr_layer_surface_v1->surface;
268 struct wlr_xdg_popup *state; 216 struct surface_iterator_data data = {
269 wl_list_for_each(state, &wlr_layer_surface_v1->popups, link) { 217 .user_iterator = iterator,
270 struct wlr_xdg_surface *popup = state->base; 218 .user_data = user_data,
271 if (!popup->configured) { 219 .output = output,
272 continue; 220 .view = NULL,
273 } 221 .ox = layer_surface->geo.x,
274 222 .oy = layer_surface->geo.y,
275 double popup_sx, popup_sy; 223 .width = surface->current.width,
276 popup_sx = layer_surface->geo.x + 224 .height = surface->current.height,
277 popup->popup->geometry.x - popup->geometry.x; 225 };
278 popup_sy = layer_surface->geo.y + 226 wlr_layer_surface_v1_for_each_popup_surface(wlr_layer_surface_v1,
279 popup->popup->geometry.y - popup->geometry.y; 227 output_for_each_surface_iterator, &data);
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 } 228 }
299} 229}
300 230
@@ -463,9 +393,9 @@ struct send_frame_done_data {
463 int msec_until_refresh; 393 int msec_until_refresh;
464}; 394};
465 395
466static void send_frame_done_iterator(struct sway_output *output, struct sway_view *view, 396static void send_frame_done_iterator(struct sway_output *output,
467 struct wlr_surface *surface, struct wlr_box *box, float rotation, 397 struct sway_view *view, struct wlr_surface *surface,
468 void *user_data) { 398 struct wlr_box *box, void *user_data) {
469 int view_max_render_time = 0; 399 int view_max_render_time = 0;
470 if (view != NULL) { 400 if (view != NULL) {
471 view_max_render_time = view->max_render_time; 401 view_max_render_time = view->max_render_time;
@@ -488,9 +418,9 @@ static void send_frame_done(struct sway_output *output, struct send_frame_done_d
488 output_for_each_surface(output, send_frame_done_iterator, data); 418 output_for_each_surface(output, send_frame_done_iterator, data);
489} 419}
490 420
491static void count_surface_iterator(struct sway_output *output, struct sway_view *view, 421static void count_surface_iterator(struct sway_output *output,
492 struct wlr_surface *surface, struct wlr_box *_box, float rotation, 422 struct sway_view *view, struct wlr_surface *surface,
493 void *data) { 423 struct wlr_box *box, void *data) {
494 size_t *n = data; 424 size_t *n = data;
495 (*n)++; 425 (*n)++;
496} 426}
@@ -577,7 +507,7 @@ static int output_repaint_timer_handler(void *data) {
577 fullscreen_con = workspace->current.fullscreen; 507 fullscreen_con = workspace->current.fullscreen;
578 } 508 }
579 509
580 if (fullscreen_con && fullscreen_con->view) { 510 if (fullscreen_con && fullscreen_con->view && !debug.noscanout) {
581 // Try to scan-out the fullscreen view 511 // Try to scan-out the fullscreen view
582 static bool last_scanned_out = false; 512 static bool last_scanned_out = false;
583 bool scanned_out = 513 bool scanned_out =
@@ -590,6 +520,7 @@ static int output_repaint_timer_handler(void *data) {
590 if (last_scanned_out && !scanned_out) { 520 if (last_scanned_out && !scanned_out) {
591 sway_log(SWAY_DEBUG, "Stopping fullscreen view scan out on %s", 521 sway_log(SWAY_DEBUG, "Stopping fullscreen view scan out on %s",
592 output->wlr_output->name); 522 output->wlr_output->name);
523 output_damage_whole(output);
593 } 524 }
594 last_scanned_out = scanned_out; 525 last_scanned_out = scanned_out;
595 526
@@ -693,18 +624,15 @@ void output_damage_whole(struct sway_output *output) {
693 } 624 }
694} 625}
695 626
696static void damage_surface_iterator(struct sway_output *output, struct sway_view *view, 627static void damage_surface_iterator(struct sway_output *output,
697 struct wlr_surface *surface, struct wlr_box *_box, float rotation, 628 struct sway_view *view, struct wlr_surface *surface,
698 void *_data) { 629 struct wlr_box *_box, void *_data) {
699 bool *data = _data; 630 bool *data = _data;
700 bool whole = *data; 631 bool whole = *data;
701 632
702 struct wlr_box box = *_box; 633 struct wlr_box box = *_box;
703 scale_box(&box, output->wlr_output->scale); 634 scale_box(&box, output->wlr_output->scale);
704 635
705 int center_x = box.x + box.width/2;
706 int center_y = box.y + box.height/2;
707
708 if (pixman_region32_not_empty(&surface->buffer_damage)) { 636 if (pixman_region32_not_empty(&surface->buffer_damage)) {
709 pixman_region32_t damage; 637 pixman_region32_t damage;
710 pixman_region32_init(&damage); 638 pixman_region32_init(&damage);
@@ -717,14 +645,11 @@ static void damage_surface_iterator(struct sway_output *output, struct sway_view
717 ceil(output->wlr_output->scale) - surface->current.scale); 645 ceil(output->wlr_output->scale) - surface->current.scale);
718 } 646 }
719 pixman_region32_translate(&damage, box.x, box.y); 647 pixman_region32_translate(&damage, box.x, box.y);
720 wlr_region_rotated_bounds(&damage, &damage, rotation,
721 center_x, center_y);
722 wlr_output_damage_add(output->damage, &damage); 648 wlr_output_damage_add(output->damage, &damage);
723 pixman_region32_fini(&damage); 649 pixman_region32_fini(&damage);
724 } 650 }
725 651
726 if (whole) { 652 if (whole) {
727 wlr_box_rotated_bounds(&box, &box, rotation);
728 wlr_output_damage_add_box(output->damage, &box); 653 wlr_output_damage_add_box(output->damage, &box);
729 } 654 }
730 655
@@ -816,7 +741,7 @@ static void update_output_manager_config(struct sway_server *server) {
816 struct wlr_box *output_box = wlr_output_layout_get_box( 741 struct wlr_box *output_box = wlr_output_layout_get_box(
817 root->output_layout, output->wlr_output); 742 root->output_layout, output->wlr_output);
818 // We mark the output enabled even if it is switched off by DPMS 743 // We mark the output enabled even if it is switched off by DPMS
819 config_head->state.enabled = output->enabled; 744 config_head->state.enabled = output->current_mode != NULL && output->enabled;
820 config_head->state.mode = output->current_mode; 745 config_head->state.mode = output->current_mode;
821 if (output_box) { 746 if (output_box) {
822 config_head->state.x = output_box->x; 747 config_head->state.x = output_box->x;
@@ -913,7 +838,17 @@ static void handle_present(struct wl_listener *listener, void *data) {
913void handle_new_output(struct wl_listener *listener, void *data) { 838void handle_new_output(struct wl_listener *listener, void *data) {
914 struct sway_server *server = wl_container_of(listener, server, new_output); 839 struct sway_server *server = wl_container_of(listener, server, new_output);
915 struct wlr_output *wlr_output = data; 840 struct wlr_output *wlr_output = data;
916 sway_log(SWAY_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); 841 sway_log(SWAY_DEBUG, "New output %p: %s (non-desktop: %d)",
842 wlr_output, wlr_output->name, wlr_output->non_desktop);
843
844 if (wlr_output->non_desktop) {
845 sway_log(SWAY_DEBUG, "Not configuring non-desktop output");
846 if (server->drm_lease_manager) {
847 wlr_drm_lease_v1_manager_offer_output(server->drm_lease_manager,
848 wlr_output);
849 }
850 return;
851 }
917 852
918 struct sway_output *output = output_create(wlr_output); 853 struct sway_output *output = output_create(wlr_output);
919 if (!output) { 854 if (!output) {