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