aboutsummaryrefslogtreecommitdiff
path: root/sway/desktop/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r--sway/desktop/output.c87
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;