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

Commit 3516ecc5 authored by Winson Chung's avatar Winson Chung
Browse files

Allow split with an existing split task

- Determine the task in the group being clicked in split-select mode
  and launch split using that selected task
- Also make sure we don't handle drag cancel twice when we are animating
  the return of the drag surface

Bug: 219060441
Test: Split from home/overview with fullscreen+fullscreen task, and with
      fullscreen+split task

Change-Id: I48ec0a82812197803ff4b3698830a9cb705719e3
parent da7a268e
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -469,13 +469,19 @@ public class TaskbarDragController extends DragController<TaskbarActivityContext
            }
        });
        mReturnAnimator.addListener(new AnimatorListenerAdapter() {
            private boolean mCanceled = false;

            @Override
            public void onAnimationCancel(Animator animation) {
                cleanUpSurface();
                mCanceled = true;
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if (mCanceled) {
                    return;
                }
                cleanUpSurface();
            }

+4 −15
Original line number Diff line number Diff line
@@ -48,8 +48,6 @@ public class FloatingTaskView extends FrameLayout {

    private SplitPlaceholderView mSplitPlaceholderView;
    private RectF mStartingPosition;
    @Nullable
    private Consumer<RectF> mAdditionalOffsetter;
    private final StatefulActivity mActivity;
    private final boolean mIsRtl;
    private final Rect mOutline = new Rect();
@@ -81,9 +79,8 @@ public class FloatingTaskView extends FrameLayout {
    }

    private void init(StatefulActivity launcher, View originalView, @Nullable Bitmap thumbnail,
            Drawable icon, RectF positionOut, Consumer<RectF> additionalOffsetter) {
            Drawable icon, RectF positionOut) {
        mStartingPosition = positionOut;
        mAdditionalOffsetter = additionalOffsetter;
        updateInitialPositionForView(originalView);
        final InsettableFrameLayout.LayoutParams lp =
                (InsettableFrameLayout.LayoutParams) getLayoutParams();
@@ -113,15 +110,13 @@ public class FloatingTaskView extends FrameLayout {
     *                               translation values from originalView will be used
     */
    public static FloatingTaskView getFloatingTaskView(StatefulActivity launcher,
            View originalView, @Nullable Bitmap thumbnail, Drawable icon, RectF positionOut,
            @Nullable Consumer<RectF> additionalOffsetter) {
            View originalView, @Nullable Bitmap thumbnail, Drawable icon, RectF positionOut) {
        final BaseDragLayer dragLayer = launcher.getDragLayer();
        ViewGroup parent = (ViewGroup) dragLayer.getParent();
        final FloatingTaskView floatingView = (FloatingTaskView) launcher.getLayoutInflater()
                .inflate(R.layout.floating_split_select_view, parent, false);

        floatingView.init(launcher, originalView, thumbnail, icon, positionOut,
                additionalOffsetter);
        floatingView.init(launcher, originalView, thumbnail, icon, positionOut);
        parent.addView(floatingView);
        return floatingView;
    }
@@ -129,14 +124,8 @@ public class FloatingTaskView extends FrameLayout {
    public void updateInitialPositionForView(View originalView) {
        Rect viewBounds = new Rect(0, 0, originalView.getWidth(), originalView.getHeight());
        Utilities.getBoundsForViewInDragLayer(mActivity.getDragLayer(), originalView, viewBounds,
                true /* ignoreTransform */, null /* recycle */,
                false /* ignoreTransform */, null /* recycle */,
                mStartingPosition);
        if (mAdditionalOffsetter != null) {
            mAdditionalOffsetter.accept(mStartingPosition);
        } else {
            mStartingPosition.offset(originalView.getTranslationX(),
                    originalView.getTranslationY());
        }
        final InsettableFrameLayout.LayoutParams lp = new InsettableFrameLayout.LayoutParams(
                Math.round(mStartingPosition.width()),
                Math.round(mStartingPosition.height()));
+17 −1
Original line number Diff line number Diff line
@@ -5,14 +5,17 @@ import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITIO
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;

import android.content.Context;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

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

import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds;
import com.android.launcher3.util.TransformingTouchDelegate;
@@ -52,7 +55,6 @@ public class GroupedTaskView extends TaskView {
    @Nullable private StagedSplitBounds mSplitBoundsConfig;
    private final DigitalWellBeingToast mDigitalWellBeingToast2;


    public GroupedTaskView(Context context) {
        this(context, null);
    }
@@ -204,6 +206,20 @@ public class GroupedTaskView extends TaskView {
        return new TaskThumbnailView[]{mSnapshotView, mSnapshotView2};
    }

    @Override
    protected int getChildTaskIndexAtPosition(PointF position) {
        if (isCoordInView(mIconView2, position) || isCoordInView(mSnapshotView2, position)) {
            return 1;
        }
        return super.getChildTaskIndexAtPosition(position);
    }

    private boolean isCoordInView(View v, PointF position) {
        float[] localPos = new float[]{position.x, position.y};
        Utilities.mapCoordInSelfToDescendant(v, this, localPos);
        return Utilities.pointInView(v, localPos[0], localPos[1], 0f /* slop */);
    }

    @Override
    public void onRecycle() {
        super.onRecycle();
+23 −21
Original line number Diff line number Diff line
@@ -619,7 +619,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
    @Nullable
    private TaskView mSplitHiddenTaskView;
    @Nullable
    private TaskView mSecondSplitHiddenTaskView;
    private View mSecondSplitHiddenView;
    @Nullable
    private StagedSplitBounds mSplitBoundsConfig;
    private final Toast mSplitToast = Toast.makeText(getContext(),
@@ -2729,11 +2729,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
            mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
                    mSplitHiddenTaskView.getThumbnail(),
                    mSplitHiddenTaskView.getThumbnail().getThumbnail(),
                    mSplitHiddenTaskView.getIconView().getDrawable(), startingTaskRect,
                    floatingTaskViewStartingPosition -> floatingTaskViewStartingPosition.offset(
                            mSplitHiddenTaskView.getTranslationX(),
                            mSplitHiddenTaskView.getTranslationY()
                    ));
                    mSplitHiddenTaskView.getIconView().getDrawable(), startingTaskRect);
            mFirstFloatingTaskView.setAlpha(1);
            mFirstFloatingTaskView.addAnimation(anim, startingTaskRect,
                    mTempRect, true /*fadeWithThumbnail*/);
@@ -2741,7 +2737,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
            mSplitSelectSource.view.setVisibility(INVISIBLE);
            mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
                    mSplitSelectSource.view, null,
                    mSplitSelectSource.drawable, startingTaskRect, null /*additionalOffsetter*/);
                    mSplitSelectSource.drawable, startingTaskRect);
            mFirstFloatingTaskView.setAlpha(1);
            mFirstFloatingTaskView.addAnimation(anim, startingTaskRect,
                    mTempRect, true /*fadeWithThumbnail*/);
@@ -4004,9 +4000,14 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        }
    }

    public void confirmSplitSelect(TaskView taskView) {
    /**
     * Confirms the selection of the next split task. The extra data is passed through because the
     * user may be selecting a subtask in a group.
     */
    public void confirmSplitSelect(TaskView containerTaskView, Task task, IconView iconView,
            TaskThumbnailView thumbnailView) {
        mSplitToast.cancel();
        if (!taskView.getTask().isDockable) {
        if (!task.isDockable) {
            // Task not split screen supported
            mSplitUnsupportedToast.show();
            return;
@@ -4032,20 +4033,21 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
                false /*fadeWithThumbnail*/);

        mSecondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
                taskView.getThumbnail(), taskView.getThumbnail().getThumbnail(),
                taskView.getIconView().getDrawable(), secondTaskStartingBounds,
                floatingTaskViewStartingPosition -> floatingTaskViewStartingPosition.offset(
                        taskView.getTranslationX(),
                        taskView.getTranslationY()
                ));
                thumbnailView, thumbnailView.getThumbnail(),
                iconView.getDrawable(), secondTaskStartingBounds);
        mSecondFloatingTaskView.setAlpha(1);
        mSecondFloatingTaskView.addAnimation(pendingAnimation, secondTaskStartingBounds,
                secondTaskEndingBounds, true /* fadeWithThumbnail */);
        pendingAnimation.addEndListener(aBoolean ->
                mSplitSelectStateController.setSecondTaskId(taskView.getTask().key.id,
                mSplitSelectStateController.setSecondTaskId(task.key.id,
                aBoolean1 -> RecentsView.this.resetFromSplitSelectionState()));
        mSecondSplitHiddenTaskView = taskView;
        taskView.setVisibility(INVISIBLE);
        if (containerTaskView.containsMultipleTasks()) {
            // If we are launching from a child task, then only hide the thumbnail itself
            mSecondSplitHiddenView = thumbnailView;
        } else {
            mSecondSplitHiddenView = containerTaskView;
        }
        mSecondSplitHiddenView.setVisibility(INVISIBLE);
        pendingAnimation.buildAnim().start();
    }

@@ -4059,8 +4061,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
            if (mSecondFloatingTaskView != null) {
                mActivity.getRootView().removeView(mSecondFloatingTaskView);
                mSecondFloatingTaskView = null;
                mSecondSplitHiddenTaskView.setVisibility(VISIBLE);
                mSecondSplitHiddenTaskView = null;
                mSecondSplitHiddenView.setVisibility(VISIBLE);
                mSecondSplitHiddenView = null;
            }
            mSplitSelectSource = null;
        }
+23 −1
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;
import android.graphics.Outline;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
@@ -426,8 +427,11 @@ public class TaskView extends FrameLayout implements Reusable {

    private final float[] mIconCenterCoords = new float[2];

    private final PointF mLastTouchDownPosition = new PointF();

    private boolean mIsClickableAsLiveTile = true;


    public TaskView(Context context) {
        this(context, null);
    }
@@ -600,6 +604,14 @@ public class TaskView extends FrameLayout implements Reusable {
        return mIconView;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            mLastTouchDownPosition.set(ev.getX(), ev.getY());
        }
        return super.dispatchTouchEvent(ev);
    }

    private void onClick(View view) {
        if (getTask() == null) {
            return;
@@ -688,11 +700,21 @@ public class TaskView extends FrameLayout implements Reusable {
    private boolean confirmSecondSplitSelectApp() {
        boolean isSelectingSecondSplitApp = getRecentsView().isSplitSelectionActive();
        if (isSelectingSecondSplitApp) {
            getRecentsView().confirmSplitSelect(this);
            int index = getChildTaskIndexAtPosition(mLastTouchDownPosition);
            TaskIdAttributeContainer container = mTaskIdAttributeContainer[index];
            getRecentsView().confirmSplitSelect(this, container.getTask(), container.getIconView(),
                    container.getThumbnailView());
        }
        return isSelectingSecondSplitApp;
    }

    /**
     * Returns the task under the given position in the local coordinates of this task view.
     */
    protected int getChildTaskIndexAtPosition(PointF position) {
        return 0;
    }

    /**
     * Starts the task associated with this view and animates the startup.
     * @return CompletionStage to indicate the animation completion or null if the launch failed.