From c51f2176b3eea842949edb42e6449c12e7ae0616 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Sun, 27 Dec 2020 01:06:18 +0100 Subject: [PATCH] view: unify clamped move logic, fix overflow --- river/Cursor.zig | 29 +++++++---------------------- river/View.zig | 21 +++++++++++++++++++++ river/command/move.zig | 32 ++++++-------------------------- 3 files changed, 34 insertions(+), 48 deletions(-) diff --git a/river/Cursor.zig b/river/Cursor.zig index b10695b..3fde7d4 100644 --- a/river/Cursor.zig +++ b/river/Cursor.zig @@ -19,6 +19,7 @@ const Self = @This(); const build_options = @import("build_options"); const std = @import("std"); +const math = std.math; const wlr = @import("wlroots"); const wayland = @import("wayland"); const wl = wayland.server.wl; @@ -468,8 +469,6 @@ fn leaveMode(self: *Self, event: *wlr.Pointer.event.Button) void { } fn processMotion(self: *Self, device: *wlr.InputDevice, time: u32, delta_x: f64, delta_y: f64) void { - const config = self.seat.input_manager.server.config; - switch (self.mode) { .passthrough => { self.wlr_cursor.move(device, delta_x, delta_y); @@ -484,42 +483,28 @@ fn processMotion(self: *Self, device: *wlr.InputDevice, time: u32, delta_x: f64, ); }, .move => |view| { - const border_width = if (view.draw_borders) config.border_width else 0; - - // Set x/y of cursor and view, clamp to output dimensions - const output_resolution = view.output.getEffectiveResolution(); - view.pending.box.x = std.math.clamp( - view.pending.box.x + @floatToInt(i32, delta_x), - @intCast(i32, border_width), - @intCast(i32, output_resolution.width - view.pending.box.width - border_width), - ); - view.pending.box.y = std.math.clamp( - view.pending.box.y + @floatToInt(i32, delta_y), - @intCast(i32, border_width), - @intCast(i32, output_resolution.height - view.pending.box.height - border_width), - ); - + view.move(@floatToInt(i32, delta_x), @floatToInt(i32, delta_y)); self.wlr_cursor.move( device, @intToFloat(f64, view.pending.box.x - view.current.box.x), @intToFloat(f64, view.pending.box.y - view.current.box.y), ); - view.applyPending(); }, .resize => |data| { + const config = &self.seat.input_manager.server.config; const border_width = if (data.view.draw_borders) config.border_width else 0; // Set width/height of view, clamp to view size constraints and output dimensions const box = &data.view.pending.box; - box.width = @intCast(u32, std.math.max(0, @intCast(i32, box.width) + @floatToInt(i32, delta_x))); - box.height = @intCast(u32, std.math.max(0, @intCast(i32, box.height) + @floatToInt(i32, delta_y))); + box.width = @intCast(u32, math.max(0, @intCast(i32, box.width) + @floatToInt(i32, delta_x))); + box.height = @intCast(u32, math.max(0, @intCast(i32, box.height) + @floatToInt(i32, delta_y))); data.view.applyConstraints(); const output_resolution = data.view.output.getEffectiveResolution(); - box.width = std.math.min(box.width, output_resolution.width - border_width - @intCast(u32, box.x)); - box.height = std.math.min(box.height, output_resolution.height - border_width - @intCast(u32, box.y)); + box.width = math.min(box.width, output_resolution.width - border_width - @intCast(u32, box.x)); + box.height = math.min(box.height, output_resolution.height - border_width - @intCast(u32, box.y)); data.view.applyPending(); diff --git a/river/View.zig b/river/View.zig index 3003f88..323904a 100644 --- a/river/View.zig +++ b/river/View.zig @@ -19,6 +19,7 @@ const Self = @This(); const build_options = @import("build_options"); const std = @import("std"); +const math = std.math; const os = std.os; const wlr = @import("wlroots"); const wl = @import("wayland").server.wl; @@ -380,6 +381,26 @@ pub fn getConstraints(self: Self) Constraints { }; } +/// Modify the pending x/y of the view by the given deltas, clamping to the +/// bounds of the output. +pub fn move(self: *Self, delta_x: i32, delta_y: i32) void { + const config = &self.output.root.server.config; + const border_width = if (self.draw_borders) @intCast(i32, config.border_width) else 0; + const output_resolution = self.output.getEffectiveResolution(); + + const max_x = @intCast(i32, output_resolution.width) - @intCast(i32, self.pending.box.width) - border_width; + self.pending.box.x += delta_x; + self.pending.box.x = math.max(self.pending.box.x, border_width); + self.pending.box.x = math.min(self.pending.box.x, max_x); + self.pending.box.x = math.max(self.pending.box.x, 0); + + const max_y = @intCast(i32, output_resolution.height) - @intCast(i32, self.pending.box.height) - border_width; + self.pending.box.y += delta_y; + self.pending.box.y = math.max(self.pending.box.y, border_width); + self.pending.box.y = math.min(self.pending.box.y, max_y); + self.pending.box.y = math.max(self.pending.box.y, 0); +} + /// Find and return the view corresponding to a given surface, if any pub fn fromWlrSurface(surface: *wlr.Surface) ?*Self { if (surface.isXdgSurface()) { diff --git a/river/command/move.zig b/river/command/move.zig index cdb29e0..7bc07cc 100644 --- a/river/command/move.zig +++ b/river/command/move.zig @@ -41,10 +41,10 @@ pub fn move( const view = getView(seat) orelse return; switch (direction) { - .up => moveVertical(view, -1 * delta), - .down => moveVertical(view, delta), - .left => moveHorizontal(view, -1 * delta), - .right => moveHorizontal(view, delta), + .up => view.move(0, -delta), + .down => view.move(0, delta), + .left => view.move(-delta, 0), + .right => view.move(delta, 0), } apply(view); @@ -110,7 +110,7 @@ pub fn resize( output_box.width - @intCast(u32, 2 * border_width), ); real_delta -= @intCast(i32, view.pending.box.width); - moveHorizontal(view, @divFloor(real_delta, 2)); + view.move(@divFloor(real_delta, 2), 0); }, .vertical => { var real_delta: i32 = @intCast(i32, view.pending.box.height); @@ -128,7 +128,7 @@ pub fn resize( output_box.height - @intCast(u32, 2 * border_width), ); real_delta -= @intCast(i32, view.pending.box.height); - moveVertical(view, @divFloor(real_delta, 2)); + view.move(0, @divFloor(real_delta, 2)); }, } @@ -155,23 +155,3 @@ fn getView(seat: *Seat) ?*View { return view; } - -fn moveVertical(view: *View, delta: i32) void { - const output_box = view.output.getEffectiveResolution(); - const border_width = @intCast(i32, view.output.root.server.config.border_width); - view.pending.box.y = std.math.clamp( - view.pending.box.y + delta, - border_width, - @intCast(i32, output_box.height - view.pending.box.height) - border_width, - ); -} - -fn moveHorizontal(view: *View, delta: i32) void { - const output_box = view.output.getEffectiveResolution(); - const border_width = @intCast(i32, view.output.root.server.config.border_width); - view.pending.box.x = std.math.clamp( - view.pending.box.x + delta, - border_width, - @intCast(i32, output_box.width - view.pending.box.width) - border_width, - ); -}