|
|
|
@ -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);
|
|
|
|
@ -338,6 +355,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;
|
|
|
|
@ -378,6 +401,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;
|
|
|
|
|