diff --git a/.gitignore b/.gitignore index 7240e4877b..694b40c7ef 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,5 @@ bin/ local.properties gradle/ build/ -gradlew* \ No newline at end of file +gradlew* +.DS_Store diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java index 5680a67090..d7bbfe06e1 100644 --- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java @@ -178,6 +178,14 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag @Override public ActivityOptions getActivityLaunchOptions(Launcher launcher, View v) { if (hasControlRemoteAppTransitionPermission()) { + boolean fromRecents = mLauncher.getStateManager().getState().overviewUi + && findTaskViewToLaunch(launcher, v, null) != null; + RecentsView recentsView = mLauncher.getOverviewPanel(); + if (fromRecents && recentsView.getQuickScrubController().isQuickSwitch()) { + return ActivityOptions.makeCustomAnimation(mLauncher, R.anim.no_anim, + R.anim.no_anim); + } + RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mHandler, true /* startAtFrontOfQueue */) { @@ -218,8 +226,6 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag } }; - boolean fromRecents = mLauncher.getStateManager().getState().overviewUi - && findTaskViewToLaunch(launcher, v, null) != null; int duration = fromRecents ? RECENTS_LAUNCH_DURATION : APP_LAUNCH_DURATION; diff --git a/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java index 26453022f0..1d65a54e7a 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java @@ -35,6 +35,7 @@ public class FastOverviewState extends OverviewState { * Vertical transition of the task previews relative to the full container. */ public static final float OVERVIEW_TRANSLATION_FACTOR = 0.4f; + public static final float OVERVIEW_CENTERED_TRANSLATION_FACTOR = 0.5f; private static final int STATE_FLAGS = FLAG_DISABLE_RESTORE | FLAG_DISABLE_INTERACTION | FLAG_OVERVIEW_UI | FLAG_HIDE_BACK_BUTTON | FLAG_DISABLE_ACCESSIBILITY; @@ -60,12 +61,17 @@ public class FastOverviewState extends OverviewState { RecentsView recentsView = launcher.getOverviewPanel(); recentsView.getTaskSize(sTempRect); - return new float[] {getOverviewScale(launcher.getDeviceProfile(), sTempRect, launcher), - OVERVIEW_TRANSLATION_FACTOR}; + boolean isQuickSwitch = recentsView.getQuickScrubController().isQuickSwitch(); + float translationYFactor = isQuickSwitch + ? OVERVIEW_CENTERED_TRANSLATION_FACTOR + : OVERVIEW_TRANSLATION_FACTOR; + return new float[] {getOverviewScale(launcher.getDeviceProfile(), sTempRect, launcher, + isQuickSwitch), translationYFactor}; } - public static float getOverviewScale(DeviceProfile dp, Rect taskRect, Context context) { - if (dp.isVerticalBarLayout()) { + public static float getOverviewScale(DeviceProfile dp, Rect taskRect, Context context, + boolean isQuickSwitch) { + if (dp.isVerticalBarLayout() && !isQuickSwitch) { return 1f; } @@ -73,6 +79,10 @@ public class FastOverviewState extends OverviewState { float usedHeight = taskRect.height() + res.getDimension(R.dimen.task_thumbnail_top_margin); float usedWidth = taskRect.width() + 2 * (res.getDimension(R.dimen.recents_page_spacing) + res.getDimension(R.dimen.quickscrub_adjacent_visible_width)); + if (isQuickSwitch) { + usedWidth = taskRect.width(); + return Math.max(dp.availableHeightPx / usedHeight, dp.availableWidthPx / usedWidth); + } return Math.min(Math.min(dp.availableHeightPx / usedHeight, dp.availableWidthPx / usedWidth), MAX_PREVIEW_SCALE_UP); } diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java index c809e28320..85eed1fbfe 100644 --- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java +++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java @@ -16,7 +16,6 @@ package com.android.quickstep; import static android.view.View.TRANSLATION_Y; - import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS; import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.LauncherState.BACKGROUND_APP; @@ -58,6 +57,7 @@ import com.android.launcher3.allapps.AllAppsTransitionController; import com.android.launcher3.allapps.DiscoveryBounce; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.compat.AccessibilityManagerCompat; +import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.uioverrides.FastOverviewState; import com.android.launcher3.userevent.nano.LauncherLogProto; @@ -192,7 +192,8 @@ public interface ActivityControlHelper { @InteractionType int interactionType, TransformedRect outRect) { LayoutUtils.calculateLauncherTaskSize(context, dp, outRect.rect); if (interactionType == INTERACTION_QUICK_SCRUB) { - outRect.scale = FastOverviewState.getOverviewScale(dp, outRect.rect, context); + outRect.scale = FastOverviewState.getOverviewScale(dp, outRect.rect, context, + FeatureFlags.QUICK_SWITCH.get()); } if (dp.isVerticalBarLayout()) { Rect targetInsets = dp.getInsets(); diff --git a/quickstep/src/com/android/quickstep/QuickScrubController.java b/quickstep/src/com/android/quickstep/QuickScrubController.java index 34207670e8..c44ccd3ded 100644 --- a/quickstep/src/com/android/quickstep/QuickScrubController.java +++ b/quickstep/src/com/android/quickstep/QuickScrubController.java @@ -16,8 +16,18 @@ package com.android.quickstep; +import static com.android.launcher3.Utilities.SINGLE_FRAME_MS; +import static com.android.launcher3.anim.Interpolators.ACCEL; +import static com.android.launcher3.anim.Interpolators.DEACCEL_3; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; +import static com.android.launcher3.anim.Interpolators.LINEAR; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; +import android.annotation.TargetApi; +import android.os.Build; +import android.util.FloatProperty; import android.util.Log; import android.view.HapticFeedbackConstants; import android.view.animation.Interpolator; @@ -37,8 +47,10 @@ import com.android.quickstep.views.TaskView; * The behavior is to evenly divide the progress into sections, each of which scrolls one page. * The first and last section set an alarm to auto-advance backwards or forwards, respectively. */ +@TargetApi(Build.VERSION_CODES.P) public class QuickScrubController implements OnAlarmListener { + public static final int QUICK_SWITCH_FROM_APP_START_DURATION = 0; public static final int QUICK_SCRUB_FROM_APP_START_DURATION = 240; public static final int QUICK_SCRUB_FROM_HOME_START_DURATION = 200; // We want the translation y to finish faster than the rest of the animation. @@ -52,6 +64,19 @@ public class QuickScrubController implements OnAlarmListener { 0.05f, 0.20f, 0.35f, 0.50f, 0.65f, 0.80f, 0.95f }; + private static final FloatProperty PROGRESS + = new FloatProperty("progress") { + @Override + public void setValue(QuickScrubController quickScrubController, float progress) { + quickScrubController.onQuickScrubProgress(progress); + } + + @Override + public Float get(QuickScrubController quickScrubController) { + return quickScrubController.mEndProgress; + } + }; + private static final String TAG = "QuickScrubController"; private static final boolean ENABLE_AUTO_ADVANCE = true; private static final long AUTO_ADVANCE_DELAY = 500; @@ -72,6 +97,13 @@ public class QuickScrubController implements OnAlarmListener { private ActivityControlHelper mActivityControlHelper; private TouchInteractionLog mTouchInteractionLog; + private boolean mIsQuickSwitch; + private float mStartProgress; + private float mEndProgress; + private float mPrevProgressDelta; + private float mPrevPrevProgressDelta; + private boolean mShouldSwitchToNext; + public QuickScrubController(BaseActivity activity, RecentsView recentsView) { mActivity = activity; mRecentsView = recentsView; @@ -91,17 +123,26 @@ public class QuickScrubController implements OnAlarmListener { mActivityControlHelper = controlHelper; mTouchInteractionLog = touchInteractionLog; + if (mIsQuickSwitch) { + mShouldSwitchToNext = true; + mPrevProgressDelta = 0; + if (mRecentsView.getTaskViewCount() > 0) { + mRecentsView.getTaskViewAt(0).setFullscreen(true); + } + if (mRecentsView.getTaskViewCount() > 1) { + mRecentsView.getTaskViewAt(1).setFullscreen(true); + } + } + snapToNextTaskIfAvailable(); mActivity.getUserEventDispatcher().resetActionDurationMillis(); } public void onQuickScrubEnd() { mInQuickScrub = false; - if (ENABLE_AUTO_ADVANCE) { - mAutoAdvanceAlarm.cancelAlarm(); - } - int page = mRecentsView.getNextPage(); + Runnable launchTaskRunnable = () -> { + int page = mRecentsView.getPageNearestToCenterOfScreen(); TaskView taskView = mRecentsView.getTaskViewAt(page); if (taskView != null) { mWaitingForTaskLaunch = true; @@ -118,12 +159,49 @@ public class QuickScrubController implements OnAlarmListener { TaskUtils.getLaunchComponentKeyForTask(taskView.getTask().key)); } mWaitingForTaskLaunch = false; + if (mIsQuickSwitch) { + mIsQuickSwitch = false; + if (mRecentsView.getTaskViewCount() > 0) { + mRecentsView.getTaskViewAt(0).setFullscreen(false); + } + if (mRecentsView.getTaskViewCount() > 1) { + mRecentsView.getTaskViewAt(1).setFullscreen(false); + } + } + }, taskView.getHandler()); } else { breakOutOfQuickScrub(); } mActivityControlHelper = null; }; + + if (mIsQuickSwitch) { + float progressVelocity = mPrevPrevProgressDelta / SINGLE_FRAME_MS; + // Move to the next frame immediately, then start the animation from the + // following frame since it starts a frame later. + float singleFrameProgress = progressVelocity * SINGLE_FRAME_MS; + float fromProgress = mEndProgress + singleFrameProgress; + onQuickScrubProgress(fromProgress); + fromProgress += singleFrameProgress; + float toProgress = mShouldSwitchToNext ? 1 : 0; + int duration = (int) Math.abs((toProgress - fromProgress) / progressVelocity); + duration = Utilities.boundToRange(duration, 80, 300); + Animator anim = ObjectAnimator.ofFloat(this, PROGRESS, fromProgress, toProgress); + anim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + launchTaskRunnable.run(); + } + }); + anim.setDuration(duration).start(); + return; + } + + if (ENABLE_AUTO_ADVANCE) { + mAutoAdvanceAlarm.cancelAlarm(); + } + int page = mRecentsView.getNextPage(); int snapDuration = Math.abs(page - mRecentsView.getPageNearestToCenterOfScreen()) * QUICKSCRUB_END_SNAP_DURATION_PER_PAGE; if (mRecentsView.getChildCount() > 0 && mRecentsView.snapToPage(page, snapDuration)) { @@ -151,19 +229,28 @@ public class QuickScrubController implements OnAlarmListener { mLaunchingTaskId = 0; } + public boolean prepareQuickScrub(String tag) { + return prepareQuickScrub(tag, mIsQuickSwitch); + } + /** * Initializes the UI for quick scrub, returns true if success. */ - public boolean prepareQuickScrub(String tag) { + public boolean prepareQuickScrub(String tag, boolean isQuickSwitch) { if (mWaitingForTaskLaunch || mInQuickScrub) { Log.d(tag, "Waiting for last scrub to finish, will skip this interaction"); return false; } mOnFinishedTransitionToQuickScrubRunnable = null; mRecentsView.setNextPageSwitchRunnable(null); + mIsQuickSwitch = isQuickSwitch; return true; } + public boolean isQuickSwitch() { + return mIsQuickSwitch; + } + public boolean isWaitingForTaskLaunch() { return mWaitingForTaskLaunch; } @@ -179,6 +266,40 @@ public class QuickScrubController implements OnAlarmListener { } public void onQuickScrubProgress(float progress) { + if (mIsQuickSwitch) { + TaskView currentPage = mRecentsView.getTaskViewAt(0); + TaskView nextPage = mRecentsView.getTaskViewAt(1); + if (currentPage == null || nextPage == null) { + return; + } + if (!mFinishedTransitionToQuickScrub) { + mStartProgress = mEndProgress = progress; + } else { + float progressDelta = progress - mEndProgress; + mEndProgress = progress; + progress = Utilities.boundToRange(progress, mStartProgress, 1); + progress = Utilities.mapToRange(progress, mStartProgress, 1, 0, 1, LINEAR); + if (mInQuickScrub) { + mShouldSwitchToNext = mPrevProgressDelta > 0.007f || progressDelta > 0.007f + || progress >= 0.5f; + } + mPrevPrevProgressDelta = mPrevProgressDelta; + mPrevProgressDelta = progressDelta; + float scrollDiff = nextPage.getWidth() + mRecentsView.getPageSpacing(); + int scrollDir = mRecentsView.isRtl() ? -1 : 1; + int linearScrollDiff = (int) (progress * scrollDiff * scrollDir); + float accelScrollDiff = ACCEL.getInterpolation(progress) * scrollDiff * scrollDir; + currentPage.setZoomScale(1 - DEACCEL_3.getInterpolation(progress) + * TaskView.EDGE_SCALE_DOWN_FACTOR); + currentPage.setTranslationX(linearScrollDiff + accelScrollDiff); + nextPage.setTranslationZ(1); + nextPage.setTranslationY(currentPage.getTranslationY()); + int startScroll = mRecentsView.isRtl() ? mRecentsView.getMaxScrollX() : 0; + mRecentsView.setScrollX(startScroll + linearScrollDiff); + } + return; + } + int quickScrubSection = 0; for (float threshold : QUICK_SCRUB_THRESHOLDS) { if (progress < threshold) { @@ -228,9 +349,14 @@ public class QuickScrubController implements OnAlarmListener { public void snapToNextTaskIfAvailable() { if (mInQuickScrub && mRecentsView.getChildCount() > 0) { - int duration = mStartedFromHome ? QUICK_SCRUB_FROM_HOME_START_DURATION - : QUICK_SCRUB_FROM_APP_START_DURATION; - int pageToGoTo = mStartedFromHome ? 0 : mRecentsView.getNextPage() + 1; + int duration = mIsQuickSwitch + ? QUICK_SWITCH_FROM_APP_START_DURATION + : mStartedFromHome + ? QUICK_SCRUB_FROM_HOME_START_DURATION + : QUICK_SCRUB_FROM_APP_START_DURATION; + int pageToGoTo = mStartedFromHome || mIsQuickSwitch + ? 0 + : mRecentsView.getNextPage() + 1; goToPageWithHaptic(pageToGoTo, duration, true /* forceHaptic */, QUICK_SCRUB_START_INTERPOLATOR); } diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java index 9ea88842d7..cc544178ca 100644 --- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -23,6 +23,7 @@ import static com.android.launcher3.anim.Interpolators.DEACCEL; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2; import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_FROM_APP_START_DURATION; +import static com.android.quickstep.QuickScrubController.QUICK_SWITCH_FROM_APP_START_DURATION; import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL; import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SCRUB; import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD; @@ -59,6 +60,7 @@ import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; +import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; @@ -979,12 +981,14 @@ public class WindowTransformSwipeHandler { setStateOnUiThread(STATE_QUICK_SCRUB_START | STATE_GESTURE_COMPLETED); // Start the window animation without waiting for launcher. - animateToProgress(mCurrentShift.value, 1f, QUICK_SCRUB_FROM_APP_START_DURATION, LINEAR, - true /* goingToHome */); + long duration = FeatureFlags.QUICK_SWITCH.get() + ? QUICK_SWITCH_FROM_APP_START_DURATION + : QUICK_SCRUB_FROM_APP_START_DURATION; + animateToProgress(mCurrentShift.value, 1f, duration, LINEAR, true /* goingToHome */); } private void onQuickScrubStartUi() { - if (!mQuickScrubController.prepareQuickScrub(TAG)) { + if (!mQuickScrubController.prepareQuickScrub(TAG, FeatureFlags.QUICK_SWITCH.get())) { mQuickScrubBlocked = true; setStateOnUiThread(STATE_RESUME_LAST_TASK | STATE_HANDLER_INVALIDATED); return; @@ -1008,6 +1012,13 @@ public class WindowTransformSwipeHandler { mQuickScrubController.onFinishedTransitionToQuickScrub(); mRecentsView.animateUpRunningTaskIconScale(); + if (mQuickScrubController.isQuickSwitch()) { + TaskView runningTask = mRecentsView.getRunningTaskView(); + if (runningTask != null) { + runningTask.setTranslationY(-mActivity.getResources().getDimension( + R.dimen.task_thumbnail_half_top_margin) * 1f / mRecentsView.getScaleX()); + } + } RecentsModel.INSTANCE.get(mContext).onOverviewShown(false, TAG); } diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java index ce65de1e09..c92c8d66b8 100644 --- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java +++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java @@ -17,7 +17,6 @@ package com.android.quickstep.views; import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_FULLSCREEN; - import android.content.Context; import android.content.res.Configuration; import android.graphics.Bitmap; @@ -33,7 +32,7 @@ import android.util.AttributeSet; import android.util.FloatProperty; import android.util.Property; import android.view.View; - +import android.view.ViewGroup; import com.android.launcher3.BaseActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; @@ -78,6 +77,7 @@ public class TaskThumbnailView extends View { private final Matrix mMatrix = new Matrix(); private float mClipBottom = -1; + private Rect mScaledInsets = new Rect(); private Task mTask; private ThumbnailData mThumbnailData; @@ -179,7 +179,17 @@ public class TaskThumbnailView extends View { @Override protected void onDraw(Canvas canvas) { - drawOnCanvas(canvas, 0, 0, getMeasuredWidth(), getMeasuredHeight(), mCornerRadius); + if (((TaskView) getParent()).isFullscreen()) { + // Draw the insets if we're being drawn fullscreen (we do this for quick switch). + drawOnCanvas(canvas, + -mScaledInsets.left, + -mScaledInsets.top, + getMeasuredWidth() + mScaledInsets.right, + getMeasuredHeight() + mScaledInsets.bottom, + mCornerRadius); + } else { + drawOnCanvas(canvas, 0, 0, getMeasuredWidth(), getMeasuredHeight(), mCornerRadius); + } } public float getCornerRadius() { @@ -253,6 +263,9 @@ public class TaskThumbnailView extends View { : getMeasuredWidth() / thumbnailWidth; } + mScaledInsets.set(thumbnailInsets); + Utilities.scaleRect(mScaledInsets, thumbnailScale); + if (rotate) { int rotationDir = profile.isVerticalBarLayout() && !profile.isSeascape() ? -1 : 1; mMatrix.setRotate(90 * rotationDir); diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 2a4226faa2..07d8b891dd 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -87,7 +87,7 @@ public class TaskView extends FrameLayout implements PageCallbacks { /** * How much to scale down pages near the edge of the screen. */ - private static final float EDGE_SCALE_DOWN_FACTOR = 0.03f; + public static final float EDGE_SCALE_DOWN_FACTOR = 0.03f; public static final long SCALE_ICON_DURATION = 120; private static final long DIM_ANIM_DURATION = 700; @@ -142,6 +142,7 @@ public class TaskView extends FrameLayout implements PageCallbacks { private IconView mIconView; private float mCurveScale; private float mZoomScale; + private boolean mIsFullscreen; private Animator mIconAndDimAnimator; private float mFocusTransitionProgress = 1; @@ -509,4 +510,18 @@ public class TaskView extends FrameLayout implements PageCallbacks { Log.w(tag, msg); Toast.makeText(getContext(), R.string.activity_not_available, LENGTH_SHORT).show(); } + + /** + * Hides the icon and shows insets when this TaskView is about to be shown fullscreen. + */ + public void setFullscreen(boolean isFullscreen) { + mIsFullscreen = isFullscreen; + mIconView.setVisibility(mIsFullscreen ? INVISIBLE : VISIBLE); + setClipChildren(!mIsFullscreen); + setClipToPadding(!mIsFullscreen); + } + + public boolean isFullscreen() { + return mIsFullscreen; + } } diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java index 36b9e97aa4..9470635cb1 100644 --- a/src/com/android/launcher3/PagedView.java +++ b/src/com/android/launcher3/PagedView.java @@ -625,6 +625,10 @@ public abstract class PagedView extends ViewGrou mMaxScrollX = computeMaxScrollX(); } + public int getMaxScrollX() { + return mMaxScrollX; + } + protected int computeMaxScrollX() { int childCount = getChildCount(); if (childCount > 0) { @@ -640,6 +644,10 @@ public abstract class PagedView extends ViewGrou requestLayout(); } + public int getPageSpacing() { + return mPageSpacing; + } + private void dispatchPageCountChanged() { if (mPageIndicator != null) { mPageIndicator.setMarkersCount(getChildCount()); diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java index 64b5652c5c..e5a8a01f5d 100644 --- a/src/com/android/launcher3/config/BaseFlags.java +++ b/src/com/android/launcher3/config/BaseFlags.java @@ -22,9 +22,6 @@ import android.content.Context; import android.content.SharedPreferences; import android.provider.Settings; -import androidx.annotation.GuardedBy; -import androidx.annotation.Keep; - import com.android.launcher3.Utilities; import java.util.ArrayList; @@ -32,6 +29,9 @@ import java.util.List; import java.util.SortedMap; import java.util.TreeMap; +import androidx.annotation.GuardedBy; +import androidx.annotation.Keep; + /** * Defines a set of flags used to control various launcher behaviors. * @@ -87,6 +87,9 @@ abstract class BaseFlags { // trying to make them fit the orientation the device is in. public static final boolean OVERVIEW_USE_SCREENSHOT_ORIENTATION = true; + public static final TogglableFlag QUICK_SWITCH = new TogglableFlag("QUICK_SWITCH", false, + "Swiping right on the nav bar while in an app switches to the previous app"); + /** * Feature flag to handle define config changes dynamically instead of killing the process. */