Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b53d8d63 authored by Pat Manning's avatar Pat Manning
Browse files

Fix focus navigation of All Apps when using external keyboard.

- All apps icons do not show the focus rectangle when focused as mIconFocusListener is null in BaseAllAppsAdapter when onCreateViewHolder is called.
- All apps recyclerview does not scroll down when focus goes from top to bottom of list, as AllAppsToastUiDelegate calls hideKeyboard which clears focus.
- Focus goes behind AllApps into hotseat, so update hotseat setDescendantFocusability.

Flag: NONE
Fix: 296844600
Test: TaplKeyboardFocusTest
Change-Id: I65f6fbb6f4df0be4b4ff922dda267d27da16effe
parent 24231d99
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -101,9 +101,15 @@ public class ExtendedEditText extends EditText {
    }

    public void hideKeyboard() {
        hideKeyboard(/* clearFocus= */ true);
    }

    public void hideKeyboard(boolean clearFocus) {
        ActivityContext.lookupContext(getContext()).hideKeyboard();
        if (clearFocus) {
            clearFocus();
        }
    }

    protected void onKeyboardShown() {
        ActivityContext.lookupContext(getContext()).getStatsLogManager()
+3 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import static com.android.launcher3.states.StateAnimationConfig.SKIP_SCRIM;
import android.animation.ValueAnimator;
import android.util.FloatProperty;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;

import com.android.launcher3.LauncherState.PageAlphaProvider;
@@ -164,6 +165,8 @@ public class WorkspaceStateTransitionAnimation {
                state.hasFlag(FLAG_HOTSEAT_INACCESSIBLE)
                        ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
                        : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
        hotseat.setDescendantFocusability(state.hasFlag(FLAG_HOTSEAT_INACCESSIBLE)
                ? ViewGroup.FOCUS_BLOCK_DESCENDANTS : ViewGroup.FOCUS_BEFORE_DESCENDANTS);

        Interpolator translationInterpolator =
                config.getInterpolator(ANIM_WORKSPACE_TRANSLATE, ZOOM_OUT);
+1 −1
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;

import com.android.launcher3.BubbleTextView;
import com.android.launcher3.Flags;
import com.android.launcher3.R;
import com.android.launcher3.allapps.search.SearchAdapterProvider;
import com.android.launcher3.config.FeatureFlags;
@@ -213,6 +212,7 @@ public abstract class BaseAllAppsAdapter<T extends Context & ActivityContext> ex
                BubbleTextView icon = (BubbleTextView) holder.itemView;
                icon.reset();
                icon.applyFromApplicationInfo(adapterItem.itemInfo);
                icon.setOnFocusChangeListener(mIconFocusListener);
                break;
            }
            case VIEW_TYPE_EMPTY_SEARCH: {
+79 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.launcher3.allapps;

import static com.android.launcher3.ui.TaplTestsLauncher3.initialize;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import android.view.KeyEvent;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;

import com.android.launcher3.LauncherState;
import com.android.launcher3.tapl.HomeAllApps;
import com.android.launcher3.ui.AbstractLauncherUiTest;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class TaplKeyboardFocusTest extends AbstractLauncherUiTest {

    @Before
    public void setUp() throws Exception {
        super.setUp();
        initialize(this);
    }

    @Test
    public void testAllAppsFocusApp() {
        final HomeAllApps allApps = mLauncher.goHome().switchToAllApps();
        assertTrue("Launcher internal state is not All Apps",
                isInState(() -> LauncherState.ALL_APPS));
        allApps.freeze();
        try {
            mLauncher.pressAndHoldKeyCode(KeyEvent.KEYCODE_DPAD_DOWN, 0);
            executeOnLauncher(launcher -> assertNotNull("No focused child.",
                    launcher.getAppsView().getActiveRecyclerView().getApps().getFocusedChild()));
        } finally {
            allApps.unfreeze();
        }
    }

    @Test
    public void testAllAppsExitSearchAndFocusApp() {
        final HomeAllApps allApps = mLauncher.goHome().switchToAllApps();
        assertTrue("Launcher internal state is not All Apps",
                isInState(() -> LauncherState.ALL_APPS));
        allApps.freeze();
        try {
            executeOnLauncher(launcher -> launcher.getAppsView().getSearchView().requestFocus());
            waitForLauncherCondition("Search view does not have focus.",
                    launcher -> launcher.getAppsView().getSearchView().hasFocus());

            mLauncher.pressAndHoldKeyCode(KeyEvent.KEYCODE_DPAD_DOWN, 0);
            executeOnLauncher(launcher -> assertNotNull("No focused child.",
                    launcher.getAppsView().getActiveRecyclerView().getApps().getFocusedChild()));
        } finally {
            allApps.unfreeze();
        }
    }
}