diff options
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r-- | sway/desktop/output.c | 73 |
1 files changed, 49 insertions, 24 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 0d706c52..6c97ac37 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -39,6 +39,32 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh, | |||
39 | } | 39 | } |
40 | } | 40 | } |
41 | 41 | ||
42 | /** | ||
43 | * Checks whether a surface at (lx, ly) intersects an output. If `box` is not | ||
44 | * NULL, it populates it with the surface box in the output, in output-local | ||
45 | * coordinates. | ||
46 | */ | ||
47 | static bool surface_intersect_output(struct wlr_surface *surface, | ||
48 | struct wlr_output_layout *output_layout, struct wlr_output *wlr_output, | ||
49 | double lx, double ly, float rotation, struct wlr_box *box) { | ||
50 | double ox = lx, oy = ly; | ||
51 | wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy); | ||
52 | |||
53 | if (box != NULL) { | ||
54 | box->x = ox * wlr_output->scale; | ||
55 | box->y = oy * wlr_output->scale; | ||
56 | box->width = surface->current->width * wlr_output->scale; | ||
57 | box->height = surface->current->height * wlr_output->scale; | ||
58 | } | ||
59 | |||
60 | struct wlr_box layout_box = { | ||
61 | .x = lx, .y = ly, | ||
62 | .width = surface->current->width, .height = surface->current->height, | ||
63 | }; | ||
64 | wlr_box_rotated_bounds(&layout_box, rotation, &layout_box); | ||
65 | return wlr_output_layout_intersects(output_layout, wlr_output, &layout_box); | ||
66 | } | ||
67 | |||
42 | static void render_surface(struct wlr_surface *surface, | 68 | static void render_surface(struct wlr_surface *surface, |
43 | struct wlr_output *wlr_output, struct timespec *when, | 69 | struct wlr_output *wlr_output, struct timespec *when, |
44 | double lx, double ly, float rotation) { | 70 | double lx, double ly, float rotation) { |
@@ -48,29 +74,21 @@ static void render_surface(struct wlr_surface *surface, | |||
48 | if (!wlr_surface_has_buffer(surface)) { | 74 | if (!wlr_surface_has_buffer(surface)) { |
49 | return; | 75 | return; |
50 | } | 76 | } |
77 | |||
51 | struct wlr_output_layout *layout = root_container.sway_root->output_layout; | 78 | struct wlr_output_layout *layout = root_container.sway_root->output_layout; |
52 | int width = surface->current->width; | 79 | |
53 | int height = surface->current->height; | 80 | struct wlr_box box; |
54 | int render_width = width * wlr_output->scale; | 81 | bool intersects = surface_intersect_output(surface, layout, wlr_output, |
55 | int render_height = height * wlr_output->scale; | 82 | lx, ly, rotation, &box); |
56 | int owidth, oheight; | 83 | if (intersects) { |
57 | wlr_output_effective_resolution(wlr_output, &owidth, &oheight); | ||
58 | |||
59 | // FIXME: view coords are inconsistently assumed to be in output or layout coords | ||
60 | struct wlr_box layout_box = { | ||
61 | .x = lx + wlr_output->lx, .y = ly + wlr_output->ly, | ||
62 | .width = render_width, .height = render_height, | ||
63 | }; | ||
64 | if (wlr_output_layout_intersects(layout, wlr_output, &layout_box)) { | ||
65 | struct wlr_box render_box = { | ||
66 | .x = lx, .y = ly, | ||
67 | .width = render_width, .height = render_height | ||
68 | }; | ||
69 | float matrix[9]; | 84 | float matrix[9]; |
70 | wlr_matrix_project_box(matrix, &render_box, surface->current->transform, | 85 | enum wl_output_transform transform = |
71 | 0, wlr_output->transform_matrix); | 86 | wlr_output_transform_invert(surface->current->transform); |
72 | wlr_render_texture_with_matrix(renderer, surface->texture, matrix, | 87 | wlr_matrix_project_box(matrix, &box, transform, rotation, |
73 | 1.0f); // TODO: configurable alpha | 88 | wlr_output->transform_matrix); |
89 | |||
90 | // TODO: configurable alpha | ||
91 | wlr_render_texture_with_matrix(renderer, surface->texture, matrix, 1.0f); | ||
74 | 92 | ||
75 | wlr_surface_send_frame_done(surface, when); | 93 | wlr_surface_send_frame_done(surface, when); |
76 | } | 94 | } |
@@ -80,9 +98,8 @@ static void render_surface(struct wlr_surface *surface, | |||
80 | struct wlr_surface_state *state = subsurface->surface->current; | 98 | struct wlr_surface_state *state = subsurface->surface->current; |
81 | double sx = state->subsurface_position.x; | 99 | double sx = state->subsurface_position.x; |
82 | double sy = state->subsurface_position.y; | 100 | double sy = state->subsurface_position.y; |
83 | double sw = state->buffer_width / state->scale; | 101 | rotate_child_position(&sx, &sy, state->width, state->height, |
84 | double sh = state->buffer_height / state->scale; | 102 | surface->current->width, surface->current->height, rotation); |
85 | rotate_child_position(&sx, &sy, sw, sh, width, height, rotation); | ||
86 | 103 | ||
87 | render_surface(subsurface->surface, wlr_output, when, | 104 | render_surface(subsurface->surface, wlr_output, when, |
88 | lx + sx, ly + sy, rotation); | 105 | lx + sx, ly + sy, rotation); |
@@ -338,6 +355,12 @@ static void handle_transform(struct wl_listener *listener, void *data) { | |||
338 | arrange_windows(output->swayc, -1, -1); | 355 | arrange_windows(output->swayc, -1, -1); |
339 | } | 356 | } |
340 | 357 | ||
358 | static void handle_scale(struct wl_listener *listener, void *data) { | ||
359 | struct sway_output *output = wl_container_of(listener, output, scale); | ||
360 | arrange_layers(output); | ||
361 | arrange_windows(output->swayc, -1, -1); | ||
362 | } | ||
363 | |||
341 | void handle_new_output(struct wl_listener *listener, void *data) { | 364 | void handle_new_output(struct wl_listener *listener, void *data) { |
342 | struct sway_server *server = wl_container_of(listener, server, new_output); | 365 | struct sway_server *server = wl_container_of(listener, server, new_output); |
343 | struct wlr_output *wlr_output = data; | 366 | struct wlr_output *wlr_output = data; |
@@ -378,6 +401,8 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
378 | output->mode.notify = handle_mode; | 401 | output->mode.notify = handle_mode; |
379 | wl_signal_add(&wlr_output->events.transform, &output->transform); | 402 | wl_signal_add(&wlr_output->events.transform, &output->transform); |
380 | output->transform.notify = handle_transform; | 403 | output->transform.notify = handle_transform; |
404 | wl_signal_add(&wlr_output->events.scale, &output->scale); | ||
405 | output->scale.notify = handle_scale; | ||
381 | 406 | ||
382 | wl_signal_add(&output->damage->events.frame, &output->damage_frame); | 407 | wl_signal_add(&output->damage->events.frame, &output->damage_frame); |
383 | output->damage_frame.notify = damage_handle_frame; | 408 | output->damage_frame.notify = damage_handle_frame; |