From bf759c7c57762d09d9b59fa2fa048c8c1bdf969e Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Wed, 1 Mar 2023 17:08:54 +0100 Subject: [PATCH] View: clamp to output on exiting float/fullscreen --- river/Cursor.zig | 2 +- river/Root.zig | 4 +++ river/View.zig | 75 ++++++++++++++++++++++-------------------- river/command/move.zig | 12 +++---- 4 files changed, 51 insertions(+), 42 deletions(-) diff --git a/river/Cursor.zig b/river/Cursor.zig index b6c34b8..efe9f4f 100644 --- a/river/Cursor.zig +++ b/river/Cursor.zig @@ -734,7 +734,7 @@ fn processMotion(self: *Self, device: *wlr.InputDevice, time: u32, delta_x: f64, data.delta_y = dy - @trunc(dy); const view = data.view; - view.move(@floatToInt(i32, dx), @floatToInt(i32, dy)); + view.pending.move(@floatToInt(i32, dx), @floatToInt(i32, dy)); self.wlr_cursor.move( device, @intToFloat(f64, view.pending.box.x - view.current.box.x), diff --git a/river/Root.zig b/river/Root.zig index 6223b0a..c86822e 100644 --- a/river/Root.zig +++ b/river/Root.zig @@ -403,6 +403,7 @@ pub fn applyPending(root: *Self) void { } else if (!view.current.float and view.pending.float) { // If switching from non-float to float, apply the saved float dimensions. view.pending.box = view.float_box; + view.pending.clampToOutput(); } if (output.pending.fullscreen == null and view.pending.fullscreen and @@ -420,7 +421,10 @@ pub fn applyPending(root: *Self) void { if (output.pending.fullscreen != output.inflight.fullscreen) { if (output.inflight.fullscreen) |view| { view.setFullscreen(false); + view.pending.box = view.post_fullscreen_box; + view.pending.clampToOutput(); + view.inflight.box = view.pending.box; } } diff --git a/river/View.zig b/river/View.zig index 5f78cf3..158d1c5 100644 --- a/river/View.zig +++ b/river/View.zig @@ -47,7 +47,7 @@ const Impl = union(enum) { xwayland_view: if (build_options.xwayland) XwaylandView else noreturn, }; -const State = struct { +pub const State = struct { /// The output the view is currently assigned to. /// May be null if there are no outputs or for newly created views. /// Must be set using setPendingOutput() @@ -66,6 +66,44 @@ const State = struct { fullscreen: bool = false, urgent: bool = false, borders: bool = true, + + /// Modify the x/y of the given state by delta_x/delta_y, clamping to the + /// bounds of the output. + pub fn move(state: *State, delta_x: i32, delta_y: i32) void { + const border_width = if (state.borders) server.config.border_width else 0; + + var output_width: i32 = math.maxInt(i32); + var output_height: i32 = math.maxInt(i32); + if (state.output) |output| { + output.wlr_output.effectiveResolution(&output_width, &output_height); + } + + const max_x = output_width - state.box.width - border_width; + state.box.x += delta_x; + state.box.x = math.max(state.box.x, border_width); + state.box.x = math.min(state.box.x, max_x); + state.box.x = math.max(state.box.x, 0); + + const max_y = output_height - state.box.height - border_width; + state.box.y += delta_y; + state.box.y = math.max(state.box.y, border_width); + state.box.y = math.min(state.box.y, max_y); + state.box.y = math.max(state.box.y, 0); + } + + pub fn clampToOutput(state: *State) void { + const output = state.output orelse return; + + var output_width: i32 = undefined; + var output_height: i32 = undefined; + output.wlr_output.effectiveResolution(&output_width, &output_height); + + const border_width = if (state.borders) server.config.border_width else 0; + state.box.width = math.min(state.box.width, output_width - (2 * border_width)); + state.box.height = math.min(state.box.height, output_height - (2 * border_width)); + + state.move(0, 0); + } }; /// The implementation of this view @@ -296,17 +334,8 @@ pub fn setPendingOutput(view: *Self, output: *Output) void { } output.pending.focus_stack.prepend(view); - // Adapt the floating position/dimensions of the view to the new output. if (view.pending.float) { - var output_width: i32 = undefined; - var output_height: i32 = undefined; - output.wlr_output.effectiveResolution(&output_width, &output_height); - - const border_width = if (view.pending.borders) server.config.border_width else 0; - view.pending.box.width = math.min(view.pending.box.width, output_width - (2 * border_width)); - view.pending.box.height = math.min(view.pending.box.height, output_height - (2 * border_width)); - - view.move(0, 0); + view.pending.clampToOutput(); } } @@ -397,30 +426,6 @@ 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 border_width = if (self.pending.borders) server.config.border_width else 0; - - var output_width: i32 = math.maxInt(i32); - var output_height: i32 = math.maxInt(i32); - if (self.pending.output) |output| { - output.wlr_output.effectiveResolution(&output_width, &output_height); - } - - const max_x = output_width - 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 = output_height - 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 73e6b54..741d83e 100644 --- a/river/command/move.zig +++ b/river/command/move.zig @@ -39,10 +39,10 @@ pub fn move( const view = getView(seat) orelse return; switch (direction) { - .up => view.move(0, -delta), - .down => view.move(0, delta), - .left => view.move(-delta, 0), - .right => view.move(delta, 0), + .up => view.pending.move(0, -delta), + .down => view.pending.move(0, delta), + .left => view.pending.move(-delta, 0), + .right => view.pending.move(delta, 0), } apply(view); @@ -108,7 +108,7 @@ pub fn resize( view.pending.box.width, output_width - 2 * server.config.border_width, ); - view.move(@divFloor(diff_width, 2), 0); + view.pending.move(@divFloor(diff_width, 2), 0); }, .vertical => { const prev_height = view.pending.box.height; @@ -120,7 +120,7 @@ pub fn resize( view.pending.box.height, output_height - 2 * server.config.border_width, ); - view.move(0, @divFloor(diff_height, 2)); + view.pending.move(0, @divFloor(diff_height, 2)); }, }