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

Commit 03c13ad1 authored by Vinit Nayak's avatar Vinit Nayak Committed by Android (Google) Code Review
Browse files

Merge "Show multiple icons for GroupedTaskView" into sc-v2-dev

parents 5f8bbcd5 af6b85e3
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -44,4 +44,11 @@
        android:layout_height="@dimen/task_thumbnail_icon_size"
        android:focusable="false"
        android:importantForAccessibility="no"/>

    <com.android.quickstep.views.IconView
        android:id="@+id/bottomRight_icon"
        android:layout_width="@dimen/task_thumbnail_icon_size"
        android:layout_height="@dimen/task_thumbnail_icon_size"
        android:focusable="false"
        android:importantForAccessibility="no"/>
</com.android.quickstep.views.GroupedTaskView>
 No newline at end of file
+74 −5
Original line number Diff line number Diff line
package com.android.quickstep.views;

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds;
import com.android.launcher3.util.TransformingTouchDelegate;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TaskIconCache;
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.util.CancellableTask;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;

import java.util.function.Consumer;

@@ -30,8 +38,14 @@ public class GroupedTaskView extends TaskView {

    private Task mSecondaryTask;
    private TaskThumbnailView mSnapshotView2;
    private CancellableTask mThumbnailLoadRequest2;
    private SplitConfigurationOptions.StagedSplitBounds mSplitBoundsConfig;
    private IconView mIconView2;
    private CancellableTask<ThumbnailData> mThumbnailLoadRequest2;
    private CancellableTask mIconLoadRequest2;
    private final float[] mIcon2CenterCoords = new float[2];
    private TransformingTouchDelegate mIcon2TouchDelegate;
    @Nullable private StagedSplitBounds mSplitBoundsConfig;
    private final Rect mPrimaryTempRect = new Rect();
    private final Rect mSecondaryTempRect = new Rect();

    public GroupedTaskView(Context context) {
        super(context);
@@ -49,10 +63,12 @@ public class GroupedTaskView extends TaskView {
    protected void onFinishInflate() {
        super.onFinishInflate();
        mSnapshotView2 = findViewById(R.id.bottomright_snapshot);
        mIconView2 = findViewById(R.id.bottomRight_icon);
        mIcon2TouchDelegate = new TransformingTouchDelegate(mIconView2);
    }

    public void bind(Task primary, Task secondary, RecentsOrientedState orientedState,
            SplitConfigurationOptions.StagedSplitBounds splitBoundsConfig) {
            StagedSplitBounds splitBoundsConfig) {
        super.bind(primary, orientedState);
        mSecondaryTask = secondary;
        mTaskIdContainer[1] = secondary.key.id;
@@ -67,6 +83,7 @@ public class GroupedTaskView extends TaskView {
        if (visible) {
            RecentsModel model = RecentsModel.INSTANCE.get(getContext());
            TaskThumbnailCache thumbnailCache = model.getThumbnailCache();
            TaskIconCache iconCache = model.getIconCache();

            if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
                mThumbnailLoadRequest2 = thumbnailCache.updateThumbnailInBackground(mSecondaryTask,
@@ -76,7 +93,11 @@ public class GroupedTaskView extends TaskView {
            }

            if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
                // TODO What's the Icon for this going to look like? :o
                mIconLoadRequest2 = iconCache.updateIconInBackground(mSecondaryTask,
                        (task) -> {
                            setIcon(mIconView2, task.icon);
                            // TODO(199936292) Digital Wellbeing for individual tasks?
                        });
            }
        } else {
            if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
@@ -86,11 +107,26 @@ public class GroupedTaskView extends TaskView {
                mSecondaryTask.thumbnail = null;
            }
            if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
                // TODO
                setIcon(mIconView2, null);
            }
        }
    }

    public void updateSplitBoundsConfig(StagedSplitBounds stagedSplitBounds) {
        mSplitBoundsConfig = stagedSplitBounds;
        invalidate();
    }

    @Override
    public boolean offerTouchToChildren(MotionEvent event) {
        computeAndSetIconTouchDelegate(mIconView2, mIcon2CenterCoords, mIcon2TouchDelegate);
        if (mIcon2TouchDelegate.onTouchEvent(event)) {
            return true;
        }

        return super.offerTouchToChildren(event);
    }

    @Override
    protected void cancelPendingLoadTasks() {
        super.cancelPendingLoadTasks();
@@ -98,6 +134,10 @@ public class GroupedTaskView extends TaskView {
            mThumbnailLoadRequest2.cancel();
            mThumbnailLoadRequest2 = null;
        }
        if (mIconLoadRequest2 != null) {
            mIconLoadRequest2.cancel();
            mIconLoadRequest2 = null;
        }
    }

    @Override
@@ -137,6 +177,7 @@ public class GroupedTaskView extends TaskView {
        getPagedOrientationHandler().measureGroupedTaskViewThumbnailBounds(mSnapshotView,
                mSnapshotView2, widthSize, heightSize, mSplitBoundsConfig,
                mActivity.getDeviceProfile());
        updateIconPlacement();
    }

    @Override
@@ -144,4 +185,32 @@ public class GroupedTaskView extends TaskView {
        super.setOverlayEnabled(overlayEnabled);
        mSnapshotView2.setOverlayEnabled(overlayEnabled);
    }

    @Override
    public void setOrientationState(RecentsOrientedState orientationState) {
        super.setOrientationState(orientationState);
        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
        boolean isGridTask = deviceProfile.overviewShowAsGrid && !isFocusedTask();
        int iconDrawableSize = isGridTask ? deviceProfile.overviewTaskIconDrawableSizeGridPx
                : deviceProfile.overviewTaskIconDrawableSizePx;
        mIconView2.setDrawableSize(iconDrawableSize, iconDrawableSize);
        mIconView2.setRotation(getPagedOrientationHandler().getDegreesRotated());
        updateIconPlacement();
    }

    private void updateIconPlacement() {
        if (mSplitBoundsConfig == null) {
            return;
        }

        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
        int taskIconHeight = deviceProfile.overviewTaskIconSizePx;
        boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;

        mSnapshotView.getBoundsOnScreen(mPrimaryTempRect);
        mSnapshotView2.getBoundsOnScreen(mSecondaryTempRect);
        getPagedOrientationHandler().setSplitIconParams(mIconView, mIconView2,
                taskIconHeight, mPrimaryTempRect, mSecondaryTempRect,
                isRtl, deviceProfile, mSplitBoundsConfig);
    }
}
+3 −1
Original line number Diff line number Diff line
@@ -54,7 +54,8 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
            HIDDEN_NON_ZERO_ROTATION,
            HIDDEN_NO_TASKS,
            HIDDEN_NO_RECENTS,
            HIDDEN_FOCUSED_SCROLL})
            HIDDEN_FOCUSED_SCROLL,
            HIDDEN_SPLIT_SCREEN})
    @Retention(RetentionPolicy.SOURCE)
    public @interface ActionsHiddenFlags { }

