rewriting cursor controls

This commit is contained in:
Harrison DiAmbrosio 2025-10-23 23:29:38 -04:00
parent b328c0a7c7
commit bb669b2d9a
6 changed files with 120 additions and 94 deletions

View file

@ -17,6 +17,7 @@ pub fn build(b: *std.Build) void {
const scanner = Scanner.create(b, .{}); const scanner = Scanner.create(b, .{});
scanner.addSystemProtocol("stable/xdg-shell/xdg-shell.xml"); scanner.addSystemProtocol("stable/xdg-shell/xdg-shell.xml");
scanner.addSystemProtocol("stable/tablet/tablet-v2.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_compositor", 6);
scanner.generate("wl_subcompositor", 1); scanner.generate("wl_subcompositor", 1);
@ -24,6 +25,7 @@ pub fn build(b: *std.Build) void {
scanner.generate("wl_output", 4); scanner.generate("wl_output", 4);
scanner.generate("wl_seat", 7); scanner.generate("wl_seat", 7);
scanner.generate("wl_data_device_manager", 3); scanner.generate("wl_data_device_manager", 3);
scanner.generate("zxdg_decoration_manager_v1", 1);
scanner.generate("xdg_wm_base", 2); scanner.generate("xdg_wm_base", 2);
scanner.generate("zwp_tablet_manager_v2", 1); scanner.generate("zwp_tablet_manager_v2", 1);

View file

@ -1,3 +1,6 @@
//! Maintains state related to cursor position, rendering, and
//! events such as button presses and dragging
pub const Cursor = @This(); pub const Cursor = @This();
const std = @import("std"); 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), hold_end: wl.Listener(*wlr.Pointer.event.HoldEnd) = .init(handleHoldEnd),
mode: enum { passthrough, move, resize } = .passthrough, mode: enum { passthrough, move, resize } = .passthrough,
grabbed_view: ?*View = null, selected_view: ?*View = null,
grab_x: f64 = 0,
grab_y: f64 = 0,
grab_box: wlr.Box = undefined, grab_box: wlr.Box = undefined,
resize_edges: wlr.Edges = .{},
pub fn init(self: *Cursor) void { pub fn init(self: *Cursor) void {
errdefer Utils.oomPanic(); errdefer Utils.oomPanic();
@ -59,6 +59,12 @@ pub fn deinit(self: *Cursor) void {
self.frame.link.remove(); 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 { pub fn processCursorMotion(self: *Cursor, time_msec: u32) void {
switch (self.mode) { switch (self.mode) {
.passthrough => { .passthrough => {
@ -71,50 +77,60 @@ pub fn processCursorMotion(self: *Cursor, time_msec: u32) void {
} }
}, },
.move => { .move => {
const view = self.grabbed_view.?; // REDOING RESIZING AND MOVING TOPLEVELS
// Should we modify the XdgSurface geometry directly??? // REDOING RESIZING AND MOVING TOPLEVELS
view.geometry.x = @as(i32, @intFromFloat(self.wlr_cursor.x - self.grab_x)); // REDOING RESIZING AND MOVING TOPLEVELS
view.geometry.y = @as(i32, @intFromFloat(self.wlr_cursor.y - self.grab_y)); // REDOING RESIZING AND MOVING TOPLEVELS
view.scene_tree.node.setPosition(view.geometry.x, view.geometry.y); // 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 => { .resize => {
// Fix this resize // Fix this resize
const view = self.grabbed_view.?; //
const border_x = @as(i32, @intFromFloat(self.wlr_cursor.x - self.grab_x)); // REDOING RESIZING AND MOVING TOPLEVELS
const border_y = @as(i32, @intFromFloat(self.wlr_cursor.y - self.grab_y)); // REDOING RESIZING AND MOVING TOPLEVELS
// REDOING RESIZING AND MOVING TOPLEVELS
var new_left = self.grab_box.x; // REDOING RESIZING AND MOVING TOPLEVELS
var new_right = self.grab_box.x + self.grab_box.width; //
var new_top = self.grab_box.y; // const view = self.grabbed_view.?;
var new_bottom = self.grab_box.y + self.grab_box.height; // 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));
if (self.resize_edges.top) { //
new_top = border_y; // var new_left = self.grab_box.x;
if (new_top >= new_bottom) // var new_right = self.grab_box.x + self.grab_box.width;
new_top = new_bottom - 1; // var new_top = self.grab_box.y;
} else if (self.resize_edges.bottom) { // var new_bottom = self.grab_box.y + self.grab_box.height;
new_bottom = border_y; //
if (new_bottom <= new_top) // if (self.resize_edges.top) {
new_bottom = new_top + 1; // new_top = border_y;
} // if (new_top >= new_bottom)
// new_top = new_bottom - 1;
if (self.resize_edges.left) { // } else if (self.resize_edges.bottom) {
new_left = border_x; // new_bottom = border_y;
if (new_left >= new_right) // if (new_bottom <= new_top)
new_left = new_right - 1; // new_bottom = new_top + 1;
} else if (self.resize_edges.right) { // }
new_right = border_x; //
if (new_right <= new_left) // if (self.resize_edges.left) {
new_right = new_left + 1; // new_left = border_x;
} // if (new_left >= new_right)
// new_left = new_right - 1;
// view.x = new_left - view.xdg_toplevel.base.geometry.x; // } else if (self.resize_edges.right) {
// view.y = new_top - view.xdg_toplevel.base.geometry.y; // new_right = border_x;
view.scene_tree.node.setPosition(view.geometry.x, view.geometry.y); // if (new_right <= new_left)
// new_right = new_left + 1;
const new_width = new_right - new_left; // }
const new_height = new_bottom - new_top; //
_ = view.xdg_toplevel.setSize(new_width, new_height); // // 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( fn handleButton(
_: *wl.Listener(*wlr.Pointer.event.Button), _: *wl.Listener(*wlr.Pointer.event.Button),
event: *wlr.Pointer.event.Button, event: *wlr.Pointer.event.Button
) void { ) void {
_ = server.seat.wlr_seat.pointerNotifyButton(event.time_msec, event.button, event.state);
switch (event.state) { switch (event.state) {
.pressed => { .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| { if (server.root.viewAt(server.cursor.wlr_cursor.x, server.cursor.wlr_cursor.y)) |res| {
server.root.focusView(res.view); server.root.focusView(res.view);
} }
}, },
.released => { .released => {
std.log.debug("Button released", .{});
server.cursor.mode = .passthrough; server.cursor.mode = .passthrough;
}, },
else => { else => {
std.log.err("Unexpected button state", .{}); std.log.err("Invalid/Unimplemented pointer button event type", .{});
} }
} }
} }
@ -163,7 +178,7 @@ fn handleHoldBegin(
) void { ) void {
_ = listener; _ = listener;
_ = event; _ = event;
std.log.err("Unimplemented cursor being hold", .{}); std.log.err("Unimplemented cursor start hold", .{});
} }
fn handleHoldEnd( fn handleHoldEnd(

View file

@ -1,3 +1,6 @@
//! Maintains state related to keyboard input devices,
//! events such as button presses and dragging
const Keyboard = @This(); const Keyboard = @This();
const std = @import("std"); const std = @import("std");
@ -9,6 +12,7 @@ const wlr = @import("wlroots");
const xkb = @import("xkbcommon"); const xkb = @import("xkbcommon");
wlr_keyboard: *wlr.Keyboard, wlr_keyboard: *wlr.Keyboard,
context: *xkb.Context,
device: *wlr.InputDevice, device: *wlr.InputDevice,
keyboards: wl.list.Head(Keyboard, .link) = undefined, keyboards: wl.list.Head(Keyboard, .link) = undefined,
@ -31,16 +35,13 @@ pub fn init(self: *Keyboard, device: *wlr.InputDevice) void {
} }
self.* = .{ self.* = .{
.context = xkb.Context.new(.no_flags) orelse return error.ContextFailed,
.wlr_keyboard = device.toKeyboard(), .wlr_keyboard = device.toKeyboard(),
.device = device, .device = device,
}; };
defer self.context.unref();
// Should handle this error here const keymap = xkb.Keymap.newFromNames(self.context, null, .no_flags) orelse return error.KeymapFailed;
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;
defer keymap.unref(); defer keymap.unref();
// TODO: configure this via lua later // TODO: configure this via lua later
@ -62,9 +63,11 @@ pub fn init(self: *Keyboard, device: *wlr.InputDevice) void {
self.keyboards.append(self); 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 { fn handleModifiers(_: *wl.Listener(*wlr.Keyboard), wlr_keyboard: *wlr.Keyboard) void {
server.seat.wlr_seat.setKeyboard(wlr_keyboard); server.seat.wlr_seat.setKeyboard(wlr_keyboard);

View file

@ -11,7 +11,7 @@ const Utils = @import("utils.zig");
const server = &@import("main.zig").server; const server = &@import("main.zig").server;
const gpa = std.heap.c_allocator; const gpa = std.heap.c_allocator;
// xdg_toplevel_decoration_manager: *wlr.XdgDecorationManagerV1, xdg_toplevel_decoration_manager: *wlr.XdgDecorationManagerV1,
scene: *wlr.Scene, scene: *wlr.Scene,
scene_output_layout: *wlr.SceneOutputLayout, scene_output_layout: *wlr.SceneOutputLayout,
@ -37,7 +37,7 @@ pub fn init(self: *Root) void {
.scene = scene, .scene = scene,
.output_layout = output_layout, .output_layout = output_layout,
.focused_output = null, .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), .scene_output_layout = try scene.attachOutputLayout(output_layout),
}; };

View file

@ -24,7 +24,7 @@ session: ?*wlr.Session,
shm: *wlr.Shm, shm: *wlr.Shm,
xdg_shell: *wlr.XdgShell, xdg_shell: *wlr.XdgShell,
// xdg_toplevel_decoration_manager: *wlr.XdgDecorationManagerV1, xdg_toplevel_decoration_manager: *wlr.XdgDecorationManagerV1,
// Input // Input
@ -43,7 +43,7 @@ new_output: wl.Listener(*wlr.Output) = .init(handleNewOutput),
// XdgShell listeners // XdgShell listeners
new_xdg_toplevel: wl.Listener(*wlr.XdgToplevel) = .init(handleNewXdgToplevel), new_xdg_toplevel: wl.Listener(*wlr.XdgToplevel) = .init(handleNewXdgToplevel),
new_xdg_popup: wl.Listener(*wlr.XdgPopup) = .init(handleNewXdgPopup), 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_popup
// new_xdg_toplevel // new_xdg_toplevel
@ -79,7 +79,7 @@ pub fn init(self: *Server) void {
std.process.exit(5); std.process.exit(5);
}, },
.xdg_shell = try wlr.XdgShell.create(wl_server, 2), .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, .event_loop = event_loop,
.session = session, .session = session,
.compositor = try wlr.Compositor.create(wl_server, 6, renderer), .compositor = try wlr.Compositor.create(wl_server, 6, renderer),
@ -192,10 +192,10 @@ fn handleNewXdgPopup(
std.log.err("Unimplemented handle new xdg popup", .{}); std.log.err("Unimplemented handle new xdg popup", .{});
} }
// fn handleNewXdgToplevelDecoration( fn handleNewXdgToplevelDecoration(
// _: *wl.Listener(*wlr.XdgToplevelDecorationV1), _: *wl.Listener(*wlr.XdgToplevelDecorationV1),
// decoration: *wlr.XdgToplevelDecorationV1 decoration: *wlr.XdgToplevelDecorationV1
// ) void { ) void {
// // TODO: Configured with lua perhaps // TODO: Configured with lua perhaps
// decoration.current.mode = .server_side; decoration.current.mode = .server_side;
// } }

View file

@ -1,6 +1,5 @@
const View = @This(); const View = @This();
const std = @import("std"); const std = @import("std");
const wl = @import("wayland").server.wl; const wl = @import("wayland").server.wl;
const wlr = @import("wlroots"); 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 // 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 = try server.root.workspaces.items[0].createSceneXdgSurface(xdg_toplevel.base);
self.scene_tree.node.data = self; self.scene_tree.node.data = self;
@ -138,35 +139,40 @@ fn handleNewPopup(listener: *wl.Listener(*wlr.XdgPopup), popup: *wlr.XdgPopup) v
} }
fn handleRequestMove( fn handleRequestMove(
listener: *wl.Listener(*wlr.XdgToplevel.event.Move), _: *wl.Listener(*wlr.XdgToplevel.event.Move),
_: *wlr.XdgToplevel.event.Move _: *wlr.XdgToplevel.event.Move
) void { ) void {
const view: *View = @fieldParentPtr("request_move", listener); // const view: *View = @fieldParentPtr("request_move", listener);
server.cursor.grabbed_view = view; std.log.err("The clients should not be request moves", .{});
server.cursor.mode = .move;
server.cursor.grab_x = server.cursor.wlr_cursor.x - @as(f64, @floatFromInt(view.geometry.x)); // server.cursor.moveView(view);
server.cursor.grab_y = server.cursor.wlr_cursor.y - @as(f64, @floatFromInt(view.geometry.y)); // 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( fn handleRequestResize(
listener: *wl.Listener(*wlr.XdgToplevel.event.Resize), _: *wl.Listener(*wlr.XdgToplevel.event.Resize),
event: *wlr.XdgToplevel.event.Resize _: *wlr.XdgToplevel.event.Resize
) void { ) void {
const view: *View = @fieldParentPtr("request_resize", listener); // const view: *View = @fieldParentPtr("request_resize", listener);
server.cursor.grabbed_view = view; std.log.err("The clients should not be request moves", .{});
server.cursor.mode = .resize;
server.cursor.resize_edges = event.edges;
const box = view.xdg_toplevel.base.geometry; // server.cursor.grabbed_view = view;
// server.cursor.mode = .resize;
const border_x = view.geometry.x + box.x + if (event.edges.right) box.width else 0; // server.cursor.resize_edges = event.edges;
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)); // const box = view.xdg_toplevel.base.geometry;
server.cursor.grab_y = server.cursor.wlr_cursor.y - @as(f64, @floatFromInt(border_y)); //
// const border_x = view.geometry.x + box.x + if (event.edges.right) box.width else 0;
server.cursor.grab_box = box; // const border_y = view.geometry.y + box.y + if (event.edges.bottom) box.height else 0;
server.cursor.grab_box.x += view.geometry.x; // server.cursor.grab_x = server.cursor.wlr_cursor.x - @as(f64, @floatFromInt(border_x));
server.cursor.grab_box.y += view.geometry.y; // 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;
} }