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

Commit 5699a18f authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add config to change drag-to-top-edge behavior" into main

parents 2a338986 5dd7500a
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -7143,6 +7143,10 @@
         root TaskDisplayArea is set to WINDOWING_MODE_FREEFORM. -->
    <bool name="config_enterDesktopByDefaultOnFreeformDisplay">false</bool>

    <!-- Whether a desktop window should be maximized when it's dragged to the top edge of the
         screen. -->
    <bool name="config_dragToMaximizeInDesktopMode">false</bool>

    <!-- Frame rate compatibility value for Wallpaper
         FRAME_RATE_COMPATIBILITY_MIN (102) is used by default for lower power consumption -->
    <integer name="config_wallpaperFrameRateCompatibility">102</integer>
+4 −0
Original line number Diff line number Diff line
@@ -5577,6 +5577,10 @@
       root TaskDisplayArea is set to WINDOWING_MODE_FREEFORM. -->
  <java-symbol type="bool" name="config_enterDesktopByDefaultOnFreeformDisplay" />

  <!-- Whether a desktop window should be maximized when it's dragged to the top edge of the
       screen. -->
  <java-symbol type="bool" name="config_dragToMaximizeInDesktopMode" />

  <!-- Frame rate compatibility value for Wallpaper -->
  <java-symbol type="integer" name="config_wallpaperFrameRateCompatibility" />

