feat(hyprdrive,hyprlua): trap pointer to focused window in monocle (super+ctrl+f)
Monocle now also confines the cursor to the focused full-size window so it can't slip onto another monitor. Hyprland has no cursor-confine dispatcher, so this drives the confine_pointer window rule: one lazily-created rule per workspace, matched by workspace id (follows focus), enabled/disabled in lock-step with the monocle toggle and refreshed immediately. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>main
parent
967af1c0f2
commit
3f05f64281
|
|
@ -107,11 +107,36 @@ hl.bind(mainMod .. " + CTRL + M", hl.dsp.exec_cmd("~/.config/scripts/togg
|
||||||
-- Switch the focused window's workspace to the "monocle" layout (one full-size window
|
-- Switch the focused window's workspace to the "monocle" layout (one full-size window
|
||||||
-- at a time), toggling back to the session default (columns) on a second press.
|
-- at a time), toggling back to the session default (columns) on a second press.
|
||||||
-- Uses the same layouts registry the astro-menu popup drives via `hyprctl eval`.
|
-- Uses the same layouts registry the astro-menu popup drives via `hyprctl eval`.
|
||||||
|
--
|
||||||
|
-- Monocle also traps the pointer to the focused window. Hyprland has no cursor-confine
|
||||||
|
-- dispatcher, but the `confine_pointer` window rule pins the pointer to whichever window
|
||||||
|
-- is focused on a matched workspace, so the trap follows focus as you cycle the single
|
||||||
|
-- full-size window and the cursor can't slip onto another monitor. We keep one rule per
|
||||||
|
-- workspace, created lazily and enabled/disabled in lock-step with the monocle toggle.
|
||||||
|
local confine_rules = {} -- wid(str) -> HL.WindowRule
|
||||||
|
local function set_pointer_trap(wid, on)
|
||||||
|
local rule = confine_rules[wid]
|
||||||
|
if not rule then
|
||||||
|
local okr, r = pcall(hl.window_rule, {
|
||||||
|
name = "monocle-confine-" .. wid,
|
||||||
|
match = { workspace = wid },
|
||||||
|
confine_pointer = true,
|
||||||
|
enabled = false,
|
||||||
|
})
|
||||||
|
if not okr then return end
|
||||||
|
rule, confine_rules[wid] = r, r
|
||||||
|
end
|
||||||
|
rule:set_enabled(on)
|
||||||
|
-- apply to the already-focused window now, instead of on the next window event
|
||||||
|
if hl.exec_scheduled_prop_refresh_immediately then hl.exec_scheduled_prop_refresh_immediately() end
|
||||||
|
end
|
||||||
local function toggle_monocle()
|
local function toggle_monocle()
|
||||||
local ok, aw = pcall(hl.get_active_window)
|
local ok, aw = pcall(hl.get_active_window)
|
||||||
if not ok or not aw or not aw.workspace then return end
|
if not ok or not aw or not aw.workspace then return end
|
||||||
local wid = tostring(aw.workspace.id)
|
local wid = tostring(aw.workspace.id)
|
||||||
layouts.set(wid, layouts.current[wid] == "monocle" and "columns" or "monocle")
|
local to_monocle = layouts.current[wid] ~= "monocle"
|
||||||
|
layouts.set(wid, to_monocle and "monocle" or "columns")
|
||||||
|
set_pointer_trap(wid, to_monocle)
|
||||||
end
|
end
|
||||||
hl.bind(mainMod .. " + CTRL + F", toggle_monocle)
|
hl.bind(mainMod .. " + CTRL + F", toggle_monocle)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,11 +111,36 @@ hl.bind(mainMod .. " + CTRL + M", hl.dsp.exec_cmd("~/.config/scripts/togg
|
||||||
-- Switch the focused window's workspace to the "monocle" layout (one full-size window
|
-- Switch the focused window's workspace to the "monocle" layout (one full-size window
|
||||||
-- at a time), toggling back to the session default (columns) on a second press.
|
-- at a time), toggling back to the session default (columns) on a second press.
|
||||||
-- Uses the same layouts registry the astal-menu popup drives via `hyprctl eval`.
|
-- Uses the same layouts registry the astal-menu popup drives via `hyprctl eval`.
|
||||||
|
--
|
||||||
|
-- Monocle also traps the pointer to the focused window. Hyprland has no cursor-confine
|
||||||
|
-- dispatcher, but the `confine_pointer` window rule pins the pointer to whichever window
|
||||||
|
-- is focused on a matched workspace, so the trap follows focus as you cycle the single
|
||||||
|
-- full-size window and the cursor can't slip onto another monitor. We keep one rule per
|
||||||
|
-- workspace, created lazily and enabled/disabled in lock-step with the monocle toggle.
|
||||||
|
local confine_rules = {} -- wid(str) -> HL.WindowRule
|
||||||
|
local function set_pointer_trap(wid, on)
|
||||||
|
local rule = confine_rules[wid]
|
||||||
|
if not rule then
|
||||||
|
local okr, r = pcall(hl.window_rule, {
|
||||||
|
name = "monocle-confine-" .. wid,
|
||||||
|
match = { workspace = wid },
|
||||||
|
confine_pointer = true,
|
||||||
|
enabled = false,
|
||||||
|
})
|
||||||
|
if not okr then return end
|
||||||
|
rule, confine_rules[wid] = r, r
|
||||||
|
end
|
||||||
|
rule:set_enabled(on)
|
||||||
|
-- apply to the already-focused window now, instead of on the next window event
|
||||||
|
if hl.exec_scheduled_prop_refresh_immediately then hl.exec_scheduled_prop_refresh_immediately() end
|
||||||
|
end
|
||||||
local function toggle_monocle()
|
local function toggle_monocle()
|
||||||
local ok, aw = pcall(hl.get_active_window)
|
local ok, aw = pcall(hl.get_active_window)
|
||||||
if not ok or not aw or not aw.workspace then return end
|
if not ok or not aw or not aw.workspace then return end
|
||||||
local wid = tostring(aw.workspace.id)
|
local wid = tostring(aw.workspace.id)
|
||||||
layouts.set(wid, layouts.current[wid] == "monocle" and "columns" or "monocle")
|
local to_monocle = layouts.current[wid] ~= "monocle"
|
||||||
|
layouts.set(wid, to_monocle and "monocle" or "columns")
|
||||||
|
set_pointer_trap(wid, to_monocle)
|
||||||
end
|
end
|
||||||
hl.bind(mainMod .. " + CTRL + F", toggle_monocle)
|
hl.bind(mainMod .. " + CTRL + F", toggle_monocle)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue