Snap for 10515480 from 80fddb6e40 to udc-qpr1-release
Change-Id: I498b2ba1a9c3aaf63d797df18cfbf6652ece7868
This commit is contained in:
@@ -24,12 +24,15 @@
|
||||
android:paddingTop="@dimen/split_instructions_vertical_padding"
|
||||
android:paddingBottom="@dimen/split_instructions_vertical_padding"
|
||||
android:elevation="@dimen/split_instructions_elevation"
|
||||
android:visibility="gone">
|
||||
android:visibility="gone"
|
||||
android:importantForAccessibility="yes">
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/split_instructions_text"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:gravity="center"
|
||||
android:textColor="?androidprv:attr/textColorOnAccent"
|
||||
android:drawableEnd="@drawable/ic_split_horizontal"
|
||||
android:drawablePadding="@dimen/split_instructions_drawable_padding"
|
||||
android:text="@string/toast_split_select_app" />
|
||||
</com.android.quickstep.views.SplitInstructionsView>
|
||||
@@ -230,6 +230,7 @@
|
||||
<string name="action_split">Split</string>
|
||||
<!-- Label for toast with instructions for split screen selection mode. [CHAR_LIMIT=50] -->
|
||||
<string name="toast_split_select_app">Tap another app to use split screen</string>
|
||||
<string name="toast_split_select_cont_desc">Exit split screen selection</string>
|
||||
<!-- Label for toast when app selected for split isn't supported. [CHAR_LIMIT=50] -->
|
||||
<string name="toast_split_app_unsupported">Choose another app to use split screen</string>
|
||||
<!-- Message shown when an action is blocked by a policy enforced by the app or the organization managing the device. [CHAR_LIMIT=NONE] -->
|
||||
|
||||
@@ -544,17 +544,9 @@ public class QuickstepLauncher extends Launcher {
|
||||
|
||||
ArrayList<TouchController> list = new ArrayList<>();
|
||||
list.add(getDragController());
|
||||
Consumer<AnimatorSet> splitAnimator = animatorSet -> {
|
||||
AnimatorSet anim = mSplitSelectStateController.getSplitAnimationController()
|
||||
.createPlaceholderDismissAnim(QuickstepLauncher.this);
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mSplitSelectStateController.resetState();
|
||||
}
|
||||
});
|
||||
animatorSet.play(anim);
|
||||
};
|
||||
Consumer<AnimatorSet> splitAnimator = animatorSet ->
|
||||
animatorSet.play(mSplitSelectStateController.getSplitAnimationController()
|
||||
.createPlaceholderDismissAnim(this));
|
||||
switch (mode) {
|
||||
case NO_BUTTON:
|
||||
list.add(new NoButtonQuickSwitchTouchController(this));
|
||||
@@ -673,6 +665,8 @@ public class QuickstepLauncher extends Launcher {
|
||||
mSplitSelectStateController.resetState();
|
||||
}
|
||||
});
|
||||
anim.add(mSplitSelectStateController.getSplitAnimationController()
|
||||
.getShowSplitInstructionsAnim(this).buildAnim());
|
||||
anim.buildAnim().start();
|
||||
}
|
||||
|
||||
|
||||
@@ -134,6 +134,7 @@ import com.android.quickstep.util.TaskViewSimulator;
|
||||
import com.android.quickstep.views.DesktopTaskView;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
@@ -150,6 +151,7 @@ import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
@@ -656,11 +658,12 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
|
||||
protected void notifyGestureAnimationStartToRecents() {
|
||||
Task[] runningTasks;
|
||||
TopTaskTracker.CachedTaskInfo cachedTaskInfo = mGestureState.getRunningTask();
|
||||
if (mIsSwipeForSplit) {
|
||||
int[] splitTaskIds = TopTaskTracker.INSTANCE.get(mContext).getRunningSplitTaskIds();
|
||||
runningTasks = mGestureState.getRunningTask().getPlaceholderTasks(splitTaskIds);
|
||||
runningTasks = cachedTaskInfo.getPlaceholderTasks(splitTaskIds);
|
||||
} else {
|
||||
runningTasks = mGestureState.getRunningTask().getPlaceholderTasks();
|
||||
runningTasks = cachedTaskInfo.getPlaceholderTasks();
|
||||
}
|
||||
|
||||
// Safeguard against any null tasks being sent to recents view, happens when quickswitching
|
||||
@@ -733,8 +736,11 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
|| mRecentsView == null) {
|
||||
return;
|
||||
}
|
||||
// looking at single target is fine here since either app of a split pair would
|
||||
// have their "isInRecents" field set? (that's what this is used for below)
|
||||
RemoteAnimationTarget runningTaskTarget = mRecentsAnimationTargets != null
|
||||
? mRecentsAnimationTargets.findTask(mGestureState.getRunningTaskId())
|
||||
? mRecentsAnimationTargets
|
||||
.findTask(mGestureState.getTopRunningTaskId())
|
||||
: null;
|
||||
final boolean recentsAttachedToAppWindow;
|
||||
if (mIsInAllAppsRegion) {
|
||||
@@ -1190,7 +1196,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
return false;
|
||||
}
|
||||
boolean hasStartedTaskBefore = Arrays.stream(appearedTaskTarget).anyMatch(
|
||||
targetCompat -> targetCompat.taskId == mGestureState.getLastStartedTaskId());
|
||||
mGestureState.mLastStartedTaskIdPredicate);
|
||||
if (mStateCallback.hasStates(STATE_START_NEW_TASK) && hasStartedTaskBefore) {
|
||||
reset();
|
||||
return true;
|
||||
@@ -1456,9 +1462,12 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
@Override
|
||||
public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
|
||||
boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
|
||||
if (task.taskId == mGestureState.getRunningTaskId()
|
||||
&& task.configuration.windowConfiguration.getActivityType()
|
||||
!= ACTIVITY_TYPE_HOME) {
|
||||
boolean taskRunningAndNotHome = Arrays.stream(mGestureState
|
||||
.getRunningTaskIds(true /*getMultipleTasks*/))
|
||||
.anyMatch(taskId -> task.taskId == taskId
|
||||
&& task.configuration.windowConfiguration.getActivityType()
|
||||
!= ACTIVITY_TYPE_HOME);
|
||||
if (taskRunningAndNotHome) {
|
||||
// Since this is an edge case, just cancel and relaunch with default activity
|
||||
// options (since we don't know if there's an associated app icon to launch from)
|
||||
endRunningWindowAnim(true /* cancel */);
|
||||
@@ -1500,8 +1509,12 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
|
||||
if (mGestureState.getEndTarget() == HOME) {
|
||||
getOrientationHandler().adjustFloatingIconStartVelocity(velocityPxPerMs);
|
||||
// Take first task ID, if there are multiple we don't have any special home
|
||||
// animation so doesn't matter for splitscreen.. though the "allowEnterPip" might change
|
||||
// depending on which task it is..
|
||||
final RemoteAnimationTarget runningTaskTarget = mRecentsAnimationTargets != null
|
||||
? mRecentsAnimationTargets.findTask(mGestureState.getRunningTaskId())
|
||||
? mRecentsAnimationTargets
|
||||
.findTask(mGestureState.getTopRunningTaskId())
|
||||
: null;
|
||||
final ArrayList<IBinder> cookies = runningTaskTarget != null
|
||||
? runningTaskTarget.taskInfo.launchCookies
|
||||
@@ -1530,7 +1543,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
|
||||
// grab a screenshot before the PipContentOverlay gets parented on top of the task
|
||||
UI_HELPER_EXECUTOR.execute(() -> {
|
||||
final int taskId = mGestureState.getRunningTaskId();
|
||||
// Directly use top task, split to pip handled on shell side
|
||||
final int taskId = mGestureState.getTopRunningTaskId();
|
||||
mTaskSnapshotCache.put(taskId,
|
||||
mRecentsAnimationController.screenshotTask(taskId));
|
||||
});
|
||||
@@ -1994,13 +2008,10 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
// If there are no targets, then we don't need to capture anything
|
||||
mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
|
||||
} else {
|
||||
final int runningTaskId = mGestureState.getRunningTaskId();
|
||||
boolean finishTransitionPosted = false;
|
||||
// If we already have cached screenshot(s) from running tasks, skip update
|
||||
boolean shouldUpdate = false;
|
||||
int[] runningTaskIds = mIsSwipeForSplit
|
||||
? TopTaskTracker.INSTANCE.get(mContext).getRunningSplitTaskIds()
|
||||
: new int[]{runningTaskId};
|
||||
int[] runningTaskIds = mGestureState.getRunningTaskIds(mIsSwipeForSplit);
|
||||
for (int id : runningTaskIds) {
|
||||
if (!mTaskSnapshotCache.containsKey(id)) {
|
||||
shouldUpdate = true;
|
||||
@@ -2205,16 +2216,27 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
if (!mCanceled) {
|
||||
TaskView nextTask = mRecentsView == null ? null : mRecentsView.getNextPageTaskView();
|
||||
if (nextTask != null) {
|
||||
Task.TaskKey nextTaskKey = nextTask.getTask().key;
|
||||
int taskId = nextTaskKey.id;
|
||||
mGestureState.updateLastStartedTaskId(taskId);
|
||||
boolean hasTaskPreviouslyAppeared = mGestureState.getPreviouslyAppearedTaskIds()
|
||||
.contains(taskId);
|
||||
int[] taskIds = nextTask.getTaskIds();
|
||||
StringBuilder nextTaskLog = new StringBuilder();
|
||||
for (TaskIdAttributeContainer c : nextTask.getTaskIdAttributeContainers()) {
|
||||
if (c == null) {
|
||||
continue;
|
||||
}
|
||||
nextTaskLog
|
||||
.append("[id: ")
|
||||
.append(c.getTask().key.id)
|
||||
.append(", pkg: ")
|
||||
.append(c.getTask().key.getPackageName())
|
||||
.append("] | ");
|
||||
}
|
||||
mGestureState.updateLastStartedTaskIds(taskIds);
|
||||
boolean hasTaskPreviouslyAppeared = Arrays.stream(taskIds).anyMatch(
|
||||
taskId -> mGestureState.getPreviouslyAppearedTaskIds()
|
||||
.contains(taskId));
|
||||
if (!hasTaskPreviouslyAppeared) {
|
||||
ActiveGestureLog.INSTANCE.trackEvent(EXPECTING_TASK_APPEARED);
|
||||
}
|
||||
ActiveGestureLog.INSTANCE.addLog("Launching task: id=" + taskId
|
||||
+ " pkg=" + nextTaskKey.getPackageName());
|
||||
ActiveGestureLog.INSTANCE.addLog("Launching task: " + nextTaskLog);
|
||||
nextTask.launchTask(success -> {
|
||||
resultCallback.accept(success);
|
||||
if (success) {
|
||||
@@ -2284,7 +2306,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
public void onTasksAppeared(RemoteAnimationTarget[] appearedTaskTargets) {
|
||||
if (mRecentsAnimationController != null) {
|
||||
boolean hasStartedTaskBefore = Arrays.stream(appearedTaskTargets).anyMatch(
|
||||
targetCompat -> targetCompat.taskId == mGestureState.getLastStartedTaskId());
|
||||
mGestureState.mLastStartedTaskIdPredicate);
|
||||
if (!mStateCallback.hasStates(STATE_GESTURE_COMPLETED) && !hasStartedTaskBefore) {
|
||||
// This is a special case, if a task is started mid-gesture that wasn't a part of a
|
||||
// previous quickswitch task launch, then cancel the animation back to the app
|
||||
@@ -2297,8 +2319,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
} else if (handleTaskAppeared(appearedTaskTargets)) {
|
||||
Optional<RemoteAnimationTarget> taskTargetOptional =
|
||||
Arrays.stream(appearedTaskTargets)
|
||||
.filter(targetCompat ->
|
||||
targetCompat.taskId == mGestureState.getLastStartedTaskId())
|
||||
.filter(mGestureState.mLastStartedTaskIdPredicate)
|
||||
.findFirst();
|
||||
if (!taskTargetOptional.isPresent()) {
|
||||
ActiveGestureLog.INSTANCE.addLog("No appeared task matching started task id");
|
||||
@@ -2367,11 +2388,16 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
* resume if we finish the controller.
|
||||
*/
|
||||
protected int getLastAppearedTaskIndex() {
|
||||
return mRecentsView == null
|
||||
? -1
|
||||
: mGestureState.getLastAppearedTaskId() != -1
|
||||
? mRecentsView.getTaskIndexForId(mGestureState.getLastAppearedTaskId())
|
||||
: mRecentsView.getRunningTaskIndex();
|
||||
if (mRecentsView == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
OptionalInt firstValidTaskId = Arrays.stream(mGestureState.getLastAppearedTaskIds())
|
||||
.filter(i -> i != -1)
|
||||
.findFirst();
|
||||
return firstValidTaskId.isPresent()
|
||||
? mRecentsView.getTaskIndexForId(firstValidTaskId.getAsInt())
|
||||
: mRecentsView.getRunningTaskIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2379,7 +2405,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
* but before that task appeared.
|
||||
*/
|
||||
protected boolean hasStartedNewTask() {
|
||||
return mGestureState.getLastStartedTaskId() != -1;
|
||||
return mGestureState.getLastStartedTaskIds()[0] != -1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
|
||||
|
||||
import static com.android.launcher3.MotionEventsUtils.isTrackpadFourFingerSwipe;
|
||||
import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe;
|
||||
import static com.android.launcher3.MotionEventsUtils.isTrackpadThreeFingerSwipe;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
|
||||
@@ -44,10 +45,12 @@ import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Manages the state for an active system gesture, listens for events from the system and Launcher,
|
||||
@@ -56,6 +59,18 @@ import java.util.Set;
|
||||
@TargetApi(Build.VERSION_CODES.R)
|
||||
public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationListener {
|
||||
|
||||
final Predicate<RemoteAnimationTarget> mLastStartedTaskIdPredicate = new Predicate<>() {
|
||||
@Override
|
||||
public boolean test(RemoteAnimationTarget targetCompat) {
|
||||
for (int taskId : mLastStartedTaskId) {
|
||||
if (targetCompat.taskId == taskId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines the end targets of a gesture and the associated state.
|
||||
*/
|
||||
@@ -161,9 +176,9 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
||||
private TrackpadGestureType mTrackpadGestureType = TrackpadGestureType.NONE;
|
||||
private CachedTaskInfo mRunningTask;
|
||||
private GestureEndTarget mEndTarget;
|
||||
private RemoteAnimationTarget mLastAppearedTaskTarget;
|
||||
private RemoteAnimationTarget[] mLastAppearedTaskTargets;
|
||||
private Set<Integer> mPreviouslyAppearedTaskIds = new HashSet<>();
|
||||
private int mLastStartedTaskId = -1;
|
||||
private int[] mLastStartedTaskId = new int[]{INVALID_TASK_ID, INVALID_TASK_ID};
|
||||
private RecentsAnimationController mRecentsAnimationController;
|
||||
private HashMap<Integer, ThumbnailData> mRecentsAnimationCanceledSnapshots;
|
||||
|
||||
@@ -189,7 +204,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
||||
mGestureId = other.mGestureId;
|
||||
mRunningTask = other.mRunningTask;
|
||||
mEndTarget = other.mEndTarget;
|
||||
mLastAppearedTaskTarget = other.mLastAppearedTaskTarget;
|
||||
mLastAppearedTaskTargets = other.mLastAppearedTaskTargets;
|
||||
mPreviouslyAppearedTaskIds = other.mPreviouslyAppearedTaskIds;
|
||||
mLastStartedTaskId = other.mLastStartedTaskId;
|
||||
}
|
||||
@@ -293,10 +308,29 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the running task id for this gesture.
|
||||
* @param getMultipleTasks Whether multiple tasks or not are to be returned (for split)
|
||||
* @return the running task ids for this gesture.
|
||||
*/
|
||||
public int getRunningTaskId() {
|
||||
return mRunningTask != null ? mRunningTask.getTaskId() : -1;
|
||||
public int[] getRunningTaskIds(boolean getMultipleTasks) {
|
||||
if (mRunningTask == null) {
|
||||
return new int[]{INVALID_TASK_ID, INVALID_TASK_ID};
|
||||
} else {
|
||||
int cachedTasksSize = mRunningTask.mAllCachedTasks.size();
|
||||
int count = Math.min(cachedTasksSize, getMultipleTasks ? 2 : 1);
|
||||
int[] runningTaskIds = new int[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
runningTaskIds[i] = mRunningTask.mAllCachedTasks.get(i).taskId;
|
||||
}
|
||||
return runningTaskIds;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getRunningTaskIds(boolean)
|
||||
* @return the single top-most running taskId for this gesture
|
||||
*/
|
||||
public int getTopRunningTaskId() {
|
||||
return getRunningTaskIds(false /*getMultipleTasks*/)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -309,18 +343,26 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
||||
/**
|
||||
* Updates the last task that appeared during this gesture.
|
||||
*/
|
||||
public void updateLastAppearedTaskTarget(RemoteAnimationTarget lastAppearedTaskTarget) {
|
||||
mLastAppearedTaskTarget = lastAppearedTaskTarget;
|
||||
if (lastAppearedTaskTarget != null) {
|
||||
mPreviouslyAppearedTaskIds.add(lastAppearedTaskTarget.taskId);
|
||||
public void updateLastAppearedTaskTargets(RemoteAnimationTarget[] lastAppearedTaskTargets) {
|
||||
mLastAppearedTaskTargets = lastAppearedTaskTargets;
|
||||
for (RemoteAnimationTarget target : lastAppearedTaskTargets) {
|
||||
if (target == null) {
|
||||
continue;
|
||||
}
|
||||
mPreviouslyAppearedTaskIds.add(target.taskId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The id of the task that appeared during this gesture.
|
||||
*/
|
||||
public int getLastAppearedTaskId() {
|
||||
return mLastAppearedTaskTarget != null ? mLastAppearedTaskTarget.taskId : -1;
|
||||
public int[] getLastAppearedTaskIds() {
|
||||
if (mLastAppearedTaskTargets == null) {
|
||||
return new int[]{INVALID_TASK_ID, INVALID_TASK_ID};
|
||||
} else {
|
||||
return Arrays.stream(mLastAppearedTaskTargets)
|
||||
.mapToInt(target -> target != null ? target.taskId : INVALID_TASK_ID).toArray();
|
||||
}
|
||||
}
|
||||
|
||||
public void updatePreviouslyAppearedTaskIds(Set<Integer> previouslyAppearedTaskIds) {
|
||||
@@ -334,7 +376,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
||||
/**
|
||||
* Updates the last task that we started via startActivityFromRecents() during this gesture.
|
||||
*/
|
||||
public void updateLastStartedTaskId(int lastStartedTaskId) {
|
||||
public void updateLastStartedTaskIds(int[] lastStartedTaskId) {
|
||||
mLastStartedTaskId = lastStartedTaskId;
|
||||
}
|
||||
|
||||
@@ -342,7 +384,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
||||
* @return The id of the task that was most recently started during this gesture, or -1 if
|
||||
* no task has been started yet (i.e. we haven't settled on a new task).
|
||||
*/
|
||||
public int getLastStartedTaskId() {
|
||||
public int[] getLastStartedTaskIds() {
|
||||
return mLastStartedTaskId;
|
||||
}
|
||||
|
||||
@@ -478,8 +520,8 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
||||
pw.println(" gestureID=" + mGestureId);
|
||||
pw.println(" runningTask=" + mRunningTask);
|
||||
pw.println(" endTarget=" + mEndTarget);
|
||||
pw.println(" lastAppearedTaskTargetId=" + getLastAppearedTaskId());
|
||||
pw.println(" lastStartedTaskId=" + mLastStartedTaskId);
|
||||
pw.println(" lastAppearedTaskTargetId=" + Arrays.toString(mLastAppearedTaskTargets));
|
||||
pw.println(" lastStartedTaskId=" + Arrays.toString(mLastStartedTaskId));
|
||||
pw.println(" isRecentsAnimationRunning=" + isRecentsAnimationRunning());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import android.view.View;
|
||||
import android.window.RemoteTransition;
|
||||
import android.window.SplashScreen;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.app.animation.Interpolators;
|
||||
@@ -240,6 +241,11 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
||||
}
|
||||
|
||||
final TaskView taskView = (TaskView) v;
|
||||
final RecentsView recentsView = taskView.getRecentsView();
|
||||
if (recentsView == null) {
|
||||
return super.getActivityLaunchOptions(v, item);
|
||||
}
|
||||
|
||||
RunnableList onEndCallback = new RunnableList();
|
||||
|
||||
mActivityLaunchAnimationRunner = new RemoteAnimationFactory() {
|
||||
@@ -248,7 +254,7 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
||||
RemoteAnimationTarget[] wallpaperTargets,
|
||||
RemoteAnimationTarget[] nonAppTargets, AnimationResult result) {
|
||||
mHandler.removeCallbacks(mAnimationStartTimeoutRunnable);
|
||||
AnimatorSet anim = composeRecentsLaunchAnimator(taskView, appTargets,
|
||||
AnimatorSet anim = composeRecentsLaunchAnimator(recentsView, taskView, appTargets,
|
||||
wallpaperTargets, nonAppTargets);
|
||||
anim.addListener(resetStateListener());
|
||||
result.setAnimation(anim, RecentsActivity.this, onEndCallback::executeAllAndDestroy,
|
||||
@@ -285,14 +291,16 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
||||
/**
|
||||
* Composes the animations for a launch from the recents list if possible.
|
||||
*/
|
||||
private AnimatorSet composeRecentsLaunchAnimator(TaskView taskView,
|
||||
private AnimatorSet composeRecentsLaunchAnimator(
|
||||
@NonNull RecentsView recentsView,
|
||||
@NonNull TaskView taskView,
|
||||
RemoteAnimationTarget[] appTargets,
|
||||
RemoteAnimationTarget[] wallpaperTargets,
|
||||
RemoteAnimationTarget[] nonAppTargets) {
|
||||
AnimatorSet target = new AnimatorSet();
|
||||
boolean activityClosing = taskIsATargetWithMode(appTargets, getTaskId(), MODE_CLOSING);
|
||||
PendingAnimation pa = new PendingAnimation(RECENTS_LAUNCH_DURATION);
|
||||
createRecentsWindowAnimator(taskView, !activityClosing, appTargets,
|
||||
createRecentsWindowAnimator(recentsView, taskView, !activityClosing, appTargets,
|
||||
wallpaperTargets, nonAppTargets, null /* depthController */, pa);
|
||||
target.play(pa.buildAnim());
|
||||
|
||||
|
||||
@@ -115,8 +115,8 @@ public class RecentsAnimationController {
|
||||
* {@link RecentsAnimationCallbacks#onTasksAppeared}}.
|
||||
*/
|
||||
@UiThread
|
||||
public void removeTaskTarget(@NonNull RemoteAnimationTarget target) {
|
||||
UI_HELPER_EXECUTOR.execute(() -> mController.removeTask(target.taskId));
|
||||
public void removeTaskTarget(int targetTaskId) {
|
||||
UI_HELPER_EXECUTOR.execute(() -> mController.removeTask(targetTaskId));
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@@ -167,7 +167,6 @@ public class RecentsAnimationController {
|
||||
/* event= */ "finishRecentsAnimation",
|
||||
/* extras= */ toRecents,
|
||||
/* gestureEvent= */ FINISH_RECENTS_ANIMATION);
|
||||
|
||||
// Finish not yet requested
|
||||
mFinishRequested = true;
|
||||
mFinishTargetIsLauncher = toRecents;
|
||||
|
||||
@@ -59,7 +59,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
||||
private RecentsAnimationTargets mTargets;
|
||||
// Temporary until we can hook into gesture state events
|
||||
private GestureState mLastGestureState;
|
||||
private RemoteAnimationTarget mLastAppearedTaskTarget;
|
||||
private RemoteAnimationTarget[] mLastAppearedTaskTargets;
|
||||
private Runnable mLiveTileCleanUpHandler;
|
||||
private Context mCtx;
|
||||
|
||||
@@ -141,8 +141,15 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
||||
}
|
||||
mController = controller;
|
||||
mTargets = targets;
|
||||
mLastAppearedTaskTarget = mTargets.findTask(mLastGestureState.getRunningTaskId());
|
||||
mLastGestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget);
|
||||
// TODO(b/236226779): We can probably get away w/ setting mLastAppearedTaskTargets
|
||||
// to all appeared targets directly vs just looking at running ones
|
||||
int[] runningTaskIds = mLastGestureState.getRunningTaskIds(targets.apps.length > 1);
|
||||
mLastAppearedTaskTargets = new RemoteAnimationTarget[runningTaskIds.length];
|
||||
for (int i = 0; i < runningTaskIds.length; i++) {
|
||||
RemoteAnimationTarget task = mTargets.findTask(runningTaskIds[i]);
|
||||
mLastAppearedTaskTargets[i] = task;
|
||||
}
|
||||
mLastGestureState.updateLastAppearedTaskTargets(mLastAppearedTaskTargets);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -196,14 +203,17 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
||||
true /*shown*/, null /* animatorHandler */);
|
||||
}
|
||||
if (mController != null) {
|
||||
if (mLastAppearedTaskTarget == null
|
||||
|| appearedTaskTarget.taskId != mLastAppearedTaskTarget.taskId) {
|
||||
if (mLastAppearedTaskTarget != null) {
|
||||
mController.removeTaskTarget(mLastAppearedTaskTarget);
|
||||
if (mLastAppearedTaskTargets != null) {
|
||||
for (RemoteAnimationTarget lastTarget : mLastAppearedTaskTargets) {
|
||||
for (RemoteAnimationTarget appearedTarget : appearedTaskTargets) {
|
||||
if (appearedTarget.taskId != lastTarget.taskId) {
|
||||
mController.removeTaskTarget(lastTarget.taskId);
|
||||
}
|
||||
}
|
||||
}
|
||||
mLastAppearedTaskTarget = appearedTaskTarget;
|
||||
mLastGestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget);
|
||||
}
|
||||
mLastAppearedTaskTargets = appearedTaskTargets;
|
||||
mLastGestureState.updateLastAppearedTaskTargets(mLastAppearedTaskTargets);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +278,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
||||
mCallbacks.addListener(gestureState);
|
||||
gestureState.setState(STATE_RECENTS_ANIMATION_INITIALIZED
|
||||
| STATE_RECENTS_ANIMATION_STARTED);
|
||||
gestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget);
|
||||
gestureState.updateLastAppearedTaskTargets(mLastAppearedTaskTargets);
|
||||
return mCallbacks;
|
||||
}
|
||||
|
||||
@@ -369,7 +379,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
||||
mCallbacks = null;
|
||||
mTargets = null;
|
||||
mLastGestureState = null;
|
||||
mLastAppearedTaskTarget = null;
|
||||
mLastAppearedTaskTargets = null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -160,13 +160,14 @@ public final class TaskViewUtils {
|
||||
}
|
||||
|
||||
public static void createRecentsWindowAnimator(
|
||||
@NonNull TaskView v, boolean skipViewChanges,
|
||||
@NonNull RecentsView recentsView,
|
||||
@NonNull TaskView v,
|
||||
boolean skipViewChanges,
|
||||
@NonNull RemoteAnimationTarget[] appTargets,
|
||||
@NonNull RemoteAnimationTarget[] wallpaperTargets,
|
||||
@NonNull RemoteAnimationTarget[] nonAppTargets,
|
||||
@Nullable DepthController depthController,
|
||||
PendingAnimation out) {
|
||||
RecentsView recentsView = v.getRecentsView();
|
||||
boolean isQuickSwitch = v.isEndQuickswitchCuj();
|
||||
v.setEndQuickswitchCuj(false);
|
||||
|
||||
@@ -606,8 +607,8 @@ public final class TaskViewUtils {
|
||||
|
||||
TaskView taskView = findTaskViewToLaunch(recentsView, v, appTargets);
|
||||
PendingAnimation pa = new PendingAnimation(RECENTS_LAUNCH_DURATION);
|
||||
createRecentsWindowAnimator(taskView, skipLauncherChanges, appTargets, wallpaperTargets,
|
||||
nonAppTargets, depthController, pa);
|
||||
createRecentsWindowAnimator(recentsView, taskView, skipLauncherChanges, appTargets,
|
||||
wallpaperTargets, nonAppTargets, depthController, pa);
|
||||
if (launcherClosing) {
|
||||
// TODO(b/182592057): differentiate between "restore split" vs "launch fullscreen app"
|
||||
TaskViewUtils.createSplitAuxiliarySurfacesAnimator(nonAppTargets, true /*shown*/,
|
||||
|
||||
@@ -210,7 +210,7 @@ public class TopTaskTracker extends ISplitScreenListener.Stub implements TaskSta
|
||||
|
||||
@Nullable
|
||||
private final RunningTaskInfo mTopTask;
|
||||
private final List<RunningTaskInfo> mAllCachedTasks;
|
||||
public final List<RunningTaskInfo> mAllCachedTasks;
|
||||
|
||||
CachedTaskInfo(List<RunningTaskInfo> allCachedTasks) {
|
||||
mAllCachedTasks = allCachedTasks;
|
||||
|
||||
@@ -41,7 +41,6 @@ import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNF
|
||||
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED;
|
||||
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION;
|
||||
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BUBBLES;
|
||||
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DESKTOP_MODE;
|
||||
@@ -792,7 +791,7 @@ public class TouchInteractionService extends Service {
|
||||
ActiveGestureLog.INSTANCE.getLogId());
|
||||
taskInfo = previousGestureState.getRunningTask();
|
||||
gestureState.updateRunningTask(taskInfo);
|
||||
gestureState.updateLastStartedTaskId(previousGestureState.getLastStartedTaskId());
|
||||
gestureState.updateLastStartedTaskIds(previousGestureState.getLastStartedTaskIds());
|
||||
gestureState.updatePreviouslyAppearedTaskIds(
|
||||
previousGestureState.getPreviouslyAppearedTaskIds());
|
||||
} else {
|
||||
@@ -1005,6 +1004,7 @@ public class TouchInteractionService extends Service {
|
||||
}
|
||||
|
||||
reasonString.append(SUBSTRING_PREFIX).append("keyguard is not showing occluded");
|
||||
|
||||
// Use overview input consumer for sharesheets on top of home.
|
||||
boolean forceOverviewInputConsumer = gestureState.getActivityInterface().isStarted()
|
||||
&& gestureState.getRunningTask() != null
|
||||
|
||||
@@ -302,7 +302,7 @@ public class AllSetActivity extends Activity {
|
||||
}
|
||||
|
||||
private AnimatedFloat createSwipeUpProxy(GestureState state) {
|
||||
if (state.getRunningTaskId() != getTaskId()) {
|
||||
if (state.getTopRunningTaskId() != getTaskId()) {
|
||||
return null;
|
||||
}
|
||||
mSwipeProgress.updateValue(0);
|
||||
|
||||
@@ -26,15 +26,17 @@ import android.graphics.Rect
|
||||
import android.graphics.RectF
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.View
|
||||
import com.android.app.animation.Interpolators
|
||||
import com.android.launcher3.DeviceProfile
|
||||
import com.android.launcher3.Launcher
|
||||
import com.android.launcher3.Utilities
|
||||
import com.android.launcher3.anim.PendingAnimation
|
||||
import com.android.launcher3.dragndrop.DragLayer
|
||||
import com.android.launcher3.statemanager.StatefulActivity
|
||||
import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource
|
||||
import com.android.launcher3.views.BaseDragLayer
|
||||
import com.android.quickstep.views.FloatingTaskView
|
||||
import com.android.quickstep.views.IconView
|
||||
import com.android.quickstep.views.RecentsView
|
||||
import com.android.quickstep.views.SplitInstructionsView
|
||||
import com.android.quickstep.views.TaskThumbnailView
|
||||
import com.android.quickstep.views.TaskView
|
||||
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer
|
||||
@@ -58,6 +60,8 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
|
||||
)
|
||||
}
|
||||
|
||||
var splitInstructionsView: SplitInstructionsView? = null
|
||||
|
||||
/**
|
||||
* Returns different elements to animate for the initial split selection animation
|
||||
* depending on the state of the surface from which the split was initiated
|
||||
@@ -188,31 +192,26 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
|
||||
}
|
||||
|
||||
/** Does not play any animation if user is not currently in split selection state. */
|
||||
fun playPlaceholderDismissAnim(launcher: Launcher) {
|
||||
fun playPlaceholderDismissAnim(launcher: StatefulActivity<*>) {
|
||||
if (!splitSelectStateController.isSplitSelectActive) {
|
||||
return
|
||||
}
|
||||
|
||||
val anim = createPlaceholderDismissAnim(launcher)
|
||||
anim.addListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
splitSelectStateController.resetState()
|
||||
}
|
||||
})
|
||||
anim.start()
|
||||
}
|
||||
|
||||
/** Returns [AnimatorSet] which slides initial split placeholder view offscreen. */
|
||||
fun createPlaceholderDismissAnim(launcher: Launcher) : AnimatorSet {
|
||||
fun createPlaceholderDismissAnim(launcher: StatefulActivity<*>) : AnimatorSet {
|
||||
val animatorSet = AnimatorSet()
|
||||
val recentsView : RecentsView<*, *> = launcher.getOverviewPanel()
|
||||
val floatingTask: FloatingTaskView = splitSelectStateController.firstFloatingTaskView
|
||||
?: return animatorSet
|
||||
|
||||
// We are in split selection state currently, transitioning to another state
|
||||
val dragLayer: DragLayer = launcher.dragLayer
|
||||
val dragLayer: BaseDragLayer<*> = launcher.dragLayer
|
||||
val onScreenRectF = RectF()
|
||||
Utilities.getBoundsForViewInDragLayer(launcher.dragLayer, floatingTask,
|
||||
Utilities.getBoundsForViewInDragLayer(dragLayer, floatingTask,
|
||||
Rect(0, 0, floatingTask.width, floatingTask.height),
|
||||
false, null, onScreenRectF)
|
||||
// Get the part of the floatingTask that intersects with the DragLayer (i.e. the
|
||||
@@ -233,6 +232,42 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
|
||||
floatingTask.stagePosition,
|
||||
launcher.deviceProfile
|
||||
)))
|
||||
animatorSet.addListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
splitSelectStateController.resetState()
|
||||
safeRemoveViewFromDragLayer(launcher, splitInstructionsView)
|
||||
}
|
||||
})
|
||||
return animatorSet
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [PendingAnimation] to animate in the chip to instruct a user to select a second
|
||||
* app for splitscreen
|
||||
*/
|
||||
fun getShowSplitInstructionsAnim(launcher: StatefulActivity<*>) : PendingAnimation {
|
||||
safeRemoveViewFromDragLayer(launcher, splitInstructionsView)
|
||||
splitInstructionsView = SplitInstructionsView.getSplitInstructionsView(launcher)
|
||||
val timings = AnimUtils.getDeviceOverviewToSplitTimings(launcher.deviceProfile.isTablet)
|
||||
val anim = PendingAnimation(100 /*duration */)
|
||||
anim.setViewAlpha(splitInstructionsView, 1f,
|
||||
Interpolators.clampToProgress(Interpolators.LINEAR,
|
||||
timings.instructionsContainerFadeInStartOffset,
|
||||
timings.instructionsContainerFadeInEndOffset))
|
||||
anim.setViewAlpha(splitInstructionsView!!.textView, 1f,
|
||||
Interpolators.clampToProgress(Interpolators.LINEAR,
|
||||
timings.instructionsTextFadeInStartOffset,
|
||||
timings.instructionsTextFadeInEndOffset))
|
||||
anim.addFloat(splitInstructionsView, SplitInstructionsView.UNFOLD, 0.1f, 1f,
|
||||
Interpolators.clampToProgress(Interpolators.EMPHASIZED_DECELERATE,
|
||||
timings.instructionsUnfoldStartOffset,
|
||||
timings.instructionsUnfoldEndOffset))
|
||||
return anim
|
||||
}
|
||||
|
||||
private fun safeRemoveViewFromDragLayer(launcher: StatefulActivity<*>, view: View?) {
|
||||
if (view != null) {
|
||||
launcher.dragLayer.removeView(view)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5233,7 +5233,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
true /* forDesktop */);
|
||||
mRemoteTargetHandles = gluer.assignTargetsForDesktop(recentsAnimationTargets);
|
||||
} else {
|
||||
gluer = new RemoteTargetGluer(getContext(), getSizeStrategy());
|
||||
gluer = new RemoteTargetGluer(getContext(), getSizeStrategy(), recentsAnimationTargets,
|
||||
false);
|
||||
mRemoteTargetHandles = gluer.assignTargetsForSplitScreen(recentsAnimationTargets);
|
||||
}
|
||||
mSplitBoundsConfig = gluer.getSplitBounds();
|
||||
|
||||
@@ -17,15 +17,21 @@
|
||||
package com.android.quickstep.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.FloatProperty;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
|
||||
/**
|
||||
@@ -65,7 +71,7 @@ public class SplitInstructionsView extends FrameLayout {
|
||||
mLauncher = (StatefulActivity) context;
|
||||
}
|
||||
|
||||
static SplitInstructionsView getSplitInstructionsView(StatefulActivity launcher) {
|
||||
public static SplitInstructionsView getSplitInstructionsView(StatefulActivity launcher) {
|
||||
ViewGroup dragLayer = launcher.getDragLayer();
|
||||
final SplitInstructionsView splitInstructionsView =
|
||||
(SplitInstructionsView) launcher.getLayoutInflater().inflate(
|
||||
@@ -73,9 +79,7 @@ public class SplitInstructionsView extends FrameLayout {
|
||||
dragLayer,
|
||||
false
|
||||
);
|
||||
|
||||
splitInstructionsView.mTextView = splitInstructionsView.findViewById(
|
||||
R.id.split_instructions_text);
|
||||
splitInstructionsView.init();
|
||||
|
||||
// Since textview overlays base view, and we sometimes manipulate the alpha of each
|
||||
// simultaneously, force overlapping rendering to false prevents redrawing of pixels,
|
||||
@@ -92,6 +96,71 @@ public class SplitInstructionsView extends FrameLayout {
|
||||
ensureProperRotation();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mTextView = findViewById(R.id.split_instructions_text);
|
||||
|
||||
if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
|
||||
mTextView.setCompoundDrawables(null, null, null, null);
|
||||
return;
|
||||
}
|
||||
|
||||
mTextView.setOnTouchListener((v, event) -> {
|
||||
if (isTouchInsideRightCompoundDrawable(event)) {
|
||||
if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||
exitSplitSelection();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
private void exitSplitSelection() {
|
||||
((RecentsView) mLauncher.getOverviewPanel()).getSplitSelectController()
|
||||
.getSplitAnimationController().playPlaceholderDismissAnim(mLauncher);
|
||||
mLauncher.getStateManager().goToState(LauncherState.NORMAL);
|
||||
}
|
||||
|
||||
private boolean isTouchInsideRightCompoundDrawable(MotionEvent event) {
|
||||
// Get the right compound drawable of the TextView.
|
||||
Drawable rightDrawable = mTextView.getCompoundDrawablesRelative()[2];
|
||||
|
||||
// Check if the touch event intersects with the drawable's bounds.
|
||||
if (rightDrawable != null) {
|
||||
// We can get away w/o caring about the Y bounds since it's such a small view, if it's
|
||||
// above/below the drawable just assume they meant to touch it. ¯\_(ツ)_/¯
|
||||
return event.getX() >= (mTextView.getWidth() - rightDrawable.getBounds().width());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
||||
super.onInitializeAccessibilityNodeInfo(info);
|
||||
if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
info.addAction(new AccessibilityNodeInfo.AccessibilityAction(
|
||||
R.string.toast_split_select_cont_desc,
|
||||
getResources().getString(R.string.toast_split_select_cont_desc)
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performAccessibilityAction(int action, Bundle arguments) {
|
||||
if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
|
||||
return super.performAccessibilityAction(action, arguments);
|
||||
}
|
||||
|
||||
if (action == R.string.toast_split_select_cont_desc) {
|
||||
exitSplitSelection();
|
||||
return true;
|
||||
}
|
||||
return super.performAccessibilityAction(action, arguments);
|
||||
}
|
||||
|
||||
void ensureProperRotation() {
|
||||
((RecentsView) mLauncher.getOverviewPanel()).getPagedOrientationHandler()
|
||||
.setSplitInstructionsParams(
|
||||
|
||||
@@ -411,6 +411,7 @@
|
||||
<dimen name="split_instructions_elevation">1dp</dimen>
|
||||
<dimen name="split_instructions_horizontal_padding">24dp</dimen>
|
||||
<dimen name="split_instructions_vertical_padding">12dp</dimen>
|
||||
<dimen name="split_instructions_drawable_padding">10dp</dimen>
|
||||
<dimen name="split_instructions_bottom_margin_phone_landscape">24dp</dimen>
|
||||
<dimen name="split_instructions_bottom_margin_phone_portrait">60dp</dimen>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user