added process spawning

This commit is contained in:
Harrison DiAmbrosio 2025-10-24 23:43:11 -04:00
parent 23ef0049f7
commit 2e2cfeebae
5 changed files with 47 additions and 249 deletions

244
2
View file

@ -1,244 +0,0 @@
//! Maintains state related to cursor position, rendering, and
//! events such as button presses and dragging
pub const Cursor = @This();
const std = @import("std");
const wl = @import("wayland").server.wl;
const wlr = @import("wlroots");
const xkb = @import("xkbcommon");
const View = @import("view.zig");
const Utils = @import("utils.zig");
const c = @import("c.zig").c;
const server = &@import("main.zig").server;
const linux = std.os.linux;
wlr_cursor: *wlr.Cursor,
x_cursor_manager: *wlr.XcursorManager,
motion: wl.Listener(*wlr.Pointer.event.Motion) = .init(handleMotion),
motion_absolute: wl.Listener(*wlr.Pointer.event.MotionAbsolute) = .init(handleMotionAbsolute),
button: wl.Listener(*wlr.Pointer.event.Button) = .init(handleButton),
axis: wl.Listener(*wlr.Pointer.event.Axis) = .init(handleAxis),
frame: wl.Listener(*wlr.Cursor) = .init(handleFrame),
hold_begin: wl.Listener(*wlr.Pointer.event.HoldBegin) = .init(handleHoldBegin),
hold_end: wl.Listener(*wlr.Pointer.event.HoldEnd) = .init(handleHoldEnd),
mode: enum { passthrough, move, resize } = .passthrough,
// Drag information
selected_view: ?*View = null,
drag_start_x: c_int = 0,
drag_start_y: c_int = 0,
drag_view_offset_x: c_int = 0,
drag_view_offset_y: c_int = 0,
pub fn init(self: *Cursor) void {
errdefer Utils.oomPanic();
self.* = .{
.wlr_cursor = try wlr.Cursor.create(),
.x_cursor_manager = try wlr.XcursorManager.create(null, 24),
};
try self.x_cursor_manager.load(1);
self.wlr_cursor.attachOutputLayout(server.root.output_layout);
self.wlr_cursor.events.motion.add(&self.motion);
self.wlr_cursor.events.motion_absolute.add(&self.motion_absolute);
self.wlr_cursor.events.button.add(&self.button);
self.wlr_cursor.events.axis.add(&self.axis);
self.wlr_cursor.events.frame.add(&self.frame);
self.wlr_cursor.events.hold_begin.add(&self.hold_begin);
self.wlr_cursor.events.hold_end.add(&self.hold_end);
}
pub fn deinit(self: *Cursor) void {
self.wlr_cursor.destroy();
self.x_cursor_manager.destroy();
self.motion.link.remove();
self.motion_absolute.link.remove();
self.button.link.remove();
self.axis.link.remove();
self.frame.link.remove();
}
fn updateDrag(self: *Cursor) void {
self.drag_box.width = @as(c_int, @intFromFloat(self.wlr_cursor.x)) - self.drag_box.x;
self.drag_box.height = @as(c_int, @intFromFloat(self.wlr_cursor.y)) - self.drag_box.y;
std.log.debug("{d}, {d}, {d}, {d}", .{self.drag_box.x, self.drag_box.y, self.drag_box.width, self.drag_box.height});
}
pub fn processCursorMotion(self: *Cursor, time_msec: u32) void {
switch (self.mode) {
.passthrough => {
if (server.root.viewAt(self.wlr_cursor.x, self.wlr_cursor.y)) |res| {
server.seat.wlr_seat.pointerNotifyEnter(res.surface, res.sx, res.sy);
server.seat.wlr_seat.pointerNotifyMotion(time_msec, res.sx, res.sy);
} else {
self.wlr_cursor.setXcursor(self.x_cursor_manager, "default");
server.seat.wlr_seat.pointerClearFocus();
}
},
.move => {
const view = self.selected_view.?;
self.updateDrag();
// const half_width = @divFloor(view.xdg_surface.geometry.width, 2);
// const half_height = @divFloor(view.xdg_surface.geometry.width, 2);
view.scene_tree.node.setPosition(
self.drag_box.x + @divFloor(self.drag_box.width, 2),
self.drag_box.y + @divFloor(self.drag_box.height, 2)
);
},
.resize => {
self.updateDrag();
// Fix this resize
//
// REDOING RESIZING AND MOVING TOPLEVELS
// REDOING RESIZING AND MOVING TOPLEVELS
// REDOING RESIZING AND MOVING TOPLEVELS
// REDOING RESIZING AND MOVING TOPLEVELS
//
// const view = self.grabbed_view.?;
// const border_x = @as(i32, @intFromFloat(self.wlr_cursor.x - self.grab_x));
// const border_y = @as(i32, @intFromFloat(self.wlr_cursor.y - self.grab_y));
//
// var new_left = self.grab_box.x;
// var new_right = self.grab_box.x + self.grab_box.width;
// var new_top = self.grab_box.y;
// var new_bottom = self.grab_box.y + self.grab_box.height;
//
// if (self.resize_edges.top) {
// new_top = border_y;
// if (new_top >= new_bottom)
// new_top = new_bottom - 1;
// } else if (self.resize_edges.bottom) {
// new_bottom = border_y;
// if (new_bottom <= new_top)
// new_bottom = new_top + 1;
// }
//
// if (self.resize_edges.left) {
// new_left = border_x;
// if (new_left >= new_right)
// new_left = new_right - 1;
// } else if (self.resize_edges.right) {
// new_right = border_x;
// if (new_right <= new_left)
// new_right = new_left + 1;
// }
//
// // view.x = new_left - view.xdg_toplevel.base.geometry.x;
// // view.y = new_top - view.xdg_toplevel.base.geometry.y;
// view.scene_tree.node.setPosition(view.geometry.x, view.geometry.y);
//
// const new_width = new_right - new_left;
// const new_height = new_bottom - new_top;
// _ = view.xdg_toplevel.setSize(new_width, new_height);
},
}
}
// --------- WLR Cursor event handlers ---------
fn handleMotion(
_: *wl.Listener(*wlr.Pointer.event.Motion),
event: *wlr.Pointer.event.Motion,
) void {
server.cursor.wlr_cursor.move(event.device, event.delta_x, event.delta_y);
server.cursor.processCursorMotion(event.time_msec);
}
fn handleMotionAbsolute(
_: *wl.Listener(*wlr.Pointer.event.MotionAbsolute),
event: *wlr.Pointer.event.MotionAbsolute,
) void {
server.cursor.wlr_cursor.warpAbsolute(event.device, event.x, event.y);
server.cursor.processCursorMotion(event.time_msec);
}
fn handleButton(
listener: *wl.Listener(*wlr.Pointer.event.Button),
event: *wlr.Pointer.event.Button
) void {
const cursor: *Cursor = @fieldParentPtr("button", listener);
_ = server.seat.wlr_seat.pointerNotifyButton(event.time_msec, event.button, event.state);
const view_at_result = server.root.viewAt(cursor.wlr_cursor.x, cursor.wlr_cursor.y);
if (view_at_result) |res| {
server.root.focusView(res.view);
}
std.log.debug("Button pressed {}", .{event.button});
switch (event.state) {
.pressed => {
if(server.keyboard.wlr_keyboard.getModifiers().alt) {
// Can be BTN_RIGHT, BTN_LEFT, or BTN_MIDDLE
if(view_at_result) |res| {
// Keep track of where the drag started
cursor.selected_view = res.view;
cursor.drag_box.x = @as(c_int, @intFromFloat(cursor.wlr_cursor.x));
cursor.drag_box.y = @as(c_int, @intFromFloat(cursor.wlr_cursor.y));
// Maybe comptime this for later reference
if(event.button == c.libevdev_event_code_from_name(c.EV_KEY, "BTN_LEFT")) {
cursor.mode = .move;
} else if(event.button == c.libevdev_event_code_from_name(c.EV_KEY, "BTN_RIGHT")) {
cursor.mode = .resize;
}
}
}
},
.released => {
cursor.mode = .passthrough;
},
else => {
std.log.err("Invalid/Unimplemented pointer button event type", .{});
}
}
}
fn handleHoldBegin(
listener: *wl.Listener(*wlr.Pointer.event.HoldBegin),
event: *wlr.Pointer.event.HoldBegin
) void {
_ = listener;
_ = event;
std.log.err("Unimplemented cursor start hold", .{});
}
fn handleHoldEnd(
listener: *wl.Listener(*wlr.Pointer.event.HoldEnd),
event: *wlr.Pointer.event.HoldEnd
) void {
_ = listener;
_ = event;
std.log.err("Unimplemented cursor end hold", .{});
}
fn handleAxis(
_: *wl.Listener(*wlr.Pointer.event.Axis),
event: *wlr.Pointer.event.Axis,
) void {
server.seat.wlr_seat.pointerNotifyAxis(
event.time_msec,
event.orientation,
event.delta,
event.delta_discrete,
event.source,
event.relative_direction,
);
}
fn handleFrame(_: *wl.Listener(*wlr.Cursor), _: *wlr.Cursor) void {
server.seat.wlr_seat.pointerNotifyFrame();
}

