Mezzaluna/src/Root.zig

122 lines
3.3 KiB
Zig

/// The root of Mezzaluna is, you guessed it, the root of many of the systems mez needs:
const Root = @This();
const std = @import("std");
const wl = @import("wayland").server.wl;
const wlr = @import("wlroots");
const server = &@import("main.zig").server;
const gpa = std.heap.c_allocator;
const Output = @import("Output.zig");
const View = @import("View.zig");
const LayerSurface = @import("LayerSurface.zig");
const SceneNodeData = @import("SceneNodeData.zig").SceneNodeData;
const Utils = @import("Utils.zig");
xdg_toplevel_decoration_manager: *wlr.XdgDecorationManagerV1,
scene: *wlr.Scene,
scene_node_data: SceneNodeData,
scene_output_layout: *wlr.SceneOutputLayout,
output_layout: *wlr.OutputLayout,
pub fn init(self: *Root) void {
std.log.info("Creating root of mezzaluna\n", .{});
errdefer Utils.oomPanic();
const output_layout = try wlr.OutputLayout.create(server.wl_server);
errdefer output_layout.destroy();
const scene = try wlr.Scene.create();
errdefer scene.tree.node.destroy();
self.* = .{
.scene = scene,
.scene_node_data = .{ .root = self },
.output_layout = output_layout,
.xdg_toplevel_decoration_manager = try wlr.XdgDecorationManagerV1.create(server.wl_server),
.scene_output_layout = try scene.attachOutputLayout(output_layout),
};
self.scene.tree.node.data = &self.scene_node_data;
}
pub fn deinit(self: *Root) void {
var it = self.scene.tree.children.iterator(.forward);
while(it.next()) |node| {
if(node.data == null) continue;
const scene_node_data: *SceneNodeData = @ptrCast(@alignCast(node.data.?));
switch(scene_node_data.*) {
.output => {
scene_node_data.output.deinit();
},
else => {
std.log.debug("The root has a child that is not an output", .{});
unreachable;
}
}
}
self.output_layout.destroy();
self.scene.tree.node.destroy();
}
// Search output_layout's ouputs, and each outputs views
pub fn viewById(self: *Root, id: u64) ?*View {
var output_it = self.output_layout.outputs.iterator(.forward);
while(output_it.next()) |o| {
if(o.output.data == null) continue;
const output_snd: *SceneNodeData = @ptrCast(@alignCast(o.output.data.?));
const output: *Output = switch (output_snd.*) {
.output => |output_ptr| output_ptr,
else => {
std.log.err("Incorrect scene node type found", .{});
unreachable;
}
};
var node_it = output.layers.content.children.iterator(.forward);
while(node_it.next()) |node| {
if(node.data == null) continue;
const view_snd: *SceneNodeData = @ptrCast(@alignCast(node.data.?));
// TODO: Should we assert that we want only views to be here
// -- Basically should we use switch statements for snd interactions
// -- Or if statements, for simplicity
if(view_snd.* == .view and view_snd.view.id == id) {
return view_snd.view;
}
}
if(output.fullscreen) |fullscreen| {
if(fullscreen.id == id) return fullscreen;
}
}
return null;
}
pub fn outputById(self: *Root, id: u64) ?*Output {
var it = self.scene.outputs.iterator(.forward);
while(it.next()) |scene_output| {
if(scene_output.output.data == null) continue;
const output: *Output = @as(*Output, @ptrCast(@alignCast(scene_output.output.data.?)));
if(output.id == id) return output;
}
return null;
}