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

Commit d1c47031 authored by Daniel Akinola's avatar Daniel Akinola Committed by Android (Google) Code Review
Browse files

Merge "[2/n] Disable snap resizing non-resizable apps" into main

parents 59dda3d6 8fc0be79
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -30,6 +30,13 @@ flag {
    bug: "324377962"
}

flag {
    name: "disable_non_resizable_app_snap_resizing"
    namespace: "lse_desktop_experience"
    description: "Stops non-resizable app desktop windows from being snap resized"
    bug: "325240072"
}

flag {
    name: "enable_desktop_windowing_task_limit"
    namespace: "lse_desktop_experience"
+1 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ enum class DesktopModeFlags(
    APP_HEADER_WITH_TASK_DENSITY(Flags::enableAppHeaderWithTaskDensity, true),
    TASK_STACK_OBSERVER_IN_SHELL(Flags::enableTaskStackObserverInShell, true),
    SIZE_CONSTRAINTS(Flags::enableDesktopWindowingSizeConstraints, true),
    DISABLE_SNAP_RESIZE(Flags::disableNonResizableAppSnapResizing, true),
    DYNAMIC_INITIAL_BOUNDS(Flags::enableWindowingDynamicInitialBounds, true),
    ENABLE_DESKTOP_WINDOWING_TASK_LIMIT(Flags::enableDesktopWindowingTaskLimit, true),
    BACK_NAVIGATION(Flags::enableDesktopWindowingBackNavigation, true),
+13 −4
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ import com.android.wm.shell.desktopmode.DesktopTasksTransitionObserver;
import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler;
import com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler;
import com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler;
import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator;
import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.draganddrop.GlobalDragListener;
@@ -538,6 +539,7 @@ public abstract class WMShellModule {
            DragAndDropController dragAndDropController,
            Transitions transitions,
            KeyguardManager keyguardManager,
            ReturnToDragStartAnimator returnToDragStartAnimator,
            EnterDesktopTaskTransitionHandler enterDesktopTransitionHandler,
            ExitDesktopTaskTransitionHandler exitDesktopTransitionHandler,
            ToggleResizeDesktopTaskTransitionHandler toggleResizeDesktopTaskTransitionHandler,
@@ -553,13 +555,13 @@ public abstract class WMShellModule {
            InteractionJankMonitor interactionJankMonitor) {
        return new DesktopTasksController(context, shellInit, shellCommandHandler, shellController,
                displayController, shellTaskOrganizer, syncQueue, rootTaskDisplayAreaOrganizer,
                dragAndDropController, transitions, keyguardManager, enterDesktopTransitionHandler,
                dragAndDropController, transitions, keyguardManager,
                returnToDragStartAnimator, enterDesktopTransitionHandler,
                exitDesktopTransitionHandler, toggleResizeDesktopTaskTransitionHandler,
                dragToDesktopTransitionHandler, desktopModeTaskRepository,
                desktopModeLoggerTransitionObserver, launchAdjacentController,
                recentsTransitionHandler, multiInstanceHelper,
                mainExecutor, desktopTasksLimiter, recentTasksController.orElse(null),
                interactionJankMonitor);
                recentsTransitionHandler, multiInstanceHelper, mainExecutor, desktopTasksLimiter,
                recentTasksController.orElse(null), interactionJankMonitor);
    }

    @WMSingleton
@@ -587,6 +589,13 @@ public abstract class WMShellModule {
        );
    }

    @WMSingleton
    @Provides
    static ReturnToDragStartAnimator provideReturnToDragStartAnimator(
            InteractionJankMonitor interactionJankMonitor) {
        return new ReturnToDragStartAnimator(interactionJankMonitor);
    }


    @WMSingleton
    @Provides
+45 −9
Original line number Diff line number Diff line
@@ -66,7 +66,6 @@ import com.android.wm.shell.common.RemoteCallable
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.common.SingleInstanceRemoteListener
import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.shared.desktopmode.DesktopModeFlags.WALLPAPER_ACTIVITY
import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource
import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT
import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT
@@ -79,13 +78,14 @@ import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
import com.android.wm.shell.recents.RecentTasksController
import com.android.wm.shell.recents.RecentsTransitionHandler
import com.android.wm.shell.recents.RecentsTransitionStateListener
import com.android.wm.shell.shared.TransitionUtil
import com.android.wm.shell.shared.annotations.ExternalThread
import com.android.wm.shell.shared.annotations.ShellMainThread
import com.android.wm.shell.shared.desktopmode.DesktopModeFlags
import com.android.wm.shell.shared.desktopmode.DesktopModeFlags.WALLPAPER_ACTIVITY
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.DESKTOP_DENSITY_OVERRIDE
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.useDesktopOverrideDensity
import com.android.wm.shell.shared.TransitionUtil
import com.android.wm.shell.shared.annotations.ExternalThread
import com.android.wm.shell.shared.annotations.ShellMainThread
import com.android.wm.shell.splitscreen.SplitScreenController
import com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DESKTOP_MODE
import com.android.wm.shell.sysui.ShellCommandHandler
@@ -96,6 +96,7 @@ import com.android.wm.shell.transition.OneShotRemoteHandler
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.windowdecor.DragPositioningCallbackUtility
import com.android.wm.shell.windowdecor.MoveToDesktopAnimator
import com.android.wm.shell.windowdecor.OnTaskRepositionAnimationListener
import com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener
import com.android.wm.shell.windowdecor.extension.isFullscreen
import com.android.wm.shell.windowdecor.extension.isMultiWindow
@@ -117,6 +118,7 @@ class DesktopTasksController(
    private val dragAndDropController: DragAndDropController,
    private val transitions: Transitions,
    private val keyguardManager: KeyguardManager,
    private val returnToDragStartAnimator: ReturnToDragStartAnimator,
    private val enterDesktopTaskTransitionHandler: EnterDesktopTaskTransitionHandler,
    private val exitDesktopTaskTransitionHandler: ExitDesktopTaskTransitionHandler,
    private val toggleResizeDesktopTaskTransitionHandler: ToggleResizeDesktopTaskTransitionHandler,
@@ -214,6 +216,10 @@ class DesktopTasksController(
        dragToDesktopTransitionHandler.setOnTaskResizeAnimatorListener(listener)
    }

    fun setOnTaskRepositionAnimationListener(listener: OnTaskRepositionAnimationListener) {
        returnToDragStartAnimator.setTaskRepositionAnimationListener(listener)
    }

    /** Setter needed to avoid cyclic dependency. */
    fun setSplitScreenController(controller: SplitScreenController) {
        splitScreenController = controller
@@ -661,6 +667,28 @@ class DesktopTasksController(
        }
    }

    @VisibleForTesting
    fun handleSnapResizingTask(
        taskInfo: RunningTaskInfo,
        position: SnapPosition,
        taskSurface: SurfaceControl,
        currentDragBounds: Rect,
        dragStartBounds: Rect
    ) {
        releaseVisualIndicator()
        if (!taskInfo.isResizeable && DesktopModeFlags.DISABLE_SNAP_RESIZE.isEnabled(context)) {
            // reposition non-resizable app back to its original position before being dragged
            returnToDragStartAnimator.start(
                taskInfo.taskId,
                taskSurface,
                startBounds = currentDragBounds,
                endBounds = dragStartBounds
            )
        } else {
            snapToHalfScreen(taskInfo, currentDragBounds, position)
        }
    }

    private fun getDefaultDesktopTaskBounds(displayLayout: DisplayLayout): Rect {
        // TODO(b/319819547): Account for app constraints so apps do not become letterboxed
        val desiredWidth = (displayLayout.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE).toInt()
@@ -1293,18 +1321,22 @@ class DesktopTasksController(
     * that change. Otherwise, ensure bounds are up to date.
     *
     * @param taskInfo the task being dragged.
     * @param taskSurface the leash of the task being dragged.
     * @param position position of surface when drag ends.
     * @param inputCoordinate the coordinates of the motion event
     * @param currentDragBounds the current bounds of where the visible task is (might be actual
     *                          task bounds or just task leash)
     * @param validDragArea the bounds of where the task can be dragged within the display.
     * @param dragStartBounds the bounds of the task before starting dragging.
     */
    fun onDragPositioningEnd(
        taskInfo: RunningTaskInfo,
        taskSurface: SurfaceControl,
        position: Point,
        inputCoordinate: PointF,
        currentDragBounds: Rect,
        validDragArea: Rect
        validDragArea: Rect,
        dragStartBounds: Rect,
    ) {
        if (taskInfo.configuration.windowConfiguration.windowingMode != WINDOWING_MODE_FREEFORM) {
            return
@@ -1325,12 +1357,14 @@ class DesktopTasksController(
                )
            }
            IndicatorType.TO_SPLIT_LEFT_INDICATOR -> {
                releaseVisualIndicator()
                snapToHalfScreen(taskInfo, currentDragBounds, SnapPosition.LEFT)
                handleSnapResizingTask(
                    taskInfo, SnapPosition.LEFT, taskSurface, currentDragBounds, dragStartBounds
                )
            }
            IndicatorType.TO_SPLIT_RIGHT_INDICATOR -> {
                releaseVisualIndicator()
                snapToHalfScreen(taskInfo, currentDragBounds, SnapPosition.RIGHT)
                handleSnapResizingTask(
                    taskInfo, SnapPosition.RIGHT, taskSurface, currentDragBounds, dragStartBounds
                )
            }
            IndicatorType.NO_INDICATOR -> {
                // If task bounds are outside valid drag area, snap them inward
@@ -1339,6 +1373,8 @@ class DesktopTasksController(
                    validDragArea
                )

                if (currentDragBounds == dragStartBounds) return

                // Update task bounds so that the task position will match the position of its leash
                val wct = WindowContainerTransaction()
                wct.setBounds(taskInfo.token, currentDragBounds)
+96 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.wm.shell.desktopmode

import android.animation.Animator
import android.animation.RectEvaluator
import android.animation.ValueAnimator
import android.graphics.Rect
import android.view.SurfaceControl
import androidx.core.animation.addListener
import com.android.internal.jank.InteractionJankMonitor
import com.android.wm.shell.windowdecor.OnTaskRepositionAnimationListener
import java.util.function.Supplier

/** Animates the task surface moving from its current drag position to its pre-drag position. */
class ReturnToDragStartAnimator(
    private val transactionSupplier: Supplier<SurfaceControl.Transaction>,
    private val interactionJankMonitor: InteractionJankMonitor
) {
    private var boundsAnimator: Animator? = null
    private lateinit var taskRepositionAnimationListener: OnTaskRepositionAnimationListener

    constructor(interactionJankMonitor: InteractionJankMonitor) :
            this(Supplier { SurfaceControl.Transaction() }, interactionJankMonitor)

    /** Sets a listener for the start and end of the reposition animation. */
    fun setTaskRepositionAnimationListener(listener: OnTaskRepositionAnimationListener) {
        taskRepositionAnimationListener = listener
    }

    /** Builds new animator and starts animation of task leash reposition. */
    fun start(taskId: Int, taskSurface: SurfaceControl, startBounds: Rect, endBounds: Rect) {
        val tx = transactionSupplier.get()

        boundsAnimator?.cancel()
        boundsAnimator =
            ValueAnimator.ofObject(RectEvaluator(), startBounds, endBounds)
                .setDuration(RETURN_TO_DRAG_START_ANIMATION_MS)
                .apply {
                    addListener(
                        onStart = {
                            val startTransaction = transactionSupplier.get()
                            startTransaction
                                .setPosition(
                                    taskSurface,
                                    startBounds.left.toFloat(),
                                    startBounds.top.toFloat()
                                )
                                .show(taskSurface)
                                .apply()
                            taskRepositionAnimationListener.onAnimationStart(taskId)
                        },
                        onEnd = {
                            val finishTransaction = transactionSupplier.get()
                            finishTransaction
                                .setPosition(
                                    taskSurface,
                                    endBounds.left.toFloat(),
                                    endBounds.top.toFloat()
                                )
                                .show(taskSurface)
                                .apply()
                            taskRepositionAnimationListener.onAnimationEnd(taskId)
                            boundsAnimator = null
                            // TODO(b/354658237) - show toast with relevant string
                            // TODO(b/339582583) - add Jank CUJ using interactionJankMonitor
                        }
                    )
                    addUpdateListener { anim ->
                        val rect = anim.animatedValue as Rect
                        tx.setPosition(taskSurface, rect.left.toFloat(), rect.top.toFloat())
                            .show(taskSurface)
                            .apply()
                    }
                }
                .also(ValueAnimator::start)
    }

    companion object {
        const val RETURN_TO_DRAG_START_ANIMATION_MS = 300L
    }
}
 No newline at end of file
Loading