Rework Server
This commit is contained in:
@ -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;
|
||||
}
|
||||
|
||||
};
|
||||
|
Reference in New Issue
Block a user