From a64a914ddf4370f96909a48c40f6c7de35bd08b5 Mon Sep 17 00:00:00 2001 From: Thales Lima Date: Tue, 18 Oct 2022 18:30:43 +0100 Subject: [PATCH 01/12] Calculate taskbar content size for edu Using the value calculated in layout was not working because TaskbarView onLayout() was being called after TaskbarEduView onMeasure(). Now uses the same value on all orientations based on taskbar icon size. Fixes: 252945031 Test: manual Change-Id: Ib6914901638c82f3b3ec4c9b86f6c20e84d34d0f --- .../taskbar/TaskbarEduController.java | 2 +- .../android/launcher3/taskbar/TaskbarView.java | 18 +++++++++++++----- .../taskbar/TaskbarViewController.java | 4 ++++ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java index 95b93febe0..2c2416170d 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java @@ -222,7 +222,7 @@ public class TaskbarEduController implements TaskbarControllers.LoggableTaskbarC } int getIconLayoutBoundsWidth() { - return mControllers.taskbarViewController.getIconLayoutBounds().width(); + return mControllers.taskbarViewController.getIconLayoutWidth(); } } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java index bb82d19734..1bddcca835 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java @@ -321,12 +321,8 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { int count = getChildCount(); - int countExcludingQsb = count; DeviceProfile deviceProfile = mActivityContext.getDeviceProfile(); - if (deviceProfile.isQsbInline) { - countExcludingQsb--; - } - int spaceNeeded = countExcludingQsb * (mItemMarginLeftRight * 2 + mIconTouchSize); + int spaceNeeded = getIconLayoutWidth(); int navSpaceNeeded = deviceProfile.hotseatBarEndOffset; boolean layoutRtl = isLayoutRtl(); int iconEnd = right - (right - left - spaceNeeded) / 2; @@ -416,6 +412,18 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar return mIconLayoutBounds; } + /** + * Returns the space used by the icons + */ + public int getIconLayoutWidth() { + int countExcludingQsb = getChildCount(); + DeviceProfile deviceProfile = mActivityContext.getDeviceProfile(); + if (deviceProfile.isQsbInline) { + countExcludingQsb--; + } + return countExcludingQsb * (mItemMarginLeftRight * 2 + mIconTouchSize); + } + /** * Returns the app icons currently shown in the taskbar. */ diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index 16dd90db29..1530ce121a 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -193,6 +193,10 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar return mTaskbarView.getIconLayoutBounds(); } + public int getIconLayoutWidth() { + return mTaskbarView.getIconLayoutWidth(); + } + public View[] getIconViews() { return mTaskbarView.getIconViews(); } From ee0bc03d58aa3672e5afd14524682887b37ac1b0 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Tue, 20 Sep 2022 13:54:29 -0700 Subject: [PATCH 02/12] Decrease TAPL All Apps scrolling flakiness scrolling in all apps did not factor in additional top padding in the all apps list recycler. This made it so that apps could occasionally scroll and be obcured by that top padding, making them un-tappable. Added this padding to the scrolling logic to make scrolling less flaky. Test: TaplTestsTaskbar, TaplTestsLauncher3 and presubmit Fixes: 248064856 Change-Id: Id76b92b4bc354917f3688ac53673d0ed7a905f02 --- .../taskbar/TaskbarActivityContext.java | 5 +++ .../allapps/TaskbarAllAppsController.java | 8 ++++ .../QuickstepTestInformationHandler.java | 20 ++++++++++ .../testing/TestInformationHandler.java | 5 +++ .../testing/shared/TestProtocol.java | 3 ++ .../com/android/launcher3/tapl/AllApps.java | 40 ++++++++++++++----- .../launcher3/tapl/AllAppsFromTaskbar.java | 8 ++++ .../android/launcher3/tapl/HomeAllApps.java | 8 ++++ 8 files changed, 86 insertions(+), 11 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 4c5e0bea8c..496a146f6b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -907,4 +907,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext { mControllers.dumpLogs(prefix + "\t", pw); mDeviceProfile.dump(this, prefix, pw); } + + @VisibleForTesting + public int getTaskbarAllAppsTopPadding() { + return mControllers.taskbarAllAppsController.getTaskbarAllAppsTopPadding(); + } } diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java index ea37944d69..85c63183ad 100644 --- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java +++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java @@ -16,6 +16,7 @@ package com.android.launcher3.taskbar.allapps; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import com.android.launcher3.R; import com.android.launcher3.appprediction.PredictionRowView; @@ -123,4 +124,11 @@ public final class TaskbarAllAppsController { .findFixedRowByType(PredictionRowView.class) .setPredictedApps(mPredictedApps); } + + + @VisibleForTesting + public int getTaskbarAllAppsTopPadding() { + // Allow null-pointer since this should only be null if the apps view is not showing. + return mAppsView.getActiveRecyclerView().getClipBounds().top; + } } diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java index b7cdecd115..9621ce6eba 100644 --- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java +++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java @@ -20,6 +20,7 @@ import com.android.quickstep.util.TISBindHelper; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.function.Consumer; +import java.util.function.Function; public class QuickstepTestInformationHandler extends TestInformationHandler { @@ -112,6 +113,13 @@ public class QuickstepTestInformationHandler extends TestInformationHandler { resources.getDimensionPixelSize(R.dimen.taskbar_stashed_size)); return response; } + + case TestProtocol.REQUEST_TASKBAR_ALL_APPS_TOP_PADDING: { + return getTISBinderUIProperty(Bundle::putInt, tisBinder -> + tisBinder.getTaskbarManager() + .getCurrentActivityContext() + .getTaskbarAllAppsTopPadding()); + } } return super.call(method, arg, extras); @@ -159,4 +167,16 @@ public class QuickstepTestInformationHandler extends TestInformationHandler { throw new RuntimeException(e); } } + + private Bundle getTISBinderUIProperty( + BundleSetter bundleSetter, Function provider) { + Bundle response = new Bundle(); + + runOnTISBinder(tisBinder -> bundleSetter.set( + response, + TestProtocol.TEST_INFO_RESPONSE_FIELD, + provider.apply(tisBinder))); + + return response; + } } diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java index d3c9bc9676..7abf1e66a0 100644 --- a/src/com/android/launcher3/testing/TestInformationHandler.java +++ b/src/com/android/launcher3/testing/TestInformationHandler.java @@ -219,6 +219,11 @@ public class TestInformationHandler implements ResourceBasedOverride { return response; } + case TestProtocol.REQUEST_ALL_APPS_TOP_PADDING: { + return getLauncherUIProperty(Bundle::putInt, + l -> l.getAppsView().getActiveRecyclerView().getClipBounds().top); + } + default: return null; } diff --git a/src/com/android/launcher3/testing/shared/TestProtocol.java b/src/com/android/launcher3/testing/shared/TestProtocol.java index 5116b01ba5..10bb87779f 100644 --- a/src/com/android/launcher3/testing/shared/TestProtocol.java +++ b/src/com/android/launcher3/testing/shared/TestProtocol.java @@ -112,6 +112,9 @@ public final class TestProtocol { "get-activities-created-count"; public static final String REQUEST_GET_ACTIVITIES = "get-activities"; public static final String REQUEST_HAS_TIS = "has-touch-interaction-service"; + public static final String REQUEST_TASKBAR_ALL_APPS_TOP_PADDING = + "taskbar-all-apps-top-padding"; + public static final String REQUEST_ALL_APPS_TOP_PADDING = "all-apps-top-padding"; public static final String REQUEST_WORKSPACE_CELL_LAYOUT_SIZE = "workspace-cell-layout-size"; public static final String REQUEST_WORKSPACE_CELL_CENTER = "workspace-cell-center"; diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java index 4791846626..6bbdf48da0 100644 --- a/tests/tapl/com/android/launcher3/tapl/AllApps.java +++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java @@ -46,8 +46,7 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { super(launcher); final UiObject2 allAppsContainer = verifyActiveContainer(); mHeight = mLauncher.getVisibleBounds(allAppsContainer).height(); - final UiObject2 appListRecycler = mLauncher.waitForObjectInContainer(allAppsContainer, - "apps_list_view"); + final UiObject2 appListRecycler = getAppListRecycler(allAppsContainer); // Wait for the recycler to populate. mLauncher.waitForObjectInContainer(appListRecycler, By.clazz(TextView.class)); verifyNotFrozen("All apps freeze flags upon opening all apps"); @@ -78,6 +77,11 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { LauncherInstrumentation.log("hasClickableIcon: icon center is under search box"); return false; } + if (iconCenterInRecyclerTopPadding(appListRecycler, icon)) { + LauncherInstrumentation.log( + "hasClickableIcon: icon center is under the app list recycler's top padding."); + return false; + } if (iconBounds.bottom > displayBottom) { LauncherInstrumentation.log("hasClickableIcon: icon bottom below bottom offset"); return false; @@ -92,6 +96,13 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { iconCenter.x, iconCenter.y); } + private boolean iconCenterInRecyclerTopPadding(UiObject2 appListRecycler, UiObject2 icon) { + final Point iconCenter = icon.getVisibleCenter(); + + return iconCenter.y <= mLauncher.getVisibleBounds(appListRecycler).top + + getAppsListRecyclerTopPadding(); + } + /** * Finds an icon. If the icon doesn't exist, return null. * Scrolls the app list when needed to make sure the icon is visible. @@ -105,9 +116,7 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { LauncherInstrumentation.Closable c = mLauncher.addContextLayer( "getting app icon " + appName + " on all apps")) { final UiObject2 allAppsContainer = verifyActiveContainer(); - final UiObject2 appListRecycler = mLauncher.waitForObjectInContainer(allAppsContainer, - "apps_list_view"); - final UiObject2 searchBox = hasSearchBox() ? getSearchBox(allAppsContainer) : null; + final UiObject2 appListRecycler = getAppListRecycler(allAppsContainer); int deviceHeight = mLauncher.getRealDisplaySize().y; int bottomGestureStartOnScreen = mLauncher.getBottomGestureStartOnScreen(); @@ -128,10 +137,9 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { mLauncher.getVisibleBounds(icon).top < bottomGestureStartOnScreen) .collect(Collectors.toList()), - hasSearchBox() - ? mLauncher.getVisibleBounds(searchBox).bottom - - mLauncher.getVisibleBounds(allAppsContainer).top - : 0); + mLauncher.getVisibleBounds(appListRecycler).top + + getAppsListRecyclerTopPadding() + - mLauncher.getVisibleBounds(allAppsContainer).top); verifyActiveContainer(); final int newScroll = getAllAppsScroll(); mLauncher.assertTrue( @@ -180,16 +188,22 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { protected abstract boolean hasSearchBox(); + protected abstract int getAppsListRecyclerTopPadding(); + private void scrollBackToBeginning() { try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( "want to scroll back in all apps")) { LauncherInstrumentation.log("Scrolling to the beginning"); final UiObject2 allAppsContainer = verifyActiveContainer(); - final UiObject2 searchBox = hasSearchBox() ? getSearchBox(allAppsContainer) : null; + final UiObject2 appListRecycler = getAppListRecycler(allAppsContainer); int attempts = 0; final Rect margins = new Rect( - 0, hasSearchBox() ? mLauncher.getVisibleBounds(searchBox).bottom + 1 : 0, 0, 5); + /* left= */ 0, + mLauncher.getVisibleBounds(appListRecycler).top + + getAppsListRecyclerTopPadding() + 1, + /* right= */ 0, + /* bottom= */ 5); for (int scroll = getAllAppsScroll(); scroll != 0; @@ -220,6 +234,10 @@ public abstract class AllApps extends LauncherInstrumentation.VisibleContainer { .getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD); } + private UiObject2 getAppListRecycler(UiObject2 allAppsContainer) { + return mLauncher.waitForObjectInContainer(allAppsContainer, "apps_list_view"); + } + private UiObject2 getSearchBox(UiObject2 allAppsContainer) { return mLauncher.waitForObjectInContainer(allAppsContainer, "search_container_all_apps"); } diff --git a/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java b/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java index 516402563d..f804e28ceb 100644 --- a/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java +++ b/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java @@ -18,6 +18,8 @@ package com.android.launcher3.tapl; import androidx.annotation.NonNull; import androidx.test.uiautomator.UiObject2; +import com.android.launcher3.testing.shared.TestProtocol; + /** * Operations on AllApps opened from the Taskbar. */ @@ -48,4 +50,10 @@ public class AllAppsFromTaskbar extends AllApps { protected boolean hasSearchBox() { return false; } + + @Override + protected int getAppsListRecyclerTopPadding() { + return mLauncher.getTestInfo(TestProtocol.REQUEST_TASKBAR_ALL_APPS_TOP_PADDING) + .getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD); + } } diff --git a/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java b/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java index 7123de44a9..9a4c6d4dce 100644 --- a/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java +++ b/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java @@ -18,6 +18,8 @@ package com.android.launcher3.tapl; import androidx.annotation.NonNull; import androidx.test.uiautomator.UiObject2; +import com.android.launcher3.testing.shared.TestProtocol; + public class HomeAllApps extends AllApps { private static final String BOTTOM_SHEET_RES_ID = "bottom_sheet_background"; @@ -47,6 +49,12 @@ public class HomeAllApps extends AllApps { return true; } + @Override + protected int getAppsListRecyclerTopPadding() { + return mLauncher.getTestInfo(TestProtocol.REQUEST_ALL_APPS_TOP_PADDING) + .getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD); + } + /** * Taps outside bottom sheet to dismiss and return to workspace. Available on tablets only. * @param tapRight Tap on the right of bottom sheet if true, or left otherwise. From 97ae16e80c54d5935c63803d9945b40a813c84db Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 24 Oct 2022 15:49:27 -0700 Subject: [PATCH 03/12] Updating AIDL interface and removing unused methods Bug: 193244407 Test: Presubmit Change-Id: If87ef08e16e541921cde4e7a15a675b07c388fef --- .../com/android/quickstep/AbsSwipeUpHandler.java | 1 - .../src/com/android/quickstep/SystemUiProxy.java | 11 ----------- .../android/quickstep/TouchInteractionService.java | 14 ++++---------- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 267593a2e7..df08596c5a 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -951,7 +951,6 @@ public abstract class AbsSwipeUpHandler, new ActiveGestureLog.CompoundString("on gesture started (animate=false)")); mStateCallback.setStateOnUiThread(STATE_GESTURE_STARTED); mGestureStarted = true; - SystemUiProxy.INSTANCE.get(mContext).notifySwipeUpGestureStarted(); } /** diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index 7705a2512a..256e68992c 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -346,17 +346,6 @@ public class SystemUiProxy implements ISystemUiProxy { } } - @Override - public void notifySwipeUpGestureStarted() { - if (mSystemUiProxy != null) { - try { - mSystemUiProxy.notifySwipeUpGestureStarted(); - } catch (RemoteException e) { - Log.w(TAG, "Failed call notifySwipeUpGestureStarted", e); - } - } - } - @Override public void notifyPrioritizedRotation(int rotation) { if (mSystemUiProxy != null) { diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 80db362b09..239b3fc70f 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -60,6 +60,7 @@ import android.util.Log; import android.view.Choreographer; import android.view.InputEvent; import android.view.MotionEvent; +import android.view.SurfaceControl; import android.view.accessibility.AccessibilityManager; import androidx.annotation.BinderThread; @@ -230,12 +231,6 @@ public class TouchInteractionService extends Service } } - @BinderThread - @Override - public void onTip(int actionType, int viewType) { - // Please delete this method from the interface - } - @BinderThread @Override public void onAssistantAvailable(boolean available) { @@ -254,10 +249,9 @@ public class TouchInteractionService extends Service }); } - @BinderThread - public void onBackAction(boolean completed, int downX, int downY, boolean isButton, - boolean gestureSwipeLeft) { - // Remove this method from the interface + @Override + public void onNavigationBarSurface(SurfaceControl surface) { + // TODO: implement } @BinderThread From 570ddadcf95a6553fb45763472503d915787be34 Mon Sep 17 00:00:00 2001 From: Jeremy Sim Date: Thu, 27 Oct 2022 16:43:07 -0700 Subject: [PATCH 04/12] Change tablet split confirm timing slightly This patch changes the split confirm animation on tablets to 500ms. Based on UX discussion at b/241126570. Fixes: 241126570 Test: Manual Change-Id: I1de0e0f8882db059de09685f7756343d8a387b4f --- .../com/android/quickstep/util/TabletSplitToConfirmTimings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/util/TabletSplitToConfirmTimings.java b/quickstep/src/com/android/quickstep/util/TabletSplitToConfirmTimings.java index 580cc99d4e..3756b4af59 100644 --- a/quickstep/src/com/android/quickstep/util/TabletSplitToConfirmTimings.java +++ b/quickstep/src/com/android/quickstep/util/TabletSplitToConfirmTimings.java @@ -26,7 +26,7 @@ public class TabletSplitToConfirmTimings public int getPlaceholderIconFadeInStart() { return 167; } public int getPlaceholderIconFadeInEnd() { return 250; } public int getStagedRectSlideStart() { return 0; } - public int getStagedRectSlideEnd() { return 383; } + public int getStagedRectSlideEnd() { return 500; } public int getDuration() { return TABLET_CONFIRM_DURATION; } } From 0bae1f55e3fa32380298297201f46e0ad31dd3a8 Mon Sep 17 00:00:00 2001 From: Pinyao Ting Date: Mon, 31 Oct 2022 10:51:31 -0700 Subject: [PATCH 05/12] Grant Launcher permission to access AppSearch This CL grants aosp launcher the permission to access appsearch to fetch data that are explicitly made visible to the app that uses the HOME role. One concrete example are shortcuts, with this CL aosp launchers will now have the permission to query shortcuts directly from appsearch. Bug: 254383738 Test: manual Change-Id: I1a2260c7bde0d52fedff38ae56572101d51abdef --- AndroidManifest-common.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml index 02b83fe889..951be4e54e 100644 --- a/AndroidManifest-common.xml +++ b/AndroidManifest-common.xml @@ -43,7 +43,8 @@ - + + 24dp diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 593605f9fb..bf5740dcac 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -24,6 +24,8 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; import static com.android.launcher3.AbstractFloatingView.TYPE_ALL; import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN; +import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_DRAGGING; +import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_FULLSCREEN; import static com.android.launcher3.taskbar.TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW; import static com.android.launcher3.testing.shared.ResourceUtils.getBoolByName; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED; @@ -75,6 +77,7 @@ import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.popup.PopupDataProvider; +import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.AutohideSuspendFlag; import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController; import com.android.launcher3.taskbar.overlay.TaskbarOverlayController; import com.android.launcher3.testing.TestLogging; @@ -303,7 +306,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext { type, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_SLIPPERY - | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, + | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH + | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL + | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, PixelFormat.TRANSLUCENT); windowLayoutParams.setTitle(WINDOW_TITLE); windowLayoutParams.packageName = getPackageName(); @@ -467,7 +472,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { @Override public void onDragEnd() { - maybeSetTaskbarWindowNotFullscreen(); + onDragEndOrViewRemoved(); } @Override @@ -571,25 +576,34 @@ public class TaskbarActivityContext extends BaseTaskbarContext { .updateValue(darkIntensity); } + /** + * Called to update a {@link AutohideSuspendFlag} with a new value. + */ + public void setAutohideSuspendFlag(@AutohideSuspendFlag int flag, boolean newValue) { + mControllers.taskbarAutohideSuspendController.updateFlag(flag, newValue); + } + /** * Updates the TaskbarContainer to MATCH_PARENT vs original Taskbar size. */ public void setTaskbarWindowFullscreen(boolean fullscreen) { - mControllers.taskbarAutohideSuspendController.updateFlag( - TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_FULLSCREEN, fullscreen); + setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_FULLSCREEN, fullscreen); mIsFullscreen = fullscreen; setTaskbarWindowHeight(fullscreen ? MATCH_PARENT : mLastRequestedNonFullscreenHeight); } /** - * Reverts Taskbar window to its original size, if all floating views are closed and there is - * no system drag operation in progress. + * Called when drag ends or when a view is removed from the DragLayer. */ - void maybeSetTaskbarWindowNotFullscreen() { - if (AbstractFloatingView.getAnyView(this, TYPE_ALL) == null - && !mControllers.taskbarDragController.isSystemDragInProgress()) { + void onDragEndOrViewRemoved() { + boolean isDragInProgress = mControllers.taskbarDragController.isSystemDragInProgress(); + + if (!isDragInProgress && !AbstractFloatingView.hasOpenView(this, TYPE_ALL)) { + // Reverts Taskbar window to its original size setTaskbarWindowFullscreen(false); } + + setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_DRAGGING, isDragInProgress); } public boolean isTaskbarWindowFullscreen() { @@ -703,6 +717,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { Task task = (Task) tag; ActivityManagerWrapper.getInstance().startActivityFromRecents(task.key, ActivityOptions.makeBasic()); + mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true); } else if (tag instanceof FolderInfo) { FolderIcon folderIcon = (FolderIcon) view; Folder folder = folderIcon.getFolder(); @@ -762,6 +777,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { } mControllers.uiController.onTaskbarIconLaunched(info); + mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true); } catch (NullPointerException | ActivityNotFoundException | SecurityException e) { Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT) .show(); @@ -771,6 +787,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { } else if (tag instanceof AppInfo) { startItemInfoActivity((AppInfo) tag); mControllers.uiController.onTaskbarIconLaunched((AppInfo) tag); + mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true); } else { Log.e(TAG, "Unknown type clicked: " + tag); } @@ -805,6 +822,20 @@ public class TaskbarActivityContext extends BaseTaskbarContext { return mControllers.taskbarStashController.onLongPressToUnstashTaskbar(); } + /** + * Called when we want to unstash taskbar when user performs swipes up gesture. + */ + public void onSwipeToUnstashTaskbar() { + mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(false); + } + + /** + * Called when a transient Autohide flag suspend status changes. + */ + public void onTransientAutohideSuspendFlagChanged(boolean isSuspended) { + mControllers.taskbarStashController.updateTaskbarTimeout(isSuspended); + } + /** * Called when we detect a motion down or up/cancel in the nav region while stashed. * @param animateForward Whether to animate towards the unstashed hint state or back to stashed. diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java index 3cf9c997c9..4350e9c280 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java @@ -33,21 +33,28 @@ import java.util.StringJoiner; public class TaskbarAutohideSuspendController implements TaskbarControllers.LoggableTaskbarController { + // Taskbar window is fullscreen. public static final int FLAG_AUTOHIDE_SUSPEND_FULLSCREEN = 1 << 0; + // User is dragging item. public static final int FLAG_AUTOHIDE_SUSPEND_DRAGGING = 1 << 1; + // User has touched down but has not lifted finger. + public static final int FLAG_AUTOHIDE_SUSPEND_TOUCHING = 1 << 2; @IntDef(flag = true, value = { FLAG_AUTOHIDE_SUSPEND_FULLSCREEN, FLAG_AUTOHIDE_SUSPEND_DRAGGING, + FLAG_AUTOHIDE_SUSPEND_TOUCHING, }) @Retention(RetentionPolicy.SOURCE) public @interface AutohideSuspendFlag {} + private final TaskbarActivityContext mActivity; private final SystemUiProxy mSystemUiProxy; private @AutohideSuspendFlag int mAutohideSuspendFlags = 0; public TaskbarAutohideSuspendController(TaskbarActivityContext activity) { + mActivity = activity; mSystemUiProxy = SystemUiProxy.INSTANCE.get(activity); } @@ -59,12 +66,27 @@ public class TaskbarAutohideSuspendController implements * Adds or removes the given flag, then notifies system UI proxy whether to suspend auto-hide. */ public void updateFlag(@AutohideSuspendFlag int flag, boolean enabled) { + int flagsBefore = mAutohideSuspendFlags; if (enabled) { mAutohideSuspendFlags |= flag; } else { mAutohideSuspendFlags &= ~flag; } - mSystemUiProxy.notifyTaskbarAutohideSuspend(mAutohideSuspendFlags != 0); + if (flagsBefore == mAutohideSuspendFlags) { + // Nothing has changed, no need to notify. + return; + } + + boolean isSuspended = isSuspended(); + mSystemUiProxy.notifyTaskbarAutohideSuspend(isSuspended); + mActivity.onTransientAutohideSuspendFlagChanged(isSuspended); + } + + /** + * Returns true iff taskbar autohide is currently suspended. + */ + public boolean isSuspended() { + return mAutohideSuspendFlags != 0; } @Override @@ -79,6 +101,7 @@ public class TaskbarAutohideSuspendController implements appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_FULLSCREEN, "FLAG_AUTOHIDE_SUSPEND_FULLSCREEN"); appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_DRAGGING, "FLAG_AUTOHIDE_SUSPEND_DRAGGING"); + appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_TOUCHING, "FLAG_AUTOHIDE_SUSPEND_TOUCHING"); return str.toString(); } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java index 7e75779c62..7c9a13c5dc 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java @@ -115,6 +115,14 @@ public class TaskbarDragLayer extends BaseDragLayer { return true; } + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (mControllerCallbacks != null && ev.getAction() == MotionEvent.ACTION_OUTSIDE) { + mControllerCallbacks.onActionOutsideEvent(); + } + return super.onTouchEvent(ev); + } + @Override public void onViewRemoved(View child) { super.onViewRemoved(child); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java index 353f1e03cb..13ecf81a7d 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java @@ -23,6 +23,7 @@ import android.view.ViewTreeObserver; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.util.DimensionUtils; +import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.TouchController; import com.android.quickstep.AnimatedFloat; @@ -165,11 +166,25 @@ public class TaskbarDragLayerController implements TaskbarControllers.LoggableTa mControllers.taskbarInsetsController.updateInsetsTouchability(insetsInfo); } + /** + * Called whenever TaskbarDragLayer receives an ACTION_OUTSIDE event. + */ + public void onActionOutsideEvent() { + if (!DisplayController.isTransientTaskbar(mActivity)) { + return; + } + if (mControllers.taskbarStashController.isStashed()) { + return; + } + + mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true); + } + /** * Called when a child is removed from TaskbarDragLayer. */ public void onDragLayerViewRemoved() { - mActivity.maybeSetTaskbarWindowNotFullscreen(); + mActivity.onDragEndOrViewRemoved(); } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index 64eb99e7d1..afd659fc6e 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -39,11 +39,13 @@ import android.view.ViewConfiguration; import androidx.annotation.NonNull; import com.android.internal.jank.InteractionJankMonitor; +import com.android.launcher3.Alarm; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorListeners; import com.android.launcher3.testing.shared.TestProtocol; +import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.MultiPropertyFactory.MultiProperty; import com.android.quickstep.AnimatedFloat; import com.android.quickstep.SystemUiProxy; @@ -70,6 +72,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba public static final int FLAG_STASHED_IN_TASKBAR_ALL_APPS = 1 << 7; // All apps is visible. public static final int FLAG_IN_SETUP = 1 << 8; // In the Setup Wizard public static final int FLAG_STASHED_SMALL_SCREEN = 1 << 9; // phone screen gesture nav, stashed + public static final int FLAG_STASHED_IN_APP_AUTO = 1 << 10; // Autohide (transient taskbar). // If any of these flags are enabled, isInApp should return true. private static final int FLAGS_IN_APP = FLAG_IN_APP | FLAG_IN_SETUP; @@ -78,7 +81,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba private static final int FLAGS_STASHED_IN_APP = FLAG_STASHED_IN_APP_MANUAL | FLAG_STASHED_IN_APP_PINNED | FLAG_STASHED_IN_APP_EMPTY | FLAG_STASHED_IN_APP_SETUP | FLAG_STASHED_IN_APP_IME | FLAG_STASHED_IN_TASKBAR_ALL_APPS - | FLAG_STASHED_SMALL_SCREEN; + | FLAG_STASHED_SMALL_SCREEN | FLAG_STASHED_IN_APP_AUTO; private static final int FLAGS_STASHED_IN_APP_IGNORING_IME = FLAGS_STASHED_IN_APP & ~FLAG_STASHED_IN_APP_IME; @@ -132,6 +135,9 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba */ private static final boolean DEFAULT_STASHED_PREF = false; + // Auto stashes when user has not interacted with the Taskbar after X ms. + private static final long NO_TOUCH_TIMEOUT_TO_STASH_MS = 5000; + private final TaskbarActivityContext mActivity; private final SharedPreferences mPrefs; private final int mStashedHeight; @@ -162,6 +168,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba private boolean mEnableManualStashingDuringTests = false; + private final Alarm mTimeoutAlarm = new Alarm(); + // Evaluate whether the handle should be stashed private final StatePropertyHolder mStatePropertyHolder = new StatePropertyHolder( flags -> { @@ -210,13 +218,16 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba StashedHandleViewController.ALPHA_INDEX_STASHED); mTaskbarStashedHandleHintScale = stashedHandleController.getStashedHandleHintScale(); + boolean isTransientTaskbar = DisplayController.isTransientTaskbar(mActivity); // We use supportsVisualStashing() here instead of supportsManualStashing() because we want // it to work properly for tests that recreate taskbar. This check is here just to ensure // that taskbar unstashes when going to 3 button mode (supportsVisualStashing() false). boolean isManuallyStashedInApp = supportsVisualStashing() - && mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF); + && mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF) + && !isTransientTaskbar; boolean isInSetup = !mActivity.isUserSetupComplete() || setupUIVisible; updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp); + updateStateForFlag(FLAG_STASHED_IN_APP_AUTO, isTransientTaskbar); updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, isInSetup); updateStateForFlag(FLAG_IN_SETUP, isInSetup); updateStateForFlag(FLAG_STASHED_SMALL_SCREEN, isPhoneMode() @@ -243,7 +254,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba protected boolean supportsManualStashing() { return supportsVisualStashing() && isInApp() - && (!Utilities.IS_RUNNING_IN_TEST_HARNESS || mEnableManualStashingDuringTests); + && (!Utilities.IS_RUNNING_IN_TEST_HARNESS || mEnableManualStashingDuringTests) + && !DisplayController.isTransientTaskbar(mActivity); } /** @@ -376,6 +388,20 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba return mStashedHeight; } + /** + * Stash or unstashes the transient taskbar. + */ + public void updateAndAnimateTransientTaskbar(boolean stash) { + if (!DisplayController.isTransientTaskbar(mActivity)) { + return; + } + + if (hasAnyFlag(FLAG_STASHED_IN_APP_AUTO) != stash) { + updateStateForFlag(FLAG_STASHED_IN_APP_AUTO, stash); + applyState(); + } + } + /** * Should be called when long pressing the nav region when taskbar is present. * @return Whether taskbar was stashed and now is unstashed. @@ -549,11 +575,17 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba public void onAnimationStart(Animator animation) { mIsStashed = isStashed; onIsStashedChanged(mIsStashed); + + cancelTimeoutIfExists(); } @Override public void onAnimationEnd(Animator animation) { mAnimator = null; + + if (!mIsStashed) { + tryStartTaskbarTimeout(); + } } }); } @@ -779,6 +811,54 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba mControllers.rotationButtonController.onTaskbarStateChange(visible, stashed); } + /** + * Cancels a timeout if any exists. + */ + public void cancelTimeoutIfExists() { + if (mTimeoutAlarm.alarmPending()) { + mTimeoutAlarm.cancelAlarm(); + } + } + + /** + * Updates the status of the taskbar timeout. + * @param isAutohideSuspended If true, cancels any existing timeout + * If false, attempts to re/start the timeout + */ + public void updateTaskbarTimeout(boolean isAutohideSuspended) { + if (!DisplayController.isTransientTaskbar(mActivity)) { + return; + } + if (isAutohideSuspended) { + cancelTimeoutIfExists(); + } else { + tryStartTaskbarTimeout(); + } + } + + /** + * Attempts to start timer to auto hide the taskbar based on time. + */ + public void tryStartTaskbarTimeout() { + if (!DisplayController.isTransientTaskbar(mActivity)) { + return; + } + if (mIsStashed) { + return; + } + cancelTimeoutIfExists(); + + mTimeoutAlarm.setOnAlarmListener(this::onTaskbarTimeout); + mTimeoutAlarm.setAlarm(NO_TOUCH_TIMEOUT_TO_STASH_MS); + } + + private void onTaskbarTimeout(Alarm alarm) { + if (mControllers.taskbarAutohideSuspendController.isSuspended()) { + return; + } + updateAndAnimateTransientTaskbar(true); + } + @Override public void dumpLogs(String prefix, PrintWriter pw) { pw.println(prefix + "TaskbarStashController:"); @@ -794,17 +874,18 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba } private static String getStateString(int flags) { - StringJoiner str = new StringJoiner("|"); - appendFlag(str, flags, FLAGS_IN_APP, "FLAG_IN_APP"); - appendFlag(str, flags, FLAG_STASHED_IN_APP_MANUAL, "FLAG_STASHED_IN_APP_MANUAL"); - appendFlag(str, flags, FLAG_STASHED_IN_APP_PINNED, "FLAG_STASHED_IN_APP_PINNED"); - appendFlag(str, flags, FLAG_STASHED_IN_APP_EMPTY, "FLAG_STASHED_IN_APP_EMPTY"); - appendFlag(str, flags, FLAG_STASHED_IN_APP_SETUP, "FLAG_STASHED_IN_APP_SETUP"); - appendFlag(str, flags, FLAG_STASHED_IN_APP_IME, "FLAG_STASHED_IN_APP_IME"); - appendFlag(str, flags, FLAG_IN_STASHED_LAUNCHER_STATE, "FLAG_IN_STASHED_LAUNCHER_STATE"); - appendFlag(str, flags, FLAG_STASHED_IN_TASKBAR_ALL_APPS, "FLAG_STASHED_IN_APP_ALL_APPS"); - appendFlag(str, flags, FLAG_IN_SETUP, "FLAG_IN_SETUP"); - return str.toString(); + StringJoiner sj = new StringJoiner("|"); + appendFlag(sj, flags, FLAGS_IN_APP, "FLAG_IN_APP"); + appendFlag(sj, flags, FLAG_STASHED_IN_APP_MANUAL, "FLAG_STASHED_IN_APP_MANUAL"); + appendFlag(sj, flags, FLAG_STASHED_IN_APP_PINNED, "FLAG_STASHED_IN_APP_PINNED"); + appendFlag(sj, flags, FLAG_STASHED_IN_APP_EMPTY, "FLAG_STASHED_IN_APP_EMPTY"); + appendFlag(sj, flags, FLAG_STASHED_IN_APP_SETUP, "FLAG_STASHED_IN_APP_SETUP"); + appendFlag(sj, flags, FLAG_STASHED_IN_APP_IME, "FLAG_STASHED_IN_APP_IME"); + appendFlag(sj, flags, FLAG_IN_STASHED_LAUNCHER_STATE, "FLAG_IN_STASHED_LAUNCHER_STATE"); + appendFlag(sj, flags, FLAG_STASHED_IN_TASKBAR_ALL_APPS, "FLAG_STASHED_IN_TASKBAR_ALL_APPS"); + appendFlag(sj, flags, FLAG_IN_SETUP, "FLAG_IN_SETUP"); + appendFlag(sj, flags, FLAG_STASHED_IN_APP_AUTO, "FLAG_STASHED_IN_APP_AUTO"); + return sj.toString(); } private class StatePropertyHolder { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java index 9ec8cfeffa..2294306ac3 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java @@ -15,6 +15,7 @@ */ package com.android.launcher3.taskbar; +import android.view.MotionEvent; import android.view.View; import androidx.annotation.CallSuper; @@ -104,6 +105,15 @@ public class TaskbarUIController { return mControllers.taskbarStashController.isStashed(); } + /* + * @param ev MotionEvent in screen coordinates. + * @return Whether any Taskbar item could handle the given MotionEvent if given the chance. + */ + public boolean isEventOverAnyTaskbarItem(MotionEvent ev) { + return mControllers.taskbarViewController.isEventOverAnyItem(ev) + || mControllers.navbarButtonsViewController.isEventOverAnyItem(ev); + } + @CallSuper protected void dumpLogs(String prefix, PrintWriter pw) { pw.println(String.format( diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java index c754a59a06..bdcc4295fe 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java @@ -380,13 +380,23 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar return super.dispatchTouchEvent(ev); } + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + mControllerCallbacks.onInterceptTouchEvent(ev); + return super.onInterceptTouchEvent(ev); + } + @Override public boolean onTouchEvent(MotionEvent event) { if (!mTouchEnabled) { return true; } - if (mIconLayoutBounds.left <= event.getX() && event.getX() <= mIconLayoutBounds.right) { - // Don't allow long pressing between icons, or above/below them. + if (mIconLayoutBounds.left <= event.getX() + && event.getX() <= mIconLayoutBounds.right + && !DisplayController.isTransientTaskbar(mActivityContext)) { + // Don't allow long pressing between icons, or above/below them + // unless its transient taskbar. + mControllerCallbacks.clearTouchInProgress(); return true; } if (mControllerCallbacks.onTouchEvent(event)) { @@ -403,6 +413,7 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar public void setTouchesEnabled(boolean touchEnabled) { this.mTouchEnabled = touchEnabled; + mControllerCallbacks.clearTouchInProgress(); } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index f0277a4d08..2bc609eaf3 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -22,6 +22,8 @@ import static com.android.launcher3.Utilities.squaredHypot; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP; import static com.android.launcher3.taskbar.TaskbarManager.isPhoneMode; +import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_NEGATIVE; +import static com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL; import static com.android.quickstep.AnimatedFloat.VALUE; import android.annotation.NonNull; @@ -32,6 +34,7 @@ import android.util.Log; import android.view.MotionEvent; import android.view.View; +import androidx.annotation.Nullable; import androidx.core.graphics.ColorUtils; import androidx.core.view.OneShotPreDrawListener; @@ -48,6 +51,7 @@ import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.icons.ThemedIconDrawable; import com.android.launcher3.model.data.ItemInfo; +import com.android.launcher3.touch.SingleAxisSwipeDetector; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.HorizontalInsettableView; import com.android.launcher3.util.ItemInfoMatcher; @@ -97,6 +101,9 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar private final TaskbarModelCallbacks mModelCallbacks; + // Captures swipe down action to close transient taskbar. + protected @Nullable SingleAxisSwipeDetector mSwipeDownDetector; + // Initialized in init. private TaskbarControllers mControllers; @@ -119,6 +126,31 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar mTaskbarBottomMargin = DisplayController.isTransientTaskbar(activity) ? activity.getResources().getDimensionPixelSize(R.dimen.transient_taskbar_margin) : 0; + + if (DisplayController.isTransientTaskbar(mActivity)) { + mSwipeDownDetector = new SingleAxisSwipeDetector(activity, + new SingleAxisSwipeDetector.Listener() { + private float mLastDisplacement; + + @Override + public boolean onDrag(float displacement) { + mLastDisplacement = displacement; + return false; + } + + @Override + public void onDragEnd(float velocity) { + if (mLastDisplacement > 0) { + mControllers.taskbarStashController + .updateAndAnimateTransientTaskbar(true); + } + } + + @Override + public void onDragStart(boolean start, float startDisplacement) {} + }, VERTICAL); + mSwipeDownDetector.setDetectableScrollConditions(DIRECTION_NEGATIVE, false); + } } public void init(TaskbarControllers controllers) { @@ -436,6 +468,8 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar private float mDownX, mDownY; private boolean mCanceledStashHint; + private boolean mTouchInProgress; + public View.OnClickListener getIconOnClickListener() { return mActivity.getItemOnClickListener(); } @@ -463,38 +497,76 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar .updateAndAnimateIsManuallyStashedInApp(true); } + /** + * Simply listens to all intercept touch events passed to TaskbarView. + */ + public void onInterceptTouchEvent(MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + mTouchInProgress = true; + } + + if (mTouchInProgress && mSwipeDownDetector != null) { + mSwipeDownDetector.onTouchEvent(ev); + } + + if (ev.getAction() == MotionEvent.ACTION_UP + || ev.getAction() == MotionEvent.ACTION_CANCEL) { + clearTouchInProgress(); + } + } + /** * Get the first chance to handle TaskbarView#onTouchEvent, and return whether we want to * consume the touch so TaskbarView treats it as an ACTION_CANCEL. */ public boolean onTouchEvent(MotionEvent motionEvent) { + boolean shouldConsumeTouch = false; + boolean clearTouchInProgress = false; + final float x = motionEvent.getRawX(); final float y = motionEvent.getRawY(); switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: + mTouchInProgress = true; mDownX = x; mDownY = y; mControllers.taskbarStashController.startStashHint(/* animateForward = */ true); mCanceledStashHint = false; break; case MotionEvent.ACTION_MOVE: - if (!mCanceledStashHint + if (mTouchInProgress + && !mCanceledStashHint && squaredHypot(mDownX - x, mDownY - y) > mSquaredTouchSlop) { mControllers.taskbarStashController.startStashHint( /* animateForward= */ false); mCanceledStashHint = true; - return true; + shouldConsumeTouch = true; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: - if (!mCanceledStashHint) { + if (mTouchInProgress && !mCanceledStashHint) { mControllers.taskbarStashController.startStashHint( /* animateForward= */ false); } + clearTouchInProgress = true; break; } - return false; + + if (mTouchInProgress && mSwipeDownDetector != null) { + mSwipeDownDetector.onTouchEvent(motionEvent); + } + if (clearTouchInProgress) { + clearTouchInProgress(); + } + return shouldConsumeTouch; + } + + /** + * Ensures that we do not pass any more touch events to the SwipeDetector. + */ + public void clearTouchInProgress() { + mTouchInProgress = false; } } diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java index 3785de4ecd..1430492401 100644 --- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java +++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java @@ -15,9 +15,14 @@ */ package com.android.quickstep.inputconsumers; +import static android.view.MotionEvent.INVALID_POINTER_ID; + import static com.android.launcher3.Utilities.squaredHypot; +import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_TOUCHING; import android.content.Context; +import android.content.res.Resources; +import android.graphics.PointF; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; @@ -25,6 +30,7 @@ import android.view.MotionEvent; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.taskbar.TaskbarActivityContext; +import com.android.launcher3.util.DisplayController; import com.android.quickstep.InputConsumer; import com.android.systemui.shared.system.InputMonitorCompat; @@ -37,20 +43,32 @@ public class TaskbarStashInputConsumer extends DelegateInputConsumer { private final GestureDetector mLongPressDetector; private final float mSquaredTouchSlop; - - private float mDownX, mDownY; + private float mLongPressDownX, mLongPressDownY; private boolean mCanceledUnstashHint; private final float mUnstashArea; private final float mScreenWidth; + private final int mTaskbarThreshold; + private boolean mHasPassedTaskbarThreshold; + + private final PointF mDownPos = new PointF(); + private final PointF mLastPos = new PointF(); + private int mActivePointerId = INVALID_POINTER_ID; + + private final boolean mIsTransientTaskbar; + public TaskbarStashInputConsumer(Context context, InputConsumer delegate, InputMonitorCompat inputMonitor, TaskbarActivityContext taskbarActivityContext) { super(delegate, inputMonitor); mTaskbarActivityContext = taskbarActivityContext; mSquaredTouchSlop = Utilities.squaredTouchSlop(context); mScreenWidth = taskbarActivityContext.getDeviceProfile().widthPx; - mUnstashArea = context.getResources() - .getDimensionPixelSize(R.dimen.taskbar_unstash_input_area); + + Resources res = context.getResources(); + mUnstashArea = res.getDimensionPixelSize(R.dimen.taskbar_unstash_input_area); + mTaskbarThreshold = res.getDimensionPixelSize(R.dimen.taskbar_nav_threshold); + + mIsTransientTaskbar = DisplayController.isTransientTaskbar(context); mLongPressDetector = new GestureDetector(context, new SimpleOnGestureListener() { @Override @@ -76,28 +94,71 @@ public class TaskbarStashInputConsumer extends DelegateInputConsumer { final float y = ev.getRawY(); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: + mActivePointerId = ev.getPointerId(0); + mDownPos.set(ev.getX(), ev.getY()); + mLastPos.set(mDownPos); + + mHasPassedTaskbarThreshold = false; + mTaskbarActivityContext.setAutohideSuspendFlag( + FLAG_AUTOHIDE_SUSPEND_TOUCHING, true); if (isInArea(x)) { - mDownX = x; - mDownY = y; - mTaskbarActivityContext.startTaskbarUnstashHint( - /* animateForward = */ true); - mCanceledUnstashHint = false; + if (!mIsTransientTaskbar) { + mLongPressDownX = x; + mLongPressDownY = y; + mTaskbarActivityContext.startTaskbarUnstashHint( + /* animateForward = */ true); + mCanceledUnstashHint = false; + } + } + break; + case MotionEvent.ACTION_POINTER_UP: + int ptrIdx = ev.getActionIndex(); + int ptrId = ev.getPointerId(ptrIdx); + if (ptrId == mActivePointerId) { + final int newPointerIdx = ptrIdx == 0 ? 1 : 0; + mDownPos.set( + ev.getX(newPointerIdx) - (mLastPos.x - mDownPos.x), + ev.getY(newPointerIdx) - (mLastPos.y - mDownPos.y)); + mLastPos.set(ev.getX(newPointerIdx), ev.getY(newPointerIdx)); + mActivePointerId = ev.getPointerId(newPointerIdx); } break; case MotionEvent.ACTION_MOVE: - if (!mCanceledUnstashHint - && squaredHypot(mDownX - x, mDownY - y) > mSquaredTouchSlop) { + if (!mIsTransientTaskbar + && !mCanceledUnstashHint + && squaredHypot(mLongPressDownX - x, mLongPressDownY - y) + > mSquaredTouchSlop) { mTaskbarActivityContext.startTaskbarUnstashHint( /* animateForward = */ false); mCanceledUnstashHint = true; } + + int pointerIndex = ev.findPointerIndex(mActivePointerId); + if (pointerIndex == INVALID_POINTER_ID) { + break; + } + mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex)); + float displacementY = mLastPos.y - mDownPos.y; + float verticalDist = Math.abs(displacementY); + boolean passedTaskbarThreshold = verticalDist >= mTaskbarThreshold; + + if (!mHasPassedTaskbarThreshold + && passedTaskbarThreshold + && mIsTransientTaskbar) { + mHasPassedTaskbarThreshold = true; + + mTaskbarActivityContext.onSwipeToUnstashTaskbar(); + } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: - if (!mCanceledUnstashHint) { + if (!mIsTransientTaskbar && !mCanceledUnstashHint) { mTaskbarActivityContext.startTaskbarUnstashHint( /* animateForward = */ false); } + mTaskbarActivityContext.setAutohideSuspendFlag( + FLAG_AUTOHIDE_SUSPEND_TOUCHING, false); + mHasPassedTaskbarThreshold = false; break; } } @@ -111,7 +172,9 @@ public class TaskbarStashInputConsumer extends DelegateInputConsumer { } private void onLongPressDetected(MotionEvent motionEvent) { - if (mTaskbarActivityContext != null && isInArea(motionEvent.getRawX())) { + if (mTaskbarActivityContext != null + && isInArea(motionEvent.getRawX()) + && !mIsTransientTaskbar) { boolean taskBarPressed = mTaskbarActivityContext.onLongPressToUnstashTaskbar(); if (taskBarPressed) { setActive(motionEvent); From 406bc6f24705df7e2fda03d709c106fe70ce6f1c Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Fri, 21 Oct 2022 11:25:07 -0700 Subject: [PATCH 10/12] Disable Drag from Taskbar in Overview * Still need to disable drag from all apps in overview * Disallow any taskbar icon long click when in split select Bug: 251747761 Test: Drag from hotseat and predicted icons in overview, snaps back to position Change-Id: Ib9b068e4914b9197614c8e8f49b7899bb964f92b --- .../taskbar/TaskbarDragController.java | 178 +++++++++++++----- .../TaskbarLauncherStateController.java | 6 + 2 files changed, 135 insertions(+), 49 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java index 9a1e0642bb..d7bb16e7a2 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java @@ -18,10 +18,12 @@ package com.android.launcher3.taskbar; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APPS; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICTION; import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT; +import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; +import android.annotation.NonNull; import android.content.ClipData; import android.content.ClipDescription; import android.content.Intent; @@ -49,7 +51,6 @@ import com.android.launcher3.DragSource; import com.android.launcher3.DropTarget; import com.android.launcher3.LauncherSettings; import com.android.launcher3.R; -import com.android.launcher3.Utilities; import com.android.launcher3.accessibility.DragViewStateAnnouncer; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.config.FeatureFlags; @@ -70,6 +71,7 @@ import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.ItemInfoMatcher; import com.android.quickstep.util.LogUtils; +import com.android.quickstep.util.MultiValueUpdateListener; import com.android.systemui.shared.recents.model.Task; import java.io.PrintWriter; @@ -83,7 +85,8 @@ import java.util.function.Predicate; public class TaskbarDragController extends DragController implements TaskbarControllers.LoggableTaskbarController { - private static boolean DEBUG_DRAG_SHADOW_SURFACE = false; + private static final boolean DEBUG_DRAG_SHADOW_SURFACE = false; + private static final int ANIM_DURATION_RETURN_ICON_TO_TASKBAR = 300; private final int mDragIconSize; private final int[] mTempXY = new int[2]; @@ -99,6 +102,8 @@ public class TaskbarDragController extends DragController im // Animation for the drag shadow back into position after an unsuccessful drag private ValueAnimator mReturnAnimator; + private boolean mDisallowGlobalDrag; + private boolean mDisallowLongClick; public TaskbarDragController(BaseTaskbarContext activity) { super(activity); @@ -110,6 +115,14 @@ public class TaskbarDragController extends DragController im mControllers = controllers; } + public void setDisallowGlobalDrag(boolean disallowGlobalDrag) { + mDisallowGlobalDrag = disallowGlobalDrag; + } + + public void setDisallowLongClick(boolean disallowLongClick) { + mDisallowLongClick = disallowLongClick; + } + /** * Attempts to start a system drag and drop operation for the given View, using its tag to * generate the ClipDescription and Intent. @@ -131,7 +144,7 @@ public class TaskbarDragController extends DragController im View view, @Nullable DragPreviewProvider dragPreviewProvider, @Nullable Point iconShift) { - if (!(view instanceof BubbleTextView)) { + if (!(view instanceof BubbleTextView) || mDisallowLongClick) { return false; } TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onTaskbarItemLongClick"); @@ -293,6 +306,7 @@ public class TaskbarDragController extends DragController im } private void startSystemDrag(BubbleTextView btv) { + if (mDisallowGlobalDrag) return; View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(btv) { @Override @@ -421,6 +435,45 @@ public class TaskbarDragController extends DragController im } } + @Override + protected void endDrag() { + if (mDisallowGlobalDrag) { + // We need to explicitly set deferDragViewCleanupPostAnimation to true here so the + // super call doesn't remove it from the drag layer before the animation completes. + // This variable gets set in to false in super.dispatchDropComplete() because it + // (rightfully so, perhaps) thinks this drag operation has failed, and does its own + // internal cleanup. + // Another way to approach this would be to make all of overview a drop target and + // accept the drop as successful and then run the setupReturnDragAnimator to simulate + // drop failure to the user + mDragObject.deferDragViewCleanupPostAnimation = true; + + float fromX = mDragObject.x - mDragObject.xOffset; + float fromY = mDragObject.y - mDragObject.yOffset; + DragView dragView = mDragObject.dragView; + setupReturnDragAnimator(fromX, fromY, (View) mDragObject.originalView, + (x, y, scale, alpha) -> { + dragView.setTranslationX(x); + dragView.setTranslationY(y); + dragView.setScaleX(scale); + dragView.setScaleY(scale); + dragView.setAlpha(alpha); + }); + mReturnAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + callOnDragEnd(); + dragView.remove(); + dragView.clearAnimation(); + mReturnAnimator = null; + + } + }); + mReturnAnimator.start(); + } + super.endDrag(); + } + @Override protected void callOnDragEnd() { super.callOnDragEnd(); @@ -432,56 +485,20 @@ public class TaskbarDragController extends DragController im SurfaceControl dragSurface = dragEvent.getDragSurface(); // For top level icons, the target is the icon itself - View target = btv; - Object tag = btv.getTag(); - if (tag instanceof ItemInfo) { - ItemInfo item = (ItemInfo) tag; - TaskbarViewController taskbarViewController = mControllers.taskbarViewController; - if (item.container == CONTAINER_ALL_APPS || item.container == CONTAINER_PREDICTION) { - // Since all apps closes when the drag starts, target the all apps button instead. - target = taskbarViewController.getAllAppsButtonView(); - } else if (item.container >= 0) { - // Since folders close when the drag starts, target the folder icon instead. - Predicate matcher = ItemInfoMatcher.forFolderMatch( - ItemInfoMatcher.ofItemIds(IntSet.wrap(item.id))); - target = taskbarViewController.getFirstIconMatch(matcher); - } else if (item.itemType == ITEM_TYPE_DEEP_SHORTCUT) { - // Find first icon with same package/user as the deep shortcut. - Predicate packageUserMatcher = ItemInfoMatcher.ofPackages( - Collections.singleton(item.getTargetPackage()), item.user); - target = taskbarViewController.getFirstIconMatch(packageUserMatcher); - } - } - - // Finish any pending return animation before starting a new drag - if (mReturnAnimator != null) { - mReturnAnimator.end(); - } + View target = findTaskbarTargetForIconView(btv); float fromX = dragEvent.getX() - dragEvent.getOffsetX(); float fromY = dragEvent.getY() - dragEvent.getOffsetY(); - int[] toPosition = target.getLocationOnScreen(); - float toScale = (float) target.getWidth() / mDragIconSize; - float toAlpha = (target == btv) ? 1f : 0f; final ViewRootImpl viewRoot = target.getViewRootImpl(); SurfaceControl.Transaction tx = new SurfaceControl.Transaction(); - mReturnAnimator = ValueAnimator.ofFloat(0f, 1f); - mReturnAnimator.setDuration(300); - mReturnAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); - mReturnAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - float t = animation.getAnimatedFraction(); - float accelT = Interpolators.ACCEL_2.getInterpolation(t); - float scale = 1f - t * (1f - toScale); - float alpha = 1f - accelT * (1f - toAlpha); - tx.setPosition(dragSurface, Utilities.mapRange(t, fromX, toPosition[0]), - Utilities.mapRange(t, fromY, toPosition[1])); - tx.setScale(dragSurface, scale, scale); - tx.setAlpha(dragSurface, alpha); - tx.apply(); - } - }); + setupReturnDragAnimator(fromX, fromY, btv, + (x, y, scale, alpha) -> { + tx.setPosition(dragSurface, x, y); + tx.setScale(dragSurface, scale, scale); + tx.setAlpha(dragSurface, alpha); + tx.apply(); + }); + mReturnAnimator.addListener(new AnimatorListenerAdapter() { private boolean mCanceled = false; @@ -517,6 +534,63 @@ public class TaskbarDragController extends DragController im mReturnAnimator.start(); } + private View findTaskbarTargetForIconView(@NonNull View iconView) { + Object tag = iconView.getTag(); + if (tag instanceof ItemInfo) { + ItemInfo item = (ItemInfo) tag; + TaskbarViewController taskbarViewController = mControllers.taskbarViewController; + if (item.container == CONTAINER_ALL_APPS || item.container == CONTAINER_PREDICTION) { + // Since all apps closes when the drag starts, target the all apps button instead. + return taskbarViewController.getAllAppsButtonView(); + } else if (item.container >= 0) { + // Since folders close when the drag starts, target the folder icon instead. + Predicate matcher = ItemInfoMatcher.forFolderMatch( + ItemInfoMatcher.ofItemIds(IntSet.wrap(item.id))); + return taskbarViewController.getFirstIconMatch(matcher); + } else if (item.itemType == ITEM_TYPE_DEEP_SHORTCUT) { + // Find first icon with same package/user as the deep shortcut. + Predicate packageUserMatcher = ItemInfoMatcher.ofPackages( + Collections.singleton(item.getTargetPackage()), item.user); + return taskbarViewController.getFirstIconMatch(packageUserMatcher); + } + } + return iconView; + } + + private void setupReturnDragAnimator(float fromX, float fromY, View originalView, + TaskbarReturnPropertiesListener animListener) { + // Finish any pending return animation before starting a new return + if (mReturnAnimator != null) { + mReturnAnimator.end(); + } + + // For top level icons, the target is the icon itself + View target = findTaskbarTargetForIconView(originalView); + + int[] toPosition = target.getLocationOnScreen(); + float toScale = (float) target.getWidth() / mDragIconSize; + float toAlpha = (target == originalView) ? 1f : 0f; + MultiValueUpdateListener listener = new MultiValueUpdateListener() { + final FloatProp mDx = new FloatProp(fromX, toPosition[0], 0, + ANIM_DURATION_RETURN_ICON_TO_TASKBAR, Interpolators.FAST_OUT_SLOW_IN); + final FloatProp mDy = new FloatProp(fromY, toPosition[1], 0, + ANIM_DURATION_RETURN_ICON_TO_TASKBAR, + FAST_OUT_SLOW_IN); + final FloatProp mScale = new FloatProp(1f, toScale, 0, + ANIM_DURATION_RETURN_ICON_TO_TASKBAR, FAST_OUT_SLOW_IN); + final FloatProp mAlpha = new FloatProp(1f, toAlpha, 0, + ANIM_DURATION_RETURN_ICON_TO_TASKBAR, Interpolators.ACCEL_2); + @Override + public void onUpdate(float percent, boolean initOnly) { + animListener.updateDragShadow(mDx.value, mDy.value, mScale.value, mAlpha.value); + } + }; + mReturnAnimator = ValueAnimator.ofFloat(0f, 1f); + mReturnAnimator.setDuration(ANIM_DURATION_RETURN_ICON_TO_TASKBAR); + mReturnAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); + mReturnAnimator.addUpdateListener(listener); + } + @Override protected float getX(MotionEvent ev) { // We will resize to fill the screen while dragging, so use screen coordinates. This ensures @@ -540,7 +614,7 @@ public class TaskbarDragController extends DragController im @Override protected void exitDrag() { - if (mDragObject != null) { + if (mDragObject != null && !mDisallowGlobalDrag) { mActivity.getDragLayer().removeView(mDragObject.dragView); } } @@ -556,6 +630,10 @@ public class TaskbarDragController extends DragController im return null; } + interface TaskbarReturnPropertiesListener { + void updateDragShadow(float x, float y, float scale, float alpha); + } + @Override public void dumpLogs(String prefix, PrintWriter pw) { pw.println(prefix + "TaskbarDragController:"); @@ -566,5 +644,7 @@ public class TaskbarDragController extends DragController im pw.println(prefix + "\tmRegistrationY=" + mRegistrationY); pw.println(prefix + "\tmIsSystemDragInProgress=" + mIsSystemDragInProgress); pw.println(prefix + "\tisInternalDragInProgess=" + super.isDragging()); + pw.println(prefix + "\tmDisallowGlobalDrag=" + mDisallowGlobalDrag); + pw.println(prefix + "\tmDisallowLongClick=" + mDisallowLongClick); } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java index 63f1486729..bc5bcf5b28 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java @@ -39,6 +39,8 @@ import com.android.launcher3.anim.AnimatorListeners; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.launcher3.util.MultiPropertyFactory.MultiProperty; +import com.android.launcher3.uioverrides.states.OverviewState; +import com.android.launcher3.util.MultiValueAlpha; import com.android.quickstep.AnimatedFloat; import com.android.quickstep.RecentsAnimationCallbacks; import com.android.quickstep.RecentsAnimationController; @@ -117,6 +119,10 @@ import java.util.StringJoiner; mLauncherState = finalState; updateStateForFlag(FLAG_TRANSITION_STATE_RUNNING, false); applyState(); + mControllers.taskbarDragController.setDisallowGlobalDrag( + (finalState instanceof OverviewState)); + mControllers.taskbarDragController.setDisallowLongClick( + finalState == LauncherState.OVERVIEW_SPLIT_SELECT); } }; From 3c7054f0d2efa6def3ebeca653c42e90b0dc598f Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Fri, 28 Oct 2022 12:37:28 -0700 Subject: [PATCH 11/12] Updating widget prediction handling: When handling widget prediction, first match the full provider names Only if no widgets are found, match any widget in the package Bug: 256202399 Test: atest WidgetsPredicationUpdateTaskTest Change-Id: I5337618d935f8b926803aeefede46059545de72d --- .../model/WidgetsPredictionUpdateTask.java | 67 +++++++++---------- .../WidgetsPredicationUpdateTaskTest.java | 43 +++++------- .../launcher3/config/FeatureFlags.java | 4 -- 3 files changed, 48 insertions(+), 66 deletions(-) diff --git a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java index 7a483a808a..1beabf1255 100644 --- a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java +++ b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java @@ -18,22 +18,22 @@ package com.android.launcher3.model; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION; import android.app.prediction.AppTarget; -import android.content.ComponentName; import android.text.TextUtils; import androidx.annotation.NonNull; import com.android.launcher3.LauncherAppState; -import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.BgDataModel.FixedContainerItems; import com.android.launcher3.model.QuickstepModelDelegate.PredictorState; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.widget.PendingAddWidgetInfo; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Predicate; import java.util.stream.Collectors; /** Task to update model as a result of predicted widgets update */ @@ -59,50 +59,43 @@ public final class WidgetsPredictionUpdateTask extends BaseModelUpdateTask { Set widgetsInWorkspace = dataModel.appWidgets.stream().map( widget -> new ComponentKey(widget.providerName, widget.user)).collect( Collectors.toSet()); + Predicate notOnWorkspace = w -> !widgetsInWorkspace.contains(w); Map> allWidgets = dataModel.widgetsModel.getAllWidgetsWithoutShortcuts(); - FixedContainerItems fixedContainerItems = - new FixedContainerItems(mPredictorState.containerId); + List servicePredictedItems = new ArrayList<>(); + List localFilteredWidgets = new ArrayList<>(); - if (FeatureFlags.ENABLE_LOCAL_RECOMMENDED_WIDGETS_FILTER.get()) { - for (AppTarget app : mTargets) { - PackageUserKey packageUserKey = new PackageUserKey(app.getPackageName(), - app.getUser()); - if (allWidgets.containsKey(packageUserKey)) { - List notAddedWidgets = allWidgets.get(packageUserKey).stream() - .filter(item -> - !widgetsInWorkspace.contains( - new ComponentKey(item.componentName, item.user))) - .collect(Collectors.toList()); - if (notAddedWidgets.size() > 0) { - // Even an apps have more than one widgets, we only include one widget. - fixedContainerItems.items.add( - new PendingAddWidgetInfo( - notAddedWidgets.get(0).widgetInfo, - CONTAINER_WIDGETS_PREDICTION)); - } - } + for (AppTarget app : mTargets) { + PackageUserKey packageUserKey = new PackageUserKey(app.getPackageName(), app.getUser()); + List widgets = allWidgets.get(packageUserKey); + if (widgets == null || widgets.isEmpty()) { + continue; } - } else { - Map widgetItems = - allWidgets.values().stream().flatMap(List::stream).distinct() - .collect(Collectors.toMap(widget -> (ComponentKey) widget, - widget -> widget)); - for (AppTarget app : mTargets) { - if (TextUtils.isEmpty(app.getClassName())) { + String className = app.getClassName(); + if (!TextUtils.isEmpty(className)) { + WidgetItem item = widgets.stream() + .filter(w -> className.equals(w.componentName.getClassName())) + .filter(notOnWorkspace) + .findFirst() + .orElse(null); + if (item != null) { + servicePredictedItems.add(item); continue; } - ComponentKey targetWidget = new ComponentKey( - new ComponentName(app.getPackageName(), app.getClassName()), app.getUser()); - if (widgetItems.containsKey(targetWidget)) { - fixedContainerItems.items.add( - new PendingAddWidgetInfo(widgetItems.get( - targetWidget).widgetInfo, - CONTAINER_WIDGETS_PREDICTION)); - } } + // No widget was added by the service, try local filtering + widgets.stream().filter(notOnWorkspace).findFirst() + .ifPresent(localFilteredWidgets::add); } + if (servicePredictedItems.isEmpty()) { + servicePredictedItems.addAll(localFilteredWidgets); + } + FixedContainerItems fixedContainerItems = + new FixedContainerItems(mPredictorState.containerId); + servicePredictedItems.forEach(w -> fixedContainerItems.items.add( + new PendingAddWidgetInfo(w.widgetInfo, CONTAINER_WIDGETS_PREDICTION))); + dataModel.extraItems.put(mPredictorState.containerId, fixedContainerItems); bindExtraContainerItems(fixedContainerItems); diff --git a/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java b/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java index b90369132b..83341cb868 100644 --- a/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java +++ b/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java @@ -41,7 +41,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.launcher3.LauncherAppState; -import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.icons.ComponentWithLabel; import com.android.launcher3.icons.IconCache; import com.android.launcher3.model.BgDataModel.FixedContainerItems; @@ -136,21 +135,21 @@ public final class WidgetsPredicationUpdateTaskTest { public void widgetsRecommendationRan_shouldOnlyReturnNotAddedWidgetsInAppPredictionOrder() throws Exception { // WHEN newPredicationTask is executed with app predication of 5 apps. - AppTarget app1 = new AppTarget(new AppTargetId("app1"), "app1", "className", + AppTarget app1 = new AppTarget(new AppTargetId("app1"), "app1", "provider1", mUserHandle); - AppTarget app2 = new AppTarget(new AppTargetId("app2"), "app2", "className", + AppTarget app2 = new AppTarget(new AppTargetId("app2"), "app2", "provider1", mUserHandle); AppTarget app3 = new AppTarget(new AppTargetId("app3"), "app3", "className", mUserHandle); - AppTarget app4 = new AppTarget(new AppTargetId("app4"), "app4", "className", + AppTarget app4 = new AppTarget(new AppTargetId("app4"), "app4", "provider1", mUserHandle); - AppTarget app5 = new AppTarget(new AppTargetId("app5"), "app5", "className", + AppTarget app5 = new AppTarget(new AppTargetId("app5"), "app5", "provider1", mUserHandle); mModelHelper.executeTaskForTest( newWidgetsPredicationTask(List.of(app5, app3, app2, app4, app1))) .forEach(Runnable::run); - // THEN only 3 widgets are returned because + // THEN only 2 widgets are returned because // 1. app5/provider1 & app4/provider1 have already been added to workspace. They are // excluded from the result. // 2. app3 doesn't have a widget. @@ -159,45 +158,39 @@ public final class WidgetsPredicationUpdateTaskTest { .stream() .map(itemInfo -> (PendingAddWidgetInfo) itemInfo) .collect(Collectors.toList()); - assertThat(recommendedWidgets).hasSize(3); + assertThat(recommendedWidgets).hasSize(2); assertWidgetInfo(recommendedWidgets.get(0).info, mApp2Provider1); - assertWidgetInfo(recommendedWidgets.get(1).info, mApp4Provider2); - assertWidgetInfo(recommendedWidgets.get(2).info, mApp1Provider1); + assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider1); } @Test - public void widgetsRecommendationRan_localFilterDisabled_shouldReturnWidgetsInPredicationOrder() + public void widgetsRecommendationRan_shouldReturnPackageWidgetsWhenEmpty() throws Exception { - if (FeatureFlags.ENABLE_LOCAL_RECOMMENDED_WIDGETS_FILTER.get()) { - return; - } - // WHEN newPredicationTask is executed with 5 predicated widgets. - AppTarget widget1 = new AppTarget(new AppTargetId("app1"), "app1", "provider1", - mUserHandle); - AppTarget widget2 = new AppTarget(new AppTargetId("app1"), "app1", "provider2", + // Not installed widget + AppTarget widget1 = new AppTarget(new AppTargetId("app1"), "app1", "provider3", mUserHandle); // Not installed app AppTarget widget3 = new AppTarget(new AppTargetId("app2"), "app3", "provider1", mUserHandle); - // Not installed widget - AppTarget widget4 = new AppTarget(new AppTargetId("app4"), "app4", "provider3", + // Workspace added widgets + AppTarget widget4 = new AppTarget(new AppTargetId("app4"), "app4", "provider1", mUserHandle); AppTarget widget5 = new AppTarget(new AppTargetId("app5"), "app5", "provider1", mUserHandle); mModelHelper.executeTaskForTest( - newWidgetsPredicationTask(List.of(widget5, widget3, widget2, widget4, widget1))) + newWidgetsPredicationTask(List.of(widget5, widget3, widget4, widget1))) .forEach(Runnable::run); - // THEN only 3 widgets are returned because the launcher only filters out non-exist widgets. + // THEN only 2 widgets are returned because the launcher only filters out non-exist widgets. List recommendedWidgets = mCallback.mRecommendedWidgets.items .stream() .map(itemInfo -> (PendingAddWidgetInfo) itemInfo) .collect(Collectors.toList()); - assertThat(recommendedWidgets).hasSize(3); - assertWidgetInfo(recommendedWidgets.get(0).info, mApp5Provider1); - assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider2); - assertWidgetInfo(recommendedWidgets.get(2).info, mApp1Provider1); + assertThat(recommendedWidgets).hasSize(2); + // Another widget from the same package + assertWidgetInfo(recommendedWidgets.get(0).info, mApp4Provider2); + assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider1); } private void assertWidgetInfo( diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index 694536c287..32463a5746 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -206,10 +206,6 @@ public final class FeatureFlags { public static final BooleanFlag ENABLE_ENFORCED_ROUNDED_CORNERS = new DeviceFlag( "ENABLE_ENFORCED_ROUNDED_CORNERS", true, "Enforce rounded corners on all App Widgets"); - public static final BooleanFlag ENABLE_LOCAL_RECOMMENDED_WIDGETS_FILTER = new DeviceFlag( - "ENABLE_LOCAL_RECOMMENDED_WIDGETS_FILTER", true, - "Enables a local filter for recommended widgets."); - public static final BooleanFlag NOTIFY_CRASHES = getDebugFlag("NOTIFY_CRASHES", false, "Sends a notification whenever launcher encounters an uncaught exception."); From afc3bff10b74c5fbfa1bbc9da01149032b36b6a5 Mon Sep 17 00:00:00 2001 From: Sam Dubey Date: Wed, 2 Nov 2022 07:59:50 +0000 Subject: [PATCH 12/12] Revert "Add a way to stash/unstash transient taskbar." This reverts commit 6163e2d39fd3fed44ec5e58df3bfd0dc76f6605b. Reason for revert: Part of Platinum+DM rotation for testing as likely culprit for breaking launcher tests on tablet. Won't be commited until proven otherwise. Bug: 256988243 Bug: 256987492 Change-Id: I21b3561f489e17c48131d2223a7d90267968232f --- quickstep/res/values/dimens.xml | 1 - .../taskbar/TaskbarActivityContext.java | 49 ++------ .../TaskbarAutohideSuspendController.java | 25 +--- .../launcher3/taskbar/TaskbarDragLayer.java | 8 -- .../taskbar/TaskbarDragLayerController.java | 17 +-- .../taskbar/TaskbarStashController.java | 109 +++--------------- .../taskbar/TaskbarUIController.java | 10 -- .../launcher3/taskbar/TaskbarView.java | 15 +-- .../taskbar/TaskbarViewController.java | 80 +------------ .../TaskbarStashInputConsumer.java | 89 +++----------- 10 files changed, 44 insertions(+), 359 deletions(-) diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index 32250787b3..c0765ee111 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -292,7 +292,6 @@ 150dp 225dp 300dp - 40dp 24dp diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index bf5740dcac..593605f9fb 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -24,8 +24,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; import static com.android.launcher3.AbstractFloatingView.TYPE_ALL; import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN; -import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_DRAGGING; -import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_FULLSCREEN; import static com.android.launcher3.taskbar.TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW; import static com.android.launcher3.testing.shared.ResourceUtils.getBoolByName; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED; @@ -77,7 +75,6 @@ import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.popup.PopupDataProvider; -import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.AutohideSuspendFlag; import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController; import com.android.launcher3.taskbar.overlay.TaskbarOverlayController; import com.android.launcher3.testing.TestLogging; @@ -306,9 +303,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { type, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_SLIPPERY - | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH - | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, + | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, PixelFormat.TRANSLUCENT); windowLayoutParams.setTitle(WINDOW_TITLE); windowLayoutParams.packageName = getPackageName(); @@ -472,7 +467,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { @Override public void onDragEnd() { - onDragEndOrViewRemoved(); + maybeSetTaskbarWindowNotFullscreen(); } @Override @@ -576,34 +571,25 @@ public class TaskbarActivityContext extends BaseTaskbarContext { .updateValue(darkIntensity); } - /** - * Called to update a {@link AutohideSuspendFlag} with a new value. - */ - public void setAutohideSuspendFlag(@AutohideSuspendFlag int flag, boolean newValue) { - mControllers.taskbarAutohideSuspendController.updateFlag(flag, newValue); - } - /** * Updates the TaskbarContainer to MATCH_PARENT vs original Taskbar size. */ public void setTaskbarWindowFullscreen(boolean fullscreen) { - setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_FULLSCREEN, fullscreen); + mControllers.taskbarAutohideSuspendController.updateFlag( + TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_FULLSCREEN, fullscreen); mIsFullscreen = fullscreen; setTaskbarWindowHeight(fullscreen ? MATCH_PARENT : mLastRequestedNonFullscreenHeight); } /** - * Called when drag ends or when a view is removed from the DragLayer. + * Reverts Taskbar window to its original size, if all floating views are closed and there is + * no system drag operation in progress. */ - void onDragEndOrViewRemoved() { - boolean isDragInProgress = mControllers.taskbarDragController.isSystemDragInProgress(); - - if (!isDragInProgress && !AbstractFloatingView.hasOpenView(this, TYPE_ALL)) { - // Reverts Taskbar window to its original size + void maybeSetTaskbarWindowNotFullscreen() { + if (AbstractFloatingView.getAnyView(this, TYPE_ALL) == null + && !mControllers.taskbarDragController.isSystemDragInProgress()) { setTaskbarWindowFullscreen(false); } - - setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_DRAGGING, isDragInProgress); } public boolean isTaskbarWindowFullscreen() { @@ -717,7 +703,6 @@ public class TaskbarActivityContext extends BaseTaskbarContext { Task task = (Task) tag; ActivityManagerWrapper.getInstance().startActivityFromRecents(task.key, ActivityOptions.makeBasic()); - mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true); } else if (tag instanceof FolderInfo) { FolderIcon folderIcon = (FolderIcon) view; Folder folder = folderIcon.getFolder(); @@ -777,7 +762,6 @@ public class TaskbarActivityContext extends BaseTaskbarContext { } mControllers.uiController.onTaskbarIconLaunched(info); - mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true); } catch (NullPointerException | ActivityNotFoundException | SecurityException e) { Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT) .show(); @@ -787,7 +771,6 @@ public class TaskbarActivityContext extends BaseTaskbarContext { } else if (tag instanceof AppInfo) { startItemInfoActivity((AppInfo) tag); mControllers.uiController.onTaskbarIconLaunched((AppInfo) tag); - mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true); } else { Log.e(TAG, "Unknown type clicked: " + tag); } @@ -822,20 +805,6 @@ public class TaskbarActivityContext extends BaseTaskbarContext { return mControllers.taskbarStashController.onLongPressToUnstashTaskbar(); } - /** - * Called when we want to unstash taskbar when user performs swipes up gesture. - */ - public void onSwipeToUnstashTaskbar() { - mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(false); - } - - /** - * Called when a transient Autohide flag suspend status changes. - */ - public void onTransientAutohideSuspendFlagChanged(boolean isSuspended) { - mControllers.taskbarStashController.updateTaskbarTimeout(isSuspended); - } - /** * Called when we detect a motion down or up/cancel in the nav region while stashed. * @param animateForward Whether to animate towards the unstashed hint state or back to stashed. diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java index 4350e9c280..3cf9c997c9 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java @@ -33,28 +33,21 @@ import java.util.StringJoiner; public class TaskbarAutohideSuspendController implements TaskbarControllers.LoggableTaskbarController { - // Taskbar window is fullscreen. public static final int FLAG_AUTOHIDE_SUSPEND_FULLSCREEN = 1 << 0; - // User is dragging item. public static final int FLAG_AUTOHIDE_SUSPEND_DRAGGING = 1 << 1; - // User has touched down but has not lifted finger. - public static final int FLAG_AUTOHIDE_SUSPEND_TOUCHING = 1 << 2; @IntDef(flag = true, value = { FLAG_AUTOHIDE_SUSPEND_FULLSCREEN, FLAG_AUTOHIDE_SUSPEND_DRAGGING, - FLAG_AUTOHIDE_SUSPEND_TOUCHING, }) @Retention(RetentionPolicy.SOURCE) public @interface AutohideSuspendFlag {} - private final TaskbarActivityContext mActivity; private final SystemUiProxy mSystemUiProxy; private @AutohideSuspendFlag int mAutohideSuspendFlags = 0; public TaskbarAutohideSuspendController(TaskbarActivityContext activity) { - mActivity = activity; mSystemUiProxy = SystemUiProxy.INSTANCE.get(activity); } @@ -66,27 +59,12 @@ public class TaskbarAutohideSuspendController implements * Adds or removes the given flag, then notifies system UI proxy whether to suspend auto-hide. */ public void updateFlag(@AutohideSuspendFlag int flag, boolean enabled) { - int flagsBefore = mAutohideSuspendFlags; if (enabled) { mAutohideSuspendFlags |= flag; } else { mAutohideSuspendFlags &= ~flag; } - if (flagsBefore == mAutohideSuspendFlags) { - // Nothing has changed, no need to notify. - return; - } - - boolean isSuspended = isSuspended(); - mSystemUiProxy.notifyTaskbarAutohideSuspend(isSuspended); - mActivity.onTransientAutohideSuspendFlagChanged(isSuspended); - } - - /** - * Returns true iff taskbar autohide is currently suspended. - */ - public boolean isSuspended() { - return mAutohideSuspendFlags != 0; + mSystemUiProxy.notifyTaskbarAutohideSuspend(mAutohideSuspendFlags != 0); } @Override @@ -101,7 +79,6 @@ public class TaskbarAutohideSuspendController implements appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_FULLSCREEN, "FLAG_AUTOHIDE_SUSPEND_FULLSCREEN"); appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_DRAGGING, "FLAG_AUTOHIDE_SUSPEND_DRAGGING"); - appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_TOUCHING, "FLAG_AUTOHIDE_SUSPEND_TOUCHING"); return str.toString(); } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java index 7c9a13c5dc..7e75779c62 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java @@ -115,14 +115,6 @@ public class TaskbarDragLayer extends BaseDragLayer { return true; } - @Override - public boolean onTouchEvent(MotionEvent ev) { - if (mControllerCallbacks != null && ev.getAction() == MotionEvent.ACTION_OUTSIDE) { - mControllerCallbacks.onActionOutsideEvent(); - } - return super.onTouchEvent(ev); - } - @Override public void onViewRemoved(View child) { super.onViewRemoved(child); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java index 13ecf81a7d..353f1e03cb 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java @@ -23,7 +23,6 @@ import android.view.ViewTreeObserver; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.util.DimensionUtils; -import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.TouchController; import com.android.quickstep.AnimatedFloat; @@ -166,25 +165,11 @@ public class TaskbarDragLayerController implements TaskbarControllers.LoggableTa mControllers.taskbarInsetsController.updateInsetsTouchability(insetsInfo); } - /** - * Called whenever TaskbarDragLayer receives an ACTION_OUTSIDE event. - */ - public void onActionOutsideEvent() { - if (!DisplayController.isTransientTaskbar(mActivity)) { - return; - } - if (mControllers.taskbarStashController.isStashed()) { - return; - } - - mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true); - } - /** * Called when a child is removed from TaskbarDragLayer. */ public void onDragLayerViewRemoved() { - mActivity.onDragEndOrViewRemoved(); + mActivity.maybeSetTaskbarWindowNotFullscreen(); } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index afd659fc6e..64eb99e7d1 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -39,13 +39,11 @@ import android.view.ViewConfiguration; import androidx.annotation.NonNull; import com.android.internal.jank.InteractionJankMonitor; -import com.android.launcher3.Alarm; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorListeners; import com.android.launcher3.testing.shared.TestProtocol; -import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.MultiPropertyFactory.MultiProperty; import com.android.quickstep.AnimatedFloat; import com.android.quickstep.SystemUiProxy; @@ -72,7 +70,6 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba public static final int FLAG_STASHED_IN_TASKBAR_ALL_APPS = 1 << 7; // All apps is visible. public static final int FLAG_IN_SETUP = 1 << 8; // In the Setup Wizard public static final int FLAG_STASHED_SMALL_SCREEN = 1 << 9; // phone screen gesture nav, stashed - public static final int FLAG_STASHED_IN_APP_AUTO = 1 << 10; // Autohide (transient taskbar). // If any of these flags are enabled, isInApp should return true. private static final int FLAGS_IN_APP = FLAG_IN_APP | FLAG_IN_SETUP; @@ -81,7 +78,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba private static final int FLAGS_STASHED_IN_APP = FLAG_STASHED_IN_APP_MANUAL | FLAG_STASHED_IN_APP_PINNED | FLAG_STASHED_IN_APP_EMPTY | FLAG_STASHED_IN_APP_SETUP | FLAG_STASHED_IN_APP_IME | FLAG_STASHED_IN_TASKBAR_ALL_APPS - | FLAG_STASHED_SMALL_SCREEN | FLAG_STASHED_IN_APP_AUTO; + | FLAG_STASHED_SMALL_SCREEN; private static final int FLAGS_STASHED_IN_APP_IGNORING_IME = FLAGS_STASHED_IN_APP & ~FLAG_STASHED_IN_APP_IME; @@ -135,9 +132,6 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba */ private static final boolean DEFAULT_STASHED_PREF = false; - // Auto stashes when user has not interacted with the Taskbar after X ms. - private static final long NO_TOUCH_TIMEOUT_TO_STASH_MS = 5000; - private final TaskbarActivityContext mActivity; private final SharedPreferences mPrefs; private final int mStashedHeight; @@ -168,8 +162,6 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba private boolean mEnableManualStashingDuringTests = false; - private final Alarm mTimeoutAlarm = new Alarm(); - // Evaluate whether the handle should be stashed private final StatePropertyHolder mStatePropertyHolder = new StatePropertyHolder( flags -> { @@ -218,16 +210,13 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba StashedHandleViewController.ALPHA_INDEX_STASHED); mTaskbarStashedHandleHintScale = stashedHandleController.getStashedHandleHintScale(); - boolean isTransientTaskbar = DisplayController.isTransientTaskbar(mActivity); // We use supportsVisualStashing() here instead of supportsManualStashing() because we want // it to work properly for tests that recreate taskbar. This check is here just to ensure // that taskbar unstashes when going to 3 button mode (supportsVisualStashing() false). boolean isManuallyStashedInApp = supportsVisualStashing() - && mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF) - && !isTransientTaskbar; + && mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF); boolean isInSetup = !mActivity.isUserSetupComplete() || setupUIVisible; updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp); - updateStateForFlag(FLAG_STASHED_IN_APP_AUTO, isTransientTaskbar); updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, isInSetup); updateStateForFlag(FLAG_IN_SETUP, isInSetup); updateStateForFlag(FLAG_STASHED_SMALL_SCREEN, isPhoneMode() @@ -254,8 +243,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba protected boolean supportsManualStashing() { return supportsVisualStashing() && isInApp() - && (!Utilities.IS_RUNNING_IN_TEST_HARNESS || mEnableManualStashingDuringTests) - && !DisplayController.isTransientTaskbar(mActivity); + && (!Utilities.IS_RUNNING_IN_TEST_HARNESS || mEnableManualStashingDuringTests); } /** @@ -388,20 +376,6 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba return mStashedHeight; } - /** - * Stash or unstashes the transient taskbar. - */ - public void updateAndAnimateTransientTaskbar(boolean stash) { - if (!DisplayController.isTransientTaskbar(mActivity)) { - return; - } - - if (hasAnyFlag(FLAG_STASHED_IN_APP_AUTO) != stash) { - updateStateForFlag(FLAG_STASHED_IN_APP_AUTO, stash); - applyState(); - } - } - /** * Should be called when long pressing the nav region when taskbar is present. * @return Whether taskbar was stashed and now is unstashed. @@ -575,17 +549,11 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba public void onAnimationStart(Animator animation) { mIsStashed = isStashed; onIsStashedChanged(mIsStashed); - - cancelTimeoutIfExists(); } @Override public void onAnimationEnd(Animator animation) { mAnimator = null; - - if (!mIsStashed) { - tryStartTaskbarTimeout(); - } } }); } @@ -811,54 +779,6 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba mControllers.rotationButtonController.onTaskbarStateChange(visible, stashed); } - /** - * Cancels a timeout if any exists. - */ - public void cancelTimeoutIfExists() { - if (mTimeoutAlarm.alarmPending()) { - mTimeoutAlarm.cancelAlarm(); - } - } - - /** - * Updates the status of the taskbar timeout. - * @param isAutohideSuspended If true, cancels any existing timeout - * If false, attempts to re/start the timeout - */ - public void updateTaskbarTimeout(boolean isAutohideSuspended) { - if (!DisplayController.isTransientTaskbar(mActivity)) { - return; - } - if (isAutohideSuspended) { - cancelTimeoutIfExists(); - } else { - tryStartTaskbarTimeout(); - } - } - - /** - * Attempts to start timer to auto hide the taskbar based on time. - */ - public void tryStartTaskbarTimeout() { - if (!DisplayController.isTransientTaskbar(mActivity)) { - return; - } - if (mIsStashed) { - return; - } - cancelTimeoutIfExists(); - - mTimeoutAlarm.setOnAlarmListener(this::onTaskbarTimeout); - mTimeoutAlarm.setAlarm(NO_TOUCH_TIMEOUT_TO_STASH_MS); - } - - private void onTaskbarTimeout(Alarm alarm) { - if (mControllers.taskbarAutohideSuspendController.isSuspended()) { - return; - } - updateAndAnimateTransientTaskbar(true); - } - @Override public void dumpLogs(String prefix, PrintWriter pw) { pw.println(prefix + "TaskbarStashController:"); @@ -874,18 +794,17 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba } private static String getStateString(int flags) { - StringJoiner sj = new StringJoiner("|"); - appendFlag(sj, flags, FLAGS_IN_APP, "FLAG_IN_APP"); - appendFlag(sj, flags, FLAG_STASHED_IN_APP_MANUAL, "FLAG_STASHED_IN_APP_MANUAL"); - appendFlag(sj, flags, FLAG_STASHED_IN_APP_PINNED, "FLAG_STASHED_IN_APP_PINNED"); - appendFlag(sj, flags, FLAG_STASHED_IN_APP_EMPTY, "FLAG_STASHED_IN_APP_EMPTY"); - appendFlag(sj, flags, FLAG_STASHED_IN_APP_SETUP, "FLAG_STASHED_IN_APP_SETUP"); - appendFlag(sj, flags, FLAG_STASHED_IN_APP_IME, "FLAG_STASHED_IN_APP_IME"); - appendFlag(sj, flags, FLAG_IN_STASHED_LAUNCHER_STATE, "FLAG_IN_STASHED_LAUNCHER_STATE"); - appendFlag(sj, flags, FLAG_STASHED_IN_TASKBAR_ALL_APPS, "FLAG_STASHED_IN_TASKBAR_ALL_APPS"); - appendFlag(sj, flags, FLAG_IN_SETUP, "FLAG_IN_SETUP"); - appendFlag(sj, flags, FLAG_STASHED_IN_APP_AUTO, "FLAG_STASHED_IN_APP_AUTO"); - return sj.toString(); + StringJoiner str = new StringJoiner("|"); + appendFlag(str, flags, FLAGS_IN_APP, "FLAG_IN_APP"); + appendFlag(str, flags, FLAG_STASHED_IN_APP_MANUAL, "FLAG_STASHED_IN_APP_MANUAL"); + appendFlag(str, flags, FLAG_STASHED_IN_APP_PINNED, "FLAG_STASHED_IN_APP_PINNED"); + appendFlag(str, flags, FLAG_STASHED_IN_APP_EMPTY, "FLAG_STASHED_IN_APP_EMPTY"); + appendFlag(str, flags, FLAG_STASHED_IN_APP_SETUP, "FLAG_STASHED_IN_APP_SETUP"); + appendFlag(str, flags, FLAG_STASHED_IN_APP_IME, "FLAG_STASHED_IN_APP_IME"); + appendFlag(str, flags, FLAG_IN_STASHED_LAUNCHER_STATE, "FLAG_IN_STASHED_LAUNCHER_STATE"); + appendFlag(str, flags, FLAG_STASHED_IN_TASKBAR_ALL_APPS, "FLAG_STASHED_IN_APP_ALL_APPS"); + appendFlag(str, flags, FLAG_IN_SETUP, "FLAG_IN_SETUP"); + return str.toString(); } private class StatePropertyHolder { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java index 2294306ac3..9ec8cfeffa 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java @@ -15,7 +15,6 @@ */ package com.android.launcher3.taskbar; -import android.view.MotionEvent; import android.view.View; import androidx.annotation.CallSuper; @@ -105,15 +104,6 @@ public class TaskbarUIController { return mControllers.taskbarStashController.isStashed(); } - /* - * @param ev MotionEvent in screen coordinates. - * @return Whether any Taskbar item could handle the given MotionEvent if given the chance. - */ - public boolean isEventOverAnyTaskbarItem(MotionEvent ev) { - return mControllers.taskbarViewController.isEventOverAnyItem(ev) - || mControllers.navbarButtonsViewController.isEventOverAnyItem(ev); - } - @CallSuper protected void dumpLogs(String prefix, PrintWriter pw) { pw.println(String.format( diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java index bdcc4295fe..c754a59a06 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java @@ -380,23 +380,13 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar return super.dispatchTouchEvent(ev); } - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - mControllerCallbacks.onInterceptTouchEvent(ev); - return super.onInterceptTouchEvent(ev); - } - @Override public boolean onTouchEvent(MotionEvent event) { if (!mTouchEnabled) { return true; } - if (mIconLayoutBounds.left <= event.getX() - && event.getX() <= mIconLayoutBounds.right - && !DisplayController.isTransientTaskbar(mActivityContext)) { - // Don't allow long pressing between icons, or above/below them - // unless its transient taskbar. - mControllerCallbacks.clearTouchInProgress(); + if (mIconLayoutBounds.left <= event.getX() && event.getX() <= mIconLayoutBounds.right) { + // Don't allow long pressing between icons, or above/below them. return true; } if (mControllerCallbacks.onTouchEvent(event)) { @@ -413,7 +403,6 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar public void setTouchesEnabled(boolean touchEnabled) { this.mTouchEnabled = touchEnabled; - mControllerCallbacks.clearTouchInProgress(); } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index 2bc609eaf3..f0277a4d08 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -22,8 +22,6 @@ import static com.android.launcher3.Utilities.squaredHypot; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP; import static com.android.launcher3.taskbar.TaskbarManager.isPhoneMode; -import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_NEGATIVE; -import static com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL; import static com.android.quickstep.AnimatedFloat.VALUE; import android.annotation.NonNull; @@ -34,7 +32,6 @@ import android.util.Log; import android.view.MotionEvent; import android.view.View; -import androidx.annotation.Nullable; import androidx.core.graphics.ColorUtils; import androidx.core.view.OneShotPreDrawListener; @@ -51,7 +48,6 @@ import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.icons.ThemedIconDrawable; import com.android.launcher3.model.data.ItemInfo; -import com.android.launcher3.touch.SingleAxisSwipeDetector; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.HorizontalInsettableView; import com.android.launcher3.util.ItemInfoMatcher; @@ -101,9 +97,6 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar private final TaskbarModelCallbacks mModelCallbacks; - // Captures swipe down action to close transient taskbar. - protected @Nullable SingleAxisSwipeDetector mSwipeDownDetector; - // Initialized in init. private TaskbarControllers mControllers; @@ -126,31 +119,6 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar mTaskbarBottomMargin = DisplayController.isTransientTaskbar(activity) ? activity.getResources().getDimensionPixelSize(R.dimen.transient_taskbar_margin) : 0; - - if (DisplayController.isTransientTaskbar(mActivity)) { - mSwipeDownDetector = new SingleAxisSwipeDetector(activity, - new SingleAxisSwipeDetector.Listener() { - private float mLastDisplacement; - - @Override - public boolean onDrag(float displacement) { - mLastDisplacement = displacement; - return false; - } - - @Override - public void onDragEnd(float velocity) { - if (mLastDisplacement > 0) { - mControllers.taskbarStashController - .updateAndAnimateTransientTaskbar(true); - } - } - - @Override - public void onDragStart(boolean start, float startDisplacement) {} - }, VERTICAL); - mSwipeDownDetector.setDetectableScrollConditions(DIRECTION_NEGATIVE, false); - } } public void init(TaskbarControllers controllers) { @@ -468,8 +436,6 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar private float mDownX, mDownY; private boolean mCanceledStashHint; - private boolean mTouchInProgress; - public View.OnClickListener getIconOnClickListener() { return mActivity.getItemOnClickListener(); } @@ -497,76 +463,38 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar .updateAndAnimateIsManuallyStashedInApp(true); } - /** - * Simply listens to all intercept touch events passed to TaskbarView. - */ - public void onInterceptTouchEvent(MotionEvent ev) { - if (ev.getAction() == MotionEvent.ACTION_DOWN) { - mTouchInProgress = true; - } - - if (mTouchInProgress && mSwipeDownDetector != null) { - mSwipeDownDetector.onTouchEvent(ev); - } - - if (ev.getAction() == MotionEvent.ACTION_UP - || ev.getAction() == MotionEvent.ACTION_CANCEL) { - clearTouchInProgress(); - } - } - /** * Get the first chance to handle TaskbarView#onTouchEvent, and return whether we want to * consume the touch so TaskbarView treats it as an ACTION_CANCEL. */ public boolean onTouchEvent(MotionEvent motionEvent) { - boolean shouldConsumeTouch = false; - boolean clearTouchInProgress = false; - final float x = motionEvent.getRawX(); final float y = motionEvent.getRawY(); switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: - mTouchInProgress = true; mDownX = x; mDownY = y; mControllers.taskbarStashController.startStashHint(/* animateForward = */ true); mCanceledStashHint = false; break; case MotionEvent.ACTION_MOVE: - if (mTouchInProgress - && !mCanceledStashHint + if (!mCanceledStashHint && squaredHypot(mDownX - x, mDownY - y) > mSquaredTouchSlop) { mControllers.taskbarStashController.startStashHint( /* animateForward= */ false); mCanceledStashHint = true; - shouldConsumeTouch = true; + return true; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: - if (mTouchInProgress && !mCanceledStashHint) { + if (!mCanceledStashHint) { mControllers.taskbarStashController.startStashHint( /* animateForward= */ false); } - clearTouchInProgress = true; break; } - - if (mTouchInProgress && mSwipeDownDetector != null) { - mSwipeDownDetector.onTouchEvent(motionEvent); - } - if (clearTouchInProgress) { - clearTouchInProgress(); - } - return shouldConsumeTouch; - } - - /** - * Ensures that we do not pass any more touch events to the SwipeDetector. - */ - public void clearTouchInProgress() { - mTouchInProgress = false; + return false; } } diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java index 1430492401..3785de4ecd 100644 --- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java +++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java @@ -15,14 +15,9 @@ */ package com.android.quickstep.inputconsumers; -import static android.view.MotionEvent.INVALID_POINTER_ID; - import static com.android.launcher3.Utilities.squaredHypot; -import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_TOUCHING; import android.content.Context; -import android.content.res.Resources; -import android.graphics.PointF; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; @@ -30,7 +25,6 @@ import android.view.MotionEvent; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.taskbar.TaskbarActivityContext; -import com.android.launcher3.util.DisplayController; import com.android.quickstep.InputConsumer; import com.android.systemui.shared.system.InputMonitorCompat; @@ -43,32 +37,20 @@ public class TaskbarStashInputConsumer extends DelegateInputConsumer { private final GestureDetector mLongPressDetector; private final float mSquaredTouchSlop; - private float mLongPressDownX, mLongPressDownY; + + private float mDownX, mDownY; private boolean mCanceledUnstashHint; private final float mUnstashArea; private final float mScreenWidth; - private final int mTaskbarThreshold; - private boolean mHasPassedTaskbarThreshold; - - private final PointF mDownPos = new PointF(); - private final PointF mLastPos = new PointF(); - private int mActivePointerId = INVALID_POINTER_ID; - - private final boolean mIsTransientTaskbar; - public TaskbarStashInputConsumer(Context context, InputConsumer delegate, InputMonitorCompat inputMonitor, TaskbarActivityContext taskbarActivityContext) { super(delegate, inputMonitor); mTaskbarActivityContext = taskbarActivityContext; mSquaredTouchSlop = Utilities.squaredTouchSlop(context); mScreenWidth = taskbarActivityContext.getDeviceProfile().widthPx; - - Resources res = context.getResources(); - mUnstashArea = res.getDimensionPixelSize(R.dimen.taskbar_unstash_input_area); - mTaskbarThreshold = res.getDimensionPixelSize(R.dimen.taskbar_nav_threshold); - - mIsTransientTaskbar = DisplayController.isTransientTaskbar(context); + mUnstashArea = context.getResources() + .getDimensionPixelSize(R.dimen.taskbar_unstash_input_area); mLongPressDetector = new GestureDetector(context, new SimpleOnGestureListener() { @Override @@ -94,71 +76,28 @@ public class TaskbarStashInputConsumer extends DelegateInputConsumer { final float y = ev.getRawY(); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: - mActivePointerId = ev.getPointerId(0); - mDownPos.set(ev.getX(), ev.getY()); - mLastPos.set(mDownPos); - - mHasPassedTaskbarThreshold = false; - mTaskbarActivityContext.setAutohideSuspendFlag( - FLAG_AUTOHIDE_SUSPEND_TOUCHING, true); if (isInArea(x)) { - if (!mIsTransientTaskbar) { - mLongPressDownX = x; - mLongPressDownY = y; - mTaskbarActivityContext.startTaskbarUnstashHint( - /* animateForward = */ true); - mCanceledUnstashHint = false; - } - } - break; - case MotionEvent.ACTION_POINTER_UP: - int ptrIdx = ev.getActionIndex(); - int ptrId = ev.getPointerId(ptrIdx); - if (ptrId == mActivePointerId) { - final int newPointerIdx = ptrIdx == 0 ? 1 : 0; - mDownPos.set( - ev.getX(newPointerIdx) - (mLastPos.x - mDownPos.x), - ev.getY(newPointerIdx) - (mLastPos.y - mDownPos.y)); - mLastPos.set(ev.getX(newPointerIdx), ev.getY(newPointerIdx)); - mActivePointerId = ev.getPointerId(newPointerIdx); + mDownX = x; + mDownY = y; + mTaskbarActivityContext.startTaskbarUnstashHint( + /* animateForward = */ true); + mCanceledUnstashHint = false; } break; case MotionEvent.ACTION_MOVE: - if (!mIsTransientTaskbar - && !mCanceledUnstashHint - && squaredHypot(mLongPressDownX - x, mLongPressDownY - y) - > mSquaredTouchSlop) { + if (!mCanceledUnstashHint + && squaredHypot(mDownX - x, mDownY - y) > mSquaredTouchSlop) { mTaskbarActivityContext.startTaskbarUnstashHint( /* animateForward = */ false); mCanceledUnstashHint = true; } - - int pointerIndex = ev.findPointerIndex(mActivePointerId); - if (pointerIndex == INVALID_POINTER_ID) { - break; - } - mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex)); - float displacementY = mLastPos.y - mDownPos.y; - float verticalDist = Math.abs(displacementY); - boolean passedTaskbarThreshold = verticalDist >= mTaskbarThreshold; - - if (!mHasPassedTaskbarThreshold - && passedTaskbarThreshold - && mIsTransientTaskbar) { - mHasPassedTaskbarThreshold = true; - - mTaskbarActivityContext.onSwipeToUnstashTaskbar(); - } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: - if (!mIsTransientTaskbar && !mCanceledUnstashHint) { + if (!mCanceledUnstashHint) { mTaskbarActivityContext.startTaskbarUnstashHint( /* animateForward = */ false); } - mTaskbarActivityContext.setAutohideSuspendFlag( - FLAG_AUTOHIDE_SUSPEND_TOUCHING, false); - mHasPassedTaskbarThreshold = false; break; } } @@ -172,9 +111,7 @@ public class TaskbarStashInputConsumer extends DelegateInputConsumer { } private void onLongPressDetected(MotionEvent motionEvent) { - if (mTaskbarActivityContext != null - && isInArea(motionEvent.getRawX()) - && !mIsTransientTaskbar) { + if (mTaskbarActivityContext != null && isInArea(motionEvent.getRawX())) { boolean taskBarPressed = mTaskbarActivityContext.onLongPressToUnstashTaskbar(); if (taskBarPressed) { setActive(motionEvent);