From 512046e300c8ff1d8a336cb71b34134ed6c6c8ae Mon Sep 17 00:00:00 2001 From: Alexander-- Date: Sat, 14 Mar 2020 13:22:02 +0659 Subject: [PATCH] Fix navigating to action bar buttons on API 28 Keyboard focus clusters prevent that from working, so we simply remove all focus clusters. While they are generally a good idea, focus clusters were created with Chrome OS and it's keyboard-driven interface in mind - there is no documented way to move focus between clusters using only IR remote. As such, there are no negative consequences to disabling them on Android TV. --- .../newpipe/views/FocusOverlayView.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/app/src/main/java/org/schabi/newpipe/views/FocusOverlayView.java b/app/src/main/java/org/schabi/newpipe/views/FocusOverlayView.java index b0b9cc421..582da38fb 100644 --- a/app/src/main/java/org/schabi/newpipe/views/FocusOverlayView.java +++ b/app/src/main/java/org/schabi/newpipe/views/FocusOverlayView.java @@ -27,6 +27,7 @@ import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -37,6 +38,7 @@ import android.view.ViewTreeObserver; import android.view.Window; import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; import androidx.appcompat.view.WindowCallbackWrapper; import org.schabi.newpipe.R; @@ -212,6 +214,8 @@ public final class FocusOverlayView extends Drawable implements ViewGroup decor = (ViewGroup) window.getDecorView(); decor.getOverlay().add(overlay); + fixFocusHierarchy(decor); + ViewTreeObserver observer = decor.getViewTreeObserver(); observer.addOnScrollChangedListener(overlay); observer.addOnGlobalFocusChangeListener(overlay); @@ -245,4 +249,42 @@ public final class FocusOverlayView extends Drawable implements animator.sendEmptyMessageDelayed(0, 100); } + + private static void fixFocusHierarchy(View decor) { + // During Android 8 development some dumb ass decided, that action bar has to be a keyboard focus cluster. + // Unfortunately, keyboard clusters do not work for primary auditory of key navigation — Android TV users + // (Android TV remotes do not have keyboard META key for moving between clusters). We have to fix this + // unfortunate accident. While we are at it, let's deal with touchscreenBlocksFocus too. + + if (Build.VERSION.SDK_INT < 26) { + return; + } + + if (!(decor instanceof ViewGroup)) { + return; + } + + clearFocusObstacles((ViewGroup) decor); + } + + @RequiresApi(api = 26) + private static void clearFocusObstacles(ViewGroup viewGroup) { + viewGroup.setTouchscreenBlocksFocus(false); + + if (viewGroup.isKeyboardNavigationCluster()) { + viewGroup.setKeyboardNavigationCluster(false); + + return; // clusters aren't supposed to nest + } + + int childCount = viewGroup.getChildCount(); + + for (int i = 0; i < childCount; ++i) { + View view = viewGroup.getChildAt(i); + + if (view instanceof ViewGroup) { + clearFocusObstacles((ViewGroup) view); + } + } + } }