## Title Windows overlay renders as large opaque window; background not transparent; sprite shows magenta matte; window is not pet-sized. ## Severity P0 ## Environment - OS: Windows - App: `sprimo-app` frontend runtime - Reported on: 2026-02-12 - Evidence screenshot: `issues/screenshots/issue1.png` ## Summary Current runtime output violates overlay requirements: - opaque dark background is visible behind the pet - sprite keeps magenta matte background - window footprint is larger than expected pet footprint ## Reproduction Steps 1. Launch the frontend executable on Windows. 2. Observe the initial overlay window at startup. ## Expected Result - Window appears borderless and transparent. - Only pet pixels are visible. - Sprite background uses alpha (no magenta matte). - Window size is constrained to sprite bounds plus small margin. ## Actual Result - Window background appears opaque dark gray. - Sprite contains magenta matte rectangle. - Window appears larger than a pet-sized overlay. ## Root Cause Analysis Current findings from repository inspection: - The default sprite is RGB (`Format24bppRgb`) and depends on runtime chroma-key conversion. - Window and clear-color transparency settings were configured, but layered-window attributes were not explicitly applied during window-handle attachment. - `SetTransform.x/y` was applied to both window coordinates and sprite world translation, causing visible offset within the client area and making the window appear larger than pet bounds. - Chroma-key conversion used exact color matching only, which is fragile for near-magenta pixels. ## Fix Plan 1. Reproduce with runtime logs enabled and capture an explicit before screenshot. 2. Validate chroma-key conversion path against loaded texture content. 3. Validate Windows composition and layered style behavior with attached HWND. 4. Apply targeted renderer/platform fixes. 5. Capture after screenshot and rerun verification checklist. ## Implementation Notes Implemented code changes: 1. `crates/sprimo-app/src/main.rs` - Sprite now spawns centered at `(0, 0, 0)`; persisted `x/y` remains window placement only. - `SetTransform.x/y` no longer mutates sprite world translation. - Chroma-key conversion now: - uses tolerance matching around `#FF00FF`, - preserves non-key alpha values, - forces chroma-key when an alpha-bearing image is fully opaque but key-colored in large areas. - Added regression tests for tolerant keying, alpha preservation, and force-key detection. 2. `crates/sprimo-platform/src/lib.rs` - Windows adapter now applies layered style + `SetLayeredWindowAttributes` when window handle is attached. - Click-through toggles now reuse the layered-style application path to keep transparency setup stable. 3. Additional Windows window configuration hardening (`crates/sprimo-app/src/main.rs`) - Primary window now explicitly sets `composite_alpha_mode = PreMultiplied`. - Primary window now starts with a small explicit resolution (`544x544`) to avoid large default client area before runtime pack sizing applies. 4. Follow-up rollback + keying adjustment after new screenshot review - Removed explicit `composite_alpha_mode` override to return control to Bevy/WGPU default. - Removed forced layered alpha attributes from Windows adapter to avoid opaque black composition. - Increased chroma-key tolerance to better remove magenta fringe around sprite edges. 5. Windows compositor fallback for persistent opaque background - Added Windows color-key transparency fallback: - sets `WS_EX_LAYERED` on attached HWND - applies `SetLayeredWindowAttributes(..., LWA_COLORKEY)` with key color `#01FE03` - Switched Windows clear color to the same key color so non-sprite background can be cut out by the OS compositor even when swapchain alpha blending is not honored. 6. Windows mode switch to avoid swapchain-alpha path conflicts - On Windows, primary window now disables Bevy transparent swapchain mode (`transparent = false`) and relies on layered color-key composition only. - Non-Windows behavior remains unchanged (`transparent = true` + alpha clear). 7. DWM composition strategy after transparent color-key regression - Removed Windows color-key compositor strategy (it hid sprite on tested path). - Added DWM composition setup on HWND attach: - `DwmIsCompositionEnabled` - `DwmExtendFrameIntoClientArea` with full glass margins - `DwmEnableBlurBehindWindow` - Restored Windows render path to alpha clear + `transparent = true`. 8. Renderer alpha mode correction pass - Removed DWM composition overrides to avoid conflicting transparency mechanisms. - Forced Bevy window `CompositeAlphaMode::PostMultiplied` on Windows to align with transparent swapchain blending expectations. - Kept native alpha clear color render path. 9. Hardware-safe Windows fallback after runtime panic - Runtime log showed wgpu surface supports alpha modes `[Opaque]` only on this machine. - Switched Windows path to opaque swapchain (`transparent = false`) plus Win32 layered color-key transparency (`WS_EX_LAYERED + LWA_COLORKEY`). - Aligned Windows clear color to the same key color (`#FF00FF`) and removed crash-causing post-multiplied alpha request. 10. Color-key visibility fix for opaque presentation path - In Windows colorkey mode, keyed pixels are now emitted with alpha `255` (not `0`) so key RGB survives the presentation path and can be matched by `LWA_COLORKEY`. - Updated chroma-key unit tests for platform-specific keyed-alpha expectations. ## Verification ### Commands Run - [x] `cargo check --workspace` - [x] `cargo test --workspace` - [x] `just qa-validate` ### Screenshots - Before: - `issues/screenshots/issue1.png` (legacy baseline) - After: - pending (capture required before `Verification Passed`/`Closed`) ### Command Output Summary - `cargo check --workspace`: pass - `cargo test --workspace`: pass - `just qa-validate`: pass - `cargo check -p sprimo-app -p sprimo-platform`: pass - `cargo test -p sprimo-app`: pass - dist runtime binary refreshed from latest debug build: done - Follow-up rebuild + dist binary refresh after screenshot-guided rollback: done - Windows color-key fallback build + dist binary refresh: done - Windows transparent-mode switch build + dist binary refresh: done - DWM composition fallback build + dist binary refresh: done - Post-multiplied alpha mode build + dist binary refresh: done - Opaque+colorkey fallback build + dist binary refresh: done - Keyed-alpha colorkey build + dist binary refresh: done ### Result - Current Status: `Fix Implemented` - Notes: code fix implemented and validated by tests; runtime after screenshot still pending. ## Status History - `2026-02-12 20:15` - reporter - `Reported` - initial bug report with screenshot. - `2026-02-12 20:35` - codex - `Triaged` - validated screenshot symptoms and repository context. - `2026-02-12 20:50` - codex - `Reported` - lifecycle file normalized; fix not yet applied. - `2026-02-12 21:20` - codex - `In Progress` - implemented window/transparency/chroma-key fixes. - `2026-02-12 21:30` - codex - `Fix Implemented` - workspace checks/tests and QA validator passed. - `2026-02-12 22:10` - codex - `In Progress` - added explicit Windows composite alpha mode and startup resolution. - `2026-02-12 22:15` - codex - `Fix Implemented` - app/platform targeted checks passed and dist binary refreshed. - `2026-02-12 22:35` - codex - `In Progress` - analyzed new after screenshot showing black opaque background and magenta fringe. - `2026-02-12 22:45` - codex - `Fix Implemented` - rolled back layered alpha/composite override and tightened chroma-key edge removal. - `2026-02-12 22:55` - codex - `In Progress` - analyzed latest screenshot still showing opaque black background. - `2026-02-12 23:05` - codex - `Fix Implemented` - added Windows color-key compositor fallback and aligned clear color. - `2026-02-12 23:15` - codex - `In Progress` - analyzed latest screenshot showing color-key path still ineffective with swapchain transparency. - `2026-02-12 23:22` - codex - `Fix Implemented` - switched Windows to non-transparent swapchain mode and kept layered color-key compositor path. - `2026-02-12 23:30` - codex - `In Progress` - analyzed screenshot where window became effectively empty/over-transparent. - `2026-02-12 23:42` - codex - `Fix Implemented` - removed color-key strategy and switched to DWM composition setup. - `2026-02-12 23:55` - codex - `In Progress` - analyzed screenshot where black background persisted under DWM strategy. - `2026-02-13 00:05` - codex - `Fix Implemented` - removed DWM overrides and forced post-multiplied alpha mode on Windows. - `2026-02-13 00:35` - codex - `In Progress` - reproduced startup panic from runtime log (`alpha modes: [Opaque]`). - `2026-02-13 00:45` - codex - `Fix Implemented` - replaced transparent swapchain path with Windows opaque+colorkey fallback; startup panic no longer reproduced. - `2026-02-13 00:55` - codex - `In Progress` - analyzed persistent black background under opaque+colorkey path. - `2026-02-13 01:05` - codex - `Fix Implemented` - changed keyed-pixel alpha to 255 in Windows colorkey mode and updated tests. ## Closure - Current Status: `Fix Implemented` - Close Date: - Owner: - Linked PR/commit: ## Original Report (2026-02-12, normalized from legacy encoding) ### Bug Report / Debugging Issue (Windows) **Title:** Windows overlay renders as large opaque window; background not transparent; sprite shows magenta matte; window not pet-sized. **Severity:** P0 (core functionality broken; not an overlay pet) **Component:** Frontend (Bevy renderer / windowing / transparency pipeline) **Summary:** The app shows a large opaque dark-gray window with a character sprite on top. The sprite includes a magenta rectangular matte. This violates transparent borderless overlay requirements. **Evidence from screenshot (`issues/screenshots/issue1.png`):** 1. Opaque background fills most of the window. 2. Window appears much larger than pet-only bounds. 3. Magenta matte appears behind the sprite. **Expected:** - Borderless transparent overlay. - Pet-only visible pixels. - No magenta matte. **Actual:** - Opaque dark window. - Magenta sprite background. - Regular app-window behavior. **Likely causes in original report:** 1. Missing OS-level transparent/layered window behavior. 2. Non-transparent clear color or camera clear. 3. Sprite asset alpha issue (RGB or wrong export). 4. Missing chroma-key discard path. 5. Missing pet-sized window sizing logic.