Update placement of the hotseat according to the bubble bar location.
Update the hotseat and Qsb placement according to the 3 nav buttons bar. Test: Manual. Set navigation mode to 3 buttons. On launcher home screen move the bubble bar from one side to another. Observe that the Hotseat and Qsb moving together with the navigation bar. Once moved the bubble bar, expand the bubble bar and collapse it. Observe how the Hotseat is stashing and un-stashing. After bubble bar changes position hit the recent apps button, observe the transition. On launcher home screen start application with the hotseat icon and exit opened application. Observe that flying icon comes back to the correct position in the hotseat. Video with the above scenarios: http://recall/-/gx8ASgewUeUS3QYohfrd1J/blTYrKopTyufOcRoPuVpYK Bug: 346381754 Flag: com.android.wm.shell.enable_bubble_bar_in_persistent_task_bar Change-Id: Ic8c6acdffbbb111cbe4f3fd6bc60195578d7035d
This commit is contained in:
@@ -1353,8 +1353,13 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
? null
|
||||
: mLauncher.getTaskbarUIController().findMatchingView(launcherView),
|
||||
true /* hideOriginal */, targetRect, false /* isOpening */);
|
||||
isInHotseat = launcherView.getTag() instanceof ItemInfo
|
||||
&& ((ItemInfo) launcherView.getTag()).isInHotseat();
|
||||
if (launcherView.getTag() instanceof ItemInfo itemInfo) {
|
||||
isInHotseat = itemInfo.isInHotseat();
|
||||
if (isInHotseat) {
|
||||
int dx = mLauncher.getHotseatItemTranslationX(itemInfo);
|
||||
targetRect.offset(dx, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
targetRect.set(getDefaultWindowTargetRect());
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ import com.android.quickstep.util.GroupTask;
|
||||
import com.android.quickstep.util.TISBindHelper;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
|
||||
import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
|
||||
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
@@ -487,6 +488,18 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
|
||||
return "LauncherTaskbarUIController";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBubbleBarLocationAnimated(BubbleBarLocation location) {
|
||||
mTaskbarLauncherStateController.onBubbleBarLocationChanged(location, /* animate = */ true);
|
||||
mLauncher.setBubbleBarLocation(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBubbleBarLocationUpdated(BubbleBarLocation location) {
|
||||
mTaskbarLauncherStateController.onBubbleBarLocationChanged(location, /* animate = */ false);
|
||||
mLauncher.setBubbleBarLocation(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwipeToUnstashTaskbar() {
|
||||
// Once taskbar is unstashed, the user cannot return back to the overlay. We can
|
||||
|
||||
@@ -201,6 +201,8 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
|
||||
|
||||
private final Rect mFloatingRotationButtonBounds = new Rect();
|
||||
|
||||
private @Nullable BubbleBarLocation mBubbleBarLocation;
|
||||
|
||||
// Initialized in init.
|
||||
private TaskbarControllers mControllers;
|
||||
private boolean mIsImeRenderingNavButtons;
|
||||
@@ -1174,6 +1176,7 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
|
||||
/** Adjusts navigation buttons layout accordingly to the bubble bar position. */
|
||||
@Override
|
||||
public void onBubbleBarLocationUpdated(BubbleBarLocation location) {
|
||||
mBubbleBarLocation = location;
|
||||
mNavButtonContainer.setTranslationX(getNavBarTranslationX(location));
|
||||
}
|
||||
|
||||
@@ -1181,6 +1184,7 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
|
||||
@Override
|
||||
public void onBubbleBarLocationAnimated(BubbleBarLocation location) {
|
||||
// TODO(b/346381754) add the teleport animation similarly to the bubble bar
|
||||
mBubbleBarLocation = location;
|
||||
mNavButtonContainer.setTranslationX(getNavBarTranslationX(location));
|
||||
}
|
||||
|
||||
@@ -1221,9 +1225,12 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
|
||||
public void onTaskbarLayoutChange() {
|
||||
if (com.android.wm.shell.Flags.enableBubbleBarInPersistentTaskBar()
|
||||
&& mControllers.bubbleControllers.isPresent()) {
|
||||
BubbleBarLocation bubblesLocation = mControllers.bubbleControllers.get()
|
||||
.bubbleBarViewController.getBubbleBarLocation();
|
||||
onBubbleBarLocationUpdated(bubblesLocation);
|
||||
if (mBubbleBarLocation == null) {
|
||||
// only set bubble bar location if it was not set before, e.g. at device boot
|
||||
mBubbleBarLocation = mControllers.bubbleControllers.get()
|
||||
.bubbleBarViewController.getBubbleBarLocation();
|
||||
}
|
||||
onBubbleBarLocationUpdated(mBubbleBarLocation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController;
|
||||
import com.android.launcher3.taskbar.bubbles.BubbleControllers;
|
||||
import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
|
||||
import com.android.systemui.shared.rotation.RotationButtonController;
|
||||
import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
@@ -219,7 +220,11 @@ public class TaskbarControllers {
|
||||
uiController = newUiController;
|
||||
uiController.init(this);
|
||||
uiController.updateStateForSysuiFlags(mSharedState.sysuiStateFlags);
|
||||
|
||||
bubbleControllers.ifPresent(bubbleControllers -> {
|
||||
BubbleBarLocation location =
|
||||
bubbleControllers.bubbleBarViewController.getBubbleBarLocation();
|
||||
uiController.onBubbleBarLocationUpdated(location);
|
||||
});
|
||||
// Notify that the ui controller has changed
|
||||
navbarButtonsViewController.onUiControllerChanged();
|
||||
}
|
||||
|
||||
@@ -19,11 +19,14 @@ import static com.android.app.animation.Interpolators.EMPHASIZED;
|
||||
import static com.android.launcher3.Hotseat.ALPHA_CHANNEL_TASKBAR_ALIGNMENT;
|
||||
import static com.android.launcher3.Hotseat.ALPHA_CHANNEL_TASKBAR_STASH;
|
||||
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
|
||||
import static com.android.launcher3.Utilities.isRtl;
|
||||
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP;
|
||||
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_OVERVIEW;
|
||||
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASHED_LAUNCHER_STATE;
|
||||
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_STASHED_FOR_BUBBLES;
|
||||
import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_HOME;
|
||||
import static com.android.launcher3.taskbar.bubbles.BubbleBarView.FADE_IN_ANIM_ALPHA_DURATION_MS;
|
||||
import static com.android.launcher3.taskbar.bubbles.BubbleBarView.FADE_OUT_ANIM_POSITION_DURATION_MS;
|
||||
import static com.android.launcher3.util.FlagDebugUtils.appendFlag;
|
||||
import static com.android.launcher3.util.FlagDebugUtils.formatFlagChange;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_AWAKE;
|
||||
@@ -42,8 +45,10 @@ import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.app.animation.Interpolators;
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Hotseat;
|
||||
import com.android.launcher3.Hotseat.HotseatQsbAlphaId;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.QuickstepTransitionManager;
|
||||
@@ -62,6 +67,7 @@ import com.android.quickstep.views.RecentsView;
|
||||
import com.android.systemui.animation.ViewRootSync;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
|
||||
import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.HashMap;
|
||||
@@ -151,6 +157,7 @@ public class TaskbarLauncherStateController {
|
||||
private AnimatedFloat mTaskbarAlpha;
|
||||
private AnimatedFloat mTaskbarCornerRoundness;
|
||||
private MultiProperty mTaskbarAlphaForHome;
|
||||
private @Nullable Animator mHotseatTranslationXAnimation;
|
||||
private QuickstepLauncher mLauncher;
|
||||
|
||||
private boolean mIsDestroyed = false;
|
||||
@@ -168,6 +175,8 @@ public class TaskbarLauncherStateController {
|
||||
|
||||
private boolean mShouldDelayLauncherStateAnim;
|
||||
|
||||
private @Nullable BubbleBarLocation mBubbleBarLocation;
|
||||
|
||||
// We skip any view synchronizations during init/destroy.
|
||||
private boolean mCanSyncViews;
|
||||
|
||||
@@ -185,6 +194,8 @@ public class TaskbarLauncherStateController {
|
||||
mIsQsbInline = dp.isQsbInline;
|
||||
TaskbarLauncherStateController.this.updateIconAlphaForHome(
|
||||
mTaskbarAlphaForHome.getValue(), ALPHA_CHANNEL_TASKBAR_ALIGNMENT);
|
||||
TaskbarLauncherStateController.this.onBubbleBarLocationChanged(
|
||||
mBubbleBarLocation, /* animate = */ false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -833,6 +844,74 @@ public class TaskbarLauncherStateController {
|
||||
}
|
||||
}
|
||||
|
||||
/** Updates launcher home screen appearance accordingly to the bubble bar location. */
|
||||
public void onBubbleBarLocationChanged(BubbleBarLocation location, boolean animate) {
|
||||
DeviceProfile deviceProfile = mLauncher.getDeviceProfile();
|
||||
if (mBubbleBarLocation == location) return;
|
||||
mBubbleBarLocation = location;
|
||||
if (!deviceProfile.shouldAdjustHotseatOnBubblesLocationUpdate(
|
||||
mControllers.taskbarActivityContext)) {
|
||||
return;
|
||||
}
|
||||
int targetX = 0;
|
||||
if (mBubbleBarLocation != null) {
|
||||
boolean isBubblesOnLeft = location.isOnLeft(isRtl(mLauncher.getResources()));
|
||||
targetX = deviceProfile.getHotseatTranslationXForBubbleBar(/* isNavbarOnRight= */
|
||||
isBubblesOnLeft);
|
||||
}
|
||||
updateHotseatAndQsbTranslationX(targetX, animate);
|
||||
}
|
||||
|
||||
private void updateHotseatAndQsbTranslationX(float targetValue, boolean animate) {
|
||||
// cancel existing animation
|
||||
if (mHotseatTranslationXAnimation != null) {
|
||||
mHotseatTranslationXAnimation.cancel();
|
||||
}
|
||||
Runnable alignTaskbar = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// We only need to align the task bar when on launcher home screen
|
||||
if (mControllers.taskbarStashController.isOnHome()) {
|
||||
DeviceProfile dp = mLauncher.getDeviceProfile();
|
||||
mControllers.taskbarViewController
|
||||
.setLauncherIconAlignment(/* alignmentRatio = */ 1, dp);
|
||||
}
|
||||
}
|
||||
};
|
||||
Hotseat hotseat = mLauncher.getHotseat();
|
||||
AnimatorSet translationXAnimation = new AnimatorSet();
|
||||
MultiProperty iconsTranslationX = hotseat.getIconsTranslationX(
|
||||
Hotseat.ICONS_TRANSLATION_X_NAV_BAR_ALIGNMENT);
|
||||
if (animate) {
|
||||
translationXAnimation.playTogether(iconsTranslationX.animateToValue(targetValue));
|
||||
} else {
|
||||
iconsTranslationX.setValue(targetValue);
|
||||
}
|
||||
float qsbTargetX = 0;
|
||||
if (mIsQsbInline) {
|
||||
qsbTargetX = targetValue;
|
||||
}
|
||||
MultiProperty qsbTranslationX = hotseat.getQsbTranslationX();
|
||||
if (qsbTranslationX != null) {
|
||||
if (animate) {
|
||||
translationXAnimation.playTogether(qsbTranslationX.animateToValue(qsbTargetX));
|
||||
} else {
|
||||
qsbTranslationX.setValue(qsbTargetX);
|
||||
}
|
||||
}
|
||||
if (!animate) {
|
||||
alignTaskbar.run();
|
||||
return;
|
||||
}
|
||||
mHotseatTranslationXAnimation = translationXAnimation;
|
||||
translationXAnimation.setStartDelay(FADE_OUT_ANIM_POSITION_DURATION_MS);
|
||||
translationXAnimation.setDuration(FADE_IN_ANIM_ALPHA_DURATION_MS);
|
||||
translationXAnimation.setInterpolator(Interpolators.EMPHASIZED);
|
||||
translationXAnimation.addListener(AnimatorListeners.forEndCallback(alignTaskbar));
|
||||
translationXAnimation.start();
|
||||
}
|
||||
|
||||
|
||||
private final class TaskBarRecentsAnimationListener implements
|
||||
RecentsAnimationCallbacks.RecentsAnimationListener {
|
||||
private final RecentsAnimationCallbacks mCallbacks;
|
||||
|
||||
@@ -446,6 +446,11 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
return hasAnyFlag(FLAG_IN_OVERVIEW);
|
||||
}
|
||||
|
||||
/** Returns whether the taskbar is currently on launcher home screen. */
|
||||
public boolean isOnHome() {
|
||||
return !isInOverview() && !isInApp();
|
||||
}
|
||||
|
||||
/** Returns whether taskbar is hidden for bubbles. */
|
||||
public boolean isHiddenForBubbles() {
|
||||
return hasAnyFlag(FLAG_STASHED_FOR_BUBBLES);
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
import com.android.launcher3.taskbar.bubbles.BubbleBarController;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.SplitConfigurationOptions;
|
||||
import com.android.quickstep.OverviewCommandHelper;
|
||||
@@ -47,6 +48,7 @@ import com.android.quickstep.views.TaskContainer;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
|
||||
import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Collections;
|
||||
@@ -55,7 +57,7 @@ import java.util.stream.Stream;
|
||||
/**
|
||||
* Base class for providing different taskbar UI
|
||||
*/
|
||||
public class TaskbarUIController {
|
||||
public class TaskbarUIController implements BubbleBarController.BubbleBarLocationListener {
|
||||
public static final TaskbarUIController DEFAULT = new TaskbarUIController();
|
||||
|
||||
// Initialized in init.
|
||||
@@ -433,6 +435,14 @@ public class TaskbarUIController {
|
||||
public void stashHotseat(boolean stash) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBubbleBarLocationAnimated(BubbleBarLocation location) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBubbleBarLocationUpdated(BubbleBarLocation location) {
|
||||
}
|
||||
|
||||
/** Un-stash the hotseat instantly */
|
||||
public void unStashHotseatInstantly() {
|
||||
}
|
||||
|
||||
@@ -827,6 +827,14 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
: mPersistentTaskbarDp.taskbarBottomMargin;
|
||||
|
||||
int firstRecentTaskIndex = -1;
|
||||
int hotseatNavBarTranslationX = 0;
|
||||
if (mCurrentBubbleBarLocation != null
|
||||
&& taskbarDp.shouldAdjustHotseatOnBubblesLocationUpdate(mActivity)) {
|
||||
boolean isBubblesOnLeft = mCurrentBubbleBarLocation.isOnLeft(
|
||||
mTaskbarView.isLayoutRtl());
|
||||
hotseatNavBarTranslationX = taskbarDp
|
||||
.getHotseatTranslationXForBubbleBar(/* isNavbarOnRight = */ isBubblesOnLeft);
|
||||
}
|
||||
for (int i = 0; i < mTaskbarView.getChildCount(); i++) {
|
||||
View child = mTaskbarView.getChildAt(i);
|
||||
boolean isAllAppsButton = child == mTaskbarView.getAllAppsButtonContainer();
|
||||
@@ -860,16 +868,20 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
: Interpolators.clampToProgress(LINEAR, 0.72f, 0.84f));
|
||||
}
|
||||
}
|
||||
|
||||
if (child == mTaskbarView.getQsb()) {
|
||||
boolean isRtl = Utilities.isRtl(child.getResources());
|
||||
float hotseatIconCenter = isRtl
|
||||
? launcherDp.widthPx - hotseatPadding.right + borderSpacing
|
||||
+ launcherDp.hotseatQsbWidth / 2f
|
||||
: hotseatPadding.left - borderSpacing - launcherDp.hotseatQsbWidth / 2f;
|
||||
if (taskbarDp.isQsbInline) {
|
||||
hotseatIconCenter += hotseatNavBarTranslationX;
|
||||
}
|
||||
float childCenter = (child.getLeft() + child.getRight()) / 2f;
|
||||
childCenter += ((Reorderable) child).getTranslateDelegate().getTranslationX(
|
||||
INDEX_TASKBAR_PINNING_ANIM).getValue();
|
||||
if (child instanceof Reorderable reorderableChild) {
|
||||
childCenter += reorderableChild.getTranslateDelegate().getTranslationX(
|
||||
INDEX_TASKBAR_PINNING_ANIM).getValue();
|
||||
}
|
||||
float halfQsbIconWidthDiff =
|
||||
(launcherDp.hotseatQsbWidth - taskbarDp.taskbarIconSize) / 2f;
|
||||
float scale = ((float) taskbarDp.taskbarIconSize)
|
||||
@@ -878,8 +890,8 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
|
||||
float fromX = isRtl ? -halfQsbIconWidthDiff : halfQsbIconWidthDiff;
|
||||
float toX = hotseatIconCenter - childCenter;
|
||||
if (child instanceof Reorderable) {
|
||||
MultiTranslateDelegate mtd = ((Reorderable) child).getTranslateDelegate();
|
||||
if (child instanceof Reorderable reorderableChild) {
|
||||
MultiTranslateDelegate mtd = reorderableChild.getTranslateDelegate();
|
||||
|
||||
setter.addFloat(mtd.getTranslationX(INDEX_TASKBAR_ALIGNMENT_ANIM),
|
||||
MULTI_PROPERTY_VALUE, fromX, toX, interpolator);
|
||||
@@ -926,6 +938,7 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
+ (hotseatCellSize + borderSpacing) * positionInHotseat
|
||||
+ hotseatCellSize / 2f;
|
||||
}
|
||||
hotseatIconCenter += hotseatNavBarTranslationX;
|
||||
float childCenter = (child.getLeft() + child.getRight()) / 2f;
|
||||
childCenter += ((Reorderable) child).getTranslateDelegate().getTranslationX(
|
||||
INDEX_TASKBAR_PINNING_ANIM).getValue();
|
||||
|
||||
@@ -196,7 +196,8 @@ public class BubbleBarController extends IBubblesListener.Stub {
|
||||
mBubbleBarViewController.setUpdateSelectedBubbleAfterCollapse(
|
||||
key -> setSelectedBubbleInternal(mBubbles.get(key)));
|
||||
mBubbleBarViewController.setBoundsChangeListener(this::onBubbleBarBoundsChanged);
|
||||
|
||||
mBubbleBarLocationListener.onBubbleBarLocationUpdated(
|
||||
mBubbleBarViewController.getBubbleBarLocation());
|
||||
if (sBubbleBarEnabled) {
|
||||
mSystemUiProxy.setBubblesListener(this);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.view.View;
|
||||
|
||||
import com.android.launcher3.taskbar.TaskbarControllers;
|
||||
import com.android.launcher3.taskbar.bubbles.BubbleBarViewController.TaskbarViewPropertiesProvider;
|
||||
import com.android.launcher3.taskbar.bubbles.stashing.BubbleBarLocationOnDemandListener;
|
||||
import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController;
|
||||
import com.android.launcher3.util.MultiPropertyFactory;
|
||||
import com.android.launcher3.util.RunnableList;
|
||||
@@ -76,11 +77,11 @@ public class BubbleControllers {
|
||||
* in constructors for now, as some controllers may still be waiting for init().
|
||||
*/
|
||||
public void init(TaskbarControllers taskbarControllers) {
|
||||
// TODO(b/346381754) add TaskbarLauncherStateController implementation to adjust the hotseat
|
||||
BubbleBarLocationCompositeListener bubbleBarLocationListeners =
|
||||
new BubbleBarLocationCompositeListener(
|
||||
taskbarControllers.navbarButtonsViewController,
|
||||
taskbarControllers.taskbarViewController
|
||||
taskbarControllers.taskbarViewController,
|
||||
new BubbleBarLocationOnDemandListener(() -> taskbarControllers.uiController)
|
||||
);
|
||||
bubbleBarController.init(this,
|
||||
bubbleBarLocationListeners,
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.bubbles.stashing
|
||||
|
||||
import com.android.launcher3.taskbar.bubbles.BubbleBarController.BubbleBarLocationListener
|
||||
import com.android.wm.shell.shared.bubbles.BubbleBarLocation
|
||||
|
||||
/** On demand implementation of [BubbleBarLocationListener]. */
|
||||
class BubbleBarLocationOnDemandListener(
|
||||
private val listenerProvider: () -> BubbleBarLocationListener
|
||||
) : BubbleBarLocationListener {
|
||||
|
||||
override fun onBubbleBarLocationAnimated(location: BubbleBarLocation) {
|
||||
listenerProvider().onBubbleBarLocationAnimated(location)
|
||||
}
|
||||
|
||||
override fun onBubbleBarLocationUpdated(location: BubbleBarLocation) {
|
||||
listenerProvider().onBubbleBarLocationUpdated(location)
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import static com.android.launcher3.LauncherState.NO_OFFSET;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
|
||||
import static com.android.launcher3.Utilities.isRtl;
|
||||
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
|
||||
import static com.android.launcher3.config.FeatureFlags.enableSplitContextually;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
|
||||
@@ -65,6 +66,8 @@ import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent
|
||||
import static com.android.quickstep.util.AnimUtils.completeRunnableListCallback;
|
||||
import static com.android.quickstep.util.SplitAnimationTimings.TABLET_HOME_TO_SPLIT;
|
||||
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
|
||||
import static com.android.wm.shell.Flags.enableBubbleAnything;
|
||||
import static com.android.wm.shell.Flags.enableBubbleBarInPersistentTaskBar;
|
||||
import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_50_50;
|
||||
|
||||
import android.animation.Animator;
|
||||
@@ -198,6 +201,7 @@ import com.android.systemui.unfold.config.UnfoldTransitionConfig;
|
||||
import com.android.systemui.unfold.dagger.UnfoldMain;
|
||||
import com.android.systemui.unfold.progress.RemoteUnfoldTransitionReceiver;
|
||||
import com.android.systemui.unfold.updates.RotationChangeProvider;
|
||||
import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
|
||||
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
|
||||
|
||||
import kotlin.Unit;
|
||||
@@ -239,6 +243,7 @@ public class QuickstepLauncher extends Launcher implements RecentsViewContainer,
|
||||
private SplitSelectStateController mSplitSelectStateController;
|
||||
private SplitWithKeyboardShortcutController mSplitWithKeyboardShortcutController;
|
||||
private SplitToWorkspaceController mSplitToWorkspaceController;
|
||||
private BubbleBarLocation mBubbleBarLocation;
|
||||
|
||||
/**
|
||||
* If Launcher restarted while in the middle of an Overview split select, it needs this data to
|
||||
@@ -463,7 +468,7 @@ public class QuickstepLauncher extends Launcher implements RecentsViewContainer,
|
||||
if (Flags.enablePrivateSpace()) {
|
||||
shortcuts.add(UNINSTALL_APP);
|
||||
}
|
||||
if (com.android.wm.shell.Flags.enableBubbleAnything()) {
|
||||
if (enableBubbleAnything()) {
|
||||
shortcuts.add(BUBBLE_SHORTCUT);
|
||||
}
|
||||
return shortcuts.stream();
|
||||
@@ -1105,6 +1110,29 @@ public class QuickstepLauncher extends Launcher implements RecentsViewContainer,
|
||||
return mTaskbarUIController;
|
||||
}
|
||||
|
||||
/** Provides the translation X for the hotseat item. */
|
||||
public int getHotseatItemTranslationX(ItemInfo itemInfo) {
|
||||
int translationX = 0;
|
||||
if (isBubbleBarEnabled()
|
||||
&& enableBubbleBarInPersistentTaskBar()
|
||||
&& mBubbleBarLocation != null) {
|
||||
boolean isBubblesOnLeft = mBubbleBarLocation.isOnLeft(isRtl(getResources()));
|
||||
translationX += mDeviceProfile
|
||||
.getHotseatTranslationXForBubbleBar(/* isNavbarOnRight = */ isBubblesOnLeft);
|
||||
}
|
||||
if (isBubbleBarEnabled() && hasBubbles()) {
|
||||
// TODO(368379159) : create a class to reuse computation logic
|
||||
float adjustedBorderSpace =
|
||||
mDeviceProfile.getHotseatAdjustedBorderSpaceForBubbleBar(this);
|
||||
if (Float.compare(adjustedBorderSpace, 0f) != 0) {
|
||||
float borderSpaceDelta = adjustedBorderSpace - mDeviceProfile.hotseatBorderSpace;
|
||||
translationX +=
|
||||
(int) (mDeviceProfile.iconSizePx + itemInfo.cellX * borderSpaceDelta);
|
||||
}
|
||||
}
|
||||
return translationX;
|
||||
}
|
||||
|
||||
public SplitToWorkspaceController getSplitToWorkspaceController() {
|
||||
return mSplitToWorkspaceController;
|
||||
}
|
||||
@@ -1410,6 +1438,11 @@ public class QuickstepLauncher extends Launcher implements RecentsViewContainer,
|
||||
SystemUiProxy.INSTANCE.get(this).showAppBubble(intent);
|
||||
}
|
||||
|
||||
/** Sets the location of the bubble bar */
|
||||
public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation) {
|
||||
mBubbleBarLocation = bubbleBarLocation;
|
||||
}
|
||||
|
||||
private static final class LauncherTaskViewController extends
|
||||
TaskViewTouchController<QuickstepLauncher> {
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTO
|
||||
import static com.android.launcher3.testing.shared.ResourceUtils.INVALID_RESOURCE_HANDLE;
|
||||
import static com.android.launcher3.testing.shared.ResourceUtils.pxFromDp;
|
||||
import static com.android.launcher3.testing.shared.ResourceUtils.roundPxValueFromFloat;
|
||||
import static com.android.wm.shell.Flags.enableBubbleBar;
|
||||
import static com.android.wm.shell.Flags.enableBubbleBarInPersistentTaskBar;
|
||||
import static com.android.wm.shell.Flags.enableTinyTaskbar;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
@@ -64,8 +66,10 @@ import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecT
|
||||
import com.android.launcher3.responsive.ResponsiveSpec.DimensionType;
|
||||
import com.android.launcher3.responsive.ResponsiveSpecsProvider;
|
||||
import com.android.launcher3.util.CellContentDimensions;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.DisplayController.Info;
|
||||
import com.android.launcher3.util.IconSizeSteps;
|
||||
import com.android.launcher3.util.NavigationMode;
|
||||
import com.android.launcher3.util.ResourceHelper;
|
||||
import com.android.launcher3.util.WindowBounds;
|
||||
import com.android.launcher3.util.window.WindowManagerProxy;
|
||||
@@ -219,6 +223,8 @@ public class DeviceProfile {
|
||||
public int hotseatBarBottomSpacePx;
|
||||
public int hotseatBarEndOffset;
|
||||
public int hotseatQsbSpace;
|
||||
public int inlineNavButtonsEndSpacingPx;
|
||||
public int navButtonsLayoutWidthPx;
|
||||
public int springLoadedHotseatBarTopMarginPx;
|
||||
// These 2 values are only used for isVerticalBar
|
||||
// Padding between edge of screen and hotseat
|
||||
@@ -233,7 +239,6 @@ public class DeviceProfile {
|
||||
private final int mMinHotseatIconSpacePx;
|
||||
private final int mMinHotseatQsbWidthPx;
|
||||
private final int mMaxHotseatIconSpacePx;
|
||||
public final int inlineNavButtonsEndSpacingPx;
|
||||
// Space required for the bubble bar between the hotseat and the edge of the screen. If there's
|
||||
// not enough space, the hotseat will adjust itself for the bubble bar.
|
||||
private final int mBubbleBarSpaceThresholdPx;
|
||||
@@ -692,17 +697,12 @@ public class DeviceProfile {
|
||||
if (areNavButtonsInline && !isPhone) {
|
||||
inlineNavButtonsEndSpacingPx =
|
||||
res.getDimensionPixelSize(inv.inlineNavButtonsEndSpacing);
|
||||
/*
|
||||
* 3 nav buttons +
|
||||
* Spacing between nav buttons +
|
||||
* Space at the end for contextual buttons
|
||||
*/
|
||||
hotseatBarEndOffset = 3 * res.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size)
|
||||
+ 2 * res.getDimensionPixelSize(R.dimen.taskbar_button_space_inbetween)
|
||||
+ inlineNavButtonsEndSpacingPx;
|
||||
} else {
|
||||
inlineNavButtonsEndSpacingPx = 0;
|
||||
hotseatBarEndOffset = 0;
|
||||
/* 3 nav buttons + Spacing between nav buttons */
|
||||
navButtonsLayoutWidthPx = 3 * res.getDimensionPixelSize(
|
||||
R.dimen.taskbar_nav_buttons_size)
|
||||
+ 2 * res.getDimensionPixelSize(R.dimen.taskbar_button_space_inbetween);
|
||||
/* nav buttons layout width + Space at the end for contextual buttons */
|
||||
hotseatBarEndOffset = navButtonsLayoutWidthPx + inlineNavButtonsEndSpacingPx;
|
||||
}
|
||||
|
||||
mBubbleBarSpaceThresholdPx =
|
||||
@@ -2326,6 +2326,25 @@ public class DeviceProfile {
|
||||
return c.createConfigurationContext(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether Taskbar and Hotseat should adjust horizontally on bubble bar location update.
|
||||
*/
|
||||
public boolean shouldAdjustHotseatOnBubblesLocationUpdate(Context context) {
|
||||
return enableBubbleBar()
|
||||
&& enableBubbleBarInPersistentTaskBar()
|
||||
&& DisplayController.getNavigationMode(context)
|
||||
== NavigationMode.THREE_BUTTONS;
|
||||
}
|
||||
|
||||
/** Returns hotseat translation X for the bubble bar position. */
|
||||
public int getHotseatTranslationXForBubbleBar(boolean isNavbarOnRight) {
|
||||
if (isNavbarOnRight) {
|
||||
return 0;
|
||||
} else {
|
||||
return navButtonsLayoutWidthPx;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback when a component changes the DeviceProfile associated with it, as a result of
|
||||
* configuration change
|
||||
|
||||
@@ -34,8 +34,10 @@ import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.util.HorizontalInsettableView;
|
||||
import com.android.launcher3.util.MultiPropertyFactory;
|
||||
import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
|
||||
import com.android.launcher3.util.MultiTranslateDelegate;
|
||||
import com.android.launcher3.util.MultiValueAlpha;
|
||||
@@ -61,6 +63,14 @@ public class Hotseat extends CellLayout implements Insettable {
|
||||
public @interface HotseatQsbAlphaId {
|
||||
}
|
||||
|
||||
public static final int ICONS_TRANSLATION_X_NAV_BAR_ALIGNMENT = 0;
|
||||
public static final int ICONS_TRANSLATION_X_CHANNELS_COUNT = 1;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@IntDef({ICONS_TRANSLATION_X_NAV_BAR_ALIGNMENT})
|
||||
public @interface IconsTranslationX {
|
||||
}
|
||||
|
||||
// Ratio of empty space, qsb should take up to appear visually centered.
|
||||
public static final float QSB_CENTER_FACTOR = .325f;
|
||||
private static final int BUBBLE_BAR_ADJUSTMENT_ANIMATION_DURATION_MS = 250;
|
||||
@@ -72,6 +82,10 @@ public class Hotseat extends CellLayout implements Insettable {
|
||||
private final MultiValueAlpha mIconsAlphaChannels;
|
||||
private final MultiValueAlpha mQsbAlphaChannels;
|
||||
|
||||
private @Nullable MultiProperty mQsbTranslationX;
|
||||
|
||||
private final MultiPropertyFactory mIconsTranslationXFactory;
|
||||
|
||||
private final View mQsb;
|
||||
|
||||
public Hotseat(Context context) {
|
||||
@@ -88,9 +102,26 @@ public class Hotseat extends CellLayout implements Insettable {
|
||||
addView(mQsb);
|
||||
mIconsAlphaChannels = new MultiValueAlpha(getShortcutsAndWidgets(),
|
||||
ALPHA_CHANNEL_CHANNELS_COUNT);
|
||||
if (mQsb instanceof Reorderable qsbReorderable) {
|
||||
mQsbTranslationX = qsbReorderable.getTranslateDelegate()
|
||||
.getTranslationX(MultiTranslateDelegate.INDEX_NAV_BAR_ANIM);
|
||||
}
|
||||
mIconsTranslationXFactory = new MultiPropertyFactory<>(getShortcutsAndWidgets(),
|
||||
VIEW_TRANSLATE_X, ICONS_TRANSLATION_X_CHANNELS_COUNT, Float::sum);
|
||||
mQsbAlphaChannels = new MultiValueAlpha(mQsb, ALPHA_CHANNEL_CHANNELS_COUNT);
|
||||
}
|
||||
|
||||
/** Provides translation X for hotseat icons for the channel. */
|
||||
public MultiProperty getIconsTranslationX(@IconsTranslationX int channelId) {
|
||||
return mIconsTranslationXFactory.get(channelId);
|
||||
}
|
||||
|
||||
/** Provides translation X for hotseat Qsb. */
|
||||
@Nullable
|
||||
public MultiProperty getQsbTranslationX() {
|
||||
return mQsbTranslationX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns orientation specific cell X given invariant order in the hotseat
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user