From 364c91254dcd18976b1cc85f9b6738dffecc5ac4 Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Thu, 4 Jun 2020 16:09:31 -0700 Subject: [PATCH] Adjust drag regions to accomodate split-minimized home Basically, this doesn't constrain home's drag bounds to its stack if it is on top of its parent since sysui has adjusted the surface crop for these cases. On the other side, anything in the primary stack must subtract the home's bounds from its own if home is the top secondary task. Bug: 154832406 Test: With a minimized dock, open quick-search and drag an app icon onto the launcher. Change-Id: Id25ec11de85530b2f43ecc0dda6864077a271ba5 --- .../core/java/com/android/server/wm/Task.java | 7 +++- .../android/server/wm/TaskDisplayArea.java | 9 +++++ .../com/android/server/wm/WindowState.java | 37 +++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index ce2ae2a420696..ed7b49dce5d96 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -2918,7 +2918,12 @@ class Task extends WindowContainer { } boolean cropWindowsToStackBounds() { - return isResizeable(); + // Don't crop HOME/RECENTS windows to stack bounds. This is because in split-screen + // they extend past their stack and sysui uses the stack surface to control cropping. + // TODO(b/158242495): get rid of this when drag/drop can use surface bounds. + final boolean isTopHomeOrRecents = (isActivityTypeHome() || isActivityTypeRecents()) + && getRootTask().getTopMostTask() == this; + return isResizeable() && !isTopHomeOrRecents; } /** diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 102c2a6364f4e..97fefa31d003c 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -207,6 +207,15 @@ final class TaskDisplayArea extends DisplayArea { return mRootSplitScreenPrimaryTask; } + ActivityStack getRootSplitScreenSecondaryTask() { + for (int i = mChildren.size() - 1; i >= 0; --i) { + if (mChildren.get(i).inSplitScreenSecondaryWindowingMode()) { + return mChildren.get(i); + } + } + return null; + } + ArrayList getVisibleTasks() { final ArrayList visibleTasks = new ArrayList<>(); forAllTasks(task -> { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index fe3ee50c34c5b..c2b730c041eb7 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1528,6 +1528,29 @@ class WindowState extends WindowContainer implements WindowManagerP && dc != null ? dc.getDefaultTaskDisplayArea().getRootHomeTask() : null; } + /** + * This is a form of rectangle "difference". It cut off each dimension of rect by the amount + * that toRemove is "pushing into" it from the outside. Any dimension that fully contains + * toRemove won't change. + */ + private void cutRect(Rect rect, Rect toRemove) { + if (toRemove.isEmpty()) return; + if (toRemove.top < rect.bottom && toRemove.bottom > rect.top) { + if (toRemove.right >= rect.right && toRemove.left >= rect.left) { + rect.right = toRemove.left; + } else if (toRemove.left <= rect.left && toRemove.right <= rect.right) { + rect.left = toRemove.right; + } + } + if (toRemove.left < rect.right && toRemove.right > rect.left) { + if (toRemove.bottom >= rect.bottom && toRemove.top >= rect.top) { + rect.bottom = toRemove.top; + } else if (toRemove.top <= rect.top && toRemove.bottom <= rect.bottom) { + rect.top = toRemove.bottom; + } + } + } + /** * Retrieves the visible bounds of the window. * @param bounds The rect which gets the bounds. @@ -1544,6 +1567,20 @@ class WindowState extends WindowContainer implements WindowManagerP } else { intersectWithStackBounds = false; } + if (inSplitScreenPrimaryWindowingMode()) { + // If this is in the primary split and the home stack is the top visible task in + // the secondary split, it means this is "minimized" and thus must prevent + // overlapping with home. + // TODO(b/158242495): get rid of this when drag/drop can use surface bounds. + final ActivityStack rootSecondary = + task.getDisplayArea().getRootSplitScreenSecondaryTask(); + if (rootSecondary.isActivityTypeHome() || rootSecondary.isActivityTypeRecents()) { + final WindowContainer topTask = rootSecondary.getTopChild(); + if (topTask.isVisible()) { + cutRect(mTmpRect, topTask.getBounds()); + } + } + } } bounds.set(mWindowFrames.mVisibleFrame);