From b6d7c3ed8ec6ae29af5d585db5417394ff49f3c7 Mon Sep 17 00:00:00 2001
From: Drew DeVault <sir@cmpwn.com>
Date: Sat, 23 Sep 2017 00:29:53 -0400
Subject: Initialize display, backend; add frame handling

---
 rootston/desktop.c   |  59 ++++++++++++++++++++++++++++++
 rootston/main.c      |  41 ++++++++++++++++++---
 rootston/meson.build |   6 ++-
 rootston/output.c    | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 200 insertions(+), 7 deletions(-)
 create mode 100644 rootston/desktop.c
 create mode 100644 rootston/output.c

(limited to 'rootston')

diff --git a/rootston/desktop.c b/rootston/desktop.c
new file mode 100644
index 00000000..551d289a
--- /dev/null
+++ b/rootston/desktop.c
@@ -0,0 +1,59 @@
+#define _POSIX_C_SOURCE 199309L
+#include <time.h>
+#include <stdlib.h>
+#include <wlr/types/wlr_output_layout.h>
+#include <wlr/types/wlr_compositor.h>
+#include <wlr/types/wlr_wl_shell.h>
+#include <wlr/types/wlr_xdg_shell_v6.h>
+#include <wlr/types/wlr_gamma_control.h>
+#include <wlr/util/log.h>
+#include "rootston/desktop.h"
+#include "rootston/server.h"
+
+static void handle_xdg_shell_v6_surface(struct wl_listener *listener,
+		void *data) {
+	struct roots_desktop *desktop =
+		wl_container_of(listener, desktop, xdg_shell_v6_surface);
+	struct wlr_xdg_surface_v6 *surface = data;
+	wlr_log(L_DEBUG, "new xdg surface: title=%s, app_id=%s",
+		surface->title, surface->app_id);
+	wlr_xdg_surface_v6_ping(surface);
+}
+
+struct roots_desktop *desktop_create(struct roots_server *server,
+		struct roots_config *config) {
+	struct roots_desktop *desktop = calloc(1, sizeof(struct roots_desktop));
+	wlr_log(L_DEBUG, "Initializing roots desktop");
+
+	wl_list_init(&desktop->outputs);
+	wl_list_init(&desktop->output_add.link);
+	desktop->output_add.notify = output_add_notify;
+	wl_list_init(&desktop->output_remove.link);
+	desktop->output_remove.notify = output_remove_notify;
+
+	wl_signal_add(&server->backend->events.output_add,
+			&desktop->output_add);
+	wl_signal_add(&server->backend->events.output_remove,
+			&desktop->output_remove);
+
+	desktop->server = server;
+	desktop->config = config;
+	desktop->layout = wlr_output_layout_create();
+	desktop->compositor = wlr_compositor_create(
+			server->wl_display, server->renderer);
+	desktop->wl_shell = wlr_wl_shell_create(server->wl_display);
+
+	desktop->xdg_shell_v6 = wlr_xdg_shell_v6_create(server->wl_display);
+	wl_signal_add(&desktop->xdg_shell_v6->events.new_surface,
+		&desktop->xdg_shell_v6_surface);
+	desktop->xdg_shell_v6_surface.notify = handle_xdg_shell_v6_surface;
+
+	desktop->gamma_control_manager = wlr_gamma_control_manager_create(
+			server->wl_display);
+
+	return desktop;
+}
+
+void desktop_destroy(struct roots_desktop *desktop) {
+	// TODO
+}
diff --git a/rootston/main.c b/rootston/main.c
index 9be2ff41..b95840a9 100644
--- a/rootston/main.c
+++ b/rootston/main.c
@@ -1,14 +1,45 @@
+#define _POSIX_C_SOURCE 200112L
+#include <assert.h>
+#include <stdlib.h>
 #include <wayland-server.h>
+#include <wlr/backend.h>
+#include <wlr/render.h>
+#include <wlr/render/gles2.h>
 #include <wlr/util/log.h>
 #include "rootston/config.h"
 #include "rootston/server.h"
 
-struct rootston root = { 0 };
+struct roots_server server = { 0 };
 
 int main(int argc, char **argv) {
-	root.config = parse_args(argc, argv);
-	root.wl_display = wl_display_create();
-	root.wl_event_loop = wl_display_get_event_loop(root.wl_display);
-	wl_display_init_shm(root.wl_display);
+	assert(server.config = parse_args(argc, argv));
+	assert(server.wl_display = wl_display_create());
+	assert(server.wl_event_loop = wl_display_get_event_loop(server.wl_display));
+
+	assert(server.backend = wlr_backend_autocreate(server.wl_display));
+
+	assert(server.renderer = wlr_gles2_renderer_create(server.backend));
+	wl_display_init_shm(server.wl_display);
+	server.desktop = desktop_create(&server, server.config);
+	server.data_device_manager = wlr_data_device_manager_create(
+			server.wl_display);
+
+	const char *socket = wl_display_add_socket_auto(server.wl_display);
+	if (!socket) {
+		wlr_log_errno(L_ERROR, "Unable to open wayland socket");
+		wlr_backend_destroy(server.backend);
+		return 1;
+	}
+
+	wlr_log(L_INFO, "Running compositor on wayland display '%s'", socket);
+	setenv("_WAYLAND_DISPLAY", socket, true);
+
+	if (!wlr_backend_start(server.backend)) {
+		wlr_log(L_ERROR, "Failed to start backend");
+		wlr_backend_destroy(server.backend);
+		return 1;
+	}
+
+	wl_display_run(server.wl_display);
 	return 0;
 }
