From 860c4ee6809522f1987bf2640f7decff7989dd28 Mon Sep 17 00:00:00 2001 From: Toni Barzic Date: Thu, 23 Jan 2025 18:58:15 +0000 Subject: [PATCH] Use pinned taskbar with desktop tasks on freeform displays Bug: 390665752 Flag: com.android.window.flags.enable_desktop_taskbar_on_freeform_displays Test: manual on desktop device. verify correct taskbar is shown on home screen, in overview, in desktop mode, with fullscreen app shown. Verify opening/launching apps from taskbar works as expected. Change-Id: I5c1e21799609c28ec44cc190bfc681934907199f --- .../taskbar/TaskbarDesktopModeController.kt | 5 +- .../TaskbarLauncherStateController.java | 10 +++- .../taskbar/TaskbarStashController.java | 3 +- .../util/SystemWindowManagerProxy.java | 20 +++++++ .../launcher3/util/DisplayController.java | 29 +++++++++- .../util/window/WindowManagerProxy.java | 8 +++ .../launcher3/util/DisplayControllerTest.kt | 58 +++++++++++++++++++ 7 files changed, 128 insertions(+), 5 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDesktopModeController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarDesktopModeController.kt index 8806bc69f4..cb399e8c70 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDesktopModeController.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDesktopModeController.kt @@ -50,8 +50,9 @@ class TaskbarDesktopModeController( fun shouldShowDesktopTasksInTaskbar(): Boolean { return desktopVisibilityController.areDesktopTasksVisible() || - DisplayController.showLockedTaskbarOnHome(context) && - taskbarControllers.taskbarStashController.isOnHome + DisplayController.showDesktopTaskbarForFreeformDisplay(context) || + (DisplayController.showLockedTaskbarOnHome(context) && + taskbarControllers.taskbarStashController.isOnHome) } fun getTaskbarCornerRoundness(doesAnyTaskRequireTaskbarRounding: Boolean): Float { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java index 9a9575debc..cada5a39d0 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java @@ -58,7 +58,6 @@ import com.android.launcher3.QuickstepTransitionManager; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatedFloat; import com.android.launcher3.anim.AnimatorListeners; -import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController.BubbleLauncherState; import com.android.launcher3.uioverrides.QuickstepLauncher; @@ -714,6 +713,10 @@ public class TaskbarLauncherStateController { private static boolean shouldShowTaskbar(Context context, boolean isInLauncher, boolean isInOverview) { + if (DisplayController.showDesktopTaskbarForFreeformDisplay(context)) { + return true; + } + if (DisplayController.showLockedTaskbarOnHome(context) && isInLauncher) { return true; } @@ -769,9 +772,14 @@ public class TaskbarLauncherStateController { * This refers to the intended state - a transition to this state might be in progress. */ public boolean isTaskbarAlignedWithHotseat() { + if (DisplayController.showDesktopTaskbarForFreeformDisplay(mLauncher)) { + return false; + } + if (DisplayController.showLockedTaskbarOnHome(mLauncher) && isInLauncher()) { return false; } + return mLauncherState.isTaskbarAlignedWithHotseat(mLauncher); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index 1ca3dfbd48..2ded1bff8d 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -301,7 +301,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba // TODO(b/390665752): Feature to "lock" pinned taskbar to home screen will be superseded by // pinning, in other launcher states, at which point this variable can be removed. mInAppStateAffectsDesktopTasksVisibilityInTaskbar = - DisplayController.showLockedTaskbarOnHome(mActivity); + !DisplayController.showDesktopTaskbarForFreeformDisplay(mActivity) + && DisplayController.showLockedTaskbarOnHome(mActivity); mTaskbarBackgroundDuration = activity.getResources().getInteger( R.integer.taskbar_background_duration); diff --git a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java index 4d56c63ad1..10ae7a30cb 100644 --- a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java +++ b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java @@ -33,6 +33,7 @@ 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.window.flags.Flags; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import java.util.List; @@ -89,6 +90,25 @@ public class SystemWindowManagerProxy extends WindowManagerProxy { return isFreeformDisplay; } + @Override + public boolean showDesktopTaskbarForFreeformDisplay(Context displayInfoContext) { + if (!DesktopModeStatus.canEnterDesktopMode(displayInfoContext)) { + return false; + } + + if (!DesktopModeStatus.enterDesktopByDefaultOnFreeformDisplay(displayInfoContext)) { + return false; + } + + if (!Flags.enableDesktopTaskbarOnFreeformDisplays()) { + 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(); diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java index 475dc04d44..ee1af810f7 100644 --- a/src/com/android/launcher3/util/DisplayController.java +++ b/src/com/android/launcher3/util/DisplayController.java @@ -220,6 +220,14 @@ public class DisplayController implements ComponentCallbacks, return INSTANCE.get(context).getInfo().showLockedTaskbarOnHome(); } + /** + * Returns whether desktop taskbar (pinned taskbar that shows desktop tasks) is to be used + * on the display because the display is a freeform display. + */ + public static boolean showDesktopTaskbarForFreeformDisplay(Context context) { + return INSTANCE.get(context).getInfo().showDesktopTaskbarForFreeformDisplay(); + } + @Override public void onDesktopVisibilityChanged(boolean visible) { notifyConfigChange(); @@ -259,7 +267,9 @@ public class DisplayController implements ComponentCallbacks, new PortraitSize(config.screenHeightDp, config.screenWidthDp)) || mWindowContext.getDisplay().getRotation() != mInfo.rotation || mWMProxy.showLockedTaskbarOnHome(mWindowContext) - != mInfo.showLockedTaskbarOnHome()) { + != mInfo.showLockedTaskbarOnHome() + || mWMProxy.showDesktopTaskbarForFreeformDisplay(mWindowContext) + != mInfo.showDesktopTaskbarForFreeformDisplay()) { notifyConfigChange(); } } @@ -376,6 +386,8 @@ public class DisplayController implements ComponentCallbacks, private final boolean mShowLockedTaskbarOnHome; private final boolean mIsHomeVisible; + private final boolean mShowDesktopTaskbarForFreeformDisplay; + public Info(Context displayInfoContext) { /* don't need system overrides for external displays */ this(displayInfoContext, new WindowManagerProxy(), new ArrayMap<>()); @@ -438,6 +450,8 @@ public class DisplayController implements ComponentCallbacks, TASKBAR_PINNING_IN_DESKTOP_MODE); mIsInDesktopMode = wmProxy.isInDesktopMode(); mShowLockedTaskbarOnHome = wmProxy.showLockedTaskbarOnHome(displayInfoContext); + mShowDesktopTaskbarForFreeformDisplay = wmProxy.showDesktopTaskbarForFreeformDisplay( + displayInfoContext); mIsHomeVisible = wmProxy.isHomeVisible(displayInfoContext); } @@ -455,6 +469,11 @@ public class DisplayController implements ComponentCallbacks, return sTransientTaskbarStatusForTests; } if (enableTaskbarPinning()) { + // If "freeform" display taskbar is enabled, ensure the taskbar is pinned. + if (mShowDesktopTaskbarForFreeformDisplay) { + return false; + } + // If Launcher is visible on the freeform display, ensure the taskbar is pinned. if (mShowLockedTaskbarOnHome && mIsHomeVisible) { return false; @@ -533,6 +552,14 @@ public class DisplayController implements ComponentCallbacks, public boolean showLockedTaskbarOnHome() { return mShowLockedTaskbarOnHome; } + + /** + * Returns whether the taskbar should be pinned, and showing desktop tasks, because the + * display is a "freeform" display. + */ + public boolean showDesktopTaskbarForFreeformDisplay() { + return mShowDesktopTaskbarForFreeformDisplay; + } } /** diff --git a/src/com/android/launcher3/util/window/WindowManagerProxy.java b/src/com/android/launcher3/util/window/WindowManagerProxy.java index e568eed691..f511ef2eac 100644 --- a/src/com/android/launcher3/util/window/WindowManagerProxy.java +++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java @@ -120,6 +120,14 @@ public class WindowManagerProxy { return false; } + /** + * Returns whether the display is a freeform display for which taskbar should be pinned + * and showing desktop tasks. + */ + public boolean showDesktopTaskbarForFreeformDisplay(Context displayInfoContext) { + return false; + } + /** * Returns if the home is visible. */ diff --git a/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt b/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt index 7e76e1965c..588a668b7a 100644 --- a/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt @@ -32,6 +32,7 @@ import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING_IN_DESKTOP_ import com.android.launcher3.dagger.LauncherAppComponent import com.android.launcher3.dagger.LauncherAppSingleton import com.android.launcher3.util.DisplayController.CHANGE_DENSITY +import com.android.launcher3.util.DisplayController.CHANGE_DESKTOP_MODE import com.android.launcher3.util.DisplayController.CHANGE_ROTATION import com.android.launcher3.util.DisplayController.CHANGE_TASKBAR_PINNING import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener @@ -229,6 +230,63 @@ class DisplayControllerTest { .onDisplayInfoChanged(any(), any(), eq(CHANGE_TASKBAR_PINNING)) assertFalse(displayController.getInfo().isTransientTaskbar()) } + + @Test + @UiThreadTest + fun testTaskbarPinnedForDesktopTaskbar_inDesktopMode() { + whenever(windowManagerProxy.showDesktopTaskbarForFreeformDisplay(any())).thenReturn(true) + whenever(launcherPrefs.get(TASKBAR_PINNING)).thenReturn(false) + whenever(launcherPrefs.get(TASKBAR_PINNING_IN_DESKTOP_MODE)).thenReturn(false) + whenever(windowManagerProxy.isInDesktopMode()).thenReturn(true) + whenever(windowManagerProxy.isHomeVisible(any())).thenReturn(false) + DisplayController.enableTaskbarModePreferenceForTests(true) + + assertTrue(displayController.getInfo().isTransientTaskbar()) + + displayController.onConfigurationChanged(configuration) + + verify(displayInfoChangeListener) + .onDisplayInfoChanged(any(), any(), eq(CHANGE_TASKBAR_PINNING or CHANGE_DESKTOP_MODE)) + assertFalse(displayController.getInfo().isTransientTaskbar()) + } + + @Test + @UiThreadTest + fun testTaskbarPinnedForDesktopTaskbar_notInDesktopMode() { + whenever(windowManagerProxy.showDesktopTaskbarForFreeformDisplay(any())).thenReturn(true) + whenever(launcherPrefs.get(TASKBAR_PINNING)).thenReturn(false) + whenever(launcherPrefs.get(TASKBAR_PINNING_IN_DESKTOP_MODE)).thenReturn(false) + whenever(windowManagerProxy.isInDesktopMode()).thenReturn(false) + whenever(windowManagerProxy.isHomeVisible(any())).thenReturn(false) + DisplayController.enableTaskbarModePreferenceForTests(true) + + assertTrue(displayController.getInfo().isTransientTaskbar()) + + displayController.onConfigurationChanged(configuration) + + verify(displayInfoChangeListener) + .onDisplayInfoChanged(any(), any(), eq(CHANGE_TASKBAR_PINNING)) + assertFalse(displayController.getInfo().isTransientTaskbar()) + } + + @Test + @UiThreadTest + fun testTaskbarPinnedForDesktopTaskbar_onHome() { + whenever(windowManagerProxy.showDesktopTaskbarForFreeformDisplay(any())).thenReturn(true) + whenever(launcherPrefs.get(TASKBAR_PINNING)).thenReturn(false) + whenever(launcherPrefs.get(TASKBAR_PINNING_IN_DESKTOP_MODE)).thenReturn(false) + whenever(windowManagerProxy.isInDesktopMode()).thenReturn(false) + whenever(windowManagerProxy.isHomeVisible(any())).thenReturn(true) + DisplayController.enableTaskbarModePreferenceForTests(true) + + assertTrue(displayController.getInfo().isTransientTaskbar()) + + displayController.onConfigurationChanged(configuration) + + verify(displayInfoChangeListener) + .onDisplayInfoChanged(any(), any(), eq(CHANGE_TASKBAR_PINNING)) + assertFalse(displayController.getInfo().isTransientTaskbar()) + } } class MyWmProxy : WindowManagerProxy()