From 4f89af16dbb17dabe996bbae767388b842a99969 Mon Sep 17 00:00:00 2001 From: rope Date: Mon, 17 Aug 2026 11:55:30 +0100 Subject: [PATCH] hyprland: focus scratchpads on toggle without warping the cursor Replaces the warp_on_toggle_special + click-away approach, which dragged the pointer around on open and close. Co-Authored-By: Claude Opus 5 --- settings/hyprland.nix | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/settings/hyprland.nix b/settings/hyprland.nix index 0857ddb..54d9f65 100644 --- a/settings/hyprland.nix +++ b/settings/hyprland.nix @@ -187,11 +187,6 @@ in follow_mouse = 1; accel_profile = "flat"; sensitivity = 0; - # An open special workspace otherwise swallows focus for the - # regular workspace underneath. Both scratchpads hold exactly one - # floating window, which is the case this unblocks — and the - # click-away handler below needs that focus change to fire. - special_fallthrough = true; } // lib.optionalAttrs isMacbook { touchpad = { tap_to_click = true; @@ -207,11 +202,6 @@ in cursor = { no_warps = true; - # Scratchpads are floated at 80% inset, so opening one leaves the - # cursor over the window underneath and follow_mouse=1 hands focus - # straight back to it. Warp onto the special workspace's window - # instead. 2, not 1: 1 obeys no_warps above and would no-op. - warp_on_toggle_special = 2; # Force real HW cursor plane (default "auto" can fall back to a # software cursor on i915 → cursor waits a full repaint = laggy). no_hardware_cursors = false; @@ -311,18 +301,20 @@ in if cmd and not shutting_down then hl.exec_cmd(cmd) end end) - -- Click-away dismiss: focus landing on anything outside the open - -- special workspace slides it back out, so a scratchpad never has - -- to be toggled off by hand. Generic on purpose — any special - -- workspace, not just these two. - hl.on("window.active", function(win) - local special = hl.get_active_special_workspace() - if not special then return end - if win and win.workspace and win.workspace.special then return end - -- Workspace name is "special:scratch"; toggle_special wants the - -- bare "scratch" (and "" for the unnamed "special" workspace). - hl.dispatch(hl.dsp.workspace.toggle_special(special.name:match("^special:(.*)$") or "")) - end) + -- Toggling a special workspace leaves keyboard focus wherever the + -- cursor already was, so a scratchpad opened over another window + -- came up unfocused. Focus its window explicitly on the way in. + -- Deliberately not cursor:warp_on_toggle_special — that yanks the + -- pointer to the window on open and back again on close. + local function toggle_scratchpad(name, class) + return function() + hl.dispatch(hl.dsp.workspace.toggle_special(name)) + -- Only on the opening half of the toggle. + if hl.get_active_special_workspace() then + hl.dispatch(hl.dsp.focus({ window = "class<" .. class .. ">" })) + end + end + end -- Startup hl.on("hyprland.start", function() @@ -479,8 +471,8 @@ in hl.bind(mod .. " + F", hl.dsp.window.fullscreen()) hl.bind(mod .. " + P", hl.dsp.window.pseudo()) hl.bind(mod .. " + S", hl.dsp.layout("togglesplit")) - hl.bind(mod .. " + M", hl.dsp.workspace.toggle_special("music")) - hl.bind(mod .. " + Return", hl.dsp.workspace.toggle_special("scratch")) + hl.bind(mod .. " + M", toggle_scratchpad("music", "dev.fred.spotify")) + hl.bind(mod .. " + Return", toggle_scratchpad("scratch", "dev.fred.scratchpad")) -- Focus hl.bind(mod .. " + left", hl.dsp.focus({ direction = "left" }))