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

Commit 8756450d authored by Omar Elmekkawy's avatar Omar Elmekkawy
Browse files

[5/n] Add desktop tiling project skeleton

This CL introduces DesktopTilingDecorViewModel, which manages features requiring
different management for different screens.

This CL also introduces DesktopTilingWindowDecoration, which manages tiling tasks
left and right and initiating the divider resources on a WindowlessWM.

and some helper classes that will help with veiling like TiledTaskHelper
and snap bound calculation helpers.

Flag: com.android.window.flags.enable_tile_resizing
Test: tests are WIP
Bug: 369332590
Change-Id: Id230403818a2261086804fa9125a15d188be20e6
parent 830d7ccf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ public enum DesktopModeFlags {
    ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS(
            Flags::enableCaptionCompatInsetForceConsumptionAlways, true),
    ENABLE_CASCADING_WINDOWS(Flags::enableCascadingWindows, true),
    ENABLE_TILE_RESIZING(Flags::enableTileResizing, true),
    ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY(
            Flags::enableDesktopWindowingWallpaperActivity, true),
    ENABLE_DESKTOP_WINDOWING_MODALS_POLICY(Flags::enableDesktopWindowingModalsPolicy, true),
+27 −3
Original line number Diff line number Diff line
@@ -131,6 +131,7 @@ import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel;
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer;
import com.android.wm.shell.windowdecor.education.DesktopWindowingEducationTooltipController;
import com.android.wm.shell.windowdecor.tiling.DesktopTilingDecorViewModel;

import dagger.Binds;
import dagger.Lazy;
@@ -650,7 +651,8 @@ public abstract class WMShellModule {
            InteractionJankMonitor interactionJankMonitor,
            InputManager inputManager,
            FocusTransitionObserver focusTransitionObserver,
            DesktopModeEventLogger desktopModeEventLogger) {
            DesktopModeEventLogger desktopModeEventLogger,
            DesktopTilingDecorViewModel desktopTilingDecorViewModel) {
        return new DesktopTasksController(context, shellInit, shellCommandHandler, shellController,
                displayController, shellTaskOrganizer, syncQueue, rootTaskDisplayAreaOrganizer,
                dragAndDropController, transitions, keyguardManager,
@@ -662,8 +664,30 @@ public abstract class WMShellModule {
                desktopModeLoggerTransitionObserver, launchAdjacentController,
                recentsTransitionHandler, multiInstanceHelper, mainExecutor, desktopTasksLimiter,
                recentTasksController.orElse(null), interactionJankMonitor, mainHandler,
                inputManager, focusTransitionObserver,
                desktopModeEventLogger);
                inputManager, focusTransitionObserver, desktopModeEventLogger,
                desktopTilingDecorViewModel);
    }

    @WMSingleton
    @Provides
    static DesktopTilingDecorViewModel provideDesktopTilingViewModel(Context context,
            DisplayController displayController,
            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
            SyncTransactionQueue syncQueue,
            Transitions transitions,
            ShellTaskOrganizer shellTaskOrganizer,
            ToggleResizeDesktopTaskTransitionHandler toggleResizeDesktopTaskTransitionHandler,
            ReturnToDragStartAnimator returnToDragStartAnimator) {
        return new DesktopTilingDecorViewModel(
                context,
                displayController,
                rootTaskDisplayAreaOrganizer,
                syncQueue,
                transitions,
                shellTaskOrganizer,
                toggleResizeDesktopTaskTransitionHandler,
                returnToDragStartAnimator
        );
    }

    @WMSingleton
+27 −1
Original line number Diff line number Diff line
@@ -118,6 +118,7 @@ import com.android.wm.shell.transition.FocusTransitionObserver
import com.android.wm.shell.transition.OneShotRemoteHandler
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.transition.Transitions.TransitionFinishCallback
import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration
import com.android.wm.shell.windowdecor.DragPositioningCallbackUtility
import com.android.wm.shell.windowdecor.MoveToDesktopAnimator
import com.android.wm.shell.windowdecor.OnTaskRepositionAnimationListener
@@ -125,6 +126,7 @@ import com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener
import com.android.wm.shell.windowdecor.extension.isFullscreen
import com.android.wm.shell.windowdecor.extension.isMultiWindow
import com.android.wm.shell.windowdecor.extension.requestingImmersive
import com.android.wm.shell.windowdecor.tiling.DesktopTilingDecorViewModel
import java.io.PrintWriter
import java.util.Optional
import java.util.concurrent.Executor
@@ -163,6 +165,7 @@ class DesktopTasksController(
    private val inputManager: InputManager,
    private val focusTransitionObserver: FocusTransitionObserver,
    private val desktopModeEventLogger: DesktopModeEventLogger,
    private val desktopTilingDecorViewModel: DesktopTilingDecorViewModel,
) :
    RemoteCallable<DesktopTasksController>,
    Transitions.TransitionHandler,
@@ -643,6 +646,11 @@ class DesktopTasksController(
    @JvmOverloads
    fun moveTaskToFront(taskInfo: RunningTaskInfo, remoteTransition: RemoteTransition? = null) {
        logV("moveTaskToFront taskId=%s", taskInfo.taskId)
        // If a task is tiled, another task should be brought to foreground with it so let
        // tiling controller handle the request.
        if (desktopTilingDecorViewModel.moveTaskToFrontIfTiled(taskInfo)) {
            return
        }
        val wct = WindowContainerTransaction()
        wct.reorder(taskInfo.token, true /* onTop */, true /* includingParents */)
        val runOnTransit = desktopImmersiveController.exitImmersiveIfApplicable(
@@ -912,7 +920,20 @@ class DesktopTasksController(
        position: SnapPosition,
        resizeTrigger: ResizeTrigger,
        motionEvent: MotionEvent?,
        desktopWindowDecoration: DesktopModeWindowDecoration,
    ) {
        if (DesktopModeFlags.ENABLE_TILE_RESIZING.isTrue()) {
            val isTiled = desktopTilingDecorViewModel.snapToHalfScreen(
                taskInfo,
                desktopWindowDecoration,
                position,
                currentDragBounds,
            )
            if (isTiled) {
                taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate(true)
            }
            return
        }
        val destinationBounds = getSnapBounds(taskInfo, position)
        desktopModeEventLogger.logTaskResizingEnded(
            resizeTrigger,
@@ -932,7 +953,7 @@ class DesktopTasksController(
                    taskSurface,
                    startBounds = currentDragBounds,
                    endBounds = destinationBounds,
                    isResizable = taskInfo.isResizeable
                    isResizable = taskInfo.isResizeable,
                )
            }
            return
@@ -952,6 +973,7 @@ class DesktopTasksController(
        currentDragBounds: Rect,
        dragStartBounds: Rect,
        motionEvent: MotionEvent,
        desktopModeWindowDecoration: DesktopModeWindowDecoration,
    ) {
        releaseVisualIndicator()
        if (!taskInfo.isResizeable && DISABLE_NON_RESIZABLE_APP_SNAP_RESIZE.isTrue()) {
@@ -986,6 +1008,7 @@ class DesktopTasksController(
                position,
                resizeTrigger,
                motionEvent,
                desktopModeWindowDecoration,
            )
        }
    }
@@ -1857,6 +1880,7 @@ class DesktopTasksController(
        validDragArea: Rect,
        dragStartBounds: Rect,
        motionEvent: MotionEvent,
        desktopModeWindowDecoration: DesktopModeWindowDecoration,
    ) {
        if (taskInfo.configuration.windowConfiguration.windowingMode != WINDOWING_MODE_FREEFORM) {
            return
@@ -1883,6 +1907,7 @@ class DesktopTasksController(
                    currentDragBounds,
                    dragStartBounds,
                    motionEvent,
                    desktopModeWindowDecoration,
                )
            }
            IndicatorType.TO_SPLIT_RIGHT_INDICATOR -> {
@@ -1893,6 +1918,7 @@ class DesktopTasksController(
                    currentDragBounds,
                    dragStartBounds,
                    motionEvent,
                    desktopModeWindowDecoration,
                )
            }
            IndicatorType.NO_INDICATOR -> {
+4 −2
Original line number Diff line number Diff line
@@ -604,7 +604,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                    decoration.mTaskInfo.configuration.windowConfiguration.getBounds(),
                    left ? SnapPosition.LEFT : SnapPosition.RIGHT,
                    resizeTrigger,
                    motionEvent);
                    motionEvent,
                    mWindowDecorByTaskId.get(taskId));
        }

        decoration.closeHandleMenu();
@@ -1063,7 +1064,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                            taskInfo, decoration.mTaskSurface, position,
                            new PointF(e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx)),
                            newTaskBounds, decoration.calculateValidDragArea(),
                            new Rect(mOnDragStartInitialBounds), e);
                            new Rect(mOnDragStartInitialBounds), e,
                            mWindowDecorByTaskId.get(taskInfo.taskId));
                    if (touchingButton && !mHasLongClicked) {
                        // We need the input event to not be consumed here to end the ripple
                        // effect on the touched button. We will reset drag state in the ensuing
+21 −5
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ import androidx.annotation.Nullable;
 *
 * All touch events must be passed through this class to track a drag event.
 */
class DragDetector {
public class DragDetector {
    private final MotionEventHandler mEventHandler;

    private final PointF mInputDownPoint = new PointF();
@@ -55,7 +55,14 @@ class DragDetector {

    private boolean mResultOfDownAction;

    DragDetector(@NonNull MotionEventHandler eventHandler, long holdToDragMinDurationMs,
    /**
     * Initialises a drag detector.
     *
     * @param eventHandler drag event handler.
     * @param holdToDragMinDurationMs hold to drag duration.
     * @param touchSlop touch slope threshold.
     */
    public DragDetector(@NonNull MotionEventHandler eventHandler, long holdToDragMinDurationMs,
            int touchSlop) {
        resetState();
        mEventHandler = eventHandler;
@@ -69,7 +76,7 @@ class DragDetector {
     * @return the result returned by {@link #mEventHandler}, or the result when
     * {@link #mEventHandler} handles the previous down event if the event shouldn't be passed
     */
    boolean onMotionEvent(MotionEvent ev) {
    public boolean onMotionEvent(MotionEvent ev) {
        return onMotionEvent(null /* view */, ev);
    }

@@ -79,7 +86,7 @@ class DragDetector {
     * @return the result returned by {@link #mEventHandler}, or the result when
     * {@link #mEventHandler} handles the previous down event if the event shouldn't be passed
     */
    boolean onMotionEvent(View v, MotionEvent ev) {
    public boolean onMotionEvent(View v, MotionEvent ev) {
        final boolean isTouchScreen =
                (ev.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN;
        if (!isTouchScreen) {
@@ -190,7 +197,16 @@ class DragDetector {
        mDidHoldForMinDuration = false;
    }

    interface MotionEventHandler {
    /**
     * Interface to be implemented by the class using the DragDetector for callback.
     */
    public interface MotionEventHandler {
        /**
         * Called back when drag is detected to notify the implementing class to handle drag events.
         * @param v view on which the input arrived.
         * @param ev motion event that resulted in drag.
         * @return whether this was a drag event or not.
         */
        boolean handleMotionEvent(@Nullable View v, MotionEvent ev);
    }
}
 No newline at end of file
Loading