mirror of
https://github.com/MezzalunaWM/Mezzaluna.git
synced 2026-03-07 19:49:53 -05:00
refine the pointer motion function, this is now closer to what other
compositors do
This commit is contained in:
parent
94e8388e7c
commit
790fad4074
1 changed files with 112 additions and 33 deletions
121
src/Cursor.zig
121
src/Cursor.zig
|
|
@ -32,10 +32,11 @@ mode: enum { normal, drag } = .normal,
|
||||||
drag: ?struct {
|
drag: ?struct {
|
||||||
event_code: u32,
|
event_code: u32,
|
||||||
start: struct { x: c_int, y: c_int },
|
start: struct { x: c_int, y: c_int },
|
||||||
view: ?struct { view: *View, dims: struct { width: c_int, height: c_int }, offset: struct {
|
view: ?struct {
|
||||||
x: c_int,
|
view: *View,
|
||||||
y: c_int,
|
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 {
|
||||||
|
|
@ -73,8 +74,21 @@ pub fn deinit(self: *Cursor) void {
|
||||||
self.x_cursor_manager.destroy();
|
self.x_cursor_manager.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn processCursorMotion(self: *Cursor, time_msec: u32) void {
|
pub fn processCursorMotion(
|
||||||
var passthrough = true;
|
self: *Cursor,
|
||||||
|
time_msec: u32,
|
||||||
|
device: *wlr.InputDevice,
|
||||||
|
delta_x: f64,
|
||||||
|
delta_y: f64,
|
||||||
|
unaccel_dx: f64,
|
||||||
|
unaccel_dy: f64,
|
||||||
|
) void {
|
||||||
|
// these will be used later when the relative pointer manager is setup
|
||||||
|
_ = unaccel_dx;
|
||||||
|
_ = unaccel_dy;
|
||||||
|
|
||||||
|
// process the cursor motion
|
||||||
|
self.wlr_cursor.move(device, delta_x, delta_y);
|
||||||
|
|
||||||
if (self.mode == .drag) {
|
if (self.mode == .drag) {
|
||||||
const modifiers = server.seat.keyboard_group.wlr_group.keyboard.getModifiers();
|
const modifiers = server.seat.keyboard_group.wlr_group.keyboard.getModifiers();
|
||||||
|
|
@ -84,12 +98,25 @@ pub fn processCursorMotion(self: *Cursor, time_msec: u32) void {
|
||||||
// Proceed if mousemap for current mouse and modifier state's exist
|
// 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 (server.mousemaps.get(Mousemap.hash(modifiers, @bitCast(self.drag.?.event_code)))) |map| {
|
||||||
if (map.options.lua_drag_ref_idx > 0) {
|
if (map.options.lua_drag_ref_idx > 0) {
|
||||||
passthrough = 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 } });
|
const passthrough = 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,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!passthrough) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (passthrough) {
|
|
||||||
const output = server.seat.focused_output;
|
const output = server.seat.focused_output;
|
||||||
// Exit the switch if no focused output exists
|
// Exit the switch if no focused output exists
|
||||||
std.debug.assert(output != null);
|
std.debug.assert(output != null);
|
||||||
|
|
@ -97,34 +124,67 @@ pub fn processCursorMotion(self: *Cursor, time_msec: u32) void {
|
||||||
const surfaceAtResult = output.?.surfaceAt(self.wlr_cursor.x, self.wlr_cursor.y);
|
const surfaceAtResult = output.?.surfaceAt(self.wlr_cursor.x, self.wlr_cursor.y);
|
||||||
if (surfaceAtResult) |surface| {
|
if (surfaceAtResult) |surface| {
|
||||||
if (surface.scene_node_data.* == .view) {
|
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.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 {
|
} else {
|
||||||
// This may not be necessary, remove if no bugs
|
|
||||||
server.seat.wlr_seat.pointerClearFocus();
|
server.seat.wlr_seat.pointerClearFocus();
|
||||||
self.wlr_cursor.setXcursor(self.x_cursor_manager, "default");
|
self.wlr_cursor.setXcursor(self.x_cursor_manager, "default");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// --------- WLR Cursor event handlers ---------
|
// --------- WLR Cursor event handlers ---------
|
||||||
fn handleMotion(
|
fn handleMotion(
|
||||||
_: *wl.Listener(*wlr.Pointer.event.Motion),
|
_: *wl.Listener(*wlr.Pointer.event.Motion),
|
||||||
event: *wlr.Pointer.event.Motion,
|
event: *wlr.Pointer.event.Motion,
|
||||||
) void {
|
) void {
|
||||||
server.cursor.wlr_cursor.move(event.device, event.delta_x, event.delta_y);
|
server.cursor.processCursorMotion(
|
||||||
server.cursor.processCursorMotion(event.time_msec);
|
event.time_msec,
|
||||||
|
event.device,
|
||||||
|
event.delta_x,
|
||||||
|
event.delta_y,
|
||||||
|
event.unaccel_dx,
|
||||||
|
event.unaccel_dy,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleMotionAbsolute(
|
fn handleMotionAbsolute(
|
||||||
_: *wl.Listener(*wlr.Pointer.event.MotionAbsolute),
|
listener: *wl.Listener(*wlr.Pointer.event.MotionAbsolute),
|
||||||
event: *wlr.Pointer.event.MotionAbsolute,
|
event: *wlr.Pointer.event.MotionAbsolute,
|
||||||
) void {
|
) void {
|
||||||
server.cursor.wlr_cursor.warpAbsolute(event.device, event.x, event.y);
|
const self: *Cursor = @fieldParentPtr("motion_absolute", listener);
|
||||||
server.cursor.processCursorMotion(event.time_msec);
|
// comment from dwl:
|
||||||
|
// This event is forwarded by the cursor when a pointer emits an _absolute_
|
||||||
|
// motion event, from 0..1 on each axis. This happens, for example, when
|
||||||
|
// wlroots is running under a Wayland window rather than KMS+DRM, and you
|
||||||
|
// move the mouse over the window. You could enter the window from any edge,
|
||||||
|
// so we have to warp the mouse there. Also, some hardware emits these events.
|
||||||
|
|
||||||
|
// move the cursor when it doesn't order its events
|
||||||
|
if (event.time_msec == 0) {
|
||||||
|
self.wlr_cursor.warpAbsolute(event.device, event.x, event.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
var layout_x: f64 = 0;
|
||||||
|
var layout_y: f64 = 0;
|
||||||
|
self.wlr_cursor.absoluteToLayoutCoords(event.device, event.x, event.y, &layout_x, &layout_y);
|
||||||
|
|
||||||
|
const delta_x = layout_x - self.wlr_cursor.x;
|
||||||
|
const delta_y = layout_y - self.wlr_cursor.y;
|
||||||
|
server.cursor.processCursorMotion(
|
||||||
|
event.time_msec,
|
||||||
|
event.device,
|
||||||
|
delta_x,
|
||||||
|
delta_y,
|
||||||
|
delta_x, // absolute motions do not decelerate
|
||||||
|
delta_y,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleButton(listener: *wl.Listener(*wlr.Pointer.event.Button), event: *wlr.Pointer.event.Button) void {
|
fn handleButton(listener: *wl.Listener(*wlr.Pointer.event.Button), event: *wlr.Pointer.event.Button) void {
|
||||||
|
|
@ -134,15 +194,28 @@ fn handleButton(listener: *wl.Listener(*wlr.Pointer.event.Button), event: *wlr.P
|
||||||
.pressed => {
|
.pressed => {
|
||||||
cursor.mode = .drag;
|
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 };
|
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
|
// Keep track of where the drag started
|
||||||
if (server.seat.focused_surface) |fs| {
|
if (server.seat.focused_surface) |fs| {
|
||||||
if (fs == .view) {
|
if (fs == .view) {
|
||||||
cursor.drag.?.view = .{
|
cursor.drag.?.view = .{
|
||||||
.view = fs.view,
|
.view = fs.view,
|
||||||
.dims = .{ .width = fs.view.xdg_toplevel.base.geometry.width, .height = fs.view.xdg_toplevel.base.geometry.height },
|
.dims = .{
|
||||||
.offset = .{ .x = cursor.drag.?.start.x - fs.view.scene_tree.node.x, .y = cursor.drag.?.start.y - fs.view.scene_tree.node.y },
|
.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,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -172,14 +245,20 @@ fn handleButton(listener: *wl.Listener(*wlr.Pointer.event.Button), event: *wlr.P
|
||||||
// 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) {
|
||||||
passthrough = map.callback(.press, .{
|
passthrough = map.callback(.press, .{
|
||||||
.{ .x = @as(c_int, @intFromFloat(cursor.wlr_cursor.x)), .y = @as(c_int, @intFromFloat(cursor.wlr_cursor.y)) },
|
.{
|
||||||
|
.x = @as(c_int, @intFromFloat(cursor.wlr_cursor.x)),
|
||||||
|
.y = @as(c_int, @intFromFloat(cursor.wlr_cursor.y)),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.released => {
|
.released => {
|
||||||
if (map.options.lua_press_ref_idx > 0) {
|
if (map.options.lua_press_ref_idx > 0) {
|
||||||
passthrough = map.callback(.release, .{
|
passthrough = map.callback(.release, .{
|
||||||
.{ .x = @as(c_int, @intFromFloat(cursor.wlr_cursor.x)), .y = @as(c_int, @intFromFloat(cursor.wlr_cursor.y)) },
|
.{
|
||||||
|
.x = @as(c_int, @intFromFloat(cursor.wlr_cursor.x)),
|
||||||
|
.y = @as(c_int, @intFromFloat(cursor.wlr_cursor.y)),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue