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

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

Merge "Consolidate Desktop Display State Checks" into main

parents 2e64c987 20368bf5
Loading
Loading
Loading
Loading
+16 −3
Original line number Diff line number Diff line
@@ -127,6 +127,8 @@ import com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler;
import com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler;
import com.android.wm.shell.desktopmode.OverviewToDesktopTransitionObserver;
import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator;
import com.android.wm.shell.desktopmode.ShellDesktopState;
import com.android.wm.shell.desktopmode.ShellDesktopStateImpl;
import com.android.wm.shell.desktopmode.SpringDragToDesktopTransitionHandler;
import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler;
import com.android.wm.shell.desktopmode.VisualIndicatorUpdateScheduler;
@@ -1227,10 +1229,10 @@ public abstract class WMShellModule {
            MultiDisplayDragMoveIndicatorController multiDisplayDragMoveIndicatorController,
            Optional<CompatUIHandler> compatUI,
            DesksOrganizer desksOrganizer,
            DesktopState desktopState,
            ShellDesktopState shelldesktopState,
            DesktopConfig desktopConfig
    ) {
        if (!desktopState.canEnterDesktopModeOrShowAppHandle()) {
        if (!shelldesktopState.canEnterDesktopModeOrShowAppHandle()) {
            return Optional.empty();
        }
        return Optional.of(new DesktopModeWindowDecorViewModel(context, shellExecutor, mainHandler,
@@ -1247,7 +1249,7 @@ public abstract class WMShellModule {
                desktopModeUiEventLogger, taskResourceLoader, recentsTransitionHandler,
                desktopModeCompatPolicy, desktopTilingDecorViewModel,
                multiDisplayDragMoveIndicatorController, compatUI.orElse(null),
                desksOrganizer, desktopState, desktopConfig));
                desksOrganizer, shelldesktopState, desktopConfig));
    }

    @WMSingleton
