diff options
| author | 2024-11-18 10:00:55 +0000 | |
|---|---|---|
| committer | 2024-11-21 11:33:58 +0000 | |
| commit | b39c74af863b22b9b893dae243712a522f220ce9 (patch) | |
| tree | d8362f66189e160fc2b5fa0fc0709e69052482a5 | |
| parent | 27e0567259fbd5a8a6fcce8b9501dab84aeba1dd (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
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 } } |