+21 −0
Original line number Diff line number Diff line
@@ -101,6 +101,15 @@ public class DesktopModeStatus {
    public static final String ENTER_DESKTOP_BY_DEFAULT_ON_FREEFORM_DISPLAY_SYS_PROP =
            "persist.wm.debug.enter_desktop_by_default_on_freeform_display";

    /**
     * Sysprop declaring whether to enable drag-to-maximize for desktop windows.
     *
     * <p>If it is not defined, then {@code R.integer.config_dragToMaximizeInDesktopMode}
     * is used.
     */
    public static final String ENABLE_DRAG_TO_MAXIMIZE_SYS_PROP =
            "persist.wm.debug.enable_drag_to_maximize";

    /**
     * Sysprop declaring the maximum number of Tasks to show in Desktop Mode at any one time.
     *
@@ -230,6 +239,18 @@ public class DesktopModeStatus {
                        R.bool.config_enterDesktopByDefaultOnFreeformDisplay));
    }

    /**
     * Return {@code true} if a window should be maximized when it's dragged to the top edge of the
     * screen.
     */
    public static boolean shouldMaximizeWhenDragToTopEdge(@NonNull Context context) {
        if (!Flags.enableDragToMaximize()) {
            return false;
        }
        return SystemProperties.getBoolean(ENABLE_DRAG_TO_MAXIMIZE_SYS_PROP,
                context.getResources().getBoolean(R.bool.config_dragToMaximizeInDesktopMode));
    }

    /** Dumps DesktopModeStatus flags and configs. */
    public static void dump(PrintWriter pw, String prefix, Context context) {
        String innerPrefix = prefix + "  ";
+42 −5
Original line number Diff line number Diff line
@@ -857,6 +857,39 @@ class DesktopTasksController(
        toggleResizeDesktopTaskTransitionHandler.startTransition(wct)
    }

    private fun dragToMaximizeDesktopTask(
        taskInfo: RunningTaskInfo,
        taskSurface: SurfaceControl,
        currentDragBounds: Rect,
        motionEvent: MotionEvent
    ) {
        val displayLayout = displayController.getDisplayLayout(taskInfo.displayId) ?: return
        val stableBounds = Rect()
        displayLayout.getStableBounds(stableBounds)
        if (isTaskMaximized(taskInfo, stableBounds)) {
            // Handle the case where we attempt to drag-to-maximize when already maximized: the task
            // position won't need to change but we want to animate the surface going back to the
            // maximized position.
            val containerBounds = taskInfo.configuration.windowConfiguration.bounds
            if (containerBounds != currentDragBounds) {
                returnToDragStartAnimator.start(
                    taskInfo.taskId,
                    taskSurface,
                    startBounds = currentDragBounds,
                    endBounds = containerBounds,
                    isResizable = taskInfo.isResizeable
                )
            }
            return
        }

        // TODO(b/375356605): Introduce a new ResizeTrigger for drag-to-top.
        desktopModeEventLogger.logTaskResizingStarted(
            ResizeTrigger.UNKNOWN_RESIZE_TRIGGER, motionEvent, taskInfo, displayController
        )
        toggleDesktopTaskSize(taskInfo, ResizeTrigger.UNKNOWN_RESIZE_TRIGGER, motionEvent)
    }

    private fun getMaximizeBounds(taskInfo: RunningTaskInfo, stableBounds: Rect): Rect {
        if (taskInfo.isResizeable) {
            // if resizable then expand to entire stable bounds (full display minus insets)
@@ -1918,12 +1951,16 @@ class DesktopTasksController(
            )
        when (indicatorType) {
            IndicatorType.TO_FULLSCREEN_INDICATOR -> {
                if (DesktopModeStatus.shouldMaximizeWhenDragToTopEdge(context)) {
                    dragToMaximizeDesktopTask(taskInfo, taskSurface, currentDragBounds, motionEvent)
                } else {
                    moveToFullscreenWithAnimation(
                        taskInfo,
                        position,
                        DesktopModeTransitionSource.TASK_DRAG
                    )
                }
            }
            IndicatorType.TO_SPLIT_LEFT_INDICATOR -> {
                handleSnapResizingTask(
                    taskInfo,
+117 −0
Original line number Diff line number Diff line
@@ -2913,6 +2913,123 @@ class DesktopTasksControllerTest : ShellTestCase() {
        eq(null))
  }

  @Test
  fun onDesktopDragEnd_fullscreenIndicator_dragToExitDesktop() {
    val task = setUpFreeformTask(bounds = Rect(0, 0, 100, 100))
    val spyController = spy(controller)
    val mockSurface = mock(SurfaceControl::class.java)
    val mockDisplayLayout = mock(DisplayLayout::class.java)
    val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!!
    tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN
    whenever(displayController.getDisplayLayout(task.displayId)).thenReturn(mockDisplayLayout)
    whenever(mockDisplayLayout.stableInsets()).thenReturn(Rect(0, 100, 2000, 2000))
    whenever(mockDisplayLayout.getStableBounds(any())).thenAnswer { i ->
      (i.arguments.first() as Rect).set(STABLE_BOUNDS)
    }
    whenever(DesktopModeStatus.shouldMaximizeWhenDragToTopEdge(context)).thenReturn(false)
    whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator)
    whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull()))
      .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR)

    // Drag move the task to the top edge
    spyController.onDragPositioningMove(task, mockSurface, 200f, Rect(100, 200, 500, 1000))
    spyController.onDragPositioningEnd(
      task,
      mockSurface,
      Point(100, 50), /* position */
      PointF(200f, 300f), /* inputCoordinate */
      Rect(100, 50, 500, 1000), /* currentDragBounds */
      Rect(0, 50, 2000, 2000) /* validDragArea */,
      Rect() /* dragStartBounds */,
      motionEvent,
      desktopWindowDecoration)

    // Assert the task exits desktop mode
    val wct = getLatestExitDesktopWct()
    assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
        .isEqualTo(WINDOWING_MODE_UNDEFINED)
  }

  @Test
  fun onDesktopDragEnd_fullscreenIndicator_dragToMaximize() {
    val task = setUpFreeformTask(bounds = Rect(0, 0, 100, 100))
    val spyController = spy(controller)
    val mockSurface = mock(SurfaceControl::class.java)
    val mockDisplayLayout = mock(DisplayLayout::class.java)
    val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!!
    tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN
    whenever(displayController.getDisplayLayout(task.displayId)).thenReturn(mockDisplayLayout)
    whenever(mockDisplayLayout.stableInsets()).thenReturn(Rect(0, 100, 2000, 2000))
    whenever(mockDisplayLayout.getStableBounds(any())).thenAnswer { i ->
      (i.arguments.first() as Rect).set(STABLE_BOUNDS)
    }
    whenever(DesktopModeStatus.shouldMaximizeWhenDragToTopEdge(context)).thenReturn(true)
    whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator)
    whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull()))
      .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR)

    // Drag move the task to the top edge
    spyController.onDragPositioningMove(task, mockSurface, 200f, Rect(100, 200, 500, 1000))
    spyController.onDragPositioningEnd(
      task,
      mockSurface,
      Point(100, 50), /* position */
      PointF(200f, 300f), /* inputCoordinate */
      Rect(100, 50, 500, 1000), /* currentDragBounds */
      Rect(0, 50, 2000, 2000) /* validDragArea */,
      Rect() /* dragStartBounds */,
      motionEvent,
      desktopWindowDecoration)

    // Assert bounds set to stable bounds
    val wct = getLatestToggleResizeDesktopTaskWct()
    assertThat(findBoundsChange(wct, task)).isEqualTo(STABLE_BOUNDS)
  }

  @Test
  fun onDesktopDragEnd_fullscreenIndicator_dragToMaximize_noBoundsChange() {
    val task = setUpFreeformTask(bounds = STABLE_BOUNDS)
    val spyController = spy(controller)
    val mockSurface = mock(SurfaceControl::class.java)
    val mockDisplayLayout = mock(DisplayLayout::class.java)
    val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!!
    tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN
    whenever(displayController.getDisplayLayout(task.displayId)).thenReturn(mockDisplayLayout)
    whenever(mockDisplayLayout.stableInsets()).thenReturn(Rect(0, 100, 2000, 2000))
    whenever(mockDisplayLayout.getStableBounds(any())).thenAnswer { i ->
      (i.arguments.first() as Rect).set(STABLE_BOUNDS)
    }
    whenever(DesktopModeStatus.shouldMaximizeWhenDragToTopEdge(context)).thenReturn(true)
    whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator)
    whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull()))
      .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR)

    // Drag move the task to the top edge
    val currentDragBounds = Rect(100, 50, 500, 1000)
    spyController.onDragPositioningMove(task, mockSurface, 200f, Rect(100, 200, 500, 1000))
    spyController.onDragPositioningEnd(
      task,
      mockSurface,
      Point(100, 50), /* position */
      PointF(200f, 300f), /* inputCoordinate */
      currentDragBounds, /* currentDragBounds */
      Rect(0, 50, 2000, 2000) /* validDragArea */,
      Rect() /* dragStartBounds */,
      motionEvent,
      desktopWindowDecoration)

    // Assert that task is NOT updated via WCT
    verify(toggleResizeDesktopTaskTransitionHandler, never()).startTransition(any(), any())
    // Assert that task leash is updated via Surface Animations
    verify(mReturnToDragStartAnimator).start(
      eq(task.taskId),
      eq(mockSurface),
      eq(currentDragBounds),
      eq(STABLE_BOUNDS),
      eq(true)
    )
  }

  @Test
  fun enterSplit_freeformTaskIsMovedToSplit() {
    val task1 = setUpFreeformTask()