Merge "Tracing widgets page events propagation to catch flake" into ub-launcher3-master
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index c7a0253..d7191b4 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -138,14 +138,6 @@
</activity>
<!--
- Should point to the content provider which can be used to dump Launcher3 compatible
- worspace configuration to the dump's file descriptor by using launcher_dump.proto
- -->
- <meta-data
- android:name="com.android.launcher3.launcher_dump_provider"
- android:value="com.android.launcher3.LauncherProvider" />
-
- <!--
The settings provider contains Home's data, like the workspace favorites. The permissions
should be changed to what is defined above. The authorities should also be changed to
represent the package name.
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 549187f..131b71f 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,18 +15,22 @@
*/
package com.android.launcher3.uioverrides;
-import static com.android.launcher3.LauncherState.RECENTS_CLEAR_ALL_BUTTON;
+import static com.android.launcher3.LauncherState.OVERVIEW_BUTTONS;
+import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
import android.annotation.TargetApi;
import android.os.Build;
import android.util.FloatProperty;
+import android.view.View;
+import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
-import com.android.launcher3.Launcher;
+import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.PendingAnimation;
@@ -44,7 +48,7 @@
public final class RecentsViewStateController extends
BaseRecentsViewStateController<LauncherRecentsView> {
- public RecentsViewStateController(Launcher launcher) {
+ public RecentsViewStateController(BaseQuickstepLauncher launcher) {
super(launcher);
}
@@ -55,7 +59,7 @@
mRecentsView.updateEmptyMessage();
mRecentsView.resetTaskVisuals();
}
- setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, state.getVisibleElements(mLauncher));
+ setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, state, LINEAR);
mRecentsView.setFullscreenProgress(state.getOverviewFullscreenProgress());
}
@@ -73,15 +77,22 @@
AnimationSuccessListener.forRunnable(mRecentsView::resetTaskVisuals));
}
- setAlphas(builder, toState.getVisibleElements(mLauncher));
+ setAlphas(builder, toState,
+ config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
builder.setFloat(mRecentsView, FULLSCREEN_PROGRESS,
toState.getOverviewFullscreenProgress(), LINEAR);
}
- private void setAlphas(PropertySetter propertySetter, int visibleElements) {
- boolean hasClearAllButton = (visibleElements & RECENTS_CLEAR_ALL_BUTTON) != 0;
+ private void setAlphas(PropertySetter propertySetter, LauncherState state,
+ Interpolator actionInterpolator) {
+ float buttonAlpha = (state.getVisibleElements(mLauncher) & OVERVIEW_BUTTONS) != 0 ? 1 : 0;
propertySetter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA,
- hasClearAllButton ? 1f : 0f, LINEAR);
+ buttonAlpha, LINEAR);
+
+ View actionsView = mLauncher.getActionsView();
+ if (actionsView != null) {
+ propertySetter.setViewAlpha(actionsView, buttonAlpha, actionInterpolator);
+ }
}
@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 de3fce1..a87d6d1 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
@@ -90,7 +90,7 @@
@Override
public int getVisibleElements(Launcher launcher) {
return super.getVisibleElements(launcher)
- & ~RECENTS_CLEAR_ALL_BUTTON & ~VERTICAL_SWIPE_INDICATOR;
+ & ~OVERVIEW_BUTTONS & ~VERTICAL_SWIPE_INDICATOR;
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewPeekState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewPeekState.java
index 8087611..1288e7b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewPeekState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewPeekState.java
@@ -25,6 +25,7 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.states.StateAnimationConfig;
public class OverviewPeekState extends OverviewState {
@@ -37,6 +38,9 @@
ScaleAndTranslation result = super.getOverviewScaleAndTranslation(launcher);
result.translationX = NORMAL.getOverviewScaleAndTranslation(launcher).translationX
- launcher.getResources().getDimension(R.dimen.overview_peek_distance);
+ if (Utilities.isRtl(launcher.getResources())) {
+ result.translationX = -result.translationX;
+ }
return result;
}
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 024872f..bcfb11c 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
@@ -164,17 +164,15 @@
@Override
public int getVisibleElements(Launcher launcher) {
- if (launcher.getDeviceProfile().isVerticalBarLayout()) {
- return VERTICAL_SWIPE_INDICATOR | RECENTS_CLEAR_ALL_BUTTON;
+ if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(launcher)) {
+ return OVERVIEW_BUTTONS;
+ } else if (launcher.getDeviceProfile().isVerticalBarLayout()) {
+ return VERTICAL_SWIPE_INDICATOR | OVERVIEW_BUTTONS;
} else {
- if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(launcher)) {
- return VERTICAL_SWIPE_INDICATOR | RECENTS_CLEAR_ALL_BUTTON;
- }
-
boolean hasAllAppsHeaderExtra = launcher.getAppsView() != null
&& launcher.getAppsView().getFloatingHeaderView().hasVisibleContent();
- return HOTSEAT_SEARCH_BOX | VERTICAL_SWIPE_INDICATOR | RECENTS_CLEAR_ALL_BUTTON |
- (hasAllAppsHeaderExtra ? ALL_APPS_HEADER_EXTRA : HOTSEAT_ICONS);
+ return HOTSEAT_SEARCH_BOX | VERTICAL_SWIPE_INDICATOR | OVERVIEW_BUTTONS
+ | (hasAllAppsHeaderExtra ? ALL_APPS_HEADER_EXTRA : HOTSEAT_ICONS);
}
}
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 7786a8f..113cdec 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
@@ -31,6 +31,7 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
+import android.util.Log;
import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
@@ -48,6 +49,7 @@
import com.android.launcher3.graphics.RotationMode;
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;
@@ -198,18 +200,33 @@
}
protected void startNewTask(int successStateFlag, Consumer<Boolean> resultCallback) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_START_FROM_RECENTS, "startNewTask1");
+ }
// Launch the task user scrolled to (mRecentsView.getNextPage()).
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
// We finish recents animation inside launchTask() when live tile is enabled.
mRecentsView.getNextPageTaskView().launchTask(false /* animate */,
true /* freezeTaskList */);
} else {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_START_FROM_RECENTS, "startNewTask2");
+ }
int taskId = mRecentsView.getNextPageTaskView().getTask().key.id;
mFinishingRecentsAnimationForNewTaskId = taskId;
mRecentsAnimationController.finish(true /* toRecents */, () -> {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_START_FROM_RECENTS, "onFinishComplete1");
+ }
if (!mCanceled) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_START_FROM_RECENTS, "onFinishComplete2");
+ }
TaskView nextTask = mRecentsView.getTaskView(taskId);
if (nextTask != null) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_START_FROM_RECENTS, "onFinishComplete3");
+ }
nextTask.launchTask(false /* animate */, true /* freezeTaskList */,
success -> {
resultCallback.accept(success);
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 ea5561b..da73bc0 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -166,6 +166,7 @@
super.onActivityInit(alreadyOnHome);
mActivity = mActivityInterface.getCreatedActivity();
mRecentsView = mActivity.getOverviewPanel();
+ mRecentsView.setOnPageTransitionEndCallback(null);
linkRecentsViewScroll();
mRecentsView.setDisallowScrollToClearAll(true);
mRecentsView.getClearAllButton().setVisibilityAlpha(0);
@@ -434,7 +435,12 @@
@Override
public void onAnimationSuccess(Animator animator) {
- finishAnimationTargetSetAnimationComplete();
+ if (mRecentsView != null) {
+ mRecentsView.setOnPageTransitionEndCallback(FallbackSwipeHandler.this
+ ::finishAnimationTargetSetAnimationComplete);
+ } else {
+ finishAnimationTargetSetAnimationComplete();
+ }
mFinishAnimation = null;
}
};
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
index 5bac844..b3b0b02 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
@@ -29,6 +29,7 @@
import static com.android.quickstep.GestureState.GestureEndTarget.NEW_TASK;
import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
import static com.android.quickstep.GestureState.STATE_END_TARGET_ANIMATION_FINISHED;
+import static com.android.quickstep.GestureState.STATE_RECENTS_SCROLLING_FINISHED;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.HIDE;
@@ -46,6 +47,7 @@
import android.graphics.RectF;
import android.os.Build;
import android.os.SystemClock;
+import android.util.Log;
import android.view.View;
import android.view.View.OnApplyWindowInsetsListener;
import android.view.ViewTreeObserver.OnDrawListener;
@@ -64,6 +66,7 @@
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.logging.UserEventDispatcher;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -244,7 +247,11 @@
| STATE_GESTURE_STARTED,
this::setupLauncherUiAfterSwipeUpToRecentsAnimation);
- mGestureState.runOnceAtState(STATE_END_TARGET_ANIMATION_FINISHED, this::onEndTargetSet);
+ mGestureState.runOnceAtState(STATE_END_TARGET_ANIMATION_FINISHED,
+ this::continueComputingRecentsScrollIfNecessary);
+ mGestureState.runOnceAtState(STATE_END_TARGET_ANIMATION_FINISHED
+ | STATE_RECENTS_SCROLLING_FINISHED,
+ this::onSettledOnEndTarget);
mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED, this::invalidateHandler);
mStateCallback.runOnceAtState(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
@@ -283,6 +290,7 @@
}
mRecentsView = activity.getOverviewPanel();
+ mRecentsView.setOnPageTransitionEndCallback(null);
linkRecentsViewScroll();
addLiveTileOverlay();
@@ -505,16 +513,22 @@
}
private void buildAnimationController() {
- if (mGestureState.getEndTarget() == HOME || mHasLauncherTransitionControllerStarted) {
- // We don't want a new mLauncherTransitionController if
- // mGestureState.getEndTarget() == HOME (it has its own animation) or if we're already
- // animating the current controller.
+ if (!canCreateNewOrUpdateExistingLauncherTransitionController()) {
return;
}
initTransitionEndpoints(mActivity.getDeviceProfile());
mAnimationFactory.createActivityInterface(mTransitionDragLength);
}
+ /**
+ * We don't want to change mLauncherTransitionController if mGestureState.getEndTarget() == HOME
+ * (it has its own animation) or if we're already animating the current controller.
+ * @return Whether we can create the launcher controller or update its progress.
+ */
+ private boolean canCreateNewOrUpdateExistingLauncherTransitionController() {
+ return mGestureState.getEndTarget() != HOME && !mHasLauncherTransitionControllerStarted;
+ }
+
@Override
public WindowInsets onApplyWindowInsets(View view, WindowInsets windowInsets) {
WindowInsets result = view.onApplyWindowInsets(windowInsets);
@@ -558,15 +572,12 @@
}
}
- if (mLauncherTransitionController == null || mLauncherTransitionController
- .getAnimationPlayer().isStarted()) {
- return;
- }
updateLauncherTransitionProgress();
}
private void updateLauncherTransitionProgress() {
- if (mGestureState.getEndTarget() == HOME) {
+ if (mLauncherTransitionController == null
+ || !canCreateNewOrUpdateExistingLauncherTransitionController()) {
return;
}
// Normalize the progress to 0 to 1, as the animation controller will clamp it to that
@@ -696,7 +707,7 @@
}
}
- private void onEndTargetSet() {
+ private void onSettledOnEndTarget() {
switch (mGestureState.getEndTarget()) {
case HOME:
mStateCallback.setState(STATE_SCALED_CONTROLLER_HOME | STATE_CAPTURE_SCREENSHOT);
@@ -859,13 +870,17 @@
if (mDeviceState.isFullyGesturalNavMode()) {
setShelfState(ShelfAnimState.OVERVIEW, interpolator, duration);
}
- } else if (endTarget == NEW_TASK || endTarget == LAST_TASK) {
- // Let RecentsView handle the scrolling to the task, which we launch in startNewTask()
- // or resumeLastTask().
- if (mRecentsView != null) {
- duration = Math.max(duration, mRecentsView.getScroller().getDuration());
- }
}
+
+ // Let RecentsView handle the scrolling to the task, which we launch in startNewTask()
+ // or resumeLastTask().
+ if (mRecentsView != null) {
+ mRecentsView.setOnPageTransitionEndCallback(
+ () -> mGestureState.setState(STATE_RECENTS_SCROLLING_FINISHED));
+ } else {
+ mGestureState.setState(STATE_RECENTS_SCROLLING_FINISHED);
+ }
+
animateToProgress(startShift, endShift, duration, interpolator, endTarget, velocityPxPerMs);
}
@@ -949,15 +964,14 @@
ValueAnimator windowAnim = mCurrentShift.animateToValue(start, end);
windowAnim.setDuration(duration).setInterpolator(interpolator);
windowAnim.addUpdateListener(valueAnimator -> {
- if (mRecentsView != null && mRecentsView.getVisibility() != View.VISIBLE) {
- // Views typically don't compute scroll when invisible as an optimization,
- // but in our case we need to since the window offset depends on the scroll.
- mRecentsView.computeScroll();
- }
+ computeRecentsScrollIfInvisible();
});
windowAnim.addListener(new AnimationSuccessListener() {
@Override
public void onAnimationSuccess(Animator animator) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_START_FROM_RECENTS, "onAnimationSuccess");
+ }
if (mRecentsAnimationController == null) {
// If the recents animation is interrupted, we still end the running
// animation (not canceled) so this is still called. In that case, we can
@@ -1005,6 +1019,21 @@
mHasLauncherTransitionControllerStarted = true;
}
+ private void computeRecentsScrollIfInvisible() {
+ if (mRecentsView != null && mRecentsView.getVisibility() != View.VISIBLE) {
+ // Views typically don't compute scroll when invisible as an optimization,
+ // but in our case we need to since the window offset depends on the scroll.
+ mRecentsView.computeScroll();
+ }
+ }
+
+ private void continueComputingRecentsScrollIfNecessary() {
+ if (!mGestureState.hasState(STATE_RECENTS_SCROLLING_FINISHED)) {
+ computeRecentsScrollIfInvisible();
+ mRecentsView.post(this::continueComputingRecentsScrollIfNecessary);
+ }
+ }
+
/**
* Creates an animation that transforms the current app window into the home app.
* @param startProgress The progress of {@link #mCurrentShift} to start the window from.
@@ -1166,6 +1195,9 @@
}
private void switchToScreenshot() {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_START_FROM_RECENTS, "switchToScreenshot");
+ }
final int runningTaskId = mGestureState.getRunningTaskId();
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
if (mRecentsAnimationController != null) {
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 24703bd..e62de18 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,7 +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.LauncherState.OVERVIEW_BUTTONS;
import static com.android.launcher3.LauncherState.SPRING_LOADED;
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.ALL_APPS_PROGRESS_OFF_SCREEN;
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
@@ -323,7 +323,7 @@
if (enabled) {
LauncherState state = mActivity.getStateManager().getState();
boolean hasClearAllButton = (state.getVisibleElements(mActivity)
- & RECENTS_CLEAR_ALL_BUTTON) != 0;
+ & OVERVIEW_BUTTONS) != 0;
setDisallowScrollToClearAll(!hasClearAllButton);
}
}
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 40d7c7a..f0f8933 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -116,7 +116,7 @@
<!-- ******* Overview ******* -->
<!-- Label for a button that causes the current overview app to be shared. [CHAR_LIMIT=40] -->
- <string translatable="false" name="action_share">Share</string>
+ <string name="action_share">Share</string>
<!-- Label for a button that causes a screen shot of the current app to be taken. [CHAR_LIMIT=40] -->
- <string translatable="false" name="action_screenshot">Screenshot</string>
+ <string name="action_screenshot">Screenshot</string>
</resources>
\ No newline at end of file
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 83c67bb..135daef 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -34,6 +34,7 @@
import android.content.IntentSender;
import android.os.Bundle;
import android.os.CancellationSignal;
+import android.view.View;
import com.android.launcher3.LauncherState.ScaleAndTranslation;
import com.android.launcher3.LauncherStateManager.StateHandler;
@@ -80,6 +81,8 @@
private final ShelfPeekAnim mShelfPeekAnim = new ShelfPeekAnim(this);
+ private View mActionsView;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -224,16 +227,22 @@
@Override
protected void setupViews() {
super.setupViews();
+ mActionsView = findViewById(R.id.overview_actions_view);
+
if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(this)) {
// Overview is above all other launcher elements, including qsb, so move it to the top.
getOverviewPanel().bringToFront();
- if (getActionsView() != null) {
- getActionsView().bringToFront();
+ if (mActionsView != null) {
+ mActionsView.bringToFront();
}
}
}
+ public View getActionsView() {
+ return mActionsView;
+ }
+
@Override
protected void closeOpenViews(boolean animate) {
super.closeOpenViews(animate);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
index 03454f7..123c988 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
@@ -17,7 +17,6 @@
package com.android.launcher3.uioverrides;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
-import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
@@ -34,11 +33,10 @@
import android.util.FloatProperty;
import android.view.View;
-import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
-import com.android.launcher3.Launcher;
+import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherState.ScaleAndTranslation;
import com.android.launcher3.LauncherStateManager.StateHandler;
@@ -55,13 +53,11 @@
public abstract class BaseRecentsViewStateController<T extends View>
implements StateHandler {
protected final T mRecentsView;
- protected final Launcher mLauncher;
- protected final View mActionsView;
+ protected final BaseQuickstepLauncher mLauncher;
- public BaseRecentsViewStateController(@NonNull Launcher launcher) {
+ public BaseRecentsViewStateController(@NonNull BaseQuickstepLauncher launcher) {
mLauncher = launcher;
mRecentsView = launcher.getOverviewPanel();
- mActionsView = launcher.getActionsView();
}
@Override
@@ -69,19 +65,12 @@
ScaleAndTranslation scaleAndTranslation = state
.getOverviewScaleAndTranslation(mLauncher);
SCALE_PROPERTY.set(mRecentsView, scaleAndTranslation.scale);
- float translationX = scaleAndTranslation.translationX;
- if (mRecentsView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
- translationX = -translationX;
- }
- mRecentsView.setTranslationX(translationX);
+ mRecentsView.setTranslationX(scaleAndTranslation.translationX);
mRecentsView.setTranslationY(scaleAndTranslation.translationY);
+
getContentAlphaProperty().set(mRecentsView, state.overviewUi ? 1f : 0);
OverviewScrim scrim = mLauncher.getDragLayer().getOverviewScrim();
SCRIM_PROGRESS.set(scrim, state.getOverviewScrimAlpha(mLauncher));
- if (mActionsView != null) {
- mActionsView.setTranslationX(translationX);
- mActionsView.setAlpha(state.overviewUi ? 1f : 0);
- }
}
@Override
@@ -107,29 +96,18 @@
void setStateWithAnimationInternal(@NonNull final LauncherState toState,
@NonNull StateAnimationConfig config, @NonNull PendingAnimation setter) {
ScaleAndTranslation scaleAndTranslation = toState.getOverviewScaleAndTranslation(mLauncher);
- Interpolator scaleInterpolator = config.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR);
- setter.setFloat(mRecentsView, SCALE_PROPERTY, scaleAndTranslation.scale, scaleInterpolator);
- Interpolator translateXInterpolator = config.getInterpolator(
- ANIM_OVERVIEW_TRANSLATE_X, LINEAR);
- Interpolator translateYInterpolator = config.getInterpolator(
- ANIM_OVERVIEW_TRANSLATE_Y, LINEAR);
- float translationX = scaleAndTranslation.translationX;
- if (mRecentsView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
- translationX = -translationX;
- }
- setter.setFloat(mRecentsView, VIEW_TRANSLATE_X, translationX, translateXInterpolator);
+ setter.setFloat(mRecentsView, SCALE_PROPERTY, scaleAndTranslation.scale,
+ config.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR));
+ setter.setFloat(mRecentsView, VIEW_TRANSLATE_X, scaleAndTranslation.translationX,
+ config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_X, LINEAR));
setter.setFloat(mRecentsView, VIEW_TRANSLATE_Y, scaleAndTranslation.translationY,
- translateYInterpolator);
+ config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR));
+
setter.setFloat(mRecentsView, getContentAlphaProperty(), toState.overviewUi ? 1 : 0,
config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
OverviewScrim scrim = mLauncher.getDragLayer().getOverviewScrim();
setter.setFloat(scrim, SCRIM_PROGRESS, toState.getOverviewScrimAlpha(mLauncher),
config.getInterpolator(ANIM_OVERVIEW_SCRIM_FADE, LINEAR));
- if (mActionsView != null) {
- setter.setFloat(mActionsView, VIEW_TRANSLATE_X, translationX, translateXInterpolator);
- setter.setFloat(mActionsView, VIEW_ALPHA, toState.overviewUi ? 1 : 0,
- config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
- }
}
/**
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index f7e40ca..631df4c 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -105,6 +105,10 @@
public static final int STATE_RECENTS_ANIMATION_ENDED =
getFlagForIndex("STATE_RECENTS_ANIMATION_ENDED");
+ // Called when RecentsView stops scrolling and settles on a TaskView.
+ public static final int STATE_RECENTS_SCROLLING_FINISHED =
+ getFlagForIndex("STATE_RECENTS_SCROLLING_FINISHED");
+
// Needed to interact with the current activity
private final Intent mHomeIntent;
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
index 0f98b32..783978d 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
@@ -19,11 +19,13 @@
import android.graphics.Rect;
import android.util.ArraySet;
+import android.util.Log;
import androidx.annotation.BinderThread;
import androidx.annotation.UiThread;
import com.android.launcher3.Utilities;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.Preconditions;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
@@ -89,6 +91,9 @@
RemoteAnimationTargetCompat[] appTargets,
RemoteAnimationTargetCompat[] wallpaperTargets,
Rect homeContentInsets, Rect minimizedHomeBounds) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_START_FROM_RECENTS, "onAnimationStart");
+ }
RecentsAnimationTargets targets = new RecentsAnimationTargets(appTargets,
wallpaperTargets, homeContentInsets, minimizedHomeBounds);
mController = new RecentsAnimationController(animationController,
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index 6902e37..b04a1ae 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -26,6 +26,7 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.testing.TestProtocol;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -52,6 +53,9 @@
@UiThread
public RecentsAnimationCallbacks startRecentsAnimation(GestureState gestureState,
Intent intent, RecentsAnimationCallbacks.RecentsAnimationListener listener) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NO_START_FROM_RECENTS, "startRecentsAnimation");
+ }
// Notify if recents animation is still running
if (mController != null) {
String msg = "New recents animation started before old animation completed";
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 21a8fd4..c8e73ba 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -39,7 +39,6 @@
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewDebug;
import android.widget.TextView;
@@ -109,8 +108,6 @@
private final int mDisplay;
private final CheckLongPressHelper mLongPressHelper;
- private final StylusEventHelper mStylusEventHelper;
- private final float mSlop;
private final boolean mLayoutHorizontal;
private final int mIconSize;
@@ -137,9 +134,6 @@
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mDisableRelayout = false;
- @ViewDebug.ExportedProperty(category = "launcher")
- private final boolean mIgnorePaddingTouch;
-
private IconLoadRequest mIconLoadRequest;
public BubbleTextView(Context context) {
@@ -153,7 +147,6 @@
public BubbleTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mActivity = ActivityContext.lookupContext(context);
- mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.BubbleTextView, defStyle, 0);
@@ -166,23 +159,19 @@
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
setCompoundDrawablePadding(grid.iconDrawablePaddingPx);
defaultIconSize = grid.iconSizePx;
- mIgnorePaddingTouch = true;
} else if (mDisplay == DISPLAY_ALL_APPS) {
DeviceProfile grid = mActivity.getDeviceProfile();
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.allAppsIconTextSizePx);
setCompoundDrawablePadding(grid.allAppsIconDrawablePaddingPx);
defaultIconSize = grid.allAppsIconSizePx;
- mIgnorePaddingTouch = true;
} else if (mDisplay == DISPLAY_FOLDER) {
DeviceProfile grid = mActivity.getDeviceProfile();
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.folderChildTextSizePx);
setCompoundDrawablePadding(grid.folderChildDrawablePaddingPx);
defaultIconSize = grid.folderChildIconSizePx;
- mIgnorePaddingTouch = true;
} else {
// widget_selection or shortcut_popup
defaultIconSize = mActivity.getDeviceProfile().iconSizePx;
- mIgnorePaddingTouch = false;
}
mCenterVertically = a.getBoolean(R.styleable.BubbleTextView_centerVertically, false);
@@ -192,7 +181,6 @@
a.recycle();
mLongPressHelper = new CheckLongPressHelper(this);
- mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
mDotParams = new DotRenderer.DrawParams();
@@ -333,42 +321,21 @@
@Override
public boolean onTouchEvent(MotionEvent event) {
// ignore events if they happen in padding area
- if (event.getAction() == MotionEvent.ACTION_DOWN && mIgnorePaddingTouch
+ if (event.getAction() == MotionEvent.ACTION_DOWN
&& (event.getY() < getPaddingTop()
|| event.getX() < getPaddingLeft()
|| event.getY() > getHeight() - getPaddingBottom()
|| event.getX() > getWidth() - getPaddingRight())) {
return false;
}
-
- // Call the superclass onTouchEvent first, because sometimes it changes the state to
- // isPressed() on an ACTION_UP
- boolean result = super.onTouchEvent(event);
-
- // Check for a stylus button press, if it occurs cancel any long press checks.
- if (mStylusEventHelper.onMotionEvent(event)) {
- mLongPressHelper.cancelLongPress();
- result = true;
+ if (isLongClickable()) {
+ super.onTouchEvent(event);
+ mLongPressHelper.onTouchEvent(event);
+ // Keep receiving the rest of the events
+ return true;
+ } else {
+ return super.onTouchEvent(event);
}
-
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- // If we're in a stylus button press, don't check for long press.
- if (!mStylusEventHelper.inStylusButtonPressed()) {
- mLongPressHelper.postCheckForLongPress();
- }
- break;
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- mLongPressHelper.cancelLongPress();
- break;
- case MotionEvent.ACTION_MOVE:
- if (!Utilities.pointInView(this, event.getX(), event.getY(), mSlop)) {
- mLongPressHelper.cancelLongPress();
- }
- break;
- }
- return result;
}
void setStayPressed(boolean stayPressed) {
@@ -531,7 +498,6 @@
@Override
public void cancelLongPress() {
super.cancelLongPress();
-
mLongPressHelper.cancelLongPress();
}
diff --git a/src/com/android/launcher3/CheckLongPressHelper.java b/src/com/android/launcher3/CheckLongPressHelper.java
index 639c173..ef353f9 100644
--- a/src/com/android/launcher3/CheckLongPressHelper.java
+++ b/src/com/android/launcher3/CheckLongPressHelper.java
@@ -16,46 +16,68 @@
package com.android.launcher3;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
-import com.android.launcher3.util.Thunk;
-
+/**
+ * Utility class to handle tripper long press on a view with custom timeout and stylus event
+ */
public class CheckLongPressHelper {
public static final float DEFAULT_LONG_PRESS_TIMEOUT_FACTOR = 0.75f;
- @Thunk View mView;
- @Thunk View.OnLongClickListener mListener;
- @Thunk boolean mHasPerformedLongPress;
- private float mLongPressTimeoutFactor = DEFAULT_LONG_PRESS_TIMEOUT_FACTOR;
- private CheckForLongPress mPendingCheckForLongPress;
+ private final View mView;
+ private final View.OnLongClickListener mListener;
+ private final float mSlop;
- class CheckForLongPress implements Runnable {
- public void run() {
- if ((mView.getParent() != null) && mView.hasWindowFocus()
- && !mHasPerformedLongPress) {
- boolean handled;
- if (mListener != null) {
- handled = mListener.onLongClick(mView);
- } else {
- handled = mView.performLongClick();
- }
- if (handled) {
- mView.setPressed(false);
- mHasPerformedLongPress = true;
- }
- }
- }
- }
+ private float mLongPressTimeoutFactor = DEFAULT_LONG_PRESS_TIMEOUT_FACTOR;
+
+ private boolean mHasPerformedLongPress;
+
+ private Runnable mPendingCheckForLongPress;
public CheckLongPressHelper(View v) {
- mView = v;
+ this(v, null);
}
public CheckLongPressHelper(View v, View.OnLongClickListener listener) {
mView = v;
mListener = listener;
+ mSlop = ViewConfiguration.get(mView.getContext()).getScaledTouchSlop();
+ }
+
+ /**
+ * Handles the touch event on a view
+ *
+ * @see View#onTouchEvent(MotionEvent)
+ */
+ public void onTouchEvent(MotionEvent ev) {
+ switch (ev.getAction()) {
+ case MotionEvent.ACTION_DOWN: {
+ // Just in case the previous long press hasn't been cleared, we make sure to
+ // start fresh on touch down.
+ cancelLongPress();
+
+ postCheckForLongPress();
+ if (isStylusButtonPressed(ev)) {
+ triggerLongPress();
+ }
+ break;
+ }
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ cancelLongPress();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (!Utilities.pointInView(mView, ev.getX(), ev.getY(), mSlop)) {
+ cancelLongPress();
+ } else if (mPendingCheckForLongPress != null && isStylusButtonPressed(ev)) {
+ // Only trigger long press if it has not been cancelled before
+ triggerLongPress();
+ }
+ break;
+ }
}
/**
@@ -65,25 +87,64 @@
mLongPressTimeoutFactor = longPressTimeoutFactor;
}
- public void postCheckForLongPress() {
+ private void postCheckForLongPress() {
mHasPerformedLongPress = false;
if (mPendingCheckForLongPress == null) {
- mPendingCheckForLongPress = new CheckForLongPress();
+ mPendingCheckForLongPress = this::triggerLongPress;
}
mView.postDelayed(mPendingCheckForLongPress,
(long) (ViewConfiguration.getLongPressTimeout() * mLongPressTimeoutFactor));
}
+ /**
+ * Cancels any pending long press
+ */
public void cancelLongPress() {
mHasPerformedLongPress = false;
+ clearCallbacks();
+ }
+
+ /**
+ * Returns true if long press has been performed in the current touch gesture
+ */
+ public boolean hasPerformedLongPress() {
+ return mHasPerformedLongPress;
+ }
+
+ private void triggerLongPress() {
+ if ((mView.getParent() != null) && mView.hasWindowFocus() && !mHasPerformedLongPress) {
+ boolean handled;
+ if (mListener != null) {
+ handled = mListener.onLongClick(mView);
+ } else {
+ handled = mView.performLongClick();
+ }
+ if (handled) {
+ mView.setPressed(false);
+ mHasPerformedLongPress = true;
+ }
+ clearCallbacks();
+ }
+ }
+
+ private void clearCallbacks() {
if (mPendingCheckForLongPress != null) {
mView.removeCallbacks(mPendingCheckForLongPress);
mPendingCheckForLongPress = null;
}
}
- public boolean hasPerformedLongPress() {
- return mHasPerformedLongPress;
+
+ /**
+ * Identifies if the provided {@link MotionEvent} is a stylus with the primary stylus button
+ * pressed.
+ *
+ * @param event The event to check.
+ * @return Whether a stylus button press occurred.
+ */
+ private static boolean isStylusButtonPressed(MotionEvent event) {
+ return event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS
+ && event.isButtonPressed(MotionEvent.BUTTON_SECONDARY);
}
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index c00a679..5b9f676 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -271,7 +271,6 @@
// UI and state for the overview panel
private View mOverviewPanel;
- private View mActionsView;
@Thunk
boolean mWorkspaceLoading = true;
@@ -1166,7 +1165,6 @@
mWorkspace = mDragLayer.findViewById(R.id.workspace);
mWorkspace.initParentViews(mDragLayer);
mOverviewPanel = findViewById(R.id.overview_panel);
- mActionsView = findViewById(R.id.overview_actions_view);
mHotseat = findViewById(R.id.hotseat);
mLauncherView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
@@ -1413,10 +1411,6 @@
return (T) mOverviewPanel;
}
- public View getActionsView() {
- return mActionsView;
- }
-
public DropTargetBar getDropTargetBar() {
return mDropTargetBar;
}
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 6ee82cd..504666a 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -73,7 +73,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;
+ public static final int OVERVIEW_BUTTONS = 1 << 6;
/** Mask of all the items that are contained in the apps view. */
public static final int APPS_VIEW_ITEM_MASK =
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index e38631d..7d7739e 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -50,6 +50,8 @@
import static com.android.launcher3.touch.PagedOrientationHandler.VIEW_SCROLL_BY;
import static com.android.launcher3.touch.PagedOrientationHandler.VIEW_SCROLL_TO;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
@@ -133,6 +135,7 @@
protected int mActivePointerId = INVALID_POINTER;
protected boolean mIsPageInTransition = false;
+ private Runnable mOnPageTransitionEndCallback;
protected float mSpringOverScroll;
@@ -391,6 +394,22 @@
AccessibilityManagerCompat.sendScrollFinishedEventToTest(getContext());
AccessibilityManagerCompat.sendCustomAccessibilityEvent(getPageAt(mCurrentPage),
AccessibilityEvent.TYPE_VIEW_FOCUSED, null);
+ if (mOnPageTransitionEndCallback != null) {
+ mOnPageTransitionEndCallback.run();
+ mOnPageTransitionEndCallback = null;
+ }
+ }
+
+ /**
+ * Sets a callback to run once when the scrolling finishes. If there is currently
+ * no page in transition, then the callback is called immediately.
+ */
+ public void setOnPageTransitionEndCallback(@Nullable Runnable callback) {
+ if (mIsPageInTransition || callback == null) {
+ mOnPageTransitionEndCallback = callback;
+ } else {
+ callback.run();
+ }
}
protected int getUnboundedScroll() {
diff --git a/src/com/android/launcher3/SimpleOnStylusPressListener.java b/src/com/android/launcher3/SimpleOnStylusPressListener.java
deleted file mode 100644
index 6b97dce..0000000
--- a/src/com/android/launcher3/SimpleOnStylusPressListener.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.android.launcher3;
-
-import android.view.MotionEvent;
-import android.view.View;
-
-import com.android.launcher3.StylusEventHelper.StylusButtonListener;
-
-/**
- * Simple listener that performs a long click on the view after a stylus button press.
- */
-public class SimpleOnStylusPressListener implements StylusButtonListener {
- private View mView;
-
- public SimpleOnStylusPressListener(View view) {
- mView = view;
- }
-
- public boolean onPressed(MotionEvent event) {
- return mView.isLongClickable() && mView.performLongClick();
- }
-
- public boolean onReleased(MotionEvent event) {
- return false;
- }
-}
\ No newline at end of file
diff --git a/src/com/android/launcher3/StylusEventHelper.java b/src/com/android/launcher3/StylusEventHelper.java
deleted file mode 100644
index d5fc0fa..0000000
--- a/src/com/android/launcher3/StylusEventHelper.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package com.android.launcher3;
-
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-
-/**
- * Helper for identifying when a stylus touches a view while the primary stylus button is pressed.
- * This can occur in {@value MotionEvent#ACTION_DOWN} or {@value MotionEvent#ACTION_MOVE}.
- */
-public class StylusEventHelper {
-
- /**
- * Implement this interface to receive callbacks for a stylus button press and release.
- */
- public interface StylusButtonListener {
- /**
- * Called when the stylus button is pressed.
- *
- * @param event The MotionEvent that the button press occurred for.
- * @return Whether the event was handled.
- */
- public boolean onPressed(MotionEvent event);
-
- /**
- * Called when the stylus button is released after a button press. This is also called if
- * the event is canceled or the stylus is lifted off the screen.
- *
- * @param event The MotionEvent the button release occurred for.
- * @return Whether the event was handled.
- */
- public boolean onReleased(MotionEvent event);
- }
-
- private boolean mIsButtonPressed;
- private View mView;
- private StylusButtonListener mListener;
- private final float mSlop;
-
- /**
- * Constructs a helper for listening to stylus button presses and releases. Ensure that {
- * {@link #onMotionEvent(MotionEvent)} and {@link #onGenericMotionEvent(MotionEvent)} are called on
- * the helper to correctly identify stylus events.
- *
- * @param listener The listener to call for stylus events.
- * @param view Optional view associated with the touch events.
- */
- public StylusEventHelper(StylusButtonListener listener, View view) {
- mListener = listener;
- mView = view;
- if (mView != null) {
- mSlop = ViewConfiguration.get(mView.getContext()).getScaledTouchSlop();
- } else {
- mSlop = ViewConfiguration.getTouchSlop();
- }
- }
-
- public boolean onMotionEvent(MotionEvent event) {
- final boolean stylusButtonPressed = isStylusButtonPressed(event);
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- mIsButtonPressed = stylusButtonPressed;
- if (mIsButtonPressed) {
- return mListener.onPressed(event);
- }
- break;
- case MotionEvent.ACTION_MOVE:
- if (!Utilities.pointInView(mView, event.getX(), event.getY(), mSlop)) {
- return false;
- }
- if (!mIsButtonPressed && stylusButtonPressed) {
- mIsButtonPressed = true;
- return mListener.onPressed(event);
- } else if (mIsButtonPressed && !stylusButtonPressed) {
- mIsButtonPressed = false;
- return mListener.onReleased(event);
- }
- break;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- if (mIsButtonPressed) {
- mIsButtonPressed = false;
- return mListener.onReleased(event);
- }
- break;
- }
- return false;
- }
-
- /**
- * Whether a stylus button press is occurring.
- */
- public boolean inStylusButtonPressed() {
- return mIsButtonPressed;
- }
-
- /**
- * Identifies if the provided {@link MotionEvent} is a stylus with the primary stylus button
- * pressed.
- *
- * @param event The event to check.
- * @return Whether a stylus button press occurred.
- */
- private static boolean isStylusButtonPressed(MotionEvent event) {
- return event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS
- && ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY)
- == MotionEvent.BUTTON_SECONDARY);
- }
-}
\ No newline at end of file
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index f0d18ae..8251d68 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -31,7 +31,6 @@
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.widget.FrameLayout;
@@ -52,8 +51,6 @@
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.OnAlarmListener;
import com.android.launcher3.R;
-import com.android.launcher3.SimpleOnStylusPressListener;
-import com.android.launcher3.StylusEventHelper;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.WorkspaceItemInfo;
@@ -87,7 +84,6 @@
private FolderInfo mInfo;
private CheckLongPressHelper mLongPressHelper;
- private StylusEventHelper mStylusEventHelper;
static final int DROP_IN_ANIMATION_DURATION = 400;
@@ -110,8 +106,6 @@
boolean mAnimating = false;
- private float mSlop;
-
private Alarm mOpenAlarm = new Alarm();
private boolean mForceHideDot;
@@ -149,9 +143,7 @@
private void init() {
mLongPressHelper = new CheckLongPressHelper(this);
- mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
mPreviewLayoutRule = new ClippedFolderIconLayoutRule();
- mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
mPreviewItemManager = new PreviewItemManager(this);
mDotParams = new DotRenderer.DrawParams();
}
@@ -663,29 +655,10 @@
public boolean onTouchEvent(MotionEvent event) {
// Call the superclass onTouchEvent first, because sometimes it changes the state to
// isPressed() on an ACTION_UP
- boolean result = super.onTouchEvent(event);
-
- // Check for a stylus button press, if it occurs cancel any long press checks.
- if (mStylusEventHelper.onMotionEvent(event)) {
- mLongPressHelper.cancelLongPress();
- return true;
- }
-
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- mLongPressHelper.postCheckForLongPress();
- break;
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- mLongPressHelper.cancelLongPress();
- break;
- case MotionEvent.ACTION_MOVE:
- if (!Utilities.pointInView(this, event.getX(), event.getY(), mSlop)) {
- mLongPressHelper.cancelLongPress();
- }
- break;
- }
- return result;
+ super.onTouchEvent(event);
+ mLongPressHelper.onTouchEvent(event);
+ // Keep receiving the rest of the events
+ return true;
}
@Override
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index e70b570..9f20df6 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -97,4 +97,5 @@
public static final String NO_BACKGROUND_TO_OVERVIEW_TAG = "b/138251824";
public static final String APP_NOT_DISABLED = "b/139891609";
public static final String NO_SCROLL_END_WIDGETS = "b/152354290";
+ public static final String NO_START_FROM_RECENTS = "b/152658211";
}
diff --git a/src/com/android/launcher3/util/OverScroller.java b/src/com/android/launcher3/util/OverScroller.java
index 3c398b8..34efb12 100644
--- a/src/com/android/launcher3/util/OverScroller.java
+++ b/src/com/android/launcher3/util/OverScroller.java
@@ -165,6 +165,9 @@
/**
* Returns how long the scroll event will take, in milliseconds.
*
+ * Note that if mScroller.mState == SPRING, this duration is ignored, so can only
+ * serve as an estimate for how long the spring-controlled scroll will take.
+ *
* @return The duration of the scroll in milliseconds.
*/
public final int getDuration() {
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
index c1310e3..78acc34 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -27,7 +27,6 @@
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -41,8 +40,6 @@
import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.R;
-import com.android.launcher3.SimpleOnStylusPressListener;
-import com.android.launcher3.StylusEventHelper;
import com.android.launcher3.Utilities;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DraggableView;
@@ -66,14 +63,11 @@
protected final LayoutInflater mInflater;
private final CheckLongPressHelper mLongPressHelper;
- private final StylusEventHelper mStylusEventHelper;
protected final Launcher mLauncher;
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mReinflateOnConfigChange;
- private float mSlop;
-
private boolean mIsScrollable;
private boolean mIsAttachedToWindow;
private boolean mIsAutoAdvanceRegistered;
@@ -93,7 +87,6 @@
super(context);
mLauncher = Launcher.getLauncher(context);
mLongPressHelper = new CheckLongPressHelper(this, this);
- mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
mInflater = LayoutInflater.from(context);
setAccessibilityDelegate(mLauncher.getAccessibilityDelegate());
setBackgroundResource(R.drawable.widget_internal_focus_bg);
@@ -157,68 +150,19 @@
}
public boolean onInterceptTouchEvent(MotionEvent ev) {
- // Just in case the previous long press hasn't been cleared, we make sure to start fresh
- // on touch down.
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mLongPressHelper.cancelLongPress();
- }
-
- // Consume any touch events for ourselves after longpress is triggered
- if (mLongPressHelper.hasPerformedLongPress()) {
- mLongPressHelper.cancelLongPress();
- return true;
- }
-
- // Watch for longpress or stylus button press events at this level to
- // make sure users can always pick up this widget
- if (mStylusEventHelper.onMotionEvent(ev)) {
- mLongPressHelper.cancelLongPress();
- return true;
- }
-
- switch (ev.getAction()) {
- case MotionEvent.ACTION_DOWN: {
- DragLayer dragLayer = Launcher.getLauncher(getContext()).getDragLayer();
-
- if (mIsScrollable) {
- dragLayer.requestDisallowInterceptTouchEvent(true);
- }
- if (!mStylusEventHelper.inStylusButtonPressed()) {
- mLongPressHelper.postCheckForLongPress();
- }
- dragLayer.setTouchCompleteListener(this);
- break;
+ DragLayer dragLayer = Launcher.getLauncher(getContext()).getDragLayer();
+ if (mIsScrollable) {
+ dragLayer.requestDisallowInterceptTouchEvent(true);
}
-
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- mLongPressHelper.cancelLongPress();
- break;
- case MotionEvent.ACTION_MOVE:
- if (!Utilities.pointInView(this, ev.getX(), ev.getY(), mSlop)) {
- mLongPressHelper.cancelLongPress();
- }
- break;
+ dragLayer.setTouchCompleteListener(this);
}
-
- // Otherwise continue letting touch events fall through to children
- return false;
+ mLongPressHelper.onTouchEvent(ev);
+ return mLongPressHelper.hasPerformedLongPress();
}
public boolean onTouchEvent(MotionEvent ev) {
- // If the widget does not handle touch, then cancel
- // long press when we release the touch
- switch (ev.getAction()) {
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- mLongPressHelper.cancelLongPress();
- break;
- case MotionEvent.ACTION_MOVE:
- if (!Utilities.pointInView(this, ev.getX(), ev.getY(), mSlop)) {
- mLongPressHelper.cancelLongPress();
- }
- break;
- }
+ mLongPressHelper.onTouchEvent(ev);
// We want to keep receiving though events to be able to cancel long press on ACTION_UP
return true;
}
@@ -226,7 +170,6 @@
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
mIsAttachedToWindow = true;
checkIfAutoAdvance();
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index f055adf..4a0b4ef 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -31,10 +31,9 @@
import android.widget.TextView;
import com.android.launcher3.BaseActivity;
+import com.android.launcher3.CheckLongPressHelper;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
-import com.android.launcher3.SimpleOnStylusPressListener;
-import com.android.launcher3.StylusEventHelper;
import com.android.launcher3.WidgetPreviewLoader;
import com.android.launcher3.icons.BaseIconFactory;
import com.android.launcher3.model.WidgetItem;
@@ -71,7 +70,6 @@
protected WidgetItem mItem;
private WidgetPreviewLoader mWidgetPreviewLoader;
- private StylusEventHelper mStylusEventHelper;
protected CancellationSignal mActiveRequest;
private boolean mAnimatePreview = true;
@@ -80,7 +78,8 @@
private Bitmap mDeferredBitmap;
protected final BaseActivity mActivity;
- protected DeviceProfile mDeviceProfile;
+ protected final DeviceProfile mDeviceProfile;
+ private final CheckLongPressHelper mLongPressHelper;
public WidgetCell(Context context) {
this(context, null);
@@ -95,8 +94,9 @@
mActivity = BaseActivity.fromContext(context);
mDeviceProfile = mActivity.getDeviceProfile();
- mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
+ mLongPressHelper = new CheckLongPressHelper(this);
+ mLongPressHelper.setLongPressTimeoutFactor(1);
setContainerWidth();
setWillNotDraw(false);
setClipToPadding(false);
@@ -210,11 +210,15 @@
@Override
public boolean onTouchEvent(MotionEvent ev) {
- boolean handled = super.onTouchEvent(ev);
- if (mStylusEventHelper.onMotionEvent(ev)) {
- return true;
- }
- return handled;
+ super.onTouchEvent(ev);
+ mLongPressHelper.onTouchEvent(ev);
+ return true;
+ }
+
+ @Override
+ public void cancelLongPress() {
+ super.cancelLongPress();
+ mLongPressHelper.cancelLongPress();
}
/**
diff --git a/tests/tapl/com/android/launcher3/tapl/LogEventChecker.java b/tests/tapl/com/android/launcher3/tapl/LogEventChecker.java
index 0fc88ee..49901ea 100644
--- a/tests/tapl/com/android/launcher3/tapl/LogEventChecker.java
+++ b/tests/tapl/com/android/launcher3/tapl/LogEventChecker.java
@@ -149,23 +149,24 @@
finishSync(waitForExpectedCountMs);
final StringBuilder sb = new StringBuilder();
+ boolean hasMismatches = false;
for (Map.Entry<String, List<Pattern>> expectedEvents : mExpectedEvents.entrySet()) {
String sequence = expectedEvents.getKey();
List<String> actual = new ArrayList<>(mEvents.getNonNull(sequence));
final int mismatchPosition = getMismatchPosition(expectedEvents.getValue(), actual);
- if (mismatchPosition != -1) {
- formatSequenceWithMismatch(
- sb,
- sequence,
- expectedEvents.getValue(),
- actual,
- mismatchPosition);
- }
+ hasMismatches = hasMismatches || mismatchPosition != -1;
+ formatSequenceWithMismatch(
+ sb,
+ sequence,
+ expectedEvents.getValue(),
+ actual,
+ mismatchPosition);
}
// Check for unexpected event sequences in the actual data.
for (String actualNamedSequence : mEvents.keySet()) {
if (!mExpectedEvents.containsKey(actualNamedSequence)) {
+ hasMismatches = true;
formatSequenceWithMismatch(
sb,
actualNamedSequence,
@@ -175,7 +176,7 @@
}
}
- return sb.length() != 0 ? "mismatching events: " + sb.toString() : null;
+ return hasMismatches ? "mismatching events: " + sb.toString() : null;
}
// If the list of actual events matches the list of expected events, returns -1, otherwise
@@ -199,10 +200,11 @@
List<Pattern> expected,
List<String> actualEvents,
int mismatchPosition) {
- sb.append("\n>> Sequence " + sequenceName);
- sb.append("\n Expected:");
+ sb.append("\n>> SEQUENCE " + sequenceName + " - "
+ + (mismatchPosition == -1 ? "MATCH" : "MISMATCH"));
+ sb.append("\n EXPECTED:");
formatEventListWithMismatch(sb, expected, mismatchPosition);
- sb.append("\n Actual:");
+ sb.append("\n ACTUAL:");
formatEventListWithMismatch(sb, actualEvents, mismatchPosition);
}