Add config option for primary_output_follows_pointer + document it

Closes: #6
This commit is contained in:
Basil Keeler 2026-03-28 21:25:42 -05:00 committed by Ben Buhse
commit e785b6e477
4 changed files with 28 additions and 5 deletions

View file

@ -37,6 +37,9 @@ primary_ratio 0.55
// Whether mousing over a new window should move focus
focus_follows_pointer #true
// Whether mousing over a new output should move output focus (i.e. the output new windows spawn on)
output_focus_follows_pointer #true
// Whether the focus should warp to the center of newly-focused windows
pointer_warp_on_focus_change #true

View file

@ -41,6 +41,10 @@ This is useful for sharing a config file across machines. Nodes without a
Whether mousing over a new window should move focus.
(Default: *true*)
*output_focus_follows_pointer* _bool_
Whether mousing over a new output should move output focus (i.e. the output new windows spawn on)
(Default: *true*)
*pointer_warp_on_focus_change* _bool_
Whether the pointer should warp to the center of newly-focused windows.
(Default: *true*)

View file

@ -35,6 +35,8 @@ primary_side: PrimarySide = .left,
attach_mode: AttachMode = .top,
/// Should focus change when the cursor moves onto a new window
focus_follows_pointer: bool = true,
/// Should the output that windows spawn on change to follow the pointer
output_focus_follows_pointer: bool = true,
/// Should the pointer warp to the center of newly-focused windows
pointer_warp_on_focus_change: bool = true,
@ -74,6 +76,7 @@ const NodeName = enum {
single_window_ratio,
primary_side,
focus_follows_pointer,
output_focus_follows_pointer,
pointer_warp_on_focus_change,
wallpaper_image_path,
// Sections with child blocks
@ -287,6 +290,16 @@ fn load(config: *Config, reader: *Io.Reader) !void {
continue;
}
},
.output_focus_follows_pointer => {
const output_focus_follows_pointer_str = utils.stripQuotes(node.arg(&parser, 0) orelse "");
if (helpers.boolFromKdlStr(output_focus_follows_pointer_str)) |output_focus_follows_pointer| {
config.output_focus_follows_pointer = output_focus_follows_pointer;
logDebugSettingNode(name, output_focus_follows_pointer_str);
} else |_| {
logWarnInvalidNodeArg(name, output_focus_follows_pointer_str);
continue;
}
},
.pointer_warp_on_focus_change => {
const pointer_warp_on_focus_change_str = utils.stripQuotes(node.arg(&parser, 0) orelse "");
if (helpers.boolFromKdlStr(pointer_warp_on_focus_change_str)) |pointer_warp_on_focus_change| {

View file

@ -111,11 +111,14 @@ fn seatListener(river_seat_v1: *river.SeatV1, event: river.SeatV1.Event, seat: *
.pointer_position => |ev| {
seat.pointer_pos.x = ev.x;
seat.pointer_pos.y = ev.y;
// Iterate over every display and check if the curser is inside it
var it = seat.context.wm.outputs.iterator(.forward);
while (it.next()) |output| {
if (utils.isPosInRect(seat.pointer_pos, output.geometry)) {
seat.focused_output = output;
if (seat.context.config.output_focus_follows_pointer) {
// Iterate over every display and check if the curser is inside it
var it = seat.context.wm.outputs.iterator(.forward);
while (it.next()) |output| {
if (utils.isPosInRect(seat.pointer_pos, output.geometry)) {
seat.focused_output = output;
break;
}
}
}
},