A simple, small calculator placed discreetly near the Windows Taskbar or anywhere on the screen
0

Configure Feed

Select the types of activity you want to include in your feed.

docs: design for auto-hide caption (frame visible only when window is active)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

authored by

Marco Maroni
Claude Fable 5
and committed by
Tangled
(Jul 15, 2026, 1:16 PM +0300) c8c21281 3aab2ccc

+90
+90
docs/superpowers/specs/2026-07-15-auto-hide-caption-design.md
··· 1 + # Auto-Hide Caption (frame visible only when active) — Design 2 + 3 + **Date:** 2026-07-15 4 + **Status:** Approved (brainstorming) 5 + 6 + ## Goal 7 + 8 + Show the calculator window's title bar and close button **only while the window is 9 + active**. When focus moves to another window the calculator stays on top as a clean, 10 + chromeless display (no caption, no X); clicking it back (or showing it from the tray) 11 + brings the frame back. 12 + 13 + ## Behavior 14 + 15 + - Handle `WM_ACTIVATE` in `CCalculatorWindow`: 16 + - **Activated** (`WA_ACTIVE` / `WA_CLICKACTIVE`): add `WS_CAPTION | WS_SYSMENU`. 17 + - **Deactivated** (`WA_INACTIVE`): remove `WS_CAPTION | WS_SYSMENU`. 18 + - The toggle uses `SetWindowLongPtr(GWL_STYLE)` followed by 19 + `SetWindowPos(SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER)`. 20 + - `CreateStandalone` is unchanged (window is created with the caption styles; it is 21 + hidden at that point, so the first activation just confirms the state). 22 + - A private helper `ApplyFrameStyle(bool visible)` centralizes the style/geometry change; 23 + a `bool m_captionVisible` member tracks the current state and makes the call idempotent 24 + (no-op when the requested state already applies). 25 + 26 + ## Geometry — display stays put 27 + 28 + When the frame toggles, the **client rectangle keeps its exact screen position**: the 29 + caption grows upward when it appears and retracts when it disappears; the displayed 30 + number never moves. 31 + 32 + - On toggle: take the current client rect in screen coordinates 33 + (`GetClientRect` + `ClientToScreen`), compute the new window rect for the new style 34 + with `AdjustWindowRectEx`, and pass position + size to the same `SetWindowPos` call 35 + that applies `SWP_FRAMECHANGED`. 36 + - Safety clamp: if growing upward would push the window top above the work area top, 37 + clamp to the work area (in practice the window sits near the taskbar, so this is a 38 + guard, not an expected path). 39 + 40 + ## Position persistence — canonical form 41 + 42 + `OnExitSizeMove` currently saves the window's top-left corner, which now depends on 43 + whether the caption is present (± caption height). To keep the restored position stable 44 + across restarts regardless of the frame state at save time: 45 + 46 + - **Save** the position in canonical form: the top-left of the **chromeless** window 47 + (equal to the client origin, since a plain `WS_POPUP` window has no frame offset). 48 + - **Restore** (`PlaceInitial`) converts the canonical point back to the window origin for 49 + the style in effect at that moment (via `AdjustWindowRectEx`): since the window is 50 + created with the caption styles, its top-left is placed one caption height above the 51 + saved client origin, so the client lands exactly where it was saved. 52 + - Registry value name and type are unchanged (`REG_DWORD` pair via `Settings`); existing 53 + saved positions are reinterpreted with at most a caption-height offset once, then 54 + stay stable. 55 + 56 + ## Accepted side effects 57 + 58 + - Opening the tray menu or the About dialog deactivates the calculator, so the caption 59 + disappears while they are open. Consistent with the rule ("active = framed"); no 60 + functional impact. 61 + - The frame appears/disappears instantly (no animation); with DWM on Windows 11 the 62 + repaint is near-imperceptible. 63 + 64 + ## Components touched 65 + 66 + `CalculatorWindow.h` / `CalculatorWindow.cpp` only: 67 + 68 + - `MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)` + `OnActivate` implementation. 69 + - Private `void ApplyFrameStyle(bool visible)` + `bool m_captionVisible`. 70 + - Canonical-position adjustment in `OnExitSizeMove` and `PlaceInitial`. 71 + 72 + Engine (`calc`), `Settings` storage format, `App.cpp`, tray icon, and packaging are all 73 + untouched. 74 + 75 + ## Testing 76 + 77 + - **Engine regression:** `tests\build-and-run.cmd` still passes 16/16 (feature is UI-only). 78 + - **Manual verification checklist:** 79 + 1. Show from tray → window appears with caption + X. 80 + 2. Click another app → caption disappears; the number display does not move. 81 + 3. Click the calculator → caption reappears; display does not move. 82 + 4. X → hides to tray (existing `WM_CLOSE` behavior). 83 + 5. Drag by caption and by body both work; position persists. 84 + 6. Restart the app → window reappears at the same visual position (no drift). 85 + 86 + ## Out of scope (YAGNI) 87 + 88 + - Animated caption transitions. 89 + - Custom-drawn caption (approach B — fallback if the native toggle disappoints). 90 + - Any change to sizing, fonts, or engine behavior.