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
This commit is contained in:
Toni Barzic
2025-01-23 18:58:15 +00:00
parent 6c19792dcd
commit 860c4ee680
7 changed files with 128 additions and 5 deletions
@@ -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 {
@@ -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);
}
@@ -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);
@@ -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();
@@ -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;
}
}
/**
@@ -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.
*/
@@ -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()