hyprland: SUPER+Right creates a new workspace past the end of a monitor

m+1/m-1 only cycle existing workspaces on the active monitor and wrap at
the edges, so SUPER+Right never created a workspace. Replace them with a
Lua helper: advancing past the last workspace on the monitor now creates
a fresh (empty) workspace there; going before the first wraps to the
monitor's last workspace.
This commit is contained in:
2026-09-07 18:26:27 -06:00
parent b148fcc256
commit f60b7e263b
2 changed files with 39 additions and 7 deletions
+37 -5
View File
@@ -44,11 +44,43 @@ hl.bind(mainMod .. " + L", hl.dsp.focus({ direction = "r" }), { desc = "Focus ri
hl.bind(mainMod .. " + K", hl.dsp.focus({ direction = "u" }), { desc = "Focus up" })
hl.bind(mainMod .. " + J", hl.dsp.focus({ direction = "d" }), { desc = "Focus down" })
-- Cycle workspaces on the active monitor with mainMod + arrows (m+1/m-1 stay
-- on the current monitor; plain +1/-1 would follow the workspace if it moves
-- to another monitor). These only visit non-empty workspaces.
hl.bind(mainMod .. " + Left", hl.dsp.focus({ workspace = "m-1" }), { desc = "Previous workspace (active monitor)" })
hl.bind(mainMod .. " + Right", hl.dsp.focus({ workspace = "m+1" }), { desc = "Next workspace (active monitor)" })
-- Cycle workspaces on the active monitor with mainMod + arrows. Advancing past
-- the last workspace on the monitor creates a fresh (empty) workspace there;
-- going before the first wraps around to the last one on the monitor.
local function step_workspace(dir)
local mon = hl.get_active_monitor()
if not mon then return end
local current = mon.active_workspace.id
local mon_ids, all_max = {}, 0
for _, ws in ipairs(hl.get_workspaces()) do
if ws.id > all_max then all_max = ws.id end
if ws.monitor and ws.monitor.id == mon.id then
table.insert(mon_ids, ws.id)
end
end
table.sort(mon_ids)
local target
if dir > 0 then
for _, id in ipairs(mon_ids) do
if id > current then target = id break end
end
-- No next workspace on this monitor: create one right here.
if not target then target = all_max + 1 end
else
for i = #mon_ids, 1, -1 do
if mon_ids[i] < current then target = mon_ids[i] break end
end
-- No previous workspace on this monitor: wrap to the last one.
if not target and #mon_ids > 0 then target = mon_ids[#mon_ids] end
end
if target then hl.dispatch(hl.dsp.focus({ workspace = target })) end
end
hl.bind(mainMod .. " + Left", function() step_workspace(-1) end, { desc = "Previous workspace (active monitor)" })
hl.bind(mainMod .. " + Right", function() step_workspace(1) end, { desc = "Next workspace (active monitor); creates one past the end" })
-- Switch workspaces with mainMod + [0-9]
for i = 1, 10 do
+2 -2
View File
@@ -41,8 +41,8 @@ hl.config({
hl.config({
binds = {
-- Let SUPER+Left/Right (and scroll) wrap around instead of stopping at the
-- edge when cycling workspaces on the active monitor.
-- Let SUPER+scroll workspace cycling wrap around instead of stopping at
-- the edges. (SUPER+Left/Right wrapping is handled directly in binds.lua.)
allow_workspace_cycles = true,
},
})