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

Commit 7d34fb1a authored by Matt Sziklay's avatar Matt Sziklay Committed by Automerger Merge Worker
Browse files

Merge "Open correct handle menu when clicked in split screen." into tm-qpr-dev...

Merge "Open correct handle menu when clicked in split screen." into tm-qpr-dev am: fc2551e5 am: 339d4ee8

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21554218



Change-Id: I76829dd5e5275d300864a2e8eaa29fca686b1ece
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 6936080c 339d4ee8
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -196,7 +196,8 @@ public abstract class WMShellModule {
            DisplayController displayController,
            SyncTransactionQueue syncQueue,
            Optional<DesktopModeController> desktopModeController,
            Optional<DesktopTasksController> desktopTasksController) {
            Optional<DesktopTasksController> desktopTasksController,
            Optional<SplitScreenController> splitScreenController) {
        if (DesktopModeStatus.isAnyEnabled()) {
            return new DesktopModeWindowDecorViewModel(
                    context,
@@ -206,7 +207,8 @@ public abstract class WMShellModule {
                    displayController,
                    syncQueue,
                    desktopModeController,
                    desktopTasksController);
                    desktopTasksController,
                    splitScreenController);
        }
        return new CaptionWindowDecorViewModel(
                    context,
+5 −0
Original line number Diff line number Diff line
@@ -422,6 +422,11 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
        mStageCoordinator.goToFullscreenFromSplit();
    }

    /** Move the specified task to fullscreen, regardless of focus state. */
    public void moveTaskToFullscreen(int taskId) {
        mStageCoordinator.moveTaskToFullscreen(taskId);
    }

    public boolean isLaunchToSplit(TaskInfo taskInfo) {
        return mStageCoordinator.isLaunchToSplit(taskInfo);
    }
+14 −0
Original line number Diff line number Diff line
@@ -2406,6 +2406,20 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        mSplitLayout.flingDividerToDismiss(!leftOrTop, EXIT_REASON_FULLSCREEN_SHORTCUT);
    }

    /** Move the specified task to fullscreen, regardless of focus state. */
    public void moveTaskToFullscreen(int taskId) {
        boolean leftOrTop;
        if (mMainStage.containsTask(taskId)) {
            leftOrTop = (mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT);
        } else if (mSideStage.containsTask(taskId)) {
            leftOrTop = (mSideStagePosition == SPLIT_POSITION_BOTTOM_OR_RIGHT);
        } else {
            return;
        }
        mSplitLayout.flingDividerToDismiss(!leftOrTop, EXIT_REASON_FULLSCREEN_SHORTCUT);

    }

    boolean isLaunchToSplit(TaskInfo taskInfo) {
        return getActivateSplitPosition(taskInfo) != SPLIT_POSITION_UNDEFINED;
    }
+71 −24
Original line number Diff line number Diff line
@@ -20,10 +20,14 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;

import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
import android.content.Context;
import android.graphics.Rect;
import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.Looper;
@@ -37,7 +41,6 @@ import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.View;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;

import androidx.annotation.Nullable;

@@ -50,6 +53,7 @@ import com.android.wm.shell.desktopmode.DesktopModeController;
import com.android.wm.shell.desktopmode.DesktopModeStatus;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
import com.android.wm.shell.splitscreen.SplitScreenController;

import java.util.Optional;

@@ -80,6 +84,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
    private final InputMonitorFactory mInputMonitorFactory;
    private TaskOperations mTaskOperations;

    private Optional<SplitScreenController> mSplitScreenController;

    public DesktopModeWindowDecorViewModel(
            Context context,
            Handler mainHandler,
@@ -88,7 +94,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
            DisplayController displayController,
            SyncTransactionQueue syncQueue,
            Optional<DesktopModeController> desktopModeController,
            Optional<DesktopTasksController> desktopTasksController) {
            Optional<DesktopTasksController> desktopTasksController,
            Optional<SplitScreenController> splitScreenController) {
        this(
                context,
                mainHandler,
@@ -98,6 +105,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                syncQueue,
                desktopModeController,
                desktopTasksController,
                splitScreenController,
                new DesktopModeWindowDecoration.Factory(),
                new InputMonitorFactory());
    }
