Merge "Enable TaskbarEduTooltipControllerTest" into main
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index aafa1f6..ffde0d1 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -471,3 +471,10 @@
description: "Shows filtered set of widgets by default and an option to show all widgets in the widget picker"
bug: "356127021"
}
+
+flag {
+ name: "show_taskbar_pinning_popup_from_anywhere"
+ namespace: "launcher"
+ description: "Shows the pinning popup view after long-pressing or right-clicking anywhere on the pinned taskbar"
+ bug: "297325541"
+}
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 8957e0d..9836172 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -424,6 +424,7 @@
<!--- Taskbar Pinning -->
<dimen name="taskbar_pinning_popup_menu_width">300dp</dimen>
<dimen name="taskbar_pinning_popup_menu_vertical_margin">16dp</dimen>
+ <dimen name="taskbar_pinning_popup_menu_min_padding_from_screen_edge">16dp</dimen>
<!--- Floating Ime Inset height-->
<dimen name="floating_ime_inset_height">60dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
index b5a3314..69bc6bd 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
@@ -31,21 +31,21 @@
import android.widget.Switch
import androidx.core.view.postDelayed
import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
+import com.android.launcher3.Flags
import com.android.launcher3.R
import com.android.launcher3.popup.ArrowPopup
import com.android.launcher3.popup.RoundedArrowDrawable
import com.android.launcher3.util.DisplayController
import com.android.launcher3.util.Themes
import com.android.launcher3.views.ActivityContext
+import kotlin.math.max
+import kotlin.math.min
/** Popup view with arrow for taskbar pinning */
class TaskbarDividerPopupView<T : TaskbarActivityContext>
@JvmOverloads
-constructor(
- context: Context,
- attrs: AttributeSet? = null,
- defStyleAttr: Int = 0,
-) : ArrowPopup<T>(context, attrs, defStyleAttr) {
+constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
+ ArrowPopup<T>(context, attrs, defStyleAttr) {
companion object {
private const val TAG = "TaskbarDividerPopupView"
private const val DIVIDER_POPUP_CLOSING_DELAY = 333L
@@ -55,24 +55,28 @@
fun createAndPopulate(
view: View,
taskbarActivityContext: TaskbarActivityContext,
+ horizontalPosition: Float,
): TaskbarDividerPopupView<*> {
val taskMenuViewWithArrow =
taskbarActivityContext.layoutInflater.inflate(
R.layout.taskbar_divider_popup_menu,
taskbarActivityContext.dragLayer,
- false
+ false,
) as TaskbarDividerPopupView<*>
- return taskMenuViewWithArrow.populateForView(view)
+ return taskMenuViewWithArrow.populateForView(view, horizontalPosition)
}
}
private lateinit var dividerView: View
+ private var horizontalPosition = 0.0f
private val popupCornerRadius = Themes.getDialogCornerRadius(context)
private val arrowWidth = resources.getDimension(R.dimen.popup_arrow_width)
private val arrowHeight = resources.getDimension(R.dimen.popup_arrow_height)
private val arrowPointRadius = resources.getDimension(R.dimen.popup_arrow_corner_radius)
+ private val minPaddingFromScreenEdge =
+ resources.getDimension(R.dimen.taskbar_pinning_popup_menu_min_padding_from_screen_edge)
private var alwaysShowTaskbarOn = !DisplayController.isTransientTaskbar(context)
private var didPreferenceChange = false
@@ -128,7 +132,15 @@
/** Orient object as usual and then center object horizontally. */
override fun orientAboutObject() {
super.orientAboutObject()
- x = mTempRect.centerX() - measuredWidth / 2f
+ x =
+ if (Flags.showTaskbarPinningPopupFromAnywhere()) {
+ min(
+ max(minPaddingFromScreenEdge, horizontalPosition - measuredWidth / 2f),
+ popupContainer.getWidth() - measuredWidth - minPaddingFromScreenEdge,
+ )
+ } else {
+ mTempRect.centerX() - measuredWidth / 2f
+ }
}
override fun onControllerInterceptTouchEvent(ev: MotionEvent?): Boolean {
@@ -142,8 +154,9 @@
return false
}
- private fun populateForView(view: View): TaskbarDividerPopupView<*> {
+ private fun populateForView(view: View, horizontalPosition: Float): TaskbarDividerPopupView<*> {
dividerView = view
+ this@TaskbarDividerPopupView.horizontalPosition = horizontalPosition
tryUpdateBackground()
return this
}
@@ -169,15 +182,21 @@
override fun addArrow() {
super.addArrow()
- val location = IntArray(2)
- popupContainer.getLocationInDragLayer(dividerView, location)
- val dividerViewX = location[0].toFloat()
- // Change arrow location to the middle of popup.
- mArrow.x = (dividerViewX + dividerView.width / 2) - (mArrowWidth / 2)
+ if (Flags.showTaskbarPinningPopupFromAnywhere()) {
+ mArrow.x = horizontalPosition - mArrowWidth / 2
+ } else {
+ val location = IntArray(2)
+ popupContainer.getLocationInDragLayer(dividerView, location)
+ val dividerViewX = location[0].toFloat()
+ // Change arrow location to the middle of popup.
+ mArrow.x = (dividerViewX + dividerView.width / 2) - (mArrowWidth / 2)
+ }
}
override fun updateArrowColor() {
- if (!Gravity.isVertical(mGravity)) {
+ if (Flags.showTaskbarPinningPopupFromAnywhere()) {
+ super.updateArrowColor()
+ } else if (!Gravity.isVertical(mGravity)) {
mArrow.background =
RoundedArrowDrawable(
arrowWidth,
@@ -227,13 +246,13 @@
ObjectAnimator.ofFloat(
this,
TRANSLATION_Y,
- *floatArrayOf(this.translationY, this.translationY + translateYValue)
+ *floatArrayOf(this.translationY, this.translationY + translateYValue),
)
val arrowTranslateY =
ObjectAnimator.ofFloat(
mArrow,
TRANSLATION_Y,
- *floatArrayOf(mArrow.translationY, mArrow.translationY + translateYValue)
+ *floatArrayOf(mArrow.translationY, mArrow.translationY + translateYValue),
)
val animatorSet = AnimatorSet()
animatorSet.playTogether(alpha, arrowAlpha, translateY, arrowTranslateY)
@@ -243,7 +262,7 @@
private fun getAnimatorOfFloat(
view: View,
property: Property<View, Float>,
- vararg values: Float
+ vararg values: Float,
): Animator {
val animator: Animator = ObjectAnimator.ofFloat(view, property, *values)
animator.setDuration(DIVIDER_POPUP_CLOSING_ANIMATION_DURATION)
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 1141a01..55722a9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -151,30 +151,26 @@
DisplayController.showLockedTaskbarOnHome(context)
) {
// adding the taskbar touch region
- val touchableHeight: Int
var left = 0
var right = context.deviceProfile.widthPx
- var bubbleBarAdjustment = 0
+ val touchableHeight: Int
if (uiController.isAnimatingToLauncher) {
val dp = controllers.taskbarActivityContext.deviceProfile
touchableHeight = windowLayoutParams.height
if (dp.isQsbInline) {
// if Qsb is inline need to exclude search icon from touch region
val isRtl = Utilities.isRtl(context.resources)
- bubbleControllers?.bubbleBarViewController?.let {
- if (dp.shouldAdjustHotseatOnBubblesLocationUpdate(context)) {
+ val navBarOffset =
+ bubbleControllers?.bubbleBarViewController?.let {
val isBubblesOnLeft = it.bubbleBarLocation.isOnLeft(isRtl)
- bubbleBarAdjustment =
- dp.getHotseatTranslationXForBubbleBar(isBubblesOnLeft, isRtl)
- }
- }
+ dp.getHotseatTranslationXForNavBar(context, isBubblesOnLeft)
+ } ?: 0
val hotseatPadding: Rect = dp.getHotseatLayoutPadding(context)
val borderSpacing: Int = dp.hotseatBorderSpace
if (isRtl) {
- right =
- dp.widthPx - hotseatPadding.right + borderSpacing + bubbleBarAdjustment
+ right = dp.widthPx - hotseatPadding.right + borderSpacing + navBarOffset
} else {
- left = hotseatPadding.left - borderSpacing + bubbleBarAdjustment
+ left = hotseatPadding.left - borderSpacing + navBarOffset
}
}
} else {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 559be36..4bc7d3c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -886,19 +886,18 @@
mBubbleBarLocation = location;
if (location == null) {
// bubble bar is not present, hence no location, resetting the hotseat
- updateHotseatAndQsbTranslationX(0, animate);
+ updateHotseatAndQsbTranslationX(/* targetValue = */ 0, animate);
mBubbleBarLocation = null;
return;
}
DeviceProfile deviceProfile = mLauncher.getDeviceProfile();
- if (!deviceProfile.shouldAdjustHotseatOnBubblesLocationUpdate(
+ if (!deviceProfile.shouldAdjustHotseatOnNavBarLocationUpdate(
mControllers.taskbarActivityContext)) {
return;
}
- boolean isRtl = isRtl(mLauncher.getResources());
- boolean isBubblesOnLeft = location.isOnLeft(isRtl);
+ boolean isBubblesOnLeft = location.isOnLeft(isRtl(mLauncher.getResources()));
int targetX = deviceProfile
- .getHotseatTranslationXForBubbleBar(isBubblesOnLeft, isRtl);
+ .getHotseatTranslationXForNavBar(mLauncher, isBubblesOnLeft);
updateHotseatAndQsbTranslationX(targetX, animate);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPinningController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarPinningController.kt
index 1867cd0..7848b7e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPinningController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPinningController.kt
@@ -76,10 +76,10 @@
}
}
- fun showPinningView(view: View) {
+ fun showPinningView(view: View, horizontalPosition: Float = -1f) {
context.isTaskbarWindowFullscreen = true
view.post {
- val popupView = getPopupView(view)
+ val popupView = getPopupView(view, horizontalPosition)
popupView.requestFocus()
popupView.onCloseCallback = onCloseCallback
context.onPopupVisibilityChanged(true)
@@ -89,8 +89,8 @@
}
@VisibleForTesting
- fun getPopupView(view: View): TaskbarDividerPopupView<*> {
- return createAndPopulate(view, context)
+ fun getPopupView(view: View, horizontalPosition: Float = -1f): TaskbarDividerPopupView<*> {
+ return createAndPopulate(view, context, horizontalPosition)
}
@VisibleForTesting
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index d757180..07ec135 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -316,7 +316,8 @@
if (mAllAppsButtonContainer != null) {
mAllAppsButtonContainer.setUpCallbacks(callbacks);
}
- if (mTaskbarDividerContainer != null && callbacks.supportsDividerLongPress()) {
+ if (mTaskbarDividerContainer != null
+ && mActivityContext.getTaskbarFeatureEvaluator().getSupportsPinningPopup()) {
mTaskbarDividerContainer.setUpCallbacks(callbacks);
}
if (mTaskbarOverflowView != null) {
@@ -325,6 +326,10 @@
mTaskbarOverflowView.setOnLongClickListener(
mControllerCallbacks.getOverflowOnLongClickListener());
}
+ if (Flags.showTaskbarPinningPopupFromAnywhere()
+ && mActivityContext.getTaskbarFeatureEvaluator().getSupportsPinningPopup()) {
+ setOnTouchListener(mControllerCallbacks.getTaskbarTouchListener());
+ }
}
private void removeAndRecycle(View view) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
index 8bc1e12..4591f9b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
@@ -19,15 +19,19 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_ALLAPPS_BUTTON_LONG_PRESS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP;
+import android.annotation.SuppressLint;
import android.content.Context;
+import android.view.GestureDetector;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.View;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.internal.jank.Cuj;
import com.android.launcher3.taskbar.bubbles.BubbleBarViewController;
+import com.android.launcher3.util.DisplayController;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
import com.android.wm.shell.Flags;
import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
@@ -40,12 +44,14 @@
private final TaskbarActivityContext mActivity;
private final TaskbarControllers mControllers;
private final TaskbarView mTaskbarView;
+ private final GestureDetector mGestureDetector;
public TaskbarViewCallbacks(TaskbarActivityContext activity, TaskbarControllers controllers,
TaskbarView taskbarView) {
mActivity = activity;
mControllers = controllers;
mTaskbarView = taskbarView;
+ mGestureDetector = new GestureDetector(activity, new TaskbarViewGestureListener());
}
public View.OnClickListener getIconOnClickListener() {
@@ -70,23 +76,23 @@
return false;
}
- public View.OnLongClickListener getTaskbarDividerLongClickListener() {
- return v -> {
- mControllers.taskbarPinningController.showPinningView(v);
- return true;
- };
+ @SuppressLint("ClickableViewAccessibility")
+ public View.OnTouchListener getTaskbarTouchListener() {
+ return (view, event) -> mGestureDetector.onTouchEvent(event);
}
- /** Check to see if we support long press on taskbar divider */
- public boolean supportsDividerLongPress() {
- return !mActivity.isThreeButtonNav();
+ public View.OnLongClickListener getTaskbarDividerLongClickListener() {
+ return v -> {
+ mControllers.taskbarPinningController.showPinningView(v, getDividerCenterX());
+ return true;
+ };
}
public View.OnTouchListener getTaskbarDividerRightClickListener() {
return (v, event) -> {
if (event.isFromSource(InputDevice.SOURCE_MOUSE)
&& event.getButtonState() == MotionEvent.BUTTON_SECONDARY) {
- mControllers.taskbarPinningController.showPinningView(v);
+ mControllers.taskbarPinningController.showPinningView(v, getDividerCenterX());
return true;
}
return false;
@@ -159,4 +165,32 @@
}
};
}
+
+ private float getDividerCenterX() {
+ View divider = mTaskbarView.getTaskbarDividerViewContainer();
+ if (divider == null) {
+ return 0.0f;
+ }
+ return divider.getX() + (float) divider.getWidth() / 2;
+ }
+
+ private class TaskbarViewGestureListener extends GestureDetector.SimpleOnGestureListener {
+ @Override
+ public boolean onDown(@NonNull MotionEvent event) {
+ return true;
+ }
+
+ @Override
+ public boolean onSingleTapUp(@NonNull MotionEvent event) {
+ return true;
+ }
+
+ @Override
+ public void onLongPress(MotionEvent event) {
+ if (DisplayController.isPinnedTaskbar(mActivity)) {
+ mControllers.taskbarPinningController.showPinningView(mTaskbarView,
+ event.getRawX());
+ }
+ }
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index c275536..e9458ff 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -837,12 +837,11 @@
int firstRecentTaskIndex = -1;
int hotseatNavBarTranslationX = 0;
- if (mCurrentBubbleBarLocation != null
- && taskbarDp.shouldAdjustHotseatOnBubblesLocationUpdate(mActivity)) {
- boolean isRtl = mTaskbarView.isLayoutRtl();
- boolean isBubblesOnLeft = mCurrentBubbleBarLocation.isOnLeft(isRtl);
+ if (mCurrentBubbleBarLocation != null) {
+ boolean isBubblesOnLeft = mCurrentBubbleBarLocation
+ .isOnLeft(mTaskbarView.isLayoutRtl());
hotseatNavBarTranslationX = taskbarDp
- .getHotseatTranslationXForBubbleBar(isBubblesOnLeft, isRtl);
+ .getHotseatTranslationXForNavBar(mActivity, isBubblesOnLeft);
}
for (int i = 0; i < mTaskbarView.getChildCount(); i++) {
View child = mTaskbarView.getChildAt(i);
diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarFeatureEvaluator.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarFeatureEvaluator.kt
index 7739a0e..f130d29 100644
--- a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarFeatureEvaluator.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarFeatureEvaluator.kt
@@ -23,9 +23,7 @@
/** Evaluates all the features taskbar can have. */
class TaskbarFeatureEvaluator
-private constructor(
- private val taskbarActivityContext: TaskbarActivityContext,
-) {
+private constructor(private val taskbarActivityContext: TaskbarActivityContext) {
val hasAllApps = true
val hasAppIcons = true
val hasBubbles = false
@@ -43,6 +41,9 @@
val isLandscape: Boolean
get() = taskbarActivityContext.deviceProfile.isLandscape
+ val supportsPinningPopup: Boolean
+ get() = !hasNavButtons
+
fun onDestroy() {
taskbarFeatureEvaluator = null
}
@@ -51,9 +52,7 @@
@Volatile private var taskbarFeatureEvaluator: TaskbarFeatureEvaluator? = null
@JvmStatic
- fun getInstance(
- taskbarActivityContext: TaskbarActivityContext,
- ): TaskbarFeatureEvaluator {
+ fun getInstance(taskbarActivityContext: TaskbarActivityContext): TaskbarFeatureEvaluator {
synchronized(this) {
if (taskbarFeatureEvaluator == null) {
taskbarFeatureEvaluator = TaskbarFeatureEvaluator(taskbarActivityContext)
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index acdff71..4ad65e1 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -1101,10 +1101,9 @@
if (isBubbleBarEnabled()
&& enableBubbleBarInPersistentTaskBar()
&& mBubbleBarLocation != null) {
- boolean isRtl = isRtl(getResources());
- boolean isBubblesOnLeft = mBubbleBarLocation.isOnLeft(isRtl);
+ boolean isBubblesOnLeft = mBubbleBarLocation.isOnLeft(isRtl(getResources()));
translationX += mDeviceProfile
- .getHotseatTranslationXForBubbleBar(isBubblesOnLeft, isRtl);
+ .getHotseatTranslationXForNavBar(this, isBubblesOnLeft);
}
if (isBubbleBarEnabled()
&& mDeviceProfile.shouldAdjustHotseatForBubbleBar(getContext(), hasBubbles())) {
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 41a8a31..1481ef2 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -607,6 +607,9 @@
this::createFallbackSwipeHandler;
private final AbsSwipeUpHandler.Factory mRecentsWindowSwipeHandlerFactory =
this::createRecentsWindowSwipeHandler;
+ // This needs to be a member to be queued and potentially removed later if the service is
+ // destroyed before the user is unlocked
+ private final Runnable mUserUnlockedRunnable = this::onUserUnlocked;
private final ScreenOnTracker.ScreenOnListener mScreenOnListener = this::onScreenOnChanged;
@@ -678,8 +681,7 @@
mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer();
// Call runOnUserUnlocked() before any other callbacks to ensure everything is initialized.
- LockedUserState.get(this).runOnUserUnlocked(this::onUserUnlocked);
- LockedUserState.get(this).runOnUserUnlocked(mTaskbarManager::onUserUnlocked);
+ LockedUserState.get(this).runOnUserUnlocked(mUserUnlockedRunnable);
mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
sConnected = true;
@@ -746,6 +748,8 @@
mOverviewComponentObserver.setOverviewChangeListener(this::onOverviewTargetChange);
onOverviewTargetChange(mOverviewComponentObserver.isHomeAndOverviewSame());
+
+ mTaskbarManager.onUserUnlocked();
}
public OverviewCommandHelper getOverviewCommandHelper() {
@@ -836,6 +840,7 @@
mDesktopVisibilityController.onDestroy();
sConnected = false;
+ LockedUserState.get(this).removeOnUserUnlockedRunnable(mUserUnlockedRunnable);
ScreenOnTracker.INSTANCE.get(this).removeListener(mScreenOnListener);
super.onDestroy();
}
diff --git a/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java b/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java
index e82d9fc..977c036 100644
--- a/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java
+++ b/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java
@@ -20,7 +20,6 @@
import com.android.launcher3.dagger.LauncherBaseAppComponent;
import com.android.launcher3.model.WellbeingModel;
import com.android.quickstep.util.AsyncClockEventDelegate;
-import com.android.quickstep.util.ContextualSearchHapticManager;
/**
* Launcher Quickstep base component for Dagger injection.
@@ -35,6 +34,4 @@
WellbeingModel getWellbeingModel();
AsyncClockEventDelegate getAsyncClockEventDelegate();
-
- ContextualSearchHapticManager getContextualSearchHapticManager();
}
diff --git a/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java b/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java
index 34b3d74..4f9d837 100644
--- a/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java
@@ -27,7 +27,6 @@
import static com.android.launcher3.GestureNavContract.EXTRA_REMOTE_CALLBACK;
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
-import android.animation.ObjectAnimator;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.Intent;
@@ -62,16 +61,15 @@
import com.android.launcher3.util.DisplayController;
import com.android.quickstep.AbsSwipeUpHandler;
import com.android.quickstep.GestureState;
+import com.android.quickstep.RecentsAnimationController;
import com.android.quickstep.RecentsAnimationDeviceState;
-import com.android.quickstep.RemoteAnimationTargets;
+import com.android.quickstep.RecentsAnimationTargets;
import com.android.quickstep.TaskAnimationManager;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.fallback.RecentsState;
-import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties;
import com.android.quickstep.util.TransformParams;
-import com.android.quickstep.util.TransformParams.BuilderProxy;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.system.InputConsumerController;
@@ -115,12 +113,25 @@
mRunningOverHome = mGestureState.getRunningTask() != null
&& mGestureState.getRunningTask().isHomeTask();
- if (mRunningOverHome) {
- runActionOnRemoteHandles(remoteTargetHandle ->
- remoteTargetHandle.getTransformParams().setHomeBuilderProxy(
- RecentsWindowSwipeHandler.
- this::updateHomeActivityTransformDuringSwipeUp));
+
+ initTransformParams();
+ }
+
+ @Override
+ public void onRecentsAnimationStart(RecentsAnimationController controller,
+ RecentsAnimationTargets targets) {
+ super.onRecentsAnimationStart(controller, targets);
+ initTransformParams();
+ }
+
+ private void initTransformParams() {
+ if (mActiveAnimationFactory != null) {
+ mActiveAnimationFactory.initTransformParams();
+ return;
}
+ runActionOnRemoteHandles(remoteTargetHandle ->
+ remoteTargetHandle.getTransformParams().setHomeBuilderProxy(
+ RecentsWindowSwipeHandler.this::updateHomeActivityTransformDuringSwipeUp));
}
@Override
@@ -135,12 +146,17 @@
private void updateHomeActivityTransformDuringSwipeUp(SurfaceProperties builder,
RemoteAnimationTarget app, TransformParams params) {
- setHomeScaleAndAlpha(builder, app, mCurrentShift.value,
- Utilities.boundToRange(1 - mCurrentShift.value, 0, 1));
+ if (mActiveAnimationFactory != null) {
+ return;
+ }
+ setHomeScaleAndAlpha(builder, app, mCurrentShift.value, 0);
}
private void setHomeScaleAndAlpha(SurfaceProperties builder,
RemoteAnimationTarget app, float verticalShift, float alpha) {
+ if (app.windowConfiguration.getActivityType() != ACTIVITY_TYPE_HOME) {
+ return;
+ }
float scale = Utilities.mapRange(verticalShift, 1, mMaxLauncherScale);
mTmpMatrix.setScale(scale, scale,
app.localBounds.exactCenterX(), app.localBounds.exactCenterY());
@@ -163,25 +179,13 @@
mActiveAnimationFactory = new FallbackHomeAnimationFactory(duration);
//todo: b/368410893 follow up on this as its intent focused and seems to cut immediately
Intent intent = new Intent(mGestureState.getHomeIntent());
- if (mActiveAnimationFactory != null && runningTaskTarget != null) {
+ if (runningTaskTarget != null) {
mActiveAnimationFactory.addGestureContract(intent, runningTaskTarget.taskInfo);
}
return mActiveAnimationFactory;
}
@Override
- protected boolean handleTaskAppeared(@NonNull RemoteAnimationTarget[] appearedTaskTargets,
- @NonNull ActiveGestureLog.CompoundString failureReason) {
- if (mActiveAnimationFactory != null
- && mActiveAnimationFactory.handleHomeTaskAppeared(appearedTaskTargets)) {
- mActiveAnimationFactory = null;
- return false;
- }
-
- return super.handleTaskAppeared(appearedTaskTargets, failureReason);
- }
-
- @Override
protected void finishRecentsControllerToHome(Runnable callback) {
final Runnable recentsCallback;
if (mAppCanEnterPip) {
@@ -236,11 +240,12 @@
private class FallbackHomeAnimationFactory extends HomeAnimationFactory
implements Consumer<Message> {
private final Rect mTempRect = new Rect();
- private final TransformParams mHomeAlphaParams = new TransformParams();
- private final AnimatedFloat mHomeAlpha;
- private final AnimatedFloat mVerticalShiftForScale = new AnimatedFloat();
- private final AnimatedFloat mRecentsAlpha = new AnimatedFloat();
+ private final TransformParams mTransformParams = new TransformParams();
+ private final AnimatedFloat mHomeAlpha = new AnimatedFloat(this::updateAppTransforms);
+ private final AnimatedFloat mVerticalShiftForScale =
+ new AnimatedFloat(this::updateAppTransforms);
+ private final AnimatedFloat mRecentsAlpha = new AnimatedFloat(this:: updateAppTransforms);
private final RectF mTargetRect = new RectF();
private SurfaceControl mSurfaceControl;
@@ -255,25 +260,12 @@
mDuration = duration;
if (mRunningOverHome) {
- mHomeAlpha = new AnimatedFloat();
- mHomeAlpha.value = Utilities.boundToRange(1 - mCurrentShift.value, 0, 1);
mVerticalShiftForScale.value = mCurrentShift.value;
- runActionOnRemoteHandles(remoteTargetHandle ->
- remoteTargetHandle.getTransformParams().setHomeBuilderProxy(
- FallbackHomeAnimationFactory.this
- ::updateHomeActivityTransformDuringHomeAnim));
- } else {
- mHomeAlpha = new AnimatedFloat(this::updateHomeAlpha);
- mHomeAlpha.value = 0;
- mHomeAlphaParams.setHomeBuilderProxy(
- this::updateHomeActivityTransformDuringHomeAnim);
}
-
mRecentsAlpha.value = 1;
- runActionOnRemoteHandles(remoteTargetHandle ->
- remoteTargetHandle.getTransformParams().setBaseBuilderProxy(
- FallbackHomeAnimationFactory.this
- ::updateRecentsActivityTransformDuringHomeAnim));
+ mHomeAlpha.value = 0;
+
+ initTransformParams();
}
@NonNull
@@ -285,63 +277,30 @@
return mTargetRect;
}
- private void updateRecentsActivityTransformDuringHomeAnim(SurfaceProperties builder,
- RemoteAnimationTarget app, TransformParams params) {
- builder.setAlpha(mRecentsAlpha.value);
- }
-
- private void updateHomeActivityTransformDuringHomeAnim(SurfaceProperties builder,
- RemoteAnimationTarget app, TransformParams params) {
- setHomeScaleAndAlpha(builder, app, mVerticalShiftForScale.value, mHomeAlpha.value);
- }
-
@NonNull
@Override
public AnimatorPlaybackController createActivityAnimationToHome() {
PendingAnimation pa = new PendingAnimation(mDuration);
pa.setFloat(mRecentsAlpha, AnimatedFloat.VALUE, 0, ACCELERATE);
+ pa.setFloat(mHomeAlpha, AnimatedFloat.VALUE, 1, ACCELERATE);
return pa.createPlaybackController();
}
- private void updateHomeAlpha() {
- if (mHomeAlphaParams.getTargetSet() != null) {
- mHomeAlphaParams.applySurfaceParams(
- mHomeAlphaParams.createSurfaceParams(BuilderProxy.NO_OP));
- }
- }
-
- public boolean handleHomeTaskAppeared(RemoteAnimationTarget[] appearedTaskTargets) {
- RemoteAnimationTarget appearedTaskTarget = appearedTaskTargets[0];
- if (appearedTaskTarget.windowConfiguration.getActivityType() == ACTIVITY_TYPE_HOME) {
- RemoteAnimationTargets targets = new RemoteAnimationTargets(
- new RemoteAnimationTarget[] {appearedTaskTarget},
- new RemoteAnimationTarget[0], new RemoteAnimationTarget[0],
- appearedTaskTarget.mode);
- mHomeAlphaParams.setTargetSet(targets);
- updateHomeAlpha();
- return true;
- }
- return false;
- }
-
@Override
public void playAtomicAnimation(float velocity) {
- ObjectAnimator alphaAnim = mHomeAlpha.animateToValue(mHomeAlpha.value, 1);
- alphaAnim.setDuration(mDuration).setInterpolator(ACCELERATE);
- alphaAnim.start();
-
- if (mRunningOverHome) {
- // Spring back launcher scale
- new SpringAnimationBuilder(mContext)
- .setStartValue(mVerticalShiftForScale.value)
- .setEndValue(0)
- .setStartVelocity(-velocity / mTransitionDragLength)
- .setMinimumVisibleChange(1f / mDp.heightPx)
- .setDampingRatio(0.6f)
- .setStiffness(800)
- .build(mVerticalShiftForScale, AnimatedFloat.VALUE)
- .start();
+ if (!mRunningOverHome) {
+ return;
}
+ // Spring back launcher scale
+ new SpringAnimationBuilder(mContext)
+ .setStartValue(mVerticalShiftForScale.value)
+ .setEndValue(0)
+ .setStartVelocity(-velocity / mTransitionDragLength)
+ .setMinimumVisibleChange(1f / mDp.heightPx)
+ .setDampingRatio(0.6f)
+ .setStiffness(800)
+ .build(mVerticalShiftForScale, AnimatedFloat.VALUE)
+ .start();
}
@Override
@@ -350,6 +309,34 @@
mSpringAnim.addAnimatorListener(forEndCallback(this::onRectAnimationEnd));
}
+ private void initTransformParams() {
+ runActionOnRemoteHandles(remoteTargetHandle ->
+ remoteTargetHandle.getTransformParams().setHomeBuilderProxy(
+ FallbackHomeAnimationFactory.this
+ ::updateHomeActivityTransformDuringHomeAnim));
+
+ mTransformParams.setTargetSet(mRecentsAnimationTargets);
+ }
+
+ private void updateRecentsActivityTransformDuringHomeAnim(SurfaceProperties builder,
+ RemoteAnimationTarget app, TransformParams params) {
+ if (app.mode != mRecentsAnimationTargets.targetMode) {
+ return;
+ }
+ builder.setAlpha(mRecentsAlpha.value);
+ }
+
+ private void updateAppTransforms() {
+ mTransformParams.applySurfaceParams(
+ mTransformParams.createSurfaceParams(FallbackHomeAnimationFactory.this
+ ::updateRecentsActivityTransformDuringHomeAnim));
+ }
+
+ private void updateHomeActivityTransformDuringHomeAnim(SurfaceProperties builder,
+ RemoteAnimationTarget app, TransformParams params) {
+ setHomeScaleAndAlpha(builder, app, mVerticalShiftForScale.value, mHomeAlpha.value);
+ }
+
private void onRectAnimationEnd() {
mAnimationFinished = true;
maybeSendEndMessage();
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java
index 1a825a4..155d095 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java
@@ -30,7 +30,6 @@
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
-import com.android.launcher3.LauncherApplication;
import com.android.launcher3.R;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceIdSequence;
@@ -62,8 +61,7 @@
mContext = context;
mStatsLogManager = StatsLogManager.newInstance(context);
mVibratorWrapper = VibratorWrapper.INSTANCE.get(mContext);
- mContextualSearchHapticManager = ((LauncherApplication) context.getApplicationContext())
- .getAppComponent().getContextualSearchHapticManager();
+ mContextualSearchHapticManager = ContextualSearchHapticManager.INSTANCE.get(context);
mContextualSearchInvoker = ContextualSearchInvoker.newInstance(mContext);
}
diff --git a/quickstep/src/com/android/quickstep/util/ContextualSearchHapticManager.kt b/quickstep/src/com/android/quickstep/util/ContextualSearchHapticManager.kt
index 8c246a5..286b77a 100644
--- a/quickstep/src/com/android/quickstep/util/ContextualSearchHapticManager.kt
+++ b/quickstep/src/com/android/quickstep/util/ContextualSearchHapticManager.kt
@@ -21,17 +21,15 @@
import android.os.VibrationEffect.Composition
import android.os.Vibrator
import com.android.launcher3.dagger.ApplicationContext
-import com.android.launcher3.dagger.LauncherAppSingleton
+import com.android.launcher3.util.MainThreadInitializedObject
+import com.android.launcher3.util.SafeCloseable
import com.android.launcher3.util.VibratorWrapper
import com.android.quickstep.DeviceConfigWrapper.Companion.get
-import javax.inject.Inject
import kotlin.math.pow
/** Manages haptics relating to Contextual Search invocations. */
-@LauncherAppSingleton
class ContextualSearchHapticManager
-@Inject
-internal constructor(@ApplicationContext private val context: Context) {
+internal constructor(@ApplicationContext private val context: Context) : SafeCloseable {
private var searchEffect = createSearchEffect()
private var contextualSearchStateManager = ContextualSearchStateManager.INSTANCE[context]
@@ -98,4 +96,10 @@
VibratorWrapper.INSTANCE[context].vibrate(composition.compose())
}
}
+
+ override fun close() {}
+
+ companion object {
+ @JvmField val INSTANCE = MainThreadInitializedObject { ContextualSearchHapticManager(it) }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/util/ContextualSearchInvoker.kt b/quickstep/src/com/android/quickstep/util/ContextualSearchInvoker.kt
index dcb72aa..bd454c0 100644
--- a/quickstep/src/com/android/quickstep/util/ContextualSearchInvoker.kt
+++ b/quickstep/src/com/android/quickstep/util/ContextualSearchInvoker.kt
@@ -22,7 +22,6 @@
import android.content.Context
import android.util.Log
import com.android.internal.app.AssistUtils
-import com.android.launcher3.LauncherApplication
import com.android.launcher3.R
import com.android.launcher3.logging.StatsLogManager
import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_LAUNCH_ASSISTANT_FAILED_SERVICE_ERROR
@@ -57,9 +56,7 @@
TopTaskTracker.INSTANCE[context],
SystemUiProxy.INSTANCE[context],
StatsLogManager.newInstance(context),
- (context.applicationContext as LauncherApplication)
- .appComponent
- .contextualSearchHapticManager,
+ ContextualSearchHapticManager.INSTANCE[context],
context.getSystemService(ContextualSearchManager::class.java),
)
diff --git a/quickstep/src/com/android/quickstep/util/TransformParams.java b/quickstep/src/com/android/quickstep/util/TransformParams.java
index ebcef30..401eccc 100644
--- a/quickstep/src/com/android/quickstep/util/TransformParams.java
+++ b/quickstep/src/com/android/quickstep/util/TransformParams.java
@@ -143,18 +143,15 @@
for (int i = 0; i < targets.unfilteredApps.length; i++) {
RemoteAnimationTarget app = targets.unfilteredApps[i];
SurfaceProperties builder = transaction.forSurface(app.leash);
+ BuilderProxy targetProxy =
+ app.windowConfiguration.getActivityType() == ACTIVITY_TYPE_HOME
+ ? mHomeBuilderProxy
+ : (app.mode == targets.targetMode ? proxy : mBaseBuilderProxy);
if (app.mode == targets.targetMode) {
- int activityType = app.windowConfiguration.getActivityType();
- if (activityType == ACTIVITY_TYPE_HOME) {
- mHomeBuilderProxy.onBuildTargetParams(builder, app, this);
- } else {
- builder.setAlpha(getTargetAlpha());
- proxy.onBuildTargetParams(builder, app, this);
- }
- } else {
- mBaseBuilderProxy.onBuildTargetParams(builder, app, this);
+ builder.setAlpha(getTargetAlpha());
}
+ targetProxy.onBuildTargetParams(builder, app, this);
}
// always put wallpaper layer to bottom.
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index b18af65..5458ba1 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -3810,7 +3810,7 @@
}
} else if (!showAsGrid || (enableLargeDesktopWindowingTile()
&& dismissedTaskView.isLargeTile()
- && nextFocusedTaskView == null)) {
+ && nextFocusedTaskView == null && !dismissingForSplitSelection)) {
int offset = getOffsetToDismissedTask(scrollDiffPerPage, dismissedIndex, taskCount);
int scrollDiff = newScroll[i] - oldScroll[i] + offset;
if (scrollDiff != 0) {
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 76dc770..5acff06 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -1130,6 +1130,9 @@
if (itemInfo.isDisabled()) {
setContentDescription(getContext().getString(R.string.disabled_app_label,
itemInfo.contentDescription));
+ } else if (itemInfo instanceof WorkspaceItemInfo wai && wai.isArchived()) {
+ setContentDescription(
+ getContext().getString(R.string.app_archived_title, itemInfo.title));
} else if (hasDot()) {
int count = mDotInfo.getNotificationCount();
setContentDescription(
@@ -1142,8 +1145,16 @@
}
private void setDownloadStateContentDescription(ItemInfoWithIcon info, int progressLevel) {
- if ((info.runtimeStatusFlags & ItemInfoWithIcon.FLAG_ARCHIVED) != 0 && progressLevel == 0) {
- setContentDescription(getContext().getString(R.string.app_archived_title, info.title));
+ if ((info.runtimeStatusFlags & ItemInfoWithIcon.FLAG_ARCHIVED) != 0
+ && progressLevel == 0) {
+ if (mIcon instanceof PreloadIconDrawable) {
+ // Tell user that download is pending and not to tap to download again.
+ setContentDescription(getContext().getString(
+ R.string.app_waiting_download_title, info.title));
+ } else {
+ setContentDescription(getContext().getString(
+ R.string.app_archived_title, info.title));
+ }
} else if ((info.runtimeStatusFlags & ItemInfoWithIcon.FLAG_SHOW_DOWNLOAD_PROGRESS_MASK)
!= 0) {
String percentageString = NumberFormat.getPercentInstance()
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index afe0ee1..8862550 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -2355,18 +2355,23 @@
/**
* Returns whether Taskbar and Hotseat should adjust horizontally on bubble bar location update.
*/
- public boolean shouldAdjustHotseatOnBubblesLocationUpdate(Context context) {
+ public boolean shouldAdjustHotseatOnNavBarLocationUpdate(Context context) {
return enableBubbleBar()
&& enableBubbleBarInPersistentTaskBar()
&& !DisplayController.getNavigationMode(context).hasGestures;
}
/** Returns hotseat translation X for the bubble bar position. */
- public int getHotseatTranslationXForBubbleBar(boolean isNavbarOnRight, boolean isRtl) {
- if (isNavbarOnRight) {
- return isRtl ? -navButtonsLayoutWidthPx : 0;
+ public int getHotseatTranslationXForNavBar(Context context, boolean isBubblesOnLeft) {
+ if (shouldAdjustHotseatOnNavBarLocationUpdate(context)) {
+ boolean isRtl = Utilities.isRtl(context.getResources());
+ if (isBubblesOnLeft) {
+ return isRtl ? -navButtonsLayoutWidthPx : 0;
+ } else {
+ return isRtl ? 0 : navButtonsLayoutWidthPx;
+ }
} else {
- return isRtl ? 0 : navButtonsLayoutWidthPx;
+ return 0;
}
}
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
index de3bb9e..7e3e392 100644
--- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
@@ -118,8 +118,14 @@
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_GO) {
- Log.i(TAG, "User tapped ime search button");
+ if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_GO || (
+ actionId == EditorInfo.IME_NULL && event != null
+ && event.getAction() == KeyEvent.ACTION_DOWN)) {
+ if (actionId == EditorInfo.IME_NULL) {
+ Log.i(TAG, "User pressed ENTER key");
+ } else {
+ Log.i(TAG, "User tapped ime search button");
+ }
// selectFocusedView should return SearchTargetEvent that is passed onto onClick
return mLauncher.getAppsView().getMainAdapterProvider().launchHighlightedItem();
}
diff --git a/src/com/android/launcher3/util/LockedUserState.kt b/src/com/android/launcher3/util/LockedUserState.kt
index 10559f3..c8d86d4 100644
--- a/src/com/android/launcher3/util/LockedUserState.kt
+++ b/src/com/android/launcher3/util/LockedUserState.kt
@@ -88,6 +88,13 @@
mUserUnlockedActions.add(action)
}
+ /**
+ * Removes a previously queued `Runnable` to be run when the user is unlocked.
+ */
+ fun removeOnUserUnlockedRunnable(action: Runnable) {
+ mUserUnlockedActions.remove(action)
+ }
+
companion object {
@VisibleForTesting
@JvmField