diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-10-22 21:06:44 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-10-22 21:06:44 +0000 |
| commit | 9bf135585885b043a05f3e74197314bdb4633c67 (patch) | |
| tree | 02b76001144b26d8711a6c3f47c4a01bfbcc97cb /app/src/main/java/org | |
| parent | 4fa99073761bbedcdc2bce45a666399bf4b425aa (diff) | |
Hardware-accelerate the video dialog's own window
Peter, on the referrer build: the player "plays and shows controls,
with a white screen instead of video. The scrubber thumbnails pop up,
but the main playback is blank white." His screenshot shows YouTube's
title, gear, play button, timecode and progress bar all drawn
correctly over a blank area.
That narrows it a long way. Everything the page renders -- chrome,
gradients, the storyboard images behind the scrubber -- composites
fine, so the renderer is healthy and the embed is right. The one thing
missing is the only thing that does not come from the page: video is
composited from a separate surface, and that needs the window it sits
in to be hardware accelerated.
The player is a Dialog, which is its own Window. The activity declares
android:hardwareAccelerated, but that does not carry to a Window a
dialog creates for itself, so the flag is now set on it explicitly.
No new logic, so nothing new to unit-test: the URL and referrer this
loads are unchanged and still covered by YouTubeLinksTest. It is a
property of the window the existing WebView lives in.
Unverified here, and this emulator cannot settle it: it has no working
video path at all in a WebView. It hard-crashed the AVD twice on a
plain <video>, and with software decoding forced it survives but
renders a broken-media placeholder rather than a picture. Everything
up to display is confirmed on-device; display is not.
If the picture is still missing, this rules the window out and the
remaining suspect is the surface itself, which means taking the player
out of a floating window entirely.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
Diffstat (limited to 'app/src/main/java/org')
| -rw-r--r-- | app/src/main/java/org/terst/feedreader/ui/ReaderWebView.kt | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/app/src/main/java/org/terst/feedreader/ui/ReaderWebView.kt b/app/src/main/java/org/terst/feedreader/ui/ReaderWebView.kt index 1bc1315..3af460a 100644 --- a/app/src/main/java/org/terst/feedreader/ui/ReaderWebView.kt +++ b/app/src/main/java/org/terst/feedreader/ui/ReaderWebView.kt @@ -7,6 +7,7 @@ import android.view.ScaleGestureDetector import android.view.View import android.webkit.WebChromeClient import android.webkit.WebResourceRequest +import android.view.WindowManager import android.webkit.WebView import android.webkit.WebViewClient import androidx.compose.foundation.layout.Column @@ -21,8 +22,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.ui.platform.LocalView import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties +import androidx.compose.ui.window.DialogWindowProvider import org.terst.feedreader.data.DEFAULT_READER_FONT_SIZE_PX import org.terst.feedreader.data.UNZOOMED_TEXT_ZOOM_PERCENT import org.terst.feedreader.data.pinchZoomFontSizePx @@ -343,6 +347,22 @@ fun YouTubePlayerDialog(videoId: String, onDismiss: () -> Unit) { // narrow, sitting off-center). Opt out so fillMaxWidth below means the real // screen width, with our own padding controlling the margin instead. Dialog(onDismissRequest = onDismiss, properties = DialogProperties(usePlatformDefaultWidth = false)) { + // A dialog is its own Window, and video is the one kind of web content that needs the + // window it sits in to be hardware accelerated: it is composited from a separate surface + // rather than drawn into the page like everything else. Without the flag, the page + // renders perfectly and only the video is missing -- reported live as the player's + // controls, title and scrubber thumbnails all appearing over a blank area where the + // picture should be, with the audio playing. + // + // The activity has android:hardwareAccelerated, but that does not carry to a Window the + // dialog creates for itself, so it is set here explicitly. + val dialogWindow = (LocalView.current.parent as? DialogWindowProvider)?.window + LaunchedEffect(dialogWindow) { + dialogWindow?.setFlags( + WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, + WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, + ) + } AndroidView( modifier = Modifier.fillMaxWidth().padding(16.dp).aspectRatio(16f / 9f), factory = { ctx -> |
