#include "wm.h" typedef struct Payload Payload; struct Payload { Client *client; struct wlr_output *output; struct wlr_renderer *renderer; struct timespec *when; }; static void draw(struct wlr_surface *surface, int sx, int sy, void *data) { float matrix[9]; double ox, oy; Client *client; Payload *payload; struct wlr_box box; struct wlr_output *output; struct wlr_texture *texture; enum wl_output_transform transform; payload = data; client = payload->client; output = payload->output; texture = wlr_surface_get_texture(surface); if(!texture) return; ox = 0, oy = 0; wlr_output_layout_output_coords(server.output.layout, output, &ox, &oy); ox += client->x + sx, oy += client->y + sy; box = (struct wlr_box){ .x = ox * output->scale, .y = oy * output->scale, .width = surface->current.width * output->scale, .height = surface->current.height * output->scale, }; transform = wlr_output_transform_invert(surface->current.transform); wlr_matrix_project_box(matrix, &box, transform, 0, output->transform_matrix); wlr_render_texture_with_matrix(payload->renderer, texture, matrix, 1); wlr_surface_send_frame_done(surface, payload->when); } static void render(struct wl_listener *l, void *data) { int width, height; struct timespec now; Client *client; Monitor *monitor; struct wlr_renderer *renderer; float color[4] = {0.3, 0.3, 0.3, 1.0}; monitor = wl_container_of(l, monitor, event.render); renderer = server.renderer; clock_gettime(CLOCK_MONOTONIC, &now); if(!wlr_output_attach_render(monitor->output, nil)) return; wlr_output_effective_resolution(monitor->output, &width, &height); /* start of rendering kernel */ wlr_renderer_begin(renderer, width, height); wlr_renderer_clear(renderer, color); wl_list_for_each_reverse(client, &server.clients, link) { if(!client->mapped) continue; Payload payload = { .output = monitor->output, .client = client, .renderer = renderer, .when = &now, }; wlr_xdg_surface_for_each_surface(client->xdg, draw, &payload); } wlr_output_render_software_cursors(monitor->output, nil); wlr_renderer_end(renderer); wlr_output_commit(monitor->output); } void make_output(struct wl_listener *l, void *data) { struct wlr_output_mode *mode; struct Monitor *monitor; struct wlr_output *output = data; if (!wl_list_empty(&output->modes)) { mode = wlr_output_preferred_mode(output); wlr_output_set_mode(output, mode); wlr_output_enable(output, true); if (!wlr_output_commit(output)) { return; } } monitor = calloc(1, sizeof(*monitor)); monitor->output = output; monitor->event.render.notify = render; wl_signal_add(&output->events.frame, &monitor->event.render); wl_list_insert(&server.output.list, &monitor->link); wlr_output_layout_add_auto(server.output.layout, output); }