From fc5fcbb0db267c07f292a6b7fa628dbc65a9eb97 Mon Sep 17 00:00:00 2001 From: edde746 <86283021+edde746@users.noreply.github.com> Date: Wed, 25 Feb 2026 16:13:53 +0100 Subject: [PATCH] fix: google tv virtual remote dpad --- .../kotlin/com/edde746/plezy/MainActivity.kt | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/android/app/src/main/kotlin/com/edde746/plezy/MainActivity.kt b/android/app/src/main/kotlin/com/edde746/plezy/MainActivity.kt index 7ea9bc96..c23b5ff7 100644 --- a/android/app/src/main/kotlin/com/edde746/plezy/MainActivity.kt +++ b/android/app/src/main/kotlin/com/edde746/plezy/MainActivity.kt @@ -9,6 +9,8 @@ import android.app.PictureInPictureParams import android.content.Context import android.content.res.Configuration import android.util.Rational +import android.view.KeyEvent +import android.view.ViewGroup import androidx.core.content.FileProvider import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.RenderMode @@ -25,6 +27,7 @@ class MainActivity : FlutterActivity() { private val PIP_CHANNEL = "app.plezy/pip" private val EXTERNAL_PLAYER_CHANNEL = "app.plezy/external_player" private var watchNextPlugin: WatchNextPlugin? = null + private var cachedFlutterView: android.view.View? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -39,6 +42,37 @@ class MainActivity : FlutterActivity() { handleWatchNextIntent(intent) } + override fun dispatchKeyEvent(event: KeyEvent): Boolean { + // Ensure FlutterView has focus for DPAD events so they reach Flutter's + // key event system. Without this, Android's native focus navigation can + // consume DPAD direction events (especially from the Google TV virtual + // remote) before they reach Flutter. + when (event.keyCode) { + KeyEvent.KEYCODE_DPAD_UP, + KeyEvent.KEYCODE_DPAD_DOWN, + KeyEvent.KEYCODE_DPAD_LEFT, + KeyEvent.KEYCODE_DPAD_RIGHT, + KeyEvent.KEYCODE_DPAD_CENTER -> { + val fv = cachedFlutterView ?: findFlutterView(window.decorView)?.also { cachedFlutterView = it } + if (fv != null && !fv.hasFocus()) { + fv.requestFocus() + } + } + } + return super.dispatchKeyEvent(event) + } + + private fun findFlutterView(view: android.view.View): android.view.View? { + if (view.javaClass.name.contains("FlutterView")) return view + if (view is ViewGroup) { + for (i in 0 until view.childCount) { + val found = findFlutterView(view.getChildAt(i)) + if (found != null) return found + } + } + return null + } + override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) // Handle Watch Next deep link when app is already running