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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
|
# Waywork
A framework for building [waywall](https://github.com/tesselslate/waywall) configurations for Minecraft speedrunning setups on Linux/Wayland.
## Overview
Waywork provides a structured, modular approach to managing waywall configurations. It abstracts common patterns like resolution switching, scene management, and process orchestration into reusable components, making waywall configs more maintainable and easier to understand.
## Example config
For reference you can look at my config which uses waywork here: [Esensats/waywall-config](https://github.com/Esensats/waywall-config)
## Table of Contents
<!-- @import "[TOC]" {cmd="toc" depthFrom=2 depthTo=6 orderedList=false} -->
<!-- code_chunk_output -->
- [Overview](#overview)
- [Example config](#example-config)
- [Table of Contents](#table-of-contents)
- [Components](#components)
- [Scene Manager (`scene.lua`)](#scene-manager-scenelua)
- [Mode Manager (`modes.lua`)](#mode-manager-modeslua)
- [Key Bindings (`keys.lua`)](#key-bindings-keyslua)
- [Core Utilities (`core.lua`)](#core-utilities-corelua)
- [Process Management (`processes.lua`)](#process-management-processeslua)
- [Migration to Waywork](#migration-to-waywork)
- [Before](#before)
- [After (Waywork)](#after-waywork)
- [Benefits](#benefits)
<!-- /code_chunk_output -->
## Components
### Scene Manager (`scene.lua`)
Manages visual elements (mirrors, images, text) uniformly with grouping and lifecycle management.
**Features:**
- **Unified Management**: Handle mirrors, images, and text objects through a single interface
- **Grouping**: Organize scene objects into logical groups for batch operations
- **Lazy Loading**: Objects are only created when enabled
- **Dynamic Updates**: Modify object properties at runtime
**Example:**
```lua
local Scene = require("waywork.scene")
local scene = Scene.SceneManager.new(waywall)
-- Register scene objects
scene:register("e_counter", {
kind = "mirror",
options = {
src = { x = 1, y = 37, w = 49, h = 9 },
dst = { x = 1150, y = 300, w = 196, h = 36 }
},
groups = { "thin" },
})
scene:register("eye_overlay", {
kind = "image",
path = "/path/to/overlay.png",
options = { dst = { x = 30, y = 340, w = 700, h = 400 } },
groups = { "tall" },
})
-- Enable/disable by group
scene:enable_group("thin", true) -- Enable all "thin" objects
scene:enable_group("tall", false) -- Disable all "tall" objects
-- Enable/disable individual objects
scene:enable("e_counter", true)
```
### Mode Manager (`modes.lua`)
Orchestrates resolution switching with enter/exit hooks and guard conditions.
**Features:**
- **Resolution Management**: Automatic resolution switching with cleanup
- **Lifecycle Hooks**: `on_enter` and `on_exit` callbacks for mode transitions
- **Toggle Guards**: Conditional guards to prevent accidental mode switches (e.g. pressing F3 + F4 to switch gamemode, but accidentally triggering mode transition instead)
- **State Tracking**: Knows which mode is currently active
**Example:**
```lua
local Modes = require("waywork.modes")
local ModeManager = Modes.ModeManager.new(waywall)
ModeManager:define("thin", {
width = 340,
height = 1080,
on_enter = function()
scene:enable_group("thin", true)
end,
on_exit = function()
scene:enable_group("thin", false)
end,
})
ModeManager:define("tall", {
width = 384,
height = 16384,
toggle_guard = function()
return not waywall.get_key("F3") -- Prevent toggle during F3 debug
end,
on_enter = function()
scene:enable_group("tall", true)
waywall.set_sensitivity(tall_sens)
end,
on_exit = function()
scene:enable_group("tall", false)
waywall.set_sensitivity(0)
end,
})
-- Toggle modes
ModeManager:toggle("thin") -- Switch to thin mode
ModeManager:toggle("thin") -- Switch back to default (0x0)
```
### Key Bindings (`keys.lua`)
Simple utility for building action tables from key mappings.
**Example:**
```lua
local Keys = require("waywork.keys")
local actions = Keys.actions({
["*-Alt_L"] = function()
return ModeManager:toggle("thin")
end,
["*-F4"] = function()
return ModeManager:toggle("tall")
end,
["Ctrl-E"] = function()
waywall.press_key("ESC")
end,
})
config.actions = actions
```
### Core Utilities (`core.lua`)
Low-level utilities used throughout the framework.
**Features:**
- **Toggle**: Boolean state management with callbacks
- **Resettable Timeout**: Timeout that cancels previous invocations
- **Table Operations**: Copy and merge utilities
### Process Management (`processes.lua`)
Utilities for managing external processes with shell command handling.
**Features:**
- **Process Detection**: Check if processes are running using `pgrep`
- **Java JAR Support**: Specialized utilities for launching Java applications
- **Argument Handling**: Proper handling of command arguments as arrays
**Example:**
```lua
local P = require("waywork.processes")
-- Check if a process is running
if P.is_running("firefox") then
print("Firefox is running")
end
-- Create Java JAR launchers with proper argument handling
local ensure_paceman = P.ensure_java_jar(
waywall,
"/usr/lib/jvm/java-24-openjdk/bin/java",
"/home/user/apps/paceman-tracker.jar",
{"--nogui"} -- arguments as array
)("paceman-tracker\\.jar*") -- process pattern to check
local ensure_ninjabrain = P.ensure_java_jar(
waywall,
"/usr/lib/jvm/java-24-openjdk/bin/java",
"/home/user/apps/ninjabrain-bot.jar",
{"-Dawt.useSystemAAFontSettings=on"} -- JVM arguments
)("ninjabrain-bot\\.jar") -- process pattern to check
-- Use in key bindings
["Ctrl-Shift-P"] = function()
ensure_ninjabrain() -- ensure Ninjabrain is running
ensure_paceman() -- ensure Paceman is running
end,
```
## Migration to Waywork
### Before
```lua
-- Scattered mirror management
local make_mirror = function(options)
local this = nil
return function(enable)
if enable and not this then
this = waywall.mirror(options)
elseif this and not enable then
this:close()
this = nil
end
end
end
local mirrors = {
e_counter = make_mirror({ src = {...}, dst = {...} }),
thin_pie_all = make_mirror({ src = {...}, dst = {...} }),
-- ... dozens more
}
-- Manual resolution management
local make_res = function(width, height, enable, disable)
return function()
local active_width, active_height = waywall.active_res()
if active_width == width and active_height == height then
waywall.set_resolution(0, 0)
disable()
else
waywall.set_resolution(width, height)
enable()
end
end
end
```
### After (Waywork)
```lua
local waywall = require("waywall")
local Scene = require("waywork.scene")
local Modes = require("waywork.modes")
local Keys = require("waywork.keys")
local scene = Scene.SceneManager.new(waywall)
local ModeManager = Modes.ModeManager.new(waywall)
-- Clean object registration
scene:register("e_counter", {
kind = "mirror",
options = { src = {...}, dst = {...} },
groups = { "thin" },
})
-- Declarative mode definitions
ModeManager:define("thin", {
width = 340,
height = 1080,
on_enter = function() scene:enable_group("thin", true) end,
on_exit = function() scene:enable_group("thin", false) end,
})
-- Simple key mappings
local actions = Keys.actions({
["*-Alt_L"] = function() return ModeManager:toggle("thin") end,
})
```
## Benefits
1. **Reduced Boilerplate**: Framework handles object lifecycle, resolution management, and state tracking
2. **Better Organization**: Logical grouping of related functionality
3. **Maintainability**: Clear separation of concerns and declarative configuration
4. **Reusability**: Common patterns abstracted into reusable components
5. **Error Prevention**: Toggle guards and proper state management prevent common issues
6. **Cleaner Code**: Focus on what you want to achieve, not how to implement it
|