> For the complete documentation index, see [llms.txt](https://docs.kouch.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kouch.dev/docs/adr/0017-game-mode-quick-menu-override.md).

# ADR 0017: In Game Mode the Quick Menu is a same-app override window

## Status

Accepted on 2026-09-26. It reverses `docs/ARCHITECTURE.md`'s "gamescope overlay (Deck Game Mode)" plan, which marked the Quick Menu with `GAMESCOPE_EXTERNAL_OVERLAY`. Verified in real Game Mode on the owner's Deck OLED (gamescope 3.16.23): Early Test 10 PASS.

## Context

* **The first plan never drew anything.** In Deck Game Mode, Steam's UI runs on gamescope's root Xwayland, while games, Kouch and its emulators run on a second one. gamescope composites `GAMESCOPE_EXTERNAL_OVERLAY` windows only from the root Xwayland, and it sets the app id of any marked window to 0 (`if (w->isExternalOverlay) w->appID = 0;` in `steamcompmgr.cpp`).
* **gamescope already supports what the Quick Menu needs.** It draws an override-redirect window over the focused window when both belong to the same app. Under Steam's focus control, "same app" means `override->appID == focus->appID`, where the app id comes from the window's `STEAM_GAME` property or from the process's Steam launch.
* **Three problems blocked that path, all found with full-composition `gamescopectl` captures and focus dumps:**
  1. **The game belonged to another app.** Kouch's Steam init (`Client::init_app`) writes its own app id into the process environment. Every emulator inherited it, so gamescope saw the game as a different app than the one Steam had focused, and the screen stayed black.
  2. **The external-overlay mark** zeroed the Quick Menu's app id.
  3. **gamescope ignored the override.** GTK/WebKit give the Quick Menu's X window a single 1×1 child. gamescope's `get_size_hints` treats an override-redirect window with one child that fits inside it as an old SDL fullscreen wrapper and sets `ignoreOverrideRedirect` for the window's lifetime, unless `WM_NORMAL_HINTS` pins min = max.
* **A live test proved it.** A test override window of the same app was drawn over the game. The same window with one child was not. With one child and pinned hints, it was drawn again.

## Decision

1. **Launch ids.** Emulators get Steam's launch ids (`SteamAppId`, `SteamGameId`, `SteamOverlayGameId`), captured before Kouch's Steam init (`kouch_launch::capture_launch_env`, `9ffbc23`). Kouch still initializes the Steam API as its configured app id.
2. **The Quick Menu under gamescope** is an override-redirect window of Kouch's own app:
   * no `GAMESCOPE_EXTERNAL_OVERLAY`;
   * pinned to the panel size (the same share of the screen as on Windows) with one min = max `WM_NORMAL_HINTS` write, before its first map and on every show (`dcc19eb`, `6b9a3bb`).
   * The game stays visible beside it.
3. **Window discovery** under gamescope takes a window's pid from the X server (X-Resource), as gamescope does (`ddf54ce`), so Flatpak emulators are found too.

## Consequences

* The Quick Menu works in Game Mode without Decky and without injecting into Steam's UI.
* It depends on gamescope's same-app override behavior, read from gamescope 3.16.23's source and verified live; it is not a documented API. `docs/EARLY_TESTS.md` Early Test 10 is the regression check, run with `~/kouch-dev/gm-run.sh`.
* The panel is drawn in gamescope's override layer, which sits below the layers Steam uses for its own overlay and menus.
* If Steam ever runs Kouch and its games under different app ids (e.g. an emulator started by another launcher), the menu won't be drawn over that game; the fallback in Early Test 10 (hide the game, show the menu full screen) remains available.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.kouch.dev/docs/adr/0017-game-mode-quick-menu-override.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
