Implement wallpaper rendering with multi-output support
This actually renders a wallpaper for each output using the newly added Buffer and BufferPool for shared-memory surfaces and creates a wlr-layer-shell surface per output. Right now, each wallpaper shares the same wallpaper (though scaled to each). wl_output globals get added to a HashMap that is used by Output when it gets an output event. Fix null-safety in WindowManager when no seats/outputs exist and route Window dimensions through pending_manage.
This commit is contained in:
parent
fb8817ebf9
commit
e186a2d017
9 changed files with 568 additions and 35 deletions
58
src/main.zig
58
src/main.zig
|
|
@ -7,10 +7,20 @@ const Globals = struct {
|
|||
river_layer_shell_v1: ?*river.LayerShellV1 = null,
|
||||
river_window_manager_v1: ?*river.WindowManagerV1 = null,
|
||||
river_xkb_bindings_v1: ?*river.XkbBindingsV1 = null,
|
||||
|
||||
wl_compositor: ?*wl.Compositor = null,
|
||||
wl_output: ?*wl.Output = null,
|
||||
wl_shm: ?*wl.Shm = null,
|
||||
wl_outputs: std.AutoHashMapUnmanaged(u32, *wl.Output) = .empty,
|
||||
|
||||
zwlr_layer_shell_v1: ?*zwlr.LayerShellV1 = null,
|
||||
|
||||
fn deinit(globals: *Globals) void {
|
||||
var it = globals.wl_outputs.valueIterator();
|
||||
while (it.next()) |output| {
|
||||
output.*.release();
|
||||
}
|
||||
globals.wl_outputs.deinit(utils.allocator);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
|
|
@ -27,6 +37,7 @@ pub fn main() !void {
|
|||
const wl_registry = try wl_display.getRegistry();
|
||||
|
||||
var globals: Globals = .{};
|
||||
defer globals.deinit();
|
||||
wl_registry.setListener(*Globals, registryListener, &globals);
|
||||
|
||||
const errno = wl_display.roundtrip();
|
||||
|
|
@ -34,12 +45,15 @@ pub fn main() !void {
|
|||
fatal("Initial roundtrip failed: E{s}", .{@tagName(errno)});
|
||||
}
|
||||
|
||||
const wl_compositor = globals.wl_compositor orelse utils.interfaceNotAdvertised(wl.Compositor);
|
||||
const wl_shm = globals.wl_shm orelse utils.interfaceNotAdvertised(wl.Shm);
|
||||
// We can theoretically start with zero wl_outputs; don't panic if it's empty.
|
||||
const wl_outputs = &globals.wl_outputs;
|
||||
|
||||
const river_layer_shell_v1 = globals.river_layer_shell_v1 orelse utils.interfaceNotAdvertised(river.LayerShellV1);
|
||||
const river_window_manager_v1 = globals.river_window_manager_v1 orelse utils.interfaceNotAdvertised(river.WindowManagerV1);
|
||||
const river_xkb_bindings_v1 = globals.river_xkb_bindings_v1 orelse utils.interfaceNotAdvertised(river.XkbBindingsV1);
|
||||
const wl_compositor = globals.wl_compositor orelse utils.interfaceNotAdvertised(wl.Compositor);
|
||||
const wl_output = globals.wl_output orelse utils.interfaceNotAdvertised(wl.Output);
|
||||
const wl_shm = globals.wl_shm orelse utils.interfaceNotAdvertised(wl.Shm);
|
||||
|
||||
const zwlr_layer_shell_v1 = globals.zwlr_layer_shell_v1 orelse utils.interfaceNotAdvertised(zwlr.LayerShellV1);
|
||||
|
||||
const config = try Config.create();
|
||||
|
|
@ -47,7 +61,7 @@ pub fn main() !void {
|
|||
const context = try Context.create(.{
|
||||
.wl_compositor = wl_compositor,
|
||||
.wl_display = wl_display,
|
||||
.wl_output = wl_output,
|
||||
.wl_outputs = wl_outputs,
|
||||
.wl_registry = wl_registry,
|
||||
.wl_shm = wl_shm,
|
||||
.river_layer_shell_v1 = river_layer_shell_v1,
|
||||
|
|
@ -73,20 +87,46 @@ fn registryListener(registry: *wl.Registry, event: wl.Registry.Event, globals: *
|
|||
if (mem.orderZ(u8, ev.interface, wl.Compositor.interface.name) == .eq) {
|
||||
if (ev.version < 4) utils.versionNotSupported(wl.Compositor, ev.version, 4);
|
||||
globals.wl_compositor = registry.bind(ev.name, wl.Compositor, 4) catch |e| {
|
||||
fatal("Failed to bind to compositor: {any}", .{@errorName(e)});
|
||||
fatal("Failed to bind to wl_compositor: {any}", .{@errorName(e)});
|
||||
};
|
||||
} else if (mem.orderZ(u8, ev.interface, wl.Output.interface.name) == .eq) {
|
||||
if (ev.version < 4) utils.versionNotSupported(wl.Output, ev.version, 4);
|
||||
|
||||
const wl_output = registry.bind(ev.name, wl.Output, 4) catch |e| {
|
||||
fatal("Failed to bind to wl_output: {any}", .{@errorName(e)});
|
||||
};
|
||||
|
||||
// We can get multiple wl_outputs, so we have to try add them to our HashMap
|
||||
// instead of just keeping the one
|
||||
globals.wl_outputs.put(utils.allocator, ev.name, wl_output) catch |e| {
|
||||
fatal("Failed to add wl_output to hashmap: {any}", .{@errorName(e)});
|
||||
};
|
||||
} else if (mem.orderZ(u8, ev.interface, wl.Shm.interface.name) == .eq) {
|
||||
globals.wl_shm = registry.bind(ev.name, wl.Shm, 1) catch |e| {
|
||||
fatal("Failed to bind to wl_shm: {any}", .{@errorName(e)});
|
||||
};
|
||||
} else if (mem.orderZ(u8, ev.interface, river.WindowManagerV1.interface.name) == .eq) {
|
||||
globals.river_window_manager_v1 = registry.bind(ev.name, river.WindowManagerV1, 3) catch |e| {
|
||||
fatal("Failed to bind to window_manager_v1: {any}", .{@errorName(e)});
|
||||
fatal("Failed to bind to river_window_manager_v1: {any}", .{@errorName(e)});
|
||||
};
|
||||
} else if (mem.orderZ(u8, ev.interface, river.XkbBindingsV1.interface.name) == .eq) {
|
||||
globals.river_xkb_bindings_v1 = registry.bind(ev.name, river.XkbBindingsV1, 2) catch |e| {
|
||||
fatal("Failed to bind to xkb_bindings_v1: {any}", .{@errorName(e)});
|
||||
fatal("Failed to bind to river_xkb_bindings_v1: {any}", .{@errorName(e)});
|
||||
};
|
||||
} else if (mem.orderZ(u8, ev.interface, zwlr.LayerShellV1.interface.name) == .eq) {
|
||||
if (ev.version < 3) utils.versionNotSupported(zwlr.LayerShellV1, ev.version, 3);
|
||||
globals.zwlr_layer_shell_v1 = registry.bind(ev.name, zwlr.LayerShellV1, 3) catch |e| {
|
||||
fatal("Failed to bind to zwlr_layer_shell_v1: {any}", .{@errorName(e)});
|
||||
};
|
||||
}
|
||||
},
|
||||
// We don't need .global_remove
|
||||
.global_remove => {},
|
||||
.global_remove => |ev| {
|
||||
// The only remove we care about is for wl_outputs
|
||||
if (!globals.wl_outputs.remove(ev.name)) {
|
||||
log.debug("Received a global_remove event for something other than a wl_output", .{});
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue