drag working, good callback arguments for moving and resizing views

This commit is contained in:
Harrison DiAmbrosio 2026-01-06 22:21:30 -05:00
parent 9d8463255c
commit 973ea9d509
3 changed files with 142 additions and 99 deletions

View file

@ -275,14 +275,29 @@ local master = function()
end end
mez.input.add_mousemap("alt", "BTN_LEFT", { mez.input.add_mousemap("alt", "BTN_LEFT", {
press = function() drag = function(pos, drag)
print("pressed mouse") if drag.view ~= nil then
mez.input.del_mousemap("alt", "BTN_LEFT"); mez.view.set_position(drag.view.id, pos.x - drag.view.offset.x, pos.y - drag.view.offset.y)
end
end, end,
release = function() print("released mouse") end,
drag = function() print("dragging mouse") end
}) })
mez.input.add_mousemap("alt", "BTN_RIGHT", {
drag = function(pos, drag)
if drag.view ~= nil then
mez.view.set_size(
drag.view.id,
(pos.x - drag.start.x) + drag.view.offset.x,
(pos.y - drag.start.y) + drag.view.offset.y
)
-- mez.view.set_size(
-- drag.view.id,
-- (pos.x - drag.start.x) + drag.view.offset.x + (drag.view.dims.width - drag.view.offset.x),
-- (pos.y - drag.start.y) + drag.view.offset.y + (drag.view.dims.height - drag.view.offset.y)
-- )
end
end,
})
end end
master() master()

View file

