Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 233a1fe1 authored by mattsziklay's avatar mattsziklay
Browse files

Update handle menu coordinates properly on rotate.

Changes AdditionalSystemViewContainer's setPosition to use
WindowManager's updateViewLayout to properly update LayoutParams.

Additionally, calculates global HandleMenu coordinates using more
variables from WindowDecoraiton.RelayoutResult to ensure correct
positioning on display rotation. Previously, task bounds were used which
may not have updated by the time the HandleMenu relayout occurred.

Bug: 341366352
Test: manual
Flag: EXEMPT bugfix
Change-Id: Ie1484dee5c517d7b5312e4190b3165eba06755b0
parent 44acf2ef
Loading
Loading
Loading
Loading
+4 −2
Original line number Original line Diff line number Diff line
@@ -337,7 +337,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        }
        }


        if (isHandleMenuActive()) {
        if (isHandleMenuActive()) {
            mHandleMenu.relayout(startT);
            mHandleMenu.relayout(startT, mResult.mCaptionX);
        }
        }


        updateRelayoutParams(mRelayoutParams, mContext, taskInfo, applyStartTransactionOnDraw,
        updateRelayoutParams(mRelayoutParams, mContext, taskInfo, applyStartTransactionOnDraw,
@@ -863,7 +863,9 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
                splitScreenController,
                splitScreenController,
                DesktopModeStatus.canEnterDesktopMode(mContext),
                DesktopModeStatus.canEnterDesktopMode(mContext),
                browserLinkAvailable(),
                browserLinkAvailable(),
                mResult.mCaptionHeight
                mResult.mCaptionWidth,
                mResult.mCaptionHeight,
                mResult.mCaptionX
        );
        );
        mWindowDecorViewHolder.onHandleMenuOpened();
        mWindowDecorViewHolder.onHandleMenuOpened();
        mHandleMenu.show();
        mHandleMenu.show();
