diff options
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r-- | sway/desktop/output.c | 87 |
1 files changed, 56 insertions, 31 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 5e8a081c..10ed1f6d 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, } } +/** + * Checks whether a surface at (lx, ly) intersects an output. If `box` is not + * NULL, it populates it with the surface box in the output, in output-local + * coordinates. + */ +static bool surface_intersect_output(struct wlr_surface *surface, + struct wlr_output_layout *output_layout, struct wlr_output *wlr_output, + double lx, double ly, float rotation, struct wlr_box *box) { + double ox = lx, oy = ly; + wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy); + + if (box != NULL) { + box->x = ox * wlr_output->scale; + box->y = oy * wlr_output->scale; + box->width = surface->current->width * wlr_output->scale; + box->height = surface->current->height * wlr_output->scale; + } + + struct wlr_box layout_box = { + .x = lx, .y = ly, + .width = surface->current->width, .height = surface->current->height, + }; + wlr_box_rotated_bounds(&layout_box, rotation, &layout_box); + return wlr_output_layout_intersects(output_layout, wlr_output, &layout_box); +} + static void render_surface(struct wlr_surface *surface, struct wlr_output *wlr_output, struct timespec *when, double lx, double ly, float rotation) { @@ -48,29 +74,21 @@ static void render_surface(struct wlr_surface *surface, if (!wlr_surface_has_buffer(surface)) { return; } + struct wlr_output_layout *layout = root_container.sway_root->output_layout; - int width = surface->current->width; - int height = surface->current->height; - int render_width = width * wlr_output->scale; - int render_height = height * wlr_output->scale; - int owidth, oheight; - wlr_output_effective_resolution(wlr_output, &owidth, &oheight); - - // FIXME: view coords are inconsistently assumed to be in output or layout coords - struct wlr_box layout_box = { - .x = lx + wlr_output->lx, .y = ly + wlr_output->ly, - .width = render_width, .height = render_height, - }; - if (wlr_output_layout_intersects(layout, wlr_output, &layout_box)) { - struct wlr_box render_box = { - .x = lx, .y = ly, - .width = render_width, .height = render_height - }; + + struct wlr_box box; + bool intersects = surface_intersect_output(surface, layout, wlr_output, + lx, ly, rotation, &box); + if (intersects) { float matrix[9]; - wlr_matrix_project_box(matrix, &render_box, surface->current->transform, - 0, wlr_output->transform_matrix); - wlr_render_texture_with_matrix(renderer, surface->texture, matrix, - 1.0f); // TODO: configurable alpha + enum wl_output_transform transform = + wlr_output_transform_invert(surface->current->transform); + wlr_matrix_project_box(matrix, &box, transform, rotation, + wlr_output->transform_matrix); + + // TODO: configurable alpha + wlr_render_texture_with_matrix(renderer, surface->texture, matrix, 1.0f); wlr_surface_send_frame_done(surface, when); } @@ -80,9 +98,8 @@ static void render_surface(struct wlr_surface *surface, struct wlr_surface_state *state = subsurface->surface->current; double sx = state->subsurface_position.x; double sy = state->subsurface_position.y; - double sw = state->buffer_width / state->scale; - double sh = state->buffer_height / state->scale; - rotate_child_position(&sx, &sy, sw, sh, width, height, rotation); + rotate_child_position(&sx, &sy, state->width, state->height, + surface->current->width, surface->current->height, rotation); render_surface(subsurface->surface, wlr_output, when, lx + sx, ly + sy, rotation); @@ -243,15 +260,15 @@ static void render_output(struct sway_output *output, struct timespec *when, container_descendants(workspace, C_VIEW, render_view, &rdata); // render unmanaged views on top - struct sway_view *view; - wl_list_for_each(view, &root_container.sway_root->unmanaged_views, - unmanaged_view_link) { - if (view->type != SWAY_XWAYLAND_VIEW) { + struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; + struct sway_xwayland_unmanaged *sway_surface; + wl_list_for_each(sway_surface, unmanaged, link) { + struct wlr_xwayland_surface *xsurface = + sway_surface->wlr_xwayland_surface; + if (xsurface->surface == NULL) { continue; } - struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; - const struct wlr_box view_box = { .x = xsurface->x, .y = xsurface->y, @@ -263,7 +280,7 @@ static void render_output(struct sway_output *output, struct timespec *when, continue; } - render_surface(view->surface, wlr_output, &output->last_frame, + render_surface(xsurface->surface, wlr_output, &output->last_frame, view_box.x - output_box->x, view_box.y - output_box->y, 0); } @@ -341,6 +358,12 @@ static void handle_transform(struct wl_listener *listener, void *data) { arrange_windows(output->swayc, -1, -1); } +static void handle_scale(struct wl_listener *listener, void *data) { + struct sway_output *output = wl_container_of(listener, output, scale); + arrange_layers(output); + arrange_windows(output->swayc, -1, -1); +} + void handle_new_output(struct wl_listener *listener, void *data) { struct sway_server *server = wl_container_of(listener, server, new_output); struct wlr_output *wlr_output = data; @@ -381,6 +404,8 @@ void handle_new_output(struct wl_listener *listener, void *data) { output->mode.notify = handle_mode; wl_signal_add(&wlr_output->events.transform, &output->transform); output->transform.notify = handle_transform; + wl_signal_add(&wlr_output->events.scale, &output->scale); + output->scale.notify = handle_scale; wl_signal_add(&output->damage->events.frame, &output->damage_frame); output->damage_frame.notify = damage_handle_frame; |