Cursor: fix pointer drags with focus-follows-cursor
This commit is contained in:
parent
0cbe2b9fc3
commit
9212ac89fa
@ -750,24 +750,7 @@ fn processMotion(self: *Self, device: *wlr.InputDevice, time: u32, delta_x: f64,
|
|||||||
switch (self.mode) {
|
switch (self.mode) {
|
||||||
.passthrough => {
|
.passthrough => {
|
||||||
self.wlr_cursor.move(device, dx, dy);
|
self.wlr_cursor.move(device, dx, dy);
|
||||||
|
self.checkFocusFollowsCursor();
|
||||||
if (self.surfaceAt()) |result| {
|
|
||||||
const focus_change = self.seat.wlr_seat.pointer_state.focused_surface != result.surface;
|
|
||||||
if (server.config.focus_follows_cursor == .normal and focus_change) {
|
|
||||||
switch (result.parent) {
|
|
||||||
.view => |view| {
|
|
||||||
if (self.seat.focused != .view or self.seat.focused.view != view) {
|
|
||||||
self.seat.focusOutput(view.output);
|
|
||||||
self.seat.focus(view);
|
|
||||||
server.root.startTransaction();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.layer_surface => {},
|
|
||||||
.xwayland_unmanaged => assert(build_options.xwayland),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.passthrough(time);
|
self.passthrough(time);
|
||||||
},
|
},
|
||||||
.down => |view| {
|
.down => |view| {
|
||||||
@ -826,6 +809,27 @@ fn processMotion(self: *Self, device: *wlr.InputDevice, time: u32, delta_x: f64,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn checkFocusFollowsCursor(self: *Self) void {
|
||||||
|
// Don't do focus-follows-cursor if a drag is in progress as focus change can't occur
|
||||||
|
if (self.seat.pointer_drag) return;
|
||||||
|
if (server.config.focus_follows_cursor == .disabled) return;
|
||||||
|
if (self.surfaceAt()) |result| {
|
||||||
|
if (self.seat.wlr_seat.pointer_state.focused_surface != result.surface) {
|
||||||
|
switch (result.parent) {
|
||||||
|
.view => |view| {
|
||||||
|
if (self.seat.focused != .view or self.seat.focused.view != view) {
|
||||||
|
self.seat.focusOutput(view.output);
|
||||||
|
self.seat.focus(view);
|
||||||
|
server.root.startTransaction();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.layer_surface => {},
|
||||||
|
.xwayland_unmanaged => assert(build_options.xwayland),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Handle potential change in location of views on the output, as well as
|
/// 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,
|
/// the target view of a cursor operation potentially being moved to a non-visible tag,
|
||||||
/// becoming fullscreen, etc.
|
/// becoming fullscreen, etc.
|
||||||
|
@ -19,6 +19,7 @@ const Self = @This();
|
|||||||
|
|
||||||
const build_options = @import("build_options");
|
const build_options = @import("build_options");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const assert = std.debug.assert;
|
||||||
const wlr = @import("wlroots");
|
const wlr = @import("wlroots");
|
||||||
const wl = @import("wayland").server.wl;
|
const wl = @import("wayland").server.wl;
|
||||||
const xkb = @import("xkbcommon");
|
const xkb = @import("xkbcommon");
|
||||||
@ -81,11 +82,15 @@ focus_stack: ViewStack(*View) = .{},
|
|||||||
/// List of status tracking objects relaying changes to this seat to clients.
|
/// List of status tracking objects relaying changes to this seat to clients.
|
||||||
status_trackers: std.SinglyLinkedList(SeatStatus) = .{},
|
status_trackers: std.SinglyLinkedList(SeatStatus) = .{},
|
||||||
|
|
||||||
|
/// True if a pointer drag is currently in progress
|
||||||
|
pointer_drag: bool = false,
|
||||||
|
|
||||||
request_set_selection: wl.Listener(*wlr.Seat.event.RequestSetSelection) =
|
request_set_selection: wl.Listener(*wlr.Seat.event.RequestSetSelection) =
|
||||||
wl.Listener(*wlr.Seat.event.RequestSetSelection).init(handleRequestSetSelection),
|
wl.Listener(*wlr.Seat.event.RequestSetSelection).init(handleRequestSetSelection),
|
||||||
request_start_drag: wl.Listener(*wlr.Seat.event.RequestStartDrag) =
|
request_start_drag: wl.Listener(*wlr.Seat.event.RequestStartDrag) =
|
||||||
wl.Listener(*wlr.Seat.event.RequestStartDrag).init(handleRequestStartDrag),
|
wl.Listener(*wlr.Seat.event.RequestStartDrag).init(handleRequestStartDrag),
|
||||||
start_drag: wl.Listener(*wlr.Drag) = wl.Listener(*wlr.Drag).init(handleStartDrag),
|
start_drag: wl.Listener(*wlr.Drag) = wl.Listener(*wlr.Drag).init(handleStartDrag),
|
||||||
|
pointer_drag_destroy: wl.Listener(*wlr.Drag) = wl.Listener(*wlr.Drag).init(handlePointerDragDestroy),
|
||||||
request_set_primary_selection: wl.Listener(*wlr.Seat.event.RequestSetPrimarySelection) =
|
request_set_primary_selection: wl.Listener(*wlr.Seat.event.RequestSetPrimarySelection) =
|
||||||
wl.Listener(*wlr.Seat.event.RequestSetPrimarySelection).init(handleRequestSetPrimarySelection),
|
wl.Listener(*wlr.Seat.event.RequestSetPrimarySelection).init(handleRequestSetPrimarySelection),
|
||||||
|
|
||||||
@ -443,7 +448,15 @@ fn handleRequestStartDrag(
|
|||||||
const self = @fieldParentPtr(Self, "request_start_drag", listener);
|
const self = @fieldParentPtr(Self, "request_start_drag", listener);
|
||||||
|
|
||||||
if (!self.wlr_seat.validatePointerGrabSerial(event.origin, event.serial)) {
|
if (!self.wlr_seat.validatePointerGrabSerial(event.origin, event.serial)) {
|
||||||
log.debug("ignoring request to start drag, failed to validate serial {}", .{event.serial});
|
log.debug("ignoring request to start drag, " ++
|
||||||
|
"failed to validate pointer serial {}", .{event.serial});
|
||||||
|
if (event.drag.source) |source| source.destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.pointer_drag) {
|
||||||
|
log.debug("ignoring request to start pointer drag, " ++
|
||||||
|
"another pointer drag is already in progress", .{});
|
||||||
if (event.drag.source) |source| source.destroy();
|
if (event.drag.source) |source| source.destroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -452,12 +465,14 @@ fn handleRequestStartDrag(
|
|||||||
self.wlr_seat.startPointerDrag(event.drag, event.serial);
|
self.wlr_seat.startPointerDrag(event.drag, event.serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleStartDrag(
|
fn handleStartDrag(listener: *wl.Listener(*wlr.Drag), wlr_drag: *wlr.Drag) void {
|
||||||
listener: *wl.Listener(*wlr.Drag),
|
|
||||||
wlr_drag: *wlr.Drag,
|
|
||||||
) void {
|
|
||||||
const self = @fieldParentPtr(Self, "start_drag", listener);
|
const self = @fieldParentPtr(Self, "start_drag", listener);
|
||||||
|
|
||||||
|
assert(wlr_drag.grab_type == .keyboard_pointer);
|
||||||
|
|
||||||
|
self.pointer_drag = true;
|
||||||
|
wlr_drag.events.destroy.add(&self.pointer_drag_destroy);
|
||||||
|
|
||||||
if (wlr_drag.icon) |wlr_drag_icon| {
|
if (wlr_drag.icon) |wlr_drag_icon| {
|
||||||
const node = util.gpa.create(std.SinglyLinkedList(DragIcon).Node) catch {
|
const node = util.gpa.create(std.SinglyLinkedList(DragIcon).Node) catch {
|
||||||
log.crit("out of memory", .{});
|
log.crit("out of memory", .{});
|
||||||
@ -469,6 +484,14 @@ fn handleStartDrag(
|
|||||||
self.cursor.mode = .passthrough;
|
self.cursor.mode = .passthrough;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handlePointerDragDestroy(listener: *wl.Listener(*wlr.Drag), wlr_drag: *wlr.Drag) void {
|
||||||
|
const self = @fieldParentPtr(Self, "pointer_drag_destroy", listener);
|
||||||
|
self.pointer_drag = false;
|
||||||
|
self.pointer_drag_destroy.link.remove();
|
||||||
|
self.cursor.checkFocusFollowsCursor();
|
||||||
|
self.cursor.updateState();
|
||||||
|
}
|
||||||
|
|
||||||
fn handleRequestSetPrimarySelection(
|
fn handleRequestSetPrimarySelection(
|
||||||
listener: *wl.Listener(*wlr.Seat.event.RequestSetPrimarySelection),
|
listener: *wl.Listener(*wlr.Seat.event.RequestSetPrimarySelection),
|
||||||
event: *wlr.Seat.event.RequestSetPrimarySelection,
|
event: *wlr.Seat.event.RequestSetPrimarySelection,
|
||||||
|
Loading…
Reference in New Issue
Block a user