mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-20 03:08:19 +00:00
Removing screenshot based quickstep logic
Bug: 75324790 Change-Id: Ifa6c2d9db64791f2d8151eda6ecf0d1f7406e1f3
This commit is contained in:
@@ -807,9 +807,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
Runnable finishedCallback) {
|
||||
Handler handler = mLauncher.getWindow().getDecorView().getHandler();
|
||||
postAtFrontOfQueueAsynchronously(handler, () -> {
|
||||
if ((Utilities.getPrefs(mLauncher)
|
||||
.getBoolean("pref_use_screenshot_for_swipe_up", false)
|
||||
&& mLauncher.getStateManager().getState().overviewUi)) {
|
||||
if (mLauncher.getStateManager().getState().overviewUi) {
|
||||
// We use a separate transition for Overview mode.
|
||||
setCurrentAnimator(null);
|
||||
finishedCallback.run();
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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 android.support.annotation.WorkerThread;
|
||||
|
||||
import com.android.launcher3.states.InternalStateHandler;
|
||||
import com.android.quickstep.TouchConsumer.InteractionType;
|
||||
|
||||
public abstract class BaseSwipeInteractionHandler extends InternalStateHandler {
|
||||
|
||||
protected Runnable mGestureEndCallback;
|
||||
protected boolean mIsGoingToHome;
|
||||
|
||||
public void setGestureEndCallback(Runnable gestureEndCallback) {
|
||||
mGestureEndCallback = gestureEndCallback;
|
||||
}
|
||||
|
||||
public void reset() {}
|
||||
|
||||
@WorkerThread
|
||||
public abstract void onGestureStarted();
|
||||
|
||||
@WorkerThread
|
||||
public abstract void onGestureEnded(float endVelocity);
|
||||
|
||||
public abstract void updateInteractionType(@InteractionType int interactionType);
|
||||
|
||||
@WorkerThread
|
||||
public abstract void onQuickScrubEnd();
|
||||
|
||||
@WorkerThread
|
||||
public abstract void onQuickScrubProgress(float progress);
|
||||
|
||||
@WorkerThread
|
||||
public abstract void updateDisplacement(float displacement);
|
||||
}
|
||||
@@ -1,394 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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 com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
|
||||
import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SWITCH;
|
||||
import static com.android.quickstep.TouchConsumer.isInteractionQuick;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.RectEvaluator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver.OnPreDrawListener;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Hotseat;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.Launcher.OnResumeCallback;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.util.Preconditions;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.quickstep.TouchConsumer.InteractionType;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.WindowManagerWrapper;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class NavBarSwipeInteractionHandler extends BaseSwipeInteractionHandler implements
|
||||
OnResumeCallback {
|
||||
|
||||
private static final int STATE_LAUNCHER_READY = 1 << 0;
|
||||
private static final int STATE_ACTIVITY_MULTIPLIER_COMPLETE = 1 << 4;
|
||||
private static final int STATE_SCALED_SNAPSHOT_RECENTS = 1 << 5;
|
||||
private static final int STATE_SCALED_SNAPSHOT_APP = 1 << 6;
|
||||
|
||||
private static final long MAX_SWIPE_DURATION = 200;
|
||||
private static final long MIN_SWIPE_DURATION = 80;
|
||||
|
||||
// Ideal velocity for a smooth transition
|
||||
private static final float PIXEL_PER_MS = 2f;
|
||||
|
||||
private static final float MIN_PROGRESS_FOR_OVERVIEW = 0.5f;
|
||||
|
||||
private final Rect mStableInsets = new Rect();
|
||||
private final Rect mSourceRect = new Rect();
|
||||
private final Rect mTargetRect = new Rect();
|
||||
private final Rect mCurrentRect = new Rect();
|
||||
private final RectEvaluator mRectEvaluator = new RectEvaluator(mCurrentRect);
|
||||
|
||||
// Shift in the range of [0, 1].
|
||||
// 0 => preview snapShot is completely visible, and hotseat is completely translated down
|
||||
// 1 => preview snapShot is completely aligned with the recents view and hotseat is completely
|
||||
// visible.
|
||||
private final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift);
|
||||
|
||||
// Activity multiplier in the range of [0, 1]. When the activity becomes visible, this is
|
||||
// animated to 1, so allow for a smooth transition.
|
||||
private final AnimatedFloat mActivityMultiplier = new AnimatedFloat(this::updateFinalShift);
|
||||
|
||||
private final int mRunningTaskId;
|
||||
private final Context mContext;
|
||||
|
||||
private final MultiStateCallback mStateCallback;
|
||||
|
||||
private Launcher mLauncher;
|
||||
private SnapshotDragView mDragView;
|
||||
private RecentsView mRecentsView;
|
||||
private QuickScrubController mQuickScrubController;
|
||||
private Hotseat mHotseat;
|
||||
|
||||
private boolean mWasLauncherAlreadyVisible;
|
||||
|
||||
private boolean mLauncherReady;
|
||||
private boolean mTouchEndHandled;
|
||||
private float mCurrentDisplacement;
|
||||
|
||||
private @InteractionType int mInteractionType;
|
||||
private boolean mStartedQuickScrubFromHome;
|
||||
|
||||
private Bitmap mTaskSnapshot;
|
||||
|
||||
NavBarSwipeInteractionHandler(RunningTaskInfo runningTaskInfo, Context context,
|
||||
@InteractionType int interactionType) {
|
||||
mContext = context;
|
||||
mInteractionType = interactionType;
|
||||
mRunningTaskId = runningTaskInfo.id;
|
||||
WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);
|
||||
|
||||
DeviceProfile dp = LauncherAppState.getIDP(mContext).getDeviceProfile(mContext);
|
||||
// TODO: If in multi window mode, dp = dp.getMultiWindowProfile()
|
||||
dp = dp.copy(mContext);
|
||||
// TODO: Use different insets for multi-window mode
|
||||
dp.updateInsets(mStableInsets);
|
||||
RecentsView.getPageRect(dp, mContext, mTargetRect);
|
||||
mSourceRect.set(0, 0, dp.widthPx - mStableInsets.left - mStableInsets.right,
|
||||
dp.heightPx - mStableInsets.top - mStableInsets.bottom);
|
||||
|
||||
// Build the state callback
|
||||
mStateCallback = new MultiStateCallback();
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_READY, this::onLauncherReady);
|
||||
mStateCallback.addCallback(STATE_SCALED_SNAPSHOT_APP, this::resumeLastTask);
|
||||
mStateCallback.addCallback(
|
||||
STATE_SCALED_SNAPSHOT_RECENTS | STATE_ACTIVITY_MULTIPLIER_COMPLETE,
|
||||
this::onAnimationToLauncherComplete);
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_READY | STATE_SCALED_SNAPSHOT_APP,
|
||||
this::cleanupLauncher);
|
||||
}
|
||||
|
||||
private void onLauncherReady() {
|
||||
mLauncherReady = true;
|
||||
executeFrameUpdate();
|
||||
|
||||
long duration = Math.min(MAX_SWIPE_DURATION,
|
||||
Math.max((long) (-mCurrentDisplacement / PIXEL_PER_MS), MIN_SWIPE_DURATION));
|
||||
if (mCurrentShift.getCurrentAnimation() != null) {
|
||||
ObjectAnimator anim = mCurrentShift.getCurrentAnimation();
|
||||
long theirDuration = anim.getDuration() - anim.getCurrentPlayTime();
|
||||
|
||||
// TODO: Find a better heuristic
|
||||
duration = (duration + theirDuration) / 2;
|
||||
}
|
||||
ObjectAnimator anim = mActivityMultiplier.animateToValue(1)
|
||||
.setDuration(duration);
|
||||
anim.addListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
mStateCallback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE);
|
||||
}
|
||||
});
|
||||
anim.start();
|
||||
}
|
||||
|
||||
public void setTaskSnapshot(Bitmap taskSnapshot) {
|
||||
mTaskSnapshot = taskSnapshot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLauncherResume() {
|
||||
TraceHelper.partitionSection("TouchInt", "Launcher On resume");
|
||||
mDragView.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
mDragView.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
mStateCallback.setState(STATE_LAUNCHER_READY);
|
||||
TraceHelper.partitionSection("TouchInt", "Launcher drawn");
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean init(Launcher launcher, boolean alreadyOnHome) {
|
||||
launcher.setOnResumeCallback(this);
|
||||
mLauncher = launcher;
|
||||
mRecentsView = launcher.getOverviewPanel();
|
||||
mRecentsView.showTask(mRunningTaskId);
|
||||
mHotseat = mLauncher.getHotseat();
|
||||
mWasLauncherAlreadyVisible = alreadyOnHome;
|
||||
|
||||
AbstractFloatingView.closeAllOpenViews(mLauncher, alreadyOnHome);
|
||||
mLauncher.getStateManager().goToState(LauncherState.OVERVIEW, alreadyOnHome);
|
||||
|
||||
mDragView = new SnapshotDragView(mLauncher, mTaskSnapshot);
|
||||
mLauncher.getDragLayer().addView(mDragView);
|
||||
mDragView.setPivotX(0);
|
||||
mDragView.setPivotY(0);
|
||||
|
||||
if (isInteractionQuick(mInteractionType)) {
|
||||
updateUiForQuickScrub();
|
||||
}
|
||||
|
||||
// Optimization
|
||||
if (!mLauncher.getDeviceProfile().isVerticalBarLayout()) {
|
||||
// All-apps search box is visible in vertical bar layout.
|
||||
mLauncher.getAppsView().setVisibility(View.GONE);
|
||||
}
|
||||
TraceHelper.partitionSection("TouchInt", "Launcher on new intent");
|
||||
return false;
|
||||
}
|
||||
|
||||
public void updateInteractionType(@InteractionType int interactionType) {
|
||||
Preconditions.assertUIThread();
|
||||
if (mInteractionType != INTERACTION_NORMAL) {
|
||||
throw new IllegalArgumentException(
|
||||
"Can't change interaction type from " + mInteractionType);
|
||||
}
|
||||
if (!isInteractionQuick(interactionType)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Can't change interaction type to " + interactionType);
|
||||
}
|
||||
mInteractionType = interactionType;
|
||||
|
||||
if (mLauncher != null) {
|
||||
updateUiForQuickScrub();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateUiForQuickScrub() {
|
||||
mStartedQuickScrubFromHome = mWasLauncherAlreadyVisible;
|
||||
mQuickScrubController = mRecentsView.getQuickScrubController();
|
||||
mQuickScrubController.onQuickScrubStart(mStartedQuickScrubFromHome);
|
||||
animateToProgress(1f, MAX_SWIPE_DURATION);
|
||||
if (mStartedQuickScrubFromHome) {
|
||||
mDragView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
public void updateDisplacement(float displacement) {
|
||||
mCurrentDisplacement = displacement;
|
||||
executeFrameUpdate();
|
||||
}
|
||||
|
||||
private void executeFrameUpdate() {
|
||||
if (mLauncherReady) {
|
||||
final float displacement = -mCurrentDisplacement;
|
||||
int hotseatSize = getHotseatSize();
|
||||
float translation = Utilities.boundToRange(displacement, 0, hotseatSize);
|
||||
float shift = hotseatSize == 0 ? 0 : translation / hotseatSize;
|
||||
mCurrentShift.updateValue(shift);
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void updateFinalShift() {
|
||||
if (!mLauncherReady || mStartedQuickScrubFromHome) {
|
||||
return;
|
||||
}
|
||||
|
||||
float shift = mCurrentShift.value * mActivityMultiplier.value;
|
||||
|
||||
AllAppsTransitionController controller = mLauncher.getAllAppsController();
|
||||
float range = getHotseatSize() / controller.getShiftRange();
|
||||
controller.setProgress(1 + (1 - shift) * range);
|
||||
|
||||
mRectEvaluator.evaluate(shift, mSourceRect, mTargetRect);
|
||||
|
||||
float scale = (float) mCurrentRect.width() / mSourceRect.width();
|
||||
mDragView.setTranslationX(mCurrentRect.left - mStableInsets.left * scale * shift);
|
||||
mDragView.setTranslationY(mCurrentRect.top - mStableInsets.top * scale * shift);
|
||||
mDragView.setScaleX(scale);
|
||||
mDragView.setScaleY(scale);
|
||||
// TODO: mDragView.getViewBounds().setClipLeft((int) (mStableInsets.left * shift));
|
||||
mDragView.getViewBounds().setClipTop((int) (mStableInsets.top * shift));
|
||||
// TODO: mDragView.getViewBounds().setClipRight((int) (mStableInsets.right * shift));
|
||||
mDragView.getViewBounds().setClipBottom((int) (mStableInsets.bottom * shift));
|
||||
}
|
||||
|
||||
private int getHotseatSize() {
|
||||
return mLauncher.getDeviceProfile().isVerticalBarLayout()
|
||||
? mHotseat.getWidth() : mHotseat.getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGestureStarted() { }
|
||||
|
||||
@UiThread
|
||||
public void onGestureEnded(float endVelocity) {
|
||||
if (mTouchEndHandled) {
|
||||
return;
|
||||
}
|
||||
mTouchEndHandled = true;
|
||||
|
||||
Resources res = mContext.getResources();
|
||||
float flingThreshold = res.getDimension(R.dimen.quickstep_fling_threshold_velocity);
|
||||
boolean isFling = Math.abs(endVelocity) > flingThreshold;
|
||||
|
||||
long duration = MAX_SWIPE_DURATION;
|
||||
final float endShift;
|
||||
if (!isFling) {
|
||||
endShift = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW ? 1 : 0;
|
||||
} else {
|
||||
endShift = endVelocity < 0 ? 1 : 0;
|
||||
float minFlingVelocity = res.getDimension(R.dimen.quickstep_fling_min_velocity);
|
||||
if (Math.abs(endVelocity) > minFlingVelocity && mLauncherReady) {
|
||||
float distanceToTravel = (endShift - mCurrentShift.value) * getHotseatSize();
|
||||
|
||||
// we want the page's snap velocity to approximately match the velocity at
|
||||
// which the user flings, so we scale the duration by a value near to the
|
||||
// derivative of the scroll interpolator at zero, ie. 5.
|
||||
duration = 5 * Math.round(1000 * Math.abs(distanceToTravel / endVelocity));
|
||||
}
|
||||
}
|
||||
|
||||
animateToProgress(endShift, duration);
|
||||
}
|
||||
|
||||
/** Animates to the given progress, where 0 is the current app and 1 is overview. */
|
||||
private void animateToProgress(float progress, long duration) {
|
||||
mIsGoingToHome = Float.compare(progress, 1) == 0;
|
||||
ObjectAnimator anim = mCurrentShift.animateToValue(progress).setDuration(duration);
|
||||
anim.setInterpolator(Interpolators.SCROLL);
|
||||
anim.addListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
mStateCallback.setState(mIsGoingToHome
|
||||
? STATE_SCALED_SNAPSHOT_RECENTS : STATE_SCALED_SNAPSHOT_APP);
|
||||
}
|
||||
});
|
||||
anim.start();
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void resumeLastTask() {
|
||||
RecentsTaskLoadPlan loadPlan = RecentsModel.getInstance(mContext).getLastLoadPlan();
|
||||
if (loadPlan != null) {
|
||||
Task task = loadPlan.getTaskStack().findTaskWithId(mRunningTaskId);
|
||||
if (task != null) {
|
||||
ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
|
||||
ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(task.key, opts,
|
||||
null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
mCurrentShift.cancelAnimation();
|
||||
if (mGestureEndCallback != null) {
|
||||
mGestureEndCallback.run();
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanupLauncher() {
|
||||
reset();
|
||||
|
||||
// TODO: These should be done as part of ActivityOptions#OnAnimationStarted
|
||||
mLauncher.getStateManager().reapplyState();
|
||||
mLauncher.setOnResumeCallback(() -> mDragView.close(false));
|
||||
}
|
||||
|
||||
private void onAnimationToLauncherComplete() {
|
||||
reset();
|
||||
|
||||
mDragView.close(false);
|
||||
View currentRecentsPage = mRecentsView.getPageAt(mRecentsView.getCurrentPage());
|
||||
if (currentRecentsPage instanceof TaskView) {
|
||||
((TaskView) currentRecentsPage).animateIconToScale(1f);
|
||||
}
|
||||
if (mInteractionType == INTERACTION_QUICK_SWITCH) {
|
||||
if (mQuickScrubController != null) {
|
||||
mQuickScrubController.onQuickSwitch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onQuickScrubEnd() {
|
||||
if (mQuickScrubController != null) {
|
||||
mQuickScrubController.onQuickScrubEnd();
|
||||
} else {
|
||||
// TODO:
|
||||
}
|
||||
}
|
||||
|
||||
public void onQuickScrubProgress(float progress) {
|
||||
if (mQuickScrubController != null) {
|
||||
mQuickScrubController.onQuickScrubProgress(progress);
|
||||
} else {
|
||||
// TODO:
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,27 +22,20 @@ import static android.view.MotionEvent.ACTION_POINTER_UP;
|
||||
import static android.view.MotionEvent.ACTION_UP;
|
||||
import static android.view.MotionEvent.INVALID_POINTER_ID;
|
||||
|
||||
import static com.android.quickstep.RemoteRunnable.executeSafely;
|
||||
import static com.android.quickstep.TouchInteractionService.DEBUG_SHOW_OVERVIEW_BUTTON;
|
||||
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK;
|
||||
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.Config;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.view.Choreographer;
|
||||
import android.view.Display;
|
||||
import android.view.MotionEvent;
|
||||
@@ -52,7 +45,6 @@ import android.view.ViewConfiguration;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.launcher3.MainThreadExecutor;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.systemui.shared.recents.ISystemUiProxy;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
@@ -73,7 +65,6 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.P)
|
||||
public class OtherActivityTouchConsumer extends ContextWrapper implements TouchConsumer {
|
||||
private static final String TAG = "ActivityTouchConsumer";
|
||||
|
||||
private static final long LAUNCHER_DRAW_TIMEOUT_MS = 150;
|
||||
private static final int[] DEFERRED_HIT_TARGETS = DEBUG_SHOW_OVERVIEW_BUTTON
|
||||
@@ -93,7 +84,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
private boolean mTouchThresholdCrossed;
|
||||
private int mTouchSlop;
|
||||
private float mStartDisplacement;
|
||||
private BaseSwipeInteractionHandler mInteractionHandler;
|
||||
private WindowTransformSwipeHandler mInteractionHandler;
|
||||
private int mDisplayRotation;
|
||||
private Rect mStableInsets = new Rect();
|
||||
|
||||
@@ -132,7 +123,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
|
||||
// Start the window animation on down to give more time for launcher to draw if the
|
||||
// user didn't start the gesture over the back button
|
||||
if (!isUsingScreenShot() && !mIsDeferredDownTarget) {
|
||||
if (!mIsDeferredDownTarget) {
|
||||
startTouchTrackingForWindowAnimation(ev.getEventTime());
|
||||
}
|
||||
|
||||
@@ -172,14 +163,11 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
if (mTouchThresholdCrossed) {
|
||||
mStartDisplacement = Math.signum(displacement) * mTouchSlop;
|
||||
|
||||
if (isUsingScreenShot()) {
|
||||
startTouchTrackingForScreenshotAnimation();
|
||||
} else if (mIsDeferredDownTarget) {
|
||||
if (mIsDeferredDownTarget) {
|
||||
// If we deferred starting the window animation on touch down, then
|
||||
// start tracking now
|
||||
startTouchTrackingForWindowAnimation(ev.getEventTime());
|
||||
}
|
||||
|
||||
notifyGestureStarted();
|
||||
}
|
||||
} else if (mInteractionHandler != null) {
|
||||
@@ -215,65 +203,6 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
return mDisplayRotation == Surface.ROTATION_270 && mStableInsets.left > 0;
|
||||
}
|
||||
|
||||
private boolean isUsingScreenShot() {
|
||||
return Utilities.getPrefs(this).getBoolean("pref_use_screenshot_for_swipe_up", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the gesture has started.
|
||||
*/
|
||||
private void startTouchTrackingForScreenshotAnimation() {
|
||||
// Create the shared handler
|
||||
final NavBarSwipeInteractionHandler handler =
|
||||
new NavBarSwipeInteractionHandler(mRunningTask, this, INTERACTION_NORMAL);
|
||||
|
||||
TraceHelper.partitionSection("TouchInt", "Thershold crossed ");
|
||||
|
||||
// Start the recents activity on a background thread
|
||||
BackgroundExecutor.get().submit(() -> {
|
||||
// Get the snap shot before
|
||||
handler.setTaskSnapshot(getCurrentTaskSnapshot());
|
||||
|
||||
// Start the launcher activity with our custom handler
|
||||
Intent homeIntent = handler.addToIntent(new Intent(mHomeIntent));
|
||||
startActivity(homeIntent, ActivityOptions.makeCustomAnimation(this, 0, 0).toBundle());
|
||||
TraceHelper.partitionSection("TouchInt", "Home started");
|
||||
});
|
||||
|
||||
// Preload the plan
|
||||
mRecentsModel.loadTasks(mRunningTask.id, null);
|
||||
mInteractionHandler = handler;
|
||||
mInteractionHandler.setGestureEndCallback(mEventQueue::reset);
|
||||
}
|
||||
|
||||
private Bitmap getCurrentTaskSnapshot() {
|
||||
TraceHelper.beginSection("TaskSnapshot");
|
||||
// TODO: We are using some hardcoded layers for now, to best approximate the activity layers
|
||||
Point displaySize = new Point();
|
||||
Display display = getSystemService(WindowManager.class).getDefaultDisplay();
|
||||
display.getRealSize(displaySize);
|
||||
int rotation = display.getRotation();
|
||||
// The rotation is backwards in landscape, so flip it.
|
||||
if (rotation == Surface.ROTATION_270) {
|
||||
rotation = Surface.ROTATION_90;
|
||||
} else if (rotation == Surface.ROTATION_90) {
|
||||
rotation = Surface.ROTATION_270;
|
||||
}
|
||||
try {
|
||||
return mISystemUiProxy.screenshot(new Rect(), displaySize.x, displaySize.y, 0, 100000,
|
||||
false, rotation).toBitmap();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error capturing snapshot", e);
|
||||
|
||||
// Return a dummy bitmap
|
||||
Bitmap bitmap = Bitmap.createBitmap(displaySize.x, displaySize.y, Config.RGB_565);
|
||||
bitmap.eraseColor(Color.WHITE);
|
||||
return bitmap;
|
||||
} finally {
|
||||
TraceHelper.endSection("TaskSnapshot");
|
||||
}
|
||||
}
|
||||
|
||||
private void startTouchTrackingForWindowAnimation(long touchTimeMs) {
|
||||
// Create the shared handler
|
||||
final WindowTransformSwipeHandler handler =
|
||||
@@ -353,7 +282,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
: isNavBarOnLeft() ? -mVelocityTracker.getXVelocity(mActivePointerId)
|
||||
: mVelocityTracker.getYVelocity(mActivePointerId);
|
||||
mInteractionHandler.onGestureEnded(velocity);
|
||||
} else if (!isUsingScreenShot()) {
|
||||
} else {
|
||||
// Since we start touch tracking on DOWN, we may reach this state without actually
|
||||
// starting the gesture. In that case, just cleanup immediately.
|
||||
reset();
|
||||
@@ -370,7 +299,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
public void reset() {
|
||||
// Clean up the old interaction handler
|
||||
if (mInteractionHandler != null) {
|
||||
final BaseSwipeInteractionHandler handler = mInteractionHandler;
|
||||
final WindowTransformSwipeHandler handler = mInteractionHandler;
|
||||
mInteractionHandler = null;
|
||||
mIsGoingToHome = handler.mIsGoingToHome;
|
||||
mMainThreadExecutor.execute(handler::reset);
|
||||
@@ -380,24 +309,15 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
@Override
|
||||
public void updateTouchTracking(int interactionType) {
|
||||
notifyGestureStarted();
|
||||
|
||||
if (isUsingScreenShot()) {
|
||||
mMainThreadExecutor.execute(() -> {
|
||||
if (mInteractionHandler != null) {
|
||||
mInteractionHandler.updateInteractionType(interactionType);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (mInteractionHandler != null) {
|
||||
mInteractionHandler.updateInteractionType(interactionType);
|
||||
}
|
||||
if (mInteractionHandler != null) {
|
||||
mInteractionHandler.updateInteractionType(interactionType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Choreographer getIntrimChoreographer(MotionEventQueue queue) {
|
||||
mEventQueue = queue;
|
||||
return isUsingScreenShot() ? null : mBackgroundThreadChoreographer;
|
||||
return mBackgroundThreadChoreographer;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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 android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Insettable;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.systemui.shared.recents.view.AnimateableViewBounds;
|
||||
|
||||
/**
|
||||
* Floating view which shows the task snapshot allowing it to be dragged and placed.
|
||||
*/
|
||||
public class SnapshotDragView extends AbstractFloatingView implements Insettable {
|
||||
|
||||
private final Launcher mLauncher;
|
||||
private final Bitmap mSnapshot;
|
||||
private final AnimateableViewBounds mViewBounds;
|
||||
|
||||
public SnapshotDragView(Launcher launcher, Bitmap snapshot) {
|
||||
super(launcher, null);
|
||||
mLauncher = launcher;
|
||||
mSnapshot = snapshot;
|
||||
mViewBounds = new AnimateableViewBounds(this, 0);
|
||||
setWillNotDraw(false);
|
||||
setClipToOutline(true);
|
||||
setOutlineProvider(mViewBounds);
|
||||
}
|
||||
|
||||
AnimateableViewBounds getViewBounds() {
|
||||
return mViewBounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
if (mSnapshot != null) {
|
||||
setMeasuredDimension(mSnapshot.getWidth(), mSnapshot.getHeight());
|
||||
} else {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInsets(Rect insets) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (mSnapshot != null) {
|
||||
canvas.drawBitmap(mSnapshot, 0, 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleClose(boolean animate) {
|
||||
// We dont suupport animate.
|
||||
mLauncher.getDragLayer().removeView(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logActionCommand(int command) {
|
||||
// We should probably log the weather
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isOfType(int type) {
|
||||
return (type & TYPE_QUICKSTEP_PREVIEW) != 0;
|
||||
}
|
||||
}
|
||||
@@ -65,6 +65,7 @@ import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.states.InternalStateHandler;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
@@ -119,7 +120,7 @@ class MetricsLogger {
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
public class WindowTransformSwipeHandler extends InternalStateHandler {
|
||||
private static final String TAG = WindowTransformSwipeHandler.class.getSimpleName();
|
||||
private static final boolean DEBUG_STATES = false;
|
||||
|
||||
@@ -193,6 +194,8 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
// The clip rect in source app window coordinates
|
||||
private final Rect mClipRect = new Rect();
|
||||
private final RectFEvaluator mRectFEvaluator = new RectFEvaluator();
|
||||
protected Runnable mGestureEndCallback;
|
||||
protected boolean mIsGoingToHome;
|
||||
private DeviceProfile mDp;
|
||||
private int mTransitionDragLength;
|
||||
|
||||
@@ -895,4 +898,8 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
Log.d(TAG, "[" + System.identityHashCode(this) + "] Adding " + stateFlagStr + " to "
|
||||
+ currentStateStr);
|
||||
}
|
||||
|
||||
public void setGestureEndCallback(Runnable gestureEndCallback) {
|
||||
mGestureEndCallback = gestureEndCallback;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user