Rework Server

This commit is contained in:
Isaac Freund
2020-03-23 01:21:15 +01:00
parent 0584fde126
commit f423f5317b
4 changed files with 85 additions and 89 deletions

View File

@ -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;
}
};