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

Commit eb84c309 authored by Jorge Gil's avatar Jorge Gil
Browse files

Let nested multi-window inherit bounds from parent

I5985242014e02e051fad98e89a38cf03cd096f66 made a change to allow
non-root, organized tasks to use launch bounds calculated by
LaunchParams instead of always inheriting bounds from the root task.
This was to allow nested freeform tasks to use launch bounds instead of
always taking fullscreen bounds.
However, this also causes multi-window (split) leaves to use
root.getRequestedOverrideBounds() as their bounds. The root bounds are
often non-empty (like in 50/50 split), which causes Task#getVisibility
to stop considering an occluding split leaf as occluding because
matchesParentBounds() relies on the bounds being empty.

To fix this, this change adjusts the bounds calculation to inherit (use
null) bounds from the parent when we're disallowing independent bounds
from parent (i.e., not freeform).

It also refactors the logic in this method to be more readable and
intentional. In particular, |allowIndependentBoundsFromParent|
determines whether or not to inherit in nested cases, even if the only
allowed scenario are nested freeform tasks right now.

Also puts this and the prior changes from
I5985242014e02e051fad98e89a38cf03cd096f66 under a new flag.

Flag: com.android.window.flags.nested_tasks_with_independent_bounds
Bug: 402825303
Bug: 394189679
Test: atest RootTaskTests#testGetVisibility_MultiLevel
Test: atest
MultiWindowTests#testVisibilityWithTranslucentAndTopFinishingActivity
Test: atest
ActivityLifecycleTopResumedStateTests#testTopPositionSwitchOnTap
Test: atest ActivityLifecycleLegacySplitScreenTests

