From 50814e0ffe3a89126e1b163dc24b09a004fc499d Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Mon, 11 Oct 2021 15:01:57 +0200 Subject: [PATCH] pointer-constraints: fix coordinates Currently the implementation treats the x/y coordinates of View.State.box as layout coordinates instead of output-relative. This causes issues when using an output not at 0,0. --- deps/zig-pixman | 2 +- river/PointerConstraint.zig | 41 ++++++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/deps/zig-pixman b/deps/zig-pixman index 135f223..88520f2 160000 --- a/deps/zig-pixman +++ b/deps/zig-pixman @@ -1 +1 @@ -Subproject commit 135f22345671e0ae2d1bc4b27cfdee9e97b97dfc +Subproject commit 88520f264cd65153fe77ad2e5a17d22eee5e1af4 diff --git a/river/PointerConstraint.zig b/river/PointerConstraint.zig index 7ab8ad5..5e632e6 100644 --- a/river/PointerConstraint.zig +++ b/river/PointerConstraint.zig @@ -24,6 +24,7 @@ const wl = @import("wayland").server.wl; const pixman = @import("pixman"); const log = @import("log.zig"); +const server = &@import("main.zig").server; const util = @import("util.zig"); const Cursor = @import("Cursor.zig"); @@ -62,11 +63,16 @@ pub fn setAsActive(self: *Self) void { self.cursor.constraint = self.constraint; + // TODO: This is the same hack sway uses to deal with the fact that this + // function may be called in response to a surface commit but before the + // the wlroots pointer constraints implementation's commit handler has been called. + // This logic is duplicated from that commit handler. if (self.constraint.current.region.notEmpty()) { _ = self.constraint.region.intersect(&self.constraint.surface.input_region, &self.constraint.current.region); } else { _ = self.constraint.region.copy(&self.constraint.surface.input_region); } + self.constrainToRegion(); self.constraint.sendActivated(); @@ -75,19 +81,23 @@ pub fn setAsActive(self: *Self) void { fn constrainToRegion(self: *Self) void { if (self.cursor.constraint != self.constraint) return; if (View.fromWlrSurface(self.constraint.surface)) |view| { - const cx = @floatToInt(c_int, self.cursor.wlr_cursor.x) - @intCast(c_int, view.current.box.x); - const cy = @floatToInt(c_int, self.cursor.wlr_cursor.y) - @intCast(c_int, view.current.box.y); + const output = view.output; + const output_box = server.root.output_layout.getBox(output.wlr_output).?; - var box: pixman.Box32 = undefined; + const surface_lx = @intToFloat(f64, output_box.x + view.current.box.x - view.surface_box.x); + const surface_ly = @intToFloat(f64, output_box.y + view.current.box.y - view.surface_box.y); - if (!self.constraint.region.containsPoint(cx, cy, &box)) { + const sx = @floatToInt(c_int, self.cursor.wlr_cursor.x - surface_lx); + const sy = @floatToInt(c_int, self.cursor.wlr_cursor.y - surface_ly); + + // If the cursor is not already inside the constraint region, warp + // it to an arbitrary point inside the constraint region. + if (!self.constraint.region.containsPoint(sx, sy, null)) { const rects = self.constraint.region.rectangles(); - if (rects.len > 0) { - const new_cx = @intToFloat(f64, view.current.box.x + rects[0].x1 + @divFloor(rects[0].x2, 2)); - const new_cy = @intToFloat(f64, view.current.box.y + rects[0].y1 + @divFloor(rects[0].y2, 2)); - - self.cursor.wlr_cursor.warpClosest(null, new_cx, new_cy); + const new_lx = surface_lx + @intToFloat(f64, rects[0].x1 + rects[0].x2) / 2; + const new_ly = surface_ly + @intToFloat(f64, rects[0].y1 + rects[0].y2) / 2; + self.cursor.wlr_cursor.warpClosest(null, new_lx, new_ly); } } } @@ -117,10 +127,17 @@ pub fn warpToHint(cursor: *Cursor) void { if (cursor.constraint) |constraint| { if (constraint.current.committed.cursor_hint) { if (View.fromWlrSurface(constraint.surface)) |view| { - const cx = constraint.current.cursor_hint.x + @intToFloat(f64, view.current.box.x); - const cy = constraint.current.cursor_hint.y + @intToFloat(f64, view.current.box.y); + const output = view.output; + const output_box = server.root.output_layout.getBox(output.wlr_output).?; - _ = cursor.wlr_cursor.warp(null, cx, cy); + const surface_lx = @intToFloat(f64, output_box.x + view.current.box.x - view.surface_box.x); + const surface_ly = @intToFloat(f64, output_box.y + view.current.box.y - view.surface_box.y); + + _ = cursor.wlr_cursor.warp( + null, + surface_lx + constraint.current.cursor_hint.x, + surface_ly + constraint.current.cursor_hint.y, + ); } } }