cursor: reset state if needed on transaction commit

A transaction may move the current target of a cursor action to a
non-visible tag, make it fullscreen, or otherwise change things such
that the current cursor state no longer makes sense.

To handle this, check if we should reset cursor state every time a
transaction is committed.
This commit is contained in:
Leon Henrik Plickat 2021-06-23 15:56:38 +02:00 committed by Isaac Freund
parent b7d330c0da
commit a3c6571326
3 changed files with 41 additions and 0 deletions

View file

@ -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);

View file

@ -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

View file

@ -16,6 +16,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
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;