@ -29,12 +29,17 @@ hold_end: wl.Listener(*wlr.Pointer.event.HoldEnd) = .init(handleHoldEnd),
mode: enum { normal, drag } = .normal, mode: enum { normal, drag } = .normal,
// Drag information // Drag information
drag: struct { drag: ?struct {
start_x: c_int, event_code: u32,
start_y: c_int, start: struct {
view: ?*View, x: c_int,
view_offset_x: ?c_int, y: c_int
view_offset_y: ?c_int, },
view: ?struct {
view: *View,
dims: struct { width: c_int, height: c_int },
offset: struct { x: c_int, y: c_int, }
},
}, },
pub fn init(self: *Cursor) void { pub fn init(self: *Cursor) void {
@ -43,13 +48,7 @@ pub fn init(self: *Cursor) void {
self.* = .{ self.* = .{
.wlr_cursor = try wlr.Cursor.create(), .wlr_cursor = try wlr.Cursor.create(),
.x_cursor_manager = try wlr.XcursorManager.create(null, 24), .x_cursor_manager = try wlr.XcursorManager.create(null, 24),
.drag = .{ .drag = null
.start_x = 0,
.start_y = 0,
.view = null,
.view_offset_x = null,
.view_offset_y = null,
}
}; };
try self.x_cursor_manager.load(1); try self.x_cursor_manager.load(1);
@ -79,55 +78,57 @@ pub fn deinit(self: *Cursor) void {
} }
pub fn processCursorMotion(self: *Cursor, time_msec: u32) void { pub fn processCursorMotion(self: *Cursor, time_msec: u32) void {
server.events.exec("PointerMotion", .{self.wlr_cursor.x, self.wlr_cursor.y}); self.wlr_cursor.setXcursor(self.x_cursor_manager, "default");
switch (self.mode) { var handled = false;
.normal => {
const output = server.seat.focused_output;
// Exit the switch if no focused output exists
if (output == null) return;
const surfaceAtResult = output.?.surfaceAt(self.wlr_cursor.x, self.wlr_cursor.y); if (self.mode == .drag) {
if (surfaceAtResult == null) { const modifiers = server.seat.keyboard_group.keyboard.getModifiers();
self.wlr_cursor.setXcursor(self.x_cursor_manager, "default");
server.seat.wlr_seat.pointerClearFocus();
// This is gonna be fun std.debug.assert(self.drag != null);
// server.seat.wlr_seat.keyboardSendKey(time_msec: u32, key: u32, state: u32);
// server.seat.wlr_seat.pointerSendMotion(time_msec: u32, sx: f64, sy: f64) // Proceed if mousemap for current mouse and modifier state's exist
// server.seat.wlr_seat.pointerSendButton(time_msec: u32, button: u32, state: ButtonState) if (server.mousemaps.get(Mousemap.hash(modifiers, @bitCast(self.drag.?.event_code)))) |map| {
return; if(map.options.lua_drag_ref_idx > 0) {
handled = true;
map.callback(.drag, .{
.{
.x = @as(c_int, @intFromFloat(self.wlr_cursor.x)),
.y = @as(c_int, @intFromFloat(self.wlr_cursor.y))
},
.{
.start = self.drag.?.start,
.view = if (self.drag.?.view != null) .{
.id = self.drag.?.view.?.view.id,
.dims = self.drag.?.view.?.dims,
.offset = self.drag.?.view.?.offset
} else null
}
});
} }
}
}
switch (surfaceAtResult.?.scene_node_data.*) { if(!handled) {
.view => { const output = server.seat.focused_output;
// TODO: If serious performance issues arise from this, we need to be able to disable unused hooks // Exit the switch if no focused output exists
// Perhaps after the config is executed, if no callbacks are present on this hook, we disable it entirely std.debug.assert(output != null);
server.events.exec("ViewPointerMotion", .{surfaceAtResult.?.scene_node_data.view.id, self.wlr_cursor.x, self.wlr_cursor.y});
}, const surfaceAtResult = output.?.surfaceAt(self.wlr_cursor.x, self.wlr_cursor.y);
.layer_surface => { }, if (surfaceAtResult) |surface| {
else => unreachable if(surface.scene_node_data.* == .view) {
server.events.exec("ViewPointerMotion", .{
surface.scene_node_data.view.id,
@as(c_int, @intFromFloat(self.wlr_cursor.x)),
@as(c_int, @intFromFloat(self.wlr_cursor.y))
});
} }
server.seat.wlr_seat.pointerNotifyEnter(surfaceAtResult.?.surface, surfaceAtResult.?.sx, surfaceAtResult.?.sy); server.seat.wlr_seat.pointerNotifyEnter(surfaceAtResult.?.surface, surfaceAtResult.?.sx, surfaceAtResult.?.sy);
server.seat.wlr_seat.pointerNotifyMotion(time_msec, surfaceAtResult.?.sx, surfaceAtResult.?.sy); server.seat.wlr_seat.pointerNotifyMotion(time_msec, surfaceAtResult.?.sx, surfaceAtResult.?.sy);
}, } else {
.drag => { // This may not be necessary, remove if no bugs
server.seat.wlr_seat.pointerClearFocus();
// @hook PointerDragMotion
// @param button string // TODO Translate a button to a string or smth
// @param state string - "pressed" or "released"
// @param time_msecs number // TODO idk what the hell msecs is
server.events.exec("PointerDragMotion", .{
self.wlr_cursor.x,
self.wlr_cursor.y,
self.drag.start_x,
self.drag.start_y,
self.drag.view.?.id,
self.drag.view_offset_x,
self.drag.view_offset_y
});
} }
} }
} }
@ -157,45 +158,49 @@ fn handleButton(
switch (event.state) { switch (event.state) {
.pressed => { .pressed => {
cursor.drag.start_x = @as(c_int, @intFromFloat(cursor.wlr_cursor.x)); cursor.mode = .drag;
cursor.drag.start_y = @as(c_int, @intFromFloat(cursor.wlr_cursor.y));
cursor.drag = .{
.event_code = event.button,
.start = .{
.x = @as(c_int, @intFromFloat(cursor.wlr_cursor.x)),
.y = @as(c_int, @intFromFloat(cursor.wlr_cursor.y))
},
.view = null
};
// Keep track of where the drag started
if(server.seat.focused_surface) |fs| { if(server.seat.focused_surface) |fs| {
// Keep track of where the drag started
if(fs == .view) { if(fs == .view) {
cursor.drag.view = fs.view; cursor.drag.?.view = .{
cursor.drag.view_offset_x = cursor.drag.start_x - fs.view.scene_tree.node.x; .view = fs.view,
cursor.drag.view_offset_y = cursor.drag.start_y - fs.view.scene_tree.node.y; .dims = .{
.width = fs.view.xdg_toplevel.base.geometry.width,
.height = fs.view.xdg_toplevel.base.geometry.height
},
.offset = .{
.x = cursor.drag.?.start.x - fs.view.scene_tree.node.x,
.y = cursor.drag.?.start.y - fs.view.scene_tree.node.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")) {
// if(fs == .view) {
// cursor.mode = .resize;
// _ = fs.view.xdg_toplevel.setResizing(true);
// }
// }
} }
}, },
.released => { .released => {
cursor.mode = .normal; cursor.mode = .normal;
if(cursor.drag.view) |view| { // How do we do this on the lua side
_ = view.xdg_toplevel.setResizing(false); // if(cursor.drag.view) |view| {
} // _ = view.xdg_toplevel.setResizing(false);
// }
cursor.drag.view = null; cursor.drag.?.view = null;
cursor.drag.view_offset_x = null;
cursor.drag.view_offset_y = null;
}, },
else => { else => {
std.log.err("Invalid/Unimplemented pointer button event type", .{}); std.log.err("Invalid/Unimplemented pointer button event type", .{});
} }
} }
var handled = false; var handled = false;
const modifiers = server.seat.keyboard_group.keyboard.getModifiers(); const modifiers = server.seat.keyboard_group.keyboard.getModifiers();
@ -205,13 +210,23 @@ fn handleButton(
.pressed => { .pressed => {
// Only make callback if a callback function exists // Only make callback if a callback function exists
if(map.options.lua_press_ref_idx > 0) { if(map.options.lua_press_ref_idx > 0) {
map.callback(.press); map.callback(.press, .{
.{
.x = @as(c_int, @intFromFloat(cursor.wlr_cursor.x)),
.y = @as(c_int, @intFromFloat(cursor.wlr_cursor.y))
},
});
handled = true; handled = true;
} }
}, },
.released => { .released => {
if(map.options.lua_press_ref_idx > 0) { if(map.options.lua_press_ref_idx > 0) {
map.callback(.release); map.callback(.release, .{
.{
.x = @as(c_int, @intFromFloat(cursor.wlr_cursor.x)),
.y = @as(c_int, @intFromFloat(cursor.wlr_cursor.y))
},
});
handled = true; handled = true;
} }
}, },
@ -227,8 +242,8 @@ fn handleButton(
} }
fn handleHoldBegin( fn handleHoldBegin(
listener: *wl.Listener(*wlr.Pointer.event.HoldBegin), listener: *wl.Listener(*wlr.Pointer.event.HoldBegin),
event: *wlr.Pointer.event.HoldBegin event: *wlr.Pointer.event.HoldBegin
) void { ) void {
_ = listener; _ = listener;
_ = event; _ = event;
@ -236,8 +251,8 @@ event: *wlr.Pointer.event.HoldBegin
} }
fn handleHoldEnd( fn handleHoldEnd(
listener: *wl.Listener(*wlr.Pointer.event.HoldEnd), listener: *wl.Listener(*wlr.Pointer.event.HoldEnd),
event: *wlr.Pointer.event.HoldEnd event: *wlr.Pointer.event.HoldEnd
) void { ) void {
_ = listener; _ = listener;
_ = event; _ = event;
@ -245,17 +260,17 @@ event: *wlr.Pointer.event.HoldEnd
} }
fn handleAxis( fn handleAxis(
_: *wl.Listener(*wlr.Pointer.event.Axis), _: *wl.Listener(*wlr.Pointer.event.Axis),
event: *wlr.Pointer.event.Axis, event: *wlr.Pointer.event.Axis,
) void { ) void {
server.seat.wlr_seat.pointerNotifyAxis( server.seat.wlr_seat.pointerNotifyAxis(
event.time_msec, event.time_msec,
event.orientation, event.orientation,
event.delta, event.delta,
event.delta_discrete, event.delta_discrete,
event.source, event.source,
event.relative_direction, event.relative_direction,
); );
} }
fn handleFrame(_: *wl.Listener(*wlr.Cursor), _: *wlr.Cursor) void { fn handleFrame(_: *wl.Listener(*wlr.Cursor), _: *wlr.Cursor) void {

View file

@ -24,7 +24,13 @@ options: struct {
pub const MousemapState = enum { press, drag, release }; pub const MousemapState = enum { press, drag, release };
pub fn callback(self: *const Mousemap, state: MousemapState) void { pub fn callback(self: *const Mousemap, state: MousemapState, args: anytype) void {
const ArgsType = @TypeOf(args);
const args_type_info = @typeInfo(ArgsType);
if (args_type_info != .@"struct") {
@compileError("expected tuple or struct argument, found " ++ @typeName(ArgsType));
}
const lua_ref_idx = switch(state) { const lua_ref_idx = switch(state) {
.press => self.options.lua_press_ref_idx, .press => self.options.lua_press_ref_idx,
.release => self.options.lua_release_ref_idx, .release => self.options.lua_release_ref_idx,
@ -38,7 +44,14 @@ pub fn callback(self: *const Mousemap, state: MousemapState) void {
return; return;
} }
Lua.state.protectedCall(.{ .args = 0, .results = 0 }) catch { // allow passing any arguments to the lua hook
var i: u8 = 0;
inline for (args, 1..) |field, k| {
try Lua.state.pushAny(field);
i = k;
}
Lua.state.protectedCall(.{ .args = i, .results = 0 }) catch {
RemoteLua.sendNewLogEntry(Lua.state.toString(-1) catch unreachable); RemoteLua.sendNewLogEntry(Lua.state.toString(-1) catch unreachable);
}; };
Lua.state.pop(-1); Lua.state.pop(-1);