diff --git a/river/Cursor.zig b/river/Cursor.zig index 5a09a88..dd1f51b 100644 --- a/river/Cursor.zig +++ b/river/Cursor.zig @@ -20,6 +20,7 @@ const Self = @This(); const build_options = @import("build_options"); const std = @import("std"); const assert = std.debug.assert; +const os = std.os; const math = std.math; const wlr = @import("wlroots"); const wayland = @import("wayland"); @@ -674,6 +675,40 @@ fn processMotion(self: *Self, device: *wlr.InputDevice, time: u32, delta_x: f64, } } +/// Handle potential change in location of views on the output, as well as +/// the target view of a cursor operation potentially being moved to a non-visible tag, +/// becoming fullscreen, etc. +pub fn maybeResetState(self: *Self) void { + switch (self.mode) { + .passthrough => {}, + .down => |target| { + // If the target view is no longer visible, abort the operation. + if (target.current.tags & target.output.current.tags == 0) { + self.mode = .passthrough; + } + }, + .resize, .move => { + // If the target view is no longer visible, or now fullscreen or no + // longer floating, abort the operation. + const target = if (self.mode == .resize) self.mode.resize.view else self.mode.move; + if (target.current.tags & target.output.current.tags == 0 or + (!target.current.float and target.output.current.layout != null) or + target.current.fullscreen) + { + self.mode = .passthrough; + } + }, + } + + if (self.mode == .passthrough) { + var now: os.timespec = undefined; + os.clock_gettime(os.CLOCK_MONOTONIC, &now) catch @panic("CLOCK_MONOTONIC not supported"); + const msec = @intCast(u32, now.tv_sec * std.time.ms_per_s + + @divFloor(now.tv_nsec, std.time.ns_per_ms)); + self.passthrough(msec); + } +} + /// Pass an event on to the surface under the cursor, if any. fn passthrough(self: *Self, time: u32) void { assert(self.mode == .passthrough); diff --git a/river/Root.zig b/river/Root.zig index aad7541..b51abed 100644 --- a/river/Root.zig +++ b/river/Root.zig @@ -405,6 +405,11 @@ fn commitTransaction(self: *Self) void { output.damage.addWhole(); } + + var seat_it = server.input_manager.seats.first; + while (seat_it) |seat_node| : (seat_it = seat_node.next) { + seat_node.data.cursor.maybeResetState(); + } } /// Send the new output configuration to all wlr-output-manager clients diff --git a/river/util.zig b/river/util.zig index d28122c..ceeea07 100644 --- a/river/util.zig +++ b/river/util.zig @@ -16,6 +16,7 @@ // along with this program. If not, see . const std = @import("std"); +const os = std.os; /// The global general-purpose allocator used throughout river's code pub const gpa = std.heap.c_allocator;