diff --git a/runtime/share/mezzaluna/master.lua b/runtime/share/mezzaluna/master.lua index f0fd66a..641d169 100644 --- a/runtime/share/mezzaluna/master.lua +++ b/runtime/share/mezzaluna/master.lua @@ -275,14 +275,29 @@ local master = function() end mez.input.add_mousemap("alt", "BTN_LEFT", { - press = function() - print("pressed mouse") - mez.input.del_mousemap("alt", "BTN_LEFT"); + drag = function(pos, drag) + if drag.view ~= nil then + mez.view.set_position(drag.view.id, pos.x - drag.view.offset.x, pos.y - drag.view.offset.y) + 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 master() diff --git a/src/Cursor.zig b/src/Cursor.zig index 28da562..3e9fb10 100644 --- a/src/Cursor.zig +++ b/src/Cursor.zig @@ -29,12 +29,17 @@ hold_end: wl.Listener(*wlr.Pointer.event.HoldEnd) = .init(handleHoldEnd), mode: enum { normal, drag } = .normal, // Drag information -drag: struct { - start_x: c_int, - start_y: c_int, - view: ?*View, - view_offset_x: ?c_int, - view_offset_y: ?c_int, +drag: ?struct { + event_code: u32, + start: struct { + x: c_int, + 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 { @@ -43,13 +48,7 @@ pub fn init(self: *Cursor) void { self.* = .{ .wlr_cursor = try wlr.Cursor.create(), .x_cursor_manager = try wlr.XcursorManager.create(null, 24), - .drag = .{ - .start_x = 0, - .start_y = 0, - .view = null, - .view_offset_x = null, - .view_offset_y = null, - } + .drag = null }; 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 { - server.events.exec("PointerMotion", .{self.wlr_cursor.x, self.wlr_cursor.y}); + self.wlr_cursor.setXcursor(self.x_cursor_manager, "default"); - switch (self.mode) { - .normal => { - const output = server.seat.focused_output; - // Exit the switch if no focused output exists - if (output == null) return; + var handled = false; - const surfaceAtResult = output.?.surfaceAt(self.wlr_cursor.x, self.wlr_cursor.y); - if (surfaceAtResult == null) { - self.wlr_cursor.setXcursor(self.x_cursor_manager, "default"); - server.seat.wlr_seat.pointerClearFocus(); + if (self.mode == .drag) { + const modifiers = server.seat.keyboard_group.keyboard.getModifiers(); - // This is gonna be fun - // server.seat.wlr_seat.keyboardSendKey(time_msec: u32, key: u32, state: u32); - // server.seat.wlr_seat.pointerSendMotion(time_msec: u32, sx: f64, sy: f64) - // server.seat.wlr_seat.pointerSendButton(time_msec: u32, button: u32, state: ButtonState) - return; + std.debug.assert(self.drag != null); + + // Proceed if mousemap for current mouse and modifier state's exist + if (server.mousemaps.get(Mousemap.hash(modifiers, @bitCast(self.drag.?.event_code)))) |map| { + 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.*) { - .view => { - // TODO: If serious performance issues arise from this, we need to be able to disable unused hooks - // Perhaps after the config is executed, if no callbacks are present on this hook, we disable it entirely - server.events.exec("ViewPointerMotion", .{surfaceAtResult.?.scene_node_data.view.id, self.wlr_cursor.x, self.wlr_cursor.y}); - }, - .layer_surface => { }, - else => unreachable + if(!handled) { + const output = server.seat.focused_output; + // Exit the switch if no focused output exists + std.debug.assert(output != null); + + const surfaceAtResult = output.?.surfaceAt(self.wlr_cursor.x, self.wlr_cursor.y); + if (surfaceAtResult) |surface| { + 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.pointerNotifyMotion(time_msec, surfaceAtResult.?.sx, surfaceAtResult.?.sy); - }, - .drag => { - - // @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 - }); + } else { + // This may not be necessary, remove if no bugs + server.seat.wlr_seat.pointerClearFocus(); } } } @@ -157,45 +158,49 @@ fn handleButton( switch (event.state) { .pressed => { - cursor.drag.start_x = @as(c_int, @intFromFloat(cursor.wlr_cursor.x)); - cursor.drag.start_y = @as(c_int, @intFromFloat(cursor.wlr_cursor.y)); + cursor.mode = .drag; + + 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| { - // Keep track of where the drag started - if(fs == .view) { - cursor.drag.view = fs.view; - cursor.drag.view_offset_x = cursor.drag.start_x - fs.view.scene_tree.node.x; - cursor.drag.view_offset_y = cursor.drag.start_y - fs.view.scene_tree.node.y; + cursor.drag.?.view = .{ + .view = fs.view, + .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 => { cursor.mode = .normal; - if(cursor.drag.view) |view| { - _ = view.xdg_toplevel.setResizing(false); - } + // How do we do this on the lua side + // if(cursor.drag.view) |view| { + // _ = view.xdg_toplevel.setResizing(false); + // } - cursor.drag.view = null; - cursor.drag.view_offset_x = null; - cursor.drag.view_offset_y = null; + cursor.drag.?.view = null; }, else => { std.log.err("Invalid/Unimplemented pointer button event type", .{}); } } - var handled = false; const modifiers = server.seat.keyboard_group.keyboard.getModifiers(); @@ -205,13 +210,23 @@ fn handleButton( .pressed => { // Only make callback if a callback function exists 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; } }, .released => { 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; } }, @@ -227,8 +242,8 @@ fn handleButton( } fn handleHoldBegin( -listener: *wl.Listener(*wlr.Pointer.event.HoldBegin), -event: *wlr.Pointer.event.HoldBegin + listener: *wl.Listener(*wlr.Pointer.event.HoldBegin), + event: *wlr.Pointer.event.HoldBegin ) void { _ = listener; _ = event; @@ -236,8 +251,8 @@ event: *wlr.Pointer.event.HoldBegin } fn handleHoldEnd( -listener: *wl.Listener(*wlr.Pointer.event.HoldEnd), -event: *wlr.Pointer.event.HoldEnd + listener: *wl.Listener(*wlr.Pointer.event.HoldEnd), + event: *wlr.Pointer.event.HoldEnd ) void { _ = listener; _ = event; @@ -245,17 +260,17 @@ event: *wlr.Pointer.event.HoldEnd } fn handleAxis( -_: *wl.Listener(*wlr.Pointer.event.Axis), -event: *wlr.Pointer.event.Axis, + _: *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, -); + event.time_msec, + event.orientation, + event.delta, + event.delta_discrete, + event.source, + event.relative_direction, + ); } fn handleFrame(_: *wl.Listener(*wlr.Cursor), _: *wlr.Cursor) void { diff --git a/src/types/Mousemap.zig b/src/types/Mousemap.zig index aef1ebd..83e1a3a 100644 --- a/src/types/Mousemap.zig +++ b/src/types/Mousemap.zig @@ -24,7 +24,13 @@ options: struct { 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) { .press => self.options.lua_press_ref_idx, .release => self.options.lua_release_ref_idx, @@ -38,7 +44,14 @@ pub fn callback(self: *const Mousemap, state: MousemapState) void { 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); }; Lua.state.pop(-1);