diff --git a/docs/TODO.md b/docs/TODO.md index 6ab257d..80b0c81 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -1,7 +1,8 @@ # TODOs -These are in rough order of my priority, though no promises I do them in this order. +These are in no particular order anymore. +- [ ] Save focused window when switching back and forth between outputs via keybind - [ ] Add a config for how to focus when a window opens with a rule on another tag; should we switch tags, add tags, or just ignore it? - [ ] Support per-output single window ratio (in config; this already works at runtime) - [ ] Support per-output wallpapers diff --git a/src/Seat.zig b/src/Seat.zig index ea9455f..2f9ee8c 100644 --- a/src/Seat.zig +++ b/src/Seat.zig @@ -101,6 +101,13 @@ fn seatListener(river_seat_v1: *river.SeatV1, event: river.SeatV1.Event, seat: * .pointer_enter => |ev| if (seat.context.config.focus_follows_pointer) { seat.setWindowFocus(ev.window); }, + .pointer_leave => if (seat.context.config.focus_follows_pointer) { + if (seat.pending_manage.window == null) { + // We only want to clear the pending focus if there's not already one set, + // e.g. from a .pointer_enter event. + seat.pending_manage.window = .clear_focus; + } + }, .window_interaction => |ev| seat.setWindowFocus(ev.window), .op_delta => |ev| { seat.pending_manage.op_delta = .{ .dx = ev.dx, .dy = ev.dy }; @@ -111,21 +118,27 @@ 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; - if (seat.context.config.output_focus_follows_pointer) { - // Iterate over every display and check if the curser is inside it + + // We use this to track if the cursor is moving to a new output + if (seat.context.config.output_focus_follows_pointer) blk: { + const focused_output = seat.focused_output orelse break :blk; + if (utils.isPosInRect(seat.pointer_pos, focused_output.geometry)) { + // Same output, skip + break :blk; + } + + // New output, find which one the pointer is in var it = seat.context.wm.outputs.iterator(.forward); while (it.next()) |output| { - if (utils.isPosInRect(seat.pointer_pos, output.geometry)) { + if (output != focused_output and + utils.isPosInRect(seat.pointer_pos, output.geometry)) + { seat.focused_output = output; - break; } } } }, - - else => |ev| { - log.debug("unhandled event: {s}", .{@tagName(ev)}); - }, + else => {}, } } @@ -156,12 +169,6 @@ pub fn manage(seat: *Seat) void { if (focused != window) { // Tell the previously focused Window that it's no longer focused focused.pending_render.focused = false; - // Update the Bar to have the newly-focused window's title - if (focused.output) |output| { - if (output.bar) |*bar| { - bar.pending_render.draw = true; - } - } } } seat.focused_window = window; @@ -177,6 +184,13 @@ pub fn manage(seat: *Seat) void { seat.river_seat_v1.clearFocus(); }, } + // Bars should redraw because the title (may) have changed + var it = seat.context.wm.outputs.iterator(.forward); + while (it.next()) |output| { + if (output.bar) |*bar| { + bar.pending_render.draw = true; + } + } } } if (seat.pending_manage.output) |pending_output| {