Cursor: lock to current geometry during move/resize

This eliminates cursor jitter entirely during interactive resize.

This also fixes a bug where the xdg-toplevel resizing state was not
cleared if a resize operation was aborted due to a change in view tags
or similar.
This commit is contained in:
Isaac Freund 2023-03-14 12:43:59 +01:00
parent 9db41115a8
commit a679743fa0
No known key found for this signature in database
GPG Key ID: 86DED400DDFD7A11
2 changed files with 47 additions and 50 deletions

View File

@ -861,12 +861,6 @@ fn processMotion(self: *Self, device: *wlr.InputDevice, time: u32, delta_x: f64,
const view = data.view;
view.pending.move(@floatToInt(i32, dx), @floatToInt(i32, dy));
self.wlr_cursor.warpClosest(
device,
@intToFloat(f64, data.offset_x + view.pending.box.x),
@intToFloat(f64, data.offset_y + view.pending.box.y),
);
server.root.applyPending();
},
.resize => |*data| {
@ -915,17 +909,6 @@ fn processMotion(self: *Self, device: *wlr.InputDevice, time: u32, delta_x: f64,
}
}
{
// Keep cursor locked to the original offset from the resize edges
const box = &data.view.pending.box;
const off_x = data.offset_x;
const off_y = data.offset_y;
const cursor_x = if (data.edges.left) off_x + box.x else box.x + box.width - off_x;
const cursor_y = if (data.edges.top) off_y + box.y else box.y + box.height - off_y;
self.wlr_cursor.warpClosest(device, @intToFloat(f64, cursor_x), @intToFloat(f64, cursor_y));
}
server.root.applyPending();
},
}
@ -979,42 +962,34 @@ pub fn updateState(self: *Self) void {
constraint.updateState();
}
if (self.shouldPassthrough()) {
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 +
@divTrunc(now.tv_nsec, std.time.ns_per_ms));
self.passthrough(msec);
}
}
fn shouldPassthrough(self: Self) bool {
// We clear focus on hiding the cursor and should not re-focus until the cursor is moved
// and shown again.
if (self.hidden) return false;
switch (self.mode) {
.passthrough => {
// If we are not currently in down/resize/move mode, we *always* need to passthrough()
// as what is under the cursor may have changed and we are not locked to a single
// target view.
return true;
if (!self.hidden) {
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 +
@divTrunc(now.tv_nsec, std.time.ns_per_ms));
self.passthrough(msec);
}
},
.down => {
// TODO: It's hard to determine from the target surface alone whether
// the surface is visible or not currently. Switching to the wlroots
// scene graph will fix this, but for now just don't bother.
return false;
},
.resize, .move => {
assert(server.lock_manager.state != .locked);
const target = if (self.mode == .resize) self.mode.resize.view else self.mode.move.view;
// The target view is no longer visible, is part of the layout, or is fullscreen.
return target.current.output == null or
target.current.tags & target.current.output.?.current.tags == 0 or
(!target.current.float and target.current.output.?.layout != null) or
target.current.fullscreen;
// TODO: Leave down mode if the target surface is no longer visible.
.down => assert(!self.hidden),
inline .move, .resize => |data, mode| {
assert(!self.hidden);
// These conditions are checked in Root.applyPending()
assert(data.view.current.tags & data.view.current.output.?.current.tags != 0);
assert(data.view.current.float or data.view.current.output.?.layout == null);
assert(!data.view.current.fullscreen);
// Keep the cursor locked to the original offset from the edges of the view.
const box = &data.view.current.box;
const dx = data.offset_x;
const dy = data.offset_y;
const lx = if (mode == .move or data.edges.left) dx + box.x else box.x + box.width - dx;
const ly = if (mode == .move or data.edges.top) dy + box.y else box.y + box.height - dy;
self.wlr_cursor.warpClosest(null, @intToFloat(f64, lx), @intToFloat(f64, ly));
},
}
}

View File

@ -493,6 +493,28 @@ pub fn applyPending(root: *Self) void {
}
}
{
var it = server.input_manager.seats.first;
while (it) |node| : (it = node.next) {
const cursor = &node.data.cursor;
switch (cursor.mode) {
.passthrough, .down => {},
inline .move, .resize => |data| {
if (data.view.inflight.output == null or
data.view.inflight.tags & data.view.inflight.output.?.inflight.tags == 0 or
(!data.view.inflight.float and data.view.inflight.output.?.layout != null) or
data.view.inflight.fullscreen)
{
cursor.mode = .passthrough;
data.view.pending.resizing = false;
data.view.inflight.resizing = false;
}
},
}
}
}
if (root.inflight_layout_demands == 0) {
root.sendConfigures();
}