diff --git a/android/app/src/main/java/com/remotedisplay/player/player/PipOverlay.kt b/android/app/src/main/java/com/remotedisplay/player/player/PipOverlay.kt index 39d06d0..3e09317 100644 --- a/android/app/src/main/java/com/remotedisplay/player/player/PipOverlay.kt +++ b/android/app/src/main/java/com/remotedisplay/player/player/PipOverlay.kt @@ -68,6 +68,13 @@ class PipOverlay( val w = p.optInt("width", 480).coerceIn(1, dm.widthPixels * 4) val h = p.optInt("height", 360).coerceIn(1, dm.heightPixels * 4) + // Set the slot token BEFORE building media: loadImageInto captures `current` as + // its drop-if-replaced token, and its decode finishes on a background thread that + // posts back AFTER show() returns. If current were still null here (teardown + // clears it), that guard would always fail and the decoded bitmap would be + // dropped — i.e. image PiPs never painted. (#109 follow-up.) + current = p.optString("pip_id", "(anon)") + val box = LinearLayout(context).apply { orientation = LinearLayout.VERTICAL clipToOutline = true @@ -129,7 +136,7 @@ class PipOverlay( pipLayout.addView(box, lp) pipLayout.visibility = View.VISIBLE - current = p.optString("pip_id", "(anon)") + // current was set above (before media build) so loadImageInto's token matches. // #109 fix (1)/(3): the pip layer is a top-level view above the WebView (reparented // to the window content in MainActivity), but make sure it composites last and is diff --git a/docs/109-android-pip-visibility.md b/docs/109-android-pip-visibility.md index 8c54501..bea21d2 100644 --- a/docs/109-android-pip-visibility.md +++ b/docs/109-android-pip-visibility.md @@ -137,6 +137,22 @@ reproduce the Fire TV / Android TV hardware-overlay punch-through that is the strongest form of cause (1). That still needs the real signage device — use the `pipDebug` magenta box there to confirm. +### Follow-up bug found in emulator testing: image PiPs never painted the image + +Verifying an **image** PiP (a QR PNG) surfaced a separate, pre-existing defect +(present on `main`, unrelated to the occlusion reparent): the image area was +always blank — only the box background + title showed. Root cause in +`PipOverlay.show()`: `teardown()` clears `current` to null, then `loadImageInto` +captured `token = current` (null) as its drop-if-replaced guard, but `current` +was only set to the new `pip_id` *after* the media was built. The decode finishes +on a background thread and posts back **after** `show()` returns — so the guard +`token != current` (null ≠ pip_id) was always true and **every decoded bitmap was +dropped**. (Web PiPs and the box/title were unaffected, which masked it.) + +Fix: set `current = pip_id` **before** building the media (so `loadImageInto`'s +token matches). Confirmed on the emulator — the QR now renders in the PiP box +over both a static image and live YouTube. + ## If the magenta box is STILL hidden over YouTube on the test device Then it is the stronger form of cause (1): the WebView places its video on a