Merge "Move logic that overrides MotionPauseDetector to callers" into ub-launcher3-qt-dev
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 2267412..11a1885 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.uioverrides;
+import static com.android.launcher3.LauncherState.RECENTS_CLEAR_ALL_BUTTON;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
import android.animation.ValueAnimator;
@@ -22,15 +24,17 @@
import android.os.Build;
import android.util.FloatProperty;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.anim.PropertySetter;
+import com.android.quickstep.views.ClearAllButton;
import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
-import androidx.annotation.NonNull;
-
/**
* State handler for handling UI changes for {@link LauncherRecentsView}. In addition to managing
* the basic view properties, this class also manages changes in the task visuals.
@@ -50,6 +54,7 @@
mRecentsView.updateEmptyMessage();
mRecentsView.resetTaskVisuals();
}
+ setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, state.getVisibleElements(mLauncher));
}
@Override
@@ -71,6 +76,14 @@
builder.play(updateAnim);
mRecentsView.updateEmptyMessage();
}
+
+ setAlphas(config.getPropertySetter(builder), toState.getVisibleElements(mLauncher));
+ }
+
+ private void setAlphas(PropertySetter propertySetter, int visibleElements) {
+ boolean hasClearAllButton = (visibleElements & RECENTS_CLEAR_ALL_BUTTON) != 0;
+ propertySetter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA,
+ hasClearAllButton ? 1f : 0f, LINEAR);
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
index 462e630..140e45c 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
@@ -18,11 +18,10 @@
import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
import android.os.RemoteException;
+
import com.android.launcher3.Launcher;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.quickstep.RecentsModel;
-import com.android.quickstep.SysUINavigationMode;
-import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.recents.ISystemUiProxy;
@@ -75,4 +74,8 @@
return new ScaleAndTranslation(scale, 0f, 0f);
}
+ @Override
+ public int getVisibleElements(Launcher launcher) {
+ return super.getVisibleElements(launcher) & ~RECENTS_CLEAR_ALL_BUTTON;
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
index 043fd55..cda03dc 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -116,9 +116,9 @@
@Override
public int getVisibleElements(Launcher launcher) {
if (launcher.getDeviceProfile().isVerticalBarLayout()) {
- return VERTICAL_SWIPE_INDICATOR;
+ return VERTICAL_SWIPE_INDICATOR | RECENTS_CLEAR_ALL_BUTTON;
} else {
- return HOTSEAT_SEARCH_BOX | VERTICAL_SWIPE_INDICATOR |
+ return HOTSEAT_SEARCH_BOX | VERTICAL_SWIPE_INDICATOR | RECENTS_CLEAR_ALL_BUTTON |
(launcher.getAppsView().getFloatingHeaderView().hasVisibleContent()
? ALL_APPS_HEADER_EXTRA : HOTSEAT_ICONS);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index 8b1b51d..a6c4445 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -17,8 +17,6 @@
import static android.view.View.TRANSLATION_X;
-import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
-import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
@@ -47,7 +45,6 @@
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.touch.SwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Command;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.TouchController;
import com.android.quickstep.views.RecentsView;
@@ -219,6 +216,7 @@
private void logStateChange(int startContainerType, int logAction) {
mLauncher.getUserEventDispatcher().logStateChangeAction(logAction,
LauncherLogProto.Action.Direction.UP,
+ mSwipeDetector.getDownX(), mSwipeDetector.getDownY(),
LauncherLogProto.ContainerType.NAVBAR,
startContainerType,
mEndState.containerType,
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java
index 21e98f2..f12efc8 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java
@@ -26,11 +26,13 @@
import android.graphics.Rect;
import android.graphics.RectF;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.userevent.nano.LauncherLogProto;
-import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.views.RecentsView;
@@ -39,9 +41,6 @@
import java.util.function.BiPredicate;
import java.util.function.Consumer;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
/**
* {@link ActivityControlHelper} for recents when the default launcher is different than the
* currently running one and apps should interact with the {@link RecentsActivity} as opposed
@@ -72,7 +71,9 @@
@Override
public void onSwipeUpComplete(RecentsActivity activity) {
- // TODO:
+ RecentsView recentsView = activity.getOverviewPanel();
+ recentsView.getClearAllButton().setVisibilityAlpha(1);
+ recentsView.setDisallowScrollToClearAll(false);
}
@Override
@@ -121,6 +122,8 @@
RecentsView rv = activity.getOverviewPanel();
rv.setContentAlpha(0);
+ rv.getClearAllButton().setVisibilityAlpha(0);
+ rv.setDisallowScrollToClearAll(true);
return new AnimationFactory() {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java
index 78cc166..44ba515 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java
@@ -354,7 +354,8 @@
: velocityY;
mInteractionHandler.updateDisplacement(getDisplacement(ev) - mStartDisplacement);
- mInteractionHandler.onGestureEnded(velocity, new PointF(velocityX, velocityY));
+ mInteractionHandler.onGestureEnded(velocity, new PointF(velocityX, velocityY),
+ mDownPos);
} else {
// Since we start touch tracking on DOWN, we may reach this state without actually
// starting the gesture. In that case, just cleanup immediately.
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index 8b9a597..fc3f332 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -87,7 +87,7 @@
new LooperExecutor(UiThreadHelper.getBackgroundLooper());
private static final String NAVBAR_VERTICAL_SIZE = "navigation_bar_frame_height";
- private static final String NAVBAR_HORIZONTAL_SIZE = "navigation_bar_frame_width";
+ private static final String NAVBAR_HORIZONTAL_SIZE = "navigation_bar_width";
public static final EventLogArray TOUCH_INTERACTION_LOG =
new EventLogArray("touch_interaction_log", 40);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 365e171..e1b38b3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -253,6 +253,7 @@
private boolean mGestureStarted;
private int mLogAction = Touch.SWIPE;
private int mLogDirection = Direction.UP;
+ private PointF mDownPos;
private final RecentsAnimationWrapper mRecentsAnimationWrapper;
@@ -703,9 +704,10 @@
/**
* @param endVelocity The velocity in the direction of the nav bar to the middle of the screen.
* @param velocity The x and y components of the velocity when the gesture ends.
+ * @param downPos The x and y value of where the gesture started.
*/
@UiThread
- public void onGestureEnded(float endVelocity, PointF velocity) {
+ public void onGestureEnded(float endVelocity, PointF velocity, PointF downPos) {
float flingThreshold = mContext.getResources()
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
boolean isFling = mGestureStarted && Math.abs(endVelocity) > flingThreshold;
@@ -718,6 +720,7 @@
} else {
mLogDirection = velocity.x < 0 ? Direction.LEFT : Direction.RIGHT;
}
+ mDownPos = downPos;
handleNormalGestureEnd(endVelocity, isFling, velocity);
}
@@ -744,14 +747,10 @@
float endShift;
final float startShift;
Interpolator interpolator = DEACCEL;
- int nextPage = 0;
- int taskToLaunch = 0;
final boolean goingToNewTask;
if (mRecentsView != null) {
- nextPage = mRecentsView.getNextPage();
- final int lastTaskIndex = mRecentsView.getTaskViewCount() - 1;
final int runningTaskIndex = mRecentsView.getRunningTaskIndex();
- taskToLaunch = nextPage <= lastTaskIndex ? nextPage : lastTaskIndex;
+ final int taskToLaunch = mRecentsView.getNextPage();
goingToNewTask = runningTaskIndex >= 0 && taskToLaunch != runningTaskIndex;
} else {
goingToNewTask = false;
@@ -817,11 +816,6 @@
}
}
- if (mRecentsView != null && !endTarget.isLauncher && taskToLaunch != nextPage) {
- // Scrolled to Clear all button, snap back to last task and launch it.
- mRecentsView.snapToPage(taskToLaunch, Math.toIntExact(duration), interpolator);
- }
-
if (endTarget == HOME) {
setShelfState(ShelfAnimState.CANCEL, LINEAR, 0);
duration = Math.max(MIN_OVERSHOOT_DURATION, duration);
@@ -856,6 +850,7 @@
: mRecentsView.getNextPage();
UserEventDispatcher.newInstance(mContext).logStateChangeAction(
mLogAction, mLogDirection,
+ (int) mDownPos.x, (int) mDownPos.y,
ContainerType.NAVBAR, ContainerType.APP,
endTarget.containerType,
pageIndex);
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 fbecd84..9db0c09 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
@@ -18,6 +18,7 @@
import android.content.Context;
import android.util.AttributeSet;
+import android.util.Property;
import android.widget.Button;
import com.android.launcher3.Utilities;
@@ -26,8 +27,22 @@
public class ClearAllButton extends Button implements PageCallbacks {
+ public static final Property<ClearAllButton, Float> VISIBILITY_ALPHA =
+ new Property<ClearAllButton, Float>(Float.class, "visibilityAlpha") {
+ @Override
+ public Float get(ClearAllButton view) {
+ return view.mVisibilityAlpha;
+ }
+
+ @Override
+ public void set(ClearAllButton view, Float visibilityAlpha) {
+ view.setVisibilityAlpha(visibilityAlpha);
+ }
+ };
+
private float mScrollAlpha = 1;
private float mContentAlpha = 1;
+ private float mVisibilityAlpha = 1;
private final boolean mIsRtl;
@@ -58,6 +73,13 @@
}
}
+ public void setVisibilityAlpha(float alpha) {
+ if (mVisibilityAlpha != alpha) {
+ mVisibilityAlpha = alpha;
+ updateAlpha();
+ }
+ }
+
@Override
public void onPageScroll(ScrollState scrollState) {
float width = getWidth();
@@ -72,7 +94,7 @@
}
private void updateAlpha() {
- final float alpha = mScrollAlpha * mContentAlpha;
+ final float alpha = mScrollAlpha * mContentAlpha * mVisibilityAlpha;
setAlpha(alpha);
setClickable(alpha == 1);
}
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 c31e829..d6f2235 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
@@ -19,6 +19,7 @@
import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.LauncherState.RECENTS_CLEAR_ALL_BUTTON;
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.ALL_APPS_PROGRESS_OFF_SCREEN;
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
@@ -204,4 +205,15 @@
// the home predictions should have been updated when the activity was resumed.
PredictionUiStateManager.INSTANCE.get(getContext()).switchClient(Client.HOME);
}
+
+ @Override
+ public void setOverviewStateEnabled(boolean enabled) {
+ super.setOverviewStateEnabled(enabled);
+ if (enabled) {
+ LauncherState state = mActivity.getStateManager().getState();
+ boolean hasClearAllButton = (state.getVisibleElements(mActivity)
+ & RECENTS_CLEAR_ALL_BUTTON) != 0;
+ setDisallowScrollToClearAll(!hasClearAllButton);
+ }
+ }
}
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 72d60da..ce8b9cd 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
@@ -18,6 +18,7 @@
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS;
+import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
@@ -27,7 +28,6 @@
import static com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController.SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
-import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.quickstep.util.ClipAnimationHelper.TransformParams;
import android.animation.Animator;
@@ -82,8 +82,6 @@
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PropertyListBuilder;
import com.android.launcher3.anim.SpringObjectAnimator;
-import com.android.launcher3.appprediction.PredictionUiStateManager;
-import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
@@ -92,7 +90,6 @@
import com.android.launcher3.util.PendingAnimation;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.ViewPool;
-import com.android.quickstep.OverviewCallbacks;
import com.android.quickstep.RecentsAnimationWrapper;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.RecentsModel.TaskThumbnailChangeListener;
@@ -172,6 +169,7 @@
private final ViewPool<TaskView> mTaskViewPool;
private boolean mDwbToastShown;
+ private boolean mDisallowScrollToClearAll;
/**
* TODO: Call reloadIdNeeded in onTaskStackChanged.
@@ -1609,4 +1607,33 @@
mRecentsAnimationWrapper.finish(toRecents, onFinishComplete);
}
+
+ public void setDisallowScrollToClearAll(boolean disallowScrollToClearAll) {
+ if (mDisallowScrollToClearAll != disallowScrollToClearAll) {
+ mDisallowScrollToClearAll = disallowScrollToClearAll;
+ updateMinAndMaxScrollX();
+ }
+ }
+
+ @Override
+ protected int computeMinScrollX() {
+ if (mIsRtl && mDisallowScrollToClearAll) {
+ // We aren't showing the clear all button, so use the leftmost task as the min scroll.
+ return getScrollForPage(getTaskViewCount() - 1);
+ }
+ return super.computeMinScrollX();
+ }
+
+ @Override
+ protected int computeMaxScrollX() {
+ if (!mIsRtl && mDisallowScrollToClearAll) {
+ // We aren't showing the clear all button, so use the rightmost task as the max scroll.
+ return getScrollForPage(getTaskViewCount() - 1);
+ }
+ return super.computeMaxScrollX();
+ }
+
+ public ClearAllButton getClearAllButton() {
+ return mClearAllButton;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java b/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java
index ca7711f..4a11601 100644
--- a/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java
+++ b/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java
@@ -42,13 +42,13 @@
public UserEventDispatcherExtension(Context context) { }
- public void logStateChangeAction(int action, int dir, int srcChildTargetType,
- int srcParentContainerType, int dstContainerType,
- int pageIndex) {
+ public void logStateChangeAction(int action, int dir, int downX, int downY,
+ int srcChildTargetType, int srcParentContainerType,
+ int dstContainerType, int pageIndex) {
new MetricsLoggerCompat().visibility(MetricsLoggerCompat.OVERVIEW_ACTIVITY,
dstContainerType == LauncherLogProto.ContainerType.TASKSWITCHER);
- super.logStateChangeAction(action, dir, srcChildTargetType, srcParentContainerType,
- dstContainerType, pageIndex);
+ super.logStateChangeAction(action, dir, downX, downY, srcChildTargetType,
+ srcParentContainerType, dstContainerType, pageIndex);
}
public void logActionTip(int actionType, int viewType) {
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 124574c..51079b0 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -18,6 +18,7 @@
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
+
import static com.android.launcher3.TestProtocol.ALL_APPS_STATE_ORDINAL;
import static com.android.launcher3.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
import static com.android.launcher3.TestProtocol.NORMAL_STATE_ORDINAL;
@@ -30,7 +31,6 @@
import android.view.animation.Interpolator;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.states.SpringLoadedState;
import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.uioverrides.states.AllAppsState;
@@ -58,6 +58,7 @@
public static final int ALL_APPS_HEADER_EXTRA = 1 << 3; // e.g. app predictions
public static final int ALL_APPS_CONTENT = 1 << 4;
public static final int VERTICAL_SWIPE_INDICATOR = 1 << 5;
+ public static final int RECENTS_CLEAR_ALL_BUTTON = 1 << 6;
protected static final int FLAG_MULTI_PAGE = 1 << 0;
protected static final int FLAG_DISABLE_ACCESSIBILITY = 1 << 1;
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index ed77786..abb45e5 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -98,6 +98,7 @@
@ViewDebug.ExportedProperty(category = "launcher")
protected int mNextPage = INVALID_PAGE;
+ protected int mMinScrollX;
protected int mMaxScrollX;
protected OverScroller mScroller;
private Interpolator mDefaultInterpolator;
@@ -266,11 +267,40 @@
}
private int validateNewPage(int newPage) {
+ newPage = ensureWithinScrollBounds(newPage);
// Ensure that it is clamped by the actual set of children in all cases
return Utilities.boundToRange(newPage, 0, getPageCount() - 1);
}
/**
+ * @return The closest page to the provided page that is within mMinScrollX and mMaxScrollX.
+ */
+ private int ensureWithinScrollBounds(int page) {
+ int dir = !mIsRtl ? 1 : - 1;
+ int currScroll = getScrollForPage(page);
+ int prevScroll;
+ while (currScroll < mMinScrollX) {
+ page += dir;
+ prevScroll = currScroll;
+ currScroll = getScrollForPage(page);
+ if (currScroll <= prevScroll) {
+ Log.e(TAG, "validateNewPage: failed to find a page > mMinScrollX");
+ break;
+ }
+ }
+ while (currScroll > mMaxScrollX) {
+ page -= dir;
+ prevScroll = currScroll;
+ currScroll = getScrollForPage(page);
+ if (currScroll >= prevScroll) {
+ Log.e(TAG, "validateNewPage: failed to find a page < mMaxScrollX");
+ break;
+ }
+ }
+ return page;
+ }
+
+ /**
* Sets the current page.
*/
public void setCurrentPage(int currentPage) {
@@ -348,29 +378,29 @@
public void scrollTo(int x, int y) {
mUnboundedScrollX = x;
- boolean isXBeforeFirstPage = mIsRtl ? (x > mMaxScrollX) : (x < 0);
- boolean isXAfterLastPage = mIsRtl ? (x < 0) : (x > mMaxScrollX);
+ boolean isXBeforeFirstPage = mIsRtl ? (x > mMaxScrollX) : (x < mMinScrollX);
+ boolean isXAfterLastPage = mIsRtl ? (x < mMinScrollX) : (x > mMaxScrollX);
if (!isXBeforeFirstPage && !isXAfterLastPage) {
mSpringOverScrollX = 0;
}
if (isXBeforeFirstPage) {
- super.scrollTo(mIsRtl ? mMaxScrollX : 0, y);
+ super.scrollTo(mIsRtl ? mMaxScrollX : mMinScrollX, y);
if (mAllowOverScroll) {
mWasInOverscroll = true;
if (mIsRtl) {
overScroll(x - mMaxScrollX);
} else {
- overScroll(x);
+ overScroll(x - mMinScrollX);
}
}
} else if (isXAfterLastPage) {
- super.scrollTo(mIsRtl ? 0 : mMaxScrollX, y);
+ super.scrollTo(mIsRtl ? mMinScrollX : mMaxScrollX, y);
if (mAllowOverScroll) {
mWasInOverscroll = true;
if (mIsRtl) {
- overScroll(x);
+ overScroll(x - mMinScrollX);
} else {
overScroll(x - mMaxScrollX);
}
@@ -557,12 +587,12 @@
// Wait until all transitions are complete.
if (!transition.isRunning()) {
transition.removeTransitionListener(this);
- updateMaxScrollX();
+ updateMinAndMaxScrollX();
}
}
});
} else {
- updateMaxScrollX();
+ updateMinAndMaxScrollX();
}
if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < childCount) {
@@ -627,12 +657,13 @@
return 0;
}
- private void updateMaxScrollX() {
+ protected void updateMinAndMaxScrollX() {
+ mMinScrollX = computeMinScrollX();
mMaxScrollX = computeMaxScrollX();
}
- public int getMaxScrollX() {
- return mMaxScrollX;
+ protected int computeMinScrollX() {
+ return 0;
}
protected int computeMaxScrollX() {
@@ -1010,12 +1041,8 @@
return;
}
- if (overScrollAmount < 0) {
- super.scrollTo(overScrollAmount, getScrollY());
- } else {
- int x = Math.max(0, Math.min(getScrollX(), mMaxScrollX));
- super.scrollTo(x + overScrollAmount, getScrollY());
- }
+ int x = Utilities.boundToRange(getScrollX(), mMinScrollX, mMaxScrollX);
+ super.scrollTo(x + overScrollAmount, getScrollY());
invalidate();
}
@@ -1030,7 +1057,7 @@
if (mFreeScroll && !mScroller.isFinished()) {
if (amount < 0) {
- super.scrollTo(amount, getScrollY());
+ super.scrollTo(mMinScrollX + amount, getScrollY());
} else {
super.scrollTo(mMaxScrollX + amount, getScrollY());
}
@@ -1169,12 +1196,12 @@
int initialScrollX = getScrollX();
if (((initialScrollX >= mMaxScrollX) && (isVelocityXLeft || !isFling)) ||
- ((initialScrollX <= 0) && (!isVelocityXLeft || !isFling))) {
- mScroller.springBack(getScrollX(), 0, mMaxScrollX);
+ ((initialScrollX <= mMinScrollX) && (!isVelocityXLeft || !isFling))) {
+ mScroller.springBack(getScrollX(), mMinScrollX, mMaxScrollX);
} else {
mScroller.setInterpolator(mDefaultInterpolator);
mScroller.fling(initialScrollX, -velocityX,
- 0, mMaxScrollX,
+ mMinScrollX, mMaxScrollX,
Math.round(getWidth() * 0.5f * OVERSCROLL_DAMP_FACTOR));
int finalX = mScroller.getFinalPos();
@@ -1182,12 +1209,13 @@
int firstPageScroll = getScrollForPage(!mIsRtl ? 0 : getPageCount() - 1);
int lastPageScroll = getScrollForPage(!mIsRtl ? getPageCount() - 1 : 0);
- if (finalX > 0 && finalX < mMaxScrollX) {
+ if (finalX > mMinScrollX && finalX < mMaxScrollX) {
// If scrolling ends in the half of the added space that is closer to
// the end, settle to the end. Otherwise snap to the nearest page.
// If flinging past one of the ends, don't change the velocity as it
// will get stopped at the end anyway.
- int pageSnappedX = finalX < firstPageScroll / 2 ? 0
+ int pageSnappedX = finalX < (firstPageScroll + mMinScrollX) / 2
+ ? mMinScrollX
: finalX > (lastPageScroll + mMaxScrollX) / 2
? mMaxScrollX
: getScrollForPage(mNextPage);
@@ -1347,7 +1375,7 @@
}
protected boolean isInOverScroll() {
- return (getScrollX() > mMaxScrollX || getScrollX() < 0);
+ return (getScrollX() > mMaxScrollX || getScrollX() < mMinScrollX);
}
protected int getPageSnapDuration() {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index efb50f0..8849768 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -956,7 +956,8 @@
private boolean isScrollingOverlay() {
return mLauncherOverlay != null &&
- ((mIsRtl && getUnboundedScrollX() > mMaxScrollX) || (!mIsRtl && getUnboundedScrollX() < 0));
+ ((mIsRtl && getUnboundedScrollX() > mMaxScrollX)
+ || (!mIsRtl && getUnboundedScrollX() < mMinScrollX));
}
@Override
diff --git a/src/com/android/launcher3/logging/LoggerUtils.java b/src/com/android/launcher3/logging/LoggerUtils.java
index d208077..1ffa698 100644
--- a/src/com/android/launcher3/logging/LoggerUtils.java
+++ b/src/com/android/launcher3/logging/LoggerUtils.java
@@ -41,7 +41,6 @@
/**
* Helper methods for logging.
*/
-@Deprecated
public class LoggerUtils {
private static final ArrayMap<Class, SparseArray<String>> sNameCache = new ArrayMap<>();
private static final String UNKNOWN = "UNKNOWN";
@@ -77,10 +76,17 @@
if (action.touch == Action.Touch.SWIPE || action.touch == Action.Touch.FLING) {
str += " direction=" + getFieldName(action.dir, Action.Direction.class);
}
- return str;
- case Action.Type.COMMAND: return getFieldName(action.command, Action.Command.class);
+ break;
+ case Action.Type.COMMAND:
+ str += getFieldName(action.command, Action.Command.class);
+ break;
default: return getFieldName(action.type, Action.Type.class);
}
+ if (action.touch == Action.Touch.SWIPE || action.touch == Action.Touch.FLING ||
+ (action.command == Action.Command.BACK && action.dir != Action.Direction.NONE)) {
+ str += " direction=" + getFieldName(action.dir, Action.Direction.class);
+ }
+ return str;
}
public static String getTargetStr(Target t) {
@@ -102,13 +108,17 @@
t.containerType == NAVBAR) {
str += " id=" + t.pageIndex;
} else if (t.containerType == ContainerType.FOLDER) {
- str += " grid(" + t.gridX + "," + t.gridY+ ")";
+ str += " grid(" + t.gridX + "," + t.gridY + ")";
}
break;
default:
str += "UNKNOWN TARGET TYPE";
}
+ if (t.spanX != 1 || t.spanY != 1) {
+ str += " span(" + t.spanX + "," + t.spanY + ")";
+ }
+
if (t.tipType != TipType.DEFAULT_NONE) {
str += " " + getFieldName(t.tipType, TipType.class);
}
diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java
index c8a4e2a..bd785a1 100644
--- a/src/com/android/launcher3/logging/UserEventDispatcher.java
+++ b/src/com/android/launcher3/logging/UserEventDispatcher.java
@@ -96,7 +96,6 @@
* Fills in the container data on the given event if the given view is not null.
* @return whether container data was added.
*/
- @Deprecated
public static boolean fillInLogContainerData(LauncherLogProto.LauncherEvent event, @Nullable View v) {
// Fill in grid(x,y), pageIndex of the child and container type of the parent
LogContainerProvider provider = StatsLogUtils.getLaunchProviderRecursive(v);
@@ -293,7 +292,7 @@
* (1) WORKSPACE: if the launcher is the foreground activity
* (2) APP: if another app was the foreground activity
*/
- public void logStateChangeAction(int action, int dir, int srcChildTargetType,
+ public void logStateChangeAction(int action, int dir, int downX, int downY, int srcChildTargetType,
int srcParentContainerType, int dstContainerType,
int pageIndex) {
LauncherEvent event;
@@ -311,6 +310,8 @@
event.action.dir = dir;
event.action.isStateChange = true;
event.srcTarget[0].pageIndex = pageIndex;
+ event.srcTarget[0].spanX = downX;
+ event.srcTarget[0].spanY = downY;
dispatchUserEvent(event, null);
resetElapsedContainerMillis("state changed");
}
@@ -325,7 +326,7 @@
public void logDeepShortcutsOpen(View icon) {
LogContainerProvider provider = StatsLogUtils.getLaunchProviderRecursive(icon);
- if (icon == null || !(icon.getTag() instanceof ItemInfo)) {
+ if (icon == null || !(icon.getTag() instanceof ItemInfo || provider == null)) {
return;
}
ItemInfo info = (ItemInfo) icon.getTag();
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 0274de3..a1871ff 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -540,7 +540,7 @@
private void logReachedState(int logAction, LauncherState targetState) {
// Transition complete. log the action
mLauncher.getUserEventDispatcher().logStateChangeAction(logAction,
- getDirectionForLog(),
+ getDirectionForLog(), mDetector.getDownX(), mDetector.getDownY(),
mStartContainerType,
mStartState.containerType,
targetState.containerType,
diff --git a/src/com/android/launcher3/touch/SwipeDetector.java b/src/com/android/launcher3/touch/SwipeDetector.java
index d758a29..4e3dcf8 100644
--- a/src/com/android/launcher3/touch/SwipeDetector.java
+++ b/src/com/android/launcher3/touch/SwipeDetector.java
@@ -180,6 +180,13 @@
return mState == ScrollState.DRAGGING || mState == ScrollState.SETTLING;
}
+ public int getDownX() {
+ return (int) mDownPos.x;
+ }
+
+ public int getDownY() {
+ return (int) mDownPos.y;
+ }
/**
* There's no touch and there's no animation.
*/