diff options
author | Winson Chung <winsonc@google.com> | 2022-02-17 23:26:12 +0000 |
---|---|---|
committer | Winson Chung <winsonc@google.com> | 2022-02-18 17:49:59 +0000 |
commit | 3516ecc5340c495cf0582ab685fecbdede20a286 (patch) | |
tree | 962028bdbadb3844967284880f371d145302e3ce /quickstep | |
parent | da7a268e7f4350a72f5fdfc054c0bd05d96c7e56 (diff) | |
download | Launcher3-3516ecc5340c495cf0582ab685fecbdede20a286.tar.gz |
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
Diffstat (limited to 'quickstep')
5 files changed, 73 insertions, 38 deletions
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java index 435eae47ee..6a2f62256b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java @@ -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(); } diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java index 307c51f6fd..f2f1c3f5f6 100644 --- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java +++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java @@ -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())); diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java index af9f818e4e..04af3c11ab 100644 --- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java +++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java @@ -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); } @@ -205,6 +207,20 @@ public class GroupedTaskView extends TaskView { } @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(); mSnapshotView2.setThumbnail(mSecondaryTask, null); diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index a042bff67f..cb7e08a255 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -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*/); + 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; } diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 488789b465..f716965fa1 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -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,12 +700,22 @@ 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. */ |