GOALS.md / AGENTS.md are the source of truth. Layout apply requires ENBOXER_ALLOW_LAYOUT=1 and a GUI confirm. Example Video FX is off.
93 lines
5.6 KiB
Markdown
93 lines
5.6 KiB
Markdown
# Goals
|
||
|
||
This is what the project is **for**. If a change fights this file, the change is wrong.
|
||
|
||
enBoxer is a **Rust rewrite, for Arch Linux + Hyprland**, of a Windows multibox controller, **then extras on top**. It lives in `~/git/enBoxer` and ships to **https://gitea.nettsi.de/en/enbuddy** over **HTTPS only** (never SSH).
|
||
|
||
The user plays several World of Warcraft clients (Forever when it exists; until then retail-shaped macros). They move with **ESDF**, not WASD. They do **not** want the game to think they are botting: **no DLL, no memory inject, no addon required in v1**. Keys and clicks only. They will bind macros in-game themselves.
|
||
|
||
They do **not** want to test until they have to. Agents must not crash the Hyprland session: **no live `hyprctl dispatch` that floats, moves, resizes, pins, or closes the user’s windows.** Layout apply is opt-in (`ENBOXER_ALLOW_LAYOUT=1` plus a GUI confirm). Do not launch Steam or unrelated programs.
|
||
|
||
## Rewrite first (the original app)
|
||
|
||
That Windows app is a **GUI** with a **window layout wizard**. enBoxer must be the same kind of program, not a YAML daemon with a thin panel bolted on.
|
||
|
||
### Control panel
|
||
|
||
- One native GUI (`enboxer` with no args). Menus, not only CLI.
|
||
- **File:** save / reload / named profiles.
|
||
- **Session:** start/stop routing, three modes, capture list, passthrough, game binds.
|
||
- **Layout:** the important missing piece from the first GUI pass — see below.
|
||
- **Maps:** hotkeys and steps.
|
||
- **Video FX:** source and viewer rectangles.
|
||
- **Macros:** text to bind in WoW.
|
||
|
||
### Window layout (from the source app’s wizard)
|
||
|
||
- Choose how many clients.
|
||
- Presets: **all stacked**, **same-size grid**, **one large main + a strip of minions**.
|
||
- Options: main at bottom, one row for small windows, stay-on-top / pin, which monitor.
|
||
- Per-slot **x y w h** (pixels), editable after generate.
|
||
- Drag-equivalent: Generate, **Capture current positions**, **Save and Apply**.
|
||
- Apply only when the user allows window moves (see Safety).
|
||
- **Swap** a minion into the main tile (Make main / swap next / per-slot swap hotkeys).
|
||
- **Focus** next / previous / main / slot N.
|
||
- **Reset all** to the saved layout.
|
||
- Auto-capture matching game windows by class/title regex (do not grab the whole desktop; empty match = match nothing).
|
||
|
||
### Key delivery (rewrite, then the extra)
|
||
|
||
The Windows app cloned keys by posting messages and/or swapping which window was in front. enBoxer **routes** instead:
|
||
|
||
1. **maps** — only configured hotkeys are intercepted and sent to `current` / `others` / `all` / groups. Everything else goes to the front client.
|
||
2. **mirror** — front client still gets the real key; the same key is cloned to the other game windows. `passthrough` (ESDF by default, or empty, or WASD — **user’s list, never hardcoded**) is not cloned.
|
||
3. **off** — no intercept. All keys go to the front window. Mode-toggle still works.
|
||
|
||
Toggle: `Shift+Alt+M` (configurable) and GUI. Routing **off** when alt-tabbed to a non-game window. The machine is a normal PC.
|
||
|
||
Keys are Hyprland compositor events (`send_shortcut` / `send_key_state`). Wine on **XWayland** (usual WoW) accepts them unfocused. Native Wayland / winewayland: brief focus, send, restore. Not a physical `/dev/input` keyboard; not process injection.
|
||
|
||
Mouse click clone (optional): relative to each client. Do not leave the cursor stranded.
|
||
|
||
### Interact / loot (on top of routing)
|
||
|
||
One press, not spam. Assist others → Click-to-Move on → Interact with Target once → wait `walk_delay_ms` → CTM off. Hold and auto styles exist. Macros: `docs/MACROS.md`. No addon until Forever exists and we know the API.
|
||
|
||
## Extras on top of the rewrite
|
||
|
||
### Video FX (live crop)
|
||
|
||
The user must be able to set:
|
||
|
||
- **Source:** which other client, which rectangle, what size.
|
||
- **Viewer:** where that crop is drawn on the **primary**, what size.
|
||
- Fractions `0`–`1` of that window, or **pixels** if any value > 1. GUI **Pick** via slurp.
|
||
- While the mouse is over the viewer: **clicks and keys go only to that source**, not to the primary and not to the rest of the team.
|
||
|
||
Today capture is `grim` (visible pixels) + `mpv` overlay. **Covered/stacked sources need compositor window-export** (`hyprland-toplevel-export`). Until that exists, keep the source on a visible output. Do not claim grim is good enough for a stacked layout.
|
||
|
||
### Other extras (wanted, not all shipped)
|
||
|
||
- Named profiles (multiple teams).
|
||
- Type/clipboard broadcast to other clients (passwords, `/commands`) without swapping windows.
|
||
- Slot-number overlay on the layout (click to make main), like the source app.
|
||
- Borderless game windows via Hyprland rules, not inject.
|
||
- Follow/assist macros that follow **who is currently main** after a swap.
|
||
- Forever client check when that game exists (lean retail macros until proven otherwise).
|
||
|
||
## Safety (non-negotiable)
|
||
|
||
- Default `enboxer run`: **keys only**. No float/move/resize/pin.
|
||
- `ENBOXER_ALLOW_LAYOUT=1` required for apply/swap-geometry/reset.
|
||
- GUI: checkbox “Allow moving game windows”, then a confirm before Apply.
|
||
- Example profile: Video FX **off**, layout tiles **empty**, `auto_apply: false`.
|
||
- Agents: unit tests only against Hyprland. No live dispatch that rearranges the user’s session. No Steam.
|
||
|
||
## Done when
|
||
|
||
- GUI can configure **all** of the above without hand-editing YAML (YAML remains the store).
|
||
- Layout wizard + apply works **when the user opts in**, without off-monitor garbage.
|
||
- Maps / mirror / off work; ESDF passthrough is configurable.
|
||
- Video FX source/viewer/size + hover click and key pass-through work for **visible** sources; export for hidden sources is the remaining capture gap.
|
||
- No inject, no required addon, HTTPS remote is `en/enbuddy`.
|