basic tiling

This commit is contained in:
Harrison DiAmbrosio 2026-03-01 20:26:54 -05:00
parent 69945499a4
commit 6d95f33446
3 changed files with 175 additions and 34 deletions

View file

@ -3,3 +3,18 @@
master.mez is meant to be part of the default config of any [Mezzaluna](https://github.com/MezzalunaWM/Mezzaluna) install. It provides basic window management in the master and stack style, simmilar to default dwm. As of right now, since Mezzaluna is in early development, this plugin does a little more than just managing windows. To be fair though, this is more for seeing how a plugin might work and seeing what would be required of plugin developers, and what they have the freedom to customize. master.mez is meant to be part of the default config of any [Mezzaluna](https://github.com/MezzalunaWM/Mezzaluna) install. It provides basic window management in the master and stack style, simmilar to default dwm. As of right now, since Mezzaluna is in early development, this plugin does a little more than just managing windows. To be fair though, this is more for seeing how a plugin might work and seeing what would be required of plugin developers, and what they have the freedom to customize.
There is **NO WAY** to officially install this right now sooooooo, maybe just copy or simlink files where they need to go. Sorry lol. There is **NO WAY** to officially install this right now sooooooo, maybe just copy or simlink files where they need to go. Sorry lol.
## Configuration
How configuration works exactly is still up for debate as of now. Peronally I don't think that things like binds for spawning windows are necessary for a window manager plugin, so those are left for the user to still define. But here is what configuring master.mez would hopefully look like.
Also don't know if constructs like workspaces or tags should really be the responsibility of the window manager plugin either, but those will stay for now.
```lua
local master = requre("master")
master.setup({
master_ratio = 0.5,
tag_count = 5
})
```

View file

@ -3,18 +3,6 @@
local M = {} local M = {}
local spawn_terminal = function()
mez.api.spawn("wmenu-run")
end
local spawn_run_launcher = function()
mez.api.spawn("wmneu-run")
end
local spawn_background = function()
mez.api.spawn("swaybg -i ~/Images/wallpapers/void/gruv_void.png")
end
local close_focused = function () local close_focused = function ()
mez.view.close(0) mez.view.close(0)
end end
@ -23,6 +11,4 @@ local close_compositor = function ()
mez.api.exit() mez.api.exit()
end end
local
return M return M

View file

@ -4,7 +4,7 @@
---@field default_config MasterConfig ---@field default_config MasterConfig
---@field config MasterConfig ---@field config MasterConfig
---@field state MasterState ---@field state MasterState
---@field builtins MasterBuiltins ---@field builtins Builtins
local M = {}; local M = {};
M.builtins = require("master.builtins") M.builtins = require("master.builtins")
@ -12,35 +12,175 @@ M.builtins = require("master.builtins")
---@class MasterConfig ---@class MasterConfig
---@field master_ratio number ---@field master_ratio number
---@field tag_count number ---@field tag_count number
---@field focus_on_spawn boolean
---@field refocus_on_kill boolean
---@field screen_gap number
---@field tile_gap number
local default_config = { local default_config = {
master_ratio = 0.5, master_ratio = 0.5,
tag_count = 5, tag_count = 5,
applications = { focus_on_spawn = true,
terminal = "alacritty", refocus_on_kill = true,
browser = "zen" screen_gap = 10,
}, tile_gap = 10
binds = {
spawn_terminal = { lhs = { mod = "alt", key = "Return" }, rhs = M.builtins.spawn_terminal },
spawn_run_launcher = { lhs = { mod = "alt", key = "p" }, rhs = M.builtins.spawn_run_launcher },
close_focused = { lhs = { mods = "alt|shift", key = "C", rhs = M.builtins.close_focused },
}
} }
---@class Tag ---@class MasterTag
---@field floating number[] ---@field master number | nil
---@field stack number[] ---@field stack number[]
---@field floating number[]
---@param config MasterConfig
---@return MasterState
local create_state = function(config)
---@type MasterTag[]
local tags = {}
for i = 1,config.tag_count do
tags[i] = {
master = nil,
floating = {},
stack = {}
}
end
return {
tag_id = 0,
tags = tags
}
end
---@class MasterState ---@class MasterState
---@field tag_id number ---@field tag_id number
---@field tags Tag[] ---@field tags MasterTag[]
M.state = { ---@field master_ratio number
tag_id = 1,
tags = {}
}
---@param config MasterConfig
M.setup = function(config) M.setup = function(config)
--- Here we need to validate the config
--- DON'T FORGET TO VALIDATE THE CONFIG
M.state = create_state(config)
---@param tag_id number
local tile_tag = function(tag_id)
local tag = M.state.tags[tag_id]
local res = mez.output.get_resolution(0)
if #tag.stack == 0 then
mez.view.set_position(tag.master, config.screen_gap, config.screen_gap)
mez.view.set_size(
tag.master,
res.width - config.screen_gap * 2,
res.height - config.screen_gap * 2)
else
mez.view.set_position(tag.master, config.screen_gap, config.screen_gap)
mez.view.set_size(
tag.master,
res.width * M.state.master_ratio - config.screen_gap - config.tile_gap,
res.height - config.screen_gap * 2)
local stack_x = (res.width * (1 - M.state.master_ratio)) - config.tile_gap - config.screen_gap
local stack_width = res.width * (1 - M.state.master_ratio) - config.tile_gap - config.screen_gap
for i, view_id in ipairs(tag.stack) do
mez.view.set_position(view_id,
stack_x,
(res.height / #tag.stack + config.tile_gap) * (i - 1) + config.screen_gap)
mez.view.set_size(view_id,
stack_width,
res.height / #tag.stack - config.screen_gap * 2 - config.tile_gap * (#tag.stack - 1))
end
end
end
mez.hook.add("ViewMapPre", {
callback = function(view_id)
local curr_tag = M.state.tags[M.state.tag_id]
if curr_tag.master == nil then
curr_tag.master = view_id
else
table.insert(curr_tag.stack, #curr_tag.stack + 1, view_id)
end
if config.focus_on_spawn then mez.view.set_focused(view_id) end
tile_tag(M.state.tag_id)
end
})
mez.hook.add("ViewUnmapPost", {
callback = function(view_id)
---@type number | nil
local tag_idx = nil
---@type "master" | "stacking" | "floating" | nil
local type = nil
---@type number | nil
local view_idx = nil
for i, curr_tag in ipairs[M.state.tags] do
local t = M.state.tags[i]
--- If view is the master
if view_id == curr_tag.master then
tag_idx = i
type = "master"
break
end
--- If view is floating
for j, curr_view in ipairs(t.floating) do
if curr_view == view_id then
tag_idx = i
type = "floating"
view_idx = j
break;
end
end
--- If view is stacking
for j, curr_view in ipairs(t.stack) do
if curr_view == view_id then
tag_idx = i
type = "stacking"
view_idx = j
break;
end
end
end
local tag = M.state.tags[tag_idx]
--- Now remove the view and retile if needed
if type == "floating" then
table.remove(tag.floating, view_idx)
elseif type == "master" then
tag.master = table.remove(tag.stack, 1)
tile_tag(tag_idx)
if config.refocus_on_kill then
mez.view.set_focused(tag.master)
end
elseif type == "stacking" then
local is_last = #tag.stack == view_idx
table.remove(tag.stack, view_idx)
tile_tag(tag_idx)
if config.refocus_on_kill then
if #tag.stack == 0 then
mez.view.set_focus(tag.master)
else
mez.view.set_focused(is_last and view_idx - 1 or view_idx)
end
end
end
end
})
end end
return M return M