rework input and new log entry handling

This commit is contained in:
Squibid 2025-12-10 14:35:46 -05:00
parent a41abb7e6b
commit 82a2601e6c
Signed by: squibid
GPG key ID: BECE5684D3C4005D
4 changed files with 41 additions and 88 deletions

View file

@ -15,6 +15,7 @@ pub fn build(b: *std.Build) void {
const wlroots = b.dependency("wlroots", .{}).module("wlroots");
const zlua = b.dependency("zlua", .{}).module("zlua");
const zargs = b.dependency("args", .{ .target = target, .optimize = optimize }).module("args");
const linenoize = b.dependency("linenoize", .{}).module("linenoise");
wlroots.addImport("wayland", wayland);
wlroots.resolved_target = target;
@ -35,6 +36,7 @@ pub fn build(b: *std.Build) void {
whet.root_module.addImport("wlroots", wlroots);
whet.root_module.addImport("zlua", zlua);
whet.root_module.addImport("args", zargs);
whet.root_module.addImport("linenoize", linenoize);
whet.root_module.linkSystemLibrary("wayland-client", .{});

View file

@ -20,6 +20,10 @@
.url = "git+https://github.com/ikskuh/zig-args?ref=master#e060ac80c244e9675471b6d213b22ddc83cc8f98",
.hash = "args-0.0.0-CiLiqo_RAADz2TiHUzG5-0Mk7IZHR-h1SZgUrb_k4c7d",
},
.linenoize = .{
.url = "git+https://github.com/Squibid/linenoize#b873710c9107d176e1a8d7b3b36df57f77447ce6",
.hash = "linenoize-0.1.1-J7HK8NTiAABSqJQoK5IQ-EfVdX4nples5yHeP7bCji7D",
},
},
.paths = .{
"build.zig",

View file

@ -1,5 +1,6 @@
const std = @import("std");
const argsParser = @import("args");
const Linenoize = @import("linenoize").Linenoise;
const util = @import("util.zig");
const Remote = @import("remote.zig");
@ -20,60 +21,28 @@ const usage =
\\
;
fn loop(input: bool) !void {
var pollfds: [2]std.posix.pollfd = undefined;
fn inputThreadRun() !void {
const ln: *Linenoize = @constCast(&Linenoize.init(gpa));
defer ln.deinit();
pollfds[0] = .{ // wayland fd
.fd = remote.display.getFd(),
.events = std.posix.POLL.IN,
.revents = 0,
};
if (input) {
pollfds[1] = .{ // stdin
.fd = std.posix.STDIN_FILENO,
.events = std.posix.POLL.IN,
.revents = 0,
};
}
var buf: [2]u8 = undefined;
var stdout_writer = std.fs.File.stdout().writer(&buf);
const stdout = &stdout_writer.interface;
while (true) {
if (input) {
try stdout.print("> ", .{});
try stdout.flush();
const in = ln.linenoise("> ") catch |err| switch (err) {
error.CtrlC => std.process.exit(130),
else => return err,
} orelse continue;
defer gpa.free(in);
if (remote.remote_lua) |rl| {
const w_sentinel = gpa.allocSentinel(u8, in.len, 0) catch util.oom();
defer gpa.free(w_sentinel);
std.mem.copyForwards(u8, w_sentinel, in[0..in.len]);
rl.pushLua(w_sentinel);
const err = remote.display.flush();
if (err != .SUCCESS) util.fatal("lost connection to the wayland socket", .{});
}
_ = std.posix.poll(&pollfds, -1) catch |err| {
util.fatal("poll() failed: {s}", .{@errorName(err)});
};
for (pollfds) |fd| {
if (fd.revents & std.posix.POLL.IN == 1) {
if (fd.fd == std.posix.STDIN_FILENO) {
var in_buf: [1024]u8 = undefined;
const len = std.posix.read(fd.fd, &in_buf) catch 0;
if (len == 0) {
try stdout.print("\n", .{});
continue;
}
if (in_buf[len - 1] == '\n') in_buf[len - 1] = 0 else in_buf[len] = 0;
if (remote.remote_lua) |rl| rl.pushLua(@ptrCast(in_buf[0..len].ptr));
}
// FIXME: we really shouldn't be reading from the socket
if (fd.fd == remote.display.getFd()) {
var in_buf: [1024]u8 = undefined;
const len = std.posix.read(fd.fd, &in_buf) catch 0;
std.debug.print("\n{s}", .{in_buf[0..len]});
}
}
}
try remote.flush();
try ln.history.add(in);
}
}
@ -101,13 +70,16 @@ pub fn main() !void {
// connect to the compositor
remote = Remote.init();
defer remote.deinit();
var input_thread: std.Thread = undefined;
// handle options
if (options.options.code) |c| {
remote.remote_lua.?.pushLua(@ptrCast(c[0..].ptr));
} else if (options.options.@"follow-log") {
try loop(false);
} else {
try loop(true);
} else if (!options.options.@"follow-log") {
input_thread = try .spawn(.{}, inputThreadRun, .{});
}
while (remote.display.dispatch() == .SUCCESS) {}
input_thread.join();
}

View file

@ -39,7 +39,7 @@ pub fn init() Remote {
self.remote_lua = self.remote_lua_manager.?.getRemote() catch util.oom();
if (self.remote_lua) |rl| {
rl.setListener(?*anyopaque, handleRemote, null);
rl.setListener(*Remote, handleRemote, @constCast(&self));
} else {
util.fatal("failed to setup the remote listener", .{});
}
@ -47,35 +47,12 @@ pub fn init() Remote {
return self;
}
pub fn flush(self: *Remote) !void {
while (true) {
while (!self.display.prepareRead()) {
const errno = self.display.dispatchPending();
if (errno != .SUCCESS) {
util.fatal("failed to dispatch pending wayland events: E{s}", .{@tagName(errno)});
}
}
const errno = self.display.flush();
switch (errno) {
.SUCCESS => return,
.PIPE => {
// libwayland uses this error to indicate that the wayland server
// closed its side of the wayland socket. We want to continue to
// read any buffered messages from the server though as there is
// likely a protocol error message we'd like libwayland to log.
_ = self.display.readEvents();
util.fatal("connection to wayland server unexpectedly terminated", .{});
},
else => {
util.fatal("failed to flush wayland requests: E{s}", .{@tagName(errno)});
},
}
}
}
pub fn deinit(self: *Remote) void {
self.registry.destroy();
if (self.remote_lua_manager) |rl_manager| rl_manager.destroy();
if (self.remote_lua) |rl| rl.destroy();
if (self.compositor) |comp| comp.destroy();
self.display.disconnect();
}
fn registry_listener(
@ -93,7 +70,7 @@ fn registry_event(registry: *wl.Registry, event: wl.Registry.Event, remote: *Rem
.global => |ev| {
if (std.mem.orderZ(u8, ev.interface, wl.Compositor.interface.name) == .eq) {
const ver = 1;
if (ev.version < 1) {
if (ev.version < ver) {
util.fatal("advertised wl_compositor version too old, version {} required", .{ver});
}
remote.compositor = try registry.bind(ev.name, wl.Compositor, ver);
@ -109,12 +86,10 @@ fn registry_event(registry: *wl.Registry, event: wl.Registry.Event, remote: *Rem
}
}
// FIXME: this doesn't actually handle events for some reason and we currently
// just read from the socket directly
fn handleRemote(_: *mez.RemoteLuaV1, event: mez.RemoteLuaV1.Event, _: ?*anyopaque) void {
fn handleRemote(_: *mez.RemoteLuaV1, event: mez.RemoteLuaV1.Event, _: *Remote) void {
switch (event) {
.new_log_entry => |e| {
std.log.info("{s}", .{e.text});
std.debug.print("\r{s}\r\n", .{e.text});
},
}
}