diff --git a/src/com/android/settings/connecteddevice/display/DisplayTopology.kt b/src/com/android/settings/connecteddevice/display/DisplayTopology.kt index d483f4624d7..162d9d284fb 100644 --- a/src/com/android/settings/connecteddevice/display/DisplayTopology.kt +++ b/src/com/android/settings/connecteddevice/display/DisplayTopology.kt @@ -59,12 +59,14 @@ class TopologyScale(paneWidth : Int, displaysPos : Collection) { val displayBounds = RectF( Float.MAX_VALUE, Float.MAX_VALUE, Float.MIN_VALUE, Float.MIN_VALUE) var smallestDisplayDim = Float.MAX_VALUE + var biggestDisplayHeight = Float.MIN_VALUE // displayBounds is the smallest rect encompassing all displays, in display space. // smallestDisplayDim is the size of the smallest display edge, in display space. for (pos in displaysPos) { displayBounds.union(pos) smallestDisplayDim = minOf(smallestDisplayDim, pos.height(), pos.width()) + biggestDisplayHeight = max(biggestDisplayHeight, pos.height()) } // Set height according to the width and the aspect ratio of the display bounds. @@ -81,9 +83,17 @@ class TopologyScale(paneWidth : Int, displaysPos : Collection) { // Essentially, we just set the pane height based on the pre-determined pane width and the // aspect ratio of the display bounds. But we may need to increase it slightly to achieve // 20% padding above and below the display bounds - this is where the 0.6 comes from. - paneHeight = max( + val rawPaneHeight = max( paneWidth.toDouble() / displayBounds.width() * displayBounds.height(), - displayBounds.height() * blockRatio / 0.6).toInt() + displayBounds.height() * blockRatio / 0.6) + + // It is easy for the aspect ratio to result in an excessively tall pane, since the width is + // pre-determined and may be considerably wider than necessary. So we prevent the height + // from growing too large here, by limiting vertical padding to the size of the tallest + // display. This improves results for very tall display bounds. + paneHeight = min( + rawPaneHeight.toInt(), + (blockRatio * (displayBounds.height() + biggestDisplayHeight * 2f)).toInt()) // Set originPaneXY (the location of 0,0 in display space in the pane's coordinate system) // such that the display bounds rect is centered in the pane. diff --git a/tests/robotests/src/com/android/settings/connecteddevice/display/TopologyScaleTest.kt b/tests/robotests/src/com/android/settings/connecteddevice/display/TopologyScaleTest.kt index e02cd40650c..078436264e7 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/display/TopologyScaleTest.kt +++ b/tests/robotests/src/com/android/settings/connecteddevice/display/TopologyScaleTest.kt @@ -40,11 +40,11 @@ class TopologyScaleTest { // blockRatio is higher than 0.05 in order to make the smallest display edge (480 dp) 48dp // in the pane. assertEquals( - "{TopoScale blockRatio=0.100000 originPaneXY=288,216 paneHeight=480}", "" + scale) + "{TopoScale blockRatio=0.100000 originPaneXY=288,48 paneHeight=144}", "" + scale) - assertEquals(Point(352, 264), scale.displayToPaneCoor(PointF(640f, 480f))) - assertEquals(Point(320, 240), scale.displayToPaneCoor(PointF(320f, 240f))) - assertEquals(PointF(640f, 480f), scale.paneToDisplayCoor(Point(352, 264))) + assertEquals(Point(352, 96), scale.displayToPaneCoor(PointF(640f, 480f))) + assertEquals(Point(320, 72), scale.displayToPaneCoor(PointF(320f, 240f))) + assertEquals(PointF(640f, 480f), scale.paneToDisplayCoor(Point(352, 96))) } @Test @@ -76,4 +76,22 @@ class TopologyScaleTest { assertEquals(Point(96, 64), scale.displayToPaneCoor(PointF(0f, -320f))) assertPointF(220f, -430f, 0.001f, scale.paneToDisplayCoor(Point(140, 42))) } + + @Test + fun paneVerticalPaddingLimitedByTallestDisplay() { + val scale = TopologyScale( + /* paneWidth= */ 300, + listOf( + RectF(0f, 0f, 640f, 480f), + RectF(0f, 480f, 640f, 960f), + RectF(0f, 960f, 640f, 1440f), + RectF(0f, 1440f, 640f, 1920f), + RectF(0f, 1920f, 640f, 2400f), + RectF(0f, 2400f, 640f, 2880f))) + + assertEquals( + "{TopoScale blockRatio=0.100000 originPaneXY=118,48 paneHeight=384}", "" + scale) + assertEquals(Point(150, 48), scale.displayToPaneCoor(PointF(320f, 0f))) + assertPointF(-180f, 2880f, 0.001f, scale.paneToDisplayCoor(Point(100, 336))) + } }