~goleo/wio

765b9bd99fb181078e15c553e0cbd57d2c0908ea — Drew DeVault 2 years ago 2e46c9d
Receive & render new XDG surfaces
6 files changed, 114 insertions(+), 1 deletions(-)

M include/server.h
A include/view.h
M main.c
M meson.build
M output.c
A view.c
M include/server.h => include/server.h +5 -0
@@ 10,6 10,7 @@
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_pointer.h>
#include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/types/wlr_xdg_shell.h>

struct wio_server {
	struct wl_display *wl_display;


@@ 20,11 21,13 @@ struct wio_server {
	struct wlr_renderer *renderer;
	struct wlr_seat *seat;
	struct wlr_xcursor_manager *cursor_mgr;
	struct wlr_xdg_shell *xdg_shell;

	struct wl_list outputs;
	struct wl_list inputs;
	struct wl_list pointers;
	struct wl_list keyboards;
	struct wl_list views;

	struct wl_listener new_output;
	struct wl_listener new_input;


@@ 32,6 35,8 @@ struct wio_server {
	struct wl_listener cursor_motion_absolute;
	struct wl_listener cursor_button;
	struct wl_listener cursor_axis;

	struct wl_listener new_xdg_surface;
};

struct wio_output {

A include/view.h => include/view.h +18 -0
@@ 0,0 1,18 @@
#ifndef _WIO_VIEW_H
#define _WIO_VIEW_H
#include <wlr/types/wlr_xdg_shell.h>
#include <wayland-server.h>

struct wio_server;

struct wio_view {
	int x, y;
	struct wlr_xdg_surface *xdg_surface;
	struct wio_server *server;
	struct wl_list link;
	struct wl_listener destroy;
};

void server_new_xdg_surface(struct wl_listener *listener, void *data);

#endif

M main.c => main.c +8 -0
@@ 8,8 8,10 @@
#include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_seat.h>
#include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/util/log.h>
#include "server.h"
#include "view.h"

int main(int argc, char **argv) {
	struct wio_server server;


@@ 56,6 58,12 @@ int main(int argc, char **argv) {
	wl_list_init(&server.keyboards);
	wl_list_init(&server.pointers);

	wl_list_init(&server.views);
	server.xdg_shell = wlr_xdg_shell_create(server.wl_display);
	server.new_xdg_surface.notify = server_new_xdg_surface;
	wl_signal_add(&server.xdg_shell->events.new_surface,
			&server.new_xdg_surface);

	const char *socket = wl_display_add_socket_auto(server.wl_display);
	if (!socket) {
		wlr_backend_destroy(server.backend);

M meson.build => meson.build +1 -0
@@ 34,6 34,7 @@ wio_sources = files(
	'main.c',
	'input.c',
	'output.c',
	'view.c',
)

executable(

M output.c => output.c +53 -1
@@ 2,10 2,47 @@
#include <stdlib.h>
#include <time.h>
#include <wayland-server.h>
#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_output.h>
#include <wlr/render/wlr_renderer.h>
#include "colors.h"
#include "server.h"
#include "view.h"

struct render_data {
	struct wlr_output *output;
	struct wlr_renderer *renderer;
	struct wio_view *view;
	struct timespec *when;
};

static void render_surface(struct wlr_surface *surface,
		int sx, int sy, void *data) {
	struct render_data *rdata = data;
	struct wio_view *view = rdata->view;
	struct wlr_output *output = rdata->output;
	struct wlr_texture *texture = wlr_surface_get_texture(surface);
	if (texture == NULL) {
		return;
	}
	double ox = 0, oy = 0;
	wlr_output_layout_output_coords(
			view->server->output_layout, output, &ox, &oy);
	ox += view->x + sx, oy += view->y + sy;
	struct wlr_box box = {
		.x = ox * output->scale,
		.y = oy * output->scale,
		.width = surface->current.width * output->scale,
		.height = surface->current.height * output->scale,
	};
	float matrix[9];
	enum wl_output_transform transform =
		wlr_output_transform_invert(surface->current.transform);
	wlr_matrix_project_box(matrix, &box, transform, 0,
		output->transform_matrix);
	wlr_render_texture_with_matrix(rdata->renderer, texture, matrix, 1);
	wlr_surface_send_frame_done(surface, rdata->when);
}

static void output_frame(struct wl_listener *listener, void *data) {
	struct wio_output *output = wl_container_of(listener, output, frame);


@@ 23,7 60,22 @@ static void output_frame(struct wl_listener *listener, void *data) {
	wlr_renderer_begin(renderer, width, height);

	wlr_renderer_clear(renderer, background);
	// TODO: other stuff

	struct wio_view *view;
	wl_list_for_each_reverse(view, &output->server->views, link) {
		if (!view->xdg_surface->mapped) {
			continue;
		}
		struct render_data rdata = {
			.output = output->wlr_output,
			.view = view,
			.renderer = renderer,
			.when = &now,
		};
		wlr_xdg_surface_for_each_surface(view->xdg_surface,
				render_surface, &rdata);
	}

	wlr_renderer_end(renderer);
	wlr_output_swap_buffers(output->wlr_output, NULL, NULL);
}

A view.c => view.c +29 -0
@@ 0,0 1,29 @@
#include <stdlib.h>
#include <wayland-server.h>
#include <wlr/types/wlr_xdg_shell.h>
#include "server.h"
#include "view.h"

static void xdg_surface_destroy(struct wl_listener *listener, void *data) {
	struct wio_view *view = wl_container_of(listener, view, destroy);
	wl_list_remove(&view->link);
	free(view);
}

void server_new_xdg_surface(struct wl_listener *listener, void *data) {
	struct wio_server *server = wl_container_of(
			listener, server, new_xdg_surface);
	struct wlr_xdg_surface *xdg_surface = data;
	if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
		return;
	}

	struct wio_view *view = calloc(1, sizeof(struct wio_view));
	view->server = server;
	view->xdg_surface = xdg_surface;

	view->destroy.notify = xdg_surface_destroy;
	wl_signal_add(&xdg_surface->events.destroy, &view->destroy);

	wl_list_insert(&server->views, &view->link);
}