From 6ddfe9b179c7f2d7a60b0c9ec13f0fc712396d8d Mon Sep 17 00:00:00 2001 From: Toshiki Kikuchi Date: Thu, 29 Aug 2024 16:39:50 +0900 Subject: [PATCH] Allow to show pinned taskbar when Launcher is visible This CL allows freeform-first devices to lock the taskbar in a pinned state when Launcher is visible. Bug: 361419732 Flag: com.android.window.flags.enter_desktop_by_default_on_freeform_displays Test: DisplayControllerTest Test: manual Change-Id: Ic0d2740e33fee19c676d88aa2bcf370eb64366e8 --- .../taskbar/LauncherTaskbarUIController.java | 4 +++ .../taskbar/TaskbarInsetsController.kt | 6 +++- .../TaskbarLauncherStateController.java | 7 ++-- .../util/SystemWindowManagerProxy.java | 21 ++++++++++++ .../launcher3/util/DisplayController.java | 33 ++++++++++++++++++- .../util/window/WindowManagerProxy.java | 14 ++++++++ .../launcher3/util/DisplayControllerTest.kt | 19 +++++++++++ 7 files changed, 100 insertions(+), 4 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index 4d144ca311..1e197c00fa 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -50,6 +50,7 @@ import com.android.quickstep.util.GroupTask; import com.android.quickstep.util.TISBindHelper; import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags; +import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import java.io.PrintWriter; import java.util.Arrays; @@ -210,6 +211,9 @@ public class LauncherTaskbarUIController extends TaskbarUIController { */ @Override public void onLauncherVisibilityChanged(boolean isVisible) { + if (DesktopModeStatus.enterDesktopByDefaultOnFreeformDisplay(mLauncher)) { + DisplayController.handleInfoChangeForLauncherVisibilityChanged(mLauncher); + } onLauncherVisibilityChanged(isVisible, false /* fromInit */); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt index 221504dd64..685c109eec 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt @@ -147,7 +147,11 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas defaultTouchableRegion.addBoundsToRegion(bubbleBarViewController.bubbleBarBounds) } } - if (taskbarStashController.isInApp || taskbarStashController.isInOverview) { + if ( + taskbarStashController.isInApp || + taskbarStashController.isInOverview || + DisplayController.showLockedTaskbarOnHome(context) + ) { // only add the taskbar touch region if not on home val bottom = windowLayoutParams.height val top = bottom - taskbarTouchableHeight diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java index 6bf1ee6802..e301dc4a1f 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java @@ -53,6 +53,7 @@ import com.android.launcher3.anim.AnimatorListeners; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.uioverrides.QuickstepLauncher; +import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.MultiPropertyFactory.MultiProperty; import com.android.quickstep.RecentsAnimationCallbacks; import com.android.quickstep.RecentsAnimationController; @@ -662,6 +663,9 @@ public class TaskbarLauncherStateController { * This refers to the intended state - a transition to this state might be in progress. */ public boolean isTaskbarAlignedWithHotseat() { + if (DisplayController.showLockedTaskbarOnHome(mLauncher) && isInLauncher()) { + return false; + } return mLauncherState.isTaskbarAlignedWithHotseat(mLauncher); } @@ -673,8 +677,7 @@ public class TaskbarLauncherStateController { boolean isInStashedState = mLauncherState.isTaskbarStashed(mLauncher); boolean willStashVisually = isInStashedState && mControllers.taskbarStashController.supportsVisualStashing(); - boolean isTaskbarAlignedWithHotseat = - mLauncherState.isTaskbarAlignedWithHotseat(mLauncher); + boolean isTaskbarAlignedWithHotseat = isTaskbarAlignedWithHotseat(); return isTaskbarAlignedWithHotseat && !willStashVisually; } else { return false; diff --git a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java index c3270dcae9..f3b984b81e 100644 --- a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java +++ b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java @@ -15,6 +15,7 @@ */ package com.android.quickstep.util; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.view.Display.DEFAULT_DISPLAY; import android.content.Context; @@ -30,6 +31,8 @@ import com.android.launcher3.statehandlers.DesktopVisibilityController; import com.android.launcher3.util.WindowBounds; import com.android.launcher3.util.window.CachedDisplayInfo; import com.android.launcher3.util.window.WindowManagerProxy; +import com.android.quickstep.SystemUiProxy; +import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import java.util.List; import java.util.Set; @@ -65,6 +68,24 @@ public class SystemWindowManagerProxy extends WindowManagerProxy { return desktopController != null && desktopController.areDesktopTasksVisible(); } + @Override + public boolean showLockedTaskbarOnHome(Context displayInfoContext) { + if (!DesktopModeStatus.canEnterDesktopMode(displayInfoContext)) { + return false; + } + if (!DesktopModeStatus.enterDesktopByDefaultOnFreeformDisplay(displayInfoContext)) { + return false; + } + final boolean isFreeformDisplay = displayInfoContext.getResources().getConfiguration() + .windowConfiguration.getWindowingMode() == WINDOWING_MODE_FREEFORM; + return isFreeformDisplay; + } + + @Override + public boolean isHomeVisible(Context context) { + return SystemUiProxy.INSTANCE.get(context).getHomeVisibilityState().isHomeVisible(); + } + @Override public int getRotation(Context displayInfoContext) { return displayInfoContext.getResources().getConfiguration().windowConfiguration diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java index 072bcdf1db..dff9a0785d 100644 --- a/src/com/android/launcher3/util/DisplayController.java +++ b/src/com/android/launcher3/util/DisplayController.java @@ -194,6 +194,13 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable { INSTANCE.get(context).handleInfoChange(context.getDisplay()); } + /** + * Handles info change for launcher visibility. + */ + public static void handleInfoChangeForLauncherVisibilityChanged(Context context) { + INSTANCE.get(context).handleInfoChange(context.getDisplay()); + } + /** * Enables transient taskbar status for tests. */ @@ -217,6 +224,13 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable { return INSTANCE.get(context).getInfo().isPinnedTaskbar(); } + /** + * Returns whether the taskbar is forced to be pinned when home is visible. + */ + public static boolean showLockedTaskbarOnHome(Context context) { + return INSTANCE.get(context).getInfo().showLockedTaskbarOnHome(); + } + @Override public void close() { mDestroyed = true; @@ -345,7 +359,8 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable { } if ((newInfo.mIsTaskbarPinned != oldInfo.mIsTaskbarPinned) || (newInfo.mIsTaskbarPinnedInDesktopMode - != oldInfo.mIsTaskbarPinnedInDesktopMode)) { + != oldInfo.mIsTaskbarPinnedInDesktopMode) + || newInfo.isPinnedTaskbar() != oldInfo.isPinnedTaskbar()) { change |= CHANGE_TASKBAR_PINNING; } if (newInfo.mIsInDesktopMode != oldInfo.mIsInDesktopMode) { @@ -399,6 +414,9 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable { private final boolean mIsInDesktopMode; + private final boolean mShowLockedTaskbarOnHome; + private final boolean mIsHomeVisible; + public Info(Context displayInfoContext) { /* don't need system overrides for external displays */ this(displayInfoContext, new WindowManagerProxy(), new ArrayMap<>()); @@ -460,6 +478,8 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable { mIsTaskbarPinnedInDesktopMode = LauncherPrefs.get(displayInfoContext).get( TASKBAR_PINNING_IN_DESKTOP_MODE); mIsInDesktopMode = wmProxy.isInDesktopMode(); + mShowLockedTaskbarOnHome = wmProxy.showLockedTaskbarOnHome(displayInfoContext); + mIsHomeVisible = wmProxy.isHomeVisible(displayInfoContext); } /** @@ -476,6 +496,10 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable { return sTransientTaskbarStatusForTests; } if (enableTaskbarPinning()) { + // If Launcher is visible on the freeform display, ensure the taskbar is pinned. + if (mShowLockedTaskbarOnHome && mIsHomeVisible) { + return false; + } if (mIsInDesktopMode) { return !mIsTaskbarPinnedInDesktopMode; } @@ -543,6 +567,13 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable { return TYPE_PHONE; } } + + /** + * Returns whether the taskbar is forced to be pinned when home is visible. + */ + public boolean showLockedTaskbarOnHome() { + return mShowLockedTaskbarOnHome; + } } /** diff --git a/src/com/android/launcher3/util/window/WindowManagerProxy.java b/src/com/android/launcher3/util/window/WindowManagerProxy.java index 0817c0ab78..22ecf684e9 100644 --- a/src/com/android/launcher3/util/window/WindowManagerProxy.java +++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java @@ -121,6 +121,20 @@ public class WindowManagerProxy implements ResourceBasedOverride, SafeCloseable return false; } + /** + * Returns if the pinned taskbar should be shown when home is visible. + */ + public boolean showLockedTaskbarOnHome(Context displayInfoContext) { + return false; + } + + /** + * Returns if the home is visible. + */ + public boolean isHomeVisible(Context context) { + return false; + } + /** * Returns the real bounds for the provided display after applying any insets normalization */ diff --git a/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt b/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt index 41effa2f01..d4e4bd253f 100644 --- a/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt @@ -38,6 +38,8 @@ import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext import com.android.launcher3.util.window.CachedDisplayInfo import com.android.launcher3.util.window.WindowManagerProxy +import junit.framework.Assert.assertFalse +import junit.framework.Assert.assertTrue import kotlin.math.min import org.junit.Before import org.junit.Test @@ -111,6 +113,7 @@ class DisplayControllerTest { whenever(windowManagerProxy.getRealBounds(any(), any())).thenAnswer { i -> bounds[i.getArgument(1).rotation] } + whenever(windowManagerProxy.showLockedTaskbarOnHome(any())).thenReturn(false) whenever(windowManagerProxy.getNavigationMode(any())).thenReturn(NavigationMode.NO_BUTTON) // Mock context @@ -180,4 +183,20 @@ class DisplayControllerTest { verify(displayInfoChangeListener) .onDisplayInfoChanged(any(), any(), eq(CHANGE_TASKBAR_PINNING)) } + + @Test + @UiThreadTest + fun testTaskbarPinningChangeInLockedTaskbarChange() { + whenever(windowManagerProxy.showLockedTaskbarOnHome(any())).thenReturn(true) + whenever(windowManagerProxy.isHomeVisible(any())).thenReturn(true) + whenever(windowManagerProxy.isInDesktopMode()).thenReturn(false) + whenever(launcherPrefs.get(TASKBAR_PINNING)).thenReturn(false) + DisplayController.enableTaskbarModePreferenceForTests(true) + + assertTrue(displayController.getInfo().isTransientTaskbar()) + displayController.handleInfoChange(display) + verify(displayInfoChangeListener) + .onDisplayInfoChanged(any(), any(), eq(CHANGE_TASKBAR_PINNING)) + assertFalse(displayController.getInfo().isTransientTaskbar()) + } }