From ce05175372a9ddca1a225db0765ace1127a39293 Mon Sep 17 00:00:00 2001 From: Nicholas Date: Fri, 12 Nov 2021 09:22:01 -0800 Subject: chore: simplified organizational structure --- src/cmd/wm/render.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 src/cmd/wm/render.c (limited to 'src/cmd/wm/render.c') diff --git a/src/cmd/wm/render.c b/src/cmd/wm/render.c new file mode 100644 index 0000000..1f51804 --- /dev/null +++ b/src/cmd/wm/render.c @@ -0,0 +1,160 @@ +#include "wm.h" + +struct Payload +{ + Client *client; + struct wlr_output *output; + struct timespec *when; + int x, y; +}; + +static +void +render(struct wlr_surface *surface, int sx, int sy, void *data) +{ + float matrix[9]; + double x, y; + struct Payload *payload; + + struct wlr_box box; + struct wlr_output *output; + struct wlr_texture *texture; + + enum wl_output_transform transform; + + payload = data; + output = payload->output; + + texture = wlr_surface_get_texture(surface); + if(!texture) + return; + + x = 0, y = 0; + wlr_output_layout_output_coords(server.monitor.layout, output, &x, &y); + + box = (struct wlr_box) { + .x = x + payload->x + sx, + .y = y + payload->y + sy, + .width = surface->current.width, + .height = surface->current.height, + }; + scale_box(&box, 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(server.renderer, texture, matrix, 1); + wlr_surface_send_frame_done(surface, payload->when); + wlr_presentation_surface_sampled_on_output(server.present, surface, output); +} + +static +void +render_layer(struct wl_list *list, struct timespec *now) +{ + Layer *layer; + wl_list_for_each(layer, list, link) { + struct Payload payload= { + .output = layer->surface->output, + .x = layer->geometry.x, + .y = layer->geometry.y, + .when = now, + }; + + wlr_surface_for_each_surface(layer->surface->surface, render, &payload); + } +} + +static +void +render_clients(Monitor *monitor, struct timespec *now) +{ + double x, y; + int i, w, h, bw; + float *color; + + Client *client; + struct wlr_output *output; + struct wlr_box *borders; + struct wlr_surface *surface; + + output = monitor->output; + wl_list_for_each_reverse(client, &server.client.stack, stack) { + if(!VISIBLE_ON(client, client->monitor)) + continue; + if(!wlr_output_layout_intersects(server.monitor.layout, monitor->output, &client->geometry)) + continue; + + surface = client->xdg->surface; + + x = client->geometry.x, y = client->geometry.y; + wlr_output_layout_output_coords(server.monitor.layout, output, &x, &y); + + if((bw=client->border)) { + w = surface->current.width; + h = surface->current.height; + borders = (struct wlr_box[4]) { + {x, y, w+2*bw, bw}, /* top */ + {x, y+bw, bw, h}, /* left */ + {x+bw+w, y+bw, bw, h}, /* right */ + {x, y+bw+h, w+2*bw, bw}, /* bottom */ + }; + + color = (client == server.selected) ? cfg·focuscolor : cfg·bordercolor; + for(i=0; i<4; i++) { + scale_box(&borders[i], output->scale); + wlr_render_rect(server.renderer, &borders[i], color, output->transform_matrix); + } + } + + struct Payload payload = { + .output = output, + .when = now, + + .x = client->geometry.x + client->border, + .y = client->geometry.y + client->border, + }; + + wlr_xdg_surface_for_each_surface(client->xdg, render, &payload); + } +} + +void +render_monitor(struct wl_listener *l, void *data) +{ + int w, h; + Client *client; + Monitor *monitor; + struct timespec now; + + clock_gettime(CLOCK_MONOTONIC, &now); + monitor = wl_container_of(l, monitor, event.render); + + wl_list_for_each(client, &server.client.list, link) { + if(client->resize) { + wlr_surface_send_frame_done(client->xdg->surface, &now); + } + } + + if(!wlr_output_attach_render(monitor->output, nil)) + return; + + wlr_output_effective_resolution(monitor->output, &w, &h); + + /* start of rendering kernel */ + wlr_renderer_begin(server.renderer, w, h); + wlr_renderer_clear(server.renderer, cfg·rootcolor); + + render_layer(&monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &now); + render_layer(&monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &now); + + render_clients(monitor, &now); + + render_layer(&monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &now); + render_layer(&monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &now); + + wlr_output_render_software_cursors(monitor->output, nil); + + wlr_renderer_end(server.renderer); + wlr_output_commit(monitor->output); +} -- cgit v1.2.1