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 posix = std.posix;
const gpa = std.heap.c_allocator;
const server = &@import("main.zig").server;
const wl = @import("wayland").server.wl;
const wlr = @import("wlroots");
const Server = @import("server.zig");
server: *Server,
wlr_output: *wlr.Output,
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),
// 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);
output.* = .{
.server = server,
.wlr_output = wlr_output,
};
wlr_output.events.frame.add(&output.frame);
@ -42,6 +41,7 @@ pub fn handleRequestState(
listener: *wl.Listener(*wlr.Output.event.RequestState),
event: *wlr.Output.event.RequestState,
) void {
std.log.debug("Handling request state", .{});
const output: *Output = @fieldParentPtr("request_state", listener);
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 {
const output: *Output = @fieldParentPtr("destroy", listener);
pub fn handleFrame(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void {
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| {
std.log.info("Rendering commitin scene output\n", .{});
std.log.info("Rendering commited scene output\n", .{});
_ = so.commit(null);
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 {
std.log.debug("Handling destroy", .{});
const output: *Output = @fieldParentPtr("destroy", listener);
std.log.debug("removing output: {s}", .{output.*.wlr_output.*.name});

View file

@ -1,19 +1,23 @@
const std = @import("std");
const Root = @This();
const std = @import("std");
const wl = @import("wayland").server.wl;
const wlr = @import("wlroots");
const Output = @import("output.zig");
const TopLevel = @import("toplevel.zig");
const server = &@import("main.zig").server;
const gpa = std.heap.c_allocator;
pub const Root = struct {
scene: *wlr.Scene,
output_layout: *wlr.OutputLayout,
new_output: wl.Listener(*wlr.Output),
all_top_levels: std.ArrayList(*TopLevel),
pub fn init(root: *Root) !void {
std.log.info("Creating root of mezzaluna\n", .{});
@ -28,6 +32,8 @@ pub const Root = struct {
.output_layout = output_layout,
.new_output = .init(handleNewOutput),
.all_top_levels = try .initCapacity(gpa, 10),
};
server.backend.events.new_output.add(&root.new_output);
@ -38,14 +44,16 @@ pub const Root = struct {
std.log.err("failed to add new output to output layout\n", .{});
return;
};
// _ = self.scene.createSceneOutput(new_output.wlr_output) catch {
// std.log.err("failed to create scene output for new output", .{});
// return;
// };
}
pub fn addTopLevel(self: *Root, top_level: *TopLevel) void {
self.all_top_levels.append(gpa, top_level) catch {
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 {
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;
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", .{});
wlr_output.destroy();
return;
@ -69,3 +77,4 @@ fn handleNewOutput(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void {
server.root.addOutput(new_output);
}

View file

@ -8,7 +8,8 @@ const wlr = @import("wlroots");
const Output = @import("output.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,
backend: *wlr.Backend,
@ -32,6 +33,9 @@ cursor_mgr: *wlr.XcursorManager,
// Listeners
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_absolute: wl.Listener(*wlr.Pointer.event.MotionAbsolute) = .init(cursorMotionAbsolute),
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 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.seat.events.request_set_cursor.add(&server.request_set_cursor);
server.seat.events.request_set_selection.add(&server.request_set_selection);
server.keyboards.init();
server.cursor.attachOutputLayout(server.output_layout);
@ -237,3 +245,16 @@ fn requestSetSelection(
const server: *Server = @fieldParentPtr("request_set_selection", listener);
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;
}