@@ -112,6 +120,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
            SyncTransactionQueue syncQueue,
            Optional<DesktopModeController> desktopModeController,
            Optional<DesktopTasksController> desktopTasksController,
            Optional<SplitScreenController> splitScreenController,
            DesktopModeWindowDecoration.Factory desktopModeWindowDecorFactory,
            InputMonitorFactory inputMonitorFactory) {
        mContext = context;
@@ -120,6 +129,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
        mActivityTaskManager = mContext.getSystemService(ActivityTaskManager.class);
        mTaskOrganizer = taskOrganizer;
        mDisplayController = displayController;
        mSplitScreenController = splitScreenController;
        mSyncQueue = syncQueue;
        mDesktopModeController = desktopModeController;
        mDesktopTasksController = desktopTasksController;
@@ -230,6 +240,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
            final int id = v.getId();
            if (id == R.id.close_window || id == R.id.close_button) {
                mTaskOperations.closeTask(mTaskToken);
                if (mSplitScreenController.isPresent()
                        && mSplitScreenController.get().isSplitScreenVisible()) {
                    int remainingTaskPosition = mTaskId == mSplitScreenController.get()
                            .getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT).taskId
                            ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT;
                    ActivityManager.RunningTaskInfo remainingTask = mSplitScreenController.get()
                            .getTaskInfo(remainingTaskPosition);
                    mSplitScreenController.get().moveTaskToFullscreen(remainingTask.taskId);
                }
            } else if (id == R.id.back_button) {
                mTaskOperations.injectBackKey();
            } else if (id == R.id.caption_handle) {
@@ -261,9 +280,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                    if (taskInfo.isFocused) {
                        return mDragDetector.isDragEvent();
                    }
                    final WindowContainerTransaction wct = new WindowContainerTransaction();
                    wct.reorder(mTaskToken, true /* onTop */);
                    mSyncQueue.queue(wct);
                    return false;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
@@ -401,14 +417,14 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
     * @param ev the {@link MotionEvent} received by {@link EventReceiver}
     */
    private void handleReceivedMotionEvent(MotionEvent ev, InputMonitor inputMonitor) {
        final DesktopModeWindowDecoration relevantDecor = getRelevantWindowDecor(ev);
        if (DesktopModeStatus.isProto2Enabled()) {
            final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
            if (focusedDecor == null
                    || focusedDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
                handleCaptionThroughStatusBar(ev);
            if (relevantDecor == null
                    || relevantDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
                handleCaptionThroughStatusBar(ev, relevantDecor);
            }
        }
        handleEventOutsideFocusedCaption(ev);
        handleEventOutsideFocusedCaption(ev, relevantDecor);
        // Prevent status bar from reacting to a caption drag.
        if (DesktopModeStatus.isProto2Enabled()) {
            if (mTransitionDragActive) {
@@ -422,16 +438,16 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
    }

    // If an UP/CANCEL action is received outside of caption bounds, turn off handle menu
    private void handleEventOutsideFocusedCaption(MotionEvent ev) {
    private void handleEventOutsideFocusedCaption(MotionEvent ev,
            DesktopModeWindowDecoration relevantDecor) {
        final int action = ev.getActionMasked();
        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
            final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
            if (focusedDecor == null) {
            if (relevantDecor == null) {
                return;
            }

            if (!mTransitionDragActive) {
                focusedDecor.closeHandleMenuIfNeeded(ev);
                relevantDecor.closeHandleMenuIfNeeded(ev);
            }
        }
    }
@@ -441,39 +457,38 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
     * Perform caption actions if not able to through normal means.
     * Turn on desktop mode if handle is dragged below status bar.
     */
    private void handleCaptionThroughStatusBar(MotionEvent ev) {
    private void handleCaptionThroughStatusBar(MotionEvent ev,
            DesktopModeWindowDecoration relevantDecor) {
        switch (ev.getActionMasked()) {
            case MotionEvent.ACTION_DOWN: {
                // Begin drag through status bar if applicable.
                final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
                if (focusedDecor != null) {
                if (relevantDecor != null) {
                    boolean dragFromStatusBarAllowed = false;
                    if (DesktopModeStatus.isProto2Enabled()) {
                        // In proto2 any full screen task can be dragged to freeform
                        dragFromStatusBarAllowed = focusedDecor.mTaskInfo.getWindowingMode()
                        dragFromStatusBarAllowed = relevantDecor.mTaskInfo.getWindowingMode()
                                == WINDOWING_MODE_FULLSCREEN;
                    }

                    if (dragFromStatusBarAllowed && focusedDecor.checkTouchEventInHandle(ev)) {
                    if (dragFromStatusBarAllowed && relevantDecor.checkTouchEventInHandle(ev)) {
                        mTransitionDragActive = true;
                    }
                }
                break;
            }
            case MotionEvent.ACTION_UP: {
                final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
                if (focusedDecor == null) {
                if (relevantDecor == null) {
                    mTransitionDragActive = false;
                    return;
                }
                if (mTransitionDragActive) {
                    mTransitionDragActive = false;
                    final int statusBarHeight = mDisplayController
                            .getDisplayLayout(focusedDecor.mTaskInfo.displayId).stableInsets().top;
                            .getDisplayLayout(relevantDecor.mTaskInfo.displayId).stableInsets().top;
                    if (ev.getY() > statusBarHeight) {
                        if (DesktopModeStatus.isProto2Enabled()) {
                            mDesktopTasksController.ifPresent(
                                    c -> c.moveToDesktop(focusedDecor.mTaskInfo));
                                    c -> c.moveToDesktop(relevantDecor.mTaskInfo));
                        } else if (DesktopModeStatus.isProto1Enabled()) {
                            mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(true));
                        }
@@ -481,7 +496,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                        return;
                    }
                }
                focusedDecor.checkClickEvent(ev);
                relevantDecor.checkClickEvent(ev);
                break;
            }
            case MotionEvent.ACTION_CANCEL: {
@@ -490,6 +505,38 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
        }
    }

    @Nullable
    private DesktopModeWindowDecoration getRelevantWindowDecor(MotionEvent ev) {
        if (mSplitScreenController.isPresent()
                && mSplitScreenController.get().isSplitScreenVisible()) {
            // We can't look at focused task here as only one task will have focus.
            return getSplitScreenDecor(ev);
        } else {
            return getFocusedDecor();
        }
    }

    @Nullable
    private DesktopModeWindowDecoration getSplitScreenDecor(MotionEvent ev) {
        ActivityManager.RunningTaskInfo topOrLeftTask =
                mSplitScreenController.get().getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT);
        ActivityManager.RunningTaskInfo bottomOrRightTask =
                mSplitScreenController.get().getTaskInfo(SPLIT_POSITION_BOTTOM_OR_RIGHT);
        if (topOrLeftTask != null && topOrLeftTask.getConfiguration()
                .windowConfiguration.getBounds().contains((int) ev.getX(), (int) ev.getY())) {
            return mWindowDecorByTaskId.get(topOrLeftTask.taskId);
        } else if (bottomOrRightTask != null && bottomOrRightTask.getConfiguration()
                .windowConfiguration.getBounds().contains((int) ev.getX(), (int) ev.getY())) {
            Rect bottomOrRightBounds = bottomOrRightTask.getConfiguration().windowConfiguration
                    .getBounds();
            ev.offsetLocation(-bottomOrRightBounds.left, -bottomOrRightBounds.top);
            return mWindowDecorByTaskId.get(bottomOrRightTask.taskId);
        } else {
            return null;
        }

    }

    @Nullable
    private DesktopModeWindowDecoration getFocusedDecor() {
        final int size = mWindowDecorByTaskId.size();
+3 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.desktopmode.DesktopModeController;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.splitscreen.SplitScreenController;

import org.junit.Before;
import org.junit.Test;
@@ -73,6 +74,7 @@ public class DesktopModeWindowDecorViewModelTests extends ShellTestCase {
    @Mock private Choreographer mMainChoreographer;
    @Mock private ShellTaskOrganizer mTaskOrganizer;
    @Mock private DisplayController mDisplayController;
    @Mock private SplitScreenController mSplitScreenController;
    @Mock private SyncTransactionQueue mSyncQueue;
    @Mock private DesktopModeController mDesktopModeController;
    @Mock private DesktopTasksController mDesktopTasksController;
@@ -98,6 +100,7 @@ public class DesktopModeWindowDecorViewModelTests extends ShellTestCase {
                mSyncQueue,
                Optional.of(mDesktopModeController),
                Optional.of(mDesktopTasksController),
                Optional.of(mSplitScreenController),
                mDesktopModeWindowDecorFactory,
                mMockInputMonitorFactory
            );