Rework Server

This commit is contained in:
Isaac Freund 2020-03-23 01:21:15 +01:00
parent 0584fde126
commit f423f5317b
No known key found for this signature in database
GPG key ID: 86DED400DDFD7A11
4 changed files with 85 additions and 89 deletions

View file

@ -2,19 +2,14 @@
#include <wlr/backend.h> #include <wlr/backend.h>
#include <wlr/render/wlr_renderer.h> #include <wlr/render/wlr_renderer.h>
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); 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); 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); return wlr_backend_start(backend);
} }
void zag_wlr_backend_destroy(struct wlr_backend *backend) {
zag_wlr_backend_destroy(backend);
}

View file

@ -18,10 +18,9 @@ struct wlr_backend {
} events; } events;
}; };
struct wlr_backend *zag_wlr_backend_autocreate(struct wl_display *display); struct wlr_backend *wlr_backend_autocreate(struct wl_display *display);
struct wlr_renderer *zag_wlr_backend_get_renderer(struct wlr_backend *backend); struct wlr_renderer *wlr_backend_get_renderer(struct wlr_backend *backend);
bool zag_wlr_backend_start(struct wlr_backend *backend); bool wlr_backend_start(struct wlr_backend *backend);
void zag_wlr_backend_destroy(struct wlr_backend *backend);
#endif #endif

View file

@ -1,31 +1,13 @@
const std = @import("std"); const std = @import("std");
const c = @import("c.zig").c; const c = @import("c.zig").c;
const man_c = @import("c.zig").manual;
const ZagError = error{
InitError,
CantAddSocket,
CantStartBackend,
CantSetEnv,
};
pub fn main() !void { pub fn main() !void {
std.debug.warn("Starting up.\n", .{}); std.debug.warn("Starting up.\n", .{});
c.wlr_log_init(c.enum_wlr_log_importance.WLR_DEBUG, null); c.wlr_log_init(c.enum_wlr_log_importance.WLR_DEBUG, null);
var server: Server = undefined; var server = try Server.init(std.heap.c_allocator);
defer server.deinit();
// 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);
// Set up our list of views and the xdg-shell. The xdg-shell is a Wayland // Set up our list of views and the xdg-shell. The xdg-shell is a Wayland
// protocol which is used for application windows. // protocol which is used for application windows.
@ -35,39 +17,13 @@ pub fn main() !void {
server.new_xdg_surface.notify = server_new_xdg_surface; server.new_xdg_surface.notify = server_new_xdg_surface;
c.wl_signal_add(&server.xdg_shell.*.events.new_surface, &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. try server.start();
const socket = c.wl_display_add_socket_auto(server.wl_display);
if (socket == null) {
c.zag_wlr_backend_destroy(server.backend);
return ZagError.CantAddSocket;
}
// Start the backend. This will enumerate outputs and inputs, become the DRM // Spawn an instance of alacritty
// master, etc // const argv = [_][]const u8{ "/bin/sh", "-c", "WAYLAND_DEBUG=1 alacritty" };
if (!c.zag_wlr_backend_start(server.backend)) { const argv = [_][]const u8{ "/bin/sh", "-c", "alacritty" };
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" };
var child = try std.ChildProcess.init(&argv, std.heap.c_allocator); var child = try std.ChildProcess.init(&argv, std.heap.c_allocator);
try std.ChildProcess.spawn(child); try std.ChildProcess.spawn(child);
// Run the Wayland event loop. This does not return until you exit the server.run();
// 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);
} }

View file

@ -3,45 +3,92 @@ const c = @import("c.zig").c;
pub const Server = struct { pub const Server = struct {
wl_display: *c.wl_display, wl_display: *c.wl_display,
backend: *c.wlr_backend, wlr_backend: *c.wlr_backend,
renderer: *c.wlr_renderer, 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, xdg_shell: *c.wlr_xdg_shell,
new_xdg_surface: c.wl_listener, new_xdg_surface: c.wl_listener,
views: std.ArrayList(View), 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() { 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 // The Wayland display is managed by libwayland. It handles accepting
// clients from the Unix socket, manging Wayland globals, and so on. // 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 // The wlr_backend abstracts the input/output hardware. Autocreate chooses
// output hardware. The autocreate option will choose the most suitable // the best option based on the environment, for example DRM when run from
// backend based on the current environment, such as opening an X11 window // a tty or wayland if WAYLAND_DISPLAY is set.
// 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 // This frees itself when the wl_display is destroyed.
// backend uses the renderer, for example, to fall back to software cursors server.wlr_backend = c.wlr_backend_autocreate(server.wl_display) orelse
// if the backend does not support hardware cursors (some older GPUs return error.CantCreateWlrBackend;
// don't).
server.backend = c.zag_wlr_backend_autocreate(server.wl_display) orelse return error.CantCreateWlrBackend;
// If we don't provide a renderer, autocreate makes a GLES2 renderer for us. // 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 // The renderer is responsible for defining the various pixel formats it
// supports for shared memory, this configures that for clients. // supports for shared memory, this configures that for clients.
server.renderer = c.zag_wlr_backend_get_renderer(server.backend) orelse return error.CantGetWlrRenderer; server.wlr_renderer = c.wlr_backend_get_renderer(server.backend) orelse
c.wlr_renderer_init_wl_display(server.renderer, server.wl_display) orelse return error.CantInitWlDisplay; 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 // These both free themselves when the wl_display is destroyed
// necessary for clients to allocate surfaces and the data device manager _ = c.wlr_compositor_create(server.wl_display, server.renderer) orelse
// handles the clipboard. Each of these wlroots interfaces has room for you return error.CantCreateWlrCompositor;
// to dig your fingers in and play with their behavior if you want. _ = c.wlr_data_device_manager_create(server.wl_display) orelse
_ = c.wlr_compositor_create(server.wl_display, server.renderer) orelse return error.CantCreateWlrCompositor; return error.CantCreateWlrDataDeviceManager;
_ = 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 { pub fn handle_keybinding(self: *@This(), sym: c.xkb_keysym_t) bool {
@ -67,5 +114,4 @@ pub const Server = struct {
} }
return true; return true;
} }
}; };