diff options
3 files changed, 65 insertions, 51 deletions
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java index 1392762fca66..4fd84896e101 100644 --- a/services/core/java/com/android/server/wm/TaskRecord.java +++ b/services/core/java/com/android/server/wm/TaskRecord.java @@ -202,13 +202,6 @@ class TaskRecord extends ConfigurationContainer { // Do not move the stack as a part of reparenting static final int REPARENT_LEAVE_STACK_IN_PLACE = 2; - // The height/width divide used when fitting a task within a bounds with method - // {@link #fitWithinBounds}. - // We always want the task to to be visible in the bounds without affecting its size when - // fitting. To make sure this is the case, we don't adjust the task left or top side pass - // the input bounds right or bottom side minus the width or height divided by this value. - private static final int FIT_WITHIN_BOUNDS_DIVIDER = 3; - /** * The factory used to create {@link TaskRecord}. This allows OEM subclass {@link TaskRecord}. */ @@ -1932,35 +1925,33 @@ class TaskRecord extends ConfigurationContainer { * * @param bounds Bounds to be adjusted. * @param stackBounds Bounds within which the other bounds should remain. + * @param overlapPxX The amount of px required to be visible in the X dimension. + * @param overlapPxY The amount of px required to be visible in the Y dimension. */ - private static void fitWithinBounds(Rect bounds, Rect stackBounds) { + private static void fitWithinBounds(Rect bounds, Rect stackBounds, int overlapPxX, + int overlapPxY) { if (stackBounds == null || stackBounds.isEmpty() || stackBounds.contains(bounds)) { return; } - if (bounds.left < stackBounds.left || bounds.right > stackBounds.right) { - final int maxRight = stackBounds.right - - (stackBounds.width() / FIT_WITHIN_BOUNDS_DIVIDER); - int horizontalDiff = stackBounds.left - bounds.left; - if ((horizontalDiff < 0 && bounds.left >= maxRight) - || (bounds.left + horizontalDiff >= maxRight)) { - horizontalDiff = maxRight - bounds.left; - } - bounds.left += horizontalDiff; - bounds.right += horizontalDiff; + // For each side of the parent (eg. left), check if the opposing side of the window (eg. + // right) is at least overlap pixels away. If less, offset the window by that difference. + int horizontalDiff = 0; + // If window is smaller than overlap, use it's smallest dimension instead + int overlapLR = Math.min(overlapPxX, bounds.width()); + if (bounds.right < (stackBounds.left + overlapLR)) { + horizontalDiff = overlapLR - (bounds.right - stackBounds.left); + } else if (bounds.left > (stackBounds.right - overlapLR)) { + horizontalDiff = -(overlapLR - (stackBounds.right - bounds.left)); } - - if (bounds.top < stackBounds.top || bounds.bottom > stackBounds.bottom) { - final int maxBottom = stackBounds.bottom - - (stackBounds.height() / FIT_WITHIN_BOUNDS_DIVIDER); - int verticalDiff = stackBounds.top - bounds.top; - if ((verticalDiff < 0 && bounds.top >= maxBottom) - || (bounds.top + verticalDiff >= maxBottom)) { - verticalDiff = maxBottom - bounds.top; - } - bounds.top += verticalDiff; - bounds.bottom += verticalDiff; + int verticalDiff = 0; + int overlapTB = Math.min(overlapPxY, bounds.width()); + if (bounds.bottom < (stackBounds.top + overlapTB)) { + verticalDiff = overlapTB - (bounds.bottom - stackBounds.top); + } else if (bounds.top > (stackBounds.bottom - overlapTB)) { + verticalDiff = -(overlapTB - (stackBounds.bottom - bounds.top)); } + bounds.offset(horizontalDiff, verticalDiff); } /** @@ -2230,7 +2221,11 @@ class TaskRecord extends ConfigurationContainer { adjustForMinimalTaskDimensions(outOverrideBounds, mTmpBounds); if (windowingMode == WINDOWING_MODE_FREEFORM) { // by policy, make sure the window remains within parent somewhere - fitWithinBounds(outOverrideBounds, newParentConfig.windowConfiguration.getBounds()); + final float density = + ((float) newParentConfig.densityDpi) / DisplayMetrics.DENSITY_DEFAULT; + fitWithinBounds(outOverrideBounds, newParentConfig.windowConfiguration.getBounds(), + (int) (density * WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP), + (int) (density * WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP)); } computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig); } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index d5a6f00ff30d..20cca66d8a52 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -942,29 +942,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // Make sure the content and visible frames are inside of the // final window frame. if (windowsAreFloating && !mWindowFrames.mFrame.isEmpty()) { - // For pinned workspace the frame isn't limited in any particular - // way since SystemUI controls the bounds. For freeform however - // we want to keep things inside the content frame. - final Rect limitFrame = task.inPinnedWindowingMode() ? mWindowFrames.mFrame - : mWindowFrames.mContentFrame; - // Keep the frame out of the blocked system area, limit it in size to the content area - // and make sure that there is always a minimum visible so that the user can drag it - // into a usable area.. - final int height = Math.min(mWindowFrames.mFrame.height(), limitFrame.height()); - final int width = Math.min(limitFrame.width(), mWindowFrames.mFrame.width()); - final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics(); - final int minVisibleHeight = Math.min(height, WindowManagerService.dipToPixel( - MINIMUM_VISIBLE_HEIGHT_IN_DP, displayMetrics)); - final int minVisibleWidth = Math.min(width, WindowManagerService.dipToPixel( - MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics)); - final int top = Math.max(limitFrame.top, - Math.min( mWindowFrames.mFrame.top, limitFrame.bottom - minVisibleHeight)); - final int left = Math.max(limitFrame.left + minVisibleWidth - width, - Math.min( mWindowFrames.mFrame.left, limitFrame.right - minVisibleWidth)); - mWindowFrames.mFrame.set(left, top, left + width, top + height); final int visBottom = mWindowFrames.mVisibleFrame.bottom; final int contentBottom = mWindowFrames.mContentFrame.bottom; - mWindowFrames.mContentFrame.set( mWindowFrames.mFrame); + mWindowFrames.mContentFrame.set(mWindowFrames.mFrame); mWindowFrames.mVisibleFrame.set(mWindowFrames.mContentFrame); mWindowFrames.mStableFrame.set(mWindowFrames.mContentFrame); if (isImeTarget && inFreeformWindowingMode()) { diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java index 5d0788881704..dc307b547a63 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java @@ -47,6 +47,7 @@ import android.content.res.Configuration; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.service.voice.IVoiceInteractionSession; +import android.util.DisplayMetrics; import android.util.Xml; import android.view.DisplayInfo; @@ -166,6 +167,44 @@ public class TaskRecordTests extends ActivityTestsBase { WINDOWING_MODE_FREEFORM, mParentBounds, insetBounds, insetBounds); } + @Test + public void testFitWithinBounds() { + final Rect parentBounds = new Rect(10, 10, 200, 200); + ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay(); + ActivityStack stack = display.createStack(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, + true /* onTop */); + TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build(); + final Configuration parentConfig = stack.getConfiguration(); + parentConfig.windowConfiguration.setBounds(parentBounds); + parentConfig.densityDpi = DisplayMetrics.DENSITY_DEFAULT; + + // check top and left + Rect reqBounds = new Rect(-190, -190, 0, 0); + task.setBounds(reqBounds); + // Make sure part of it is exposed + assertTrue(task.getBounds().right > parentBounds.left); + assertTrue(task.getBounds().bottom > parentBounds.top); + // Should still be more-or-less in that corner + assertTrue(task.getBounds().left <= parentBounds.left); + assertTrue(task.getBounds().top <= parentBounds.top); + + assertEquals(reqBounds.width(), task.getBounds().width()); + assertEquals(reqBounds.height(), task.getBounds().height()); + + // check bottom and right + reqBounds = new Rect(210, 210, 400, 400); + task.setBounds(reqBounds); + // Make sure part of it is exposed + assertTrue(task.getBounds().left < parentBounds.right); + assertTrue(task.getBounds().top < parentBounds.bottom); + // Should still be more-or-less in that corner + assertTrue(task.getBounds().right >= parentBounds.right); + assertTrue(task.getBounds().bottom >= parentBounds.bottom); + + assertEquals(reqBounds.width(), task.getBounds().width()); + assertEquals(reqBounds.height(), task.getBounds().height()); + } + /** Tests that the task bounds adjust properly to changes between FULLSCREEN and FREEFORM */ @Test public void testBoundsOnModeChangeFreeformToFullscreen() { |