diff --git a/rootston/meson.build b/rootston/meson.build
index 501fe17e..9342d19c 100644
--- a/rootston/meson.build
+++ b/rootston/meson.build
@@ -1,7 +1,9 @@
 executable(
-	'rooston', [
-		'main.c',
+	'rootson', [
 		'config.c',
+		'desktop.c',
 		'ini.c',
+		'main.c',
+		'output.c',
 	], dependencies: wlroots
 )
diff --git a/rootston/output.c b/rootston/output.c
new file mode 100644
index 00000000..39586e0e
--- /dev/null
+++ b/rootston/output.c
@@ -0,0 +1,101 @@
+#define _POSIX_C_SOURCE 199309L
+#include <time.h>
+#include <stdlib.h>
+#include <wlr/types/wlr_output_layout.h>
+#include <wlr/types/wlr_compositor.h>
+#include <wlr/types/wlr_wl_shell.h>
+#include <wlr/types/wlr_xdg_shell_v6.h>
+#include <wlr/util/log.h>
+#include "rootston/server.h"
+#include "rootston/desktop.h"
+#include "rootston/config.h"
+
+static void output_frame_notify(struct wl_listener *listener, void *data) {
+	struct wlr_output *wlr_output = data;
+	struct roots_output *output = wl_container_of(listener, output, frame);
+	struct roots_desktop *desktop = output->desktop;
+	struct roots_server *server = desktop->server;
+
+	struct timespec now;
+	clock_gettime(CLOCK_MONOTONIC, &now);
+
+	wlr_output_make_current(wlr_output);
+	wlr_renderer_begin(server->renderer, wlr_output);
+
+	// TODO: render views
+
+	wlr_renderer_end(server->renderer);
+	wlr_output_swap_buffers(wlr_output);
+
+	output->last_frame = desktop->last_frame = now;
+}
+
+void output_add_notify(struct wl_listener *listener, void *data) {
+	struct wlr_output *wlr_output = data;
+	struct roots_desktop *desktop = wl_container_of(listener, desktop, output_add);
+	struct roots_config *config = desktop->config;
+
+	wlr_log(L_DEBUG, "Output '%s' added", wlr_output->name);
+	wlr_log(L_DEBUG, "%s %s %"PRId32"mm x %"PRId32"mm",
+			wlr_output->make, wlr_output->model,
+			wlr_output->phys_width, wlr_output->phys_height);
+	if (wlr_output->modes->length > 0) {
+		wlr_output_set_mode(wlr_output, wlr_output->modes->items[0]);
+	}
+
+	struct roots_output *output = calloc(1, sizeof(struct roots_output));
+	clock_gettime(CLOCK_MONOTONIC, &output->last_frame);
+	output->desktop = desktop;
+	output->wlr_output = wlr_output;
+	output->frame.notify = output_frame_notify;
+	wl_list_init(&output->frame.link);
+	wl_signal_add(&wlr_output->events.frame, &output->frame);
+	wl_list_insert(&desktop->outputs, &output->link);
+
+	struct output_config *output_config = config_get_output(config, wlr_output);
+	if (output_config) {
+		wlr_output_transform(wlr_output, output_config->transform);
+		wlr_output_layout_add(desktop->layout,
+				wlr_output, output_config->x, output_config->y);
+	} else {
+		wlr_output_layout_add_auto(desktop->layout, wlr_output);
+	}
+
+	/* TODO: cursor
+	example_config_configure_cursor(sample->config, sample->cursor,
+		sample->compositor);
+
+	// TODO the cursor must be set depending on which surface it is displayed
+	// over which should happen in the compositor.
+	if (!wlr_output_set_cursor(wlr_output, image->buffer,
+			image->width, image->width, image->height)) {
+		wlr_log(L_DEBUG, "Failed to set hardware cursor");
+		return;
+	}
+
+	wlr_cursor_warp(sample->cursor, NULL, sample->cursor->x, sample->cursor->y);
+	*/
+}
+
+void output_remove_notify(struct wl_listener *listener, void *data) {
+	struct wlr_output *wlr_output = data;
+	struct roots_desktop *desktop = wl_container_of(listener, desktop, output_remove);
+	struct roots_output *output = NULL, *_output;
+	wl_list_for_each(_output, &desktop->outputs, link) {
+		if (_output->wlr_output == wlr_output) {
+			output = _output;
+			break;
+		}
+	}
+	if (!output) {
+		return; // We are unfamiliar with this output
+	}
+	wlr_output_layout_remove(desktop->layout, output->wlr_output);
+	// TODO: cursor
+	//example_config_configure_cursor(sample->config, sample->cursor,
+	//	sample->compositor);
+	wl_list_remove(&output->link);
+	wl_list_remove(&output->frame.link);
+	wl_list_remove(&output->resolution.link);
+	free(output);
+}
-- 
cgit v1.2.3