Begin work to add wallpaper support to beansprout
Added pixman and zigimg dependencies
Set up in build.zig, added to both exe and exe_check
Add new protocols:
river-layer-shell-v1
wlr-layer-shell-unstable-v1
xdg-shell (dep of wlr-layer-shell-unstable-v1)
Update Context.zig to hold wl_output, wl_shm, and a WallpaperImage
Also re-ordered all of its fields into alphabetical order
Context.create() now takes a Context.Options struct so that it takes
one arg instead of many smaller args.
Added new WallpaperImage.zig, but it's not yet actually used
This commit is contained in:
parent
e5d439e27d
commit
fb8817ebf9
7 changed files with 718 additions and 26 deletions
|
|
@ -10,11 +10,14 @@ const Context = @This();
|
|||
initialized: bool,
|
||||
|
||||
// Wayland globals
|
||||
wl_display: *wl.Display,
|
||||
wl_registry: *wl.Registry,
|
||||
wl_compositor: *wl.Compositor,
|
||||
wl_display: *wl.Display,
|
||||
wl_output: *wl.Output,
|
||||
wl_registry: *wl.Registry,
|
||||
wl_shm: *wl.Shm,
|
||||
|
||||
// Wayland globals that we have structs for
|
||||
// Wayland globals that we have special structs for
|
||||
wallpaper_image: *WallpaperImage,
|
||||
wm: *WindowManager,
|
||||
xkb_bindings: *XkbBindings,
|
||||
|
||||
|
|
@ -28,25 +31,36 @@ pub const PendingManage = struct {
|
|||
config: ?*Config = null,
|
||||
};
|
||||
|
||||
pub fn create(
|
||||
wl_display: *wl.Display,
|
||||
wl_registry: *wl.Registry,
|
||||
// I use this because otherwise create() takes
|
||||
// a LOT of arguments.
|
||||
pub const Options = struct {
|
||||
wl_compositor: *wl.Compositor,
|
||||
wl_display: *wl.Display,
|
||||
wl_output: *wl.Output,
|
||||
wl_registry: *wl.Registry,
|
||||
wl_shm: *wl.Shm,
|
||||
river_layer_shell_v1: *river.LayerShellV1,
|
||||
river_window_manager_v1: *river.WindowManagerV1,
|
||||
river_xkb_bindings_v1: *river.XkbBindingsV1,
|
||||
zwlr_layer_shell_v1: *zwlr.LayerShellV1,
|
||||
config: *Config,
|
||||
) !*Context {
|
||||
};
|
||||
|
||||
pub fn create(options: Options) !*Context {
|
||||
const context = try utils.allocator.create(Context);
|
||||
errdefer context.destroy();
|
||||
|
||||
context.* = .{
|
||||
.initialized = false,
|
||||
.wl_display = wl_display,
|
||||
.wl_registry = wl_registry,
|
||||
.wl_compositor = wl_compositor,
|
||||
.wm = try WindowManager.create(context, river_window_manager_v1),
|
||||
.xkb_bindings = try XkbBindings.create(context, river_xkb_bindings_v1),
|
||||
.config = config,
|
||||
.wl_compositor = options.wl_compositor,
|
||||
.wl_display = options.wl_display,
|
||||
.wl_output = options.wl_output,
|
||||
.wl_registry = options.wl_registry,
|
||||
.wl_shm = options.wl_shm,
|
||||
.wallpaper_image = try WallpaperImage.create("FIXME"), // FIXME: TODO: Get this from Config
|
||||
.wm = try WindowManager.create(context, options.river_window_manager_v1),
|
||||
.xkb_bindings = try XkbBindings.create(context, options.river_xkb_bindings_v1),
|
||||
.config = options.config,
|
||||
};
|
||||
|
||||
return context;
|
||||
|
|
@ -80,9 +94,11 @@ const std = @import("std");
|
|||
const wayland = @import("wayland");
|
||||
const river = wayland.client.river;
|
||||
const wl = wayland.client.wl;
|
||||
const zwlr = wayland.client.zwlr;
|
||||
|
||||
const utils = @import("utils.zig");
|
||||
const Config = @import("Config.zig");
|
||||
const WallpaperImage = @import("WallpaperImage.zig");
|
||||
const WindowManager = @import("WindowManager.zig");
|
||||
const XkbBindings = @import("XkbBindings.zig");
|
||||
|
||||
|
|
|
|||
60
src/WallpaperImage.zig
Normal file
60
src/WallpaperImage.zig
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// SPDX-FileCopyrightText: 2026 Ben Buhse <me@benbuhse.email>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
const WallpaperImage = @This();
|
||||
|
||||
image: *pixman.Image,
|
||||
pixels: std.ArrayList(u32),
|
||||
|
||||
// TODO: Make image_path nullable, if null, do a single color with a single_pixel_buffer instead(?)
|
||||
pub fn create(image_path: []const u8) !*WallpaperImage {
|
||||
var wallpaper_image = try utils.allocator.create(WallpaperImage);
|
||||
errdefer utils.allocator.destroy(wallpaper_image);
|
||||
|
||||
var read_buf: [zigimg.io.DEFAULT_BUFFER_SIZE]u8 = undefined;
|
||||
var image = try zigimg.Image.fromFilePath(utils.allocator, image_path, &read_buf);
|
||||
defer image.deinit(utils.allocator);
|
||||
|
||||
// We don't want to deal with all the possible formats,
|
||||
// so let's just convert to one we can use with pixman.
|
||||
if (image.pixelFormat() != .rgba32) {
|
||||
try image.convert(utils.allocator, .rgba32);
|
||||
}
|
||||
|
||||
log.debug("image loaded ({}x{})", .{ image.width, image.height });
|
||||
|
||||
const pixels = image.pixels.rgba32;
|
||||
// We have to manually convert to argb --
|
||||
// It's only guaranteed that Wayland compositors will have xrgb and argb support but zigimg doesn't have either of those.
|
||||
wallpaper_image.pixels = try std.ArrayList(u32).initCapacity(utils.allocator, pixels.len);
|
||||
errdefer wallpaper_image.pixels.deinit(utils.allocator);
|
||||
for (0..pixels.len) |i| {
|
||||
const a: u32 = @intCast(pixels[i].a);
|
||||
const r: u32 = @intCast(pixels[i].r);
|
||||
const g: u32 = @intCast(pixels[i].g);
|
||||
const b: u32 = @intCast(pixels[i].b);
|
||||
const new_val: u32 = (a << 24) + (r << 16) + (g << 8) + b;
|
||||
try wallpaper_image.pixels.append(utils.allocator, new_val);
|
||||
}
|
||||
|
||||
wallpaper_image.image = pixman.Image.createBits(.a8r8g8b8, @intCast(image.width), @intCast(image.height), @ptrCast(@alignCast(wallpaper_image.pixels.items.ptr)), @intCast(image.width * image.pixelFormat().pixelStride())) orelse return error.FailedToCreatePixmanImage;
|
||||
|
||||
return wallpaper_image;
|
||||
}
|
||||
|
||||
pub fn destroy(wallpaper_image: *WallpaperImage) void {
|
||||
_ = wallpaper_image.image.unref();
|
||||
wallpaper_image.pixels.deinit(utils.allocator);
|
||||
|
||||
utils.allocator.destroy(wallpaper_image);
|
||||
}
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
const pixman = @import("pixman");
|
||||
const zigimg = @import("zigimg");
|
||||
|
||||
const utils = @import("utils.zig");
|
||||
|
||||
const log = std.log.scoped(.WallpaperImage);
|
||||
35
src/main.zig
35
src/main.zig
|
|
@ -2,11 +2,15 @@
|
|||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
/// Wayland globals that we need to bind to
|
||||
/// Wayland globals that we need to bind listen in alphabetical order
|
||||
const Globals = struct {
|
||||
wl_compositor: ?*wl.Compositor = null,
|
||||
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,
|
||||
zwlr_layer_shell_v1: ?*zwlr.LayerShellV1 = null,
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
|
|
@ -30,20 +34,28 @@ pub fn main() !void {
|
|||
fatal("Initial roundtrip failed: E{s}", .{@tagName(errno)});
|
||||
}
|
||||
|
||||
const wl_compositor = globals.wl_compositor orelse utils.interfaceNotAdvertised(wl.Compositor);
|
||||
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();
|
||||
defer config.destroy();
|
||||
const context = try Context.create(
|
||||
wl_display,
|
||||
wl_registry,
|
||||
wl_compositor,
|
||||
river_window_manager_v1,
|
||||
river_xkb_bindings_v1,
|
||||
config,
|
||||
);
|
||||
const context = try Context.create(.{
|
||||
.wl_compositor = wl_compositor,
|
||||
.wl_display = wl_display,
|
||||
.wl_output = wl_output,
|
||||
.wl_registry = wl_registry,
|
||||
.wl_shm = wl_shm,
|
||||
.river_layer_shell_v1 = river_layer_shell_v1,
|
||||
.river_window_manager_v1 = river_window_manager_v1,
|
||||
.river_xkb_bindings_v1 = river_xkb_bindings_v1,
|
||||
.zwlr_layer_shell_v1 = zwlr_layer_shell_v1,
|
||||
.config = config,
|
||||
});
|
||||
defer context.destroy();
|
||||
|
||||
while (true) {
|
||||
|
|
@ -86,6 +98,7 @@ const process = std.process;
|
|||
const wayland = @import("wayland");
|
||||
const river = wayland.client.river;
|
||||
const wl = wayland.client.wl;
|
||||
const zwlr = wayland.client.zwlr;
|
||||
|
||||
const utils = @import("utils.zig");
|
||||
const Config = @import("Config.zig");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue