diff --git a/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.kt b/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.kt index 67358bbb45..80b50cbd83 100644 --- a/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.kt +++ b/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.kt @@ -248,14 +248,14 @@ class SeascapePagedViewHandler : LandscapePagedViewHandler() { val iconCenter = iconAppChipView.getHeight() / 2f if (isRtl) { - iconMenuParams.gravity = Gravity.TOP or Gravity.END + iconMenuParams.gravity = Gravity.TOP or Gravity.START iconMenuParams.topMargin = iconMenuMargin iconMenuParams.marginEnd = thumbnailTopMargin // Use half menu height to place the pivot within the X/Y center of icon in the menu. iconAppChipView.pivotX = iconMenuParams.width / 2f iconAppChipView.pivotY = iconMenuParams.width / 2f } else { - iconMenuParams.gravity = Gravity.BOTTOM or Gravity.START + iconMenuParams.gravity = Gravity.BOTTOM or Gravity.END iconMenuParams.topMargin = 0 iconMenuParams.marginEnd = 0 iconAppChipView.pivotX = iconCenter @@ -409,7 +409,7 @@ class SeascapePagedViewHandler : LandscapePagedViewHandler() { if (Flags.enableOverviewIconMenu()) { val appChipView = iconView as IconAppChipView layoutParams.gravity = - if (isRtl) Gravity.TOP or Gravity.END else Gravity.BOTTOM or Gravity.START + if (isRtl) Gravity.TOP or Gravity.START else Gravity.BOTTOM or Gravity.END appChipView.layoutParams = layoutParams appChipView.setSplitTranslationX(0f) appChipView.setSplitTranslationY(translationY.toFloat()) diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt b/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt index 71a4dde395..10a2e902cb 100644 --- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt +++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt @@ -182,7 +182,6 @@ class GroupedTaskView @JvmOverloads constructor(context: Context, attrs: Attribu val splitBoundsConfig = splitBoundsConfig ?: return val deviceProfile = container.deviceProfile val taskIconHeight = deviceProfile.overviewTaskIconSizePx - val isRtl = layoutDirection == LAYOUT_DIRECTION_RTL val inSplitSelection = getThisTaskCurrentlyInSplitSelection() != INVALID_TASK_ID var oneIconHiddenDueToSmallWidth = false @@ -211,6 +210,7 @@ class GroupedTaskView @JvmOverloads constructor(context: Context, attrs: Attribu } if (enableOverviewIconMenu()) { + val isDeviceRtl = Utilities.isRtl(resources) val groupedTaskViewSizes = pagedOrientationHandler.getGroupedTaskViewSizes( deviceProfile, @@ -226,7 +226,7 @@ class GroupedTaskView @JvmOverloads constructor(context: Context, attrs: Attribu groupedTaskViewSizes.first.y, layoutParams.height, layoutParams.width, - isRtl, + isDeviceRtl, deviceProfile, splitBoundsConfig, inSplitSelection, @@ -241,7 +241,7 @@ class GroupedTaskView @JvmOverloads constructor(context: Context, attrs: Attribu leftTopTaskContainer.taskContentView.measuredHeight, measuredHeight, measuredWidth, - isRtl, + isLayoutRtl, deviceProfile, splitBoundsConfig, inSplitSelection, diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index c1df0fb1da..8c7fe26f3c 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -34,8 +34,6 @@ import static com.android.app.animation.Interpolators.FINAL_FRAME; import static com.android.app.animation.Interpolators.LINEAR; import static com.android.app.animation.Interpolators.clampToProgress; import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE; -import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU; -import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType; import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS; import static com.android.launcher3.Flags.enableAdditionalHomeAnimations; import static com.android.launcher3.Flags.enableDesktopExplodedView; @@ -834,7 +832,7 @@ public abstract class RecentsView< mOrientationState.setMultiWindowMode(inMultiWindowMode); setLayoutRotation(mOrientationState.getTouchRotation(), mOrientationState.getDisplayRotation()); - updateChildTaskOrientations(); + mUtils.updateChildTaskOrientations(); if (!inMultiWindowMode && mOverviewStateEnabled) { // TODO: Re-enable layout transitions for addition of the unpinned task reloadIfNeeded(); @@ -2092,7 +2090,7 @@ public abstract class RecentsView< traceBegin(Trace.TRACE_TAG_APP, "RecentsView.applyLoadPlan.layouts"); updateTaskSize(); - updateChildTaskOrientations(); + mUtils.updateChildTaskOrientations(); traceEnd(Trace.TRACE_TAG_APP); TaskView newRunningTaskView = mUtils.getDesktopTaskViewForDeskId(runningTaskViewDeskId); @@ -2344,7 +2342,7 @@ public abstract class RecentsView< updateSizeAndPadding(); // Update TaskView's DeviceProfile dependent layout. - updateChildTaskOrientations(); + mUtils.updateChildTaskOrientations(); requestLayout(); // Reapply the current page to update page scrolls. @@ -2952,22 +2950,6 @@ public abstract class RecentsView< return as; } - private void updateChildTaskOrientations() { - for (TaskView taskView : getTaskViews()) { - taskView.setOrientationState(mOrientationState); - } - boolean shouldRotateMenuForFakeRotation = - !mOrientationState.isRecentsActivityRotationAllowed(); - if (!shouldRotateMenuForFakeRotation) { - return; - } - AbstractFloatingView floatingView = getTopOpenViewWithType(mContainer, TYPE_TASK_MENU); - if (floatingView instanceof TaskMenuView taskMenuView) { - // Rotation is supported on phone (details at b/254198019#comment4) - taskMenuView.onRotationChanged(); - } - } - /** * Called when a gesture from an app has finished, and an end target has been determined. */ @@ -3205,7 +3187,7 @@ public abstract class RecentsView< setRunningTaskHidden(runningTaskTileHidden); // Update task size after setting current task. updateTaskSize(); - updateChildTaskOrientations(); + mUtils.updateChildTaskOrientations(); // Reload the task list reloadIfNeeded(); @@ -4358,7 +4340,7 @@ public abstract class RecentsView< finalNextFocusedTaskView.getDismissIconFadeInAnimator().start(); } updateTaskSize(); - updateChildTaskOrientations(); + mUtils.updateChildTaskOrientations(); // Update scroll and snap to page. updateScrollSynchronously(); @@ -7062,7 +7044,7 @@ public abstract class RecentsView< addView(desktopTaskView, insertionIndex); updateTaskSize(); - updateChildTaskOrientations(); + mUtils.updateChildTaskOrientations(); // TODO: b/401002178 - Recalculate the new current page such that the addition of the new // desk does not result in a change in the current scroll page. diff --git a/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt b/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt index 24b7fa7c81..9c35913841 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt +++ b/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt @@ -20,10 +20,13 @@ import android.graphics.Rect import android.util.FloatProperty import android.view.KeyEvent import android.view.View +import android.view.View.LAYOUT_DIRECTION_LTR +import android.view.View.LAYOUT_DIRECTION_RTL import androidx.core.view.children -import com.android.launcher3.AbstractFloatingView -import com.android.launcher3.Flags +import com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU +import com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType import com.android.launcher3.Flags.enableLargeDesktopWindowingTile +import com.android.launcher3.Flags.enableOverviewIconMenu import com.android.launcher3.Flags.enableSeparateExternalDisplayTasks import com.android.launcher3.statehandlers.DesktopVisibilityController import com.android.launcher3.statehandlers.DesktopVisibilityController.Companion.INACTIVE_DESK_ID @@ -357,18 +360,33 @@ class RecentsViewUtils(private val recentsView: RecentsView<*, *>) { } } + private fun getTaskMenu(): TaskMenuView? = + getTopOpenViewWithType(recentsView.mContainer, TYPE_TASK_MENU) as? TaskMenuView + fun shouldInterceptKeyEvent(event: KeyEvent): Boolean { - if (Flags.enableOverviewIconMenu()) { - val floatingView: AbstractFloatingView? = AbstractFloatingView.getTopOpenViewWithType( - recentsView.mContainer as RecentsViewContainer, - AbstractFloatingView.TYPE_TASK_MENU - ) - val isMenuOpen = floatingView?.isOpen - return isMenuOpen == true || event.keyCode == KeyEvent.KEYCODE_TAB + if (enableOverviewIconMenu()) { + return getTaskMenu()?.isOpen == true || event.keyCode == KeyEvent.KEYCODE_TAB } return false } + fun updateChildTaskOrientations() { + with(recentsView) { + taskViews.forEach { it.setOrientationState(mOrientationState) } + if (enableOverviewIconMenu()) { + children.forEach { + it.layoutDirection = if (isRtl) LAYOUT_DIRECTION_LTR else LAYOUT_DIRECTION_RTL + } + } + + // Return when it's not fake landscape + if (mOrientationState.isRecentsActivityRotationAllowed) return@with + + // Rotation is supported on phone (details at b/254198019#comment4) + getTaskMenu()?.onRotationChanged() + } + } + var deskExplodeProgress: Float = 0f set(value) { field = value diff --git a/quickstep/src/com/android/quickstep/views/TaskView.kt b/quickstep/src/com/android/quickstep/views/TaskView.kt index 0a373b560f..3d1643cefe 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.kt +++ b/quickstep/src/com/android/quickstep/views/TaskView.kt @@ -616,6 +616,16 @@ constructor( super.draw(canvas) } + override fun setLayoutDirection(layoutDirection: Int) { + super.setLayoutDirection(layoutDirection) + if (enableOverviewIconMenu()) { + val deviceLayoutDirection = resources.configuration.layoutDirection + taskContainers.forEach { + (it.iconView as IconAppChipView).layoutDirection = deviceLayoutDirection + } + } + } + override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { super.onLayout(changed, left, top, right, bottom) val thumbnailTopMargin = container.deviceProfile.overviewTaskThumbnailTopMarginPx diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/orientation/SeascapePagedViewHandlerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/orientation/SeascapePagedViewHandlerTest.kt index 37886888ea..d455b0d1e9 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/orientation/SeascapePagedViewHandlerTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/orientation/SeascapePagedViewHandlerTest.kt @@ -43,12 +43,12 @@ class SeascapePagedViewHandlerTest { if (isEnabled) { setFlagsRule.enableFlags( Flags.FLAG_ENABLE_GRID_ONLY_OVERVIEW, - Flags.FLAG_ENABLE_OVERVIEW_ICON_MENU + Flags.FLAG_ENABLE_OVERVIEW_ICON_MENU, ) } else { setFlagsRule.disableFlags( Flags.FLAG_ENABLE_GRID_ONLY_OVERVIEW, - Flags.FLAG_ENABLE_OVERVIEW_ICON_MENU + Flags.FLAG_ENABLE_OVERVIEW_ICON_MENU, ) } } @@ -110,12 +110,6 @@ class SeascapePagedViewHandlerTest { val (topLeftY, bottomRightY) = getSplitIconsPosition(isRTL = true) - // TODO(b/326377497): When started in fake seascape and rotated to landscape, - // the icon chips are in RTL and wrongly positioned at the right side of the snapshot. - // Top-Left app chip should be placed at the top left of the first snapshot, but because - // this issue, it's displayed at the top-right of the second snapshot. - // The Bottom-Right app chip is displayed at the top-right of the first snapshot because - // of this issue. assertThat(topLeftY).isEqualTo(316) assertThat(bottomRightY).isEqualTo(0) } @@ -167,7 +161,7 @@ class SeascapePagedViewHandlerTest { `when`(iconView.layoutParams).thenReturn(frameLayout) sut.updateSplitIconsPosition(iconView, expectedTranslationY, false) - assertThat(frameLayout.gravity).isEqualTo(Gravity.BOTTOM or Gravity.START) + assertThat(frameLayout.gravity).isEqualTo(Gravity.BOTTOM or Gravity.END) verify(iconView).setSplitTranslationX(0f) verify(iconView).setSplitTranslationY(expectedTranslationY.toFloat()) } @@ -182,7 +176,7 @@ class SeascapePagedViewHandlerTest { `when`(iconView.layoutParams).thenReturn(frameLayout) sut.updateSplitIconsPosition(iconView, expectedTranslationY, true) - assertThat(frameLayout.gravity).isEqualTo(Gravity.TOP or Gravity.END) + assertThat(frameLayout.gravity).isEqualTo(Gravity.TOP or Gravity.START) verify(iconView).setSplitTranslationX(0f) verify(iconView).setSplitTranslationY(expectedTranslationY.toFloat()) }