add multimonitor
This commit is contained in:
+47
-2
@@ -76,6 +76,10 @@ pointer_y: i32 = 0,
|
||||
/// The window the pointer is currently inside.
|
||||
hovered: ?*Window = null,
|
||||
|
||||
/// A screen to warp the pointer onto in the next manage sequence. Set when
|
||||
/// focus moves to an output with no window on it to warp to.
|
||||
pending_warp_output: ?*Output = null,
|
||||
|
||||
op: ?Op = null,
|
||||
/// An operation to start in the next manage sequence.
|
||||
pending_op: ?Op = null,
|
||||
@@ -165,12 +169,19 @@ fn createBindings(self: *Seat) !void {
|
||||
std.log.info("registered {d}/{d} pointer bindings", .{ self.buttons.items.len, config.buttons.len });
|
||||
}
|
||||
|
||||
/// The output this seat is working on: the one holding the focused window,
|
||||
/// else the one under the pointer.
|
||||
/// The output this seat is working on: the one holding the focused window, else
|
||||
/// the one focus was last moved to, else the one under the pointer.
|
||||
///
|
||||
/// That middle case is what makes an empty screen a place the user can be.
|
||||
/// Moving to a screen with nothing on it clears the focused window, and with
|
||||
/// only the pointer to fall back on the seat would go on reporting the screen it
|
||||
/// came from — so the tag keys, the layout keys and the next window spawned
|
||||
/// would all land back on the monitor just left.
|
||||
pub fn currentOutput(self: *Seat) ?*Output {
|
||||
if (self.focused) |win| {
|
||||
if (win.output) |out| return out;
|
||||
}
|
||||
if (self.wm.focused_output) |out| return out;
|
||||
return self.wm.outputAt(self.pointer_x, self.pointer_y) orelse self.wm.firstOutput();
|
||||
}
|
||||
|
||||
@@ -256,6 +267,11 @@ pub fn applyManage(self: *Seat) void {
|
||||
self.pending_clear_focus = false;
|
||||
self.wm.ipcDirty();
|
||||
}
|
||||
|
||||
if (self.pending_warp_output) |out| {
|
||||
self.warpToOutput(out);
|
||||
self.pending_warp_output = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Pull the pointer to the middle of a newly focused window.
|
||||
@@ -274,6 +290,25 @@ fn warpTo(self: *Seat, win: *Window) void {
|
||||
);
|
||||
}
|
||||
|
||||
/// Pull the pointer onto a screen the keyboard has just moved to, when there is
|
||||
/// no window there to warp to instead.
|
||||
///
|
||||
/// Without it, moving to an empty screen leaves the cursor on the one before —
|
||||
/// and with `focus_follows_mouse` on, the first window the pointer then brushes
|
||||
/// past takes the focus straight back. Manage sequence only.
|
||||
fn warpToOutput(self: *Seat, out: *Output) void {
|
||||
if (!config.warp_cursor) return;
|
||||
if (self.op != null) return;
|
||||
const area = out.layoutArea();
|
||||
if (area.width <= 0 or area.height <= 0) return;
|
||||
if (area.contains(self.pointer_x, self.pointer_y)) return;
|
||||
|
||||
self.seat.pointerWarp(
|
||||
area.x + @divTrunc(area.width, 2),
|
||||
area.y + @divTrunc(area.height, 2),
|
||||
);
|
||||
}
|
||||
|
||||
fn onEvent(_: *river.SeatV1, event: river.SeatV1.Event, self: *Seat) void {
|
||||
switch (event) {
|
||||
.removed => {
|
||||
@@ -289,6 +324,16 @@ fn onEvent(_: *river.SeatV1, event: river.SeatV1.Event, self: *Seat) void {
|
||||
.pointer_position => |ev| {
|
||||
self.pointer_x = ev.x;
|
||||
self.pointer_y = ev.y;
|
||||
|
||||
// Sloppy focus crosses screens too, as dwm's motion handler does:
|
||||
// the pointer leaving a monitor is what moves the seat to the next
|
||||
// one, so the tag and layout keys follow the cursor even over a
|
||||
// screen with no window on it to focus.
|
||||
if (config.focus_follows_mouse and self.op == null) {
|
||||
if (self.wm.outputAt(ev.x, ev.y)) |out| {
|
||||
if (self.wm.focused_output != out) self.wm.enterOutput(self, out);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
.pointer_enter => |ev| {
|
||||
|
||||
Reference in New Issue
Block a user