Skip to content

Esensats/waywork

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Waywork

A framework for building 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

Installation

Clone the repository into your waywall configuration directory:

# For example:
git clone --depth 1 https://github.com/Esensats/waywork ~/.config/waywall/waywork

Table of Contents

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:

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:

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:

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:

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

-- 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)

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

About

Config building framework for waywall

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages