Loading services/core/java/com/android/server/am/ActivityStack.java +5 −17 Original line number Diff line number Diff line Loading @@ -358,8 +358,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai /** Run all ActivityStacks through this */ protected final ActivityStackSupervisor mStackSupervisor; private final LaunchingTaskPositioner mTaskPositioner; private boolean mTopActivityOccludesKeyguard; private ActivityRecord mTopDismissingKeyguardActivity; Loading Loading @@ -462,8 +460,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mWindowManager = mService.mWindowManager; mStackId = stackId; mCurrentUser = mService.mUserController.getCurrentUserId(); mTaskPositioner = windowingMode == WINDOWING_MODE_FREEFORM ? new LaunchingTaskPositioner() : null; mTmpRect2.setEmpty(); setWindowingMode(windowingMode); setActivityType(activityType); Loading Loading @@ -504,11 +500,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mDisplayId = activityDisplay.mDisplayId; mBounds = bounds != null ? new Rect(bounds) : null; mFullscreen = mBounds == null; if (mTaskPositioner != null) { activityDisplay.mDisplay.getSize(mTmpSize); mTaskPositioner.setDisplaySize(mTmpSize); mTaskPositioner.configure(mBounds); } onParentChanged(); activityDisplay.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM); Loading Loading @@ -536,9 +528,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai display.removeChild(this); } mDisplayId = INVALID_DISPLAY; if (mTaskPositioner != null) { mTaskPositioner.reset(); } } /** Removes the stack completely. Also calls WindowManager to do the same on its side. */ Loading Loading @@ -642,9 +631,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai void setBounds(Rect bounds) { mBounds = mFullscreen ? null : new Rect(bounds); if (mTaskPositioner != null) { mTaskPositioner.configure(bounds); } } ActivityRecord topRunningActivityLocked() { Loading Loading @@ -5137,10 +5123,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } boolean layoutTaskInStack(TaskRecord task, ActivityInfo.WindowLayout windowLayout) { if (mTaskPositioner == null) { if (!task.inFreeformWindowingMode()) { return false; } mTaskPositioner.updateDefaultBounds(task, mTaskHistory, windowLayout); mStackSupervisor.getLaunchingTaskPositioner() .updateDefaultBounds(task, mTaskHistory, windowLayout); return true; } Loading services/core/java/com/android/server/am/ActivityStackSupervisor.java +6 −0 Original line number Diff line number Diff line Loading @@ -293,6 +293,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D WindowManagerService mWindowManager; DisplayManager mDisplayManager; LaunchingTaskPositioner mTaskPositioner = new LaunchingTaskPositioner(); /** Counter for next free stack ID to use for dynamic activity stacks. */ private int mNextFreeStackId = 0; Loading Loading @@ -2138,6 +2140,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D || mService.mSupportsFreeformWindowManagement; } LaunchingTaskPositioner getLaunchingTaskPositioner() { return mTaskPositioner; } protected <T extends ActivityStack> T getStack(int stackId) { for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { final T stack = mActivityDisplays.valueAt(i).getStack(stackId); Loading services/core/java/com/android/server/am/LaunchingTaskPositioner.java +76 −86 Original line number Diff line number Diff line Loading @@ -64,23 +64,12 @@ class LaunchingTaskPositioner { private static final int SHIFT_POLICY_HORIZONTAL_RIGHT = 2; private static final int SHIFT_POLICY_HORIZONTAL_LEFT = 3; private boolean mDefaultStartBoundsConfigurationSet = false; private final Rect mAvailableRect = new Rect(); private final Rect mTmpProposal = new Rect(); private final Rect mTmpOriginal = new Rect(); private int mDefaultFreeformStartX; private int mDefaultFreeformStartY; private int mDefaultFreeformWidth; private int mDefaultFreeformHeight; private int mDefaultFreeformStepHorizontal; private int mDefaultFreeformStepVertical; private final Point mDisplaySize = new Point(); void setDisplaySize(Point size) { mDisplaySize.set(size.x, size.y); } /** * Tries to set task's bound in a way that it won't collide with any other task. By colliding * we mean that two tasks have left-top corner very close to each other, so one might get Loading @@ -93,52 +82,47 @@ class LaunchingTaskPositioner { */ void updateDefaultBounds(TaskRecord task, ArrayList<TaskRecord> tasks, @Nullable ActivityInfo.WindowLayout windowLayout) { if (!mDefaultStartBoundsConfigurationSet) { return; } updateAvailableRect(task, mAvailableRect); if (windowLayout == null) { positionCenter(task, tasks, mDefaultFreeformWidth, mDefaultFreeformHeight); positionCenter(task, tasks, mAvailableRect, getFreeformWidth(mAvailableRect), getFreeformHeight(mAvailableRect)); return; } int width = getFinalWidth(windowLayout); int height = getFinalHeight(windowLayout); int width = getFinalWidth(windowLayout, mAvailableRect); int height = getFinalHeight(windowLayout, mAvailableRect); int verticalGravity = windowLayout.gravity & Gravity.VERTICAL_GRAVITY_MASK; int horizontalGravity = windowLayout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; if (verticalGravity == Gravity.TOP) { if (horizontalGravity == Gravity.RIGHT) { positionTopRight(task, tasks, width, height); positionTopRight(task, tasks, mAvailableRect, width, height); } else { positionTopLeft(task, tasks, width, height); positionTopLeft(task, tasks, mAvailableRect, width, height); } } else if (verticalGravity == Gravity.BOTTOM) { if (horizontalGravity == Gravity.RIGHT) { positionBottomRight(task, tasks, width, height); positionBottomRight(task, tasks, mAvailableRect, width, height); } else { positionBottomLeft(task, tasks, width, height); positionBottomLeft(task, tasks, mAvailableRect, width, height); } } else { // Some fancy gravity setting that we don't support yet. We just put the activity in the // center. Slog.w(TAG, "Received unsupported gravity: " + windowLayout.gravity + ", positioning in the center instead."); positionCenter(task, tasks, width, height); positionCenter(task, tasks, mAvailableRect, width, height); } } void configure(Rect availableSpace) { if (availableSpace == null) { mAvailableRect.set(0, 0, mDisplaySize.x, mDisplaySize.y); private void updateAvailableRect(TaskRecord task, Rect availableRect) { final Rect stackBounds = task.getStack().mBounds; if (stackBounds != null) { availableRect.set(stackBounds); } else { mAvailableRect.set(availableSpace); task.getStack().getDisplay().mDisplay.getSize(mDisplaySize); availableRect.set(0, 0, mDisplaySize.x, mDisplaySize.y); } mDefaultFreeformStartX = getFreeformStartLeft(mAvailableRect); mDefaultFreeformStartY = getFreeformStartTop(mAvailableRect); mDefaultFreeformWidth = getFreeformWidth(mAvailableRect); mDefaultFreeformHeight = getFreeformHeight(mAvailableRect); mDefaultFreeformStepHorizontal = getHorizontalStep(mAvailableRect); mDefaultFreeformStepVertical = getVerticalStep(mAvailableRect); mDefaultStartBoundsConfigurationSet = true; } @VisibleForTesting Loading Loading @@ -173,72 +157,79 @@ class LaunchingTaskPositioner { private int getFinalWidth(ActivityInfo.WindowLayout windowLayout) { int width = mDefaultFreeformWidth; private int getFinalWidth(ActivityInfo.WindowLayout windowLayout, Rect availableRect) { int width = getFreeformWidth(availableRect); if (windowLayout.width > 0) { width = windowLayout.width; } if (windowLayout.widthFraction > 0) { width = (int) (mAvailableRect.width() * windowLayout.widthFraction); width = (int) (availableRect.width() * windowLayout.widthFraction); } return width; } private int getFinalHeight(ActivityInfo.WindowLayout windowLayout) { int height = mDefaultFreeformHeight; private int getFinalHeight(ActivityInfo.WindowLayout windowLayout, Rect availableRect) { int height = getFreeformHeight(availableRect); if (windowLayout.height > 0) { height = windowLayout.height; } if (windowLayout.heightFraction > 0) { height = (int) (mAvailableRect.height() * windowLayout.heightFraction); height = (int) (availableRect.height() * windowLayout.heightFraction); } return height; } private void positionBottomLeft(TaskRecord task, ArrayList<TaskRecord> tasks, int width, int height) { mTmpProposal.set(mAvailableRect.left, mAvailableRect.bottom - height, mAvailableRect.left + width, mAvailableRect.bottom); position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT); private void positionBottomLeft(TaskRecord task, ArrayList<TaskRecord> tasks, Rect availableRect, int width, int height) { mTmpProposal.set(availableRect.left, availableRect.bottom - height, availableRect.left + width, availableRect.bottom); position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT); } private void positionBottomRight(TaskRecord task, ArrayList<TaskRecord> tasks, int width, int height) { mTmpProposal.set(mAvailableRect.right - width, mAvailableRect.bottom - height, mAvailableRect.right, mAvailableRect.bottom); position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT); private void positionBottomRight(TaskRecord task, ArrayList<TaskRecord> tasks, Rect availableRect, int width, int height) { mTmpProposal.set(availableRect.right - width, availableRect.bottom - height, availableRect.right, availableRect.bottom); position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT); } private void positionTopLeft(TaskRecord task, ArrayList<TaskRecord> tasks, int width, int height) { mTmpProposal.set(mAvailableRect.left, mAvailableRect.top, mAvailableRect.left + width, mAvailableRect.top + height); position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT); private void positionTopLeft(TaskRecord task, ArrayList<TaskRecord> tasks, Rect availableRect, int width, int height) { mTmpProposal.set(availableRect.left, availableRect.top, availableRect.left + width, availableRect.top + height); position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT); } private void positionTopRight(TaskRecord task, ArrayList<TaskRecord> tasks, int width, int height) { mTmpProposal.set(mAvailableRect.right - width, mAvailableRect.top, mAvailableRect.right, mAvailableRect.top + height); position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT); private void positionTopRight(TaskRecord task, ArrayList<TaskRecord> tasks, Rect availableRect, int width, int height) { mTmpProposal.set(availableRect.right - width, availableRect.top, availableRect.right, availableRect.top + height); position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT); } private void positionCenter(TaskRecord task, ArrayList<TaskRecord> tasks, int width, int height) { mTmpProposal.set(mDefaultFreeformStartX, mDefaultFreeformStartY, mDefaultFreeformStartX + width, mDefaultFreeformStartY + height); position(task, tasks, mTmpProposal, ALLOW_RESTART, SHIFT_POLICY_DIAGONAL_DOWN); private void positionCenter(TaskRecord task, ArrayList<TaskRecord> tasks, Rect availableRect, int width, int height) { final int defaultFreeformLeft = getFreeformStartLeft(availableRect); final int defaultFreeformTop = getFreeformStartTop(availableRect); mTmpProposal.set(defaultFreeformLeft, defaultFreeformTop, defaultFreeformLeft + width, defaultFreeformTop + height); position(task, tasks, availableRect, mTmpProposal, ALLOW_RESTART, SHIFT_POLICY_DIAGONAL_DOWN); } private void position(TaskRecord task, ArrayList<TaskRecord> tasks, Rect proposal, boolean allowRestart, int shiftPolicy) { private void position(TaskRecord task, ArrayList<TaskRecord> tasks, Rect availableRect, Rect proposal, boolean allowRestart, int shiftPolicy) { mTmpOriginal.set(proposal); boolean restarted = false; while (boundsConflict(proposal, tasks)) { // Unfortunately there is already a task at that spot, so we need to look for some // other place. shiftStartingPoint(proposal, shiftPolicy); if (shiftedTooFar(proposal, shiftPolicy)) { shiftStartingPoint(proposal, availableRect, shiftPolicy); if (shiftedTooFar(proposal, availableRect, shiftPolicy)) { // We don't want the task to go outside of the stack, because it won't look // nice. Depending on the starting point we either restart, or immediately give up. if (!allowRestart) { Loading @@ -247,13 +238,13 @@ class LaunchingTaskPositioner { } // We must have started not from the top. Let's restart from there because there // might be some space there. proposal.set(mAvailableRect.left, mAvailableRect.top, mAvailableRect.left + proposal.width(), mAvailableRect.top + proposal.height()); proposal.set(availableRect.left, availableRect.top, availableRect.left + proposal.width(), availableRect.top + proposal.height()); restarted = true; } if (restarted && (proposal.left > mDefaultFreeformStartX || proposal.top > mDefaultFreeformStartY)) { if (restarted && (proposal.left > getFreeformStartLeft(availableRect) || proposal.top > getFreeformStartTop(availableRect))) { // If we restarted and crossed the initial position, let's not struggle anymore. // The user already must have ton of tasks visible, we can just smack the new // one in the center. Loading @@ -264,27 +255,30 @@ class LaunchingTaskPositioner { task.updateOverrideConfiguration(proposal); } private boolean shiftedTooFar(Rect start, int shiftPolicy) { private boolean shiftedTooFar(Rect start, Rect availableRect, int shiftPolicy) { switch (shiftPolicy) { case SHIFT_POLICY_HORIZONTAL_LEFT: return start.left < mAvailableRect.left; return start.left < availableRect.left; case SHIFT_POLICY_HORIZONTAL_RIGHT: return start.right > mAvailableRect.right; return start.right > availableRect.right; default: // SHIFT_POLICY_DIAGONAL_DOWN return start.right > mAvailableRect.right || start.bottom > mAvailableRect.bottom; return start.right > availableRect.right || start.bottom > availableRect.bottom; } } private void shiftStartingPoint(Rect posposal, int shiftPolicy) { private void shiftStartingPoint(Rect posposal, Rect availableRect, int shiftPolicy) { final int defaultFreeformStepHorizontal = getHorizontalStep(availableRect); final int defaultFreeformStepVertical = getVerticalStep(availableRect); switch (shiftPolicy) { case SHIFT_POLICY_HORIZONTAL_LEFT: posposal.offset(-mDefaultFreeformStepHorizontal, 0); posposal.offset(-defaultFreeformStepHorizontal, 0); break; case SHIFT_POLICY_HORIZONTAL_RIGHT: posposal.offset(mDefaultFreeformStepHorizontal, 0); posposal.offset(defaultFreeformStepHorizontal, 0); break; default: // SHIFT_POLICY_DIAGONAL_DOWN: posposal.offset(mDefaultFreeformStepHorizontal, mDefaultFreeformStepVertical); posposal.offset(defaultFreeformStepHorizontal, defaultFreeformStepVertical); break; } } Loading Loading @@ -323,8 +317,4 @@ class LaunchingTaskPositioner { return Math.abs(first.right - second.right) < BOUNDS_CONFLICT_MIN_DISTANCE && Math.abs(first.bottom - second.bottom) < BOUNDS_CONFLICT_MIN_DISTANCE; } void reset() { mDefaultStartBoundsConfigurationSet = false; } } Loading
services/core/java/com/android/server/am/ActivityStack.java +5 −17 Original line number Diff line number Diff line Loading @@ -358,8 +358,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai /** Run all ActivityStacks through this */ protected final ActivityStackSupervisor mStackSupervisor; private final LaunchingTaskPositioner mTaskPositioner; private boolean mTopActivityOccludesKeyguard; private ActivityRecord mTopDismissingKeyguardActivity; Loading Loading @@ -462,8 +460,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mWindowManager = mService.mWindowManager; mStackId = stackId; mCurrentUser = mService.mUserController.getCurrentUserId(); mTaskPositioner = windowingMode == WINDOWING_MODE_FREEFORM ? new LaunchingTaskPositioner() : null; mTmpRect2.setEmpty(); setWindowingMode(windowingMode); setActivityType(activityType); Loading Loading @@ -504,11 +500,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mDisplayId = activityDisplay.mDisplayId; mBounds = bounds != null ? new Rect(bounds) : null; mFullscreen = mBounds == null; if (mTaskPositioner != null) { activityDisplay.mDisplay.getSize(mTmpSize); mTaskPositioner.setDisplaySize(mTmpSize); mTaskPositioner.configure(mBounds); } onParentChanged(); activityDisplay.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM); Loading Loading @@ -536,9 +528,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai display.removeChild(this); } mDisplayId = INVALID_DISPLAY; if (mTaskPositioner != null) { mTaskPositioner.reset(); } } /** Removes the stack completely. Also calls WindowManager to do the same on its side. */ Loading Loading @@ -642,9 +631,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai void setBounds(Rect bounds) { mBounds = mFullscreen ? null : new Rect(bounds); if (mTaskPositioner != null) { mTaskPositioner.configure(bounds); } } ActivityRecord topRunningActivityLocked() { Loading Loading @@ -5137,10 +5123,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } boolean layoutTaskInStack(TaskRecord task, ActivityInfo.WindowLayout windowLayout) { if (mTaskPositioner == null) { if (!task.inFreeformWindowingMode()) { return false; } mTaskPositioner.updateDefaultBounds(task, mTaskHistory, windowLayout); mStackSupervisor.getLaunchingTaskPositioner() .updateDefaultBounds(task, mTaskHistory, windowLayout); return true; } Loading
services/core/java/com/android/server/am/ActivityStackSupervisor.java +6 −0 Original line number Diff line number Diff line Loading @@ -293,6 +293,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D WindowManagerService mWindowManager; DisplayManager mDisplayManager; LaunchingTaskPositioner mTaskPositioner = new LaunchingTaskPositioner(); /** Counter for next free stack ID to use for dynamic activity stacks. */ private int mNextFreeStackId = 0; Loading Loading @@ -2138,6 +2140,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D || mService.mSupportsFreeformWindowManagement; } LaunchingTaskPositioner getLaunchingTaskPositioner() { return mTaskPositioner; } protected <T extends ActivityStack> T getStack(int stackId) { for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { final T stack = mActivityDisplays.valueAt(i).getStack(stackId); Loading
services/core/java/com/android/server/am/LaunchingTaskPositioner.java +76 −86 Original line number Diff line number Diff line Loading @@ -64,23 +64,12 @@ class LaunchingTaskPositioner { private static final int SHIFT_POLICY_HORIZONTAL_RIGHT = 2; private static final int SHIFT_POLICY_HORIZONTAL_LEFT = 3; private boolean mDefaultStartBoundsConfigurationSet = false; private final Rect mAvailableRect = new Rect(); private final Rect mTmpProposal = new Rect(); private final Rect mTmpOriginal = new Rect(); private int mDefaultFreeformStartX; private int mDefaultFreeformStartY; private int mDefaultFreeformWidth; private int mDefaultFreeformHeight; private int mDefaultFreeformStepHorizontal; private int mDefaultFreeformStepVertical; private final Point mDisplaySize = new Point(); void setDisplaySize(Point size) { mDisplaySize.set(size.x, size.y); } /** * Tries to set task's bound in a way that it won't collide with any other task. By colliding * we mean that two tasks have left-top corner very close to each other, so one might get Loading @@ -93,52 +82,47 @@ class LaunchingTaskPositioner { */ void updateDefaultBounds(TaskRecord task, ArrayList<TaskRecord> tasks, @Nullable ActivityInfo.WindowLayout windowLayout) { if (!mDefaultStartBoundsConfigurationSet) { return; } updateAvailableRect(task, mAvailableRect); if (windowLayout == null) { positionCenter(task, tasks, mDefaultFreeformWidth, mDefaultFreeformHeight); positionCenter(task, tasks, mAvailableRect, getFreeformWidth(mAvailableRect), getFreeformHeight(mAvailableRect)); return; } int width = getFinalWidth(windowLayout); int height = getFinalHeight(windowLayout); int width = getFinalWidth(windowLayout, mAvailableRect); int height = getFinalHeight(windowLayout, mAvailableRect); int verticalGravity = windowLayout.gravity & Gravity.VERTICAL_GRAVITY_MASK; int horizontalGravity = windowLayout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; if (verticalGravity == Gravity.TOP) { if (horizontalGravity == Gravity.RIGHT) { positionTopRight(task, tasks, width, height); positionTopRight(task, tasks, mAvailableRect, width, height); } else { positionTopLeft(task, tasks, width, height); positionTopLeft(task, tasks, mAvailableRect, width, height); } } else if (verticalGravity == Gravity.BOTTOM) { if (horizontalGravity == Gravity.RIGHT) { positionBottomRight(task, tasks, width, height); positionBottomRight(task, tasks, mAvailableRect, width, height); } else { positionBottomLeft(task, tasks, width, height); positionBottomLeft(task, tasks, mAvailableRect, width, height); } } else { // Some fancy gravity setting that we don't support yet. We just put the activity in the // center. Slog.w(TAG, "Received unsupported gravity: " + windowLayout.gravity + ", positioning in the center instead."); positionCenter(task, tasks, width, height); positionCenter(task, tasks, mAvailableRect, width, height); } } void configure(Rect availableSpace) { if (availableSpace == null) { mAvailableRect.set(0, 0, mDisplaySize.x, mDisplaySize.y); private void updateAvailableRect(TaskRecord task, Rect availableRect) { final Rect stackBounds = task.getStack().mBounds; if (stackBounds != null) { availableRect.set(stackBounds); } else { mAvailableRect.set(availableSpace); task.getStack().getDisplay().mDisplay.getSize(mDisplaySize); availableRect.set(0, 0, mDisplaySize.x, mDisplaySize.y); } mDefaultFreeformStartX = getFreeformStartLeft(mAvailableRect); mDefaultFreeformStartY = getFreeformStartTop(mAvailableRect); mDefaultFreeformWidth = getFreeformWidth(mAvailableRect); mDefaultFreeformHeight = getFreeformHeight(mAvailableRect); mDefaultFreeformStepHorizontal = getHorizontalStep(mAvailableRect); mDefaultFreeformStepVertical = getVerticalStep(mAvailableRect); mDefaultStartBoundsConfigurationSet = true; } @VisibleForTesting Loading Loading @@ -173,72 +157,79 @@ class LaunchingTaskPositioner { private int getFinalWidth(ActivityInfo.WindowLayout windowLayout) { int width = mDefaultFreeformWidth; private int getFinalWidth(ActivityInfo.WindowLayout windowLayout, Rect availableRect) { int width = getFreeformWidth(availableRect); if (windowLayout.width > 0) { width = windowLayout.width; } if (windowLayout.widthFraction > 0) { width = (int) (mAvailableRect.width() * windowLayout.widthFraction); width = (int) (availableRect.width() * windowLayout.widthFraction); } return width; } private int getFinalHeight(ActivityInfo.WindowLayout windowLayout) { int height = mDefaultFreeformHeight; private int getFinalHeight(ActivityInfo.WindowLayout windowLayout, Rect availableRect) { int height = getFreeformHeight(availableRect); if (windowLayout.height > 0) { height = windowLayout.height; } if (windowLayout.heightFraction > 0) { height = (int) (mAvailableRect.height() * windowLayout.heightFraction); height = (int) (availableRect.height() * windowLayout.heightFraction); } return height; } private void positionBottomLeft(TaskRecord task, ArrayList<TaskRecord> tasks, int width, int height) { mTmpProposal.set(mAvailableRect.left, mAvailableRect.bottom - height, mAvailableRect.left + width, mAvailableRect.bottom); position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT); private void positionBottomLeft(TaskRecord task, ArrayList<TaskRecord> tasks, Rect availableRect, int width, int height) { mTmpProposal.set(availableRect.left, availableRect.bottom - height, availableRect.left + width, availableRect.bottom); position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT); } private void positionBottomRight(TaskRecord task, ArrayList<TaskRecord> tasks, int width, int height) { mTmpProposal.set(mAvailableRect.right - width, mAvailableRect.bottom - height, mAvailableRect.right, mAvailableRect.bottom); position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT); private void positionBottomRight(TaskRecord task, ArrayList<TaskRecord> tasks, Rect availableRect, int width, int height) { mTmpProposal.set(availableRect.right - width, availableRect.bottom - height, availableRect.right, availableRect.bottom); position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT); } private void positionTopLeft(TaskRecord task, ArrayList<TaskRecord> tasks, int width, int height) { mTmpProposal.set(mAvailableRect.left, mAvailableRect.top, mAvailableRect.left + width, mAvailableRect.top + height); position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT); private void positionTopLeft(TaskRecord task, ArrayList<TaskRecord> tasks, Rect availableRect, int width, int height) { mTmpProposal.set(availableRect.left, availableRect.top, availableRect.left + width, availableRect.top + height); position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT); } private void positionTopRight(TaskRecord task, ArrayList<TaskRecord> tasks, int width, int height) { mTmpProposal.set(mAvailableRect.right - width, mAvailableRect.top, mAvailableRect.right, mAvailableRect.top + height); position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT); private void positionTopRight(TaskRecord task, ArrayList<TaskRecord> tasks, Rect availableRect, int width, int height) { mTmpProposal.set(availableRect.right - width, availableRect.top, availableRect.right, availableRect.top + height); position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT); } private void positionCenter(TaskRecord task, ArrayList<TaskRecord> tasks, int width, int height) { mTmpProposal.set(mDefaultFreeformStartX, mDefaultFreeformStartY, mDefaultFreeformStartX + width, mDefaultFreeformStartY + height); position(task, tasks, mTmpProposal, ALLOW_RESTART, SHIFT_POLICY_DIAGONAL_DOWN); private void positionCenter(TaskRecord task, ArrayList<TaskRecord> tasks, Rect availableRect, int width, int height) { final int defaultFreeformLeft = getFreeformStartLeft(availableRect); final int defaultFreeformTop = getFreeformStartTop(availableRect); mTmpProposal.set(defaultFreeformLeft, defaultFreeformTop, defaultFreeformLeft + width, defaultFreeformTop + height); position(task, tasks, availableRect, mTmpProposal, ALLOW_RESTART, SHIFT_POLICY_DIAGONAL_DOWN); } private void position(TaskRecord task, ArrayList<TaskRecord> tasks, Rect proposal, boolean allowRestart, int shiftPolicy) { private void position(TaskRecord task, ArrayList<TaskRecord> tasks, Rect availableRect, Rect proposal, boolean allowRestart, int shiftPolicy) { mTmpOriginal.set(proposal); boolean restarted = false; while (boundsConflict(proposal, tasks)) { // Unfortunately there is already a task at that spot, so we need to look for some // other place. shiftStartingPoint(proposal, shiftPolicy); if (shiftedTooFar(proposal, shiftPolicy)) { shiftStartingPoint(proposal, availableRect, shiftPolicy); if (shiftedTooFar(proposal, availableRect, shiftPolicy)) { // We don't want the task to go outside of the stack, because it won't look // nice. Depending on the starting point we either restart, or immediately give up. if (!allowRestart) { Loading @@ -247,13 +238,13 @@ class LaunchingTaskPositioner { } // We must have started not from the top. Let's restart from there because there // might be some space there. proposal.set(mAvailableRect.left, mAvailableRect.top, mAvailableRect.left + proposal.width(), mAvailableRect.top + proposal.height()); proposal.set(availableRect.left, availableRect.top, availableRect.left + proposal.width(), availableRect.top + proposal.height()); restarted = true; } if (restarted && (proposal.left > mDefaultFreeformStartX || proposal.top > mDefaultFreeformStartY)) { if (restarted && (proposal.left > getFreeformStartLeft(availableRect) || proposal.top > getFreeformStartTop(availableRect))) { // If we restarted and crossed the initial position, let's not struggle anymore. // The user already must have ton of tasks visible, we can just smack the new // one in the center. Loading @@ -264,27 +255,30 @@ class LaunchingTaskPositioner { task.updateOverrideConfiguration(proposal); } private boolean shiftedTooFar(Rect start, int shiftPolicy) { private boolean shiftedTooFar(Rect start, Rect availableRect, int shiftPolicy) { switch (shiftPolicy) { case SHIFT_POLICY_HORIZONTAL_LEFT: return start.left < mAvailableRect.left; return start.left < availableRect.left; case SHIFT_POLICY_HORIZONTAL_RIGHT: return start.right > mAvailableRect.right; return start.right > availableRect.right; default: // SHIFT_POLICY_DIAGONAL_DOWN return start.right > mAvailableRect.right || start.bottom > mAvailableRect.bottom; return start.right > availableRect.right || start.bottom > availableRect.bottom; } } private void shiftStartingPoint(Rect posposal, int shiftPolicy) { private void shiftStartingPoint(Rect posposal, Rect availableRect, int shiftPolicy) { final int defaultFreeformStepHorizontal = getHorizontalStep(availableRect); final int defaultFreeformStepVertical = getVerticalStep(availableRect); switch (shiftPolicy) { case SHIFT_POLICY_HORIZONTAL_LEFT: posposal.offset(-mDefaultFreeformStepHorizontal, 0); posposal.offset(-defaultFreeformStepHorizontal, 0); break; case SHIFT_POLICY_HORIZONTAL_RIGHT: posposal.offset(mDefaultFreeformStepHorizontal, 0); posposal.offset(defaultFreeformStepHorizontal, 0); break; default: // SHIFT_POLICY_DIAGONAL_DOWN: posposal.offset(mDefaultFreeformStepHorizontal, mDefaultFreeformStepVertical); posposal.offset(defaultFreeformStepHorizontal, defaultFreeformStepVertical); break; } } Loading Loading @@ -323,8 +317,4 @@ class LaunchingTaskPositioner { return Math.abs(first.right - second.right) < BOUNDS_CONFLICT_MIN_DISTANCE && Math.abs(first.bottom - second.bottom) < BOUNDS_CONFLICT_MIN_DISTANCE; } void reset() { mDefaultStartBoundsConfigurationSet = false; } }