@@ -62,6 +63,7 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
    public static final int HIDDEN_NO_TASKS = 1 << 1;
    public static final int HIDDEN_NO_RECENTS = 1 << 2;
    public static final int HIDDEN_FOCUSED_SCROLL = 1 << 3;
    public static final int HIDDEN_SPLIT_SCREEN = 1 << 4;

    @IntDef(flag = true, value = {
            DISABLED_SCROLLING,
+24 −11
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ import static com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SCREEN;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -1109,6 +1110,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
                gtv.onTaskListVisibilityChanged(false);
                removeView(gtv);
            }
            mSplitBoundsConfig = null;
        }
        updateLocusId();
    }
@@ -2161,7 +2163,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
     * All subsequent calls to reload will keep the task as the first item until {@link #reset()}
     * is called.  Also scrolls the view to this task.
     */
    public void showCurrentTask(RunningTaskInfo[] runningTaskInfo) {
    private void showCurrentTask(RunningTaskInfo[] runningTaskInfo) {
        int runningTaskViewId = -1;
        boolean needGroupTaskView = runningTaskInfo.length > 1;
        RunningTaskInfo taskInfo = runningTaskInfo[0];
@@ -3134,7 +3136,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
                        }
                    }
                }
                updateFocusedSplitButtonVisibility();
                updateCurrentTaskActionsVisibility();
                onDismissAnimationEnds();
                mPendingAnimation = null;
            }
