git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit8998355880a1f0311acedc33907cd13b29a8d919
parent787066c8b1
authorIsaac Freund <[email protected]>
date2023-11-06 13:10
pointer-constraints: fix assertion failure

It is possible for the assertion in PointerConstraint.confine() to fail
if a view with an active pointer constraint is, for example, resized
using a keybinding such that the pointer is outside the constraint
region.

Handle this edge case by deactivating the constraint. The other option
would be to warp the pointer to the nearest point still inside the
constraint region. Deactivating the constraint is far simpler however
and I don't expect this to be a UX pain point.

 river/PointerConstraint.zig | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/river/PointerConstraint.zig b/river/PointerConstraint.zig
index 5da1dc3..e833ee8 100644
--- a/river/PointerConstraint.zig
+++ b/river/PointerConstraint.zig
@@ -119,13 +119,23 @@ pub fn updateState(constraint: *PointerConstraint) void {
         return;
     }
 
-    const warp_lx = @as(f64, @floatFromInt(lx)) + constraint.state.active.sx;
-    const warp_ly = @as(f64, @floatFromInt(ly)) + constraint.state.active.sy;
+    const sx = constraint.state.active.sx;
+    const sy = constraint.state.active.sy;
+    const warp_lx = @as(f64, @floatFromInt(lx)) + sx;
+    const warp_ly = @as(f64, @floatFromInt(ly)) + sy;
     if (!seat.cursor.wlr_cursor.warp(null, warp_lx, warp_ly)) {
         log.info("deactivating pointer constraint, could not warp cursor", .{});
         constraint.deactivate();
         return;
     }
+
+    // It is possible for the cursor to end up outside of the constraint region despite the warp
+    // if, for example, the a keybinding is used to resize the view.
+    if (!constraint.wlr_constraint.region.containsPoint(@intFromFloat(sx), @intFromFloat(sy), null)) {
+        log.info("deactivating pointer constraint, cursor outside region despite warp", .{});
+        constraint.deactivate();
+        return;
+    }
 }
 
 pub fn confine(constraint: *PointerConstraint, dx: *f64, dy: *f64) void {