+16 −13
Original line number Original line Diff line number Diff line
@@ -69,7 +69,9 @@ class HandleMenu(
    private val splitScreenController: SplitScreenController,
    private val splitScreenController: SplitScreenController,
    private val shouldShowWindowingPill: Boolean,
    private val shouldShowWindowingPill: Boolean,
    private val shouldShowBrowserPill: Boolean,
    private val shouldShowBrowserPill: Boolean,
    private val captionHeight: Int
    private val captionWidth: Int,
    private val captionHeight: Int,
    captionX: Int
) {
) {
    private val context: Context = parentDecor.mDecorWindowContext
    private val context: Context = parentDecor.mDecorWindowContext
    private val taskInfo: ActivityManager.RunningTaskInfo = parentDecor.mTaskInfo
    private val taskInfo: ActivityManager.RunningTaskInfo = parentDecor.mTaskInfo
@@ -105,7 +107,7 @@ class HandleMenu(
    private val globalMenuPosition: Point = Point()
    private val globalMenuPosition: Point = Point()


    init {
    init {
        updateHandleMenuPillPositions()
        updateHandleMenuPillPositions(captionX)
    }
    }


    fun show() {
    fun show() {
@@ -262,11 +264,11 @@ class HandleMenu(
    /**
    /**
     * Updates handle menu's position variables to reflect its next position.
     * Updates handle menu's position variables to reflect its next position.
     */
     */
    private fun updateHandleMenuPillPositions() {
    private fun updateHandleMenuPillPositions(captionX: Int) {
        val menuX: Int
        val menuX: Int
        val menuY: Int
        val menuY: Int
        val taskBounds = taskInfo.getConfiguration().windowConfiguration.bounds
        val taskBounds = taskInfo.getConfiguration().windowConfiguration.bounds
        updateGlobalMenuPosition(taskBounds)
        updateGlobalMenuPosition(taskBounds, captionX)
        if (layoutResId == R.layout.desktop_mode_app_header) {
        if (layoutResId == R.layout.desktop_mode_app_header) {
            // Align the handle menu to the left side of the caption.
            // Align the handle menu to the left side of the caption.
            menuX = marginMenuStart
            menuX = marginMenuStart
@@ -287,7 +289,8 @@ class HandleMenu(
        handleMenuPosition.set(menuX.toFloat(), menuY.toFloat())
        handleMenuPosition.set(menuX.toFloat(), menuY.toFloat())
    }
    }


    private fun updateGlobalMenuPosition(taskBounds: Rect) {
    private fun updateGlobalMenuPosition(taskBounds: Rect, captionX: Int) {
        val nonFreeformX = captionX + (captionWidth / 2) - (menuWidth / 2)
        when {
        when {
            taskInfo.isFreeform -> {
            taskInfo.isFreeform -> {
                globalMenuPosition.set(
                globalMenuPosition.set(
@@ -297,7 +300,7 @@ class HandleMenu(
            }
            }
            taskInfo.isFullscreen -> {
            taskInfo.isFullscreen -> {
                globalMenuPosition.set(
                globalMenuPosition.set(
                    /* x = */ taskBounds.width() / 2 - (menuWidth / 2),
                    /* x = */ nonFreeformX,
                    /* y = */ marginMenuTop
                    /* y = */ marginMenuTop
                )
                )
            }
            }
@@ -311,16 +314,13 @@ class HandleMenu(
                when (splitPosition) {
                when (splitPosition) {
                    SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT -> {
                    SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT -> {
                        globalMenuPosition.set(
                        globalMenuPosition.set(
                            /* x = */ leftOrTopStageBounds.width()
                            /* x = */ leftOrTopStageBounds.width() + nonFreeformX,
                                    + (rightOrBottomStageBounds.width() / 2)
                                    - (menuWidth / 2),
                            /* y = */ marginMenuTop
                            /* y = */ marginMenuTop
                        )
                        )
                    }
                    }
                    SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT -> {
                    SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT -> {
                        globalMenuPosition.set(
                        globalMenuPosition.set(
                            /* x = */ (leftOrTopStageBounds.width() / 2)
                            /* x = */ nonFreeformX,
                                    - (menuWidth / 2),
                            /* y = */ marginMenuTop
                            /* y = */ marginMenuTop
                        )
                        )
                    }
                    }
@@ -332,9 +332,12 @@ class HandleMenu(
    /**
    /**
     * Update pill layout, in case task changes have caused positioning to change.
     * Update pill layout, in case task changes have caused positioning to change.
     */
     */
    fun relayout(t: SurfaceControl.Transaction) {
    fun relayout(
        t: SurfaceControl.Transaction,
        captionX: Int
    ) {
        handleMenuViewContainer?.let { container ->
        handleMenuViewContainer?.let { container ->
            updateHandleMenuPillPositions()
            updateHandleMenuPillPositions(captionX)
            container.setPosition(t, handleMenuPosition.x, handleMenuPosition.y)
            container.setPosition(t, handleMenuPosition.x, handleMenuPosition.y)
        }
        }
    }
    }
+4 −4
Original line number Original line Diff line number Diff line
@@ -38,6 +38,7 @@ class AdditionalSystemViewContainer(
    height: Int
    height: Int
) : AdditionalViewContainer() {
) : AdditionalViewContainer() {
    override val view: View
    override val view: View
    val windowManager: WindowManager? = context.getSystemService(WindowManager::class.java)


    init {
    init {
        view = LayoutInflater.from(context).inflate(layoutId, null)
        view = LayoutInflater.from(context).inflate(layoutId, null)
@@ -51,12 +52,11 @@ class AdditionalSystemViewContainer(
            gravity = Gravity.LEFT or Gravity.TOP
            gravity = Gravity.LEFT or Gravity.TOP
            setTrustedOverlay()
            setTrustedOverlay()
        }
        }
        val wm: WindowManager? = context.getSystemService(WindowManager::class.java)
        windowManager?.addView(view, lp)
        wm?.addView(view, lp)
    }
    }


    override fun releaseView() {
    override fun releaseView() {
        context.getSystemService(WindowManager::class.java)?.removeViewImmediate(view)
        windowManager?.removeViewImmediate(view)
    }
    }


    override fun setPosition(t: SurfaceControl.Transaction, x: Float, y: Float) {
    override fun setPosition(t: SurfaceControl.Transaction, x: Float, y: Float) {
@@ -64,6 +64,6 @@ class AdditionalSystemViewContainer(
            this.x = x.toInt()
            this.x = x.toInt()
            this.y = y.toInt()
            this.y = y.toInt()
        }
        }
        view.layoutParams = lp
        windowManager?.updateViewLayout(view, lp)
    }
    }
}
}
+22 −7
Original line number Original line Diff line number Diff line
@@ -130,7 +130,7 @@ class HandleMenuTest : ShellTestCase() {
    @EnableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
    @EnableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
    fun testFullscreenMenuUsesSystemViewContainer() {
    fun testFullscreenMenuUsesSystemViewContainer() {
        createTaskInfo(WINDOWING_MODE_FULLSCREEN, SPLIT_POSITION_UNDEFINED)
        createTaskInfo(WINDOWING_MODE_FULLSCREEN, SPLIT_POSITION_UNDEFINED)
        val handleMenu = createAndShowHandleMenu()
        val handleMenu = createAndShowHandleMenu(SPLIT_POSITION_UNDEFINED)
        assertTrue(handleMenu.handleMenuViewContainer is AdditionalSystemViewContainer)
        assertTrue(handleMenu.handleMenuViewContainer is AdditionalSystemViewContainer)
        // Verify menu is created at coordinates that, when added to WindowManager,
        // Verify menu is created at coordinates that, when added to WindowManager,
        // show at the top-center of display.
        // show at the top-center of display.
@@ -142,7 +142,7 @@ class HandleMenuTest : ShellTestCase() {
    @EnableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
    @EnableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
    fun testFreeformMenu_usesViewHostViewContainer() {
    fun testFreeformMenu_usesViewHostViewContainer() {
        createTaskInfo(WINDOWING_MODE_FREEFORM, SPLIT_POSITION_UNDEFINED)
        createTaskInfo(WINDOWING_MODE_FREEFORM, SPLIT_POSITION_UNDEFINED)
        handleMenu = createAndShowHandleMenu()
        handleMenu = createAndShowHandleMenu(SPLIT_POSITION_UNDEFINED)
        assertTrue(handleMenu.handleMenuViewContainer is AdditionalViewHostViewContainer)
        assertTrue(handleMenu.handleMenuViewContainer is AdditionalViewHostViewContainer)
        // Verify menu is created near top-left of task.
        // Verify menu is created near top-left of task.
        val expected = Point(MENU_START_MARGIN, MENU_TOP_MARGIN)
        val expected = Point(MENU_START_MARGIN, MENU_TOP_MARGIN)
@@ -153,7 +153,7 @@ class HandleMenuTest : ShellTestCase() {
    @EnableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
    @EnableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
    fun testSplitLeftMenu_usesSystemViewContainer() {
    fun testSplitLeftMenu_usesSystemViewContainer() {
        createTaskInfo(WINDOWING_MODE_MULTI_WINDOW, SPLIT_POSITION_TOP_OR_LEFT)
        createTaskInfo(WINDOWING_MODE_MULTI_WINDOW, SPLIT_POSITION_TOP_OR_LEFT)
        handleMenu = createAndShowHandleMenu()
        handleMenu = createAndShowHandleMenu(SPLIT_POSITION_TOP_OR_LEFT)
        assertTrue(handleMenu.handleMenuViewContainer is AdditionalSystemViewContainer)
        assertTrue(handleMenu.handleMenuViewContainer is AdditionalSystemViewContainer)
        // Verify menu is created at coordinates that, when added to WindowManager,
        // Verify menu is created at coordinates that, when added to WindowManager,
        // show at the top-center of split left task.
        // show at the top-center of split left task.
@@ -168,7 +168,7 @@ class HandleMenuTest : ShellTestCase() {
    @EnableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
    @EnableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
    fun testSplitRightMenu_usesSystemViewContainer() {
    fun testSplitRightMenu_usesSystemViewContainer() {
        createTaskInfo(WINDOWING_MODE_MULTI_WINDOW, SPLIT_POSITION_BOTTOM_OR_RIGHT)
        createTaskInfo(WINDOWING_MODE_MULTI_WINDOW, SPLIT_POSITION_BOTTOM_OR_RIGHT)
        handleMenu = createAndShowHandleMenu()
        handleMenu = createAndShowHandleMenu(SPLIT_POSITION_BOTTOM_OR_RIGHT)
        assertTrue(handleMenu.handleMenuViewContainer is AdditionalSystemViewContainer)
        assertTrue(handleMenu.handleMenuViewContainer is AdditionalSystemViewContainer)
        // Verify menu is created at coordinates that, when added to WindowManager,
        // Verify menu is created at coordinates that, when added to WindowManager,
        // show at the top-center of split right task.
        // show at the top-center of split right task.
@@ -208,16 +208,30 @@ class HandleMenuTest : ShellTestCase() {
        }
        }
    }
    }


    private fun createAndShowHandleMenu(): HandleMenu {
    private fun createAndShowHandleMenu(splitPosition: Int): HandleMenu {
        val layoutId = if (mockDesktopWindowDecoration.mTaskInfo.isFreeform) {
        val layoutId = if (mockDesktopWindowDecoration.mTaskInfo.isFreeform) {
            R.layout.desktop_mode_app_header
            R.layout.desktop_mode_app_header
        } else {
        } else {
            R.layout.desktop_mode_app_handle
            R.layout.desktop_mode_app_handle
        }
        }
        val captionX = when (mockDesktopWindowDecoration.mTaskInfo.windowingMode) {
            WINDOWING_MODE_FULLSCREEN -> (DISPLAY_BOUNDS.width() / 2) - (HANDLE_WIDTH / 2)
            WINDOWING_MODE_FREEFORM -> 0
            WINDOWING_MODE_MULTI_WINDOW -> {
                if (splitPosition == SPLIT_POSITION_TOP_OR_LEFT) {
                    (SPLIT_LEFT_BOUNDS.width() / 2) - (HANDLE_WIDTH / 2)
                } else {
                    (SPLIT_RIGHT_BOUNDS.width() / 2) - (HANDLE_WIDTH / 2)
                }
            }
            else -> error("Invalid windowing mode")
        }
        val handleMenu = HandleMenu(mockDesktopWindowDecoration, layoutId,
        val handleMenu = HandleMenu(mockDesktopWindowDecoration, layoutId,
                onClickListener, onTouchListener, appIcon, appName, displayController,
                onClickListener, onTouchListener, appIcon, appName, displayController,
                splitScreenController, true /* shouldShowWindowingPill */,
                splitScreenController, shouldShowWindowingPill = true,
                true /* shouldShowBrowserPill */, 50 /* captionHeight */)
                shouldShowBrowserPill = true, captionWidth = HANDLE_WIDTH, captionHeight = 50,
                captionX = captionX
        )
        handleMenu.show()
        handleMenu.show()
        return handleMenu
        return handleMenu
    }
    }
@@ -233,5 +247,6 @@ class HandleMenuTest : ShellTestCase() {
        private const val MENU_START_MARGIN = 20
        private const val MENU_START_MARGIN = 20
        private const val MENU_PILL_ELEVATION = 2
        private const val MENU_PILL_ELEVATION = 2
        private const val MENU_PILL_SPACING_MARGIN = 4
        private const val MENU_PILL_SPACING_MARGIN = 4
        private const val HANDLE_WIDTH = 80
    }
    }
}
}