diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index bb12356b8c..f1244ff5db 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -888,7 +888,8 @@ public class TouchInteractionService extends Service { .append(SUBSTRING_PREFIX) .append("TaskbarActivityContext != null, " + "using TaskbarUnstashInputConsumer"); - base = new TaskbarUnstashInputConsumer(this, base, mInputMonitorCompat, tac); + base = new TaskbarUnstashInputConsumer(this, base, mInputMonitorCompat, tac, + mOverviewCommandHelper); } } else if (canStartSystemGesture && FeatureFlags.ENABLE_LONG_PRESS_NAV_HANDLE.get()) { base = new NavHandleLongPressInputConsumer(this, base, mInputMonitorCompat); diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java index e9a0761caf..172c9e9d52 100644 --- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java +++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java @@ -15,6 +15,7 @@ */ package com.android.quickstep.inputconsumers; +import static android.view.MotionEvent.ACTION_BUTTON_RELEASE; import static android.view.MotionEvent.INVALID_POINTER_ID; import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent; @@ -41,6 +42,7 @@ import com.android.launcher3.taskbar.bubbles.BubbleControllers; import com.android.launcher3.touch.OverScroll; import com.android.launcher3.util.DisplayController; import com.android.quickstep.InputConsumer; +import com.android.quickstep.OverviewCommandHelper; import com.android.systemui.shared.system.InputMonitorCompat; /** @@ -51,6 +53,7 @@ import com.android.systemui.shared.system.InputMonitorCompat; public class TaskbarUnstashInputConsumer extends DelegateInputConsumer { private final TaskbarActivityContext mTaskbarActivityContext; + private final OverviewCommandHelper mOverviewCommandHelper; private final GestureDetector mLongPressDetector; private final float mSquaredTouchSlop; @@ -80,9 +83,11 @@ public class TaskbarUnstashInputConsumer extends DelegateInputConsumer { private final @Nullable TransitionCallback mTransitionCallback; public TaskbarUnstashInputConsumer(Context context, InputConsumer delegate, - InputMonitorCompat inputMonitor, TaskbarActivityContext taskbarActivityContext) { + InputMonitorCompat inputMonitor, TaskbarActivityContext taskbarActivityContext, + OverviewCommandHelper overviewCommandHelper) { super(delegate, inputMonitor); mTaskbarActivityContext = taskbarActivityContext; + mOverviewCommandHelper = overviewCommandHelper; // TODO(b/270395798): remove this when cleaning up old Persistent Taskbar code. mSquaredTouchSlop = Utilities.squaredTouchSlop(context); mScreenWidth = taskbarActivityContext.getDeviceProfile().widthPx; @@ -123,7 +128,11 @@ public class TaskbarUnstashInputConsumer extends DelegateInputConsumer { public void onMotionEvent(MotionEvent ev) { mLongPressDetector.onTouchEvent(ev); if (mState != STATE_ACTIVE) { - mDelegate.onMotionEvent(ev); + boolean isStashedTaskbarHovered = + isStashedTaskbarHovered((int) ev.getX(), (int) ev.getY()); + if (!isStashedTaskbarHovered) { + mDelegate.onMotionEvent(ev); + } // Only show the transient task bar if the touch events are on the screen. if (mTaskbarActivityContext != null && !isTrackpadMotionEvent(ev)) { @@ -218,6 +227,11 @@ public class TaskbarUnstashInputConsumer extends DelegateInputConsumer { mHasPassedTaskbarNavThreshold = false; mIsInBubbleBarArea = false; break; + case ACTION_BUTTON_RELEASE: + if (isStashedTaskbarHovered) { + mOverviewCommandHelper.addCommand(OverviewCommandHelper.TYPE_HOME); + } + break; } } } @@ -274,19 +288,17 @@ public class TaskbarUnstashInputConsumer extends DelegateInputConsumer { private void updateHoveredTaskbarState(int x, int y) { DeviceProfile dp = mTaskbarActivityContext.getDeviceProfile(); - mStashedTaskbarHandleBounds.set( + mBottomEdgeBounds.set( (dp.widthPx - (int) mUnstashArea) / 2, - dp.heightPx - dp.stashedTaskbarHeight, + dp.heightPx - mStashedTaskbarBottomEdge, (int) (((dp.widthPx - mUnstashArea) / 2) + mUnstashArea), dp.heightPx); - mBottomEdgeBounds.set(mStashedTaskbarHandleBounds); - mBottomEdgeBounds.top = dp.heightPx - mStashedTaskbarBottomEdge; if (mBottomEdgeBounds.contains(x, y)) { // If hovering stashed taskbar and then hover screen bottom edge, unstash it. mTaskbarActivityContext.onSwipeToUnstashTaskbar(); mIsStashedTaskbarHovered = false; - } else if (!mStashedTaskbarHandleBounds.contains(x, y)) { + } else if (!isStashedTaskbarHovered(x, y)) { // If exit hovering stashed taskbar, remove hint. startStashedTaskbarHover(/* isHovered = */ false); } @@ -294,18 +306,13 @@ public class TaskbarUnstashInputConsumer extends DelegateInputConsumer { private void updateUnhoveredTaskbarState(int x, int y) { DeviceProfile dp = mTaskbarActivityContext.getDeviceProfile(); - mStashedTaskbarHandleBounds.set( - (dp.widthPx - (int) mUnstashArea) / 2, - dp.heightPx - dp.stashedTaskbarHeight, - (int) (((dp.widthPx - mUnstashArea) / 2) + mUnstashArea), - dp.heightPx); mBottomEdgeBounds.set( 0, dp.heightPx - mBottomScreenEdge, dp.widthPx, dp.heightPx); - if (mStashedTaskbarHandleBounds.contains(x, y)) { + if (isStashedTaskbarHovered(x, y)) { // If enter hovering stashed taskbar, start hint. startStashedTaskbarHover(/* isHovered = */ true); } else if (mBottomEdgeBounds.contains(x, y)) { @@ -318,4 +325,19 @@ public class TaskbarUnstashInputConsumer extends DelegateInputConsumer { mTaskbarActivityContext.startTaskbarUnstashHint(isHovered, /* forceUnstash = */ true); mIsStashedTaskbarHovered = isHovered; } + + private boolean isStashedTaskbarHovered(int x, int y) { + if (!mTaskbarActivityContext.isTaskbarStashed() + || mTaskbarActivityContext.isTaskbarAllAppsOpen() + || !ENABLE_CURSOR_HOVER_STATES.get()) { + return false; + } + DeviceProfile dp = mTaskbarActivityContext.getDeviceProfile(); + mStashedTaskbarHandleBounds.set( + (dp.widthPx - (int) mUnstashArea) / 2, + dp.heightPx - dp.stashedTaskbarHeight, + (int) (((dp.widthPx - mUnstashArea) / 2) + mUnstashArea), + dp.heightPx); + return mStashedTaskbarHandleBounds.contains(x, y); + } } diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java index b58fe29a96..3869bf7642 100644 --- a/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java +++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java @@ -18,7 +18,6 @@ package com.android.quickstep; import static com.android.launcher3.config.FeatureFlags.ENABLE_CURSOR_HOVER_STATES; import static com.android.quickstep.TaskbarModeSwitchRule.Mode.TRANSIENT; - import androidx.test.filters.LargeTest; import androidx.test.runner.AndroidJUnit4; @@ -64,4 +63,15 @@ public class TaplTestsTransientTaskbar extends AbstractTaplTestsTaskbar { throw new RuntimeException(e); } } + + @Test + @TaskbarModeSwitch(mode = TRANSIENT) + public void testClickHoveredTaskbarToGoHome() { + try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) { + getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE); + mLauncher.getLaunchedAppState().clickStashedTaskbarToGoHome(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } } diff --git a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java index a59eff7318..9b4d273647 100644 --- a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java +++ b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java @@ -37,6 +37,7 @@ import androidx.test.uiautomator.By; import androidx.test.uiautomator.Condition; import androidx.test.uiautomator.UiDevice; +import com.android.launcher3.testing.shared.ResourceUtils; import com.android.launcher3.testing.shared.TestProtocol; /** @@ -50,6 +51,8 @@ public final class LaunchedAppState extends Background { // UNSTASHED_TASKBAR_HANDLE_HINT_SCALE value from TaskbarStashController. private static final float UNSTASHED_TASKBAR_HANDLE_HINT_SCALE = 1.1f; + private static final int STASHED_TASKBAR_BOTTOM_EDGE_DP = 1; + private final Condition mStashedTaskbarHintScaleCondition = device -> mLauncher.getTestInfo(REQUEST_STASHED_TASKBAR_SCALE).getFloat( TestProtocol.TEST_INFO_RESPONSE_FIELD) - UNSTASHED_TASKBAR_HANDLE_HINT_SCALE @@ -209,7 +212,7 @@ public final class LaunchedAppState extends Background { * *

This unstashing occurs when not actively hovering the taskbar. */ - public void hoverScreenBottomEdgeToUnstashTaskbar() { + public Taskbar hoverScreenBottomEdgeToUnstashTaskbar() { try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); LauncherInstrumentation.Closable c = mLauncher.addContextLayer( "cursor hover entering screen edge to unstash taskbar")) { @@ -226,13 +229,15 @@ public final class LaunchedAppState extends Background { mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_EXIT, new Point(taskbarUnstashArea.x, taskbarUnstashArea.y), null); + + return new Taskbar(mLauncher); } } /** * Emulate the cursor hovering the taskbar to get unstash hint, then hovering below to unstash. */ - public void hoverBelowHintedTaskbarToUnstash() { + public Taskbar hoverBelowHintedTaskbarToUnstash() { try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); LauncherInstrumentation.Closable c = mLauncher.addContextLayer( "cursor hover entering stashed taskbar")) { @@ -254,6 +259,7 @@ public final class LaunchedAppState extends Background { new Point(taskbarUnstashArea.x, taskbarUnstashArea.y), null); mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID); + return new Taskbar(mLauncher); } } } @@ -288,4 +294,45 @@ public final class LaunchedAppState extends Background { } } } + + /** + * Emulate the cursor clicking the stashed taskbar to go home. + */ + public Workspace clickStashedTaskbarToGoHome() { + try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); + LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "cursor hover entering stashed taskbar")) { + long downTime = SystemClock.uptimeMillis(); + int stashedTaskbarBottomEdge = ResourceUtils.pxFromDp(STASHED_TASKBAR_BOTTOM_EDGE_DP, + mLauncher.getResources().getDisplayMetrics()); + Point stashedTaskbarHintArea = new Point(mLauncher.getRealDisplaySize().x / 2, + mLauncher.getRealDisplaySize().y - stashedTaskbarBottomEdge - 1); + mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_ENTER, + new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y), null); + + mLauncher.getDevice().wait(mStashedTaskbarHintScaleCondition, + LauncherInstrumentation.WAIT_TIME_MS); + + try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer( + "cursor clicking stashed taskbar to go home")) { + mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_EXIT, + new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y), + null); + mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, + new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y), + LauncherInstrumentation.GestureScope.OUTSIDE_WITHOUT_PILFER); + mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_BUTTON_PRESS, + new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y), + null); + mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_BUTTON_RELEASE, + new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y), + null); + mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, + new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y), + LauncherInstrumentation.GestureScope.OUTSIDE_WITHOUT_PILFER); + + return mLauncher.getWorkspace(); + } + } + } } diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index 89f141f54a..3395bbf83c 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -110,6 +110,9 @@ public final class LauncherInstrumentation { static final Pattern EVENT_TOUCH_CANCEL_TIS = getTouchEventPatternTIS("ACTION_CANCEL"); static final Pattern EVENT_HOVER_ENTER_TIS = getTouchEventPatternTIS("ACTION_HOVER_ENTER"); static final Pattern EVENT_HOVER_EXIT_TIS = getTouchEventPatternTIS("ACTION_HOVER_EXIT"); + static final Pattern EVENT_BUTTON_PRESS_TIS = getTouchEventPatternTIS("ACTION_BUTTON_PRESS"); + static final Pattern EVENT_BUTTON_RELEASE_TIS = + getTouchEventPatternTIS("ACTION_BUTTON_RELEASE"); private static final Pattern EVENT_KEY_BACK_DOWN = getKeyEventPattern("ACTION_DOWN", "KEYCODE_BACK"); @@ -173,7 +176,7 @@ public final class LauncherInstrumentation { void close(); } - private static final String WORKSPACE_RES_ID = "workspace"; + static final String WORKSPACE_RES_ID = "workspace"; private static final String APPS_RES_ID = "apps_view"; private static final String OVERVIEW_RES_ID = "overview_panel"; private static final String WIDGETS_RES_ID = "primary_widgets_list_view"; @@ -1834,6 +1837,12 @@ public final class LauncherInstrumentation { } mPointerCount--; break; + case MotionEvent.ACTION_BUTTON_PRESS: + expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_BUTTON_PRESS_TIS); + break; + case MotionEvent.ACTION_BUTTON_RELEASE: + expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_BUTTON_RELEASE_TIS); + break; } final MotionEvent event = isTrackpadGesture @@ -1841,6 +1850,10 @@ public final class LauncherInstrumentation { downTime, currentTime, action, point.x, point.y, pointerCount, mTrackpadGestureType) : getMotionEvent(downTime, currentTime, action, point.x, point.y); + if (action == MotionEvent.ACTION_BUTTON_PRESS + || action == MotionEvent.ACTION_BUTTON_RELEASE) { + event.setActionButton(MotionEvent.BUTTON_PRIMARY); + } assertTrue("injectInputEvent failed", mInstrumentation.getUiAutomation().injectInputEvent(event, true, false)); event.recycle();