@@ -3143,16 +3145,19 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
    }

    /**
     * Shows split button if
     * * We're in large screen
     * * We're not already in split
     * Hides all overview actions if current page is for split apps, shows otherwise
     * If actions are showing, we only show split option if
     * * Device is large screen
     * * There are at least 2 tasks to invoke split
     */
    private void updateFocusedSplitButtonVisibility() {
        mActionsView.setSplitButtonVisible(mActivity.getDeviceProfile().isTablet &&
                !(getFocusedTaskView() instanceof GroupedTaskView) &&
                getTaskViewCount() > 1
        );
    private void updateCurrentTaskActionsVisibility() {
        boolean isCurrentSplit = getCurrentPageTaskView() instanceof GroupedTaskView;
        mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SCREEN, isCurrentSplit);
        if (isCurrentSplit) {
            return;
        }
        mActionsView.setSplitButtonVisible(
                mActivity.getDeviceProfile().isTablet && getTaskViewCount() > 1);
    }

    /**
@@ -4174,7 +4179,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
    @Override
    protected void notifyPageSwitchListener(int prevPage) {
        super.notifyPageSwitchListener(prevPage);
        updateFocusedSplitButtonVisibility();
        updateCurrentTaskActionsVisibility();
        loadVisibleTaskData(TaskView.FLAG_UPDATE_ALL);
        updateEnabledOverlays();
    }
@@ -4260,6 +4265,14 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        RemoteTargetGluer gluer = new RemoteTargetGluer(getContext(), getSizeStrategy());
        mRemoteTargetHandles = gluer.assignTargetsForSplitScreen(recentsAnimationTargets);
        mSplitBoundsConfig = gluer.getStagedSplitBounds();
        TaskView runningTaskView = getRunningTaskView();
        if (runningTaskView instanceof GroupedTaskView) {
            // We initially create a GroupedTaskView in showCurrentTask() before launcher even
            // receives the leashes for the remote apps, so the mSplitBoundsConfig that gets passed
            // in there is either null or outdated, so we need to update here as soon as we're
            // notified.
            ((GroupedTaskView) runningTaskView).updateSplitBoundsConfig(mSplitBoundsConfig);
        }
        for (RemoteTargetHandle remoteTargetHandle : mRemoteTargetHandles) {
            TaskViewSimulator tvs = remoteTargetHandle.getTaskViewSimulator();
            tvs.setOrientationState(mOrientationState);
+23 −46
Original line number Diff line number Diff line
@@ -374,7 +374,7 @@ public class TaskView extends FrameLayout implements Reusable {

    protected Task mTask;
    protected TaskThumbnailView mSnapshotView;
    private IconView mIconView;
    protected IconView mIconView;
    private final DigitalWellBeingToast mDigitalWellBeingToast;
    private float mFullscreenProgress;
    private float mGridProgress;
@@ -492,7 +492,7 @@ public class TaskView extends FrameLayout implements Reusable {
     */
    public boolean offerTouchToChildren(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            computeAndSetIconTouchDelegate();
            computeAndSetIconTouchDelegate(mIconView, mIconCenterCoords, mIconTouchDelegate);
            computeAndSetChipTouchDelegate();
        }
        if (mIconTouchDelegate != null && mIconTouchDelegate.onTouchEvent(event)) {
@@ -504,16 +504,17 @@ public class TaskView extends FrameLayout implements Reusable {
        return false;
    }

    private void computeAndSetIconTouchDelegate() {
        float iconHalfSize = mIconView.getWidth() / 2f;
        mIconCenterCoords[0] = mIconCenterCoords[1] = iconHalfSize;
        getDescendantCoordRelativeToAncestor(mIconView, mActivity.getDragLayer(), mIconCenterCoords,
    protected void computeAndSetIconTouchDelegate(IconView iconView, float[] tempCenterCoords,
            TransformingTouchDelegate transformingTouchDelegate) {
        float iconHalfSize = iconView.getWidth() / 2f;
        tempCenterCoords[0] = tempCenterCoords[1] = iconHalfSize;
        getDescendantCoordRelativeToAncestor(iconView, mActivity.getDragLayer(), tempCenterCoords,
                false);
        mIconTouchDelegate.setBounds(
                (int) (mIconCenterCoords[0] - iconHalfSize),
                (int) (mIconCenterCoords[1] - iconHalfSize),
                (int) (mIconCenterCoords[0] + iconHalfSize),
                (int) (mIconCenterCoords[1] + iconHalfSize));
        transformingTouchDelegate.setBounds(
                (int) (tempCenterCoords[0] - iconHalfSize),
                (int) (tempCenterCoords[1] - iconHalfSize),
                (int) (tempCenterCoords[0] + iconHalfSize),
                (int) (tempCenterCoords[1] + iconHalfSize));
    }

    private void computeAndSetChipTouchDelegate() {
@@ -792,7 +793,7 @@ public class TaskView extends FrameLayout implements Reusable {
            if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
                mIconLoadRequest = iconCache.updateIconInBackground(mTask,
                        (task) -> {
                            setIcon(task.icon);
                            setIcon(mIconView, task.icon);
                            mDigitalWellBeingToast.initialize(mTask);
                        });
            }
@@ -804,7 +805,7 @@ public class TaskView extends FrameLayout implements Reusable {
                mTask.thumbnail = null;
            }
            if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
                setIcon(null);
                setIcon(mIconView, null);
            }
        }
    }
@@ -840,10 +841,10 @@ public class TaskView extends FrameLayout implements Reusable {
        }
    }

    private void setIcon(Drawable icon) {
    protected void setIcon(IconView iconView, Drawable icon) {
        if (icon != null) {
            mIconView.setDrawable(icon);
            mIconView.setOnClickListener(v -> {
            iconView.setDrawable(icon);
            iconView.setOnClickListener(v -> {
                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask()) {
                    RecentsView recentsView = getRecentsView();
                    recentsView.switchToScreenshot(
@@ -854,14 +855,14 @@ public class TaskView extends FrameLayout implements Reusable {
                    showTaskMenu();
                }
            });
            mIconView.setOnLongClickListener(v -> {
            iconView.setOnLongClickListener(v -> {
                requestDisallowInterceptTouchEvent(true);
                return showTaskMenu();
            });
        } else {
            mIconView.setDrawable(null);
            mIconView.setOnClickListener(null);
            mIconView.setOnLongClickListener(null);
            iconView.setDrawable(null);
            iconView.setOnClickListener(null);
            iconView.setOnLongClickListener(null);
        }
    }

@@ -877,32 +878,8 @@ public class TaskView extends FrameLayout implements Reusable {
                : deviceProfile.overviewTaskMarginPx;
        int taskIconMargin = snapshotParams.topMargin - taskIconHeight - taskMargin;
        LayoutParams iconParams = (LayoutParams) mIconView.getLayoutParams();
        switch (orientationHandler.getRotation()) {
            case ROTATION_90:
                iconParams.gravity = (isRtl ? START : END) | CENTER_VERTICAL;
                iconParams.rightMargin = -taskIconHeight - taskIconMargin / 2;
                iconParams.leftMargin = 0;
                iconParams.topMargin = snapshotParams.topMargin / 2;
                break;
            case ROTATION_180:
                iconParams.gravity = BOTTOM | CENTER_HORIZONTAL;
                iconParams.bottomMargin = -snapshotParams.topMargin;
                iconParams.leftMargin = iconParams.rightMargin = 0;
                iconParams.topMargin = taskIconMargin;
                break;
            case ROTATION_270:
                iconParams.gravity = (isRtl ? END : START) | CENTER_VERTICAL;
                iconParams.leftMargin = -taskIconHeight - taskIconMargin / 2;
                iconParams.rightMargin = 0;
                iconParams.topMargin = snapshotParams.topMargin / 2;
                break;
            case Surface.ROTATION_0:
            default:
                iconParams.gravity = TOP | CENTER_HORIZONTAL;
                iconParams.leftMargin = iconParams.rightMargin = 0;
                iconParams.topMargin = taskIconMargin;
                break;
        }
        orientationHandler.setIconAndSnapshotParams(mIconView, taskIconMargin, taskIconHeight,
                snapshotParams, isRtl);
        mSnapshotView.setLayoutParams(snapshotParams);
        iconParams.width = iconParams.height = taskIconHeight;
        mIconView.setLayoutParams(iconParams);
Loading