From bb669b2d9acc8c59f413cf13e60a34055e7dc08e Mon Sep 17 00:00:00 2001 From: Harrison DiAmbrosio Date: Thu, 23 Oct 2025 23:29:38 -0400 Subject: [PATCH] rewriting cursor controls --- build.zig | 2 + src/cursor.zig | 115 ++++++++++++++++++++++++++--------------------- src/keyboard.zig | 21 +++++---- src/root.zig | 4 +- src/server.zig | 20 ++++----- src/view.zig | 52 +++++++++++---------- 6 files changed, 120 insertions(+), 94 deletions(-) diff --git a/build.zig b/build.zig index 2aa4bbe..afb4a2a 100644 --- a/build.zig +++ b/build.zig @@ -17,6 +17,7 @@ pub fn build(b: *std.Build) void { const scanner = Scanner.create(b, .{}); scanner.addSystemProtocol("stable/xdg-shell/xdg-shell.xml"); scanner.addSystemProtocol("stable/tablet/tablet-v2.xml"); + scanner.addSystemProtocol("unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"); scanner.generate("wl_compositor", 6); scanner.generate("wl_subcompositor", 1); @@ -24,6 +25,7 @@ pub fn build(b: *std.Build) void { scanner.generate("wl_output", 4); scanner.generate("wl_seat", 7); scanner.generate("wl_data_device_manager", 3); + scanner.generate("zxdg_decoration_manager_v1", 1); scanner.generate("xdg_wm_base", 2); scanner.generate("zwp_tablet_manager_v2", 1); diff --git a/src/cursor.zig b/src/cursor.zig index 4ef8b7f..cfc5490 100644 --- a/src/cursor.zig +++ b/src/cursor.zig @@ -1,3 +1,6 @@ +//! Maintains state related to cursor position, rendering, and +//! events such as button presses and dragging + pub const Cursor = @This(); const std = @import("std"); @@ -21,11 +24,8 @@ 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, -grabbed_view: ?*View = null, -grab_x: f64 = 0, -grab_y: f64 = 0, +selected_view: ?*View = null, grab_box: wlr.Box = undefined, -resize_edges: wlr.Edges = .{}, pub fn init(self: *Cursor) void { errdefer Utils.oomPanic(); @@ -59,6 +59,12 @@ pub fn deinit(self: *Cursor) void { self.frame.link.remove(); } +// pub fn moveView(self: *Cursor, view: *View) void { +// } + +// pub fn resizeView(self: *Cursor, view: *View) void { +// } + pub fn processCursorMotion(self: *Cursor, time_msec: u32) void { switch (self.mode) { .passthrough => { @@ -71,50 +77,60 @@ pub fn processCursorMotion(self: *Cursor, time_msec: u32) void { } }, .move => { - const view = self.grabbed_view.?; - // Should we modify the XdgSurface geometry directly??? - view.geometry.x = @as(i32, @intFromFloat(self.wlr_cursor.x - self.grab_x)); - view.geometry.y = @as(i32, @intFromFloat(self.wlr_cursor.y - self.grab_y)); - view.scene_tree.node.setPosition(view.geometry.x, view.geometry.y); + // REDOING RESIZING AND MOVING TOPLEVELS + // REDOING RESIZING AND MOVING TOPLEVELS + // REDOING RESIZING AND MOVING TOPLEVELS + // REDOING RESIZING AND MOVING TOPLEVELS + // const view = self.selected_view.?; + // view.scene_tree.node.setPosition( + // @as(i32, @intFromFloat(self.wlr_cursor.x - self.grab_x)), + // @as(i32, @intFromFloat(self.wlr_cursor.y - self.grab_y)) + // ); }, .resize => { // Fix this resize - 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); + // + // 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); }, } } @@ -138,21 +154,20 @@ fn handleMotionAbsolute( fn handleButton( _: *wl.Listener(*wlr.Pointer.event.Button), - event: *wlr.Pointer.event.Button, + event: *wlr.Pointer.event.Button ) void { + _ = server.seat.wlr_seat.pointerNotifyButton(event.time_msec, event.button, event.state); switch (event.state) { .pressed => { - _ = server.seat.wlr_seat.pointerNotifyButton(event.time_msec, event.button, event.state); if (server.root.viewAt(server.cursor.wlr_cursor.x, server.cursor.wlr_cursor.y)) |res| { server.root.focusView(res.view); } }, .released => { - std.log.debug("Button released", .{}); server.cursor.mode = .passthrough; }, else => { - std.log.err("Unexpected button state", .{}); + std.log.err("Invalid/Unimplemented pointer button event type", .{}); } } } @@ -163,7 +178,7 @@ fn handleHoldBegin( ) void { _ = listener; _ = event; - std.log.err("Unimplemented cursor being hold", .{}); + std.log.err("Unimplemented cursor start hold", .{}); } fn handleHoldEnd( diff --git a/src/keyboard.zig b/src/keyboard.zig index c23b756..c3a6e2c 100644 --- a/src/keyboard.zig +++ b/src/keyboard.zig @@ -1,3 +1,6 @@ +//! Maintains state related to keyboard input devices, +//! events such as button presses and dragging + const Keyboard = @This(); const std = @import("std"); @@ -9,6 +12,7 @@ const wlr = @import("wlroots"); const xkb = @import("xkbcommon"); wlr_keyboard: *wlr.Keyboard, +context: *xkb.Context, device: *wlr.InputDevice, keyboards: wl.list.Head(Keyboard, .link) = undefined, @@ -31,16 +35,13 @@ pub fn init(self: *Keyboard, device: *wlr.InputDevice) void { } self.* = .{ + .context = xkb.Context.new(.no_flags) orelse return error.ContextFailed, .wlr_keyboard = device.toKeyboard(), .device = device, }; + defer self.context.unref(); - // Should handle this error here - const context = xkb.Context.new(.no_flags) orelse return error.ContextFailed; - defer context.unref(); - - // Should handle this error here - const keymap = xkb.Keymap.newFromNames(context, null, .no_flags) orelse return error.KeymapFailed; + const keymap = xkb.Keymap.newFromNames(self.context, null, .no_flags) orelse return error.KeymapFailed; defer keymap.unref(); // TODO: configure this via lua later @@ -62,9 +63,11 @@ pub fn init(self: *Keyboard, device: *wlr.InputDevice) void { self.keyboards.append(self); } -// pub fn destroy(self: *Keyboard) { -// -// } +pub fn deinit (self: *Keyboard) void { + self.key.link.remove(); + self.key_map.link.remove(); + self.modifiers.link.remove(); +} fn handleModifiers(_: *wl.Listener(*wlr.Keyboard), wlr_keyboard: *wlr.Keyboard) void { server.seat.wlr_seat.setKeyboard(wlr_keyboard); diff --git a/src/root.zig b/src/root.zig index c9ef609..88cff11 100644 --- a/src/root.zig +++ b/src/root.zig @@ -11,7 +11,7 @@ const Utils = @import("utils.zig"); const server = &@import("main.zig").server; const gpa = std.heap.c_allocator; -// xdg_toplevel_decoration_manager: *wlr.XdgDecorationManagerV1, +xdg_toplevel_decoration_manager: *wlr.XdgDecorationManagerV1, scene: *wlr.Scene, scene_output_layout: *wlr.SceneOutputLayout, @@ -37,7 +37,7 @@ pub fn init(self: *Root) void { .scene = scene, .output_layout = output_layout, .focused_output = null, - // .xdg_toplevel_decoration_manager = try wlr.XdgDecorationManagerV1.create(server.wl_server), + .xdg_toplevel_decoration_manager = try wlr.XdgDecorationManagerV1.create(server.wl_server), .scene_output_layout = try scene.attachOutputLayout(output_layout), }; diff --git a/src/server.zig b/src/server.zig index ea658ca..88384de 100644 --- a/src/server.zig +++ b/src/server.zig @@ -24,7 +24,7 @@ session: ?*wlr.Session, shm: *wlr.Shm, xdg_shell: *wlr.XdgShell, -// xdg_toplevel_decoration_manager: *wlr.XdgDecorationManagerV1, +xdg_toplevel_decoration_manager: *wlr.XdgDecorationManagerV1, // Input @@ -43,7 +43,7 @@ new_output: wl.Listener(*wlr.Output) = .init(handleNewOutput), // XdgShell listeners new_xdg_toplevel: wl.Listener(*wlr.XdgToplevel) = .init(handleNewXdgToplevel), new_xdg_popup: wl.Listener(*wlr.XdgPopup) = .init(handleNewXdgPopup), -// new_xdg_toplevel_decoration: wl.Listener(*wlr.XdgToplevelDecorationV1) = .init(handleNewXdgToplevelDecoration), +new_xdg_toplevel_decoration: wl.Listener(*wlr.XdgToplevelDecorationV1) = .init(handleNewXdgToplevelDecoration), // new_xdg_popup // new_xdg_toplevel @@ -79,7 +79,7 @@ pub fn init(self: *Server) void { std.process.exit(5); }, .xdg_shell = try wlr.XdgShell.create(wl_server, 2), - // .xdg_toplevel_decoration_manager = try wlr.XdgDecorationManagerV1.create(self.wl_server), + .xdg_toplevel_decoration_manager = try wlr.XdgDecorationManagerV1.create(self.wl_server), .event_loop = event_loop, .session = session, .compositor = try wlr.Compositor.create(wl_server, 6, renderer), @@ -192,10 +192,10 @@ fn handleNewXdgPopup( std.log.err("Unimplemented handle new xdg popup", .{}); } -// fn handleNewXdgToplevelDecoration( -// _: *wl.Listener(*wlr.XdgToplevelDecorationV1), -// decoration: *wlr.XdgToplevelDecorationV1 -// ) void { -// // TODO: Configured with lua perhaps -// decoration.current.mode = .server_side; -// } +fn handleNewXdgToplevelDecoration( + _: *wl.Listener(*wlr.XdgToplevelDecorationV1), + decoration: *wlr.XdgToplevelDecorationV1 +) void { + // TODO: Configured with lua perhaps + decoration.current.mode = .server_side; +} diff --git a/src/view.zig b/src/view.zig index ebcfcc2..54c44e6 100644 --- a/src/view.zig +++ b/src/view.zig @@ -1,6 +1,5 @@ const View = @This(); - const std = @import("std"); const wl = @import("wayland").server.wl; const wlr = @import("wlroots"); @@ -45,6 +44,8 @@ pub fn initFromTopLevel(xdg_toplevel: *wlr.XdgToplevel) *View { }; // Add new Toplevel to focused output instead of some random shit + // This is where we find out where to tile the widow, but not NOW + // We need lua for that self.scene_tree = try server.root.workspaces.items[0].createSceneXdgSurface(xdg_toplevel.base); self.scene_tree.node.data = self; @@ -138,35 +139,40 @@ fn handleNewPopup(listener: *wl.Listener(*wlr.XdgPopup), popup: *wlr.XdgPopup) v } fn handleRequestMove( - listener: *wl.Listener(*wlr.XdgToplevel.event.Move), + _: *wl.Listener(*wlr.XdgToplevel.event.Move), _: *wlr.XdgToplevel.event.Move ) void { - const view: *View = @fieldParentPtr("request_move", listener); + // const view: *View = @fieldParentPtr("request_move", listener); - server.cursor.grabbed_view = view; - server.cursor.mode = .move; - server.cursor.grab_x = server.cursor.wlr_cursor.x - @as(f64, @floatFromInt(view.geometry.x)); - server.cursor.grab_y = server.cursor.wlr_cursor.y - @as(f64, @floatFromInt(view.geometry.y)); + std.log.err("The clients should not be request moves", .{}); + + // server.cursor.moveView(view); + // server.cursor.grabbed_view = view; + // server.cursor.mode = .move; + // server.cursor.grab_x = server.cursor.wlr_cursor.x - @as(f64, @floatFromInt(view.geometry.x)); + // server.cursor.grab_y = server.cursor.wlr_cursor.y - @as(f64, @floatFromInt(view.geometry.y)); } fn handleRequestResize( - listener: *wl.Listener(*wlr.XdgToplevel.event.Resize), - event: *wlr.XdgToplevel.event.Resize + _: *wl.Listener(*wlr.XdgToplevel.event.Resize), + _: *wlr.XdgToplevel.event.Resize ) void { - const view: *View = @fieldParentPtr("request_resize", listener); + // const view: *View = @fieldParentPtr("request_resize", listener); - server.cursor.grabbed_view = view; - server.cursor.mode = .resize; - server.cursor.resize_edges = event.edges; + std.log.err("The clients should not be request moves", .{}); - const box = view.xdg_toplevel.base.geometry; - - const border_x = view.geometry.x + box.x + if (event.edges.right) box.width else 0; - const border_y = view.geometry.y + box.y + if (event.edges.bottom) box.height else 0; - server.cursor.grab_x = server.cursor.wlr_cursor.x - @as(f64, @floatFromInt(border_x)); - server.cursor.grab_y = server.cursor.wlr_cursor.y - @as(f64, @floatFromInt(border_y)); - - server.cursor.grab_box = box; - server.cursor.grab_box.x += view.geometry.x; - server.cursor.grab_box.y += view.geometry.y; + // server.cursor.grabbed_view = view; + // server.cursor.mode = .resize; + // server.cursor.resize_edges = event.edges; + // + // const box = view.xdg_toplevel.base.geometry; + // + // const border_x = view.geometry.x + box.x + if (event.edges.right) box.width else 0; + // const border_y = view.geometry.y + box.y + if (event.edges.bottom) box.height else 0; + // server.cursor.grab_x = server.cursor.wlr_cursor.x - @as(f64, @floatFromInt(border_x)); + // server.cursor.grab_y = server.cursor.wlr_cursor.y - @as(f64, @floatFromInt(border_y)); + // + // server.cursor.grab_box = box; + // server.cursor.grab_box.x += view.geometry.x; + // server.cursor.grab_box.y += view.geometry.y; }