Merge "Add new FolderLabelStates to better understand smart folder acceptance rate based on primary suggestion." into ub-launcher3-master
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
index 5abeae4..85741ed 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
@@ -46,11 +46,8 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.model.PagedViewOrientedState;
-import com.android.launcher3.states.RotationHelper;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.PagedOrientationHandler;
-import com.android.launcher3.touch.PortraitPagedViewHandler;
import com.android.launcher3.util.VibratorWrapper;
import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.BaseActivityInterface.HomeAnimationFactory;
@@ -59,6 +56,7 @@
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.AppWindowAnimationHelper;
import com.android.quickstep.util.AppWindowAnimationHelper.TransformParams;
+import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -127,7 +125,7 @@
protected boolean mCanceled;
protected int mFinishingRecentsAnimationForNewTaskId = -1;
- private PagedViewOrientedState mOrientedState;
+ private RecentsOrientedState mOrientedState;
protected BaseSwipeUpHandler(Context context, RecentsAnimationDeviceState deviceState,
GestureState gestureState, InputConsumerController inputConsumer) {
@@ -350,9 +348,11 @@
// TODO(b/150300347): The first recents animation after launcher is started with the
// foreground app not in landscape will look funky until that bug is fixed
displayRotation = mOrientedState.getDisplayRotation();
+
+ RectF tempRectF = new RectF(TEMP_RECT);
+ mOrientedState.mapRectFromNormalOrientation(tempRectF, dp.widthPx, dp.heightPx);
+ tempRectF.roundOut(TEMP_RECT);
}
- RotationHelper.getTargetRectForRotation(TEMP_RECT, dp.widthPx, dp.heightPx,
- displayRotation);
mAppWindowAnimationHelper.updateTargetRect(TEMP_RECT);
if (mDeviceState.isFullyGesturalNavMode()) {
// We can drag all the way to the top of the screen.
@@ -447,7 +447,7 @@
protected PagedOrientationHandler getOrientationHandler() {
if (mOrientedState == null) {
- return new PortraitPagedViewHandler();
+ return PagedOrientationHandler.PORTRAIT;
}
return mOrientedState.getOrientationHandler();
}
@@ -468,8 +468,8 @@
.setTargetSet(mRecentsAnimationTargets)
.setLauncherOnTop(false)));
if (isFloatingIconView) {
- RotationHelper.mapInverseRectFromNormalOrientation(startRect,
- mDp.widthPx, mDp.heightPx, mOrientedState.getDisplayRotation());
+ mOrientedState.mapInverseRectFromNormalOrientation(
+ startRect, mDp.widthPx, mDp.heightPx);
}
RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mContext);
if (isFloatingIconView) {
@@ -500,8 +500,8 @@
rotatedRect.set(currentRect);
if (isFloatingIconView) {
- RotationHelper.mapRectFromNormalOrientation(rotatedRect,
- mDp.widthPx, mDp.heightPx, mOrientedState.getDisplayRotation());
+ mOrientedState.mapRectFromNormalOrientation(
+ rotatedRect, mDp.widthPx, mDp.heightPx);
mTransformParams.setCornerRadius(endRadius * progress + startRadius
* (1f - progress));
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
index 4abb86a..2214dd0 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
@@ -33,8 +33,6 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.touch.PortraitPagedViewHandler;
-import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.util.ActivityInitListener;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java
index da73bc0..46b026e 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -40,9 +40,7 @@
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.touch.LandscapePagedViewHandler;
import com.android.launcher3.touch.PagedOrientationHandler;
-import com.android.launcher3.touch.PortraitPagedViewHandler;
import com.android.launcher3.util.ObjectWrapper;
import com.android.quickstep.BaseActivityInterface.HomeAnimationFactory;
import com.android.quickstep.GestureState.GestureEndTarget;
@@ -503,8 +501,8 @@
PagedOrientationHandler orientationHandler = mRecentsView != null
? mRecentsView.getPagedOrientationHandler()
: (mDp.isLandscape
- ? new LandscapePagedViewHandler()
- : new PortraitPagedViewHandler());
+ ? PagedOrientationHandler.LANDSCAPE
+ : PagedOrientationHandler.PORTRAIT);
return HomeAnimationFactory
.getDefaultWindowTargetRect(orientationHandler, mDp);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java
index d9e9cc7..75a5976 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java
@@ -15,6 +15,13 @@
*/
package com.android.quickstep.util;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
+import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius;
+import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
+
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
@@ -33,7 +40,6 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.model.PagedViewOrientedState;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.RemoteAnimationTargets;
import com.android.quickstep.SystemUiProxy;
@@ -47,13 +53,6 @@
import com.android.systemui.shared.system.TransactionCompat;
import com.android.systemui.shared.system.WindowManagerWrapper;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
-import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius;
-import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
-import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
-import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
-import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
-
/**
* Utility class to handle window clip animation
*/
@@ -86,7 +85,7 @@
private final Rect mTmpRect = new Rect();
private final RectF mTmpRectF = new RectF();
private final RectF mCurrentRectWithInsets = new RectF();
- private PagedViewOrientedState mOrientedState;
+ private RecentsOrientedState mOrientedState;
// Corner radius of windows, in pixels
private final float mWindowCornerRadius;
// Corner radius of windows when they're in overview mode.
@@ -105,7 +104,7 @@
private TargetAlphaProvider mTaskAlphaCallback = (t, a) -> a;
private TargetAlphaProvider mBaseAlphaCallback = (t, a) -> 1;
- public AppWindowAnimationHelper(PagedViewOrientedState orientedState, Context context) {
+ public AppWindowAnimationHelper(RecentsOrientedState orientedState, Context context) {
Resources res = context.getResources();
mOrientedState = orientedState;
mWindowCornerRadius = getWindowCornerRadius(res);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/ClearAllButton.java
index 763f5be..e455939 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/ClearAllButton.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/ClearAllButton.java
@@ -78,21 +78,6 @@
}
}
- public void onLayoutChanged() {
- if (mParent == null) {
- return;
- }
- setRotation(mParent.getPagedOrientationHandler().getDegreesRotated());
- }
-
- public void setRtl(boolean rtl) {
- if (mIsRtl == rtl) {
- return;
- }
- mIsRtl = rtl;
- invalidate();
- }
-
public void setVisibilityAlpha(float alpha) {
if (mVisibilityAlpha != alpha) {
mVisibilityAlpha = alpha;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
index e62de18..98eb29a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -42,7 +42,6 @@
import com.android.launcher3.Hotseat;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.StateListener;
-import com.android.launcher3.R;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.appprediction.PredictionUiStateManager;
import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
@@ -172,7 +171,7 @@
mActivity.getAllAppsController(), ALL_APPS_PROGRESS, allAppsProgressOffscreen));
ObjectAnimator dragHandleAnim = ObjectAnimator.ofInt(
- mActivity.findViewById(R.id.scrim_view), ScrimView.DRAG_HANDLE_ALPHA, 0);
+ mActivity.getScrimView(), ScrimView.DRAG_HANDLE_ALPHA, 0);
dragHandleAnim.setInterpolator(Interpolators.ACCEL_2);
anim.play(dragHandleAnim);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index e3b3102..5e8c232 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -100,8 +100,8 @@
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statehandlers.DepthController;
-import com.android.launcher3.states.RotationHelper;
import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.touch.PagedOrientationHandler.CurveProperties;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
@@ -122,6 +122,7 @@
import com.android.quickstep.ViewUtils;
import com.android.quickstep.util.AppWindowAnimationHelper;
import com.android.quickstep.util.LayoutUtils;
+import com.android.quickstep.util.RecentsOrientedState;
import com.android.systemui.plugins.ResourceProvider;
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
import com.android.systemui.shared.recents.model.Task;
@@ -171,6 +172,8 @@
}
};
+ protected final RecentsOrientedState mOrientationState = new RecentsOrientedState();
+
private OrientationEventListener mOrientationListener;
private int mPreviousRotation;
protected RecentsAnimationController mRecentsAnimationController;
@@ -383,7 +386,7 @@
mOrientationListener = new OrientationEventListener(getContext()) {
@Override
public void onOrientationChanged(int i) {
- int rotation = RotationHelper.getRotationFromDegrees(i);
+ int rotation = RecentsOrientedState.getRotationForUserDegreesRotated(i);
if (mPreviousRotation != rotation) {
animateRecentsRotationInPlace(rotation);
if (rotation == 0) {
@@ -661,7 +664,7 @@
final int pageIndex = requiredTaskCount - i - 1 + mTaskViewStartIndex;
final Task task = tasks.get(i);
final TaskView taskView = (TaskView) getChildAt(pageIndex);
- taskView.bind(task, mLayoutRotation);
+ taskView.bind(task, mOrientationState);
}
if (mNextPage == INVALID_PAGE) {
@@ -973,7 +976,7 @@
AnimatorSet pa = setRecentsChangedOrientation(true);
pa.addListener(AnimationSuccessListener.forRunnable(() -> {
- updateLayoutRotation(newRotation);
+ setLayoutRotation(newRotation, mOrientationState.getDisplayRotation());
mActivity.getDragLayer().recreateControllers();
rotateAllChildTasks();
setRecentsChangedOrientation(false).start();
@@ -999,8 +1002,7 @@
private void rotateAllChildTasks() {
for (int i = 0; i < getTaskViewCount(); i++) {
- TaskView taskView = getTaskViewAt(i);
- taskView.setOverviewRotation(mLayoutRotation);
+ getTaskViewAt(i).setOrientationState(mOrientationState);
}
}
@@ -1041,7 +1043,7 @@
new ComponentName(getContext(), getClass()), 0, 0), null, null, "", "", 0, 0,
false, true, false, false, new ActivityManager.TaskDescription(), 0,
new ComponentName("", ""), false);
- taskView.bind(mTmpRunningTask, mLayoutRotation);
+ taskView.bind(mTmpRunningTask, mOrientationState);
}
boolean runningTaskTileHidden = mRunningTaskTileHidden;
@@ -1530,16 +1532,28 @@
}
}
- @Override
public void setLayoutRotation(int touchRotation, int displayRotation) {
- if (!FeatureFlags.ENABLE_FIXED_ROTATION_TRANSFORM.get()) {
- return;
+ if (mOrientationState.update(touchRotation, displayRotation)) {
+ mOrientationHandler = mOrientationState.getOrientationHandler();
+ mIsRtl = mOrientationHandler.getRecentsRtlSetting(getResources());
+ setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
+ mClearAllButton.setRotation(mOrientationHandler.getDegreesRotated());
+ requestLayout();
}
+ }
- super.setLayoutRotation(touchRotation, displayRotation);
- mClearAllButton.onLayoutChanged();
- mIsRtl = mOrientationHandler.getRecentsRtlSetting(getResources());
- setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
+ public void disableMultipleLayoutRotations(boolean disable) {
+ mOrientationState.disableMultipleOrientations(disable);
+ mOrientationHandler = mOrientationState.getOrientationHandler();
+ requestLayout();
+ }
+
+ public RecentsOrientedState getPagedViewOrientedState() {
+ return mOrientationState;
+ }
+
+ public PagedOrientationHandler getPagedOrientationHandler() {
+ return mOrientationHandler;
}
@Override
@@ -1986,8 +2000,7 @@
public Consumer<MotionEvent> getEventDispatcher(float navbarRotation) {
float degreesRotated;
if (navbarRotation == 0) {
- degreesRotated = mOrientationState.areMultipleLayoutOrientationsDisabled() ? 0 :
- RotationHelper.getDegreesFromRotation(mLayoutRotation);
+ degreesRotated = mOrientationState.getTouchRotationDegrees();
} else {
degreesRotated = -navbarRotation;
}
@@ -2001,14 +2014,14 @@
return e -> {
if (navbarRotation != 0
&& !mOrientationState.areMultipleLayoutOrientationsDisabled()) {
- RotationHelper.transformEventForNavBar(e, true);
+ mOrientationState.flipVertical(e);
super.onTouchEvent(e);
- RotationHelper.transformEventForNavBar(e, false);
+ mOrientationState.flipVertical(e);
return;
}
- RotationHelper.transformEvent(-degreesRotated, e, true);
+ mOrientationState.transformEvent(-degreesRotated, e, true);
super.onTouchEvent(e);
- RotationHelper.transformEvent(-degreesRotated, e, false);
+ mOrientationState.transformEvent(-degreesRotated, e, false);
};
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index 7010f9a..ceb099f 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -64,7 +64,6 @@
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.popup.SystemShortcut;
-import com.android.launcher3.states.RotationHelper;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.PagedOrientationHandler;
@@ -79,6 +78,7 @@
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.util.LayoutUtils;
+import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.util.TaskCornerRadius;
import com.android.quickstep.views.RecentsView.PageCallbacks;
import com.android.quickstep.views.RecentsView.ScrollState;
@@ -119,19 +119,6 @@
private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT =
Collections.singletonList(new Rect());
- public static final FloatProperty<TaskView> FULLSCREEN_PROGRESS =
- new FloatProperty<TaskView>("fullscreenProgress") {
- @Override
- public void setValue(TaskView taskView, float v) {
- taskView.setFullscreenProgress(v);
- }
-
- @Override
- public Float get(TaskView taskView) {
- return taskView.mFullscreenProgress;
- }
- };
-
private static final FloatProperty<TaskView> FOCUS_TRANSITION =
new FloatProperty<TaskView>("focusTransition") {
@Override
@@ -286,11 +273,11 @@
/**
* Updates this task view to the given {@param task}.
*/
- public void bind(Task task, int recentsRotation) {
+ public void bind(Task task, RecentsOrientedState orientedState) {
cancelPendingLoadTasks();
mTask = task;
mSnapshotView.bind(task);
- setOverviewRotation(recentsRotation);
+ setOrientationState(orientedState);
}
public Task getTask() {
@@ -459,14 +446,15 @@
}
}
- void setOverviewRotation(int iconRotation) {
- PagedOrientationHandler orientationHandler = getRecentsView().getPagedOrientationHandler();
+ public void setOrientationState(RecentsOrientedState orientationState) {
+ int iconRotation = orientationState.getTouchRotation();
+ PagedOrientationHandler orientationHandler = orientationState.getOrientationHandler();
boolean isRtl = orientationHandler.getRecentsRtlSetting(getResources());
LayoutParams snapshotParams = (LayoutParams) mSnapshotView.getLayoutParams();
snapshotParams.bottomMargin = LayoutUtils.thumbnailBottomMargin(getContext());
int thumbnailPadding = (int) getResources().getDimension(R.dimen.task_thumbnail_top_margin);
LayoutParams iconParams = (LayoutParams) mIconView.getLayoutParams();
- int rotation = RotationHelper.getDegreesFromRotation(iconRotation);
+ int rotation = orientationState.getTouchRotationDegrees();
switch (iconRotation) {
case Surface.ROTATION_90:
iconParams.gravity = (isRtl ? END : START) | CENTER_VERTICAL;
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 8d42c4a..dcc85d5 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -66,9 +66,6 @@
docked_stack_divider_thickness - 2 * docked_stack_divider_insets -->
<dimen name="multi_window_task_divider_size">10dp</dimen>
- <!-- same as vertical_drag_handle_size -->
- <dimen name="shelf_surface_offset">24dp</dimen>
-
<!-- Assistant Gestures -->
<!-- Distance from the vertical edges of the screen in which assist gestures are recognized -->
<dimen name="gestures_assistant_width">48dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PreviewSurfaceRenderer.java b/quickstep/src/com/android/launcher3/uioverrides/PreviewSurfaceRenderer.java
deleted file mode 100644
index c7cce0b..0000000
--- a/quickstep/src/com/android/launcher3/uioverrides/PreviewSurfaceRenderer.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2020 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.launcher3.uioverrides;
-
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.util.Size;
-import android.view.View;
-
-import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.graphics.LauncherPreviewRenderer;
-import com.android.systemui.shared.system.SurfaceViewRequestReceiver;
-
-/** Render preview using surface view. */
-public class PreviewSurfaceRenderer {
-
- /** Handle a received surface view request. */
- public static void render(Context context, Bundle bundle) {
- String gridName = bundle.getString("name");
- bundle.remove("name");
- if (gridName == null) {
- gridName = InvariantDeviceProfile.getCurrentGridName(context);
- }
- final InvariantDeviceProfile idp = new InvariantDeviceProfile(context, gridName);
-
- MAIN_EXECUTOR.execute(() -> {
- View view = new LauncherPreviewRenderer(context, idp).getRenderedView();
- new SurfaceViewRequestReceiver().onReceive(context, bundle, view,
- new Size(view.getMeasuredWidth(), view.getMeasuredHeight()));
- });
- }
-}
diff --git a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
index 3e73f49..95cd4f2 100644
--- a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
+++ b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
@@ -22,6 +22,8 @@
import static android.view.MotionEvent.ACTION_POINTER_DOWN;
import static android.view.MotionEvent.ACTION_UP;
+import static com.android.quickstep.util.RecentsOrientedState.postDisplayRotation;
+
import android.content.res.Resources;
import android.graphics.Matrix;
import android.graphics.Point;
@@ -33,8 +35,8 @@
import com.android.launcher3.R;
import com.android.launcher3.ResourceUtils;
-import com.android.launcher3.states.RotationHelper;
import com.android.launcher3.util.DefaultDisplay;
+import com.android.quickstep.util.RecentsOrientedState.SurfaceRotation;
import java.io.PrintWriter;
@@ -52,6 +54,9 @@
private static final boolean DEBUG = false;
private static final int MAX_ORIENTATIONS = 4;
+ private final Matrix mTmpMatrix = new Matrix();
+ private final float[] mTmpPoint = new float[2];
+
private SparseArray<OrientationRectF> mSwipeTouchRegions = new SparseArray<>(MAX_ORIENTATIONS);
private final RectF mAssistantLeftRegion = new RectF();
private final RectF mAssistantRightRegion = new RectF();
@@ -304,42 +309,46 @@
}
boolean applyTransform(MotionEvent event, boolean forceTransform) {
- // TODO(b/149658423): See if we can use RotationHelper.getRotationMatrix here
- MotionEvent tmp = MotionEvent.obtain(event);
- Matrix outMatrix = new Matrix();
- int delta = RotationHelper.deltaRotation(mCurrentRotation, mRotation);
- switch (delta) {
- case Surface.ROTATION_0:
- outMatrix.reset();
- break;
- case Surface.ROTATION_90:
- outMatrix.setRotate(270);
- outMatrix.postTranslate(0, mHeight);
- break;
- case Surface.ROTATION_180:
- outMatrix.setRotate(180);
- outMatrix.postTranslate(mHeight, mWidth);
- break;
- case Surface.ROTATION_270:
- outMatrix.setRotate(90);
- outMatrix.postTranslate(mWidth, 0);
- break;
+ mTmpMatrix.reset();
+ postDisplayRotation(deltaRotation(mCurrentRotation, mRotation),
+ mHeight, mWidth, mTmpMatrix);
+ if (forceTransform) {
+ if (DEBUG) {
+ Log.d(TAG, "Transforming rotation due to forceTransform, "
+ + "mCurrentRotation: " + mCurrentRotation
+ + "mRotation: " + mRotation);
+ }
+ event.transform(mTmpMatrix);
+ return true;
}
+ mTmpPoint[0] = event.getX();
+ mTmpPoint[1] = event.getY();
+ mTmpMatrix.mapPoints(mTmpPoint);
- tmp.transform(outMatrix);
if (DEBUG) {
Log.d(TAG, "original: " + event.getX() + ", " + event.getY()
- + " new: " + tmp.getX() + ", " + tmp.getY()
+ + " new: " + mTmpPoint[0] + ", " + mTmpPoint[1]
+ " rect: " + this + " forceTransform: " + forceTransform
- + " contains: " + contains(tmp.getX(), tmp.getY()));
+ + " contains: " + contains(mTmpPoint[0], mTmpPoint[1]));
}
- if (forceTransform || contains(tmp.getX(), tmp.getY())) {
- event.transform(outMatrix);
- tmp.recycle();
+ if (contains(mTmpPoint[0], mTmpPoint[1])) {
+ event.transform(mTmpMatrix);
return true;
}
return false;
}
}
+
+ /**
+ * @return how many factors {@param newRotation} is rotated 90 degrees clockwise.
+ * E.g. 1->Rotated by 90 degrees clockwise, 2->Rotated 180 clockwise...
+ * A value of 0 means no rotation has been applied
+ */
+ @SurfaceRotation
+ private static int deltaRotation(int oldRotation, int newRotation) {
+ int delta = newRotation - oldRotation;
+ if (delta < 0) delta += 4;
+ return delta;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
index ba99016..1f1a999 100644
--- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -33,9 +33,6 @@
import java.lang.annotation.Retention;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
public class LayoutUtils {
private static final int MULTI_WINDOW_STRATEGY_HALF_SCREEN = 1;
@@ -68,7 +65,7 @@
// UI when shown.
extraSpace = 0;
} else {
- extraSpace = getDefaultSwipeHeight(context, dp) + dp.verticalDragHandleSizePx
+ extraSpace = getDefaultSwipeHeight(context, dp) + dp.workspacePageIndicatorHeight
+ res.getDimensionPixelSize(
R.dimen.dynamic_grid_hotseat_extra_vertical_size)
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
new file mode 100644
index 0000000..f72e458
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2020 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.util;
+
+import static android.hardware.camera2.params.OutputConfiguration.ROTATION_180;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.graphics.Matrix;
+import android.graphics.RectF;
+import android.view.MotionEvent;
+import android.view.Surface;
+
+import androidx.annotation.IntDef;
+
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.touch.PagedOrientationHandler;
+import com.android.launcher3.touch.PortraitPagedViewHandler;
+
+import java.lang.annotation.Retention;
+
+/**
+ * Container to hold orientation/rotation related information for Launcher.
+ * This is not meant to be an abstraction layer for applying different functionality between
+ * the different orientation/rotations. For that see {@link PagedOrientationHandler}
+ *
+ * This class has initial default state assuming the device and foreground app have
+ * no ({@link Surface#ROTATION_0} rotation.
+ */
+public final class RecentsOrientedState {
+
+ @Retention(SOURCE)
+ @IntDef({ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270})
+ public @interface SurfaceRotation {}
+
+ private PagedOrientationHandler mOrientationHandler = PagedOrientationHandler.PORTRAIT;
+
+ private @SurfaceRotation int mTouchRotation = ROTATION_0;
+ private @SurfaceRotation int mDisplayRotation = ROTATION_0;
+ /**
+ * If {@code true} we default to {@link PortraitPagedViewHandler} and don't support any fake
+ * launcher orientations.
+ */
+ private boolean mDisableMultipleOrientations;
+
+ private final Matrix mTmpMatrix = new Matrix();
+ private final Matrix mTmpInverseMatrix = new Matrix();
+
+ /**
+ * Sets the appropriate {@link PagedOrientationHandler} for {@link #mOrientationHandler}
+ * @param touchRotation The rotation the nav bar region that is touched is in
+ * @param displayRotation Rotation of the display/device
+ *
+ * @return true if there was any change in the internal state as a result of this call,
+ * false otherwise
+ */
+ public boolean update(
+ @SurfaceRotation int touchRotation, @SurfaceRotation int displayRotation) {
+ if (!FeatureFlags.ENABLE_FIXED_ROTATION_TRANSFORM.get()) {
+ return false;
+ }
+ if (mDisableMultipleOrientations) {
+ return false;
+ }
+ if (mDisplayRotation == displayRotation && mTouchRotation == touchRotation) {
+ return false;
+ }
+
+ mDisplayRotation = displayRotation;
+ mTouchRotation = touchRotation;
+ if (mTouchRotation == ROTATION_90) {
+ mOrientationHandler = PagedOrientationHandler.LANDSCAPE;
+ } else if (mTouchRotation == ROTATION_270) {
+ mOrientationHandler = PagedOrientationHandler.SEASCAPE;
+ } else {
+ mOrientationHandler = PagedOrientationHandler.PORTRAIT;
+ }
+ return true;
+ }
+
+ public boolean areMultipleLayoutOrientationsDisabled() {
+ return mDisableMultipleOrientations;
+ }
+
+ /**
+ * Setting this preference will render future calls to {@link #update(int, int)} as a no-op.
+ */
+ public void disableMultipleOrientations(boolean disable) {
+ mDisableMultipleOrientations = disable;
+ if (disable) {
+ mDisplayRotation = mTouchRotation = ROTATION_0;
+ mOrientationHandler = PagedOrientationHandler.PORTRAIT;
+ }
+ }
+
+ @SurfaceRotation
+ public int getDisplayRotation() {
+ return mDisplayRotation;
+ }
+
+ @SurfaceRotation
+ public int getTouchRotation() {
+ return mTouchRotation;
+ }
+
+ public int getTouchRotationDegrees() {
+ switch (mTouchRotation) {
+ case ROTATION_90:
+ return 90;
+ case ROTATION_180:
+ return 180;
+ case ROTATION_270:
+ return 270;
+ case ROTATION_0:
+ default:
+ return 0;
+ }
+ }
+
+ public PagedOrientationHandler getOrientationHandler() {
+ return mOrientationHandler;
+ }
+
+ /**
+ * For landscape, since the navbar is already in a vertical position, we don't have to do any
+ * rotations as the change in Y coordinate is what is read. We only flip the sign of the
+ * y coordinate to make it match existing behavior of swipe to the top to go previous
+ */
+ public void flipVertical(MotionEvent ev) {
+ mTmpMatrix.setScale(1, -1);
+ ev.transform(mTmpMatrix);
+ }
+
+ /**
+ * Creates a matrix to transform the given motion event specified by degrees.
+ * If inverse is {@code true}, the inverse of that matrix will be applied
+ */
+ public void transformEvent(float degrees, MotionEvent ev, boolean inverse) {
+ mTmpMatrix.setRotate(inverse ? -degrees : degrees);
+ ev.transform(mTmpMatrix);
+
+ // TODO: Add scaling back in based on degrees
+ /*
+ if (getWidth() > 0 && getHeight() > 0) {
+ float scale = ((float) getWidth()) / getHeight();
+ transform.postScale(scale, 1 / scale);
+ }
+ */
+ }
+
+ public void mapRectFromNormalOrientation(RectF src, int screenWidth, int screenHeight) {
+ mTmpMatrix.reset();
+ postDisplayRotation(mDisplayRotation, screenWidth, screenHeight, mTmpMatrix);
+ mTmpMatrix.mapRect(src);
+ }
+
+ public void mapInverseRectFromNormalOrientation(RectF src, int screenWidth, int screenHeight) {
+ mTmpMatrix.reset();
+ postDisplayRotation(mDisplayRotation, screenWidth, screenHeight, mTmpMatrix);
+ mTmpMatrix.invert(mTmpInverseMatrix);
+ mTmpInverseMatrix.mapRect(src);
+ }
+
+ @SurfaceRotation
+ public static int getRotationForUserDegreesRotated(float degrees) {
+ int threshold = 70;
+ if (degrees >= (360 - threshold) || degrees < (threshold)) {
+ return ROTATION_0;
+ } else if (degrees < (90 + threshold)) {
+ return ROTATION_270;
+ } else if (degrees < 180 + threshold) {
+ return ROTATION_180;
+ } else {
+ return ROTATION_90;
+ }
+ }
+
+ /**
+ * Posts the transformation on the matrix representing the provided display rotation
+ */
+ public static void postDisplayRotation(@SurfaceRotation int displayRotation,
+ float screenWidth, float screenHeight, Matrix out) {
+ switch (displayRotation) {
+ case ROTATION_0:
+ return;
+ case ROTATION_90:
+ out.postRotate(270);
+ out.postTranslate(0, screenWidth);
+ break;
+ case ROTATION_180:
+ out.postRotate(180);
+ out.postTranslate(screenHeight, screenWidth);
+ break;
+ case ROTATION_270:
+ out.postRotate(90);
+ out.postTranslate(screenHeight, 0);
+ break;
+ }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
index 14c458e..c2ccd90 100644
--- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
+++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
@@ -88,7 +88,6 @@
private float mShiftRange;
- private final float mShelfOffset;
private float mTopOffset;
private float mShelfTop;
private float mShelfTopAtThreshold;
@@ -110,7 +109,6 @@
mRadius = BOTTOM_CORNER_RADIUS_RATIO * Themes.getDialogCornerRadius(context);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mShelfOffset = context.getResources().getDimension(R.dimen.shelf_surface_offset);
// Just assume the easiest UI for now, until we have the proper layout information.
mDrawingFlatColor = true;
}
@@ -179,7 +177,7 @@
Math.min(hotseatSize, LayoutUtils.getDefaultSwipeHeight(context, dp));
mDragHandleProgress = 1 - (dragHandleTop / mShiftRange);
}
- mTopOffset = dp.getInsets().top - mShelfOffset;
+ mTopOffset = dp.getInsets().top - mDragHandleSize.y;
mShelfTopAtThreshold = mShiftRange * SCRIM_CATCHUP_THRESHOLD + mTopOffset;
}
updateColors();
@@ -190,12 +188,15 @@
@Override
public void updateColors() {
super.updateColors();
+ mDragHandleOffset = 0;
if (mDrawingFlatColor) {
- mDragHandleOffset = 0;
return;
}
- mDragHandleOffset = mShelfOffset - mDragHandleSize;
+ if (mProgress < mDragHandleProgress) {
+ mDragHandleOffset = mShiftRange * (mDragHandleProgress - mProgress);
+ }
+
if (mProgress >= SCRIM_CATCHUP_THRESHOLD) {
mShelfTop = mShiftRange * mProgress + mTopOffset;
} else {
@@ -231,10 +232,6 @@
(float) 0, LINEAR));
mRemainingScreenColor = setColorAlphaBound(mScrimColor, remainingScrimAlpha);
}
-
- if (mProgress < mDragHandleProgress) {
- mDragHandleOffset += mShiftRange * (mDragHandleProgress - mProgress);
- }
}
@Override
@@ -290,4 +287,9 @@
mPaint.setColor(mShelfColor);
canvas.drawRoundRect(0, mShelfTop, width, height + mRadius, mRadius, mRadius, mPaint);
}
+
+ @Override
+ public float getVisualTop() {
+ return mShelfTop;
+ }
}
diff --git a/res/drawable-v24/drag_handle_indicator_shadow.xml b/res/drawable-v24/drag_handle_indicator_shadow.xml
new file mode 100644
index 0000000..774bc38
--- /dev/null
+++ b/res/drawable-v24/drag_handle_indicator_shadow.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<com.android.launcher3.graphics.ShadowDrawable
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/drag_handle_indicator_no_shadow"
+ android:elevation="@dimen/vertical_drag_handle_elevation" />
diff --git a/res/drawable/drag_handle_indicator.xml b/res/drawable/drag_handle_indicator.xml
deleted file mode 100644
index b01b84a..0000000
--- a/res/drawable/drag_handle_indicator.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="@dimen/vertical_drag_handle_size"
- android:height="@dimen/vertical_drag_handle_size"
- android:viewportWidth="36.0"
- android:viewportHeight="36.0" >
-
- <group
- android:translateX="11.5"
- android:translateY="11.5">
- <path
- android:pathData="M2 8.5L6.5 4L11 8.5"
- android:strokeColor="?attr/workspaceAmbientShadowColor"
- android:strokeWidth="3.6"
- android:strokeLineCap="round"
- android:strokeLineJoin="round" />
-
- <path
- android:pathData="M2 8.5L6.5 4L11 8.5"
- android:strokeColor="?attr/workspaceTextColor"
- android:strokeWidth="1.8"
- android:strokeLineCap="round"
- android:strokeLineJoin="round" />
- </group>
-</vector>
diff --git a/res/drawable/drag_handle_indicator_no_shadow.xml b/res/drawable/drag_handle_indicator_no_shadow.xml
new file mode 100644
index 0000000..341e60c
--- /dev/null
+++ b/res/drawable/drag_handle_indicator_no_shadow.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="@dimen/vertical_drag_handle_width"
+ android:height="@dimen/vertical_drag_handle_height"
+ android:viewportWidth="18.0"
+ android:viewportHeight="6.0"
+ android:tint="?attr/workspaceTextColor" >
+
+ <path
+ android:pathData="M17,6c-0.15,0-0.3-0.03-0.45-0.11L9,2.12L1.45,5.89c-0.5,0.25-1.09,
+ 0.05-1.34-0.45S0.06,4.35,0.55,4.11l8-4c0.28-0.14,0.61-0.14,0.89,0l8,4c0.49,0.25,0.69,
+ 0.85,0.45,1.34C17.72,5.8,17.37,6,17,6z"
+ android:fillColor="@android:color/white" />
+</vector>
diff --git a/res/layout/launcher.xml b/res/layout/launcher.xml
index ab6c960..de13277 100644
--- a/res/layout/launcher.xml
+++ b/res/layout/launcher.xml
@@ -57,7 +57,7 @@
<com.android.launcher3.pageindicators.WorkspacePageIndicator
android:id="@+id/page_indicator"
android:layout_width="match_parent"
- android:layout_height="@dimen/vertical_drag_handle_size"
+ android:layout_height="@dimen/workspace_page_indicator_height"
android:layout_gravity="bottom|center_horizontal"
android:theme="@style/HomeScreenElementTheme" />
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 271511e..0b589a2 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -20,7 +20,6 @@
<!-- Dynamic Grid -->
<dimen name="dynamic_grid_edge_margin">8dp</dimen>
- <dimen name="dynamic_grid_page_indicator_line_height">1dp</dimen>
<dimen name="dynamic_grid_icon_drawable_padding">8dp</dimen>
<!-- Minimum space between workspace and hotseat in spring loaded mode -->
<dimen name="dynamic_grid_min_spring_loaded_space">8dp</dimen>
@@ -36,10 +35,18 @@
<dimen name="dynamic_grid_hotseat_extra_vertical_size">34dp</dimen>
<dimen name="dynamic_grid_hotseat_side_padding">0dp</dimen>
+ <!-- Workspace page indicator -->
+ <dimen name="workspace_page_indicator_height">24dp</dimen>
+ <dimen name="workspace_page_indicator_line_height">1dp</dimen>
+ <dimen name="workspace_page_indicator_overlap_workspace">0dp</dimen>
+
<!-- Hotseat/all-apps scrim -->
<dimen name="all_apps_scrim_blur">4dp</dimen>
- <dimen name="vertical_drag_handle_size">24dp</dimen>
- <dimen name="vertical_drag_handle_overlap_workspace">0dp</dimen>
+ <dimen name="vertical_drag_handle_width">18dp</dimen>
+ <dimen name="vertical_drag_handle_height">6dp</dimen>
+ <dimen name="vertical_drag_handle_elevation">1dp</dimen>
+ <dimen name="vertical_drag_handle_touch_size">48dp</dimen>
+ <dimen name="vertical_drag_handle_padding_in_vertical_bar_layout">16dp</dimen>
<!-- Drop target bar -->
<dimen name="dynamic_grid_drop_target_size">48dp</dimen>
diff --git a/res/values/drawables.xml b/res/values/drawables.xml
index 9c57ec1..7d63142 100644
--- a/res/values/drawables.xml
+++ b/res/values/drawables.xml
@@ -18,4 +18,5 @@
<drawable name="ic_remove_shadow">@drawable/ic_remove_no_shadow</drawable>
<drawable name="ic_uninstall_shadow">@drawable/ic_uninstall_no_shadow</drawable>
<drawable name="ic_block_shadow">@drawable/ic_block_no_shadow</drawable>
+ <drawable name="all_apps_arrow_shadow">@drawable/drag_handle_indicator_no_shadow</drawable>
</resources>
\ No newline at end of file
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index c049069..4e1e586 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -76,9 +76,9 @@
public float workspaceSpringLoadShrinkFactor;
public final int workspaceSpringLoadedBottomSpace;
- // Drag handle
- public final int verticalDragHandleSizePx;
- private final int verticalDragHandleOverlapWorkspace;
+ // Workspace page indicator
+ public final int workspacePageIndicatorHeight;
+ private final int mWorkspacePageIndicatorOverlapWorkspace;
// Workspace icons
public int iconSizePx;
@@ -190,10 +190,10 @@
cellLayoutBottomPaddingPx = 0;
}
- verticalDragHandleSizePx = res.getDimensionPixelSize(
- R.dimen.vertical_drag_handle_size);
- verticalDragHandleOverlapWorkspace =
- res.getDimensionPixelSize(R.dimen.vertical_drag_handle_overlap_workspace);
+ workspacePageIndicatorHeight = res.getDimensionPixelSize(
+ R.dimen.workspace_page_indicator_height);
+ mWorkspacePageIndicatorOverlapWorkspace =
+ res.getDimensionPixelSize(R.dimen.workspace_page_indicator_overlap_workspace);
iconDrawablePaddingOriginalPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding);
@@ -211,7 +211,7 @@
hotseatBarSidePaddingEndPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_side_padding);
// Add a bit of space between nav bar and hotseat in vertical bar layout.
- hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? verticalDragHandleSizePx : 0;
+ hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? workspacePageIndicatorHeight : 0;
hotseatBarSizePx = ResourceUtils.pxFromDp(inv.iconSize, dm) + (isVerticalBarLayout()
? (hotseatBarSidePaddingStartPx + hotseatBarSidePaddingEndPx)
: (res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size)
@@ -227,7 +227,7 @@
// in portrait mode closer together by adding more height to the hotseat.
// Note: This calculation was created after noticing a pattern in the design spec.
int extraSpace = getCellSize().y - iconSizePx - iconDrawablePaddingPx * 2
- - verticalDragHandleSizePx;
+ - workspacePageIndicatorHeight;
hotseatBarSizePx += extraSpace;
hotseatBarBottomPaddingPx += extraSpace;
@@ -376,7 +376,7 @@
if (!isVerticalLayout) {
int expectedWorkspaceHeight = availableHeightPx - hotseatBarSizePx
- - verticalDragHandleSizePx - edgeMarginPx;
+ - workspacePageIndicatorHeight - edgeMarginPx;
float minRequiredHeight = dropTargetBarSizePx + workspaceSpringLoadedBottomSpace;
workspaceSpringLoadShrinkFactor = Math.min(
res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f,
@@ -480,14 +480,14 @@
padding.bottom = edgeMarginPx;
if (isSeascape()) {
padding.left = hotseatBarSizePx;
- padding.right = verticalDragHandleSizePx;
+ padding.right = hotseatBarSidePaddingStartPx;
} else {
- padding.left = verticalDragHandleSizePx;
+ padding.left = hotseatBarSidePaddingStartPx;
padding.right = hotseatBarSizePx;
}
} else {
- int paddingBottom = hotseatBarSizePx + verticalDragHandleSizePx
- - verticalDragHandleOverlapWorkspace;
+ int paddingBottom = hotseatBarSizePx + workspacePageIndicatorHeight
+ - mWorkspacePageIndicatorOverlapWorkspace;
if (isTablet) {
// Pad the left and right of the workspace to ensure consistent spacing
// between all icons
@@ -554,7 +554,7 @@
mInsets.top + dropTargetBarSizePx + edgeMarginPx,
mInsets.left + availableWidthPx - edgeMarginPx,
mInsets.top + availableHeightPx - hotseatBarSizePx
- - verticalDragHandleSizePx - edgeMarginPx);
+ - workspacePageIndicatorHeight - edgeMarginPx);
}
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 03817ad..043ea2f 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1140,7 +1140,7 @@
// Setup the drag controller (drop targets have to be added in reverse order in priority)
mDropTargetBar.setup(mDragController);
- mAllAppsController.setupViews(mAppsView);
+ mAllAppsController.setupViews(mAppsView, mScrimView);
}
/**
@@ -1362,6 +1362,10 @@
return mDropTargetBar;
}
+ public ScrimView getScrimView() {
+ return mScrimView;
+ }
+
public LauncherAppWidgetHost getAppWidgetHost() {
return mAppWidgetHost;
}
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 5e47e2f..e36ae94 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -38,7 +38,6 @@
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
-import android.view.Surface;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
@@ -55,12 +54,10 @@
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.model.PagedViewOrientedState;
import com.android.launcher3.pageindicators.PageIndicator;
import com.android.launcher3.touch.OverScroll;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.touch.PagedOrientationHandler.ChildBounds;
-import com.android.launcher3.touch.PortraitPagedViewHandler;
import com.android.launcher3.util.OverScroller;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.views.ActivityContext;
@@ -121,8 +118,7 @@
private float mLastMotion;
private float mLastMotionRemainder;
private float mTotalMotion;
- protected PagedOrientationHandler mOrientationHandler = new PortraitPagedViewHandler();
- protected final PagedViewOrientedState mOrientationState = new PagedViewOrientedState();
+ protected PagedOrientationHandler mOrientationHandler = PagedOrientationHandler.PORTRAIT;
protected int[] mPageScrolls;
private boolean mIsBeingDragged;
@@ -144,9 +140,6 @@
protected int mUnboundedScroll;
- protected int mLayoutRotation = Surface.ROTATION_0;
- protected int mDisplayRotation = Surface.ROTATION_0;
-
// Page Indicator
@Thunk int mPageIndicatorViewId;
protected T mPageIndicator;
@@ -417,37 +410,6 @@
return mUnboundedScroll;
}
- protected void updateLayoutRotation(int touchRotation) {
- setLayoutRotation(touchRotation, mDisplayRotation);
- }
-
- /** @param touchRotation Must be one of {@link android.view.Surface.ROTATION_0/90/180/270} */
- public void setLayoutRotation(int touchRotation, int displayRotation) {
- if (mLayoutRotation == touchRotation && mDisplayRotation == displayRotation) {
- return;
- }
-
- mOrientationState.update(touchRotation, displayRotation);
- mOrientationHandler = mOrientationState.getOrientationHandler();
- mLayoutRotation = touchRotation;
- mDisplayRotation = displayRotation;
- requestLayout();
- }
-
- public PagedViewOrientedState getPagedViewOrientedState() {
- return mOrientationState;
- }
-
- public PagedOrientationHandler getPagedOrientationHandler() {
- return getPagedViewOrientedState().getOrientationHandler();
- }
-
- public void disableMultipleLayoutRotations(boolean disable) {
- mOrientationState.disableMultipleOrientations(disable);
- mOrientationHandler = mOrientationState.getOrientationHandler();
- requestLayout();
- }
-
@Override
public void scrollBy(int x, int y) {
mOrientationHandler.delegateScrollBy(this, getUnboundedScroll(), x, y);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index fc40fa6..7c504a6 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -124,7 +124,7 @@
private static final int ADJACENT_SCREEN_DROP_DURATION = 300;
- private static final int DEFAULT_PAGE = 0;
+ public static final int DEFAULT_PAGE = 0;
private LayoutTransition mLayoutTransition;
@Thunk final WallpaperManager mWallpaperManager;
@@ -282,6 +282,7 @@
Rect padding = grid.workspacePadding;
setPadding(padding.left, padding.top, padding.right, padding.bottom);
+ mInsets.set(insets);
if (mWorkspaceFadeInAdjacentScreens) {
// In landscape mode the page spacing is set to the default.
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 7600f52..68b0706 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -123,8 +123,8 @@
// Use a light system UI (dark icons) if all apps is behind at least half of the
// status bar.
- boolean forceChange = shiftCurrent - mScrimView.getDragHandleSize()
- <= mLauncher.getDeviceProfile().getInsets().top / 2;
+ boolean forceChange = Math.min(shiftCurrent, mScrimView.getVisualTop())
+ <= mLauncher.getDeviceProfile().getInsets().top / 2f;
if (forceChange) {
mLauncher.getSystemUiController().updateUiState(UI_STATE_ALL_APPS, !mIsDarkTheme);
} else {
@@ -212,9 +212,9 @@
return AnimationSuccessListener.forRunnable(this::onProgressAnimationEnd);
}
- public void setupViews(AllAppsContainerView appsView) {
+ public void setupViews(AllAppsContainerView appsView, ScrimView scrimView) {
mAppsView = appsView;
- mScrimView = mLauncher.findViewById(R.id.scrim_view);
+ mScrimView = scrimView;
}
/**
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index ec34350..bcd91da 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -92,8 +92,8 @@
public static final BooleanFlag ENABLE_QUICKSTEP_LIVE_TILE = getDebugFlag(
"ENABLE_QUICKSTEP_LIVE_TILE", false, "Enable live tile in Quickstep overview");
- public static final BooleanFlag ENABLE_HINTS_IN_OVERVIEW = getDebugFlag(
- "ENABLE_HINTS_IN_OVERVIEW", false, "Show chip hints and gleams on the overview screen");
+ public static final BooleanFlag ENABLE_SUGGESTED_ACTIONS_OVERVIEW = new DeviceFlag(
+ "ENABLE_SUGGESTED_ACTIONS_OVERVIEW", false, "Show chip hints on the overview screen");
public static final BooleanFlag FOLDER_NAME_SUGGEST = new DeviceFlag(
"FOLDER_NAME_SUGGEST", true,
diff --git a/src/com/android/launcher3/graphics/GridOptionsProvider.java b/src/com/android/launcher3/graphics/GridOptionsProvider.java
index 607aba9..af974f8 100644
--- a/src/com/android/launcher3/graphics/GridOptionsProvider.java
+++ b/src/com/android/launcher3/graphics/GridOptionsProvider.java
@@ -20,7 +20,6 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.InvariantDeviceProfile.GridOption;
import com.android.launcher3.R;
-import com.android.launcher3.uioverrides.PreviewSurfaceRenderer;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -201,12 +200,11 @@
}
@Override
- public Bundle call(String method, String arg, Bundle extras) {
+ public Bundle call(String method, String arg, Bundle extras) {
if (!METHOD_GET_PREVIEW.equals(method)) {
return null;
}
- PreviewSurfaceRenderer.render(getContext(), extras);
- return null;
+ return new PreviewSurfaceRenderer(getContext(), extras).render();
}
}
diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
new file mode 100644
index 0000000..20eec9a
--- /dev/null
+++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2020 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.launcher3.graphics;
+
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+
+import android.content.Context;
+import android.hardware.display.DisplayManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.view.Display;
+import android.view.SurfaceControlViewHost;
+import android.view.View;
+
+import com.android.launcher3.InvariantDeviceProfile;
+
+import java.util.concurrent.TimeUnit;
+
+/** Render preview using surface view. */
+public class PreviewSurfaceRenderer implements IBinder.DeathRecipient {
+
+ private static final String KEY_HOST_TOKEN = "host_token";
+ private static final String KEY_VIEW_WIDTH = "width";
+ private static final String KEY_VIEW_HEIGHT = "height";
+ private static final String KEY_DISPLAY_ID = "display_id";
+ private static final String KEY_SURFACE_PACKAGE = "surface_package";
+ private static final String KEY_CALLBACK = "callback";
+
+ private final Context mContext;
+ private final InvariantDeviceProfile mIdp;
+ private final IBinder mHostToken;
+ private final int mWidth;
+ private final int mHeight;
+ private final Display mDisplay;
+
+ private SurfaceControlViewHost mSurfaceControlViewHost;
+
+ PreviewSurfaceRenderer(Context context, Bundle bundle) {
+ mContext = context;
+
+ String gridName = bundle.getString("name");
+ bundle.remove("name");
+ if (gridName == null) {
+ gridName = InvariantDeviceProfile.getCurrentGridName(context);
+ }
+ mIdp = new InvariantDeviceProfile(context, gridName);
+
+ mHostToken = bundle.getBinder(KEY_HOST_TOKEN);
+ mWidth = bundle.getInt(KEY_VIEW_WIDTH);
+ mHeight = bundle.getInt(KEY_VIEW_HEIGHT);
+
+ final DisplayManager displayManager = (DisplayManager) context.getSystemService(
+ Context.DISPLAY_SERVICE);
+ mDisplay = displayManager.getDisplay(bundle.getInt(KEY_DISPLAY_ID));
+ }
+
+ /** Handle a received surface view request. */
+ Bundle render() {
+ if (mSurfaceControlViewHost != null) {
+ binderDied();
+ }
+
+ try {
+ mSurfaceControlViewHost = MAIN_EXECUTOR
+ .submit(() -> new SurfaceControlViewHost(mContext, mDisplay, mHostToken))
+ .get(5, TimeUnit.SECONDS);
+ mHostToken.linkToDeath(this, 0);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+
+ MAIN_EXECUTOR.execute(() -> {
+ View view = new LauncherPreviewRenderer(mContext, mIdp).getRenderedView();
+ // This aspect scales the view to fit in the surface and centers it
+ final float scale = Math.min(mWidth / (float) view.getMeasuredWidth(),
+ mHeight / (float) view.getMeasuredHeight());
+ view.setScaleX(scale);
+ view.setScaleY(scale);
+ view.setPivotX(0);
+ view.setPivotY(0);
+ view.setTranslationX((mWidth - scale * view.getWidth()) / 2);
+ view.setTranslationY((mHeight - scale * view.getHeight()) / 2);
+ mSurfaceControlViewHost.setView(view, view.getMeasuredWidth(),
+ view.getMeasuredHeight());
+ });
+
+ Bundle result = new Bundle();
+ result.putParcelable(KEY_SURFACE_PACKAGE, mSurfaceControlViewHost.getSurfacePackage());
+
+ Handler handler = new Handler(Looper.getMainLooper(), Loopermessage -> {
+ binderDied();
+ return true;
+ });
+ Messenger messenger = new Messenger(handler);
+ Message msg = Message.obtain();
+ msg.replyTo = messenger;
+ result.putParcelable(KEY_CALLBACK, msg);
+ return result;
+ }
+
+ @Override
+ public void binderDied() {
+ if (mSurfaceControlViewHost != null) {
+ mSurfaceControlViewHost.release();
+ mSurfaceControlViewHost = null;
+ }
+ mHostToken.unlinkToDeath(this, 0);
+ }
+}
diff --git a/src/com/android/launcher3/model/PagedViewOrientedState.java b/src/com/android/launcher3/model/PagedViewOrientedState.java
deleted file mode 100644
index e48b8c1..0000000
--- a/src/com/android/launcher3/model/PagedViewOrientedState.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- *
- * * Copyright (C) 2020 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.launcher3.model;
-
-import android.view.Surface;
-
-import com.android.launcher3.states.RotationHelper;
-import com.android.launcher3.touch.PortraitPagedViewHandler;
-import com.android.launcher3.touch.LandscapePagedViewHandler;
-import com.android.launcher3.touch.PagedOrientationHandler;
-import com.android.launcher3.touch.SeascapePagedViewHandler;
-
-/**
- * Container to hold orientation/rotation related information for Launcher.
- * This is not meant to be an abstraction layer for applying different functionality between
- * the different orientation/rotations. For that see {@link PagedOrientationHandler}
- *
- * This class has initial default state assuming the device and foreground app have
- * no ({@link Surface.ROTATION_0} rotation.
- *
- * Currently this class resides in {@link com.android.launcher3.PagedView}, but there's a ticket
- * to disassociate it from Launcher since it's needed before Launcher is instantiated
- * See TODO(b/150300347)
- */
-public final class PagedViewOrientedState {
-
- private PagedOrientationHandler mOrientationHandler = new PortraitPagedViewHandler();
-
- private int mTouchRotation = Surface.ROTATION_0;
- private int mDisplayRotation = Surface.ROTATION_0;
- /**
- * If {@code true} we default to {@link PortraitPagedViewHandler} and don't support any fake
- * launcher orientations.
- */
- private boolean mDisableMultipleOrientations;
-
- /**
- * Sets the appropriate {@link PagedOrientationHandler} for {@link #mOrientationHandler}
- * @param touchRotation The rotation the nav bar region that is touched is in
- * @param displayRotation Rotation of the display/device
- */
- public void update(int touchRotation, int displayRotation) {
- if (mDisableMultipleOrientations) {
- return;
- }
-
- mDisplayRotation = displayRotation;
- mTouchRotation = touchRotation;
- if (mTouchRotation == Surface.ROTATION_90) {
- mOrientationHandler = new LandscapePagedViewHandler();
- } else if (mTouchRotation == Surface.ROTATION_270) {
- mOrientationHandler = new SeascapePagedViewHandler();
- } else {
- mOrientationHandler = new PortraitPagedViewHandler();
- }
- }
-
- public boolean areMultipleLayoutOrientationsDisabled() {
- return mDisableMultipleOrientations;
- }
-
- /**
- * Setting this preference will render future calls to {@link #update(int, int)} as a no-op.
- */
- public void disableMultipleOrientations(boolean disable) {
- mDisableMultipleOrientations = disable;
- if (disable) {
- mOrientationHandler = new PortraitPagedViewHandler();
- }
- }
-
- public int getDisplayRotation() {
- return mDisplayRotation;
- }
-
- /**
- * Gets the difference between the rotation of the device/display and which region the
- * user is currently interacting with in factors of 90 degree clockwise rotations.
- * Ex. Display is in portrait -> 0, user touches landscape region -> 1, this
- * method would return 3 because it takes 3 clockwise 90 degree rotations from normal to
- * landscape (portrait -> seascape -> reverse portrait -> landscape)
- */
- public int getTouchDisplayDelta() {
- return RotationHelper.deltaRotation(mTouchRotation, mDisplayRotation);
- }
-
- public PagedOrientationHandler getOrientationHandler() {
- return mOrientationHandler;
- }
-}
diff --git a/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java b/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
index 0f2ca72..408796f 100644
--- a/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
@@ -121,7 +121,7 @@
mLinePaint.setAlpha(0);
mLauncher = Launcher.getLauncher(context);
- mLineHeight = res.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_line_height);
+ mLineHeight = res.getDimensionPixelSize(R.dimen.workspace_page_indicator_line_height);
boolean darkText = WallpaperColorInfo.INSTANCE.get(context).supportsDarkText();
mActiveAlpha = darkText ? BLACK_ALPHA : WHITE_ALPHA;
diff --git a/src/com/android/launcher3/states/HintState.java b/src/com/android/launcher3/states/HintState.java
index 290dbb6..43f30f1 100644
--- a/src/com/android/launcher3/states/HintState.java
+++ b/src/com/android/launcher3/states/HintState.java
@@ -17,6 +17,7 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.LauncherStateManager;
import com.android.launcher3.Workspace;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -50,8 +51,13 @@
@Override
public void onStateTransitionEnd(Launcher launcher) {
- launcher.getStateManager().goToState(NORMAL);
+ LauncherStateManager stateManager = launcher.getStateManager();
Workspace workspace = launcher.getWorkspace();
- workspace.post(workspace::moveToDefaultScreen);
+ boolean willMoveScreens = workspace.getNextPage() != Workspace.DEFAULT_PAGE;
+ stateManager.goToState(NORMAL, true, willMoveScreens ? null
+ : launcher.getScrimView()::startDragHandleEducationAnim);
+ if (willMoveScreens) {
+ workspace.post(workspace::moveToDefaultScreen);
+ }
}
}
diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java
index 8bb6a08..2e0521f 100644
--- a/src/com/android/launcher3/states/RotationHelper.java
+++ b/src/com/android/launcher3/states/RotationHelper.java
@@ -31,12 +31,7 @@
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.Resources;
-import android.graphics.Matrix;
-import android.graphics.Rect;
-import android.graphics.RectF;
import android.provider.Settings;
-import android.view.MotionEvent;
-import android.view.Surface;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -258,138 +253,6 @@
}
}
- public static int getDegreesFromRotation(int rotation) {
- int degrees;
- switch (rotation) {
- case Surface.ROTATION_90:
- degrees = 90;
- break;
- case Surface.ROTATION_180:
- degrees = 180;
- break;
- case Surface.ROTATION_270:
- degrees = 270;
- break;
- case Surface.ROTATION_0:
- default:
- degrees = 0;
- break;
- }
- return degrees;
- }
-
- public static int getRotationFromDegrees(float degrees) {
- int threshold = 70;
- if (degrees >= (360 - threshold) || degrees < (threshold)) {
- return Surface.ROTATION_0;
- } else if (degrees < (90 + threshold)) {
- return Surface.ROTATION_270;
- } else if (degrees < 180 + threshold) {
- return Surface.ROTATION_180;
- } else {
- return Surface.ROTATION_90;
- }
- }
-
- /**
- * @return how many factors {@param newRotation} is rotated 90 degrees clockwise.
- * E.g. 1->Rotated by 90 degrees clockwise, 2->Rotated 180 clockwise...
- * A value of 0 means no rotation has been applied
- */
- public static int deltaRotation(int oldRotation, int newRotation) {
- int delta = newRotation - oldRotation;
- if (delta < 0) delta += 4;
- return delta;
- }
-
- /**
- * For landscape, since the navbar is already in a vertical position, we don't have to do any
- * rotations as the change in Y coordinate is what is read. We only flip the sign of the
- * y coordinate to make it match existing behavior of swipe to the top to go previous
- */
- public static void transformEventForNavBar(MotionEvent ev, boolean inverse) {
- // TODO(b/151269990): Use a temp matrix
- Matrix m = new Matrix();
- m.setScale(1, -1);
- if (inverse) {
- Matrix inv = new Matrix();
- m.invert(inv);
- ev.transform(inv);
- } else {
- ev.transform(m);
- }
- }
-
- /**
- * Creates a matrix to transform the given motion event specified by degrees.
- * If {@param inverse} is {@code true}, the inverse of that matrix will be applied
- */
- public static void transformEvent(float degrees, MotionEvent ev, boolean inverse) {
- Matrix transform = new Matrix();
- // TODO(b/151269990): Use a temp matrix
- transform.setRotate(degrees);
- if (inverse) {
- Matrix inv = new Matrix();
- transform.invert(inv);
- ev.transform(inv);
- } else {
- ev.transform(transform);
- }
- // TODO: Add scaling back in based on degrees
-// if (getWidth() > 0 && getHeight() > 0) {
-// float scale = ((float) getWidth()) / getHeight();
-// transform.postScale(scale, 1 / scale);
-// }
- }
-
- /**
- * TODO(b/149658423): Have {@link com.android.quickstep.OrientationTouchTransformer
- * also use this}
- */
- public static Matrix getRotationMatrix(int screenWidth, int screenHeight, int displayRotation) {
- Matrix m = new Matrix();
- // TODO(b/151269990): Use a temp matrix
- switch (displayRotation) {
- case Surface.ROTATION_0:
- return m;
- case Surface.ROTATION_90:
- m.setRotate(360 - RotationHelper.getDegreesFromRotation(displayRotation));
- m.postTranslate(0, screenWidth);
- break;
- case Surface.ROTATION_270:
- m.setRotate(360 - RotationHelper.getDegreesFromRotation(displayRotation));
- m.postTranslate(screenHeight, 0);
- break;
- }
- return m;
- }
-
- public static void mapRectFromNormalOrientation(RectF src, int screenWidth, int screenHeight,
- int displayRotation) {
- Matrix m = RotationHelper.getRotationMatrix(screenWidth, screenHeight, displayRotation);
- m.mapRect(src);
- }
-
- public static void mapInverseRectFromNormalOrientation(RectF src, int screenWidth,
- int screenHeight, int displayRotation) {
- Matrix m = RotationHelper.getRotationMatrix(screenWidth, screenHeight, displayRotation);
- Matrix inverse = new Matrix();
- m.invert(inverse);
- inverse.mapRect(src);
- }
-
- public static void getTargetRectForRotation(Rect srcOut, int screenWidth, int screenHeight,
- int displayRotation) {
- RectF wrapped = new RectF(srcOut);
- Matrix m = RotationHelper.getRotationMatrix(screenWidth, screenHeight, displayRotation);
- m.mapRect(wrapped);
- wrapped.round(srcOut);
- }
-
- public static boolean isRotationLandscape(int rotation) {
- return rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90;
- }
-
@Override
public String toString() {
return String.format("[mStateHandlerRequest=%d, mCurrentStateRequest=%d,"
diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java
index 24fa815..974e3f3 100644
--- a/src/com/android/launcher3/touch/PagedOrientationHandler.java
+++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java
@@ -39,6 +39,10 @@
*/
public interface PagedOrientationHandler {
+ PagedOrientationHandler PORTRAIT = new PortraitPagedViewHandler();
+ PagedOrientationHandler LANDSCAPE = new LandscapePagedViewHandler();
+ PagedOrientationHandler SEASCAPE = new SeascapePagedViewHandler();
+
interface Int2DAction<T> {
void call(T target, int x, int y);
}
diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java
index 6d204f6..39e1eac 100644
--- a/src/com/android/launcher3/views/ScrimView.java
+++ b/src/com/android/launcher3/views/ScrimView.java
@@ -22,8 +22,10 @@
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.anim.Interpolators.ACCEL;
+import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
import android.animation.Animator;
@@ -33,8 +35,10 @@
import android.animation.PropertyValuesHolder;
import android.animation.RectEvaluator;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
@@ -98,6 +102,12 @@
private static final int SETTINGS = R.string.settings_button_text;
private static final int ALPHA_CHANNEL_COUNT = 1;
+ private static final long DRAG_HANDLE_BOUNCE_DURATION_MS = 300;
+ // How much to delay before repeating the bounce.
+ private static final long DRAG_HANDLE_BOUNCE_DELAY_MS = 200;
+ // Repeat this many times (i.e. total number of bounces is 1 + this).
+ private static final int DRAG_HANDLE_BOUNCE_REPEAT_COUNT = 2;
+
private final Rect mTempRect = new Rect();
private final int[] mTempPos = new int[2];
@@ -115,10 +125,13 @@
protected int mEndFlatColor;
protected int mEndFlatColorAlpha;
- protected final int mDragHandleSize;
+ protected final Point mDragHandleSize;
+ private final int mDragHandleTouchSize;
+ private final int mDragHandlePaddingInVerticalBarLayout;
protected float mDragHandleOffset;
private final Rect mDragHandleBounds;
private final RectF mHitRect = new RectF();
+ private ObjectAnimator mDragHandleAnim;
private final MultiValueAlpha mMultiValueAlpha;
@@ -136,9 +149,13 @@
mMaxScrimAlpha = 0.7f;
- mDragHandleSize = context.getResources()
- .getDimensionPixelSize(R.dimen.vertical_drag_handle_size);
- mDragHandleBounds = new Rect(0, 0, mDragHandleSize, mDragHandleSize);
+ Resources res = context.getResources();
+ mDragHandleSize = new Point(res.getDimensionPixelSize(R.dimen.vertical_drag_handle_width),
+ res.getDimensionPixelSize(R.dimen.vertical_drag_handle_height));
+ mDragHandleBounds = new Rect(0, 0, mDragHandleSize.x, mDragHandleSize.y);
+ mDragHandleTouchSize = res.getDimensionPixelSize(R.dimen.vertical_drag_handle_touch_size);
+ mDragHandlePaddingInVerticalBarLayout = context.getResources()
+ .getDimensionPixelSize(R.dimen.vertical_drag_handle_padding_in_vertical_bar_layout);
mAccessibilityHelper = createAccessibilityHelper();
ViewCompat.setAccessibilityDelegate(this, mAccessibilityHelper);
@@ -204,6 +221,7 @@
public void setProgress(float progress) {
if (mProgress != progress) {
mProgress = progress;
+ stopDragHandleEducationAnim();
updateColors();
updateDragHandleAlpha();
invalidate();
@@ -251,70 +269,103 @@
@Override
public boolean onTouchEvent(MotionEvent event) {
- boolean value = super.onTouchEvent(event);
- if (!value && mDragHandle != null && event.getAction() == ACTION_DOWN
- && mDragHandle.getAlpha() == 255
- && mHitRect.contains(event.getX(), event.getY())) {
-
- final Drawable drawable = mDragHandle;
- mDragHandle = null;
-
- Rect bounds = new Rect(mDragHandleBounds);
- bounds.offset(0, -(int) mDragHandleOffset);
- drawable.setBounds(bounds);
-
- Rect topBounds = new Rect(bounds);
- topBounds.offset(0, -bounds.height() / 2);
-
- Rect invalidateRegion = new Rect(bounds);
- invalidateRegion.top = topBounds.top;
-
- Keyframe frameTop = Keyframe.ofObject(0.6f, topBounds);
- frameTop.setInterpolator(DEACCEL);
- Keyframe frameBot = Keyframe.ofObject(1, bounds);
- frameBot.setInterpolator(ACCEL);
- PropertyValuesHolder holder = PropertyValuesHolder .ofKeyframe("bounds",
- Keyframe.ofObject(0, bounds), frameTop, frameBot);
- holder.setEvaluator(new RectEvaluator());
-
- ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(drawable, holder);
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- getOverlay().remove(drawable);
- updateDragHandleVisibility(drawable);
+ boolean superHandledTouch = super.onTouchEvent(event);
+ if (event.getAction() == ACTION_DOWN) {
+ if (!superHandledTouch && mHitRect.contains(event.getX(), event.getY())) {
+ if (startDragHandleEducationAnim()) {
+ return true;
}
- });
- anim.addUpdateListener((v) -> invalidate(invalidateRegion));
- getOverlay().add(drawable);
- anim.start();
- return true;
+ }
+ stopDragHandleEducationAnim();
}
- return value;
+ return superHandledTouch;
+ }
+
+ /**
+ * Animates the drag handle to demonstrate how to get to all apps.
+ * @return Whether the animation was started (false if drag handle is invisible).
+ */
+ public boolean startDragHandleEducationAnim() {
+ stopDragHandleEducationAnim();
+
+ if (mDragHandle == null || mDragHandle.getAlpha() != 255) {
+ return false;
+ }
+
+ final Drawable drawable = mDragHandle;
+ mDragHandle = null;
+
+ Rect bounds = new Rect(mDragHandleBounds);
+ bounds.offset(0, -(int) mDragHandleOffset);
+ drawable.setBounds(bounds);
+
+ Rect topBounds = new Rect(bounds);
+ topBounds.offset(0, -bounds.height());
+
+ Rect invalidateRegion = new Rect(bounds);
+ invalidateRegion.top = topBounds.top;
+
+ final float progressToReachTop = 0.6f;
+ Keyframe frameTop = Keyframe.ofObject(progressToReachTop, topBounds);
+ frameTop.setInterpolator(DEACCEL);
+ Keyframe frameBot = Keyframe.ofObject(1, bounds);
+ frameBot.setInterpolator(ACCEL_DEACCEL);
+ PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("bounds",
+ Keyframe.ofObject(0, bounds), frameTop, frameBot);
+ holder.setEvaluator(new RectEvaluator());
+
+ mDragHandleAnim = ObjectAnimator.ofPropertyValuesHolder(drawable, holder);
+ long totalBounceDuration = DRAG_HANDLE_BOUNCE_DURATION_MS + DRAG_HANDLE_BOUNCE_DELAY_MS;
+ // The bounce finishes by this progress, the rest of the duration just delays next bounce.
+ float delayStartProgress = 1f - (float) DRAG_HANDLE_BOUNCE_DELAY_MS / totalBounceDuration;
+ mDragHandleAnim.addUpdateListener((v) -> invalidate(invalidateRegion));
+ mDragHandleAnim.setDuration(totalBounceDuration);
+ mDragHandleAnim.setInterpolator(clampToProgress(LINEAR, 0, delayStartProgress));
+ mDragHandleAnim.setRepeatCount(DRAG_HANDLE_BOUNCE_REPEAT_COUNT);
+ getOverlay().add(drawable);
+
+ mDragHandleAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mDragHandleAnim = null;
+ getOverlay().remove(drawable);
+ updateDragHandleVisibility(drawable);
+ }
+ });
+ mDragHandleAnim.start();
+ return true;
+ }
+
+ private void stopDragHandleEducationAnim() {
+ if (mDragHandleAnim != null) {
+ mDragHandleAnim.end();
+ }
}
protected void updateDragHandleBounds() {
DeviceProfile grid = mLauncher.getDeviceProfile();
final int left;
final int width = getMeasuredWidth();
- final int top = getMeasuredHeight() - mDragHandleSize - grid.getInsets().bottom;
+ final int top = getMeasuredHeight() - mDragHandleSize.y - grid.getInsets().bottom;
final int topMargin;
if (grid.isVerticalBarLayout()) {
- topMargin = grid.workspacePadding.bottom;
+ topMargin = grid.workspacePadding.bottom + mDragHandlePaddingInVerticalBarLayout;
if (grid.isSeascape()) {
- left = width - grid.getInsets().right - mDragHandleSize;
+ left = width - grid.getInsets().right - mDragHandleSize.x
+ - mDragHandlePaddingInVerticalBarLayout;
} else {
- left = mDragHandleSize + grid.getInsets().left;
+ left = grid.getInsets().left + mDragHandlePaddingInVerticalBarLayout;
}
} else {
- left = (width - mDragHandleSize) / 2;
+ left = Math.round((width - mDragHandleSize.x) / 2f);
topMargin = grid.hotseatBarSizePx;
}
mDragHandleBounds.offsetTo(left, top - topMargin);
mHitRect.set(mDragHandleBounds);
- float inset = -mDragHandleSize / 2;
- mHitRect.inset(inset, inset);
+ // Inset outwards to increase touch size.
+ mHitRect.inset((mDragHandleSize.x - mDragHandleTouchSize) / 2f,
+ (mDragHandleSize.y - mDragHandleTouchSize) / 2f);
if (mDragHandle != null) {
mDragHandle.setBounds(mDragHandleBounds);
@@ -341,7 +392,7 @@
if (visible != wasVisible) {
if (visible) {
mDragHandle = recycle != null ? recycle :
- mLauncher.getDrawable(R.drawable.drag_handle_indicator);
+ mLauncher.getDrawable(R.drawable.drag_handle_indicator_shadow);
mDragHandle.setBounds(mDragHandleBounds);
updateDragHandleAlpha();
@@ -397,7 +448,7 @@
@Override
protected int getVirtualViewAt(float x, float y) {
- return mDragHandleBounds.contains((int) x, (int) y)
+ return mHitRect.contains((int) x, (int) y)
? DRAG_HANDLE_ID : INVALID_ID;
}
@@ -470,7 +521,10 @@
}
}
- public int getDragHandleSize() {
- return mDragHandleSize;
+ /**
+ * @return The top of this scrim view, or {@link Float#MAX_VALUE} if there's no distinct top.
+ */
+ public float getVisualTop() {
+ return Float.MAX_VALUE;
}
}