rgui - Terminal Transport Tycoon GUI Framework + XFCE-Style Desktop Demo
Zero-dependency C++20 header-only terminal GUI framework recreating the
Transport Tycoon / OpenTTD window-and-widget look in a plain terminal,
plus an XFCE-style desktop demo (demo.cpp).
Build
make # builds ./demo and ./run_tests (see Makefile)
make -j2 tests # batched per-file objects under build/obj (same binary, incremental; keep -j low, each TU is large)
make check # tests + --dump-config + --help smoke
./demo
./demo --help
./demo --dump-config
./demo --selftest # runs the §13 suite ./run_tests (build it first with `make tests`)
# Without make: g++ -std=c++20 -Wall -Wextra -Wpedantic -O2 demo.cpp -o demo
Requires Linux, g++ with C++20. No ncurses or third-party libraries.
Only the C++ standard library and POSIX (termios, ioctl, poll,
pty) are used.
Run
Needs a real terminal (xterm / gnome-terminal / tmux). Use at least
80×24; 160×50 recommended. The demo boots into:
- Top green TT-toolbar panel: Whisker-style menu, launchers, tasklist,
workspace pager (4), tray, clock with calendar via menu. - Bottom grey status bar: user@host, memory, CPU, scrolling ticker.
- Wallpaper desktop with icons: Home, Terminal, Editor, Settings,
Widget Gallery, SmallMap Toy, Trash, README. - Pre-opened windows: green Terminal (real PTY shell), grey File
Manager, purple Settings, brown SmallMap + linked Viewport.
Exit: Applications menu → close, Ctrl+Q, or Console quit.
Terminal is restored on exit (alternate screen, raw mode, mouse).
Keys & Mouse
| Input | Action |
|---|---|
Alt+Tab |
Window switcher |
Delete |
Close all non-sticky windows |
F12 or ` ~ |
Toggle Console drop-down |
Ctrl+Q |
Quit |
Tab / Shift+Tab |
Focus traversal |
Esc |
Cancel drag, close menu, release edit focus |
| Drag caption | Move window (snaps to edges/windows) |
| Drag resize box / border | Resize |
| Double-click caption | Maximize/restore |
| Wheel on caption | Shade/roll-up |
| Caption ✕ / shade / sticky boxes | Close / shade / pin |
| Right-click caption | Window menu |
| Hover | Tooltip after delay; right-click also shows help |
One edit widget holds global keyboard focus (OpenTTD rule); Esc
or clicking away releases it. Terminal widgets forward keys to the
PTY except reserved chords (Ctrl+Q, F12, Alt+Tab).
Config
Single source of truth: Config in ttgui.hpp.
File format is JSON (*.env.json) parsed by the built-in strict parser.
Search order (first found wins):
$RGUI_CONFIG./rgui.env.json./.env.json$XDG_CONFIG_HOME/rgui/rgui.env.json(or~/.config/rgui/rgui.env.json)- Built-in defaults
--config <path> overrides; --dump-config prints the effective
config as JSON and exits. Unknown keys warn and are ignored; wrong
types fall back per-key; bad JSON reports line:column and uses
defaults - never crashes. Settings → Save Config writes back to the
loaded path with stable key order. See rgui.env.json
for the commented example covering window colours, TT colours,
widget base colours (uiColors: paper, selection, urgent, progress…),
glyphs, bevel, snap, timings, effects, bell, keybindings, shell,
workspaces, clock, and wallpaper.
Documentation
- README.md (this file) - build, run, keys, config for users.
- API.md - architecture, class/widget catalogue, events, full config-key reference, how to write an app or widget, known limitations.
- tests/README.md - test tiers, runner options, requirement → test traceability.
- prompt.md - the original specification (§1-§13) the code was built against.
- Source files start with a file map: ttgui.hpp, demo.cpp, tttest.hpp.
Review status
A full critical review of this project lives in
review.md: every finding (critical / high / medium / demo)
with file:line evidence, a researched best-practice fix approach with
sources, a Status, and the regression test that closes it. As of the
final verification pass recorded there, 42 of 42 findings are FIXED and
0 are OPEN or PARTIAL - including the VT-parser memory-safety cluster,
double terminal input, real mouse Drag events, bell urgency, working
effects and drag & drop, full-cell (glyph+colour+attributes) goldens,
and honest test-framework self-tests. Each fix is covered by the suite
(tests/test_stageb.cpp, tests/test_stagec.cpp, tests/test_staged.cpp,
tests/test_terminal_input_once.cpp, tests/test_uicolors.cpp, plus the
original per-area files). Last full run on this tree: 131 run / 123
passed / 0 failed / 8 skipped (opt-in tiers), [pty] 5/5, [fuzz]
3/3, ASan/UBSan tier equally green, --dump-config round-trips.
Details: tests/README.md.
Layout
- ttgui.hpp - framework (header-only)
- API.md - developer API & architecture documentation
- tttest.hpp - own zero-dependency test framework (§13)
- demo.cpp - desktop demo, apps via
IApp/AppRegistry - rgui.env.json - example config
tests/- structured suite + golden screens (seetests/README.md)- review.md - critical review, researched fixes, per-finding status
Makefile-make/make -j2 tests(batched objects) /make asan/make checkprompt.md- full specification (§1-§13)
Framework: Config/Theme, Geometry, Canvas double-buffer with
diff rendering, Terminal RAII, InputParser, event hierarchy,
Widget tree with Signal slots, layout containers, full §4 widget
catalogue, Window/WindowManager (drag/snap/shade/sticky/maximize/
workspaces), Desktop, Application poll loop, VtParser +
PTY TerminalWidget, DragManager, BellService.
Demo apps registered without touching framework code: Terminal,
File Manager (sandbox mutations in /tmp/rgui-sandbox), Editor,
Settings (live re-theme + save), Widget Gallery (all widgets),
SmallMap Toy, About, Calculator, Task Manager (/proc), Console
(help, open <app>, bell, effects on|off, config, quit).
Tests
Zero-dependency suite with its own header-only framework
(tttest.hpp); no Catch2/GoogleTest/doctest.
make tests && ./run_tests # tiers 1-3: unit, integration, golden
./run_tests --tags [pty] # real-PTY tier
./run_tests --update-golden # intentionally regenerate goldens only
make asan && ./run_tests_asan # sanitizer tier (binary: run_tests_asan)
./demo --selftest # executes this same ./run_tests suite
# Goldens are full-cell (glyph+fg+bg+attrs, *.cells.txt via CHECK_GOLDEN_CELLS); the real demo boot is covered by the [pty] smoke tier (see review.md C11).
See tests/README.md for tiers, runner options,
and the prompt.md § → test traceability table.