Shrink default launch bounds on small display
The current implementation doesn't allow changing the default launch size when it doesn't fit the display. However, lots of apps have important UI pieces on top or bottom, so having a window height larger than the display height can degrade the usability of such app a lot. More and more laptops have horizentally longer displays these days, so this problem is getting more common. I think any adjustment will be small enough not to affect apps' layouts much. Also, this logic cannot make the app smaller than the min sizes defined by the system or apps. Bug: 185427982 Test: atest WmTests:TaskLaunchParamsModifierTests Change-Id: I53171bba183e5f00be3118d41c57731b5e3d5e19
This commit is contained in:
@@ -46,6 +46,8 @@ class LaunchParamsUtil {
|
||||
|
||||
private static final int DISPLAY_EDGE_OFFSET_DP = 27;
|
||||
|
||||
private static final Rect TMP_STABLE_BOUNDS = new Rect();
|
||||
|
||||
private LaunchParamsUtil() {}
|
||||
|
||||
/**
|
||||
@@ -130,18 +132,42 @@ class LaunchParamsUtil {
|
||||
return new Size(adjWidth, adjHeight);
|
||||
}
|
||||
|
||||
static void adjustBoundsToFitInDisplayArea(@NonNull Rect stableBounds, int layoutDirection,
|
||||
static void adjustBoundsToFitInDisplayArea(@NonNull TaskDisplayArea displayArea,
|
||||
int layoutDirection,
|
||||
@NonNull ActivityInfo.WindowLayout layout,
|
||||
@NonNull Rect inOutBounds) {
|
||||
// Give a small margin between the window bounds and the display bounds.
|
||||
final Rect stableBounds = TMP_STABLE_BOUNDS;
|
||||
displayArea.getStableRect(stableBounds);
|
||||
final float density = (float) displayArea.getConfiguration().densityDpi / DENSITY_DEFAULT;
|
||||
final int displayEdgeOffset = (int) (DISPLAY_EDGE_OFFSET_DP * density + 0.5f);
|
||||
stableBounds.inset(displayEdgeOffset, displayEdgeOffset);
|
||||
|
||||
if (stableBounds.width() < inOutBounds.width()
|
||||
|| stableBounds.height() < inOutBounds.height()) {
|
||||
// There is no way for us to fit the bounds in the displayArea without changing width
|
||||
// or height. Just move the start to align with the displayArea.
|
||||
final int left = layoutDirection == View.LAYOUT_DIRECTION_RTL
|
||||
? stableBounds.right - inOutBounds.right + inOutBounds.left
|
||||
: stableBounds.left;
|
||||
inOutBounds.offsetTo(left, stableBounds.top);
|
||||
return;
|
||||
final float heightShrinkRatio = stableBounds.width() / (float) inOutBounds.width();
|
||||
final float widthShrinkRatio =
|
||||
stableBounds.height() / (float) inOutBounds.height();
|
||||
final float shrinkRatio = Math.min(heightShrinkRatio, widthShrinkRatio);
|
||||
// Minimum layout requirements.
|
||||
final int layoutMinWidth = (layout == null) ? -1 : layout.minWidth;
|
||||
final int layoutMinHeight = (layout == null) ? -1 : layout.minHeight;
|
||||
int adjustedWidth = Math.max(layoutMinWidth, (int) (inOutBounds.width() * shrinkRatio));
|
||||
int adjustedHeight = Math.max(layoutMinHeight,
|
||||
(int) (inOutBounds.height() * shrinkRatio));
|
||||
if (stableBounds.width() < adjustedWidth
|
||||
|| stableBounds.height() < adjustedHeight) {
|
||||
// There is no way for us to fit the bounds in the displayArea without breaking min
|
||||
// size constraints. Set the min size to make visible as much content as possible.
|
||||
final int left = layoutDirection == View.LAYOUT_DIRECTION_RTL
|
||||
? stableBounds.right - adjustedWidth
|
||||
: stableBounds.left;
|
||||
inOutBounds.set(left, stableBounds.top, left + adjustedWidth,
|
||||
stableBounds.top + adjustedHeight);
|
||||
return;
|
||||
}
|
||||
inOutBounds.set(inOutBounds.left, inOutBounds.top,
|
||||
inOutBounds.left + adjustedWidth, inOutBounds.top + adjustedHeight);
|
||||
}
|
||||
|
||||
final int dx;
|
||||
|
||||
@@ -768,9 +768,10 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
|
||||
// to the center of suggested bounds (or the displayArea if no suggested bounds). The
|
||||
// default size might be too big to center to source activity bounds in displayArea, so
|
||||
// we may need to move it back to the displayArea.
|
||||
adjustBoundsToFitInDisplayArea(displayArea, layout, mTmpBounds);
|
||||
inOutBounds.setEmpty();
|
||||
LaunchParamsUtil.centerBounds(displayArea, mTmpBounds.width(), mTmpBounds.height(),
|
||||
inOutBounds);
|
||||
adjustBoundsToFitInDisplayArea(displayArea, layout, inOutBounds);
|
||||
if (DEBUG) appendLog("freeform-size-mismatch=" + inOutBounds);
|
||||
}
|
||||
|
||||
@@ -821,8 +822,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
|
||||
@NonNull Rect inOutBounds) {
|
||||
final int layoutDirection = mSupervisor.mRootWindowContainer.getConfiguration()
|
||||
.getLayoutDirection();
|
||||
displayArea.getStableRect(mTmpStableBounds);
|
||||
LaunchParamsUtil.adjustBoundsToFitInDisplayArea(mTmpStableBounds, layoutDirection, layout,
|
||||
LaunchParamsUtil.adjustBoundsToFitInDisplayArea(displayArea, layoutDirection, layout,
|
||||
inOutBounds);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,11 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
|
||||
private static final Rect DISPLAY_STABLE_BOUNDS = new Rect(/* left */ 100,
|
||||
/* top */ 200, /* right */ 1620, /* bottom */ 680);
|
||||
|
||||
private static final Rect SMALL_DISPLAY_BOUNDS = new Rect(/* left */ 0, /* top */ 0,
|
||||
/* right */ 1000, /* bottom */ 500);
|
||||
private static final Rect SMALL_DISPLAY_STABLE_BOUNDS = new Rect(/* left */ 100,
|
||||
/* top */ 50, /* right */ 900, /* bottom */ 450);
|
||||
|
||||
private ActivityRecord mActivity;
|
||||
|
||||
private TaskLaunchParamsModifier mTarget;
|
||||
@@ -1345,6 +1350,20 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
|
||||
DISPLAY_STABLE_BOUNDS.bottom - mResult.mBounds.bottom, /* delta */ 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultFreeformSizeShrinksOnSmallDisplay() {
|
||||
final TestDisplayContent freeformDisplay = createNewDisplayContent(
|
||||
WINDOWING_MODE_FREEFORM, SMALL_DISPLAY_BOUNDS, SMALL_DISPLAY_STABLE_BOUNDS);
|
||||
|
||||
final ActivityOptions options = ActivityOptions.makeBasic();
|
||||
options.setLaunchDisplayId(freeformDisplay.mDisplayId);
|
||||
|
||||
assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setOptions(options)
|
||||
.calculate());
|
||||
|
||||
assertEquals(new Rect(414, 77, 587, 423), mResult.mBounds);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultFreeformSizeRespectsMinAspectRatio() {
|
||||
final TestDisplayContent freeformDisplay = createNewDisplayContent(
|
||||
@@ -1535,16 +1554,15 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
|
||||
options.setLaunchDisplayId(freeformDisplay.mDisplayId);
|
||||
|
||||
mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
|
||||
mCurrent.mBounds.set(100, 300, 1820, 1380);
|
||||
mCurrent.mBounds.set(0, 0, 3000, 2000);
|
||||
|
||||
mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
|
||||
|
||||
assertEquals(RESULT_CONTINUE,
|
||||
new CalculateRequestBuilder().setOptions(options).calculate());
|
||||
|
||||
assertTrue("Result bounds should start from app bounds's origin, but it's "
|
||||
+ mResult.mBounds,
|
||||
mResult.mBounds.left == 100 && mResult.mBounds.top == 200);
|
||||
// Must shrink to fit the display while reserving aspect ratio.
|
||||
assertEquals(new Rect(127, 227, 766, 653), mResult.mBounds);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1560,18 +1578,19 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
|
||||
|
||||
final ActivityOptions options = ActivityOptions.makeBasic();
|
||||
options.setLaunchDisplayId(freeformDisplay.mDisplayId);
|
||||
final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
|
||||
.setMinWidth(500).setMinHeight(500).build();
|
||||
|
||||
mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
|
||||
mCurrent.mBounds.set(100, 300, 1820, 1380);
|
||||
mCurrent.mBounds.set(0, 0, 2000, 3000);
|
||||
|
||||
mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
|
||||
|
||||
assertEquals(RESULT_CONTINUE,
|
||||
new CalculateRequestBuilder().setOptions(options).calculate());
|
||||
new CalculateRequestBuilder().setOptions(options).setLayout(layout).calculate());
|
||||
|
||||
assertTrue("Result bounds should start from top-right corner of app bounds, but "
|
||||
+ "it's " + mResult.mBounds,
|
||||
mResult.mBounds.left == -100 && mResult.mBounds.top == 200);
|
||||
// Must shrink to fit the display while reserving aspect ratio.
|
||||
assertEquals(new Rect(1093, 227, 1593, 727), mResult.mBounds);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1746,7 +1765,7 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
|
||||
assertEquals(RESULT_CONTINUE,
|
||||
new CalculateRequestBuilder().setOptions(options).calculate());
|
||||
|
||||
assertEquals(new Rect(100, 200, 400, 500), mResult.mBounds);
|
||||
assertEquals(new Rect(127, 227, 427, 527), mResult.mBounds);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1799,13 +1818,18 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
|
||||
}
|
||||
|
||||
private TestDisplayContent createNewDisplayContent(int windowingMode) {
|
||||
return createNewDisplayContent(windowingMode, DISPLAY_BOUNDS, DISPLAY_STABLE_BOUNDS);
|
||||
}
|
||||
|
||||
private TestDisplayContent createNewDisplayContent(int windowingMode, Rect displayBounds,
|
||||
Rect displayStableBounds) {
|
||||
final TestDisplayContent display = addNewDisplayContentAt(DisplayContent.POSITION_TOP);
|
||||
display.getDefaultTaskDisplayArea().setWindowingMode(windowingMode);
|
||||
display.setBounds(DISPLAY_BOUNDS);
|
||||
display.setBounds(displayBounds);
|
||||
display.getConfiguration().densityDpi = DENSITY_DEFAULT;
|
||||
display.getConfiguration().orientation = ORIENTATION_LANDSCAPE;
|
||||
configInsetsState(display.getInsetsStateController().getRawInsetsState(), display,
|
||||
DISPLAY_STABLE_BOUNDS);
|
||||
displayStableBounds);
|
||||
return display;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user