summaryrefslogtreecommitdiff
path: root/modes.lua
blob: 3bf0047e9bc2f2bb854576d507cb47f926bcf088 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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