Document iteration 1: settings file, HA Dashboard tab, new hooks
README: settings file, --config, the new tab. ARCHITECTURE.md and CLAUDE.md: prepare() hook, app command-line options, app code layout, WebEngine notes, the moc raw-string pitfall. THIRD_PARTY_NOTICES: Qt WebEngine. Ship config.example.json; the package README explains the set-up. PROGRESS.md and DESIGN.md: phase 3 results and deviations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,7 +29,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
**FrameAssistant**, "Steam Frame companion for Home Assistant" (in the spirit of HASS.Agent):
|
||||
it reports headset/environment sensors to Home Assistant, offers services Home Assistant can
|
||||
call (e.g. notifications in the headset), and shows a Home Assistant dashboard as a SteamVR
|
||||
dashboard tab. Status: the overlay platform works; the Home Assistant parts are being planned.
|
||||
dashboard tab. Status: the overlay platform works; the Home Assistant parts are being built
|
||||
(implementation iteration 1: settings file and the "HA Dashboard" web UI tab).
|
||||
|
||||
**Start every session by reading `docs/PROGRESS.md`** (current state, next steps, log).
|
||||
|
||||
@@ -60,7 +61,7 @@ cmake --preset native-debug && cmake --build --preset native-debug # system Qt
|
||||
ctest --preset native-debug # all tests
|
||||
build/native-debug/bin/tst_inputbridge clickUsesGlCoordinates # one QtTest function
|
||||
build/native-debug/bin/frame-assistant --desktop # UI preview in a window, no SteamVR
|
||||
build/native-debug/bin/frame-assistant --snapshot x.png # one frame via the real offscreen path
|
||||
build/native-debug/bin/frame-assistant --snapshot x.png # x-0.png (main tab), x-dashboard.png
|
||||
scripts/container-build.sh cross # x86_64 → aarch64 against the Frame's system Qt (default)
|
||||
scripts/container-build.sh native # same for the host arch (use on the Frame)
|
||||
scripts/container-build.sh cross-bundle # fallback: self-contained, Qt bundled (also native-bundle)
|
||||
@@ -70,7 +71,11 @@ VK_DRIVER=lvp scripts/container-test.sh # same on lavapipe (software Vulkan)
|
||||
build/native-debug/bin/frame-assistant --graphics-api vulkan --benchmark 600 # frame ms incl. GPU
|
||||
```
|
||||
|
||||
- Use `--snapshot` and then read the PNG to check UI or rendering changes without a headset.
|
||||
- Use `--snapshot` and then read the PNGs to check UI or rendering changes without a headset.
|
||||
With several surfaces it writes `<name>-<id>.png` per surface (`-0` for the main tab's
|
||||
empty id). Snapshot and benchmark don't load the settings, so the "HA Dashboard" tab shows
|
||||
its "no URL" hint there.
|
||||
- Overlay and desktop mode need a settings file; pass a test one with `--config <path>`.
|
||||
- `tst_render` runs once per backend (`VRDASH_TEST_API`, separate CTest entries, because the
|
||||
Qt graphics API is process-global). It QSKIPs without a GPU context or when Vulkan isn't
|
||||
compiled in.
|
||||
@@ -106,11 +111,14 @@ into Qt events.
|
||||
modes (overlay, `--desktop`, `--snapshot`, `--benchmark`, manifest install).
|
||||
- **Inheritance for the app, components for the surfaces** (the user's decision, after
|
||||
trying composition): the app derives from `DashboardApplication`. In its constructor it
|
||||
configures (`addSurface`, optional `setAppKey`/`setDisplayName`) and it
|
||||
overrides the hooks `loading()` (backends + shared engine exist, QML not loaded) and
|
||||
`started()` (everything runs). In the hooks, protected accessors give the running state:
|
||||
`mode()`, `appKey()`, `appName()`, `engine()`, `surfaces()`, `surface()` (primary),
|
||||
`surface(id)`, `vrRuntime()`, `navigation()`. The app is `src/Dashboard.h/.cpp`.
|
||||
configures (`addSurface`, optional `setAppKey`/`setDisplayName`) and passes its own
|
||||
command-line options (`QCommandLineOption` list) to the base constructor. It overrides
|
||||
the hooks `prepare(QString*)` (first; mode and app key known, no engine/surfaces/SteamVR
|
||||
yet; returning false ends `exec()` with exit code 1), `loading()` (backends + shared
|
||||
engine exist, QML not loaded) and `started()` (everything runs). In the hooks, protected
|
||||
accessors give the running state: `mode()`, `appKey()`, `appName()`, `isOptionSet()`,
|
||||
`optionValue()`, `engine()`, `surfaces()`, `surface()` (primary), `surface(id)`,
|
||||
`vrRuntime()`, `navigation()`. The app is `src/Dashboard.h/.cpp`.
|
||||
- The base constructor creates the `QGuiApplication` (`QCoreApplication` for manifest
|
||||
commands), so derived members can be QObjects with timers.
|
||||
- All QML and surfaces are torn down **at the end of `exec()`**, while the derived object
|
||||
@@ -188,6 +196,22 @@ into Qt events.
|
||||
- **QML singletons owned by the app:** keep them as members of the app class. A singleton
|
||||
must not be default-constructible, or QML builds its own instance instead of calling
|
||||
`create()` (e.g. give the constructor a required `QObject* parent` and init it `{nullptr}`).
|
||||
- **App code layout:** logic without SteamVR or rendering goes into the static library
|
||||
`frameassistant_lib` (`src/config/`, …), which the app and its tests link. QML types
|
||||
(`QML_ELEMENT`, e.g. `src/ha/HaWebUi`) go into `QML_SOURCES` of `vrdash_add_dashboard()`:
|
||||
they must be part of the QML module. The generated type registration includes their
|
||||
headers by file name only, so their directory is on the app's include path.
|
||||
- **Settings** (`src/config/Config`) are loaded once in `Dashboard::prepare()` (overlay and
|
||||
desktop mode) and passed on as an immutable value (DESIGN.md, D19).
|
||||
- **Qt WebEngine** ("HA Dashboard" tab): `QtWebEngineQuick::initialize()` runs in `main()`
|
||||
before the app object, because it must precede the `QGuiApplication`. `HaWebUi` creates a
|
||||
persistent profile under `~/.local/share/frameassistant/webengine` with the Qt 6.8 API
|
||||
(setters on `QQuickWebEngineProfile`). Qt ≥ 6.9 logs a hint to use
|
||||
`WebEngineProfilePrototype` instead, which the Frame's Qt 6.8 doesn't have.
|
||||
- **moc and raw string literals:** a raw string containing `//` (e.g. a URL) makes moc treat
|
||||
the rest as a comment; it then misses `Q_OBJECT` classes in that file (link error "vtable
|
||||
for …"). In moc'ed files, write such text as normal string literals (`tst_config` uses
|
||||
JSON with `'` quotes and converts them).
|
||||
- Publish per-frame values (frame stats etc.) to QML at most about once per second. Binding
|
||||
per-frame values in QML re-triggers the on-demand renderer forever.
|
||||
- **The executable is `frame-assistant` (`VRDASH_EXECUTABLE_NAME`), never `vrdashboard`.**
|
||||
@@ -307,3 +331,5 @@ Check these when testing on the device, and update this list:
|
||||
- The restructured app code (base class `DashboardApplication`, `Surface`, `Overlay` base,
|
||||
active-surface navigation) has only been tested off the device so far.
|
||||
- Several dashboard tabs from one process (works in `tst_surfaces`, not tried in SteamVR).
|
||||
- Qt WebEngine in the off-screen renderer (Vulkan and OpenGL), the SteamVR keyboard in web
|
||||
page input fields, and the persistent login ("HA Dashboard" tab, DSH-1).
|
||||
|
||||
Reference in New Issue
Block a user