Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 11b57704 authored by Saho Kobayashi's avatar Saho Kobayashi
Browse files

Migrate DesktopTilingWindowDecoration to FocusTransitionObserver

This CL migrates DesktopTilingWindowDecoration from
ShellTaskOrganizer.FocusListener to FocusTransitionObserver.

Bug: b:381361555
Test: DesktopTilingWindowDecorationTest
Test: DesktopTilingWindowDecorViewModelTest
Flag: com.android.window.flags.enable_display_focus_in_shell_transitions

Change-Id: Ib8564ef18d6f847ea1cdb17eeb8f38e457195226
parent 4b45f29b
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -814,7 +814,9 @@ public abstract class WMShellModule {
            ReturnToDragStartAnimator returnToDragStartAnimator,
            @DynamicOverride DesktopUserRepositories desktopUserRepositories,
            DesktopModeEventLogger desktopModeEventLogger,
            WindowDecorTaskResourceLoader windowDecorTaskResourceLoader) {
            WindowDecorTaskResourceLoader windowDecorTaskResourceLoader,
            FocusTransitionObserver focusTransitionObserver,
            @ShellMainThread ShellExecutor mainExecutor) {
        return new DesktopTilingDecorViewModel(
                context,
                mainDispatcher,
@@ -828,7 +830,9 @@ public abstract class WMShellModule {
                returnToDragStartAnimator,
                desktopUserRepositories,
                desktopModeEventLogger,
                windowDecorTaskResourceLoader
                windowDecorTaskResourceLoader,
                focusTransitionObserver,
                mainExecutor
        );
    }

+8 −1
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.common.DisplayChangeController
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.desktopmode.DesktopModeEventLogger
import com.android.wm.shell.desktopmode.DesktopTasksController
@@ -37,6 +38,7 @@ import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator
import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler
import com.android.wm.shell.shared.annotations.ShellBackgroundThread
import com.android.wm.shell.shared.annotations.ShellMainThread
import com.android.wm.shell.transition.FocusTransitionObserver
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration
import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader
@@ -58,6 +60,8 @@ class DesktopTilingDecorViewModel(
    private val desktopUserRepositories: DesktopUserRepositories,
    private val desktopModeEventLogger: DesktopModeEventLogger,
    private val taskResourceLoader: WindowDecorTaskResourceLoader,
    private val focusTransitionObserver: FocusTransitionObserver,
    private val mainExecutor: ShellExecutor,
) : DisplayChangeController.OnDisplayChangingListener {
    @VisibleForTesting
    var tilingTransitionHandlerByDisplayId = SparseArray<DesktopTilingWindowDecoration>()
@@ -94,6 +98,8 @@ class DesktopTilingDecorViewModel(
                            returnToDragStartAnimator,
                            desktopUserRepositories,
                            desktopModeEventLogger,
                            focusTransitionObserver,
                            mainExecutor,
                        )
                    tilingTransitionHandlerByDisplayId.put(displayId, newHandler)
                    newHandler
@@ -112,9 +118,10 @@ class DesktopTilingDecorViewModel(
    }

    fun moveTaskToFrontIfTiled(taskInfo: RunningTaskInfo): Boolean {
        // Always pass focus=true because taskInfo.isFocused is not updated yet.
        return tilingTransitionHandlerByDisplayId
            .get(taskInfo.displayId)
            ?.moveTiledPairToFront(taskInfo, isTaskFocused = true) ?: false
            ?.moveTiledPairToFront(taskInfo.taskId, isFocusedOnDisplay = true) ?: false
    }

    fun onOverviewAnimationStateChange(isRunning: Boolean) {
+65 −40
Original line number Diff line number Diff line
@@ -35,11 +35,14 @@ import android.window.TransitionRequestInfo
import android.window.WindowContainerTransaction
import com.android.internal.annotations.VisibleForTesting
import com.android.launcher3.icons.BaseIconFactory
import com.android.window.flags.Flags
import com.android.wm.shell.shared.FocusTransitionListener
import com.android.wm.shell.R
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.DisplayLayout
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.desktopmode.DesktopModeEventLogger
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger
@@ -49,6 +52,7 @@ import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator
import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler
import com.android.wm.shell.shared.annotations.ShellBackgroundThread
import com.android.wm.shell.shared.annotations.ShellMainThread
import com.android.wm.shell.transition.FocusTransitionObserver
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.transition.Transitions.TRANSIT_MINIMIZE
import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration
@@ -78,13 +82,16 @@ class DesktopTilingWindowDecoration(
    private val returnToDragStartAnimator: ReturnToDragStartAnimator,
    private val desktopUserRepositories: DesktopUserRepositories,
    private val desktopModeEventLogger: DesktopModeEventLogger,
    private val focusTransitionObserver: FocusTransitionObserver,
    @ShellMainThread private val mainExecutor: ShellExecutor,
    private val transactionSupplier: Supplier<Transaction> = Supplier { Transaction() },
) :
    Transitions.TransitionHandler,
    ShellTaskOrganizer.FocusListener,
    ShellTaskOrganizer.TaskVanishedListener,
    DragEventListener,
    Transitions.TransitionObserver {
    Transitions.TransitionObserver,
    FocusTransitionListener {
    companion object {
        private val TAG: String = DesktopTilingWindowDecoration::class.java.simpleName
        private const val TILING_DIVIDER_TAG = "Tiling Divider"
@@ -176,9 +183,14 @@ class DesktopTilingWindowDecoration(
            if (!isTilingManagerInitialised) {
                desktopTilingDividerWindowManager = initTilingManagerForDisplay(displayId, config)
                isTilingManagerInitialised = true

                if (Flags.enableDisplayFocusInShellTransitions()) {
                    focusTransitionObserver.setLocalFocusTransitionListener(this, mainExecutor)
                } else {
                    shellTaskOrganizer.addFocusListener(this)
                    isTilingFocused = true
                }
            }
            leftTaskResizingHelper?.initIfNeeded()
            rightTaskResizingHelper?.initIfNeeded()
            leftTaskResizingHelper
@@ -474,23 +486,33 @@ class DesktopTilingWindowDecoration(
        }
    }

    // Only called if [taskInfo] relates to a focused task
    private fun isTilingFocusRemoved(taskInfo: RunningTaskInfo): Boolean {
    // Only called if [taskId] relates to a focused task
    private fun isTilingFocusRemoved(taskId: Int): Boolean {
        return isTilingFocused &&
            taskInfo.taskId != leftTaskResizingHelper?.taskInfo?.taskId &&
            taskInfo.taskId != rightTaskResizingHelper?.taskInfo?.taskId
            taskId != leftTaskResizingHelper?.taskInfo?.taskId &&
            taskId != rightTaskResizingHelper?.taskInfo?.taskId
    }

    // Overriding ShellTaskOrganizer.FocusListener
    override fun onFocusTaskChanged(taskInfo: RunningTaskInfo?) {
        if (Flags.enableDisplayFocusInShellTransitions()) return
        if (taskInfo != null) {
            moveTiledPairToFront(taskInfo)
            moveTiledPairToFront(taskInfo.taskId, taskInfo.isFocused)
        }
    }

    // Overriding FocusTransitionListener
    override fun onFocusedTaskChanged(taskId: Int,
            isFocusedOnDisplay: Boolean,
            isFocusedGlobally: Boolean) {
        if (!Flags.enableDisplayFocusInShellTransitions()) return
        moveTiledPairToFront(taskId, isFocusedOnDisplay)
    }

    // Only called if [taskInfo] relates to a focused task
    private fun isTilingRefocused(taskInfo: RunningTaskInfo): Boolean {
        return taskInfo.taskId == leftTaskResizingHelper?.taskInfo?.taskId ||
                taskInfo.taskId == rightTaskResizingHelper?.taskInfo?.taskId
    private fun isTilingRefocused(taskId: Int): Boolean {
        return taskId == leftTaskResizingHelper?.taskInfo?.taskId ||
                taskId == rightTaskResizingHelper?.taskInfo?.taskId
    }

    private fun buildTiledTasksMoveToFront(leftOnTop: Boolean): WindowContainerTransaction {
@@ -582,14 +604,13 @@ class DesktopTilingWindowDecoration(
     * If specified, [isTaskFocused] will override [RunningTaskInfo.isFocused]. This is to be used
     * when called when the task will be focused, but the [taskInfo] hasn't been updated yet.
     */
    fun moveTiledPairToFront(taskInfo: RunningTaskInfo, isTaskFocused: Boolean? = null): Boolean {
    fun moveTiledPairToFront(taskId: Int, isFocusedOnDisplay: Boolean): Boolean {
        if (!isTilingManagerInitialised) return false

        val isFocused = isTaskFocused ?: taskInfo.isFocused
        if (!isFocused) return false
        if (!isFocusedOnDisplay) return false

        // If a task that isn't tiled is being focused, let the generic handler do the work.
        if (isTilingFocusRemoved(taskInfo)) {
        if (!Flags.enableDisplayFocusInShellTransitions() && isTilingFocusRemoved(taskId)) {
            isTilingFocused = false
            return false
        }
@@ -597,17 +618,17 @@ class DesktopTilingWindowDecoration(
        val leftTiledTask = leftTaskResizingHelper ?: return false
        val rightTiledTask = rightTaskResizingHelper ?: return false
        if (!allTiledTasksVisible()) return false
        val isLeftOnTop = taskInfo.taskId == leftTiledTask.taskInfo.taskId
        if (isTilingRefocused(taskInfo)) {
        val isLeftOnTop = taskId == leftTiledTask.taskInfo.taskId
        if (!isTilingRefocused(taskId)) return false
        val t = transactionSupplier.get()
            isTilingFocused = true
            if (taskInfo.taskId == leftTaskResizingHelper?.taskInfo?.taskId) {
        if (!Flags.enableDisplayFocusInShellTransitions()) isTilingFocused = true
        if (taskId == leftTaskResizingHelper?.taskInfo?.taskId) {
          desktopTilingDividerWindowManager?.onRelativeLeashChanged(
              leftTiledTask.getLeash(),
              t,
          )
        }
            if (taskInfo.taskId == rightTaskResizingHelper?.taskInfo?.taskId) {
        if (taskId == rightTaskResizingHelper?.taskInfo?.taskId) {
          desktopTilingDividerWindowManager?.onRelativeLeashChanged(
              rightTiledTask.getLeash(),
              t,
@@ -621,8 +642,6 @@ class DesktopTilingWindowDecoration(
        t.apply()
        return true
    }
        return false
    }

    private fun allTiledTasksVisible(): Boolean {
        val leftTiledTask = leftTaskResizingHelper ?: return false
@@ -706,7 +725,13 @@ class DesktopTilingWindowDecoration(
    }

    private fun tearDownTiling() {
        if (isTilingManagerInitialised) shellTaskOrganizer.removeFocusListener(this)
        if (isTilingManagerInitialised) {
            if (Flags.enableDisplayFocusInShellTransitions()) {
                focusTransitionObserver.unsetLocalFocusTransitionListener(this)
            } else {
                shellTaskOrganizer.removeFocusListener(this)
            }
        }

        if (leftTaskResizingHelper == null && rightTaskResizingHelper == null) {
            shellTaskOrganizer.removeTaskVanishedListener(this)
+7 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.desktopmode.DesktopModeEventLogger
import com.android.wm.shell.desktopmode.DesktopUserRepositories
@@ -30,6 +31,7 @@ import com.android.wm.shell.desktopmode.DesktopTasksController
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask
import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator
import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler
import com.android.wm.shell.transition.FocusTransitionObserver
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration
import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader
@@ -67,6 +69,8 @@ class DesktopTilingDecorViewModelTest : ShellTestCase() {
    private val desktopModeWindowDecorationMock: DesktopModeWindowDecoration = mock()
    private val desktopTilingDecoration: DesktopTilingWindowDecoration = mock()
    private val taskResourceLoader: WindowDecorTaskResourceLoader = mock()
    private val focusTransitionObserver: FocusTransitionObserver = mock()
    private val mainExecutor: ShellExecutor = mock()
    private lateinit var desktopTilingDecorViewModel: DesktopTilingDecorViewModel

    @Before
@@ -86,6 +90,8 @@ class DesktopTilingDecorViewModelTest : ShellTestCase() {
                userRepositories,
                desktopModeEventLogger,
                taskResourceLoader,
                focusTransitionObserver,
                mainExecutor
            )
        whenever(contextMock.createContextAsUser(any(), any())).thenReturn(contextMock)
    }
@@ -140,7 +146,7 @@ class DesktopTilingDecorViewModelTest : ShellTestCase() {
        desktopTilingDecorViewModel.moveTaskToFrontIfTiled(task1)

        verify(desktopTilingDecoration, times(1))
            .moveTiledPairToFront(any(), isTaskFocused = eq(true))
            .moveTiledPairToFront(any(), isFocusedOnDisplay = eq(true))
    }

    @Test
+13 −7
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.DisplayLayout
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.desktopmode.DesktopModeEventLogger
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger
@@ -42,6 +43,7 @@ import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask
import com.android.wm.shell.desktopmode.DesktopUserRepositories
import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator
import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler
import com.android.wm.shell.transition.FocusTransitionObserver
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration
import com.android.wm.shell.windowdecor.DragResizeWindowGeometry
@@ -105,6 +107,8 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() {
    private val mainDispatcher: MainCoroutineDispatcher = mock()
    private val bgScope: CoroutineScope = mock()
    private val taskResourceLoader: WindowDecorTaskResourceLoader = mock()
    private val focusTransitionObserver: FocusTransitionObserver = mock()
    private val mainExecutor: ShellExecutor = mock()
    private lateinit var tilingDecoration: DesktopTilingWindowDecoration

    private val split_divider_width = 10
@@ -129,6 +133,8 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() {
                returnToDragStartAnimator,
                userRepositories,
                desktopModeEventLogger,
                focusTransitionObserver,
                mainExecutor
            )
        whenever(context.createContextAsUser(any(), any())).thenReturn(context)
        whenever(userRepositories.current).thenReturn(desktopRepository)
@@ -242,7 +248,7 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() {
            BOUNDS,
        )

        assertThat(tilingDecoration.moveTiledPairToFront(task2)).isFalse()
        assertThat(tilingDecoration.moveTiledPairToFront(task2.taskId, false)).isFalse()
        verify(transitions, never()).startTransition(any(), any(), any())
    }

@@ -272,7 +278,7 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() {
            BOUNDS,
        )

        assertThat(tilingDecoration.moveTiledPairToFront(task3)).isFalse()
        assertThat(tilingDecoration.moveTiledPairToFront(task3.taskId, false)).isFalse()
        verify(transitions, never()).startTransition(any(), any(), any())
    }

@@ -304,7 +310,7 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() {
        )
        task1.isFocused = true

        assertThat(tilingDecoration.moveTiledPairToFront(task1, isTaskFocused = true)).isTrue()
        assertThat(tilingDecoration.moveTiledPairToFront(task1.taskId, isFocusedOnDisplay = true)).isTrue()
        verify(transitions, times(1)).startTransition(eq(TRANSIT_TO_FRONT), any(), eq(null))
    }

@@ -336,8 +342,8 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() {
        task1.isFocused = true
        task3.isFocused = true

        assertThat(tilingDecoration.moveTiledPairToFront(task3)).isFalse()
        assertThat(tilingDecoration.moveTiledPairToFront(task1)).isTrue()
        assertThat(tilingDecoration.moveTiledPairToFront(task3.taskId, true)).isFalse()
        assertThat(tilingDecoration.moveTiledPairToFront(task1.taskId, true)).isTrue()
        verify(transitions, times(1)).startTransition(eq(TRANSIT_TO_FRONT), any(), eq(null))
    }

@@ -367,8 +373,8 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() {
            BOUNDS,
        )

        assertThat(tilingDecoration.moveTiledPairToFront(task3, isTaskFocused = true)).isFalse()
        assertThat(tilingDecoration.moveTiledPairToFront(task1, isTaskFocused = true)).isTrue()
        assertThat(tilingDecoration.moveTiledPairToFront(task3.taskId, isFocusedOnDisplay = true)).isFalse()
        assertThat(tilingDecoration.moveTiledPairToFront(task1.taskId, isFocusedOnDisplay = true)).isTrue()
        verify(transitions, times(1)).startTransition(eq(TRANSIT_TO_FRONT), any(), eq(null))
    }