From f423f5317bfa46fe8a7a0149240ea5fe49bd5f89 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Mon, 23 Mar 2020 01:21:15 +0100 Subject: [PATCH] Rework Server --- include/render.c | 11 ++---- include/render.h | 7 ++-- src/main.zig | 58 ++++------------------------ src/server.zig | 98 +++++++++++++++++++++++++++++++++++------------- 4 files changed, 85 insertions(+), 89 deletions(-) diff --git a/include/render.c b/include/render.c index 2a85fb7..36e42c3 100644 --- a/include/render.c +++ b/include/render.c @@ -2,19 +2,14 @@ #include #include -struct wlr_backend *zag_wlr_backend_autocreate(struct wl_display *display) { +struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) { return wlr_backend_autocreate(display, NULL); } -struct wlr_renderer *zag_wlr_backend_get_renderer(struct wlr_backend *backend) { +struct wlr_renderer *wlr_backend_get_renderer(struct wlr_backend *backend) { return wlr_backend_get_renderer(backend); } -bool zag_wlr_backend_start(struct wlr_backend *backend) { +bool wlr_backend_start(struct wlr_backend *backend) { return wlr_backend_start(backend); } - -void zag_wlr_backend_destroy(struct wlr_backend *backend) { - zag_wlr_backend_destroy(backend); -} - diff --git a/include/render.h b/include/render.h index cb0bd52..3ac3cf2 100644 --- a/include/render.h +++ b/include/render.h @@ -18,10 +18,9 @@ struct wlr_backend { } events; }; -struct wlr_backend *zag_wlr_backend_autocreate(struct wl_display *display); -struct wlr_renderer *zag_wlr_backend_get_renderer(struct wlr_backend *backend); -bool zag_wlr_backend_start(struct wlr_backend *backend); -void zag_wlr_backend_destroy(struct wlr_backend *backend); +struct wlr_backend *wlr_backend_autocreate(struct wl_display *display); +struct wlr_renderer *wlr_backend_get_renderer(struct wlr_backend *backend); +bool wlr_backend_start(struct wlr_backend *backend); #endif diff --git a/src/main.zig b/src/main.zig index 9034289..76ddf8d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,31 +1,13 @@ const std = @import("std"); const c = @import("c.zig").c; -const man_c = @import("c.zig").manual; - -const ZagError = error{ - InitError, - CantAddSocket, - CantStartBackend, - CantSetEnv, -}; pub fn main() !void { std.debug.warn("Starting up.\n", .{}); c.wlr_log_init(c.enum_wlr_log_importance.WLR_DEBUG, null); - var server: Server = undefined; - - // Creates an output layout, which a wlroots utility for working with an - // arrangement of screens in a physical layout. - server.output_layout = c.wlr_output_layout_create(); - - server.outputs = std.ArrayList(Output).init(std.heap.c_allocator); - - // Configure a listener to be notified when new outputs are available on the - // backend. - server.new_output.notify = server_new_output; - c.wl_signal_add(&server.backend.*.events.new_output, &server.new_output); + var server = try Server.init(std.heap.c_allocator); + defer server.deinit(); // Set up our list of views and the xdg-shell. The xdg-shell is a Wayland // protocol which is used for application windows. @@ -35,39 +17,13 @@ pub fn main() !void { server.new_xdg_surface.notify = server_new_xdg_surface; c.wl_signal_add(&server.xdg_shell.*.events.new_surface, &server.new_xdg_surface); - // Add a Unix socket to the Wayland display. - const socket = c.wl_display_add_socket_auto(server.wl_display); - if (socket == null) { - c.zag_wlr_backend_destroy(server.backend); - return ZagError.CantAddSocket; - } + try server.start(); - // Start the backend. This will enumerate outputs and inputs, become the DRM - // master, etc - if (!c.zag_wlr_backend_start(server.backend)) { - c.zag_wlr_backend_destroy(server.backend); - c.wl_display_destroy(server.wl_display); - return ZagError.CantStartBackend; - } - - // Set the WAYLAND_DISPLAY environment variable to our socket and run the - // startup command if requested. */ - if (c.setenv("WAYLAND_DISPLAY", socket, 1) == -1) { - return ZagError.CantSetEnv; - } - - const argv = [_][]const u8{ "/bin/sh", "-c", "WAYLAND_DEBUG=1 alacritty" }; + // Spawn an instance of alacritty + // const argv = [_][]const u8{ "/bin/sh", "-c", "WAYLAND_DEBUG=1 alacritty" }; + const argv = [_][]const u8{ "/bin/sh", "-c", "alacritty" }; var child = try std.ChildProcess.init(&argv, std.heap.c_allocator); try std.ChildProcess.spawn(child); - // Run the Wayland event loop. This does not return until you exit the - // compositor. Starting the backend rigged up all of the necessary event - // loop configuration to listen to libinput events, DRM events, generate - // frame events at the refresh rate, and so on. - //c.wlr_log(WLR_INFO, "Running Wayland compositor on WAYLAND_DISPLAY=%s", socket); - c.wl_display_run(server.wl_display); - - // Once wl_display_run returns, we shut down the server. - c.wl_display_destroy_clients(server.wl_display); - c.wl_display_destroy(server.wl_display); + server.run(); } diff --git a/src/server.zig b/src/server.zig index fc1fef0..d1e0002 100644 --- a/src/server.zig +++ b/src/server.zig @@ -3,45 +3,92 @@ const c = @import("c.zig").c; pub const Server = struct { wl_display: *c.wl_display, - backend: *c.wlr_backend, - renderer: *c.wlr_renderer, + wlr_backend: *c.wlr_backend, + wlr_renderer: *c.wlr_renderer, + + wlr_output_layout: *c.wlr_output_layout, + outputs: std.ArrayList(Output), + + listen_new_output: c.wl_listener, + xdg_shell: *c.wlr_xdg_shell, new_xdg_surface: c.wl_listener, views: std.ArrayList(View), - output_layout: *c.wlr_output_layout, - outputs: std.ArrayList(Output), - new_output: c.wl_listener, - pub fn init(allocator: *std.mem.Allocator) !@This() { - var server: @This() = undefined; + var server = undefined; // The Wayland display is managed by libwayland. It handles accepting // clients from the Unix socket, manging Wayland globals, and so on. - server.wl_display = c.wl_display_create() orelse return error.CantCreateWlDisplay; + server.wl_display = c.wl_display_create() orelse + return error.CantCreateWlDisplay; + errdefer c.wl_display_destroy(server.wl_display); - // The backend is a wlroots feature which abstracts the underlying input and - // output hardware. The autocreate option will choose the most suitable - // backend based on the current environment, such as opening an X11 window - // if an X11 server is running. The NULL argument here optionally allows you - // to pass in a custom renderer if wlr_renderer doesn't meet your needs. The - // backend uses the renderer, for example, to fall back to software cursors - // if the backend does not support hardware cursors (some older GPUs - // don't). - server.backend = c.zag_wlr_backend_autocreate(server.wl_display) orelse return error.CantCreateWlrBackend; + // The wlr_backend abstracts the input/output hardware. Autocreate chooses + // the best option based on the environment, for example DRM when run from + // a tty or wayland if WAYLAND_DISPLAY is set. + // + // This frees itself when the wl_display is destroyed. + server.wlr_backend = c.wlr_backend_autocreate(server.wl_display) orelse + return error.CantCreateWlrBackend; // If we don't provide a renderer, autocreate makes a GLES2 renderer for us. // The renderer is responsible for defining the various pixel formats it // supports for shared memory, this configures that for clients. - server.renderer = c.zag_wlr_backend_get_renderer(server.backend) orelse return error.CantGetWlrRenderer; - c.wlr_renderer_init_wl_display(server.renderer, server.wl_display) orelse return error.CantInitWlDisplay; + server.wlr_renderer = c.wlr_backend_get_renderer(server.backend) orelse + return error.CantGetWlrRenderer; + c.wlr_renderer_init_wl_display(server.wlr_renderer, server.wl_display) orelse + return error.CantInitWlDisplay; - // This creates some hands-off wlroots interfaces. The compositor is - // necessary for clients to allocate surfaces and the data device manager - // handles the clipboard. Each of these wlroots interfaces has room for you - // to dig your fingers in and play with their behavior if you want. - _ = c.wlr_compositor_create(server.wl_display, server.renderer) orelse return error.CantCreateWlrCompositor; - _ = c.wlr_data_device_manager_create(server.wl_display) orelse return error.CantCreateWlrDataDeviceManager; + // These both free themselves when the wl_display is destroyed + _ = c.wlr_compositor_create(server.wl_display, server.renderer) orelse + return error.CantCreateWlrCompositor; + _ = c.wlr_data_device_manager_create(server.wl_display) orelse + return error.CantCreateWlrDataDeviceManager; + + // Create an output layout, which a wlroots utility for working with an + // arrangement of screens in a physical layout. + server.wlr_output_layout = c.wlr_output_layout_create() orelse + return error.CantCreateWlrOutputLayout; + errdefer c.wlr_output_layout_destroy(server.wlr_output_layout); + + server.outputs = std.ArrayList(Output).init(std.heap.c_allocator); + + // Setup a listener for new outputs + server.listen_new_output = handle_new_output; + c.wl_signal_add(&server.wlr_backend.*.events.new_output, &server.listen_new_output); + } + + /// Free allocated memory and clean up + pub fn deinit(self: @This()) void { + c.wl_display_destroy_clients(self.wl_display); + c.wl_display_destroy(self.wl_display); + c.wlr_output_layout_destroy(self.wlr_output_layout); + } + + /// Create the socket, set WAYLAND_DISPLAY, and start the backend + pub fn start(self: @This()) !void { + // Add a Unix socket to the Wayland display. + const socket = c.wl_display_add_socket_auto(self.wl_display) orelse; + return error.CantAddSocket; + + // Start the backend. This will enumerate outputs and inputs, become the DRM + // master, etc + if (!c.wlr_backend_start(self.wlr_backend)) { + c.wlr_backend_destroy(self.wlr_backend); + return error.CantStartBackend; + } + + // Set the WAYLAND_DISPLAY environment variable to our socket and run the + // startup command if requested. */ + if (c.setenv("WAYLAND_DISPLAY", socket, 1) == -1) { + return error.CantSetEnv; + } + } + + /// Enter the wayland event loop and block until the compositor is exited + pub fn run(self: @This()) void { + c.wl_display_run(server.wl_display); } pub fn handle_keybinding(self: *@This(), sym: c.xkb_keysym_t) bool { @@ -67,5 +114,4 @@ pub const Server = struct { } return true; } - };