Merge branch 'mez_remote_lua' into dev

This commit is contained in:
Squibid 2025-12-10 20:19:42 -05:00
commit 1f2e333846
Signed by: squibid
GPG key ID: BECE5684D3C4005D
7 changed files with 293 additions and 39 deletions

103
src/RemoteLua.zig Normal file
View file

@ -0,0 +1,103 @@
const RemoteLua = @This();
const std = @import("std");
const zlua = @import("zlua");
const wayland = @import("wayland");
const Utils = @import("Utils.zig");
const Lua = @import("lua/Lua.zig");
const wl = wayland.server.wl;
const mez = wayland.server.zmez;
const gpa = std.heap.c_allocator;
const server = &@import("main.zig").server;
node: std.DoublyLinkedList.Node,
remote_lua_v1: *mez.RemoteLuaV1,
L: *zlua.Lua,
pub fn sendNewLogEntry(str: [*:0]const u8) void {
var node = server.remote_lua_clients.first;
while (node) |n| {
const data: ?*RemoteLua = @fieldParentPtr("node", n);
if (data) |d| d.remote_lua_v1.sendNewLogEntry(str);
node = n.next;
}
}
pub fn create(client: *wl.Client, version: u32, id: u32) !void {
const remote_lua_v1 = try mez.RemoteLuaV1.create(client, version, id);
const node = try gpa.create(RemoteLua);
errdefer gpa.destroy(node);
node.* = .{
.remote_lua_v1 = remote_lua_v1,
.node = .{},
.L = try zlua.Lua.init(gpa),
};
errdefer node.L.deinit();
node.L.openLibs();
Lua.openLibs(node.L);
// TODO: replace stdout and stderr with buffers we can send to the clients
server.remote_lua_clients.prepend(&node.node);
remote_lua_v1.setHandler(*RemoteLua, handleRequest, handleDestroy, node);
}
fn handleRequest(
remote_lua_v1: *mez.RemoteLuaV1,
request: mez.RemoteLuaV1.Request,
remote: *RemoteLua,
) void {
const L = remote.L;
switch (request) {
.destroy => remote_lua_v1.destroy(),
.push_lua => |req| {
const chunk: [:0]const u8 = std.mem.sliceTo(req.lua_chunk, 0);
const str = std.mem.concatWithSentinel(gpa, u8, &[_][]const u8{
"return ",
chunk,
";",
}, 0) catch return catchLuaFail(remote);
defer gpa.free(str);
zlua.Lua.loadBuffer(L, str, "=repl", zlua.Mode.text) catch {
L.pop(L.getTop());
L.loadString(chunk) catch {
catchLuaFail(remote);
L.pop(-1);
};
return;
};
L.protectedCall(.{ .results = zlua.mult_return, }) catch {
catchLuaFail(remote);
L.pop(1);
};
var i: i32 = 1;
const nresults = L.getTop();
while (i <= nresults) : (i += 1) {
// TODO: support lua5.1 and luajit?
sendNewLogEntry(L.toStringEx(i));
L.pop(-1);
}
},
}
}
fn handleDestroy(_: *mez.RemoteLuaV1, remote_lua: *RemoteLua) void {
if (remote_lua.node.prev) |p| {
if (remote_lua.node.next) |n| n.prev.? = p;
p.next = remote_lua.node.next;
} else server.remote_lua_clients.first = remote_lua.node.next;
remote_lua.L.deinit();
gpa.destroy(remote_lua);
}
fn catchLuaFail(remote: *RemoteLua) void {
const err: [:0]const u8 = remote.L.toStringEx(-1);
sendNewLogEntry(std.mem.sliceTo(err, 0));
}

49
src/RemoteLuaManager.zig Normal file
View file

@ -0,0 +1,49 @@
const RemoteLuaManager = @This();
const std = @import("std");
const wayland = @import("wayland");
const Utils = @import("Utils.zig");
const RemoteLua = @import("RemoteLua.zig");
const wl = wayland.server.wl;
const mez = wayland.server.zmez;
const gpa = std.heap.c_allocator;
const server = &@import("main.zig").server;
global: *wl.Global,
pub fn init() !?*RemoteLuaManager {
const self = try gpa.create(RemoteLuaManager);
self.global = try wl.Global.create(server.wl_server, mez.RemoteLuaManagerV1, 1, ?*anyopaque, null, bind);
return self;
}
fn bind(client: *wl.Client, _: ?*anyopaque, version: u32, id: u32) void {
const remote_lua_manager_v1 = mez.RemoteLuaManagerV1.create(client, version, id) catch {
client.postNoMemory();
Utils.oomPanic();
};
remote_lua_manager_v1.setHandler(?*anyopaque, handleRequest, null, null);
}
fn handleRequest(
remote_lua_manager_v1: *mez.RemoteLuaManagerV1,
request: mez.RemoteLuaManagerV1.Request,
_: ?*anyopaque,
) void {
switch (request) {
.destroy => remote_lua_manager_v1.destroy(),
.get_remote => |req| {
RemoteLua.create(
remote_lua_manager_v1.getClient(),
remote_lua_manager_v1.getVersion(),
req.id,
) catch {
remote_lua_manager_v1.getClient().postNoMemory();
Utils.oomPanic();
};
},
}
}

