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

Commit 946a2493 authored by Helen Cheuk's avatar Helen Cheuk Committed by Android (Google) Code Review
Browse files

Merge "Not show hover border on select mode" into main

parents 0f395e8a b4cda2ad
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -238,6 +238,12 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
        if (toState == MODAL_TASK) {
            setOverviewSelectEnabled(true);
        }

        // Set border after select mode changes to avoid showing border during state transition
        if (!toState.overviewUi() || toState == MODAL_TASK) {
            setTaskBorderEnabled(false);
        }

        setFreezeViewVisibility(true);
    }

@@ -253,6 +259,11 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
        if (finalState != MODAL_TASK) {
            setOverviewSelectEnabled(false);
        }

        if (finalState.overviewUi() && finalState != MODAL_TASK) {
            setTaskBorderEnabled(true);
        }

        if (finalState != OVERVIEW_SPLIT_SELECT) {
            if (FeatureFlags.enableSplitContextually()) {
                mSplitSelectStateController.resetState();
+10 −0
Original line number Diff line number Diff line
@@ -145,6 +145,12 @@ public class LauncherRecentsView extends RecentsView<QuickstepLauncher, Launcher
        if (toState == OVERVIEW_MODAL_TASK) {
            setOverviewSelectEnabled(true);
        }

        // Set border after select mode changes to avoid showing border during state transition
        if (!toState.overviewUi || toState == OVERVIEW_MODAL_TASK) {
            setTaskBorderEnabled(false);
        }

        setFreezeViewVisibility(true);
        if (mActivity.getDesktopVisibilityController() != null) {
            mActivity.getDesktopVisibilityController().onLauncherStateChanged(toState);
@@ -165,6 +171,10 @@ public class LauncherRecentsView extends RecentsView<QuickstepLauncher, Launcher
            setOverviewSelectEnabled(false);
        }

        if (finalState.overviewUi && finalState != OVERVIEW_MODAL_TASK) {
            setTaskBorderEnabled(true);
        }

        if (isOverlayEnabled) {
            runActionOnRemoteHandles(remoteTargetHandle ->
                    remoteTargetHandle.getTaskViewSimulator().setDrawsBelowRecents(true));
+11 −0
Original line number Diff line number Diff line
@@ -1409,6 +1409,17 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        updateLocusId();
    }

    /**
     * Enable or disable showing border on hover and focus change on task views
     */
    public void setTaskBorderEnabled(boolean enabled) {
        int taskCount = getTaskViewCount();
        for (int i = 0; i < taskCount; i++) {
            TaskView taskView = requireTaskViewAt(i);
            taskView.setBorderEnabled(enabled);
        }
    }

    /**
     * Whether the Clear All button is hidden or fully visible. Used to determine if center
     * displayed page is a task or the Clear All button.
+66 −31
Original line number Diff line number Diff line
@@ -408,6 +408,7 @@ public class TaskView extends FrameLayout implements Reusable {
            new TaskIdAttributeContainer[2];

    private boolean mShowScreenshot;
    private boolean mBorderEnabled;

    // The current background requests to load the task thumbnail and icon
    @Nullable
@@ -439,8 +440,15 @@ public class TaskView extends FrameLayout implements Reusable {
        this(context, attrs, defStyleAttr, 0);
    }

    public TaskView(
            Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    public TaskView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
            int defStyleRes) {
        this(context, attrs, defStyleAttr, defStyleRes, null, null);
    }

    @VisibleForTesting
    public TaskView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
            int defStyleRes, BorderAnimator focusBorderAnimator,
            BorderAnimator hoverBorderAnimator) {
        super(context, attrs, defStyleAttr, defStyleRes);
        mActivity = StatefulActivity.fromContext(context);
        setOnClickListener(this::onClick);
@@ -457,6 +465,9 @@ public class TaskView extends FrameLayout implements Reusable {
        TypedArray styledAttrs = context.obtainStyledAttributes(
                attrs, R.styleable.TaskView, defStyleAttr, defStyleRes);

        if (focusBorderAnimator != null) {
            mFocusBorderAnimator = focusBorderAnimator;
        } else {
            mFocusBorderAnimator = keyboardFocusHighlightEnabled
                    ? BorderAnimator.createSimpleBorderAnimator(
                    /* borderRadiusPx= */ (int) mCurrentFullscreenParams.mCornerRadius,
@@ -467,7 +478,11 @@ public class TaskView extends FrameLayout implements Reusable {
                    /* borderColor= */ styledAttrs.getColor(
                            R.styleable.TaskView_focusBorderColor, DEFAULT_BORDER_COLOR))
                    : null;
        }

        if (hoverBorderAnimator != null) {
            mHoverBorderAnimator = hoverBorderAnimator;
        } else {
            mHoverBorderAnimator = cursorHoverStatesEnabled
                    ? BorderAnimator.createSimpleBorderAnimator(
                    /* borderRadiusPx= */ (int) mCurrentFullscreenParams.mCornerRadius,
@@ -478,7 +493,7 @@ public class TaskView extends FrameLayout implements Reusable {
                    /* borderColor= */ styledAttrs.getColor(
                            R.styleable.TaskView_hoverBorderColor, DEFAULT_BORDER_COLOR))
                    : null;

        }
        styledAttrs.recycle();
    }

@@ -538,24 +553,25 @@ public class TaskView extends FrameLayout implements Reusable {
    }

    @Override
    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
    @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
    public void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
        if (mFocusBorderAnimator != null) {
        if (mFocusBorderAnimator != null && mBorderEnabled) {
            mFocusBorderAnimator.setBorderVisibility(gainFocus, /* animated= */ true);
        }
    }

    @Override
    public boolean onHoverEvent(MotionEvent event) {
        if (mHoverBorderAnimator != null) {
        if (mHoverBorderAnimator != null && mBorderEnabled) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_HOVER_ENTER:
                    mHoverBorderAnimator.setBorderVisibility(
                            /* visible= */ true, /* animated= */ true);
                    mHoverBorderAnimator.setBorderVisibility(/* visible= */ true, /* animated= */
                            true);
                    break;
                case MotionEvent.ACTION_HOVER_EXIT:
                    mHoverBorderAnimator.setBorderVisibility(
                            /* visible= */ false, /* animated= */ true);
                    mHoverBorderAnimator.setBorderVisibility(/* visible= */ false, /* animated= */
                            true);
                    break;
                default:
                    break;
@@ -564,6 +580,24 @@ public class TaskView extends FrameLayout implements Reusable {
        return super.onHoverEvent(event);
    }

    /**
     * Enable or disable showing border on hover and focus change
     */
    public void setBorderEnabled(boolean enabled) {
        mBorderEnabled = enabled;
        // Set the animation correctly in case it misses the hover/focus event during state
        // transition
        if (mHoverBorderAnimator != null) {
            mHoverBorderAnimator.setBorderVisibility(/* visible= */
                    enabled && isHovered(), /* animated= */ true);
        }

        if (mFocusBorderAnimator != null) {
            mFocusBorderAnimator.setBorderVisibility(/* visible= */
                    enabled && isFocused(), /* animated= */true);
        }
    }

    @Override
    public boolean onInterceptHoverEvent(MotionEvent event) {
        if (enableCursorHoverStates()) {
@@ -1327,6 +1361,7 @@ public class TaskView extends FrameLayout implements Reusable {
        mSnapshotView.setThumbnail(mTask, null);
        setOverlayEnabled(false);
        onTaskListVisibilityChanged(false);
        mBorderEnabled = false;
    }

    public float getTaskCornerRadius() {
+118 −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.quickstep;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.MotionEvent;

import androidx.test.filters.SmallTest;

import com.android.launcher3.statemanager.StatefulActivity;
import com.android.quickstep.util.BorderAnimator;
import com.android.quickstep.views.TaskView;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

@SmallTest
public class TaskViewTest {

    @Mock
    private StatefulActivity mContext;
    @Mock
    private Resources mResource;
    @Mock
    private BorderAnimator mHoverAnimator;
    @Mock
    private BorderAnimator mFocusAnimator;
    private TaskView mTaskView;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        when(mResource.getDisplayMetrics()).thenReturn(mock(DisplayMetrics.class));
        when(mResource.getConfiguration()).thenReturn(new Configuration());

        when(mContext.getResources()).thenReturn(mResource);
        when(mContext.getTheme()).thenReturn(mock(Resources.Theme.class));
        when(mContext.getApplicationInfo()).thenReturn(mock(ApplicationInfo.class));
        when(mContext.obtainStyledAttributes(any(), any(), anyInt(), anyInt())).thenReturn(
                mock(TypedArray.class));

        mTaskView = new TaskView(mContext, null, 0, 0, mFocusAnimator, mHoverAnimator);
    }

    @Test
    public void notShowBorderOnBorderDisabled() {
        mTaskView.setBorderEnabled(/* enabled= */ false);
        MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_ENTER, 0.0f, 0.0f, 0);
        mTaskView.onHoverEvent(MotionEvent.obtain(event));
        verify(mHoverAnimator, never()).setBorderVisibility(/* visible= */ true, /* animated= */
                true);

        mTaskView.onFocusChanged(false, 0, new Rect());
        verify(mFocusAnimator, never()).setBorderVisibility(/* visible= */ true, /* animated= */
                true);
    }

    @Test
    public void showBorderOnBorderEnabled() {
        mTaskView.setBorderEnabled(/* enabled= */ true);
        MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_ENTER, 0.0f, 0.0f, 0);
        mTaskView.onHoverEvent(MotionEvent.obtain(event));
        verify(mHoverAnimator, times(1)).setBorderVisibility(/* visible= */ true, /* animated= */
                true);
        mTaskView.onFocusChanged(true, 0, new Rect());
        verify(mFocusAnimator, times(1)).setBorderVisibility(/* visible= */ true, /* animated= */
                true);
    }

    @Test
    public void hideBorderOnBorderDisabled() {
        mTaskView.setBorderEnabled(/* enabled= */ false);
        verify(mHoverAnimator, times(1)).setBorderVisibility(/* visible= */ false, /* animated= */
                true);
        verify(mFocusAnimator, times(1)).setBorderVisibility(/* visible= */ false, /* animated= */
                true);
    }

    @Test
    public void notShowBorderByDefault() {
        MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_ENTER, 0.0f, 0.0f, 0);
        mTaskView.onHoverEvent(MotionEvent.obtain(event));
        verify(mHoverAnimator, never()).setBorderVisibility(/* visible= */ false, /* animated= */
                true);
        mTaskView.onFocusChanged(true, 0, new Rect());
        verify(mHoverAnimator, never()).setBorderVisibility(/* visible= */ false, /* animated= */
                true);
    }
}