diff options
4 files changed, 64 insertions, 20 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandler.kt index 127a8a9c41ad..80c6f2e5ff33 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandler.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandler.kt @@ -72,7 +72,10 @@ class DesktopDisplayEventHandler( override fun onDisplayAdded(displayId: Int) { if (displayId != DEFAULT_DISPLAY) { - desktopDisplayModeController.refreshDisplayWindowingMode() + desktopDisplayModeController.updateExternalDisplayWindowingMode(displayId) + // The default display's windowing mode depends on the availability of the external + // display. So updating the default display's windowing mode here. + desktopDisplayModeController.updateDefaultDisplayWindowingMode() } createDefaultDesksIfNeeded(displayIds = setOf(displayId), userId = null) @@ -80,7 +83,7 @@ class DesktopDisplayEventHandler( override fun onDisplayRemoved(displayId: Int) { if (displayId != DEFAULT_DISPLAY) { - desktopDisplayModeController.refreshDisplayWindowingMode() + desktopDisplayModeController.updateDefaultDisplayWindowingMode() } // TODO: b/362720497 - move desks in closing display to the remaining desk. @@ -91,7 +94,10 @@ class DesktopDisplayEventHandler( DesktopExperienceFlags.ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT.isTrue && displayId != DEFAULT_DISPLAY ) { - desktopDisplayModeController.refreshDisplayWindowingMode() + desktopDisplayModeController.updateExternalDisplayWindowingMode(displayId) + // The default display's windowing mode depends on the desktop eligibility of the + // external display. So updating the default display's windowing mode here. + desktopDisplayModeController.updateDefaultDisplayWindowingMode() } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayModeController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayModeController.kt index 0a3e2cc3b434..dec489e8fc63 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayModeController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopDisplayModeController.kt @@ -59,15 +59,15 @@ class DesktopDisplayModeController( private val inputDeviceListener = object : InputManager.InputDeviceListener { override fun onInputDeviceAdded(deviceId: Int) { - refreshDisplayWindowingMode() + updateDefaultDisplayWindowingMode() } override fun onInputDeviceChanged(deviceId: Int) { - refreshDisplayWindowingMode() + updateDefaultDisplayWindowingMode() } override fun onInputDeviceRemoved(deviceId: Int) { - refreshDisplayWindowingMode() + updateDefaultDisplayWindowingMode() } } @@ -77,12 +77,30 @@ class DesktopDisplayModeController( } } - fun refreshDisplayWindowingMode() { + fun updateExternalDisplayWindowingMode(displayId: Int) { + if (!DesktopExperienceFlags.ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT.isTrue) return + + val desktopModeSupported = + displayController.getDisplay(displayId)?.let { display -> + DesktopModeStatus.isDesktopModeSupportedOnDisplay(context, display) + } ?: false + if (!desktopModeSupported) return + + // An external display should always be a freeform display when desktop mode is enabled. + updateDisplayWindowingMode(displayId, WINDOWING_MODE_FREEFORM) + } + + fun updateDefaultDisplayWindowingMode() { if (!DesktopExperienceFlags.ENABLE_DISPLAY_WINDOWING_MODE_SWITCHING.isTrue) return - val targetDisplayWindowingMode = getTargetWindowingModeForDefaultDisplay() - val tdaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY) - requireNotNull(tdaInfo) { "DisplayAreaInfo of DEFAULT_DISPLAY must be non-null." } + updateDisplayWindowingMode(DEFAULT_DISPLAY, getTargetWindowingModeForDefaultDisplay()) + } + + private fun updateDisplayWindowingMode(displayId: Int, targetDisplayWindowingMode: Int) { + val tdaInfo = + requireNotNull(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(displayId)) { + "DisplayAreaInfo of display#$displayId must be non-null." + } val currentDisplayWindowingMode = tdaInfo.configuration.windowConfiguration.windowingMode if (currentDisplayWindowingMode == targetDisplayWindowingMode) { // Already in the target mode. @@ -90,15 +108,16 @@ class DesktopDisplayModeController( } logV( - "As an external display is connected, changing default display's windowing mode from" + - " ${windowingModeToString(currentDisplayWindowingMode)}" + - " to ${windowingModeToString(targetDisplayWindowingMode)}" + "Changing display#%d's windowing mode from %s to %s", + displayId, + windowingModeToString(currentDisplayWindowingMode), + windowingModeToString(targetDisplayWindowingMode), ) val wct = WindowContainerTransaction() wct.setWindowingMode(tdaInfo.token, targetDisplayWindowingMode) shellTaskOrganizer - .getRunningTasks(DEFAULT_DISPLAY) + .getRunningTasks(displayId) .filter { it.activityType == ACTIVITY_TYPE_STANDARD } .forEach { // TODO: b/391965153 - Reconsider the logic under multi-desk window hierarchy @@ -114,7 +133,7 @@ class DesktopDisplayModeController( // The override windowing mode of DesktopWallpaper can be UNDEFINED on fullscreen-display // right after the first launch while its resolved windowing mode is FULLSCREEN. We here // it has the FULLSCREEN override windowing mode. - desktopWallpaperActivityTokenProvider.getToken(DEFAULT_DISPLAY)?.let { token -> + desktopWallpaperActivityTokenProvider.getToken(displayId)?.let { token -> wct.setWindowingMode(token, WINDOWING_MODE_FULLSCREEN) } transitions.startTransition(TRANSIT_CHANGE, wct, /* handler= */ null) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandlerTest.kt index 565145b8616e..42dcaf4b4f33 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandlerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayEventHandlerTest.kt @@ -242,20 +242,22 @@ class DesktopDisplayEventHandlerTest : ShellTestCase() { @Test fun testConnectExternalDisplay() { onDisplaysChangedListenerCaptor.lastValue.onDisplayAdded(externalDisplayId) - verify(desktopDisplayModeController).refreshDisplayWindowingMode() + verify(desktopDisplayModeController).updateExternalDisplayWindowingMode(externalDisplayId) + verify(desktopDisplayModeController).updateDefaultDisplayWindowingMode() } @Test fun testDisconnectExternalDisplay() { onDisplaysChangedListenerCaptor.lastValue.onDisplayRemoved(externalDisplayId) - verify(desktopDisplayModeController).refreshDisplayWindowingMode() + verify(desktopDisplayModeController).updateDefaultDisplayWindowingMode() } @Test @EnableFlags(DisplayFlags.FLAG_ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT) fun testDesktopModeEligibleChanged() { onDisplaysChangedListenerCaptor.lastValue.onDesktopModeEligibleChanged(externalDisplayId) - verify(desktopDisplayModeController).refreshDisplayWindowingMode() + verify(desktopDisplayModeController).updateExternalDisplayWindowingMode(externalDisplayId) + verify(desktopDisplayModeController).updateDefaultDisplayWindowingMode() } private class FakeDesktopRepositoryInitializer : DesktopRepositoryInitializer { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayModeControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayModeControllerTest.kt index 488025a3d754..7e9ee34c8f68 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayModeControllerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopDisplayModeControllerTest.kt @@ -101,6 +101,7 @@ class DesktopDisplayModeControllerTest( private val fullscreenTask = TestRunningTaskInfoBuilder().setWindowingMode(WINDOWING_MODE_FULLSCREEN).build() private val defaultTDA = DisplayAreaInfo(MockToken().token(), DEFAULT_DISPLAY, 0) + private val externalTDA = DisplayAreaInfo(MockToken().token(), EXTERNAL_DISPLAY_ID, 0) private val wallpaperToken = MockToken().token() private val defaultDisplay = mock<Display>() private val externalDisplay = mock<Display>() @@ -129,6 +130,8 @@ class DesktopDisplayModeControllerTest( whenever(transitions.startTransition(anyInt(), any(), isNull())).thenReturn(Binder()) whenever(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)) .thenReturn(defaultTDA) + whenever(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(EXTERNAL_DISPLAY_ID)) + .thenReturn(externalTDA) controller = DesktopDisplayModeController( context, @@ -292,16 +295,30 @@ class DesktopDisplayModeControllerTest( .isEqualTo(WINDOWING_MODE_UNDEFINED) } + @Test + @EnableFlags(DisplayFlags.FLAG_ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT) + fun externalDisplayWindowingMode() { + externalTDA.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN + setExtendedMode(true) + + controller.updateExternalDisplayWindowingMode(EXTERNAL_DISPLAY_ID) + + val arg = argumentCaptor<WindowContainerTransaction>() + verify(transitions, times(1)).startTransition(eq(TRANSIT_CHANGE), arg.capture(), isNull()) + assertThat(arg.firstValue.changes[externalTDA.token.asBinder()]?.windowingMode) + .isEqualTo(WINDOWING_MODE_FREEFORM) + } + private fun connectExternalDisplay() { whenever(rootTaskDisplayAreaOrganizer.getDisplayIds()) .thenReturn(intArrayOf(DEFAULT_DISPLAY, EXTERNAL_DISPLAY_ID)) - controller.refreshDisplayWindowingMode() + controller.updateDefaultDisplayWindowingMode() } private fun disconnectExternalDisplay() { whenever(rootTaskDisplayAreaOrganizer.getDisplayIds()) .thenReturn(intArrayOf(DEFAULT_DISPLAY)) - controller.refreshDisplayWindowingMode() + controller.updateDefaultDisplayWindowingMode() } private fun setExtendedMode(enabled: Boolean) { |