View file

@ -16,6 +16,8 @@ const Keymap = @import("types/Keymap.zig");
const Hook = @import("types/Hook.zig");
const Events = @import("types/Events.zig");
const Popup = @import("Popup.zig");
const RemoteLua = @import("RemoteLua.zig");
const RemoteLuaManager = @import("RemoteLuaManager.zig");
const gpa = std.heap.c_allocator;
const server = &@import("main.zig").server;
@ -26,6 +28,7 @@ renderer: *wlr.Renderer,
backend: *wlr.Backend,
event_loop: *wl.EventLoop,
session: ?*wlr.Session,
remote_lua_manager: ?*RemoteLuaManager,
shm: *wlr.Shm,
xdg_shell: *wlr.XdgShell,
@ -44,6 +47,7 @@ cursor: Cursor,
keymaps: std.AutoHashMap(u64, Keymap),
hooks: std.ArrayList(*Hook),
events: Events,
remote_lua_clients: std.DoublyLinkedList,
// Backend listeners
new_input: wl.Listener(*wlr.InputDevice) = .init(handleNewInput),
@ -98,9 +102,11 @@ pub fn init(self: *Server) void {
.root = undefined,
.seat = undefined,
.cursor = undefined,
.remote_lua_manager = RemoteLuaManager.init() catch Utils.oomPanic(),
.keymaps = .init(gpa),
.hooks = try .initCapacity(gpa, 10), // TODO: choose how many slots to start with
.events = try .init(gpa),
.remote_lua_clients = .{},
};
self.renderer.initServer(wl_server) catch {

View file

@ -45,49 +45,53 @@ fn loadConfigDir(self: *Lua) !void {
try self.state.doFile(path);
}
pub fn openLibs(self: *zlua.Lua) void {
{
self.newTable();
defer _ = self.setGlobal("mez");
{
self.newTable();
defer _ = self.setField(-2, "path");
}
{
const fs_funcs = zlua.fnRegsFromType(Fs);
self.newLib(fs_funcs);
self.setField(-2, "fs");
}
{
const input_funcs = zlua.fnRegsFromType(Input);
self.newLib(input_funcs);
self.setField(-2, "input");
}
{
const hook_funcs = zlua.fnRegsFromType(Hook);
self.newLib(hook_funcs);
self.setField(-2, "hook");
}
{
const api_funcs = zlua.fnRegsFromType(Api);
self.newLib(api_funcs);
self.setField(-2, "api");
}
{
const view_funcs = zlua.fnRegsFromType(View);
self.newLib(view_funcs);
self.setField(-2, "view");
}
{
const output_funcs = zlua.fnRegsFromType(Output);
self.newLib(output_funcs);
self.setField(-2, "output");
}
}
}
pub fn init(self: *Lua) !void {
self.state = try zlua.Lua.init(gpa);
errdefer self.state.deinit();
self.state.openLibs();
{
self.state.newTable();
defer _ = self.state.setGlobal("mez");
{
self.state.newTable();
defer _ = self.state.setField(-2, "path");
}
{
const fs_funcs = zlua.fnRegsFromType(Fs);
self.state.newLib(fs_funcs);
self.state.setField(-2, "fs");
}
{
const input_funcs = zlua.fnRegsFromType(Input);
self.state.newLib(input_funcs);
self.state.setField(-2, "input");
}
{
const hook_funcs = zlua.fnRegsFromType(Hook);
self.state.newLib(hook_funcs);
self.state.setField(-2, "hook");
}
{
const api_funcs = zlua.fnRegsFromType(Api);
self.state.newLib(api_funcs);
self.state.setField(-2, "api");
}
{
const view_funcs = zlua.fnRegsFromType(View);
self.state.newLib(view_funcs);
self.state.setField(-2, "view");
}
{
const output_funcs = zlua.fnRegsFromType(Output);
self.state.newLib(output_funcs);
self.state.setField(-2, "output");
}
}
openLibs(self.state);
loadRuntimeDir(self) catch |err| {
if (err == error.LuaRuntime) {

View file

@ -8,6 +8,7 @@ const wlr = @import("wlroots");
const zlua = @import("zlua");
const Event = @import("Events.zig");
const RemoteLua = @import("../RemoteLua.zig");
const Lua = &@import("../main.zig").lua;
events: std.ArrayList([]const u8), // a list of events
@ -39,7 +40,7 @@ pub fn callback(self: *const Hook, args: anytype) void {
}
Lua.state.protectedCall(.{ .args = i }) catch {
// TODO: add a callback to remote lua when that gets merged
RemoteLua.sendNewLogEntry(Lua.state.toString(-1) catch unreachable);
};
Lua.state.pop(-1);
}