aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/docs/notes/avalonia-gotchas.md
diff options
context:
space:
mode:
authorgodosa <godosa@godosa.eu>2026-10-06 23:39:36 +0200
committergodosa <godosa@godosa.eu>2026-10-06 23:39:36 +0200
commit39066900773e7857faf2d02e7ed51b71d219d97d (patch)
treeffab8e4ddd971626776c3b1f4ce1da2c186c2187 /docs/notes/avalonia-gotchas.md
downloadgodosa-engine-39066900773e7857faf2d02e7ed51b71d219d97d.tar.gz
godosa-engine-39066900773e7857faf2d02e7ed51b71d219d97d.zip
godosa-engine: initial public history
Diffstat (limited to 'docs/notes/avalonia-gotchas.md')
-rw-r--r--docs/notes/avalonia-gotchas.md53
1 files changed, 53 insertions, 0 deletions
diff --git a/docs/notes/avalonia-gotchas.md b/docs/notes/avalonia-gotchas.md
new file mode 100644
index 0000000..5150505
--- /dev/null
+++ b/docs/notes/avalonia-gotchas.md
@@ -0,0 +1,53 @@
+# Avalonia / Desktop gotchas
+
+Each one cost debugging time once. The code has comments at each site;
+this file is the index.
+
+- **The GL view isn't hit-testable by default.** `OpenGlControlBase` draws
+ through GL, not Avalonia's scene. Pointer events and `Cursor` go to the
+ panel beneath unless the control implements `ICustomHitTest`
+ (`GameView.HitTest`). Display-only overlays need `IsHitTestVisible =
+ false` so the pointer reaches the game.
+- **Deactivation ≠ lost focus.** Clicking another app deactivates the window
+ but keeps logical focus (`IsFocused` stays true), so `OnLostFocus` never
+ fires. Release held keys on `Window.Deactivated` too, because `OnKeyUp`
+ never arrives for a key released elsewhere.
+- **The sim only advances while frames render.** `GameLoop.Frame` runs
+ inside `OnOpenGlRender`. Stopping `RequestNextFrameRendering` (paused)
+ stops the sim, and "keep simulating while minimized" would need a timer.
+- **The render callback runs on the UI thread** (verified on this Linux/X11
+ setup). The overlay and `FrameTimeStats` share state without locks for
+ that reason. Re-check if a platform moves rendering off-thread.
+- **No pointer lock API** in Avalonia 12.1.2. Free look reads deltas between
+ pointer positions and stalls at the window edge. Recentering uses a
+ platform call (`CursorWarp`, X11 `XWarpPointer`; off where it fails).
+- **Escape vs focused controls.** A clicked `CheckBox` takes keyboard focus,
+ so `Esc` for the options menu is a window-level *tunnel* handler, not
+ `GameView.OnKeyDown`.
+- **Tests: float vs double.** `FixedStepClock.TickSeconds` is `float`. Compare
+ it against double arithmetic with a tolerance (~1e-6), not 9 places.
+- **A clicked in-game `Button` steals the game's keys.** It takes focus, so
+ WASD stops reaching `GameView` and Space presses the button. HUD buttons
+ are `Focusable = false` (`Ui.Action`).
+- **Raising `Button.ClickEvent` doesn't toggle a `CheckBox`.** Toggle logic
+ lives in `ToggleButton.OnClick`; scripted/pad presses use `Ui.Press`.
+- **`KeyBindings` inside a control resolves to Avalonia's
+ `InputElement.KeyBindings`**, not ours — qualify the game's own `KeyBindings` type fully.
+- **Invisible controls aren't templated.** `IsVisible = false` skips
+ measure/template, so the first real open pays for it (first NPC dialog
+ ~170 ms). `Ui.WarmUp()` shows a zero-opacity card briefly instead.
+- **Routed key events only reach controls on the route.** A `KeyDown` raised
+ on the focused `GameView` tunnels window → `GameScreen` → `GameView`; a
+ sibling panel (options) never sees it. Screen-wide key handling lives on
+ `GameScreen` (e.g. key-rebind capture).
+- **Scripted input vs X injection.** On KDE Wayland `xdotool` keys don't reach
+ a focused XWayland window (and may type into the user's terminal); drive
+ smoke runs with `smoke_run.sh --input FILE` (routed events in-process).
+- **The HUD is redrawn every frame over the GL view.** The GL control changes every frame
+ and covers the window, so the compositor re-draws every overlay each frame — text is
+ the expensive part. `CacheMode = new BitmapCache()` on HUD cards (`Ui.Card`) makes them
+ re-render only on change; set `RenderAtScale` to any scale transform above them or they
+ blur. Merging text blocks into fewer visuals doesn't help.
+- **Don't judge perf by CPU % on this machine** (±50 % with other load). Use the `instr:`
+ smoke step, interleaved runs, `PauseWhenInactive` off; see game-loop spec §7.
+