summaryrefslogtreecommitdiff
path: root/modes.lua
diff options
context:
space:
mode:
authorSam Nystrom <sam@samnystrom.dev>2025-11-27 17:35:48 -0500
committerSam Nystrom <sam@samnystrom.dev>2025-11-27 17:35:48 -0500
commit747b8a465a501211ebe41d5892eb9262f26743dc (patch)
tree170ef89197a6648a378cec1ce45201442c3e163e /modes.lua
Squashed '.config/waywall/waywork/' content from commit f0b8424
git-subtree-dir: .config/waywall/waywork git-subtree-split: f0b84240c63f4a13d6a8cb54a037424d5d64329a
Diffstat (limited to 'modes.lua')
-rw-r--r--modes.lua103
1 files changed, 103 insertions, 0 deletions
diff --git a/modes.lua b/modes.lua
new file mode 100644
index 0000000..3bf0047
--- /dev/null
+++ b/modes.lua
@@ -0,0 +1,103 @@
+local modes = {}
+
+--- ModeManager orchestrates resolution toggles and on_enter/on_exit hooks.
+local ModeManager = {}
+ModeManager.__index = ModeManager
+
+function ModeManager.new(waywall)
+ return setmetatable({ ww = waywall, active = nil, defs = {} }, ModeManager)
+end
+
+--- def: { width, height, on_enter=function(), on_exit=function(), toggle_guard=function()->bool }
+function ModeManager:define(name, def)
+ self.defs[name] = def
+end
+
+local function active_res(ww)
+ local w, h = ww.active_res()
+ return tonumber(w), tonumber(h)
+end
+
+--- Get the mode definition by name, erroring if not found.
+--- @param name string
+function ModeManager:_get_def(name)
+ assert(self.defs[name], "No such mode: " .. tostring(name))
+ return self.defs[name]
+end
+
+--- Transition to a mode by name, turning off any previously active mode.
+--- If name is nil, turn off any active mode.
+--- This does not check toggle_guard.
+--- @param name string?
+function ModeManager:_transition_to(name)
+ local function exit_active()
+ if self.active then
+ local prev = self:_get_def(self.active)
+ self.ww.set_resolution(0, 0)
+ if prev.on_exit then
+ prev.on_exit()
+ end
+ self.active = nil
+ end
+ end
+
+ local function enter_mode(_name)
+ if _name then
+ local new = self:_get_def(_name)
+ self.ww.set_resolution(new.width, new.height)
+ if new.on_enter then
+ new.on_enter()
+ end
+ self.active = _name
+ end
+ end
+
+ if name == nil then
+ exit_active()
+ return
+ end
+ if name == self.active then
+ -- already active, do nothing
+ return
+ end
+ exit_active()
+ enter_mode(name)
+end
+
+--- Toggle a mode by name. If it's active, turn it off. If it's inactive, turn it on.
+--- If the mode has a toggle_guard and it returns false, do nothing and return false.
+--- @param name string
+--- @return boolean|nil
+function ModeManager:toggle(name)
+ local ww, def = self.ww, self.defs[name]
+ if not def then
+ return
+ end
+ if def.toggle_guard and def.toggle_guard() == false then
+ return false
+ end
+ -- local w, h = active_res(ww)
+ -- if w == def.width and h == def.height then
+ -- ww.set_resolution(0, 0)
+ -- if def.on_exit then
+ -- def.on_exit()
+ -- end
+ -- self.active = nil
+ -- else
+ -- ww.set_resolution(def.width, def.height)
+ -- if def.on_enter then
+ -- def.on_enter()
+ -- end
+ -- -- exit previous if different
+ -- self.active = name
+ -- end
+
+ if name == self.active then
+ self:_transition_to(nil)
+ else
+ self:_transition_to(name)
+ end
+end
+
+modes.ModeManager = ModeManager
+return modes