summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Pierre Barbier de Reuille <pbdr@google.com> 2024-11-18 10:00:55 +0000
committer Pierre Barbier de Reuille <pbdr@google.com> 2024-11-21 11:33:58 +0000
commitb39c74af863b22b9b893dae243712a522f220ce9 (patch)
treed8362f66189e160fc2b5fa0fc0709e69052482a5
parent27e0567259fbd5a8a6fcce8b9501dab84aeba1dd (diff)
Fix the size of the handle and touch area.
Set the touch region correctly, including corners, divider and handle. Also increases the size of the handle. Fix: 377960322 Test: manual + existing tests Flag: com.android.window.flags.enable_tile_resizing Change-Id: I148e9b0117c0205fea71eef6bf9d4f042227ac4d
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManager.kt89
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/TilingDividerView.kt31
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManagerTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/TilingDividerViewTest.kt16
4 files changed, 106 insertions, 32 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManager.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManager.kt
index 6cdc517c9cb7..583282247f58 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManager.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManager.kt
@@ -18,10 +18,12 @@ package com.android.wm.shell.windowdecor.tiling
import android.content.Context
import android.content.res.Configuration
+import android.graphics.Path
import android.graphics.PixelFormat
import android.graphics.Rect
import android.graphics.Region
import android.os.Binder
+import android.util.Size
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.RoundedCorner
@@ -40,7 +42,6 @@ import android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER
import android.view.WindowlessWindowManager
import com.android.wm.shell.R
import com.android.wm.shell.common.SyncTransactionQueue
-import com.android.wm.shell.desktopmode.DesktopModeEventLogger
import java.util.function.Supplier
/**
@@ -48,7 +49,7 @@ import java.util.function.Supplier
* when two tasks are tiled on left and right to resize them simultaneously.
*/
class DesktopTilingDividerWindowManager(
- private val config: Configuration,
+ config: Configuration,
private val windowName: String,
private val context: Context,
private val leash: SurfaceControl,
@@ -61,7 +62,11 @@ class DesktopTilingDividerWindowManager(
private lateinit var viewHost: SurfaceControlViewHost
private var tilingDividerView: TilingDividerView? = null
private var dividerShown = false
- private var handleRegionWidth: Int = -1
+ private var handleRegionSize: Size =
+ Size(
+ context.resources.getDimensionPixelSize(R.dimen.split_divider_handle_region_width),
+ context.resources.getDimensionPixelSize(R.dimen.split_divider_handle_region_height),
+ )
private var setTouchRegion = true
private val maxRoundedCornerRadius = getMaxRoundedCornerRadius()
@@ -74,9 +79,62 @@ class DesktopTilingDividerWindowManager(
rect.set(dividerBounds)
}
- /** Sets the touch region for the SurfaceControlViewHost. */
- fun setTouchRegion(region: Rect) {
- setTouchRegion(viewHost.windowToken.asBinder(), Region(region))
+ /**
+ * Sets the touch region for the SurfaceControlViewHost.
+ *
+ * The region includes the area around the handle (for accessibility), the divider itself and
+ * the rounded corners (to prevent click reaching windows behind).
+ */
+ fun setTouchRegion(handle: Rect, divider: Rect, cornerRadius: Float) {
+ val path = Path()
+ path.fillType = Path.FillType.WINDING
+ // The UI starts on the top-left corner, the region will be:
+ //
+ // cornerLeft cornerRight
+ // c1Top +--------+
+ // |corners |
+ // c1Bottom +--+ +--+
+ // | |
+ // handleLeft| | handleRight
+ // handleTop +----+ +----+
+ // | handle |
+ // handleBot +----+ +----+
+ // | |
+ // | |
+ // c2Top +--+ +--+
+ // |corners |
+ // c2Bottom +--------+
+ val cornerLeft = 0f
+ val centerX = cornerRadius + divider.width() / 2f
+ val centerY = divider.height()
+ val cornerRight = divider.width() + 2 * cornerRadius
+ val handleLeft = centerX - handle.width() / 2f
+ val handleRight = handleLeft + handle.width()
+ val dividerLeft = centerY - divider.width() / 2f
+ val dividerRight = dividerLeft + divider.width()
+
+ val c1Top = 0f
+ val c1Bottom = cornerRadius
+ val handleTop = centerY - handle.height() / 2f
+ val handleBottom = handleTop + handle.height()
+ val c2Top = divider.height() - cornerRadius
+ val c2Bottom = divider.height().toFloat()
+
+ // Top corners
+ path.addRect(cornerLeft, c1Top, cornerRight, c1Bottom, Path.Direction.CCW)
+ // Bottom corners
+ path.addRect(cornerLeft, c1Top, cornerRight, c2Bottom, Path.Direction.CCW)
+ // Handle
+ path.addRect(handleLeft, handleTop, handleRight, handleBottom, Path.Direction.CCW)
+ // Divider
+ path.addRect(dividerLeft, c2Top, dividerRight, c2Bottom, Path.Direction.CCW)
+
+ val clip = Rect(handleLeft.toInt(), c1Top.toInt(), handleRight.toInt(), c2Bottom.toInt())
+
+ val region = Region()
+ region.setPath(path, Region(clip))
+
+ setTouchRegion(viewHost.windowToken.asBinder(), region)
}
/**
@@ -96,7 +154,7 @@ class DesktopTilingDividerWindowManager(
surfaceControlViewHost.setView(dividerView, lp)
val tmpDividerBounds = Rect()
getDividerBounds(tmpDividerBounds)
- dividerView.setup(this, tmpDividerBounds)
+ dividerView.setup(this, tmpDividerBounds, handleRegionSize)
t.setRelativeLayer(leash, relativeLeash, 1)
.setPosition(
leash,
@@ -112,7 +170,7 @@ class DesktopTilingDividerWindowManager(
viewHost = surfaceControlViewHost
dividerView.addOnLayoutChangeListener(this)
tilingDividerView = dividerView
- handleRegionWidth = dividerView.handleRegionWidth
+ updateTouchRegion()
}
/** Hides the divider bar. */
@@ -176,8 +234,8 @@ class DesktopTilingDividerWindowManager(
private fun getWindowManagerParams(): WindowManager.LayoutParams {
val lp =
WindowManager.LayoutParams(
- dividerBounds.width() + 2 * maxRoundedCornerRadius,
- dividerBounds.height(),
+ /* w= */ dividerBounds.width() + 2 * maxRoundedCornerRadius,
+ /* h= */ dividerBounds.height(),
TYPE_DOCK_DIVIDER,
FLAG_NOT_FOCUSABLE or
FLAG_NOT_TOUCH_MODAL or
@@ -216,13 +274,16 @@ class DesktopTilingDividerWindowManager(
) {
if (!setTouchRegion) return
- val startX = (dividerBounds.width() - handleRegionWidth) / 2
- val startY = 0
- val tempRect = Rect(startX, startY, startX + handleRegionWidth, dividerBounds.height())
- setTouchRegion(tempRect)
+ updateTouchRegion()
setTouchRegion = false
}
+ private fun updateTouchRegion() {
+ val startX = -handleRegionSize.width / 2
+ val handle = Rect(startX, 0, startX + handleRegionSize.width, dividerBounds.height())
+ setTouchRegion(handle, dividerBounds, maxRoundedCornerRadius.toFloat())
+ }
+
private fun setSlippery(slippery: Boolean) {
val lp = tilingDividerView?.layoutParams as WindowManager.LayoutParams
val isSlippery = (lp.flags and FLAG_SLIPPERY) != 0
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/TilingDividerView.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/TilingDividerView.kt
index 111e28e450bd..b8e3b0fdb8d8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/TilingDividerView.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/tiling/TilingDividerView.kt
@@ -21,8 +21,10 @@ import android.graphics.Paint
import android.graphics.Rect
import android.provider.DeviceConfig
import android.util.AttributeSet
+import android.util.Size
import android.view.MotionEvent
import android.view.PointerIcon
+import android.view.RoundedCorner
import android.view.View
import android.view.ViewConfiguration
import android.widget.FrameLayout
@@ -42,6 +44,7 @@ class TilingDividerView : FrameLayout, View.OnTouchListener, DragDetector.Motion
private lateinit var callback: DividerMoveCallback
private lateinit var handle: DividerHandleView
private lateinit var corners: DividerRoundedCorner
+ private var cornersRadius: Int = 0
private var touchElevation = 0
private var moving = false
@@ -49,8 +52,7 @@ class TilingDividerView : FrameLayout, View.OnTouchListener, DragDetector.Motion
var handleRegionWidth: Int = 0
private var handleRegionHeight = 0
private var lastAcceptedPos = 0
- @VisibleForTesting var handleStartY = 0
- @VisibleForTesting var handleEndY = 0
+ @VisibleForTesting var handleY: IntRange = 0..0
private var canResize = false
private var resized = false
/**
@@ -79,16 +81,19 @@ class TilingDividerView : FrameLayout, View.OnTouchListener, DragDetector.Motion
) : super(context, attrs, defStyleAttr, defStyleRes)
/** Sets up essential dependencies of the divider bar. */
- fun setup(dividerMoveCallback: DividerMoveCallback, dividerBounds: Rect) {
+ fun setup(
+ dividerMoveCallback: DividerMoveCallback,
+ dividerBounds: Rect,
+ handleRegionSize: Size,
+ ) {
callback = dividerMoveCallback
this.dividerBounds.set(dividerBounds)
handle.setIsLeftRightSplit(true)
corners.setIsLeftRightSplit(true)
- handleRegionHeight =
- resources.getDimensionPixelSize(R.dimen.split_divider_handle_region_width)
-
- handleRegionWidth =
- resources.getDimensionPixelSize(R.dimen.split_divider_handle_region_height)
+ handleRegionHeight = handleRegionSize.height
+ handleRegionWidth = handleRegionSize.width
+ cornersRadius =
+ context.display.getRoundedCorner(RoundedCorner.POSITION_TOP_LEFT)?.radius ?: 0
initHandleYCoordinates()
dragDetector =
DragDetector(
@@ -241,17 +246,17 @@ class TilingDividerView : FrameLayout, View.OnTouchListener, DragDetector.Motion
return true
}
- private fun isWithinHandleRegion(touchYPos: Int): Boolean {
- return touchYPos in handleStartY..handleEndY
- }
+ private fun isWithinHandleRegion(touchYPos: Int): Boolean = touchYPos in handleY
private fun initHandleYCoordinates() {
- handleStartY = (dividerBounds.height() - handleRegionHeight) / 2
- handleEndY = handleStartY + handleRegionHeight
+ val handleStartY = (dividerBounds.height() - handleRegionHeight) / 2
+ val handleEndY = handleStartY + handleRegionHeight
+ handleY = handleStartY..handleEndY
}
companion object {
const val TOUCH_ANIMATION_DURATION: Long = 150
const val TOUCH_RELEASE_ANIMATION_DURATION: Long = 200
+ private val TAG = TilingDividerView::class.java.simpleName
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManagerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManagerTest.kt
index 3143946fa828..121e0e915d08 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManagerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/DesktopTilingDividerWindowManagerTest.kt
@@ -122,6 +122,6 @@ class DesktopTilingDividerWindowManagerTest : ShellTestCase() {
companion object {
private val BOUNDS = Rect(1, 2, 3, 4)
- private val CORNER_RADIUS = 28
+ private const val CORNER_RADIUS = 28
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/TilingDividerViewTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/TilingDividerViewTest.kt
index 734815cdd915..9a9d05a72442 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/TilingDividerViewTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/tiling/TilingDividerViewTest.kt
@@ -19,9 +19,12 @@ package com.android.wm.shell.windowdecor.tiling
import android.graphics.Rect
import android.os.SystemClock
import android.testing.AndroidTestingRunner
+import android.util.Size
+import android.view.Display
import android.view.InputDevice
import android.view.LayoutInflater
import android.view.MotionEvent
+import android.view.RoundedCorner
import android.view.View
import androidx.test.annotation.UiThreadTest
import androidx.test.filters.SmallTest
@@ -46,16 +49,19 @@ class TilingDividerViewTest : ShellTestCase() {
private val dividerMoveCallbackMock = mock<DividerMoveCallback>()
private val viewMock = mock<View>()
+ private val display = mock<Display>()
+ private val roundedCorner = mock<RoundedCorner>()
@Before
@UiThreadTest
fun setUp() {
+ whenever(display.getRoundedCorner(any())).thenReturn(roundedCorner)
+ whenever(roundedCorner.radius).thenReturn(CORNER_RADIUS)
tilingDividerView =
LayoutInflater.from(mContext).inflate(R.layout.tiling_split_divider, /* root= */ null)
as TilingDividerView
- tilingDividerView.setup(dividerMoveCallbackMock, BOUNDS)
- tilingDividerView.handleStartY = 0
- tilingDividerView.handleEndY = 1500
+ tilingDividerView.setup(dividerMoveCallbackMock, DIVIDER_BOUNDS, HANDLE_SIZE)
+ tilingDividerView.handleY = 0..1500
}
@Test
@@ -130,6 +136,8 @@ class TilingDividerViewTest : ShellTestCase() {
}
companion object {
- private val BOUNDS = Rect(0, 0, 1500, 1500)
+ private val DIVIDER_BOUNDS = Rect(15, 0, 35, 1500)
+ private val HANDLE_SIZE = Size(800, 300)
+ private const val CORNER_RADIUS = 15
}
}