diff --git a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.kt b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.kt index 37e8d4dcd0..6ee43ff04d 100644 --- a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.kt +++ b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.kt @@ -62,8 +62,6 @@ constructor( * (Used only when multiple desks are enabled). * * @property displayId The ID of the display this object represents. - * @property canCreateDesks true if it's possible to create new desks on the display represented - * by this object. * @property activeDeskId The ID of the active desk on the associated display (if any). It has a * value of `INACTIVE_DESK_ID` (-1) if there are no active desks. Note that there can only be * at most one active desk on each display. @@ -71,11 +69,18 @@ constructor( */ private data class DisplayDeskConfig( val displayId: Int, - var canCreateDesks: Boolean, var activeDeskId: Int = INACTIVE_DESK_ID, val deskIds: MutableSet, ) + /** True if it is possible to create new desks on current setup. */ + var canCreateDesks: Boolean = false + private set(value) { + if (field == value) return + field = value + desktopVisibilityListeners.forEach { it.onCanCreateDesksChanged(field) } + } + /** Maps each display by its ID to its desks configuration. */ private val displaysDesksConfigsMap = SparseArray() @@ -393,7 +398,10 @@ constructor( } } - private fun onListenerConnected(displayDeskStates: Array) { + private fun onListenerConnected( + displayDeskStates: Array, + canCreateDesks: Boolean, + ) { if (!DesktopModeStatus.enableMultipleDesktops(context)) { return } @@ -404,23 +412,24 @@ constructor( displaysDesksConfigsMap[displayDeskState.displayId] = DisplayDeskConfig( displayId = displayDeskState.displayId, - canCreateDesks = displayDeskState.canCreateDesk, activeDeskId = displayDeskState.activeDeskId, deskIds = displayDeskState.deskIds.toMutableSet(), ) } + + this.canCreateDesks = canCreateDesks } private fun getDisplayDeskConfig(displayId: Int) = displaysDesksConfigsMap[displayId] ?: null.also { Slog.e(TAG, "Expected non-null desk config for display: $displayId") } - private fun onCanCreateDesksChanged(displayId: Int, canCreateDesks: Boolean) { + private fun onCanCreateDesksChanged(canCreateDesks: Boolean) { if (!DesktopModeStatus.enableMultipleDesktops(context)) { return } - getDisplayDeskConfig(displayId)?.canCreateDesks = canCreateDesks + this.canCreateDesks = canCreateDesks } private fun onDeskAdded(displayId: Int, deskId: Int) { @@ -525,9 +534,12 @@ constructor( ) : Stub() { private val controller = WeakReference(controller) - override fun onListenerConnected(displayDeskStates: Array) { + override fun onListenerConnected( + displayDeskStates: Array, + canCreateDesks: Boolean, + ) { Executors.MAIN_EXECUTOR.execute { - controller.get()?.onListenerConnected(displayDeskStates) + controller.get()?.onListenerConnected(displayDeskStates, canCreateDesks) } } @@ -565,9 +577,9 @@ constructor( override fun onExitDesktopModeTransitionStarted(transitionDuration: Int) {} - override fun onCanCreateDesksChanged(displayId: Int, canCreateDesks: Boolean) { + override fun onCanCreateDesksChanged(canCreateDesks: Boolean) { Executors.MAIN_EXECUTOR.execute { - controller.get()?.onCanCreateDesksChanged(displayId, canCreateDesks) + controller.get()?.onCanCreateDesksChanged(canCreateDesks) } } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index a29d3028bc..c5a76cb067 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -157,6 +157,7 @@ import com.android.launcher3.logger.LauncherAtom; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.statehandlers.DepthController; +import com.android.launcher3.statehandlers.DesktopVisibilityController; import com.android.launcher3.statemanager.BaseState; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.statemanager.StatefulContainer; @@ -179,6 +180,7 @@ import com.android.launcher3.util.TranslateEdgeEffect; import com.android.launcher3.util.VibratorWrapper; import com.android.launcher3.util.ViewPool; import com.android.launcher3.util.coroutines.DispatcherProvider; +import com.android.launcher3.util.window.WindowManagerProxy.DesktopVisibilityListener; import com.android.quickstep.BaseContainerInterface; import com.android.quickstep.GestureState; import com.android.quickstep.HighResLoadingState; @@ -265,7 +267,7 @@ public abstract class RecentsView< CONTAINER_TYPE extends Context & RecentsViewContainer & StatefulContainer, STATE_TYPE extends BaseState> extends PagedView implements Insettable, HighResLoadingState.HighResLoadingStateChangedCallback, - TaskVisualsChangeListener { + TaskVisualsChangeListener, DesktopVisibilityListener { private static final String TAG = "RecentsView"; private static final boolean DEBUG = false; @@ -556,6 +558,10 @@ public abstract class RecentsView< private final Rect mTaskViewDeadZoneRect = new Rect(); private final Rect mTopRowDeadZoneRect = new Rect(); private final Rect mBottomRowDeadZoneRect = new Rect(); + + @Nullable + private DesktopVisibilityController mDesktopVisibilityController = null; + /** * Reflects if Recents is currently in the middle of a gesture, and if so, which tasks are * running. If a gesture is not in progress, this will be null. @@ -913,6 +919,8 @@ public abstract class RecentsView< mAddDesktopButton = (AddDesktopButton) LayoutInflater.from(context).inflate( R.layout.overview_add_desktop_button, this, false); mAddDesktopButton.setOnClickListener(this::createDesk); + + mDesktopVisibilityController = DesktopVisibilityController.INSTANCE.get(mContext); } mTaskViewPool = new ViewPool<>(context, this, R.layout.task, 20 /* max size */, @@ -1227,13 +1235,16 @@ public abstract class RecentsView< mSyncTransactionApplier = new SurfaceTransactionApplier(this); runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTransformParams() .setSyncTransactionApplier(mSyncTransactionApplier)); - RecentsModel.INSTANCE.get(getContext()).addThumbnailChangeListener(this); + RecentsModel.INSTANCE.get(mContext).addThumbnailChangeListener(this); mIPipAnimationListener.setActivityAndRecentsView(mContainer, this); - SystemUiProxy.INSTANCE.get(getContext()).setPipAnimationListener( + SystemUiProxy.INSTANCE.get(mContext).setPipAnimationListener( mIPipAnimationListener); mOrientationState.initListeners(); mTaskOverlayFactory.initListeners(); mSplitSelectStateController.registerSplitListener(mSplitSelectionListener); + if (mDesktopVisibilityController != null) { + mDesktopVisibilityController.registerDesktopVisibilityListener(this); + } } @Override @@ -1248,12 +1259,15 @@ public abstract class RecentsView< runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTransformParams() .setSyncTransactionApplier(null)); executeSideTaskLaunchCallback(); - RecentsModel.INSTANCE.get(getContext()).removeThumbnailChangeListener(this); - SystemUiProxy.INSTANCE.get(getContext()).setPipAnimationListener(null); + RecentsModel.INSTANCE.get(mContext).removeThumbnailChangeListener(this); + SystemUiProxy.INSTANCE.get(mContext).setPipAnimationListener(null); mIPipAnimationListener.setActivityAndRecentsView(null, null); mOrientationState.destroyListeners(); mTaskOverlayFactory.removeListeners(); mSplitSelectStateController.unregisterSplitListener(mSplitSelectionListener); + if (mDesktopVisibilityController != null) { + mDesktopVisibilityController.unregisterDesktopVisibilityListener(this); + } reset(); } @@ -6859,6 +6873,11 @@ public abstract class RecentsView< } } + @Override + public void onCanCreateDesksChanged(boolean canCreateDesks) { + // TODO: b/389209338 - update the AddDesktopButton's visibility on this. + } + /** Get the color used for foreground scrimming the RecentsView for sharing. */ public static int getForegroundScrimDimColor(Context context) { return context.getColor(R.color.overview_foreground_scrim_color); diff --git a/src/com/android/launcher3/util/window/WindowManagerProxy.java b/src/com/android/launcher3/util/window/WindowManagerProxy.java index 647d170340..11f0bc21b9 100644 --- a/src/com/android/launcher3/util/window/WindowManagerProxy.java +++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java @@ -509,7 +509,17 @@ public class WindowManagerProxy { * @param isInDesktopModeAndNotInOverview True if a desktop is currently active on the given * display, and Overview is currently inactive. */ - void onIsInDesktopModeChanged(int displayId, boolean isInDesktopModeAndNotInOverview); + default void onIsInDesktopModeChanged(int displayId, + boolean isInDesktopModeAndNotInOverview) { + } + + /** + * Called whenever the conditions that allow the creation of desks change. + * + * @param canCreateDesks whether it is possible to create new desks. + */ + default void onCanCreateDesksChanged(boolean canCreateDesks) { + } } }