Cursor: fix move/resize with high poll rate/low dpi mice
This commit is contained in:
parent
4b0c5acc46
commit
8134b81283
1 changed files with 32 additions and 9 deletions
|
@ -43,9 +43,21 @@ const XwaylandUnmanaged = @import("XwaylandUnmanaged.zig");
|
||||||
const Mode = union(enum) {
|
const Mode = union(enum) {
|
||||||
passthrough: void,
|
passthrough: void,
|
||||||
down: *View,
|
down: *View,
|
||||||
move: *View,
|
move: struct {
|
||||||
|
view: *View,
|
||||||
|
/// View coordinates are stored as i32s as they are in logical pixels.
|
||||||
|
/// However, it is possible to move the cursor by a fraction of a
|
||||||
|
/// logical pixel and this happens in practice with low dpi, high
|
||||||
|
/// polling rate mice. Therefore we must accumulate the current
|
||||||
|
/// fractional offset of the mouse to avoid rounding down tiny
|
||||||
|
/// motions to 0.
|
||||||
|
delta_x: f64 = 0,
|
||||||
|
delta_y: f64 = 0,
|
||||||
|
},
|
||||||
resize: struct {
|
resize: struct {
|
||||||
view: *View,
|
view: *View,
|
||||||
|
delta_x: f64 = 0,
|
||||||
|
delta_y: f64 = 0,
|
||||||
/// Offset from the lower right corner of the view
|
/// Offset from the lower right corner of the view
|
||||||
offset_x: i32,
|
offset_x: i32,
|
||||||
offset_y: i32,
|
offset_y: i32,
|
||||||
|
@ -184,7 +196,7 @@ pub fn handleViewUnmap(self: *Self, view: *View) void {
|
||||||
if (switch (self.mode) {
|
if (switch (self.mode) {
|
||||||
.passthrough => false,
|
.passthrough => false,
|
||||||
.down => |target_view| target_view == view,
|
.down => |target_view| target_view == view,
|
||||||
.move => |target_view| target_view == view,
|
.move => |data| data.view == view,
|
||||||
.resize => |data| data.view == view,
|
.resize => |data| data.view == view,
|
||||||
}) {
|
}) {
|
||||||
self.mode = .passthrough;
|
self.mode = .passthrough;
|
||||||
|
@ -649,7 +661,7 @@ pub fn enterMode(self: *Self, mode: std.meta.Tag((Mode)), view: *View) void {
|
||||||
.move, .resize => {
|
.move, .resize => {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
.passthrough, .down => unreachable,
|
.passthrough, .down => unreachable,
|
||||||
.move => self.mode = .{ .move = view },
|
.move => self.mode = .{ .move = .{ .view = view } },
|
||||||
.resize => {
|
.resize => {
|
||||||
const cur_box = &view.current.box;
|
const cur_box = &view.current.box;
|
||||||
self.mode = .{ .resize = .{
|
self.mode = .{ .resize = .{
|
||||||
|
@ -768,8 +780,14 @@ fn processMotion(self: *Self, device: *wlr.InputDevice, time: u32, delta_x: f64,
|
||||||
self.wlr_cursor.y - @intToFloat(f64, output_box.y + view.current.box.y - view.surface_box.y),
|
self.wlr_cursor.y - @intToFloat(f64, output_box.y + view.current.box.y - view.surface_box.y),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
.move => |view| {
|
.move => |*data| {
|
||||||
view.move(@floatToInt(i32, delta_x), @floatToInt(i32, delta_y));
|
dx += data.delta_x;
|
||||||
|
dy += data.delta_y;
|
||||||
|
data.delta_x = dx - @trunc(dx);
|
||||||
|
data.delta_y = dy - @trunc(dy);
|
||||||
|
|
||||||
|
const view = data.view;
|
||||||
|
view.move(@floatToInt(i32, dx), @floatToInt(i32, dy));
|
||||||
self.wlr_cursor.move(
|
self.wlr_cursor.move(
|
||||||
device,
|
device,
|
||||||
@intToFloat(f64, view.pending.box.x - view.current.box.x),
|
@intToFloat(f64, view.pending.box.x - view.current.box.x),
|
||||||
|
@ -777,13 +795,18 @@ fn processMotion(self: *Self, device: *wlr.InputDevice, time: u32, delta_x: f64,
|
||||||
);
|
);
|
||||||
view.applyPending();
|
view.applyPending();
|
||||||
},
|
},
|
||||||
.resize => |data| {
|
.resize => |*data| {
|
||||||
|
dx += data.delta_x;
|
||||||
|
dy += data.delta_y;
|
||||||
|
data.delta_x = dx - @trunc(dx);
|
||||||
|
data.delta_y = dy - @trunc(dy);
|
||||||
|
|
||||||
const border_width = if (data.view.draw_borders) server.config.border_width else 0;
|
const border_width = if (data.view.draw_borders) server.config.border_width else 0;
|
||||||
|
|
||||||
// Set width/height of view, clamp to view size constraints and output dimensions
|
// Set width/height of view, clamp to view size constraints and output dimensions
|
||||||
const box = &data.view.pending.box;
|
const box = &data.view.pending.box;
|
||||||
box.width = @intCast(u32, math.max(0, @intCast(i32, box.width) + @floatToInt(i32, delta_x)));
|
box.width = @intCast(u32, math.max(0, @intCast(i32, box.width) + @floatToInt(i32, dx)));
|
||||||
box.height = @intCast(u32, math.max(0, @intCast(i32, box.height) + @floatToInt(i32, delta_y)));
|
box.height = @intCast(u32, math.max(0, @intCast(i32, box.height) + @floatToInt(i32, dy)));
|
||||||
|
|
||||||
data.view.applyConstraints();
|
data.view.applyConstraints();
|
||||||
|
|
||||||
|
@ -830,7 +853,7 @@ fn shouldPassthrough(self: Self) bool {
|
||||||
return target.current.tags & target.output.current.tags == 0;
|
return target.current.tags & target.output.current.tags == 0;
|
||||||
},
|
},
|
||||||
.resize, .move => {
|
.resize, .move => {
|
||||||
const target = if (self.mode == .resize) self.mode.resize.view else self.mode.move;
|
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.
|
// The target view is no longer visible, is part of the layout, or is fullscreen.
|
||||||
return target.current.tags & target.output.current.tags == 0 or
|
return target.current.tags & target.output.current.tags == 0 or
|
||||||
(!target.current.float and target.output.current.layout != null) or
|
(!target.current.float and target.output.current.layout != null) or
|
||||||
|
|
Loading…
Reference in a new issue