some basic xdg surface stuff

This commit is contained in:
Harrison DiAmbrosio 2025-10-18 23:45:13 -04:00
parent f500937b96
commit f10906f0fc
4 changed files with 104 additions and 38 deletions

View file

@ -3,13 +3,13 @@ const Output = @This();
const std = @import("std"); const std = @import("std");
const posix = std.posix; const posix = std.posix;
const gpa = std.heap.c_allocator; const gpa = std.heap.c_allocator;
const server = &@import("main.zig").server;
const wl = @import("wayland").server.wl; const wl = @import("wayland").server.wl;
const wlr = @import("wlroots"); const wlr = @import("wlroots");
const Server = @import("server.zig"); const Server = @import("server.zig");
server: *Server,
wlr_output: *wlr.Output, wlr_output: *wlr.Output,
frame: wl.Listener(*wlr.Output) = .init(handleFrame), frame: wl.Listener(*wlr.Output) = .init(handleFrame),
@ -17,11 +17,10 @@ request_state: wl.Listener(*wlr.Output.event.RequestState) = .init(handleRequest
destroy: wl.Listener(*wlr.Output) = .init(handleDestroy), destroy: wl.Listener(*wlr.Output) = .init(handleDestroy),
// The wlr.Output should be destroyed by the caller on failure to trigger cleanup. // The wlr.Output should be destroyed by the caller on failure to trigger cleanup.
pub fn create(server: *Server, wlr_output: *wlr.Output) !*Output { pub fn create(wlr_output: *wlr.Output) !*Output {
const output = try gpa.create(Output); const output = try gpa.create(Output);
output.* = .{ output.* = .{
.server = server,
.wlr_output = wlr_output, .wlr_output = wlr_output,
}; };
wlr_output.events.frame.add(&output.frame); wlr_output.events.frame.add(&output.frame);
@ -42,6 +41,7 @@ pub fn handleRequestState(
listener: *wl.Listener(*wlr.Output.event.RequestState), listener: *wl.Listener(*wlr.Output.event.RequestState),
event: *wlr.Output.event.RequestState, event: *wlr.Output.event.RequestState,
) void { ) void {
std.log.debug("Handling request state", .{});
const output: *Output = @fieldParentPtr("request_state", listener); const output: *Output = @fieldParentPtr("request_state", listener);
if (!output.wlr_output.commitState(event.state)) { if (!output.wlr_output.commitState(event.state)) {
@ -49,13 +49,13 @@ event: *wlr.Output.event.RequestState,
} }
} }
pub fn handleFrame(listener: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void { pub fn handleFrame(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void {
const output: *Output = @fieldParentPtr("destroy", listener); std.log.debug("Handling frame for {s}", .{wlr_output.name});
const scene_output = output.*.server.*.scene.*.getSceneOutput(wlr_output); const scene_output = server.scene.*.getSceneOutput(wlr_output);
if(scene_output) |so| { if(scene_output) |so| {
std.log.info("Rendering commitin scene output\n", .{}); std.log.info("Rendering commited scene output\n", .{});
_ = so.commit(null); _ = so.commit(null);
var now = posix.clock_gettime(posix.CLOCK.MONOTONIC) catch @panic("CLOCK_MONOTONIC not supported"); var now = posix.clock_gettime(posix.CLOCK.MONOTONIC) catch @panic("CLOCK_MONOTONIC not supported");
@ -65,6 +65,7 @@ pub fn handleFrame(listener: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output)
} }
pub fn handleDestroy(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void { pub fn handleDestroy(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void {
std.log.debug("Handling destroy", .{});
const output: *Output = @fieldParentPtr("destroy", listener); const output: *Output = @fieldParentPtr("destroy", listener);
std.log.debug("removing output: {s}", .{output.*.wlr_output.*.name}); std.log.debug("removing output: {s}", .{output.*.wlr_output.*.name});

View file

@ -1,20 +1,24 @@
const std = @import("std"); const Root = @This();
const std = @import("std");
const wl = @import("wayland").server.wl; const wl = @import("wayland").server.wl;
const wlr = @import("wlroots"); const wlr = @import("wlroots");
const Output = @import("output.zig"); const Output = @import("output.zig");
const TopLevel = @import("toplevel.zig");
const server = &@import("main.zig").server; const server = &@import("main.zig").server;
const gpa = std.heap.c_allocator;
pub const Root = struct { scene: *wlr.Scene,
scene: *wlr.Scene,
output_layout: *wlr.OutputLayout, output_layout: *wlr.OutputLayout,
new_output: wl.Listener(*wlr.Output), new_output: wl.Listener(*wlr.Output),
pub fn init(root: *Root) !void { all_top_levels: std.ArrayList(*TopLevel),
pub fn init(root: *Root) !void {
std.log.info("Creating root of mezzaluna\n", .{}); std.log.info("Creating root of mezzaluna\n", .{});
const output_layout = try wlr.OutputLayout.create(server.wl_server); const output_layout = try wlr.OutputLayout.create(server.wl_server);
@ -28,23 +32,27 @@ pub const Root = struct {
.output_layout = output_layout, .output_layout = output_layout,
.new_output = .init(handleNewOutput), .new_output = .init(handleNewOutput),
.all_top_levels = try .initCapacity(gpa, 10),
}; };
server.backend.events.new_output.add(&root.new_output); server.backend.events.new_output.add(&root.new_output);
} }
pub fn addOutput(self: *Root, new_output: *Output) void { pub fn addOutput(self: *Root, new_output: *Output) void {
_ = self.output_layout.addAuto(new_output.wlr_output) catch { _ = self.output_layout.addAuto(new_output.wlr_output) catch {
std.log.err("failed to add new output to output layout\n", .{}); std.log.err("failed to add new output to output layout\n", .{});
return; return;
}; };
}
// _ = self.scene.createSceneOutput(new_output.wlr_output) catch { pub fn addTopLevel(self: *Root, top_level: *TopLevel) void {
// std.log.err("failed to create scene output for new output", .{}); self.all_top_levels.append(gpa, top_level) catch {
// return; std.log.err("Out of memory to append top level", .{});
// }; };
}
}; // self.scene.tree.children.append(wlr.SceneNode)
}
fn handleNewOutput(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void { fn handleNewOutput(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void {
std.log.info("Handling a new output - {s}", .{wlr_output.name}); std.log.info("Handling a new output - {s}", .{wlr_output.name});
@ -61,7 +69,7 @@ fn handleNewOutput(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void {
} }
if (!wlr_output.commitState(&state)) return; if (!wlr_output.commitState(&state)) return;
const new_output = Output.create(server, wlr_output) catch { const new_output = Output.create(wlr_output) catch {
std.log.err("failed to allocate new output", .{}); std.log.err("failed to allocate new output", .{});
wlr_output.destroy(); wlr_output.destroy();
return; return;
@ -69,3 +77,4 @@ fn handleNewOutput(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void {
server.root.addOutput(new_output); server.root.addOutput(new_output);
} }

View file

@ -8,7 +8,8 @@ const wlr = @import("wlroots");
const Output = @import("output.zig"); const Output = @import("output.zig");
const Keyboard = @import("keyboard.zig"); const Keyboard = @import("keyboard.zig");
const Root = @import("root.zig").Root; const TopLevel = @import("toplevel.zig");
const Root = @import("root.zig");
allocator: *wlr.Allocator, allocator: *wlr.Allocator,
backend: *wlr.Backend, backend: *wlr.Backend,
@ -32,6 +33,9 @@ cursor_mgr: *wlr.XcursorManager,
// Listeners // Listeners
new_input: wl.Listener(*wlr.InputDevice) = .init(newInput), new_input: wl.Listener(*wlr.InputDevice) = .init(newInput),
new_xdg_surface: wl.Listener(*wlr.XdgSurface) = .init(handleNewXdgSurface),
cursor_motion: wl.Listener(*wlr.Pointer.event.Motion) = .init(cursorMotion), cursor_motion: wl.Listener(*wlr.Pointer.event.Motion) = .init(cursorMotion),
cursor_motion_absolute: wl.Listener(*wlr.Pointer.event.MotionAbsolute) = .init(cursorMotionAbsolute), cursor_motion_absolute: wl.Listener(*wlr.Pointer.event.MotionAbsolute) = .init(cursorMotionAbsolute),
cursor_button: wl.Listener(*wlr.Pointer.event.Button) = .init(cursorButton), cursor_button: wl.Listener(*wlr.Pointer.event.Button) = .init(cursorButton),
@ -75,9 +79,13 @@ pub fn init(server: *Server) !void {
try server.renderer.initServer(wl_server); try server.renderer.initServer(wl_server);
try Root.init(&server.root); try Root.init(&server.root);
server.xdg_shell.events.new_surface.add(&server.new_xdg_surface);
server.backend.events.new_input.add(&server.new_input); server.backend.events.new_input.add(&server.new_input);
server.seat.events.request_set_cursor.add(&server.request_set_cursor); server.seat.events.request_set_cursor.add(&server.request_set_cursor);
server.seat.events.request_set_selection.add(&server.request_set_selection); server.seat.events.request_set_selection.add(&server.request_set_selection);
server.keyboards.init(); server.keyboards.init();
server.cursor.attachOutputLayout(server.output_layout); server.cursor.attachOutputLayout(server.output_layout);
@ -237,3 +245,16 @@ fn requestSetSelection(
const server: *Server = @fieldParentPtr("request_set_selection", listener); const server: *Server = @fieldParentPtr("request_set_selection", listener);
server.seat.setSelection(event.source, event.serial); server.seat.setSelection(event.source, event.serial);
} }
fn handleNewXdgSurface(listener: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wlr.XdgSurface) void {
const server: *Server = @fieldParentPtr("new_xdg_surface", listener);
std.log.info("New xdg_toplevel added", .{});
const top_level = TopLevel.init(xdg_surface) catch {
std.log.err("Unable to allocate a top level", .{});
return;
};
server.root.addTopLevel(top_level);
}

35
src/toplevel.zig Normal file
View file

@ -0,0 +1,35 @@
const TopLevel = @This();
const std = @import("std");
const wl = @import("wayland").server.wl;
const wlr = @import("wlroots");
const gpa = std.heap.c_allocator;
const server = &@import("main.zig").server;
xdg_toplevel: *wlr.XdgToplevel,
box: *wlr.Box,
pub fn init(xdg_surface: *wlr.XdgSurface) !*TopLevel {
const top_level = gpa.create(TopLevel) catch |err| {
std.log.err("Unable to allocate memory for new XdgTopLevel", .{});
return err;
};
if(xdg_surface.role_data.toplevel) |xgd_toplevel| {
top_level.* = .{
.xdg_toplevel = xgd_toplevel,
.box = undefined,
};
top_level.box.x = 0;
top_level.box.y = 0;
top_level.box.width = 640;
top_level.box.height = 360;
}
// Listen to important toplevel events
// top_level.xdg_toplevel.events.set_title.add(listener: *Listener(void))
return top_level;
}