View file

@ -14,3 +14,13 @@ package.path = package.path..";"..mez.fs.joinpath(env_conf, "mez", "lua", "?.lua
mez.api.add_keymap("alt", "a", function() mez.api.add_keymap("alt", "a", function()
print("hello from my keymap") print("hello from my keymap")
end) end)
mez.api.add_keymap("alt", "t", function()
print("spawning foot")
mez.api.spawn("foot")
end)
mez.api.add_keymap("alt", "p", function()
print("spawning foot")
mez.api.spawn("wmenu-run")
end)

View file

@ -23,9 +23,10 @@ pub fn callback(self: *const Keymap) void {
const t = Lua.state.rawGetIndex(zlua.registry_index, self.lua_ref_idx); const t = Lua.state.rawGetIndex(zlua.registry_index, self.lua_ref_idx);
if (t != zlua.LuaType.function) { if (t != zlua.LuaType.function) {
std.log.err("Failed to call keybind, it doesn't have a callback.", .{}); std.log.err("Failed to call keybind, it doesn't have a callback.", .{});
Lua.state.pop(1);
return; return;
} }
Lua.state.pushValue(1);
Lua.state.call(.{ .args = 0, .results = 0 }); Lua.state.call(.{ .args = 0, .results = 0 });
Lua.state.pop(-1); Lua.state.pop(-1);
} }

