From b9a07a67b85e9192faa0e285b4419bd5ef242a03 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Tue, 28 Sep 2021 14:34:34 -0700 Subject: feat: reorganized code to be more modular --- sys/cmd/wm/output.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 sys/cmd/wm/output.c (limited to 'sys/cmd/wm/output.c') diff --git a/sys/cmd/wm/output.c b/sys/cmd/wm/output.c new file mode 100644 index 0000000..3283c41 --- /dev/null +++ b/sys/cmd/wm/output.c @@ -0,0 +1,121 @@ +#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); +} + -- cgit v1.2.1