@@ -1273,6 +1275,17 @@ public abstract class WMShellModule {
        return new MultiDisplayDragMoveIndicatorSurface.Factory();
    }

    @WMSingleton
    @Provides
    static ShellDesktopState provideShellDesktopState(
            DesktopState desktopState,
            @DynamicOverride DesktopUserRepositories desktopUserRepositories,
            FocusTransitionObserver focusTransitionObserver,
            ShellController shellController) {
        return new ShellDesktopStateImpl(desktopState, desktopUserRepositories,
                focusTransitionObserver, shellController);
    }

    @WMSingleton
    @Provides
    static AppHandleAndHeaderVisibilityHelper provideAppHandleAndHeaderVisibilityHelper(
+27 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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 com.android.wm.shell.shared.desktopmode.DesktopState

/** Extends [DesktopState] with methods that integrate with shell-specific components and logic. */
interface ShellDesktopState : DesktopState {
    /**
     * Determines if a display with [displayId] is an eligible drop target for a window in the
     * context of desktop mode.
     */
    fun isEligibleWindowDropTarget(displayId: Int): Boolean
}
+58 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.app.WindowConfiguration.ACTIVITY_TYPE_HOME
import com.android.wm.shell.shared.desktopmode.DesktopState
import com.android.wm.shell.sysui.ShellController
import com.android.wm.shell.transition.FocusTransitionObserver

class ShellDesktopStateImpl(
    private val desktopState: DesktopState,
    private val desktopUserRepositories: DesktopUserRepositories,
    private val focusTransitionObserver: FocusTransitionObserver,
    private val shellController: ShellController,
) : ShellDesktopState, DesktopState by desktopState {
    /** Checks if the given display has an active desktop session (i.e., running freeform tasks). */
    private fun isInDesktop(displayId: Int): Boolean =
        desktopUserRepositories
            .getProfile(shellController.currentUserId)
            .getActiveDeskId(displayId) != null

    /** Checks if the currently focused task on the given display is the home screen. */
    private fun isHomeFocused(displayId: Int): Boolean {
        val focusedTask = focusTransitionObserver.getFocusedTaskOnDisplay(displayId)
        if (focusedTask == null) {
            // A null focused task can occur if the Home activity launched before Shell was
            // fully initialized, and this display has not yet received focus. In this case,
            // we assume that Home is the focused activity on the display.
            return true
        }
        return focusedTask.activityType == ACTIVITY_TYPE_HOME
    }

    /**
     * Determines if a display with [displayId] is an eligible drop target for a window in the
     * context of desktop mode.
     *
     * A display is considered an eligible target if either:
     * 1. It already has an active desktop session.
     * 2. It supports desktop mode and the home screen is currently focused.
     */
    override fun isEligibleWindowDropTarget(displayId: Int): Boolean =
        isInDesktop(displayId) ||
            (desktopState.isDesktopModeSupportedOnDisplay(displayId) && isHomeFocused(displayId))
}
+13 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import static android.window.TransitionInfo.FLAG_MOVED_TO_TOP;
import static com.android.wm.shell.transition.Transitions.TransitionObserver;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager.RunningTaskInfo;
import android.os.RemoteException;
import android.util.ArraySet;
@@ -267,6 +268,18 @@ public class FocusTransitionObserver {
        return task.displayId == mFocusedDisplayId && isFocusedOnDisplay(task);
    }

    /**
     * Gets the focused task on a specific display.
     *
     * @param displayId The ID of the display.
     * @return The {@link RunningTaskInfo} of the focused task on the given display,
     *         or {@code null} if no task is focused or display not recorded in the observer.
     */
    @Nullable
    public RunningTaskInfo getFocusedTaskOnDisplay(int displayId) {
        return mFocusedTaskOnDisplay.get(displayId);
    }

    /** Dumps focused display and tasks. */
    public void dump(PrintWriter originalWriter, String prefix) {
        final IndentingPrintWriter writer =
+18 −21
Original line number Diff line number Diff line
@@ -122,6 +122,7 @@ import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition;
import com.android.wm.shell.desktopmode.DesktopTasksLimiter;
import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.desktopmode.ShellDesktopState;
import com.android.wm.shell.desktopmode.WindowDecorCaptionRepository;
import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction;
import com.android.wm.shell.desktopmode.common.ToggleTaskSizeUtilsKt;
@@ -215,7 +216,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
    private final AppHeaderViewHolder.Factory mAppHeaderViewHolderFactory;
    private final AppHandleViewHolder.Factory mAppHandleViewHolderFactory;
    private final DesksOrganizer mDesksOrganizer;
    private final DesktopState mDesktopState;
    private final ShellDesktopState mShellDesktopState;
    private final DesktopConfig mDesktopConfig;
    private boolean mTransitionDragActive;

@@ -304,7 +305,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
            MultiDisplayDragMoveIndicatorController multiDisplayDragMoveIndicatorController,
            CompatUIHandler compatUI,
            DesksOrganizer desksOrganizer,
            DesktopState desktopState,
            ShellDesktopState shellDesktopState,
            DesktopConfig desktopConfig) {
        this(
                context,
@@ -355,7 +356,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                multiDisplayDragMoveIndicatorController,
                compatUI,
                desksOrganizer,
                desktopState,
                shellDesktopState,
                desktopConfig);
    }

@@ -409,7 +410,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
            MultiDisplayDragMoveIndicatorController multiDisplayDragMoveIndicatorController,
            CompatUIHandler compatUI,
            DesksOrganizer desksOrganizer,
            DesktopState desktopState,
            ShellDesktopState shellDesktopState,
            DesktopConfig desktopConfig) {
        mContext = context;
        mMainExecutor = shellExecutor;
@@ -489,7 +490,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
        mMultiDisplayDragMoveIndicatorController = multiDisplayDragMoveIndicatorController;
        mLatencyTracker = LatencyTracker.getInstance(mContext);
        mDesksOrganizer = desksOrganizer;
        mDesktopState = desktopState;
        mShellDesktopState = shellDesktopState;
        mDesktopConfig = desktopConfig;
        mWindowDecorationActions =
                new DefaultWindowDecorationActions(this, mDesktopTasksController,
@@ -519,7 +520,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                    new DesktopModeRecentsTransitionStateListener());
        }
        mDisplayController.addDisplayChangingController(mOnDisplayChangingListener);
        if (mDesktopState.canEnterDesktopModeOrShowAppHandle()
        if (mShellDesktopState.canEnterDesktopModeOrShowAppHandle()
                && Flags.enableDesktopWindowingAppHandleEducation()) {
            mAppHandleEducationController.setAppHandleEducationTooltipCallbacks(
                    /* appHandleTooltipClickCallback= */(taskId) -> {
@@ -1306,7 +1307,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
        public boolean handleMotionEvent(@Nullable View v, MotionEvent e) {
            final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId);
            final RunningTaskInfo taskInfo = decoration.mTaskInfo;
            if (mDesktopState.canEnterDesktopModeOrShowAppHandle()
            if (mShellDesktopState.canEnterDesktopModeOrShowAppHandle()
                    && !taskInfo.isFreeform()) {
                return handleNonFreeformMotionEvent(decoration, v, e);
            } else {
@@ -1394,8 +1395,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,

                    if (DesktopExperienceFlags
                            .ENABLE_BLOCK_NON_DESKTOP_DISPLAY_WINDOW_DRAG_BUGFIX.isTrue()) {
                        final boolean inDesktopModeDisplay = isDisplayInDesktopMode(
                                e.getDisplayId());
                        final boolean inDesktopModeDisplay = mShellDesktopState
                                .isEligibleWindowDropTarget(e.getDisplayId());
                        // TODO: b/418651425 - Use a more specific pointer icon when available.
                        updatePointerIcon(e, dragPointerIdx, v.getViewRootImpl().getInputToken(),
                                inDesktopModeDisplay ? PointerIcon.TYPE_ARROW
@@ -1447,7 +1448,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                                PointerIcon.TYPE_ARROW);
                        // If the cursor ends on a non-desktop-mode display, revert the window
                        // to its initial bounds prior to the drag starting.
                        if (!isDisplayInDesktopMode(e.getDisplayId())) {
                        if (!mShellDesktopState
                                .isEligibleWindowDropTarget(e.getDisplayId())) {
                            newTaskBounds.set(mOnDragStartInitialBounds);
                        }
                    }
@@ -1485,11 +1487,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
            mCurrentPointerIconType = iconType;
        }

        private boolean isDisplayInDesktopMode(int displayId) {
            return mDesktopState.isDesktopModeSupportedOnDisplay(displayId)
                    && mDesktopTasksController.getActiveDeskId(displayId) != null;
        }

        private void updateDragStatus(DesktopModeWindowDecoration decor, MotionEvent e) {
            switch (e.getActionMasked()) {
                case MotionEvent.ACTION_DOWN:
@@ -1620,7 +1617,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
     */
    private void handleReceivedMotionEvent(MotionEvent ev, InputMonitor inputMonitor) {
        final DesktopModeWindowDecoration relevantDecor = getRelevantWindowDecor(ev);
        if (mDesktopState.canEnterDesktopMode()) {
        if (mShellDesktopState.canEnterDesktopMode()) {
            if (!mInImmersiveMode && (relevantDecor == null
                    || relevantDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM
                    || mTransitionDragActive)) {
@@ -1630,7 +1627,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
        }
        handleEventOutsideCaption(ev, relevantDecor);
        // Prevent status bar from reacting to a caption drag.
        if (mDesktopState.canEnterDesktopMode()) {
        if (mShellDesktopState.canEnterDesktopMode()) {
            if (mTransitionDragActive) {
                inputMonitor.pilferPointers();
            }
@@ -1682,7 +1679,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                        relevantDecor.mTaskInfo.configuration.windowConfiguration.getBounds());
                boolean dragFromStatusBarAllowed = false;
                final int windowingMode = relevantDecor.mTaskInfo.getWindowingMode();
                if (mDesktopState.canEnterDesktopMode()
                if (mShellDesktopState.canEnterDesktopMode()
                        || BubbleAnythingFlagHelper.enableBubbleToFullscreen()) {
                    // In proto2 any full screen or multi-window task can be dragged to
                    // freeform.
@@ -1944,7 +1941,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                        mDesktopModeEventLogger,
                        mDesktopModeUiEventLogger,
                        mDesktopModeCompatPolicy,
                        mDesktopState,
                        mShellDesktopState,
                        mDesktopConfig,
                        mWindowDecorationActions);
        mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
@@ -1958,7 +1955,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                mTransactionFactory,
                mMainHandler,
                mMultiDisplayDragMoveIndicatorController,
                mDesktopState,
                mShellDesktopState,
                mDesktopConfig);
        windowDecoration.setTaskDragResizer(taskPositioner);

@@ -1995,7 +1992,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
        final String innerPrefix = prefix + "  ";
        pw.println(prefix + "DesktopModeWindowDecorViewModel");
        pw.println(innerPrefix + "DesktopModeStatus="
                + mDesktopState.canEnterDesktopMode());
                + mShellDesktopState.canEnterDesktopMode());
        pw.println(innerPrefix + "mTransitionDragActive=" + mTransitionDragActive);
        pw.println(innerPrefix + "mEventReceiversByDisplay=" + mEventReceiversByDisplay);
        pw.println(innerPrefix + "mGestureExclusionTracker="
Loading