From 15a9feb67ff4ef6323d1913cc835bf2df32a64e1 Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Thu, 13 Apr 2023 14:01:34 -0700 Subject: [PATCH] Add support for taskbar phone 3 button seascape * Ignore orientation check from ag/22709055 for now, that will be reverted. This causes recreateTaskbar() to not run when folding the device Bug: 274517647 Test: Tested 3 button nav in portrait/landscape/seascape Flag: persist.wm.debug.hide_navbar_window Change-Id: Ied02ead677d496b465c748257e32b7db5eb9580c --- .../taskbar/NavbarButtonsViewController.java | 10 +- .../taskbar/TaskbarActivityContext.java | 76 +++++++-- .../taskbar/TaskbarInsetsController.kt | 149 ++++++++++-------- .../launcher3/taskbar/TaskbarManager.java | 9 +- .../taskbar/TaskbarViewController.java | 15 +- .../navbutton/AbstractNavButtonLayoutter.kt | 19 ++- .../taskbar/navbutton/KidsNavLayoutter.kt | 4 +- .../navbutton/NavButtonLayoutFactory.kt | 14 +- .../navbutton/PhoneLandscapeNavLayoutter.kt | 6 +- .../navbutton/PhonePortraitNavLayoutter.kt | 3 +- .../navbutton/PhoneSeascapeNavLayoutter.kt | 46 ++++++ .../navbutton/NavButtonLayoutFactoryTest.kt | 48 ++++-- .../android/launcher3/util/DimensionUtils.kt | 6 +- 13 files changed, 298 insertions(+), 107 deletions(-) create mode 100644 quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneSeascapeNavLayoutter.kt diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java index 10ae97b822..39c8da028e 100644 --- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java @@ -88,6 +88,7 @@ import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarButton; import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory; import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory.NavButtonLayoutter; import com.android.launcher3.util.DimensionUtils; +import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.MultiPropertyFactory.MultiProperty; import com.android.launcher3.util.MultiValueAlpha; import com.android.launcher3.util.TouchController; @@ -197,6 +198,7 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT this::onComputeInsetsForSeparateWindow; private final RecentsHitboxExtender mHitboxExtender = new RecentsHitboxExtender(); private ImageView mRecentsButton; + private DisplayController mDisplayController; public NavbarButtonsViewController(TaskbarActivityContext context, FrameLayout navButtonsView) { mContext = context; @@ -226,6 +228,8 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT TaskbarManager.isPhoneMode(deviceProfile)); mNavButtonsView.getLayoutParams().height = p.y; + mDisplayController = DisplayController.INSTANCE.get(mContext); + mIsImeRenderingNavButtons = InputMethodService.canImeRenderGesturalNavButtons() && mContext.imeDrawsImeNavBar(); if (!mIsImeRenderingNavButtons) { @@ -727,14 +731,10 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT boolean isInKidsMode = mContext.isNavBarKidsModeActive(); if (TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW) { - if (!isThreeButtonNav) { - return; - } - NavButtonLayoutter navButtonLayoutter = NavButtonLayoutFactory.Companion.getUiLayoutter( dp, mNavButtonsView, res, isInKidsMode, isInSetup, isThreeButtonNav, - TaskbarManager.isPhoneMode(dp)); + TaskbarManager.isPhoneMode(dp), mDisplayController.getInfo().rotation); navButtonLayoutter.layoutButtons(dp, isContextualButtonShowing()); return; } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 43aceecd0b..baaddad4e8 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -55,6 +55,7 @@ import android.util.Log; import android.view.Display; import android.view.Gravity; import android.view.RoundedCorner; +import android.view.Surface; import android.view.View; import android.view.WindowManager; import android.widget.FrameLayout; @@ -295,8 +296,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { public void init(@NonNull TaskbarSharedState sharedState) { mLastRequestedNonFullscreenHeight = getDefaultTaskbarWindowHeight(); - mWindowLayoutParams = - createDefaultWindowLayoutParams(TYPE_NAVIGATION_BAR_PANEL, WINDOW_TITLE); + mWindowLayoutParams = createAllWindowParams(); // Initialize controllers after all are constructed. mControllers.init(sharedState); @@ -360,11 +360,6 @@ public class TaskbarActivityContext extends BaseTaskbarContext { * @param title The window title to pass to the created WindowManager.LayoutParams. */ public WindowManager.LayoutParams createDefaultWindowLayoutParams(int type, String title) { - DeviceProfile deviceProfile = getDeviceProfile(); - // Taskbar is on the logical bottom of the screen - boolean isVerticalBarLayout = TaskbarManager.isPhoneButtonNavMode(this) && - deviceProfile.isLandscape; - int windowFlags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_SLIPPERY | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; @@ -373,17 +368,14 @@ public class TaskbarActivityContext extends BaseTaskbarContext { | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; } WindowManager.LayoutParams windowLayoutParams = new WindowManager.LayoutParams( - isVerticalBarLayout ? mLastRequestedNonFullscreenHeight : MATCH_PARENT, - isVerticalBarLayout ? MATCH_PARENT : mLastRequestedNonFullscreenHeight, + MATCH_PARENT, + mLastRequestedNonFullscreenHeight, type, windowFlags, PixelFormat.TRANSLUCENT); windowLayoutParams.setTitle(title); windowLayoutParams.packageName = getPackageName(); - windowLayoutParams.gravity = !isVerticalBarLayout ? - Gravity.BOTTOM : - Gravity.END; // TODO(b/230394142): seascape - + windowLayoutParams.gravity = Gravity.BOTTOM; windowLayoutParams.setFitInsetsTypes(0); windowLayoutParams.receiveInsetsIgnoringZOrder = true; windowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; @@ -394,6 +386,64 @@ public class TaskbarActivityContext extends BaseTaskbarContext { TaskbarManager.isPhoneMode(mDeviceProfile) ? R.string.taskbar_phone_a11y_title : R.string.taskbar_a11y_title); + + return windowLayoutParams; + } + + /** + * Creates {@link WindowManager.LayoutParams} for Taskbar, and also sets LP.paramsForRotation + * for taskbar showing as navigation bar + */ + private WindowManager.LayoutParams createAllWindowParams() { + WindowManager.LayoutParams windowLayoutParams = + createDefaultWindowLayoutParams(TYPE_NAVIGATION_BAR_PANEL, + TaskbarActivityContext.WINDOW_TITLE); + boolean isPhoneNavMode = TaskbarManager.isPhoneButtonNavMode(this); + if (!isPhoneNavMode) { + return windowLayoutParams; + } + + // Provide WM layout params for all rotations to cache, see NavigationBar#getBarLayoutParams + int width = WindowManager.LayoutParams.MATCH_PARENT; + int height = WindowManager.LayoutParams.MATCH_PARENT; + int gravity = Gravity.BOTTOM; + windowLayoutParams.paramsForRotation = new WindowManager.LayoutParams[4]; + for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) { + WindowManager.LayoutParams lp = + createDefaultWindowLayoutParams(TYPE_NAVIGATION_BAR_PANEL, + TaskbarActivityContext.WINDOW_TITLE); + switch (rot) { + case Surface.ROTATION_0, Surface.ROTATION_180 -> { + // Defaults are fine + width = WindowManager.LayoutParams.MATCH_PARENT; + height = mLastRequestedNonFullscreenHeight; + gravity = Gravity.BOTTOM; + } + case Surface.ROTATION_90 -> { + width = mLastRequestedNonFullscreenHeight; + height = WindowManager.LayoutParams.MATCH_PARENT; + gravity = Gravity.END; + } + case Surface.ROTATION_270 -> { + width = mLastRequestedNonFullscreenHeight; + height = WindowManager.LayoutParams.MATCH_PARENT; + gravity = Gravity.START; + } + + } + lp.width = width; + lp.height = height; + lp.gravity = gravity; + windowLayoutParams.paramsForRotation[rot] = lp; + } + + // Override current layout params + WindowManager.LayoutParams currentParams = + windowLayoutParams.paramsForRotation[getDisplay().getRotation()]; + windowLayoutParams.width = currentParams.width; + windowLayoutParams.height = currentParams.height; + windowLayoutParams.gravity = currentParams.gravity; + return windowLayoutParams; } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt index 07cd8ff1de..79b8db80ff 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt @@ -19,6 +19,7 @@ import android.graphics.Insets import android.graphics.Region import android.os.Binder import android.os.IBinder +import android.view.Gravity import android.view.InsetsFrameProvider import android.view.InsetsFrameProvider.SOURCE_DISPLAY import android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER @@ -109,16 +110,12 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas .setSource(SOURCE_DISPLAY) ) } else { - windowLayoutParams.providedInsets = - arrayOf( - InsetsFrameProvider(insetsOwner, 0, navigationBars()) - .setFlags( - insetsRoundedCornerFlag, - (FLAG_SUPPRESS_SCRIM or FLAG_INSETS_ROUNDED_CORNER) - ), - InsetsFrameProvider(insetsOwner, 0, tappableElement()), - InsetsFrameProvider(insetsOwner, 0, mandatorySystemGestures()) - ) + windowLayoutParams.providedInsets = getButtonNavInsets(insetsRoundedCornerFlag) + if (windowLayoutParams.paramsForRotation != null) { + for (layoutParams in windowLayoutParams.paramsForRotation) { + layoutParams.providedInsets = getButtonNavInsets(insetsRoundedCornerFlag) + } + } } val taskbarTouchableHeight = controllers.taskbarStashController.touchableHeight @@ -148,75 +145,99 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas windowLayoutParams.height ) } - val contentHeight = controllers.taskbarStashController.contentHeightToReportToApps - val res = context.resources + + val gravity = windowLayoutParams.gravity for (provider in windowLayoutParams.providedInsets) { - if (provider.type == navigationBars() || provider.type == mandatorySystemGestures()) { - provider.insetsSize = getInsetsByNavMode(contentHeight) - } else if (provider.type == tappableElement()) { - provider.insetsSize = getInsetsByNavMode(tappableHeight) - } else if (provider.type == systemGestures() && provider.index == INDEX_LEFT) { - provider.insetsSize = - Insets.of( - gestureNavSettingsObserver.getLeftSensitivityForCallingUser(res), - 0, - 0, - 0 - ) - } else if (provider.type == systemGestures() && provider.index == INDEX_RIGHT) { - provider.insetsSize = - Insets.of( - 0, - 0, - gestureNavSettingsObserver.getRightSensitivityForCallingUser(res), - 0 - ) - } + setProviderInsets(provider, gravity) } - val imeInsetsSize = getInsetsByNavMode(taskbarHeightForIme) - val insetsSizeOverride = - arrayOf( - InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, imeInsetsSize), - ) - // Use 0 tappableElement insets for the VoiceInteractionWindow when gesture nav is enabled. - val visInsetsSizeForGestureNavTappableElement = getInsetsByNavMode(0) - val insetsSizeOverrideForGestureNavTappableElement = - arrayOf( - InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, imeInsetsSize), - InsetsFrameProvider.InsetsSizeOverride( - TYPE_VOICE_INTERACTION, - visInsetsSizeForGestureNavTappableElement - ), - ) - for (provider in windowLayoutParams.providedInsets) { - if (context.isGestureNav && provider.type == tappableElement()) { - provider.insetsSizeOverrides = insetsSizeOverrideForGestureNavTappableElement - } else if (provider.type != systemGestures()) { - // We only override insets at the bottom of the screen - provider.insetsSizeOverrides = insetsSizeOverride + if (windowLayoutParams.paramsForRotation != null) { + // Add insets for navbar rotated params + for (layoutParams in windowLayoutParams.paramsForRotation) { + for (provider in layoutParams.providedInsets) { + setProviderInsets(provider, layoutParams.gravity) + } } } context.notifyUpdateLayoutParams() } + private fun getButtonNavInsets(insetsRoundedCornerFlag: Int): Array { + return arrayOf( + InsetsFrameProvider(insetsOwner, 0, navigationBars()) + .setFlags( + insetsRoundedCornerFlag, + (FLAG_SUPPRESS_SCRIM or FLAG_INSETS_ROUNDED_CORNER) + ), + InsetsFrameProvider(insetsOwner, 0, tappableElement()), + InsetsFrameProvider(insetsOwner, 0, mandatorySystemGestures())) + } + + private fun setProviderInsets(provider: InsetsFrameProvider, gravity: Int) { + val contentHeight = controllers.taskbarStashController.contentHeightToReportToApps + val tappableHeight = controllers.taskbarStashController.tappableHeightToReportToApps + val res = context.resources + if (provider.type == navigationBars() || provider.type == mandatorySystemGestures()) { + provider.insetsSize = getInsetsByNavMode(contentHeight, gravity) + } else if (provider.type == tappableElement()) { + provider.insetsSize = getInsetsByNavMode(tappableHeight, gravity) + } else if (provider.type == systemGestures() && provider.index == INDEX_LEFT) { + provider.insetsSize = + Insets.of( + gestureNavSettingsObserver.getLeftSensitivityForCallingUser(res), + 0, + 0, + 0 + ) + } else if (provider.type == systemGestures() && provider.index == INDEX_RIGHT) { + provider.insetsSize = + Insets.of( + 0, + 0, + gestureNavSettingsObserver.getRightSensitivityForCallingUser(res), + 0 + ) + } + + val imeInsetsSize = getInsetsByNavMode(taskbarHeightForIme, gravity) + val insetsSizeOverride = + arrayOf( + InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, imeInsetsSize), + ) + // Use 0 tappableElement insets for the VoiceInteractionWindow when gesture nav is enabled. + val visInsetsSizeForGestureNavTappableElement = getInsetsByNavMode(0, gravity) + val insetsSizeOverrideForGestureNavTappableElement = + arrayOf( + InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, imeInsetsSize), + InsetsFrameProvider.InsetsSizeOverride( + TYPE_VOICE_INTERACTION, + visInsetsSizeForGestureNavTappableElement + ), + ) + if (context.isGestureNav && provider.type == tappableElement()) { + provider.insetsSizeOverrides = insetsSizeOverrideForGestureNavTappableElement + } else if (provider.type != systemGestures()) { + // We only override insets at the bottom of the screen + provider.insetsSizeOverrides = insetsSizeOverride + } + } + /** - * @return [Insets] where the [bottomInset] is either used as a bottom inset or - * - * ``` - * right/left inset if using 3 button nav - * ``` + * @return [Insets] where the [inset] is either used as a bottom inset or + * right/left inset if using 3 button nav */ - private fun getInsetsByNavMode(bottomInset: Int): Insets { - val devicePortrait = !context.deviceProfile.isLandscape - if (!TaskbarManager.isPhoneButtonNavMode(context) || devicePortrait) { + private fun getInsetsByNavMode(inset: Int, gravity: Int): Insets { + if ((gravity and Gravity.BOTTOM) != 0) { // Taskbar or portrait phone mode - return Insets.of(0, 0, 0, bottomInset) + return Insets.of(0, 0, 0, inset) } // TODO(b/230394142): seascape - return Insets.of(0, 0, bottomInset, 0) + val isSeascape = (gravity and Gravity.START) != 0 + val leftInset = if (isSeascape) inset else 0 + val rightInset = if (isSeascape) 0 else inset + return Insets.of(leftInset , 0, rightInset, 0) } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java index 8f3898f345..1809d403d7 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java @@ -206,7 +206,14 @@ public class TaskbarManager { destroyExistingTaskbar(); } else { if (dp != null && isTaskbarPresent(dp)) { - mTaskbarActivityContext.updateDeviceProfile(dp); + if (FLAG_HIDE_NAVBAR_WINDOW) { + // Re-initialize for screen size change? Should this be done + // by looking at screen-size change flag in configDiff in the + // block above? + recreateTaskbar(); + } else { + mTaskbarActivityContext.updateDeviceProfile(dp); + } } mTaskbarActivityContext.onConfigurationChanged(configDiff); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index 29f4f38017..1b454044db 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -25,6 +25,7 @@ import static com.android.launcher3.Utilities.squaredHypot; import static com.android.launcher3.anim.AnimatedFloat.VALUE; import static com.android.launcher3.anim.AnimatorListeners.forEndCallback; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP; +import static com.android.launcher3.taskbar.TaskbarManager.isPhoneButtonNavMode; import static com.android.launcher3.taskbar.TaskbarManager.isPhoneMode; import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE; import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_TASKBAR_ALIGNMENT_ANIM; @@ -171,6 +172,13 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar .getTaskbarNavButtonTranslationYForInAppDisplay(); mActivity.addOnDeviceProfileChangeListener(mDeviceProfileChangeListener); + + if (TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW) { + // This gets modified in NavbarButtonsViewController, but the initial value it reads + // may be incorrect since it's state gets destroyed on taskbar recreate, so reset here + mTaskbarIconAlpha.get(ALPHA_INDEX_SMALL_SCREEN) + .animateToValue(isPhoneButtonNavMode(mActivity) ? 0 : 1).start(); + } } /** @@ -444,8 +452,13 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar * Creates an animation for aligning the Taskbar icons with the provided Launcher device profile */ private AnimatorPlaybackController createIconAlignmentController(DeviceProfile launcherDp) { - mOnControllerPreCreateCallback.run(); PendingAnimation setter = new PendingAnimation(100); + if (TaskbarManager.isPhoneButtonNavMode(mActivity)) { + // No animation for icons in small-screen + return setter.createPlaybackController(); + } + + mOnControllerPreCreateCallback.run(); DeviceProfile taskbarDp = mActivity.getDeviceProfile(); Rect hotseatPadding = launcherDp.getHotseatLayoutPadding(mActivity); float scaleUp = ((float) launcherDp.iconSizePx) / taskbarDp.taskbarIconSize; diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt index 27a4988b6a..b6820817c8 100644 --- a/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt +++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt @@ -17,10 +17,12 @@ package com.android.launcher3.taskbar.navbutton import android.content.res.Resources +import android.graphics.drawable.RotateDrawable import android.view.ViewGroup import android.widget.ImageView import android.widget.LinearLayout import com.android.launcher3.R +import com.android.launcher3.Utilities import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory.NavButtonLayoutter /** @@ -40,7 +42,18 @@ abstract class AbstractNavButtonLayoutter( protected val endContextualContainer: ViewGroup, protected val startContextualContainer: ViewGroup ) : NavButtonLayoutter { - protected val homeButton: ImageView = navButtonContainer.findViewById(R.id.home) - protected val recentsButton: ImageView = navButtonContainer.findViewById(R.id.recent_apps) - protected val backButton: ImageView = navButtonContainer.findViewById(R.id.back) + protected val homeButton: ImageView? = navButtonContainer.findViewById(R.id.home) + protected val recentsButton: ImageView? = navButtonContainer.findViewById(R.id.recent_apps) + protected val backButton: ImageView? = navButtonContainer.findViewById(R.id.back) + + init { + // setup back button drawable + if (backButton != null) { + val rotateDrawable = RotateDrawable() + rotateDrawable.drawable = backButton.context?.getDrawable(R.drawable.ic_sysbar_back) + rotateDrawable.fromDegrees = 0f + rotateDrawable.toDegrees = if (Utilities.isRtl(backButton.resources)) 90f else -90f + backButton.setImageDrawable(rotateDrawable) + } + } } diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt index 468a1a7093..4a53c0c3b1 100644 --- a/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt +++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt @@ -51,10 +51,10 @@ class KidsNavLayoutter( val paddingTop = (buttonHeight - iconSize) / 2 // Update icons - backButton.setImageDrawable(backButton.context.getDrawable(DRAWABLE_SYSBAR_BACK_KIDS)) + backButton!!.setImageDrawable(backButton.context.getDrawable(DRAWABLE_SYSBAR_BACK_KIDS)) backButton.scaleType = ImageView.ScaleType.FIT_CENTER backButton.setPadding(paddingLeft, paddingTop, paddingLeft, paddingTop) - homeButton.setImageDrawable(homeButton.getContext().getDrawable(DRAWABLE_SYSBAR_HOME_KIDS)) + homeButton!!.setImageDrawable(homeButton.context.getDrawable(DRAWABLE_SYSBAR_HOME_KIDS)) homeButton.scaleType = ImageView.ScaleType.FIT_CENTER homeButton.setPadding(paddingLeft, paddingTop, paddingLeft, paddingTop) diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt index 0668da959c..7db2320216 100644 --- a/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt +++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt @@ -17,6 +17,8 @@ package com.android.launcher3.taskbar.navbutton import android.content.res.Resources +import android.view.Surface.ROTATION_90 +import android.view.Surface.Rotation import android.view.ViewGroup import android.widget.FrameLayout import android.widget.LinearLayout @@ -56,7 +58,8 @@ class NavButtonLayoutFactory { isKidsMode: Boolean, isInSetup: Boolean, isThreeButtonNav: Boolean, - phoneMode: Boolean + phoneMode: Boolean, + @Rotation surfaceRotation: Int ): NavButtonLayoutter { val navButtonContainer = navButtonsView.findViewById(ID_END_NAV_BUTTONS) val endContextualContainer = @@ -73,13 +76,20 @@ class NavButtonLayoutFactory { endContextualContainer, startContextualContainer ) - } else { + } else if (surfaceRotation == ROTATION_90) { PhoneLandscapeNavLayoutter( resources, navButtonContainer, endContextualContainer, startContextualContainer ) + } else { + PhoneSeascapeNavLayoutter( + resources, + navButtonContainer, + endContextualContainer, + startContextualContainer + ) } } deviceProfile.isTaskbarPresent -> { diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt index 201895fc67..92715a740e 100644 --- a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt +++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt @@ -27,7 +27,7 @@ import com.android.launcher3.R import com.android.launcher3.taskbar.TaskbarManager import com.android.launcher3.util.DimensionUtils -class PhoneLandscapeNavLayoutter( +open class PhoneLandscapeNavLayoutter( resources: Resources, navBarContainer: LinearLayout, endContextualContainer: ViewGroup, @@ -44,8 +44,8 @@ class PhoneLandscapeNavLayoutter( // TODO(b/230395757): Polish pending, this is just to make it usable val navContainerParams = navButtonContainer.layoutParams as FrameLayout.LayoutParams val endStartMargins = resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size) - val taskbarDimensions = - DimensionUtils.getTaskbarPhoneDimensions(dp, resources, TaskbarManager.isPhoneMode(dp)) + val taskbarDimensions = DimensionUtils.getTaskbarPhoneDimensions(dp, resources, + TaskbarManager.isPhoneMode(dp)) navButtonContainer.removeAllViews() navButtonContainer.orientation = LinearLayout.VERTICAL diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt index f7ac9745f0..7f7fda79c1 100644 --- a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt +++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt @@ -43,7 +43,8 @@ class PhonePortraitNavLayoutter( // TODO(b/230395757): Polish pending, this is just to make it usable val navContainerParams = navButtonContainer.layoutParams as FrameLayout.LayoutParams val taskbarDimensions = - DimensionUtils.getTaskbarPhoneDimensions(dp, resources, TaskbarManager.isPhoneMode(dp)) + DimensionUtils.getTaskbarPhoneDimensions(dp, resources, + TaskbarManager.isPhoneMode(dp)) val endStartMargins = resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size) navContainerParams.width = taskbarDimensions.x navContainerParams.height = ViewGroup.LayoutParams.MATCH_PARENT diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneSeascapeNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneSeascapeNavLayoutter.kt new file mode 100644 index 0000000000..f0fe58197b --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneSeascapeNavLayoutter.kt @@ -0,0 +1,46 @@ +/* +* Copyright (C) 2023 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License +*/ + +package com.android.launcher3.taskbar.navbutton + +import android.content.res.Resources +import android.view.ViewGroup +import android.widget.LinearLayout +import com.android.launcher3.DeviceProfile + +class PhoneSeascapeNavLayoutter( + resources: Resources, + navBarContainer: LinearLayout, + endContextualContainer: ViewGroup, + startContextualContainer: ViewGroup +) : + PhoneLandscapeNavLayoutter( + resources, + navBarContainer, + endContextualContainer, + startContextualContainer + ) { + + override fun layoutButtons(dp: DeviceProfile, isContextualButtonShowing: Boolean) { + // TODO(b/230395757): Polish pending, this is just to make it usable + super.layoutButtons(dp, isContextualButtonShowing) + navButtonContainer.removeAllViews() + // Flip ordering of back and recents buttons + navButtonContainer.addView(backButton) + navButtonContainer.addView(homeButton) + navButtonContainer.addView(recentsButton) + } +} diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt b/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt index 236b5db10c..3920b08030 100644 --- a/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt +++ b/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt @@ -1,6 +1,9 @@ package com.android.launcher3.taskbar.navbutton import android.content.res.Resources +import android.view.Surface +import android.view.Surface.ROTATION_270 +import android.view.Surface.Rotation import android.view.View import android.view.ViewGroup import android.widget.FrameLayout @@ -32,6 +35,8 @@ class NavButtonLayoutFactoryTest { @Mock lateinit var mockRecentsButton: ImageView @Mock lateinit var mockHomeButton: ImageView + private var surfaceRotation = Surface.ROTATION_0 + @Before fun setup() { MockitoAnnotations.initMocks(this) @@ -60,7 +65,8 @@ class NavButtonLayoutFactoryTest { isKidsMode = true, isInSetup = false, isThreeButtonNav = false, - phoneMode = false + phoneMode = false, + surfaceRotation = surfaceRotation ) assert(layoutter is KidsNavLayoutter) } @@ -74,7 +80,8 @@ class NavButtonLayoutFactoryTest { isKidsMode = false, isInSetup = true, isThreeButtonNav = false, - phoneMode = false + phoneMode = false, + surfaceRotation = surfaceRotation ) assert(layoutter is SetupNavLayoutter) } @@ -88,7 +95,8 @@ class NavButtonLayoutFactoryTest { isKidsMode = false, isInSetup = false, isThreeButtonNav = false, - phoneMode = false + phoneMode = false, + surfaceRotation = surfaceRotation ) assert(layoutter is TaskbarNavLayoutter) } @@ -101,7 +109,8 @@ class NavButtonLayoutFactoryTest { isKidsMode = false, isInSetup = false, isThreeButtonNav = false, - phoneMode = false + phoneMode = false, + surfaceRotation = surfaceRotation ) } @@ -114,7 +123,8 @@ class NavButtonLayoutFactoryTest { isKidsMode = false, isInSetup = false, isThreeButtonNav = true, - phoneMode = true + phoneMode = true, + surfaceRotation = surfaceRotation ) assert(layoutter is PhonePortraitNavLayoutter) } @@ -129,11 +139,28 @@ class NavButtonLayoutFactoryTest { isKidsMode = false, isInSetup = false, isThreeButtonNav = true, - phoneMode = true + phoneMode = true, + surfaceRotation = surfaceRotation ) assert(layoutter is PhoneLandscapeNavLayoutter) } + @Test + fun getTaskbarSeascapeLayoutter() { + assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW) + mockDeviceProfile.isTaskbarPresent = false + setDeviceProfileLandscape() + val layoutter: NavButtonLayoutFactory.NavButtonLayoutter = + getLayoutter( + isKidsMode = false, + isInSetup = false, + isThreeButtonNav = true, + phoneMode = true, + surfaceRotation = ROTATION_270 + ) + assert(layoutter is PhoneSeascapeNavLayoutter) + } + @Test(expected = IllegalStateException::class) fun noValidLayoutForPhoneGestureNav() { assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW) @@ -142,7 +169,8 @@ class NavButtonLayoutFactoryTest { isKidsMode = false, isInSetup = false, isThreeButtonNav = false, - phoneMode = true + phoneMode = true, + surfaceRotation = surfaceRotation ) } @@ -157,7 +185,8 @@ class NavButtonLayoutFactoryTest { isKidsMode: Boolean, isInSetup: Boolean, isThreeButtonNav: Boolean, - phoneMode: Boolean + phoneMode: Boolean, + @Rotation surfaceRotation: Int ): NavButtonLayoutFactory.NavButtonLayoutter { return NavButtonLayoutFactory.getUiLayoutter( deviceProfile = mockDeviceProfile, @@ -166,7 +195,8 @@ class NavButtonLayoutFactoryTest { isKidsMode = isKidsMode, isInSetup = isInSetup, isThreeButtonNav = isThreeButtonNav, - phoneMode = phoneMode + phoneMode = phoneMode, + surfaceRotation = surfaceRotation ) } } diff --git a/src/com/android/launcher3/util/DimensionUtils.kt b/src/com/android/launcher3/util/DimensionUtils.kt index 9188c2ead4..0eb0e087ee 100644 --- a/src/com/android/launcher3/util/DimensionUtils.kt +++ b/src/com/android/launcher3/util/DimensionUtils.kt @@ -29,9 +29,9 @@ object DimensionUtils { */ @JvmStatic fun getTaskbarPhoneDimensions( - deviceProfile: DeviceProfile, - res: Resources, - isPhoneMode: Boolean + deviceProfile: DeviceProfile, + res: Resources, + isPhoneMode: Boolean ): Point { val p = Point() // Taskbar for large screen