Change-Id: I32e82b6f975bf4c77f8991b02df8999db63c634a
parent c6af79cf
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -790,12 +790,6 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
                || mWindowingMode == WINDOWING_MODE_MULTI_WINDOW;
    }

    /** Returns true if the task bounds should persist across power cycles.
     * @hide */
    public boolean persistTaskBounds() {
        return mWindowingMode == WINDOWING_MODE_FREEFORM;
    }

    /**
     * Returns true if the tasks associated with this window configuration are floating.
     * Floating tasks are laid out differently as they are allowed to extend past the display bounds
+53 −27
Original line number Diff line number Diff line
@@ -1832,6 +1832,17 @@ class Task extends TaskFragment {
                && supportsMultiWindowInDisplayArea(tda);
    }

    /** Returns true if the task bounds should persist across power cycles. */
    private static boolean persistTaskBounds(@NonNull WindowConfiguration configuration) {
        return configuration.getWindowingMode() == WINDOWING_MODE_FREEFORM;
    }

    /** Returns true if the nested task is allowed to have independent bounds from its parent. */
    private static boolean allowIndependentBoundsFromParent(
            @NonNull WindowConfiguration configuration) {
        return configuration.getWindowingMode() == WINDOWING_MODE_FREEFORM;
    }

    /**
     * Check whether this task can be launched on the specified display.
     *
@@ -1996,11 +2007,11 @@ class Task extends TaskFragment {
    private void onConfigurationChangedInner(Configuration newParentConfig) {
        // Check if the new configuration supports persistent bounds (eg. is Freeform) and if so
        // restore the last recorded non-fullscreen bounds.
        final boolean prevPersistTaskBounds = getWindowConfiguration().persistTaskBounds();
        boolean nextPersistTaskBounds =
                getRequestedOverrideConfiguration().windowConfiguration.persistTaskBounds();
        final boolean prevPersistTaskBounds = persistTaskBounds(getWindowConfiguration());
        boolean nextPersistTaskBounds = persistTaskBounds(
                getRequestedOverrideConfiguration().windowConfiguration);
        if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_UNDEFINED) {
            nextPersistTaskBounds = newParentConfig.windowConfiguration.persistTaskBounds();
            nextPersistTaskBounds = persistTaskBounds(newParentConfig.windowConfiguration);
        }
        // Only restore to the last non-fullscreen bounds when the requested override bounds
        // have not been explicitly set already.
@@ -2042,7 +2053,7 @@ class Task extends TaskFragment {

        // If the configuration supports persistent bounds (eg. Freeform), keep track of the
        // current (non-fullscreen) bounds for persistence.
        if (getWindowConfiguration().persistTaskBounds()) {
        if (persistTaskBounds(getWindowConfiguration())) {
            final Rect currentBounds = getRequestedOverrideBounds();
            if (!currentBounds.isEmpty()) {
                setLastNonFullscreenBounds(currentBounds);
@@ -2383,33 +2394,48 @@ class Task extends TaskFragment {
    }

    void updateOverrideConfigurationFromLaunchBounds() {
        // If the task is controlled by another organized task, do not set override
        // configurations and let its parent (organized task) to control it;
        final Task rootTask = getRootTask();
        boolean shouldInheritBounds = rootTask != this && rootTask.isOrganized();
        if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue()) {
            // Only inherit from organized parent when this task is not organized.
            shouldInheritBounds &= !isOrganized();
        final boolean hasParentTask = rootTask != this;
        final int windowingMode = getWindowingMode();
        final boolean isNonStandardOrFullscreen = !isActivityTypeStandardOrUndefined()
                || windowingMode == WINDOWING_MODE_FULLSCREEN;
        if (!Flags.nestedTasksWithIndependentBounds()
                && !DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue()) {
            final Rect bounds;
            if (hasParentTask && rootTask.isOrganized()) {
                bounds = null;
            } else if (isNonStandardOrFullscreen) {
                bounds = isResizeable() ? rootTask.getRequestedOverrideBounds() : null;
            } else if (!persistTaskBounds(getWindowConfiguration())) {
                bounds = rootTask.getRequestedOverrideBounds();
            } else {
                bounds = mLastNonFullscreenBounds;
            }
        final Rect bounds = shouldInheritBounds ? null : getLaunchBounds();
            setBounds(bounds);
            return;
        }

    /** Returns the bounds that should be used to launch this task. */
    Rect getLaunchBounds() {
        final Task rootTask = getRootTask();
        if (rootTask == null) {
            return null;
        // Non-standard/fullscreen unresizable tasks should always inherit.
        boolean shouldInheritBounds = isNonStandardOrFullscreen && !isResizeable();
        // Task itself is not organized (e.g. Home), just inherit from its organized parent.
        shouldInheritBounds |= hasParentTask && rootTask.isOrganized() && !isOrganized();
        // Nested tasks should inherit when they're not allowed to have independent bounds, such as
        // in multi-window split-screen.
        shouldInheritBounds |= hasParentTask
                && !(allowIndependentBoundsFromParent(getWindowConfiguration())
                && persistTaskBounds(getWindowConfiguration()));
        if (shouldInheritBounds) {
            setBounds(null);
            return;
        }

        final int windowingMode = getWindowingMode();
        if (!isActivityTypeStandardOrUndefined()
                || windowingMode == WINDOWING_MODE_FULLSCREEN) {
            return isResizeable() ? rootTask.getRequestedOverrideBounds() : null;
        } else if (!getWindowConfiguration().persistTaskBounds()) {
            return rootTask.getRequestedOverrideBounds();
        if (!hasParentTask && !persistTaskBounds(getWindowConfiguration())) {
            // Non-nested, non-persistable tasks such as PIP or multi-window floating windows.
            return;
        }
        return mLastNonFullscreenBounds;
        // Non-nested, persisted tasks (e.g. top-level freeform) or nested persisted tasks that
        // allow independent bounds from parent (e.g. nested freeform) should use launch-params
        // bounds set to |mLastNonFullscreenBounds|.
        setBounds(mLastNonFullscreenBounds);
    }

    void setRootProcess(WindowProcessController proc) {