Wallpickr compatibility with Aestuarium newest version

This commit is contained in:
Marcius 2024-03-08 01:57:22 +00:00
parent 26a5e526b5
commit 7e432b59e2
8 changed files with 179 additions and 62 deletions

View file

@ -1,20 +1,3 @@
# Aestuarium
Yet another wayland background manager using openGL. This is still in very early stages of development and I don't recommend anyone to use it yet.
### Why another tool for background in wayland?
Because all other tools for background didn't have the features I want and also nothing bad in some competition
### Why the name "Aestuarium"
It is the latin for [Estuary](https://en.wikipedia.org/wiki/Estuary), I will leave the explanation to your imagination.
### Dependencies
- [zigimg/zigimg](https://github.com/zigimg/zigimg)
- [getty-zig/json](https://github.com/getty-zig/json)
- [ifeund/zig-wayland](https://codeberg.org/ifreund/zig-wayland)
- [ziglibs/known-folders](https://github.com/ziglibs/known-folders)
- [ziglibs/ini](https://github.com/ziglibs/ini)
- [MasterQ32/zig-args](https://github.com/MasterQ32/zig-args)
Well, at the moment this is a complet copy of the original project but I plan to later on make some changes here

View file

@ -1,6 +1,7 @@
const std = @import("std");
const Outputs = @import("Outputs.zig");
const Render = @import("Render.zig");
const Preload = @import("Preload.zig");
const Allocator = std.mem.Allocator;
@ -18,6 +19,7 @@ layer_shell: ?*zwlr.LayerShellV1 = null,
xdg_output_manager: ?*zxdg.OutputManagerV1 = null,
outputs_info: ?Outputs = null,
rendered_outputs: ?[]*Render = null,
preloaded: ?*Preload = null,
const Globals = @This();
@ -127,7 +129,7 @@ fn registryListener(registry: *wl.Registry, ev: wl.Registry.Event, data: *Global
.global_remove => |remove_event| {
//TODO handle output removed
std.log.warn("Global Removed {}", .{remove_event.name});
std.log.warn("Global Removed {}", .{remove_event});
},
}
}

View file

@ -0,0 +1,91 @@
const std = @import("std");
const zigimg = @import("zigimg");
const c = @import("ffi.zig");
const Allocator = std.mem.Allocator;
const Image = zigimg.Image;
const Preload = @This();
alloc: Allocator,
preloaded_list: std.ArrayList(*Preloaded),
const Preloaded = struct {
index: usize,
path: []const u8,
height: c_int,
width: c_int,
bytes: []const u8,
format: c_int,
zigimg: *Image,
};
pub fn init(alloc: Allocator) Preload {
return .{
.alloc = alloc,
.preloaded_list = std.ArrayList(*Preloaded).init(alloc),
};
}
pub fn preload(self: *Preload, path: []const u8) !void {
if (self.findPreloaded(path) != null) {
std.log.warn("Already preloaded", .{});
return;
}
var image = try zigimg.Image.fromFilePath(self.alloc, path);
var preloaded = try self.alloc.create(Preloaded);
std.debug.print("to preload: {s}", .{path});
const new_mem_path = try self.alloc.alloc(u8, path.len);
@memcpy(new_mem_path, path);
preloaded.path = new_mem_path;
preloaded.bytes = image.rawBytes();
preloaded.height = @intCast(image.height);
preloaded.width = @intCast(image.width);
preloaded.zigimg = ℑ
preloaded.format = try switch (image.pixelFormat()) {
.rgba32, .rgba64 => c.GL_RGBA,
.rgb24, .rgb48, .rgb565, .rgb555 => c.GL_RGB,
.bgr24, .bgr555 => c.GL_BGR,
.bgra32 => c.GL_BGRA,
else => error.FormatUnsuported,
};
try self.preloaded_list.append(preloaded);
preloaded.index = self.preloaded_list.items.len - 1;
}
pub fn findPreloaded(self: Preload, path: []const u8) ?*Preloaded {
for (self.preloaded_list.items) |preloaded| {
if (std.mem.eql(u8, preloaded.path, path)) {
return preloaded;
}
}
return null;
}
pub fn unload(self: *Preload, path: []const u8) void {
if (std.mem.eql(u8, "all", path)) {
self.preloaded_list.deinit();
self.preloaded_list = std.ArrayList(*Preloaded).init(self.alloc);
return;
}
if (self.findPreloaded(path)) |preloaded| {
preloaded.zigimg.deinit();
self.alloc.destroy(preloaded);
_ = self.preloaded_list.orderedRemove(preloaded.index);
}
}
pub fn deinit(self: *Preload) void {
for (self.preloaded_list.items) |preloaded| {
preloaded.zigimg.deinit();
self.alloc.free(preloaded.path);
self.alloc.destroy(preloaded);
}
self.preloaded_list.deinit();
}

View file

@ -1,12 +1,14 @@
const std = @import("std");
const c = @import("ffi.zig");
const wayland = @import("wayland");
const zigimg = @import("zigimg");
const Globals = @import("Globals.zig");
const OutputInfo = @import("Outputs.zig").OutputInfo;
const Allocator = std.mem.Allocator;
const zigimg = @import("zigimg");
const Image = zigimg.Image;
const Preload = @import("Preload.zig");
const wayland = @import("wayland");
const Allocator = std.mem.Allocator;
const Image = zigimg.Image;
const wl = wayland.client.wl;
const zxdg = wayland.client.zxdg;
const zwlr = wayland.client.zwlr;
@ -21,6 +23,7 @@ egl_context: c.EGLContext,
egl_window: *wl.EglWindow,
egl_surface: c.EGLSurface,
output_info: OutputInfo,
preload: *Preload,
pub fn init(
alloc: Allocator,
@ -28,6 +31,7 @@ pub fn init(
display: *wl.Display,
layer_shell: ?*zwlr.LayerShellV1,
output_info: OutputInfo,
preload: *Preload,
) !Render {
const surface = try compositor.?.createSurface();
@ -119,23 +123,12 @@ pub fn init(
.layer = layer_surface,
.surface = surface,
.output_info = output_info,
.preload = preload,
};
}
pub fn setWallpaper(self: *Render, path: []const u8) !void {
var image = try zigimg.Image.fromFilePath(self.allocator, path);
defer image.deinit();
//only support RGB AND RGBA yet
const image_format: c_int = try switch (image.pixelFormat()) {
.rgba32, .rgba64 => c.GL_RGBA,
.rgb24, .rgb48, .rgb565, .rgb555 => c.GL_RGB,
else => error.FormatUnsuported,
};
const width: c_int = @intCast(image.width);
const height: c_int = @intCast(image.height);
const texture = image.rawBytes();
const preloaded = self.preload.findPreloaded(path) orelse return error.ImageNotPreloaded;
// Vertex Shader
const vertexShaderSource = @embedFile("shaders/main_vertex_shader.glsl");
@ -253,13 +246,13 @@ pub fn setWallpaper(self: *Render, path: []const u8) !void {
c.glTexImage2D(
c.GL_TEXTURE_2D,
0,
image_format,
width,
height,
preloaded.format,
preloaded.width,
preloaded.height,
0,
@intCast(image_format),
@intCast(preloaded.format),
c.GL_UNSIGNED_BYTE,
texture.ptr,
preloaded.bytes.ptr,
);
c.glGenerateMipmap(c.GL_TEXTURE_2D);
@ -269,7 +262,6 @@ pub fn setWallpaper(self: *Render, path: []const u8) !void {
c.glDrawElements(c.GL_TRIANGLES, 6, c.GL_UNSIGNED_BYTE, @ptrFromInt(0));
try getEglError();
try getEglError();
// swap double-buffered framebuffer
if (c.eglSwapBuffers(self.egl_display, self.egl_surface) != c.EGL_TRUE) return error.EGLError;

View file

@ -8,14 +8,10 @@ const Outputs = @import("Outputs.zig");
const Config = @import("Config.zig");
const Render = @import("Render.zig");
const Server = @import("socket/Server.zig");
const Preload = @import("Preload.zig");
const Allocator = std.mem.Allocator;
const wayland = @import("wayland");
const wl = wayland.client.wl;
const zxdg = wayland.client.zxdg;
const zwlr = wayland.client.zwlr;
pub const std_options = .{
.logFn = @import("log.zig").log,
.log_level = .debug,
@ -87,19 +83,27 @@ fn runMainInstance(alloc: Allocator) !u8 {
var rendered_outputs = std.ArrayList(*Render).init(alloc);
defer rendered_outputs.deinit();
var preload = Preload.init(alloc);
defer preload.deinit();
globals.preloaded = &preload;
for (config.monitor_wallpapers) |mw| {
const output_info = globals.outputs_info.?.findOutputByName(mw.monitor) orelse {
std.log.warn("Monitor {s} not found", .{mw.monitor});
continue;
};
try preload.preload(mw.wallpaper);
var rendered = try Render.init(
alloc,
globals.compositor,
globals.display,
globals.layer_shell,
output_info,
&preload,
);
std.debug.print("{s}\n", .{mw.wallpaper});
try rendered.setWallpaper(mw.wallpaper);
try rendered_outputs.append(&rendered);
}
@ -135,9 +139,10 @@ fn runMainInstance(alloc: Allocator) !u8 {
return 1;
}
const MAX_EVENT_COUNT: usize = 10;
while (true) {
var epoll_events: [2]c.epoll_event = undefined;
const ev_count = c.epoll_wait(epoll_fd, &epoll_events, 2, -1);
var epoll_events: [MAX_EVENT_COUNT]c.epoll_event = undefined;
const ev_count = c.epoll_wait(epoll_fd, &epoll_events, MAX_EVENT_COUNT, -1);
if (ev_count == -1) {
std.log.err("epoll wait failed", .{});
return 1;
@ -147,7 +152,7 @@ fn runMainInstance(alloc: Allocator) !u8 {
while (i <= ev_count) : (i += 1) {
if (epoll_events[i].data.fd == display_fd) {
std.log.info("epoll display global event", .{});
if (globals.display.dispatch() != .SUCCESS) return error.foo;
if (globals.display.roundtrip() != .SUCCESS) return error.RoundTripFail;
}
if (epoll_events[i].data.fd == server.fd) {
std.log.info("epoll socket server event", .{});

View file

@ -46,7 +46,8 @@ pub fn init(alloc: Allocator, globals: *Globals) !Server {
pub fn handleConnection(self: *Server) !void {
const connection = try self.stream_server.accept();
defer connection.stream.close();
errdefer connection.stream.close();
std.log.info("Accepting incoming connection...", .{});
var buff: [std.fs.MAX_PATH_BYTES + 200]u8 = undefined;
@ -57,6 +58,18 @@ pub fn handleConnection(self: *Server) !void {
var it = std.mem.splitAny(u8, buff[0..response_size], " =");
if (it.next()) |command| {
if (std.mem.eql(u8, "preload", command)) {
if (it.next()) |wallpaper| {
self.globals.preloaded.?.preload(std.mem.trim(u8, wallpaper, "\x0a")) catch |err| {
std.log.err("{s}", .{@errorName(err)});
_ = try connection.stream.write(@errorName(err));
return;
};
_ = try connection.stream.write("preloaded successfully");
return;
}
}
if (std.mem.eql(u8, "wallpaper", command)) {
if (it.next()) |monitor| {
if (it.next()) |wallpaper| {
@ -65,10 +78,11 @@ pub fn handleConnection(self: *Server) !void {
if (std.mem.eql(u8, output.output_info.name.?, monitor)) {
// Trimming because socat add a trailing space
self.globals.rendered_outputs.?[i].setWallpaper(std.mem.trim(u8, wallpaper, "\x0a")) catch |err| {
std.log.debug("{s}", .{@errorName(err)});
break;
std.log.err("{s}", .{@errorName(err)});
_ = try connection.stream.write(@errorName(err));
return;
};
_ = try connection.stream.write("changed successfully");
_ = try connection.stream.write("Changed successfully!\n");
break;
}
}
@ -77,6 +91,13 @@ pub fn handleConnection(self: *Server) !void {
return error.RenderedOutputsNull;
}
}
return;
}
}
if (std.mem.eql(u8, "unload", command)) {
if (it.next()) |wallpaper| {
self.globals.preloaded.?.unload(wallpaper);
_ = try connection.stream.write("Unloaded successfully!\n");
}
}
}

View file

@ -34,5 +34,5 @@ end
os.execute("river")
buildZigScripts(listDirectories())
buildzigscripts(listdirectories())

View file

@ -32,7 +32,7 @@ fn getActiveMonitor(alloc: Allocator, signature: ?[]const u8) ![]const u8 {
}
}
pub fn setWallpaperToCurrentMonitorHyprland(alloc: Allocator, path: []const u8) !void {
pub fn setWallpaperToCurrentMonitorHyprpaper(alloc: Allocator, path: []const u8) !void {
var arena = std.heap.ArenaAllocator.init(alloc);
defer arena.deinit();
@ -83,8 +83,10 @@ pub fn setWallpaperToCurrentMonitorAestuarium(alloc: Allocator, path: []const u8
const aestuarium_socket_path =
try std.fs.path.join(alloc, &.{ env, "aestuarium.sock" });
const stream = try std.net.connectUnixSocket(aestuarium_socket_path);
defer stream.close();
const preload_msg = try std.mem.concat(arena.allocator(), u8, &[_][]const u8{
"preload ",
path,
});
const wallpaper_msg = try std.mem.concat(arena.allocator(), u8, &[_][]const u8{
"wallpaper ",
@ -93,7 +95,28 @@ pub fn setWallpaperToCurrentMonitorAestuarium(alloc: Allocator, path: []const u8
path,
});
_ = try stream.write(wallpaper_msg);
const bytes_len = try stream.read(&buf);
std.log.info("{s}", .{buf[0..bytes_len]});
const unload_msg = "unload all";
var bytes: usize = 0;
{
const stream = try std.net.connectUnixSocket(aestuarium_socket_path);
defer stream.close();
_ = try stream.write(preload_msg);
bytes = try stream.read(&buf);
std.log.info("{s}", .{buf[0..bytes]});
}
{
const stream = try std.net.connectUnixSocket(aestuarium_socket_path);
defer stream.close();
_ = try stream.write(wallpaper_msg);
bytes = try stream.read(&buf);
std.log.info("{s}", .{buf[0..bytes]});
}
{
const stream = try std.net.connectUnixSocket(aestuarium_socket_path);
defer stream.close();
_ = try stream.write(unload_msg);
bytes = try stream.read(&buf);
std.log.info("{s}", .{buf[0..bytes]});
}
}