From 255d8c06003518d1270b391217c9c2313046730b Mon Sep 17 00:00:00 2001 From: ScreenTinker Date: Fri, 19 Jun 2026 14:45:14 -0500 Subject: [PATCH] feat(#109): implement PiP close_button on Android (was a documented no-op) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The server forwarded close_button (routes/pip.js) and it's in openapi.yaml, but no player rendered it — Tizen deferred "close-button focus" as non-MVP, the web player has none, and Android's PipOverlay never read the flag. So the documented field did nothing on any device. Implement it on Android: when close_button:true, a tappable ✕ floats at the box's top-right in a FrameLayout wrapper that is a SIBLING of the box — so it isn't clipped by the box outline or dimmed by the overlay opacity. Tapping it clears THIS overlay (id-matched via the captured token). Only the ✕ is clickable; the rest of the full-screen pipLayout stays touch-transparent, so taps elsewhere fall through to the playing content (no input regression). Verified on the emulator over live YouTube: the ✕ renders at the corner, and tapping it removes the overlay while the video keeps playing. Parity note: web/Tizen players still don't implement close_button; D-pad focus of the ✕ on non-touch TV hardware is intentionally not wired (MVP = touch/pointer, matching the Tizen focus deferral). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../remotedisplay/player/player/PipOverlay.kt | 31 ++++++++++++++++++- docs/109-android-pip-visibility.md | 11 +++++++ 2 files changed, 41 insertions(+), 1 deletion(-) 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 3e09317..309636c 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 @@ -134,7 +134,36 @@ class PipOverlay( else -> { lp.rightMargin = mx; lp.topMargin = my; Gravity.TOP or Gravity.END } // top-right } - pipLayout.addView(box, lp) + // Optional close button (close_button:true). Render a tappable ✕ floating at the + // box's top-right corner; tapping clears THIS overlay (id-matched). It lives in a + // FrameLayout wrapper that is a SIBLING of the box — so it isn't clipped by the + // box outline and isn't dimmed by the box's opacity. Only the button is clickable; + // the rest of pipLayout stays touch-transparent so taps fall through to content. + val attach: View = if (p.optBoolean("close_button", false)) { + val token = current + FrameLayout(context).apply { + addView(box, FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)) + val d = dm.density + addView(TextView(context).apply { + text = "✕" // ✕ + setTextColor(Color.WHITE) + textSize = 16f + gravity = Gravity.CENTER + background = GradientDrawable().apply { + shape = GradientDrawable.OVAL; setColor(Color.argb(150, 0, 0, 0)) + } + isClickable = true + contentDescription = "Close" + setOnClickListener { clear(token) } + }, FrameLayout.LayoutParams((28 * d).toInt(), (28 * d).toInt()).apply { + gravity = Gravity.TOP or Gravity.END + val m = (6 * d).toInt(); topMargin = m; rightMargin = m + }) + } + } else box + + pipLayout.addView(attach, lp) pipLayout.visibility = View.VISIBLE // current was set above (before media build) so loadImageInto's token matches. diff --git a/docs/109-android-pip-visibility.md b/docs/109-android-pip-visibility.md index fbf25c3..4bc8b13 100644 --- a/docs/109-android-pip-visibility.md +++ b/docs/109-android-pip-visibility.md @@ -162,6 +162,17 @@ over both a static image and live YouTube. needed — web PiPs never went through the broken image path. - title + `background_color` box — paints above the video (the original cause-1 fix). +- **`close_button: true`** — the server already forwarded this flag + (`routes/pip.js`) and it's in `openapi.yaml`, but no player rendered it (Tizen + deferred "close-button focus" as non-MVP; the web player has none). Implemented + on Android: a tappable ✕ floats at the box's top-right (a sibling of the box, so + it isn't clipped by the outline or dimmed by `opacity`) and clears THIS overlay + (id-matched) on tap. Only the ✕ is clickable; the rest of the full-screen + `pipLayout` stays touch-transparent so taps fall through to the content. Verified + on the emulator — tapping it removed the overlay and the video kept playing. + Parity note: the web/Tizen players still don't implement `close_button`; D-pad + focus of the ✕ on non-touch TV hardware is intentionally not wired (MVP = + touch/pointer only, matching the Tizen focus deferral). ## If the magenta box is STILL hidden over YouTube on the test device