Plugins
SamWM has a Lua-based plugin system that allows extending the window manager with custom behavior.
Plugin System
Plugins are Lua scripts that register event handlers, custom layouts, window rules, and actions.
Loading Plugins
Place plugin files in ~/.config/samwm/plugins/ and load them from your config:
dofile(os.getenv("HOME") .. "/.config/samwm/plugins/my-plugin.lua")
``continue`
### Plugin Structure
```lua
samwm.plugin("my-plugin", function()
samwm.log("My plugin initialized!")
end)Events
Register handlers for compositor events:
samwm.on_event("window_created", function(data)
local info = json.decode(data)
samwm.log("New window: " .. info.title .. " (" .. info.class .. ")")
end)
samwm.on_event("window_destroyed", function(data)
samwm.log("Window closed")
end)
samwm.on_event("focus_changed", function(data)
samwm.log("Focus changed")
end)
samwm.on_event("workspace_changed", function(data)
samwm.log("Workspace: " .. data)
end)
samwm.on_event("layout_changed", function(data)
samwm.log("Layout: " .. data)
end)Window Rules
Apply rules based on window class/title:
samwm.set_window_rule({ class = "firefox" }, "workspace 2")
samwm.set_window_rule({ title = "Picture-in-Picture" }, "float")
samwm.set_window_rule({ class = "mpv" }, "fullscreen")Rule actions:
"float"— Make window floating"tile"— Force tiling"fullscreen"— Make fullscreen"workspace N"— Move to workspace N
Custom Layouts as Plugins
samwm.plugin("fibonacci-layout", function()
samwm.register_layout("fibonacci", function(windows, bounds)
local result = {}
local remaining = {}
for _, w in pairs(windows) do
table.insert(remaining, w)
end
local x, y = bounds.x, bounds.y
local w, h = bounds.width, bounds.height
local horiz = true
for i, win in ipairs(remaining) do
if i == #remaining then
table.insert(result, {
id = win.id, x = x, y = y,
width = w, height = h
})
elseif horiz then
local half = math.floor(w / 2)
table.insert(result, {
id = win.id, x = x, y = y,
width = half, height = h
})
x = x + half
w = w - half
horiz = false
else
local half = math.floor(h / 2)
table.insert(result, {
id = win.id, x = x, y = y,
width = w, height = half
})
y = y + half
h = h - half
horiz = true
end
end
return result
end)
samwm.log("Fibonacci layout registered")
end)Window Manipulation from Lua
-- Get all windows
local windows = samwm.get_windows()
for _, w in pairs(windows) do
samwm.log(w.title .. " at (" .. w.x .. "," .. w.y .. ")")
end
-- Get focused window
local focused = samwm.get_focused()
if focused then
samwm.log("Focused: " .. focused.title)
end
-- Move a window
samwm.move_window(window_id, x, y)
-- Resize a window
samwm.resize_window(window_id, width, height)
-- Get output dimensions
local size = samwm.get_output_size()
samwm.log("Output: " .. size.width .. "x" .. size.height)Complete Plugin Example
-- ~/.config/samwm/plugins/auto-center-float.lua
samwm.plugin("auto-center-float", function()
samwm.on_event("window_created", function(data)
-- Auto-center floating windows
local size = samwm.get_output_size()
local focused = samwm.get_focused()
if focused and focused.floating then
local wx = math.floor((size.width - focused.width) / 2)
local wy = math.floor((size.height - focused.height) / 2)
samwm.move_window(focused.id, wx, wy)
end
end)
end)Lua API Reference
| Function | Description |
|---|---|
samwm.bind(mod, key, action) |
Register keybinding |
samwm.exec(cmd) |
Execute shell command |
samwm.focus(dir) |
Focus next/prev window |
samwm.toggle_floating() |
Toggle focused window floating |
samwm.toggle_fullscreen() |
Toggle focused window fullscreen |
samwm.close_window() |
Close focused window |
samwm.switch_layout(name) |
Switch active layout |
samwm.list_layouts() |
List available layouts |
samwm.register_layout(name, fn) |
Register custom layout |
samwm.get_windows() |
Get all windows |
samwm.get_focused() |
Get focused window |
samwm.move_window(id, x, y) |
Move window |
samwm.resize_window(id, w, h) |
Resize window |
samwm.set_window_rule(match, action) |
Set window rule |
samwm.on_event(event, fn) |
Register event handler |
samwm.plugin(name, fn) |
Register plugin |
samwm.get_output_size() |
Get output dimensions |
samwm.move_to_workspace(n) |
Move focused window to workspace |
samwm.set_workspace(n) |
Switch to workspace |
samwm.send_action(action) |
Send custom action |
samwm.log(msg) |
Log message |