11e4e94ee8
Lua config (hyprland.d.lua):
- keybinds: layout-aware binds now read the per-workspace layout via
cur_ws_layout() instead of the global hl.get_config("general.layout"),
fixing mouse-wheel/bracket scrolling and ratio keys on the lua:*-scroll
layouts.
- add state.lua shared module (ws_layouts) replacing the _G globals.
- layout: factor the 9 duplicated layout_msg bodies into scroll_msg/swap_msg
builders; drop a dead #state expression.
- rules: NO_BLUELIGHT window.open handler no longer leaks a rule per open
(one per class) and regex-escapes/nil-guards the class.
- monitors: quote non-numeric scale so scale="auto" renders.
- drop debug print() focus handler, local-next shadowing, stray {mouse=true}
on wheel binds (kept on drag/resize, which require it).
Quickshell:
- brightness OSD is now event-driven: Osd.qml gains an IpcHandler(target:osd)
and the keybind pushes the new level via `qs ipc call osd brightness`,
removing the always-on 500ms brightnessctl poll.
- GamemodePill watches GameMode's D-Bus signals via gdbus monitor instead of
polling gamemoded --status every 5s.
Cleanup:
- remove stock hyprland.lua.refactor/ boilerplate and the redundant,
partly-wrong hyprland_lua_api.md (both were deployed into ~/.config/hypr;
.luarc.json already points the LSP at /usr/share/hypr/stubs).
- refresh hypr/AGENTS.md (lua layout) and quickshell/CLAUDE.md (v0.3.0).
503 lines
19 KiB
Lua
503 lines
19 KiB
Lua
hl.config({
|
|
master = {
|
|
orientation = "left",
|
|
mfact = 0.60,
|
|
new_status = "slave",
|
|
new_on_top = true,
|
|
new_on_active = "after",
|
|
allow_small_split = true,
|
|
special_scale_factor = 0.8,
|
|
drop_at_cursor = true
|
|
},
|
|
scrolling = {
|
|
fullscreen_on_one_column = true,
|
|
focus_fit_method = 0,
|
|
follow_focus = true,
|
|
follow_min_visible = 0.1,
|
|
column_width = 0.7
|
|
}
|
|
})
|
|
|
|
-- ─── Scrolling slave column helper ───────────────────────────────────────────
|
|
-- Shared by all master-scroll variants.
|
|
-- state = { visible, peek, offset, peek_top_addr, peek_bottom_addr }
|
|
-- slave_area = HL.Box for this column
|
|
-- targets = ctx.targets
|
|
-- slave_indices = ordered list of indices into `targets` for this column
|
|
local function place_scroll_col(state, slave_area, targets, slave_indices)
|
|
local n = #slave_indices
|
|
state.peek_top_addr = nil
|
|
state.peek_bottom_addr = nil
|
|
if n == 0 then return end
|
|
|
|
local max_off = math.max(0, n - state.visible)
|
|
state.offset = math.max(0, math.min(state.offset, max_off))
|
|
|
|
if n <= state.visible then
|
|
local h = slave_area.h / n
|
|
for j = 1, n do
|
|
targets[slave_indices[j]]:place({
|
|
x = slave_area.x, y = slave_area.y + (j - 1) * h,
|
|
w = slave_area.w, h = h,
|
|
})
|
|
end
|
|
return
|
|
end
|
|
|
|
local has_top = state.offset > 0
|
|
local has_bot = state.offset < max_off
|
|
local top_f = has_top and state.peek or 0
|
|
local bot_f = has_bot and state.peek or 0
|
|
-- h chosen so top_peek + visible*h + bot_peek == slave_area.h exactly
|
|
local h = slave_area.h / (state.visible + top_f + bot_f)
|
|
|
|
if has_top then
|
|
local w = targets[slave_indices[state.offset]].window
|
|
if w then state.peek_top_addr = w.address end
|
|
end
|
|
if has_bot then
|
|
local ti = slave_indices[state.offset + state.visible + 1]
|
|
if ti then
|
|
local w = targets[ti].window
|
|
if w then state.peek_bottom_addr = w.address end
|
|
end
|
|
end
|
|
|
|
for j = 1, n do
|
|
local t = targets[slave_indices[j]]
|
|
if has_top and j == state.offset then
|
|
-- Peek at top: extends above slave_area; safe because master is in a different x-range
|
|
t:place({ x=slave_area.x, y=slave_area.y - h*(1-state.peek), w=slave_area.w, h=h })
|
|
elseif has_bot and j == state.offset + state.visible + 1 then
|
|
-- Peek at bottom: extends below the last visible slot
|
|
t:place({ x=slave_area.x, y=slave_area.y + (top_f + state.visible)*h, w=slave_area.w, h=h })
|
|
elseif j >= state.offset + 1 and j <= state.offset + state.visible then
|
|
local k = j - state.offset - 1
|
|
t:place({ x=slave_area.x, y=slave_area.y + (top_f + k)*h, w=slave_area.w, h=h })
|
|
else
|
|
-- Fully off-screen: park below work area
|
|
t:set_box({ x=slave_area.x, y=slave_area.y + slave_area.h + h, w=slave_area.w, h=h })
|
|
end
|
|
end
|
|
end
|
|
|
|
-- ─── Layout states ────────────────────────────────────────────────────────────
|
|
local shared = require("state") -- shared ws_layouts table (written by keybinds.lua)
|
|
|
|
local mfact = 0.60 -- master width fraction (horizontal single-master variants)
|
|
local mfact_v = 0.55 -- master height fraction (vertical variants)
|
|
|
|
-- mfact setters: clamp and write back to the shared upvalue.
|
|
local function set_mfact(v) if v then mfact = math.max(0.1, math.min(0.95, v)) end end
|
|
local function set_mfact_v(v) if v then mfact_v = math.max(0.1, math.min(0.95, v)) end end
|
|
|
|
-- layout_msg builder for single-column/row scroll layouts (master + N slaves).
|
|
local function scroll_msg(s, set_mf)
|
|
return function(ctx, msg)
|
|
local max_off = math.max(0, #ctx.targets - 1 - s.visible)
|
|
if msg == "scrolldown" then s.offset = math.min(s.offset + 1, max_off); return true
|
|
elseif msg == "scrollup" then s.offset = math.max(s.offset - 1, 0); return true
|
|
elseif msg == "reset" then s.offset = 0; return true
|
|
else
|
|
local v = msg:match("^mfact exact (.+)$")
|
|
if v then set_mf(tonumber(v)); return true end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- layout_msg builder for swap-on-focus layouts (recalc + mfact only).
|
|
local function swap_msg(set_mf)
|
|
return function(_, msg)
|
|
if msg == "recalc" then return true end
|
|
local v = msg:match("^mfact exact (.+)$")
|
|
if v then set_mf(tonumber(v)); return true end
|
|
end
|
|
end
|
|
|
|
local ms = { visible=2, peek=0.10, offset=0, peek_top_addr=nil, peek_bottom_addr=nil }
|
|
local sm = { visible=2, peek=0.10, offset=0, peek_top_addr=nil, peek_bottom_addr=nil }
|
|
|
|
local cm = { side_w=0.20, visible=2, peek=0.10 }
|
|
local cm_left = { visible=cm.visible, peek=cm.peek, offset=0, peek_top_addr=nil, peek_bottom_addr=nil }
|
|
local cm_right = { visible=cm.visible, peek=cm.peek, offset=0, peek_top_addr=nil, peek_bottom_addr=nil }
|
|
local cm_left_addrs = {}
|
|
local cm_right_addrs = {}
|
|
|
|
-- ─── master-scroll: master left, slaves right ─────────────────────────────────
|
|
hl.layout.register("master-scroll", {
|
|
recalculate = function(ctx)
|
|
local targets = ctx.targets
|
|
local n = #targets
|
|
if n == 0 then return end
|
|
if n == 1 then targets[1]:place(ctx.area); return end
|
|
|
|
local slave_area = ctx:split(ctx.area, "right", 1.0 - mfact)
|
|
local master_area = { x=ctx.area.x, y=ctx.area.y, w=slave_area.x-ctx.area.x, h=ctx.area.h }
|
|
targets[1]:place(master_area)
|
|
|
|
local idx = {}
|
|
for i = 2, n do idx[#idx+1] = i end
|
|
place_scroll_col(ms, slave_area, targets, idx)
|
|
end,
|
|
|
|
layout_msg = scroll_msg(ms, set_mfact),
|
|
})
|
|
|
|
-- ─── slave-master-scroll: slaves left, master right ──────────────────────────
|
|
hl.layout.register("slave-master-scroll", {
|
|
recalculate = function(ctx)
|
|
local targets = ctx.targets
|
|
local n = #targets
|
|
if n == 0 then return end
|
|
if n == 1 then targets[1]:place(ctx.area); return end
|
|
|
|
local slave_area = ctx:split(ctx.area, "left", 1.0 - mfact)
|
|
local master_area = {
|
|
x = slave_area.x + slave_area.w, y = ctx.area.y,
|
|
w = ctx.area.w - slave_area.w, h = ctx.area.h,
|
|
}
|
|
targets[1]:place(master_area)
|
|
|
|
local idx = {}
|
|
for i = 2, n do idx[#idx+1] = i end
|
|
place_scroll_col(sm, slave_area, targets, idx)
|
|
end,
|
|
|
|
layout_msg = scroll_msg(sm, set_mfact),
|
|
})
|
|
|
|
-- ─── center-master-scroll: center master, both columns scroll ─────────────────
|
|
-- Slaves alternate: odd (1,3,5…) → left column, even (2,4,6…) → right column.
|
|
-- scrolldown/scrollup applies to whichever column the active window is in.
|
|
hl.layout.register("center-master-scroll", {
|
|
recalculate = function(ctx)
|
|
local targets = ctx.targets
|
|
local n = #targets
|
|
cm_left_addrs = {}
|
|
cm_right_addrs = {}
|
|
if n == 0 then return end
|
|
if n == 1 then targets[1]:place(ctx.area); return end
|
|
|
|
local left_area = ctx:split(ctx.area, "left", cm.side_w)
|
|
local right_area = ctx:split(ctx.area, "right", cm.side_w)
|
|
local master_area = {
|
|
x = left_area.x + left_area.w, y = ctx.area.y,
|
|
w = right_area.x - (left_area.x + left_area.w), h = ctx.area.h,
|
|
}
|
|
targets[1]:place(master_area)
|
|
|
|
local left_idx, right_idx = {}, {}
|
|
for i = 2, n do
|
|
local slave_pos = i - 1 -- 1-indexed slave number
|
|
if slave_pos % 2 == 1 then
|
|
left_idx[#left_idx+1] = i
|
|
else
|
|
right_idx[#right_idx+1] = i
|
|
end
|
|
local w = targets[i].window
|
|
if w then
|
|
if slave_pos % 2 == 1 then cm_left_addrs[w.address] = true
|
|
else cm_right_addrs[w.address] = true
|
|
end
|
|
end
|
|
end
|
|
|
|
place_scroll_col(cm_left, left_area, targets, left_idx)
|
|
place_scroll_col(cm_right, right_area, targets, right_idx)
|
|
end,
|
|
|
|
layout_msg = function(ctx, msg)
|
|
local aw = hl.get_active_window()
|
|
local addr = aw and aw.address
|
|
|
|
local function scroll_col(state, delta)
|
|
-- Count windows in this column from targets
|
|
local col_n = 0
|
|
for i = 2, #ctx.targets do
|
|
local w = ctx.targets[i].window
|
|
if w and ((state == cm_left and cm_left_addrs[w.address])
|
|
or (state == cm_right and cm_right_addrs[w.address])) then
|
|
col_n = col_n + 1
|
|
end
|
|
end
|
|
local col_max = math.max(0, col_n - state.visible)
|
|
if delta > 0 then state.offset = math.min(state.offset + 1, col_max)
|
|
else state.offset = math.max(state.offset - 1, 0)
|
|
end
|
|
return true
|
|
end
|
|
|
|
if msg == "scrolldown" then
|
|
if addr and cm_left_addrs[addr] then return scroll_col(cm_left, 1) end
|
|
if addr and cm_right_addrs[addr] then return scroll_col(cm_right, 1) end
|
|
elseif msg == "scrollup" then
|
|
if addr and cm_left_addrs[addr] then return scroll_col(cm_left, -1) end
|
|
if addr and cm_right_addrs[addr] then return scroll_col(cm_right, -1) end
|
|
elseif msg == "reset" then
|
|
cm_left.offset = 0; cm_right.offset = 0; return true
|
|
else
|
|
local v = msg:match("^mfact exact (.+)$")
|
|
if v then set_mfact(tonumber(v)); return true end
|
|
end
|
|
end,
|
|
})
|
|
|
|
-- ─── Scrolling slave row helper (horizontal) ─────────────────────────────────
|
|
-- Mirror of place_scroll_col but scrolls left↔right instead of up↔down.
|
|
-- state fields: visible, peek, offset, peek_top_addr (left peek), peek_bottom_addr (right peek)
|
|
local function place_scroll_row(state, slave_area, targets, slave_indices)
|
|
local n = #slave_indices
|
|
state.peek_top_addr = nil
|
|
state.peek_bottom_addr = nil
|
|
if n == 0 then return end
|
|
|
|
local max_off = math.max(0, n - state.visible)
|
|
state.offset = math.max(0, math.min(state.offset, max_off))
|
|
|
|
if n <= state.visible then
|
|
local w = slave_area.w / n
|
|
for j = 1, n do
|
|
targets[slave_indices[j]]:place({
|
|
x = slave_area.x + (j - 1) * w, y = slave_area.y,
|
|
w = w, h = slave_area.h,
|
|
})
|
|
end
|
|
return
|
|
end
|
|
|
|
local has_left = state.offset > 0
|
|
local has_right = state.offset < max_off
|
|
local left_f = has_left and state.peek or 0
|
|
local right_f = has_right and state.peek or 0
|
|
-- w chosen so left_peek + visible*w + right_peek == slave_area.w exactly
|
|
local w = slave_area.w / (state.visible + left_f + right_f)
|
|
|
|
if has_left then
|
|
local wi = targets[slave_indices[state.offset]].window
|
|
if wi then state.peek_top_addr = wi.address end
|
|
end
|
|
if has_right then
|
|
local ti = slave_indices[state.offset + state.visible + 1]
|
|
if ti then
|
|
local wi = targets[ti].window
|
|
if wi then state.peek_bottom_addr = wi.address end
|
|
end
|
|
end
|
|
|
|
for j = 1, n do
|
|
local t = targets[slave_indices[j]]
|
|
if has_left and j == state.offset then
|
|
t:place({ x=slave_area.x - w*(1-state.peek), y=slave_area.y, w=w, h=slave_area.h })
|
|
elseif has_right and j == state.offset + state.visible + 1 then
|
|
t:place({ x=slave_area.x + (left_f + state.visible)*w, y=slave_area.y, w=w, h=slave_area.h })
|
|
elseif j >= state.offset + 1 and j <= state.offset + state.visible then
|
|
local k = j - state.offset - 1
|
|
t:place({ x=slave_area.x + (left_f + k)*w, y=slave_area.y, w=w, h=slave_area.h })
|
|
else
|
|
t:set_box({ x=slave_area.x + slave_area.w + w, y=slave_area.y, w=w, h=slave_area.h })
|
|
end
|
|
end
|
|
end
|
|
|
|
-- ─── Vertical layout states ───────────────────────────────────────────────────
|
|
local tm = { visible=2, peek=0.10, offset=0, peek_top_addr=nil, peek_bottom_addr=nil }
|
|
|
|
local cm_v = { side_h=0.20, visible=2, peek=0.10 }
|
|
local cm_vtop = { visible=cm_v.visible, peek=cm_v.peek, offset=0, peek_top_addr=nil, peek_bottom_addr=nil }
|
|
local cm_vbot = { visible=cm_v.visible, peek=cm_v.peek, offset=0, peek_top_addr=nil, peek_bottom_addr=nil }
|
|
local cm_vtop_addrs = {}
|
|
local cm_vbot_addrs = {}
|
|
|
|
-- ─── top-master-scroll: master top, slaves bottom row ────────────────────────
|
|
hl.layout.register("top-master-scroll", {
|
|
recalculate = function(ctx)
|
|
local targets = ctx.targets
|
|
local n = #targets
|
|
if n == 0 then return end
|
|
if n == 1 then targets[1]:place(ctx.area); return end
|
|
|
|
local slave_area = ctx:split(ctx.area, "bottom", 1.0 - mfact_v)
|
|
local master_area = { x=ctx.area.x, y=ctx.area.y, w=ctx.area.w, h=slave_area.y-ctx.area.y }
|
|
targets[1]:place(master_area)
|
|
|
|
local idx = {}
|
|
for i = 2, n do idx[#idx+1] = i end
|
|
place_scroll_row(tm, slave_area, targets, idx)
|
|
end,
|
|
|
|
layout_msg = scroll_msg(tm, set_mfact_v),
|
|
})
|
|
|
|
-- ─── center-master-scroll-v: center master, top and bottom slave rows ────────
|
|
-- Slaves alternate: odd (1,3,5…) → top row, even (2,4,6…) → bottom row.
|
|
-- scrolldown/scrollup scrolls whichever row the active window is in.
|
|
hl.layout.register("center-master-scroll-v", {
|
|
recalculate = function(ctx)
|
|
local targets = ctx.targets
|
|
local n = #targets
|
|
cm_vtop_addrs = {}
|
|
cm_vbot_addrs = {}
|
|
if n == 0 then return end
|
|
if n == 1 then targets[1]:place(ctx.area); return end
|
|
|
|
local top_area = ctx:split(ctx.area, "top", cm_v.side_h)
|
|
local bot_area = ctx:split(ctx.area, "bottom", cm_v.side_h)
|
|
local master_area = {
|
|
x = ctx.area.x, y = top_area.y + top_area.h,
|
|
w = ctx.area.w, h = bot_area.y - (top_area.y + top_area.h),
|
|
}
|
|
targets[1]:place(master_area)
|
|
|
|
local top_idx, bot_idx = {}, {}
|
|
for i = 2, n do
|
|
local slave_pos = i - 1
|
|
if slave_pos % 2 == 1 then
|
|
top_idx[#top_idx+1] = i
|
|
else
|
|
bot_idx[#bot_idx+1] = i
|
|
end
|
|
local w = targets[i].window
|
|
if w then
|
|
if slave_pos % 2 == 1 then cm_vtop_addrs[w.address] = true
|
|
else cm_vbot_addrs[w.address] = true
|
|
end
|
|
end
|
|
end
|
|
|
|
place_scroll_row(cm_vtop, top_area, targets, top_idx)
|
|
place_scroll_row(cm_vbot, bot_area, targets, bot_idx)
|
|
end,
|
|
|
|
layout_msg = function(ctx, msg)
|
|
local aw = hl.get_active_window()
|
|
local addr = aw and aw.address
|
|
|
|
local function scroll_row(state, col_addrs, delta)
|
|
local col_n = 0
|
|
for i = 2, #ctx.targets do
|
|
local w = ctx.targets[i].window
|
|
if w and col_addrs[w.address] then col_n = col_n + 1 end
|
|
end
|
|
local col_max = math.max(0, col_n - state.visible)
|
|
if delta > 0 then state.offset = math.min(state.offset + 1, col_max)
|
|
else state.offset = math.max(state.offset - 1, 0)
|
|
end
|
|
return true
|
|
end
|
|
|
|
if msg == "scrolldown" then
|
|
if addr and cm_vtop_addrs[addr] then return scroll_row(cm_vtop, cm_vtop_addrs, 1) end
|
|
if addr and cm_vbot_addrs[addr] then return scroll_row(cm_vbot, cm_vbot_addrs, 1) end
|
|
elseif msg == "scrollup" then
|
|
if addr and cm_vtop_addrs[addr] then return scroll_row(cm_vtop, cm_vtop_addrs, -1) end
|
|
if addr and cm_vbot_addrs[addr] then return scroll_row(cm_vbot, cm_vbot_addrs, -1) end
|
|
elseif msg == "reset" then
|
|
cm_vtop.offset = 0; cm_vbot.offset = 0; return true
|
|
else
|
|
local v = msg:match("^mfact exact (.+)$")
|
|
if v then set_mfact_v(tonumber(v)); return true end
|
|
end
|
|
end,
|
|
})
|
|
|
|
-- ─── Swap-on-focus layouts ────────────────────────────────────────────────────
|
|
-- Focusing any window promotes it to master. recalculate reads the active
|
|
-- window directly via hl.get_active_window() — no external address tracking.
|
|
|
|
local function swap_master_idx(targets)
|
|
local aw = hl.get_active_window()
|
|
if aw and aw.address then
|
|
for i = 1, #targets do
|
|
local w = targets[i].window
|
|
if w and w.address == aw.address then return i end
|
|
end
|
|
end
|
|
return 1
|
|
end
|
|
|
|
local function swap_place_slaves(targets, midx, slave_area, vertical)
|
|
local sidx = {}
|
|
for i = 1, #targets do if i ~= midx then sidx[#sidx+1] = i end end
|
|
if #sidx == 0 then return end
|
|
if vertical then
|
|
local h = slave_area.h / #sidx
|
|
for j, si in ipairs(sidx) do
|
|
targets[si]:place({ x=slave_area.x, y=slave_area.y+(j-1)*h, w=slave_area.w, h=h })
|
|
end
|
|
else
|
|
local w = slave_area.w / #sidx
|
|
for j, si in ipairs(sidx) do
|
|
targets[si]:place({ x=slave_area.x+(j-1)*w, y=slave_area.y, w=w, h=slave_area.h })
|
|
end
|
|
end
|
|
end
|
|
|
|
-- ─── master-swap: master left, slaves right ───────────────────────────────────
|
|
hl.layout.register("master-swap", {
|
|
recalculate = function(ctx)
|
|
local targets, n = ctx.targets, #ctx.targets
|
|
if n == 0 then return end
|
|
if n == 1 then targets[1]:place(ctx.area); return end
|
|
local midx = swap_master_idx(targets)
|
|
local slave_area = ctx:split(ctx.area, "right", 1.0 - mfact)
|
|
local master_area = { x=ctx.area.x, y=ctx.area.y, w=slave_area.x-ctx.area.x, h=ctx.area.h }
|
|
targets[midx]:place(master_area)
|
|
swap_place_slaves(targets, midx, slave_area, true)
|
|
end,
|
|
layout_msg = swap_msg(set_mfact),
|
|
})
|
|
|
|
-- ─── slave-master-swap: slaves left, master right ─────────────────────────────
|
|
hl.layout.register("slave-master-swap", {
|
|
recalculate = function(ctx)
|
|
local targets, n = ctx.targets, #ctx.targets
|
|
if n == 0 then return end
|
|
if n == 1 then targets[1]:place(ctx.area); return end
|
|
local midx = swap_master_idx(targets)
|
|
local slave_area = ctx:split(ctx.area, "left", 1.0 - mfact)
|
|
local master_area = { x=slave_area.x+slave_area.w, y=ctx.area.y, w=ctx.area.w-slave_area.w, h=ctx.area.h }
|
|
targets[midx]:place(master_area)
|
|
swap_place_slaves(targets, midx, slave_area, true)
|
|
end,
|
|
layout_msg = swap_msg(set_mfact),
|
|
})
|
|
|
|
-- ─── top-master-swap: master top, slaves bottom row ───────────────────────────
|
|
hl.layout.register("top-master-swap", {
|
|
recalculate = function(ctx)
|
|
local targets, n = ctx.targets, #ctx.targets
|
|
if n == 0 then return end
|
|
if n == 1 then targets[1]:place(ctx.area); return end
|
|
local midx = swap_master_idx(targets)
|
|
local slave_area = ctx:split(ctx.area, "bottom", 1.0 - mfact_v)
|
|
local master_area = { x=ctx.area.x, y=ctx.area.y, w=ctx.area.w, h=slave_area.y-ctx.area.y }
|
|
targets[midx]:place(master_area)
|
|
swap_place_slaves(targets, midx, slave_area, false)
|
|
end,
|
|
layout_msg = swap_msg(set_mfact_v),
|
|
})
|
|
|
|
-- ─── Auto-scroll on focus + swap-on-focus ────────────────────────────────────
|
|
local all_col_states = { ms, sm, cm_left, cm_right, tm, cm_vtop, cm_vbot }
|
|
|
|
hl.on("window.active", function(w)
|
|
if w == nil or w.address == nil then return end
|
|
|
|
-- Auto-scroll: if the focused window is a peek slot, slide it into view
|
|
for _, state in ipairs(all_col_states) do
|
|
if w.address == state.peek_bottom_addr then
|
|
hl.dispatch(hl.dsp.layout("scrolldown")); return
|
|
elseif w.address == state.peek_top_addr then
|
|
hl.dispatch(hl.dsp.layout("scrollup")); return
|
|
end
|
|
end
|
|
|
|
-- Trigger recalc for swap layouts so the focused window becomes master.
|
|
-- shared.ws_layouts is written by keybinds.lua and tracks per-workspace layout.
|
|
local ws_id = w.workspace and w.workspace.id
|
|
local cur = ws_id and shared.ws_layouts[ws_id]
|
|
if cur == "lua:master-swap" or cur == "lua:slave-master-swap" or cur == "lua:top-master-swap" then
|
|
hl.dispatch(hl.dsp.layout("recalc"))
|
|
end
|
|
end)
|