aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/wm/render.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/wm/render.c')
-rw-r--r--src/cmd/wm/render.c160
1 files changed, 160 insertions, 0 deletions
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);
+}