View file

@ -1,7 +1,6 @@
const Api = @This(); const Api = @This();
const std = @import("std"); const std = @import("std");
const server = &@import("../main.zig").server;
const Keymap = @import("../keymap.zig"); const Keymap = @import("../keymap.zig");
const zlua = @import("zlua"); const zlua = @import("zlua");
@ -9,9 +8,12 @@ const xkb = @import("xkbcommon");
const wlr = @import("wlroots"); const wlr = @import("wlroots");
const gpa = std.heap.c_allocator; const gpa = std.heap.c_allocator;
const server = &@import("../main.zig").server;
const env_map = &@import("../main.zig").env_map;
pub fn add_keymap(L: *zlua.Lua) i32 { pub fn add_keymap(L: *zlua.Lua) i32 {
const nargs: i32 = L.getTop(); const nargs: i32 = L.getTop();
if (nargs < 3) { if (nargs < 3) {
L.raiseErrorStr("Expected at least three arguments", .{}); L.raiseErrorStr("Expected at least three arguments", .{});
return 0; return 0;
@ -23,6 +25,9 @@ pub fn add_keymap(L: *zlua.Lua) i32 {
L.checkType(3, .function); L.checkType(3, .function);
var keymap: Keymap = undefined; var keymap: Keymap = undefined;
keymap.options = .{
.on_release = false,
};
const mod = L.toString(1) catch { const mod = L.toString(1) catch {
L.raiseErrorStr("Lua error check your config", .{}); L.raiseErrorStr("Lua error check your config", .{});
@ -89,3 +94,27 @@ pub fn get_keybind(L: *zlua.Lua) i32 {
_ = L; _ = L;
return 0; return 0;
} }
pub fn spawn(L: *zlua.Lua) i32 {
const nargs: i32 = L.getTop();
if (nargs < 1) {
L.raiseErrorStr("Expected at least one arguments", .{});
return 0;
}
L.checkType(1, .string);
const cmd = L.toString(1) catch {
L.raiseErrorStr("Lua error check your config", .{});
return 0;
};
var child = std.process.Child.init(&[_][]const u8{ "/bin/sh", "-c", cmd }, gpa);
child.env_map = env_map;
child.spawn() catch {
std.log.err("Unable to spawn process \"{s}\"", .{cmd});
};
return 0;
}

View file

@ -8,6 +8,7 @@ const gpa = std.heap.c_allocator;
pub var server: Server = undefined; pub var server: Server = undefined;
pub var lua: Lua = undefined; pub var lua: Lua = undefined;
pub var env_map: std.process.EnvMap = undefined;
pub fn main() !void { pub fn main() !void {
wlr.log.init(.err, null); wlr.log.init(.err, null);
@ -21,15 +22,16 @@ pub fn main() !void {
var buf: [11]u8 = undefined; var buf: [11]u8 = undefined;
const socket = try server.wl_server.addSocketAuto(&buf); const socket = try server.wl_server.addSocketAuto(&buf);
env_map = try std.process.getEnvMap(gpa);
try env_map.put("WAYLAND_DISPLAY", socket);
if (std.os.argv.len >= 2) { if (std.os.argv.len >= 2) {
const cmd = std.mem.span(std.os.argv[1]); const cmd = std.mem.span(std.os.argv[1]);
var child = std.process.Child.init(&[_][]const u8{ "/bin/sh", "-c", cmd }, gpa); var child = std.process.Child.init(&[_][]const u8{ "/bin/sh", "-c", cmd }, gpa);
var env_map = try std.process.getEnvMap(gpa);
defer env_map.deinit();
try env_map.put("WAYLAND_DISPLAY", socket);
child.env_map = &env_map; child.env_map = &env_map;
try child.spawn(); try child.spawn();
} }
defer env_map.deinit();
std.log.info("Starting backend", .{}); std.log.info("Starting backend", .{});
server.backend.start() catch |err| { server.backend.start() catch |err| {