Merge "Move task to middle when dragging up in grid only overview" into main
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index 874f862..ace2210 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -32,7 +32,7 @@
name: "enable_responsive_workspace"
namespace: "launcher"
description: "Enables new workspace grid calculations method."
- bug: "241386436"
+ bug: "302189128"
}
flag {
@@ -41,3 +41,17 @@
description: "Enable updated overview icon and menu within task."
bug: "257950105"
}
+
+flag {
+ name: "enable_taskbar_no_recreate"
+ namespace: "launcher"
+ description: "Enables taskbar with no recreation from lifecycle changes of TaskbarActivityContext."
+ bug: "299193589"
+}
+
+flag {
+ name: "enable_home_transition_listener"
+ namespace: "launcher"
+ description: "Enables launcher to listen to all transitions that include home activity"
+ bug: "306053414"
+}
diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto
index f8b08f8..dde69e3 100644
--- a/protos/launcher_atom.proto
+++ b/protos/launcher_atom.proto
@@ -135,7 +135,7 @@
}
}
-// Next value 52
+// Next value 53
enum Attribute {
option allow_alias = true;
@@ -188,6 +188,7 @@
ALL_APPS_SEARCH_RESULT_EDUCARD = 43;
ALL_APPS_SEARCH_RESULT_LOCATION = 50;
ALL_APPS_SEARCH_RESULT_TEXT_HEADER = 51;
+ ALL_APPS_SEARCH_RESULT_NO_FULFILLMENT = 52;
// Result sources
DATA_SOURCE_APPSEARCH_APP_PREVIEW = 45;
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index 6d958ed..82f8ebe 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -30,7 +30,9 @@
<uses-permission android:name="android.permission.REMOVE_TASKS"/>
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_TASKS"/>
+ <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"/>
<uses-permission android:name="android.permission.STATUS_BAR"/>
+ <uses-permission android:name="android.permission.STATUS_BAR_SERVICE"/>
<uses-permission android:name="android.permission.STOP_APP_SWITCHES"/>
<uses-permission android:name="android.permission.SET_ORIENTATION"/>
<uses-permission android:name="android.permission.READ_FRAME_BUFFER"/>
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index c5d0b95..e77d2c6 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -1057,9 +1057,9 @@
boolean allowBlurringLauncher = mLauncher.getStateManager().getState() != OVERVIEW
&& BlurUtils.supportsBlursOnWindows();
- ObjectAnimator backgroundRadiusAnim =
- ObjectAnimator.ofFloat(mLauncher.getDepthController().stateDepth,
- MULTI_PROPERTY_VALUE, BACKGROUND_APP.getDepth(mLauncher))
+ LaunchDepthController depthController = new LaunchDepthController(mLauncher);
+ ObjectAnimator backgroundRadiusAnim = ObjectAnimator.ofFloat(depthController.stateDepth,
+ MULTI_PROPERTY_VALUE, BACKGROUND_APP.getDepth(mLauncher))
.setDuration(APP_LAUNCH_DURATION);
if (allowBlurringLauncher) {
@@ -1085,6 +1085,9 @@
new SurfaceControl.Transaction().remove(dimLayer).apply()));
}
+ backgroundRadiusAnim.addListener(
+ AnimatorListeners.forEndCallback(depthController::dispose));
+
return backgroundRadiusAnim;
}
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
index 957db64..882682d 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
@@ -94,6 +94,18 @@
}
}
+ /**
+ * Cleans up after this controller so it can be garbage collected without leaving traces.
+ */
+ public void dispose() {
+ removeSecondaryListeners();
+
+ if (mLauncher.getRootView() != null && mOnAttachListener != null) {
+ mLauncher.getRootView().removeOnAttachStateChangeListener(mOnAttachListener);
+ mOnAttachListener = null;
+ }
+ }
+
private void removeSecondaryListeners() {
if (mCrossWindowBlurListener != null) {
CrossWindowBlurListeners.getInstance().removeListener(mCrossWindowBlurListener);
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 445a1bd..09376d7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -16,7 +16,6 @@
package com.android.launcher3.taskbar;
import static com.android.launcher3.QuickstepTransitionManager.TRANSIENT_TASKBAR_TRANSITION_DURATION;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_HOME_TRANSITION_LISTENER;
import static com.android.launcher3.statemanager.BaseState.FLAG_NON_INTERACTIVE;
import static com.android.launcher3.taskbar.TaskbarEduTooltipControllerKt.TOOLTIP_STEP_FEATURES;
import static com.android.launcher3.taskbar.TaskbarLauncherStateController.FLAG_VISIBLE;
@@ -39,6 +38,7 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatedFloat;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceIdSequence;
import com.android.launcher3.model.data.ItemInfo;
@@ -101,7 +101,7 @@
mLauncher.setTaskbarUIController(this);
- if (!ENABLE_HOME_TRANSITION_LISTENER.get()) {
+ if (!FeatureFlags.enableHomeTransitionListener()) {
onLauncherVisibilityChanged(mLauncher.hasBeenResumed(), true /* fromInit */);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index d4d6b26..6ee151b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -20,6 +20,7 @@
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.window.SplashScreen.SPLASH_SCREEN_STYLE_UNDEFINED;
@@ -29,8 +30,8 @@
import static com.android.launcher3.Flags.enableCursorHoverStates;
import static com.android.launcher3.Utilities.calculateTextHeight;
import static com.android.launcher3.Utilities.isRunningInTestHarness;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NO_RECREATION;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_PINNING;
+import static com.android.launcher3.config.FeatureFlags.enableTaskbarNoRecreate;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_DRAGGING;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_FULLSCREEN;
@@ -128,6 +129,7 @@
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Optional;
+import java.util.function.Consumer;
/**
* The {@link ActivityContext} with which we inflate Taskbar-related Views. This allows UI elements
@@ -173,13 +175,16 @@
private final TaskbarShortcutMenuAccessibilityDelegate mAccessibilityDelegate;
+ private DeviceProfile mTransientTaskbarDeviceProfile;
+
+ private DeviceProfile mPersistentTaskbarDeviceProfile;
+
public TaskbarActivityContext(Context windowContext, DeviceProfile launcherDp,
TaskbarNavButtonController buttonController, ScopedUnfoldTransitionProgressProvider
unfoldTransitionProgressProvider) {
super(windowContext);
applyDeviceProfile(launcherDp);
-
final Resources resources = getResources();
mImeDrawsImeNavBar = getBoolByName(IME_DRAWS_IME_NAV_BAR_RES_NAME, resources, false);
@@ -254,9 +259,9 @@
new TaskbarViewController(this, taskbarView),
new TaskbarScrimViewController(this, taskbarScrimView),
new TaskbarUnfoldAnimationController(this, unfoldTransitionProgressProvider,
- mWindowManager,
- new RotationChangeProvider(c.getSystemService(DisplayManager.class), this,
- getMainThreadHandler())),
+ mWindowManager,
+ new RotationChangeProvider(c.getSystemService(DisplayManager.class), this,
+ getMainThreadHandler())),
new TaskbarKeyguardController(this),
new StashedHandleViewController(this, stashedHandleView),
new TaskbarStashController(this),
@@ -274,7 +279,7 @@
: TaskbarRecentAppsController.DEFAULT,
new TaskbarEduTooltipController(this),
new KeyboardQuickSwitchController(),
- new TaskbarDividerPopupController(this),
+ new TaskbarPinningController(this),
bubbleControllersOptional);
}
@@ -295,17 +300,34 @@
* the icon size
*/
private void applyDeviceProfile(DeviceProfile originDeviceProfile) {
- mDeviceProfile = originDeviceProfile.toBuilder(this)
- .withDimensionsOverride(deviceProfile -> {
- // Taskbar should match the number of icons of hotseat
- deviceProfile.numShownHotseatIcons = originDeviceProfile.numShownHotseatIcons;
- // Same QSB width to have a smooth animation
- deviceProfile.hotseatQsbWidth = originDeviceProfile.hotseatQsbWidth;
+ Consumer<DeviceProfile> overrideProvider = deviceProfile -> {
+ // Taskbar should match the number of icons of hotseat
+ deviceProfile.numShownHotseatIcons = originDeviceProfile.numShownHotseatIcons;
+ // Same QSB width to have a smooth animation
+ deviceProfile.hotseatQsbWidth = originDeviceProfile.hotseatQsbWidth;
- // Update icon size
- deviceProfile.iconSizePx = deviceProfile.taskbarIconSize;
- deviceProfile.updateIconSize(1f, getResources());
- }).build();
+ // Update icon size
+ deviceProfile.iconSizePx = deviceProfile.taskbarIconSize;
+ deviceProfile.updateIconSize(1f, getResources());
+ };
+ mDeviceProfile = originDeviceProfile.toBuilder(this)
+ .withDimensionsOverride(overrideProvider).build();
+
+ if (DisplayController.isTransientTaskbar(this)) {
+ mTransientTaskbarDeviceProfile = mDeviceProfile;
+ mPersistentTaskbarDeviceProfile = mDeviceProfile
+ .toBuilder(this)
+ .withDimensionsOverride(overrideProvider)
+ .setIsTransientTaskbar(false)
+ .build();
+ } else {
+ mPersistentTaskbarDeviceProfile = mDeviceProfile;
+ mTransientTaskbarDeviceProfile = mDeviceProfile
+ .toBuilder(this)
+ .withDimensionsOverride(overrideProvider)
+ .setIsTransientTaskbar(true)
+ .build();
+ }
mNavMode = DisplayController.getNavigationMode(this);
}
@@ -339,7 +361,7 @@
mIsDestroyed = false;
}
- if (!ENABLE_TASKBAR_NO_RECREATION.get() && !mAddedWindow) {
+ if (!enableTaskbarNoRecreate() && !mAddedWindow) {
mWindowManager.addView(mDragLayer, mWindowLayoutParams);
mAddedWindow = true;
} else {
@@ -391,7 +413,8 @@
/**
* Creates LayoutParams for adding a view directly to WindowManager as a new window.
- * @param type The window type to pass to the created WindowManager.LayoutParams.
+ *
+ * @param type The window type to pass to the created WindowManager.LayoutParams.
* @param title The window title to pass to the created WindowManager.LayoutParams.
*/
public WindowManager.LayoutParams createDefaultWindowLayoutParams(int type, String title) {
@@ -430,9 +453,10 @@
* for taskbar showing as navigation bar
*/
private WindowManager.LayoutParams createAllWindowParams() {
+ final int windowType =
+ FLAG_HIDE_NAVBAR_WINDOW ? TYPE_NAVIGATION_BAR : TYPE_NAVIGATION_BAR_PANEL;
WindowManager.LayoutParams windowLayoutParams =
- createDefaultWindowLayoutParams(TYPE_NAVIGATION_BAR_PANEL,
- TaskbarActivityContext.WINDOW_TITLE);
+ createDefaultWindowLayoutParams(windowType, TaskbarActivityContext.WINDOW_TITLE);
boolean isPhoneNavMode = TaskbarManager.isPhoneButtonNavMode(this);
if (!isPhoneNavMode) {
return windowLayoutParams;
@@ -445,7 +469,7 @@
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,
+ createDefaultWindowLayoutParams(windowType,
TaskbarActivityContext.WINDOW_TITLE);
switch (rot) {
case Surface.ROTATION_0, Surface.ROTATION_180 -> {
@@ -695,7 +719,7 @@
mIsDestroyed = true;
setUIController(TaskbarUIController.DEFAULT);
mControllers.onDestroy();
- if (!ENABLE_TASKBAR_NO_RECREATION.get() && !FLAG_HIDE_NAVBAR_WINDOW) {
+ if (!enableTaskbarNoRecreate() && !FLAG_HIDE_NAVBAR_WINDOW) {
mWindowManager.removeViewImmediate(mDragLayer);
mAddedWindow = false;
}
@@ -794,7 +818,7 @@
// Overlay AFVs are in a separate window and do not require Taskbar to be fullscreen.
if (!isDragInProgress
&& !AbstractFloatingView.hasOpenView(
- this, TYPE_ALL & ~TYPE_TASKBAR_OVERLAY_PROXY)) {
+ this, TYPE_ALL & ~TYPE_TASKBAR_OVERLAY_PROXY)) {
// Reverts Taskbar window to its original size
setTaskbarWindowFullscreen(false);
}
@@ -853,7 +877,7 @@
? resources.getDimensionPixelSize(R.dimen.arrow_toast_arrow_height)
+ (resources.getDimensionPixelSize(R.dimen.taskbar_tooltip_vertical_padding) * 2)
+ calculateTextHeight(
- resources.getDimensionPixelSize(R.dimen.arrow_toast_text_size))
+ resources.getDimensionPixelSize(R.dimen.arrow_toast_text_size))
: 0;
// Return transient taskbar window height when pinning feature is enabled, so taskbar view
@@ -865,7 +889,7 @@
return transientTaskbarDp.taskbarHeight
+ (2 * transientTaskbarDp.taskbarBottomMargin)
+ Math.max(extraHeightForTaskbarTooltips, resources.getDimensionPixelSize(
- R.dimen.transient_taskbar_shadow_blur));
+ R.dimen.transient_taskbar_shadow_blur));
}
@@ -878,6 +902,14 @@
return getResources().getDimensionPixelSize(R.dimen.taskbar_suw_frame);
}
+ public DeviceProfile getTransientTaskbarDeviceProfile() {
+ return mTransientTaskbarDeviceProfile;
+ }
+
+ public DeviceProfile getPersistentTaskbarDeviceProfile() {
+ return mPersistentTaskbarDeviceProfile;
+ }
+
/**
* Either adds or removes {@link WindowManager.LayoutParams#FLAG_NOT_FOCUSABLE} on the taskbar
* window.
@@ -1290,7 +1322,7 @@
void notifyUpdateLayoutParams() {
if (mDragLayer.isAttachedToWindow()) {
- if (ENABLE_TASKBAR_NO_RECREATION.get()) {
+ if (enableTaskbarNoRecreate()) {
mWindowManager.updateViewLayout(mDragLayer.getRootView(), mWindowLayoutParams);
} else {
mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
index d237c1f..d6016f1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
@@ -29,26 +29,39 @@
import com.android.launcher3.Utilities.mapRange
import com.android.launcher3.Utilities.mapToRange
import com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound
+import com.android.launcher3.taskbar.TaskbarPinningController.Companion.PINNING_PERSISTENT
+import com.android.launcher3.taskbar.TaskbarPinningController.Companion.PINNING_TRANSIENT
import com.android.launcher3.util.DisplayController
+import kotlin.math.min
/** Helps draw the taskbar background, made up of a rectangle plus two inverted rounded corners. */
-class TaskbarBackgroundRenderer(context: TaskbarActivityContext) {
+class TaskbarBackgroundRenderer(private val context: TaskbarActivityContext) {
private val isInSetup: Boolean = !context.isUserSetupComplete
private val DARK_THEME_SHADOW_ALPHA = 51f
private val LIGHT_THEME_SHADOW_ALPHA = 25f
+ private val maxTransientTaskbarHeight =
+ context.transientTaskbarDeviceProfile.taskbarHeight.toFloat()
+ private val maxPersistentTaskbarHeight =
+ context.persistentTaskbarDeviceProfile.taskbarHeight.toFloat()
+ var backgroundProgress =
+ if (DisplayController.isTransientTaskbar(context)) {
+ PINNING_TRANSIENT
+ } else {
+ PINNING_PERSISTENT
+ }
+
+ var isAnimatingPinning = false
+
val paint = Paint()
val lastDrawnTransientRect = RectF()
var backgroundHeight = context.deviceProfile.taskbarHeight.toFloat()
var translationYForSwipe = 0f
var translationYForStash = 0f
- private var maxBackgroundHeight = context.deviceProfile.taskbarHeight.toFloat()
private val transientBackgroundBounds = context.transientTaskbarBounds
- private val isTransientTaskbar = DisplayController.isTransientTaskbar(context)
-
private val shadowAlpha: Float
private var shadowBlur = 0f
private var keyShadowDistance = 0f
@@ -75,13 +88,6 @@
paint.flags = Paint.ANTI_ALIAS_FLAG
paint.style = Paint.Style.FILL
- if (isTransientTaskbar) {
- val res = context.resources
- bottomMargin = res.getDimensionPixelSize(R.dimen.transient_taskbar_bottom_margin)
- shadowBlur = res.getDimension(R.dimen.transient_taskbar_shadow_blur)
- keyShadowDistance = res.getDimension(R.dimen.transient_taskbar_key_shadow_distance)
- }
-
shadowAlpha =
if (Utilities.isDarkTheme(context)) DARK_THEME_SHADOW_ALPHA
else LIGHT_THEME_SHADOW_ALPHA
@@ -90,10 +96,11 @@
}
fun updateStashedHandleWidth(dp: DeviceProfile, res: Resources) {
- stashedHandleWidth = res.getDimensionPixelSize(
+ stashedHandleWidth =
+ res.getDimensionPixelSize(
if (TaskbarManager.isPhoneMode(dp)) R.dimen.taskbar_stashed_small_screen
else R.dimen.taskbar_stashed_handle_width
- )
+ )
}
/**
@@ -102,7 +109,7 @@
* @param cornerRoundness 0 has no round corner, 1 has complete round corner.
*/
fun setCornerRoundness(cornerRoundness: Float) {
- if (isTransientTaskbar && !transientBackgroundBounds.isEmpty) {
+ if (DisplayController.isTransientTaskbar(context) && !transientBackgroundBounds.isEmpty) {
return
}
@@ -126,63 +133,123 @@
/** Draws the background with the given paint and height, on the provided canvas. */
fun draw(canvas: Canvas) {
+ if (isInSetup) return
+ val isTransientTaskbar = backgroundProgress == 0f
canvas.save()
- if (!isTransientTaskbar || transientBackgroundBounds.isEmpty) {
- canvas.translate(0f, canvas.height - backgroundHeight - bottomMargin)
- // Draw the background behind taskbar content.
- canvas.drawRect(0f, 0f, canvas.width.toFloat(), backgroundHeight, paint)
-
- // Draw the inverted rounded corners above the taskbar.
- canvas.translate(0f, -leftCornerRadius)
- canvas.drawPath(invertedLeftCornerPath, paint)
- canvas.translate(0f, leftCornerRadius)
- canvas.translate(canvas.width - rightCornerRadius, -rightCornerRadius)
- canvas.drawPath(invertedRightCornerPath, paint)
- } else if (!isInSetup) {
- // backgroundHeight is a value from [0...maxBackgroundHeight], so we can use it as a
- // proxy to figure out the animation progress of the stash/unstash animation.
- val progress = backgroundHeight / maxBackgroundHeight
-
- // At progress 0, we draw the background as the stashed handle.
- // At progress 1, we draw the background as the full taskbar.
- val newBackgroundHeight =
- mapRange(progress, stashedHandleHeight.toFloat(), maxBackgroundHeight)
- val fullWidth = transientBackgroundBounds.width()
- val newWidth = mapRange(progress, stashedHandleWidth.toFloat(), fullWidth.toFloat())
- val halfWidthDelta = (fullWidth - newWidth) / 2f
- val radius = newBackgroundHeight / 2f
- val bottomMarginProgress = bottomMargin * ((1f - progress) / 2f)
-
- // Aligns the bottom with the bottom of the stashed handle.
- val bottom =
- canvas.height - bottomMargin +
- bottomMarginProgress +
- translationYForSwipe +
- translationYForStash +
- -mapRange(1f - progress, 0f, stashedHandleHeight / 2f)
-
- // Draw shadow.
- val newShadowAlpha =
- mapToRange(paint.alpha.toFloat(), 0f, 255f, 0f, shadowAlpha, Interpolators.LINEAR)
- paint.setShadowLayer(
- shadowBlur,
- 0f,
- keyShadowDistance,
- setColorAlphaBound(Color.BLACK, Math.round(newShadowAlpha))
- )
-
- lastDrawnTransientRect.set(
- transientBackgroundBounds.left + halfWidthDelta,
- bottom - newBackgroundHeight,
- transientBackgroundBounds.right - halfWidthDelta,
- bottom
- )
- val horizontalInset = fullWidth * widthInsetPercentage
- lastDrawnTransientRect.inset(horizontalInset, 0f)
-
- canvas.drawRoundRect(lastDrawnTransientRect, radius, radius, paint)
+ if (!isTransientTaskbar || transientBackgroundBounds.isEmpty || isAnimatingPinning) {
+ drawPersistentBackground(canvas)
}
canvas.restore()
+ canvas.save()
+ if (isAnimatingPinning || isTransientTaskbar) {
+ drawTransientBackground(canvas)
+ }
+ canvas.restore()
+ }
+
+ private fun drawPersistentBackground(canvas: Canvas) {
+ if (isAnimatingPinning) {
+ val persistentTaskbarHeight = maxPersistentTaskbarHeight * backgroundProgress
+ canvas.translate(0f, canvas.height - persistentTaskbarHeight)
+ // Draw the background behind taskbar content.
+ canvas.drawRect(0f, 0f, canvas.width.toFloat(), persistentTaskbarHeight, paint)
+ } else {
+ val persistentTaskbarHeight = min(maxPersistentTaskbarHeight, backgroundHeight)
+ canvas.translate(0f, canvas.height - persistentTaskbarHeight)
+ // Draw the background behind taskbar content.
+ canvas.drawRect(0f, 0f, canvas.width.toFloat(), persistentTaskbarHeight, paint)
+ }
+
+ // Draw the inverted rounded corners above the taskbar.
+ canvas.translate(0f, -leftCornerRadius)
+ canvas.drawPath(invertedLeftCornerPath, paint)
+ canvas.translate(0f, leftCornerRadius)
+ canvas.translate(canvas.width - rightCornerRadius, -rightCornerRadius)
+ canvas.drawPath(invertedRightCornerPath, paint)
+ }
+
+ private fun drawTransientBackground(canvas: Canvas) {
+ val res = context.resources
+ val transientTaskbarHeight = maxTransientTaskbarHeight * (1f - backgroundProgress)
+ val heightProgressWhileAnimating =
+ if (isAnimatingPinning) transientTaskbarHeight else backgroundHeight
+
+ var progress = heightProgressWhileAnimating / maxTransientTaskbarHeight
+ progress = Math.round(progress * 100f) / 100f
+ if (isAnimatingPinning) {
+ var scale = transientTaskbarHeight / maxTransientTaskbarHeight
+ scale = Math.round(scale * 100f) / 100f
+ bottomMargin =
+ mapRange(
+ scale,
+ 0f,
+ res.getDimensionPixelSize(R.dimen.transient_taskbar_bottom_margin).toFloat()
+ )
+ .toInt()
+ shadowBlur =
+ mapRange(scale, 0f, res.getDimension(R.dimen.transient_taskbar_shadow_blur))
+ keyShadowDistance =
+ mapRange(scale, 0f, res.getDimension(R.dimen.transient_taskbar_key_shadow_distance))
+ } else {
+ bottomMargin = res.getDimensionPixelSize(R.dimen.transient_taskbar_bottom_margin)
+ shadowBlur = res.getDimension(R.dimen.transient_taskbar_shadow_blur)
+ keyShadowDistance = res.getDimension(R.dimen.transient_taskbar_key_shadow_distance)
+ }
+
+ // At progress 0, we draw the background as the stashed handle.
+ // At progress 1, we draw the background as the full taskbar.
+ // Min height capped to max persistent taskbar height for animation
+ val backgroundHeightWhileAnimating =
+ if (isAnimatingPinning) maxPersistentTaskbarHeight else stashedHandleHeight.toFloat()
+ val newBackgroundHeight =
+ mapRange(progress, backgroundHeightWhileAnimating, maxTransientTaskbarHeight)
+ val fullWidth = transientBackgroundBounds.width()
+
+ // .9f is here to restrict min width of the background while animating, so transient
+ // background keeps it pill shape until animation end.
+ val animationWidth =
+ if (DisplayController.isTransientTaskbar(context)) fullWidth.toFloat() * .9f
+ else fullWidth.toFloat()
+ val backgroundWidthWhileAnimating =
+ if (isAnimatingPinning) animationWidth else stashedHandleWidth.toFloat()
+
+ val newWidth = mapRange(progress, backgroundWidthWhileAnimating, fullWidth.toFloat())
+ val halfWidthDelta = (fullWidth - newWidth) / 2f
+ val radius = newBackgroundHeight / 2f
+ val bottomMarginProgress = bottomMargin * ((1f - progress) / 2f)
+
+ // Aligns the bottom with the bottom of the stashed handle.
+ val bottom =
+ canvas.height - bottomMargin +
+ bottomMarginProgress +
+ translationYForSwipe +
+ translationYForStash +
+ -mapRange(
+ 1f - progress,
+ 0f,
+ if (isAnimatingPinning) 0f else stashedHandleHeight / 2f
+ )
+
+ // Draw shadow.
+ val newShadowAlpha =
+ mapToRange(paint.alpha.toFloat(), 0f, 255f, 0f, shadowAlpha, Interpolators.LINEAR)
+ paint.setShadowLayer(
+ shadowBlur,
+ 0f,
+ keyShadowDistance,
+ setColorAlphaBound(Color.BLACK, Math.round(newShadowAlpha))
+ )
+
+ lastDrawnTransientRect.set(
+ transientBackgroundBounds.left + halfWidthDelta,
+ bottom - newBackgroundHeight,
+ transientBackgroundBounds.right - halfWidthDelta,
+ bottom
+ )
+ val horizontalInset = fullWidth * widthInsetPercentage
+ lastDrawnTransientRect.inset(horizontalInset, 0f)
+
+ canvas.drawRoundRect(lastDrawnTransientRect, radius, radius, paint)
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index d82f501..f9ddc3d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -62,7 +62,7 @@
public final TaskbarOverlayController taskbarOverlayController;
public final TaskbarEduTooltipController taskbarEduTooltipController;
public final KeyboardQuickSwitchController keyboardQuickSwitchController;
- public final TaskbarDividerPopupController taskbarPinningController;
+ public final TaskbarPinningController taskbarPinningController;
public final Optional<BubbleControllers> bubbleControllers;
@Nullable private LoggableTaskbarController[] mControllersToLog = null;
@@ -110,7 +110,7 @@
TaskbarRecentAppsController taskbarRecentAppsController,
TaskbarEduTooltipController taskbarEduTooltipController,
KeyboardQuickSwitchController keyboardQuickSwitchController,
- TaskbarDividerPopupController taskbarPinningController,
+ TaskbarPinningController taskbarPinningController,
Optional<BubbleControllers> bubbleControllers) {
this.taskbarActivityContext = taskbarActivityContext;
this.taskbarDragController = taskbarDragController;
@@ -171,7 +171,7 @@
taskbarTranslationController.init(this);
taskbarEduTooltipController.init(this);
keyboardQuickSwitchController.init(this);
- taskbarPinningController.init(this);
+ taskbarPinningController.init(this, mSharedState);
bubbleControllers.ifPresent(controllers -> controllers.init(this));
mControllersToLog = new LoggableTaskbarController[] {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupController.kt
deleted file mode 100644
index a2c61ce..0000000
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupController.kt
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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
-
-import android.view.View
-import com.android.launcher3.LauncherPrefs
-import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING
-import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_DIVIDER_MENU_CLOSE
-import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_DIVIDER_MENU_OPEN
-import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_PINNED
-import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_UNPINNED
-import com.android.launcher3.taskbar.TaskbarDividerPopupView.Companion.createAndPopulate
-import java.io.PrintWriter
-
-/** Controls taskbar pinning through a popup view. */
-class TaskbarDividerPopupController(private val context: TaskbarActivityContext) :
- TaskbarControllers.LoggableTaskbarController {
-
- private lateinit var controllers: TaskbarControllers
- private val launcherPrefs = LauncherPrefs.get(context)
- private val statsLogManager = context.statsLogManager
-
- fun init(taskbarControllers: TaskbarControllers) {
- controllers = taskbarControllers
- }
-
- fun showPinningView(view: View) {
- context.isTaskbarWindowFullscreen = true
-
- view.post {
- val popupView = createAndPopulate(view, context)
- popupView.requestFocus()
-
- popupView.onCloseCallback =
- callback@{ didPreferenceChange ->
- statsLogManager.logger().log(LAUNCHER_TASKBAR_DIVIDER_MENU_CLOSE)
- context.dragLayer.post { context.onPopupVisibilityChanged(false) }
-
- if (!didPreferenceChange) {
- return@callback
- }
-
- if (launcherPrefs.get(TASKBAR_PINNING)) {
- animateTransientToPersistentTaskbar()
- statsLogManager.logger().log(LAUNCHER_TASKBAR_PINNED)
- } else {
- animatePersistentToTransientTaskbar()
- statsLogManager.logger().log(LAUNCHER_TASKBAR_UNPINNED)
- }
- }
- popupView.changePreference = {
- launcherPrefs.put(TASKBAR_PINNING, !launcherPrefs.get(TASKBAR_PINNING))
- }
- context.onPopupVisibilityChanged(true)
- popupView.show()
- statsLogManager.logger().log(LAUNCHER_TASKBAR_DIVIDER_MENU_OPEN)
- }
- }
-
- // TODO(b/265436799): provide animation/transition from transient taskbar to persistent one
- private fun animateTransientToPersistentTaskbar() {}
-
- // TODO(b/265436799): provide animation/transition from persistent taskbar to transient one
- private fun animatePersistentToTransientTaskbar() {}
-
- override fun dumpLogs(prefix: String, pw: PrintWriter) {
- pw.println(prefix + "TaskbarPinningController:")
- }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
index b200858..d13b53f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
@@ -75,12 +75,6 @@
/** Callback invoked when the pinning popup view is closing. */
var onCloseCallback: (preferenceChanged: Boolean) -> Unit = {}
- /**
- * Callback invoked when the user preference changes in popup view. Preference change will be
- * based upon current value stored in [LauncherPrefs] for `TASKBAR_PINNING`
- */
- var changePreference: () -> Unit = {}
-
init {
// This synchronizes the arrow and menu to open at the same time
mOpenChildFadeStartDelay = mOpenFadeStartDelay
@@ -185,8 +179,6 @@
private fun onClickAlwaysShowTaskbarSwitchOption() {
didPreferenceChange = true
- changePreference()
- changePreference = {}
// Allow switch animation to finish and then close the popup.
postDelayed(DIVIDER_POPUP_CLOSING_DELAY) {
if (isOpen) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index e521154..1eb8d53 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -73,6 +73,8 @@
private SafeCloseable mViewCaptureCloseable;
private float mTaskbarBackgroundOffset;
+ private float mTaskbarBackgroundProgress;
+ private boolean mIsAnimatingTaskbarPinning = false;
private final MultiPropertyFactory<TaskbarDragLayer> mTaskbarBackgroundAlpha;
@@ -162,10 +164,19 @@
float backgroundHeight = mControllerCallbacks.getTaskbarBackgroundHeight()
* (1f - mTaskbarBackgroundOffset);
mBackgroundRenderer.setBackgroundHeight(backgroundHeight);
+ mBackgroundRenderer.setBackgroundProgress(mTaskbarBackgroundProgress);
mBackgroundRenderer.draw(canvas);
super.dispatchDraw(canvas);
}
+ /**
+ * Sets animation boolean when taskbar pinning animation starts or stops.
+ */
+ public void setAnimatingTaskbarPinning(boolean animatingTaskbarPinning) {
+ mIsAnimatingTaskbarPinning = animatingTaskbarPinning;
+ mBackgroundRenderer.setAnimatingPinning(mIsAnimatingTaskbarPinning);
+ }
+
protected MultiProperty getBackgroundRendererAlpha() {
return mTaskbarBackgroundAlpha.get(INDEX_ALL_OTHER_STATES);
}
@@ -175,6 +186,15 @@
}
/**
+ * Sets the value for taskbar background switching between persistent and transient backgrounds.
+ * @param progress 0 is transient background, 1 is persistent background.
+ */
+ protected void setTaskbarBackgroundProgress(float progress) {
+ mTaskbarBackgroundProgress = progress;
+ invalidate();
+ }
+
+ /**
* Sets the translation of the background color behind all the Taskbar contents.
* @param offset 0 is fully onscreen, 1 is fully offscreen.
*/
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index 867b062..73e32ab 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -15,6 +15,9 @@
*/
package com.android.launcher3.taskbar;
+import static com.android.launcher3.taskbar.TaskbarPinningController.PINNING_PERSISTENT;
+import static com.android.launcher3.taskbar.TaskbarPinningController.PINNING_TRANSIENT;
+
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
@@ -24,6 +27,7 @@
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.util.DimensionUtils;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
import com.android.launcher3.util.TouchController;
@@ -58,6 +62,9 @@
// changes the inset visibility.
private final AnimatedFloat mTaskbarAlpha = new AnimatedFloat(this::updateTaskbarAlpha);
+ private final AnimatedFloat mTaskbarBackgroundProgress = new AnimatedFloat(
+ this::updateTaskbarBackgroundProgress);
+
// Initialized in init.
private TaskbarControllers mControllers;
private TaskbarStashViaTouchController mTaskbarStashViaTouchController;
@@ -83,6 +90,10 @@
mOnBackgroundNavButtonColorIntensity = mControllers.navbarButtonsViewController
.getOnTaskbarBackgroundNavButtonColorOverride();
+ mTaskbarBackgroundProgress.updateValue(DisplayController.isTransientTaskbar(mActivity)
+ ? PINNING_TRANSIENT
+ : PINNING_PERSISTENT);
+
mBgTaskbar.value = 1;
mKeyguardBgTaskbar.value = 1;
mNotificationShadeBgTaskbar.value = 1;
@@ -138,6 +149,11 @@
return mBgOffset;
}
+ // AnimatedFloat is for animating between pinned and transient taskbar
+ public AnimatedFloat getTaskbarBackgroundProgress() {
+ return mTaskbarBackgroundProgress;
+ }
+
public AnimatedFloat getTaskbarAlpha() {
return mTaskbarAlpha;
}
@@ -180,10 +196,13 @@
private void updateBackgroundOffset() {
mTaskbarDragLayer.setTaskbarBackgroundOffset(mBgOffset.value);
-
updateOnBackgroundNavButtonColorIntensity();
}
+ private void updateTaskbarBackgroundProgress() {
+ mTaskbarDragLayer.setTaskbarBackgroundProgress(mTaskbarBackgroundProgress.value);
+ }
+
private void updateTaskbarAlpha() {
mTaskbarDragLayer.setAlpha(mTaskbarAlpha.value);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 56ba460..267b15c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -206,12 +206,14 @@
updateStateForFlag(FLAG_LAUNCHER_IN_STATE_TRANSITION, false);
// TODO(b/279514548) Cleans up bad state that can occur when user interacts with
// taskbar on top of transparent activity.
- if (finalState == LauncherState.NORMAL && mLauncher.hasBeenResumed()) {
+ if (!FeatureFlags.enableHomeTransitionListener()
+ && finalState == LauncherState.NORMAL
+ && mLauncher.hasBeenResumed()) {
updateStateForFlag(FLAG_VISIBLE, true);
}
applyState();
boolean disallowLongClick =
- FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()
+ FeatureFlags.enableSplitContextually()
? mLauncher.isSplitSelectionEnabled()
: finalState == LauncherState.OVERVIEW_SPLIT_SELECT;
com.android.launcher3.taskbar.Utilities.setOverviewDragState(
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 6dfd243..b500c3e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -18,12 +18,11 @@
import static android.content.Context.RECEIVER_NOT_EXPORTED;
import static android.content.pm.PackageManager.FEATURE_PC;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
-import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING;
-import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING_KEY;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NO_RECREATION;
+import static com.android.launcher3.config.FeatureFlags.enableTaskbarNoRecreate;
import static com.android.launcher3.util.DisplayController.TASKBAR_NOT_DESTROYED_TAG;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.FlagDebugUtils.formatFlagChange;
@@ -37,7 +36,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.hardware.display.DisplayManager;
@@ -59,12 +57,12 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile.OnIDPChangeListener;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.taskbar.unfold.NonDestroyableScopedUnfoldTransitionProgressProvider;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.SettingsCache;
import com.android.launcher3.util.SimpleBroadcastReceiver;
import com.android.quickstep.RecentsActivity;
@@ -147,13 +145,6 @@
private final SimpleBroadcastReceiver mTaskbarBroadcastReceiver =
new SimpleBroadcastReceiver(this::showTaskbarFromBroadcast);
- private final SharedPreferences.OnSharedPreferenceChangeListener
- mTaskbarPinningPreferenceChangeListener = (sharedPreferences, key) -> {
- if (TASKBAR_PINNING_KEY.equals(key)) {
- recreateTaskbar();
- }
- };
-
private final ActivityLifecycleCallbacksAdapter mLifecycleCallbacks =
new ActivityLifecycleCallbacksAdapter() {
@Override
@@ -209,8 +200,9 @@
public TaskbarManager(TouchInteractionService service) {
Display display =
service.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
- mContext = service.createWindowContext(display, TYPE_NAVIGATION_BAR_PANEL, null);
- if (ENABLE_TASKBAR_NO_RECREATION.get()) {
+ mContext = service.createWindowContext(display,
+ FLAG_HIDE_NAVBAR_WINDOW ? TYPE_NAVIGATION_BAR : TYPE_NAVIGATION_BAR_PANEL, null);
+ if (enableTaskbarNoRecreate()) {
mWindowManager = mContext.getSystemService(WindowManager.class);
mTaskbarRootLayout = new FrameLayout(mContext) {
@Override
@@ -305,10 +297,8 @@
private void destroyExistingTaskbar() {
debugWhyTaskbarNotDestroyed("destroyExistingTaskbar: " + mTaskbarActivityContext);
if (mTaskbarActivityContext != null) {
- LauncherPrefs.get(mContext).removeListener(mTaskbarPinningPreferenceChangeListener,
- TASKBAR_PINNING);
mTaskbarActivityContext.onDestroy();
- if (!FLAG_HIDE_NAVBAR_WINDOW || ENABLE_TASKBAR_NO_RECREATION.get()) {
+ if (!FLAG_HIDE_NAVBAR_WINDOW || enableTaskbarNoRecreate()) {
mTaskbarActivityContext = null;
}
}
@@ -448,12 +438,14 @@
return;
}
- if (ENABLE_TASKBAR_NO_RECREATION.get() || mTaskbarActivityContext == null) {
+ if (enableTaskbarNoRecreate() || mTaskbarActivityContext == null) {
mTaskbarActivityContext = new TaskbarActivityContext(mContext, dp,
mNavButtonController, mUnfoldProgressProvider);
} else {
mTaskbarActivityContext.updateDeviceProfile(dp);
}
+ mSharedState.startTaskbarVariantIsTransient =
+ DisplayController.isTransientTaskbar(mTaskbarActivityContext);
mTaskbarActivityContext.init(mSharedState);
if (mActivity != null) {
@@ -461,16 +453,12 @@
createTaskbarUIControllerForActivity(mActivity));
}
- if (ENABLE_TASKBAR_NO_RECREATION.get()) {
+ if (enableTaskbarNoRecreate()) {
addTaskbarRootViewToWindow();
mTaskbarRootLayout.removeAllViews();
mTaskbarRootLayout.addView(mTaskbarActivityContext.getDragLayer());
mTaskbarActivityContext.notifyUpdateLayoutParams();
}
-
- // We to wait until user unlocks the device to attach listener.
- LauncherPrefs.get(mContext).addListener(mTaskbarPinningPreferenceChangeListener,
- TASKBAR_PINNING);
} finally {
Trace.endSection();
}
@@ -603,8 +591,7 @@
}
private void addTaskbarRootViewToWindow() {
- if (ENABLE_TASKBAR_NO_RECREATION.get() && !mAddedWindow
- && mTaskbarActivityContext != null) {
+ if (enableTaskbarNoRecreate() && !mAddedWindow && mTaskbarActivityContext != null) {
mWindowManager.addView(mTaskbarRootLayout,
mTaskbarActivityContext.getWindowLayoutParams());
mAddedWindow = true;
@@ -612,7 +599,7 @@
}
private void removeTaskbarRootViewFromWindow() {
- if (ENABLE_TASKBAR_NO_RECREATION.get() && mAddedWindow) {
+ if (enableTaskbarNoRecreate() && mAddedWindow) {
mWindowManager.removeViewImmediate(mTaskbarRootLayout);
mAddedWindow = false;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPinningController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarPinningController.kt
new file mode 100644
index 0000000..d1bed3e
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPinningController.kt
@@ -0,0 +1,112 @@
+/*
+ * 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
+
+import android.animation.AnimatorSet
+import android.view.View
+import androidx.core.animation.doOnEnd
+import com.android.launcher3.LauncherPrefs
+import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING
+import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_DIVIDER_MENU_CLOSE
+import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_DIVIDER_MENU_OPEN
+import com.android.launcher3.taskbar.TaskbarDividerPopupView.Companion.createAndPopulate
+import java.io.PrintWriter
+
+/** Controls taskbar pinning through a popup view. */
+class TaskbarPinningController(private val context: TaskbarActivityContext) :
+ TaskbarControllers.LoggableTaskbarController {
+
+ private lateinit var controllers: TaskbarControllers
+ private lateinit var taskbarSharedState: TaskbarSharedState
+ private val launcherPrefs = LauncherPrefs.get(context)
+ private val statsLogManager = context.statsLogManager
+ private var isAnimatingTaskbarPinning = false
+
+ fun init(taskbarControllers: TaskbarControllers, sharedState: TaskbarSharedState) {
+ controllers = taskbarControllers
+ taskbarSharedState = sharedState
+ }
+
+ fun showPinningView(view: View) {
+ context.isTaskbarWindowFullscreen = true
+
+ view.post {
+ val popupView = createAndPopulate(view, context)
+ popupView.requestFocus()
+
+ popupView.onCloseCallback =
+ callback@{ didPreferenceChange ->
+ statsLogManager.logger().log(LAUNCHER_TASKBAR_DIVIDER_MENU_CLOSE)
+ context.dragLayer.post { context.onPopupVisibilityChanged(false) }
+
+ if (!didPreferenceChange) {
+ return@callback
+ }
+ val animateToValue =
+ if (!launcherPrefs.get(TASKBAR_PINNING)) {
+ PINNING_PERSISTENT
+ } else {
+ PINNING_TRANSIENT
+ }
+ taskbarSharedState.taskbarWasPinned = animateToValue == PINNING_TRANSIENT
+ animateTaskbarPinning(animateToValue)
+ }
+ context.onPopupVisibilityChanged(true)
+ popupView.show()
+ statsLogManager.logger().log(LAUNCHER_TASKBAR_DIVIDER_MENU_OPEN)
+ }
+ }
+
+ private fun animateTaskbarPinning(animateToValue: Float) {
+ val animatorSet = AnimatorSet()
+ val taskbarViewController = controllers.taskbarViewController
+ val dragLayerController = controllers.taskbarDragLayerController
+
+ animatorSet.playTogether(
+ dragLayerController.taskbarBackgroundProgress.animateToValue(animateToValue),
+ taskbarViewController.taskbarIconTranslationYForPinning.animateToValue(animateToValue),
+ taskbarViewController.taskbarIconScaleForPinning.animateToValue(animateToValue),
+ taskbarViewController.taskbarIconTranslationXForPinning.animateToValue(animateToValue)
+ )
+
+ animatorSet.doOnEnd { recreateTaskbarAndUpdatePinningValue() }
+ animatorSet.duration = PINNING_ANIMATION_DURATION
+ updateIsAnimatingTaskbarPinningAndNotifyTaskbarDragLayer(true)
+ animatorSet.start()
+ }
+
+ private fun updateIsAnimatingTaskbarPinningAndNotifyTaskbarDragLayer(isAnimating: Boolean) {
+ isAnimatingTaskbarPinning = isAnimating
+ context.dragLayer.setAnimatingTaskbarPinning(isAnimating)
+ }
+
+ private fun recreateTaskbarAndUpdatePinningValue() {
+ updateIsAnimatingTaskbarPinningAndNotifyTaskbarDragLayer(false)
+ launcherPrefs.put(TASKBAR_PINNING, !launcherPrefs.get(TASKBAR_PINNING))
+ }
+
+ override fun dumpLogs(prefix: String, pw: PrintWriter) {
+ pw.println(prefix + "TaskbarPinningController:")
+ pw.println("$prefix\tisAnimatingTaskbarPinning=$isAnimatingTaskbarPinning")
+ pw.println("$prefix\tTASKBAR_PINNING shared pref =" + launcherPrefs.get(TASKBAR_PINNING))
+ }
+
+ companion object {
+ const val PINNING_PERSISTENT = 1f
+ const val PINNING_TRANSIENT = 0f
+ const val PINNING_ANIMATION_DURATION = 500L
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
index abbd18b..176a8c5 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
@@ -71,4 +71,11 @@
new InsetsFrameProvider(mInsetsOwner, INDEX_RIGHT, systemGestures())
.setSource(SOURCE_DISPLAY)
};
+
+ // Allows us to shift translation logic when doing taskbar pinning animation.
+ public Boolean startTaskbarVariantIsTransient = true;
+
+ // To track if taskbar was pinned using taskbar pinning feature at the time of recreate,
+ // so we can unstash transient taskbar when we un-pinning taskbar.
+ public Boolean taskbarWasPinned = false;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index e67a6d5..5be74be 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -22,7 +22,7 @@
import static com.android.app.animation.Interpolators.FINAL_FRAME;
import static com.android.app.animation.Interpolators.INSTANT;
import static com.android.app.animation.Interpolators.LINEAR;
-import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING_KEY;
+import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_PINNING;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_HIDE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_SHOW;
@@ -337,7 +337,8 @@
&& mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF);
boolean isInSetup = !mActivity.isUserSetupComplete() || setupUIVisible;
updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp);
- updateStateForFlag(FLAG_STASHED_IN_APP_AUTO, isTransientTaskbar);
+ updateStateForFlag(FLAG_STASHED_IN_APP_AUTO,
+ isTransientTaskbar && !mTaskbarSharedState.taskbarWasPinned);
updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, isInSetup);
updateStateForFlag(FLAG_IN_SETUP, isInSetup);
updateStateForFlag(FLAG_STASHED_SMALL_SCREEN, isPhoneMode()
@@ -346,6 +347,9 @@
// us that we're paused until a bit later. This avoids flickering upon recreating taskbar.
updateStateForFlag(FLAG_IN_APP, true);
applyState(/* duration = */ 0);
+ if (mTaskbarSharedState.taskbarWasPinned) {
+ tryStartTaskbarTimeout();
+ }
notifyStashChange(/* visible */ false, /* stashed */ isStashedInApp());
}
@@ -361,7 +365,7 @@
* Returns whether the user can manually stash the taskbar based on the current device state.
*/
protected boolean supportsManualStashing() {
- if (ENABLE_TASKBAR_PINNING.get() && mPrefs.getBoolean(TASKBAR_PINNING_KEY, false)) {
+ if (ENABLE_TASKBAR_PINNING.get() && LauncherPrefs.get(mActivity).get(TASKBAR_PINNING)) {
return false;
}
return supportsVisualStashing()
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 5f58de5..a7461b7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -20,7 +20,6 @@
import static com.android.launcher3.Flags.enableCursorHoverStates;
import static com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_PINNING;
import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
import android.content.Context;
@@ -98,8 +97,6 @@
private final float mTransientTaskbarMinWidth;
- private final float mTaskbarAllAppsButtonTranslationXOffset;
-
private boolean mShouldTryStartAlign;
public TaskbarView(@NonNull Context context) {
@@ -125,13 +122,16 @@
&& !TaskbarManager.isPhoneMode(mActivityContext.getDeviceProfile());
mIsRtl = Utilities.isRtl(resources);
mTransientTaskbarMinWidth = resources.getDimension(R.dimen.transient_taskbar_min_width);
- mTaskbarAllAppsButtonTranslationXOffset =
- resources.getDimension(getAllAppsButtonTranslationXOffset(isTransientTaskbar));
+
onDeviceProfileChanged(mActivityContext.getDeviceProfile());
int actualMargin = resources.getDimensionPixelSize(R.dimen.taskbar_icon_spacing);
int actualIconSize = mActivityContext.getDeviceProfile().taskbarIconSize;
+ if (FeatureFlags.ENABLE_TASKBAR_PINNING.get()) {
+ DeviceProfile deviceProfile = mActivityContext.getTransientTaskbarDeviceProfile();
+ actualIconSize = deviceProfile.taskbarIconSize;
+ }
int visualIconSize = (int) (actualIconSize * ICON_VISIBLE_AREA_FACTOR);
mIconTouchSize = Math.max(actualIconSize,
@@ -139,8 +139,11 @@
// We layout the icons to be of mIconTouchSize in width and height
mItemMarginLeftRight = actualMargin - (mIconTouchSize - visualIconSize) / 2;
- mItemPadding = (mIconTouchSize - actualIconSize) / 2;
+ // We always layout taskbar as a transient taskbar when we have taskbar pinning feature on,
+ // then we scale and translate the icons to match persistent taskbar designs, so we use
+ // taskbar icon size from current device profile to calculate correct item padding.
+ mItemPadding = (mIconTouchSize - mActivityContext.getDeviceProfile().taskbarIconSize) / 2;
mFolderLeaveBehindColor = Themes.getAttrColor(mActivityContext,
android.R.attr.textColorTertiary);
@@ -173,7 +176,8 @@
@DrawableRes
private int getAllAppsButton(boolean isTransientTaskbar) {
- boolean shouldSelectTransientIcon = (isTransientTaskbar || ENABLE_TASKBAR_PINNING.get())
+ boolean shouldSelectTransientIcon =
+ (isTransientTaskbar || FeatureFlags.ENABLE_TASKBAR_PINNING.get())
&& !mActivityContext.isThreeButtonNav();
if (ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) {
return shouldSelectTransientIcon
@@ -187,7 +191,7 @@
}
@DimenRes
- private int getAllAppsButtonTranslationXOffset(boolean isTransientTaskbar) {
+ public int getAllAppsButtonTranslationXOffset(boolean isTransientTaskbar) {
if (isTransientTaskbar) {
return R.dimen.transient_taskbar_all_apps_button_translation_x_offset;
} else {
@@ -370,8 +374,6 @@
}
if (mAllAppsButton != null) {
- mAllAppsButton.setTranslationXForTaskbarAllAppsIcon(getChildCount() > 0
- ? mTaskbarAllAppsButtonTranslationXOffset : 0f);
addView(mAllAppsButton, mIsRtl ? getChildCount() : 0);
// if only all apps button present, don't include divider view.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 8a8c3bc..0d06088 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -21,14 +21,19 @@
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
+import static com.android.launcher3.Utilities.mapRange;
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.config.FeatureFlags.ENABLE_TASKBAR_PINNING;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP;
+import static com.android.launcher3.taskbar.TaskbarPinningController.PINNING_PERSISTENT;
+import static com.android.launcher3.taskbar.TaskbarPinningController.PINNING_TRANSIENT;
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;
+import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_TASKBAR_PINNING_ANIM;
import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_TASKBAR_REVEAL_ANIM;
import android.animation.Animator;
@@ -61,11 +66,13 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.ThemedIconDrawable;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LauncherBindableItemsContainer;
import com.android.launcher3.util.MultiPropertyFactory;
import com.android.launcher3.util.MultiTranslateDelegate;
import com.android.launcher3.util.MultiValueAlpha;
+import com.android.launcher3.views.IconButtonView;
import java.io.PrintWriter;
import java.util.function.Predicate;
@@ -98,12 +105,27 @@
this::updateTranslationY);
private final AnimatedFloat mTaskbarIconTranslationYForStash = new AnimatedFloat(
this::updateTranslationY);
+
+ private final AnimatedFloat mTaskbarIconScaleForPinning = new AnimatedFloat(
+ this::updateTaskbarIconsScale);
+
+ private final AnimatedFloat mTaskbarIconTranslationXForPinning = new AnimatedFloat(
+ this::updateTaskbarIconTranslationXForPinning);
+
+ private final AnimatedFloat mTaskbarIconTranslationYForPinning = new AnimatedFloat(
+ this::updateTranslationY);
+
+ private final View.OnLayoutChangeListener mTaskbarViewLayoutChangeListener =
+ (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom)
+ -> updateTaskbarIconTranslationXForPinning();
+
+
private AnimatedFloat mTaskbarNavButtonTranslationY;
private AnimatedFloat mTaskbarNavButtonTranslationYForInAppDisplay;
private float mTaskbarIconTranslationYForSwipe;
private float mTaskbarIconTranslationYForSpringOnStash;
- private final int mTaskbarBottomMargin;
+ private int mTaskbarBottomMargin;
private final int mStashedHandleHeight;
private final int mLauncherThemedIconsBackgroundColor;
private final int mTaskbarThemedIconsBackgroundColor;
@@ -131,8 +153,18 @@
private final boolean mIsRtl;
+ private final DeviceProfile mTransientTaskbarDp;
+ private final DeviceProfile mPersistentTaskbarDp;
+
+ private final int mTransientIconSize;
+ private final int mPersistentIconSize;
+
public TaskbarViewController(TaskbarActivityContext activity, TaskbarView taskbarView) {
mActivity = activity;
+ mTransientTaskbarDp = mActivity.getTransientTaskbarDeviceProfile();
+ mPersistentTaskbarDp = mActivity.getPersistentTaskbarDeviceProfile();
+ mTransientIconSize = mTransientTaskbarDp.taskbarIconSize;
+ mPersistentIconSize = mPersistentTaskbarDp.taskbarIconSize;
mTaskbarView = taskbarView;
mTaskbarIconAlpha = new MultiValueAlpha(mTaskbarView, NUM_ALPHA_CHANNELS);
mTaskbarIconAlpha.setUpdateVisibility(true);
@@ -162,6 +194,12 @@
: mActivity.getDeviceProfile().taskbarHeight;
mTaskbarIconScaleForStash.updateValue(1f);
+ float pinningValue = DisplayController.isTransientTaskbar(mActivity)
+ ? PINNING_TRANSIENT
+ : PINNING_PERSISTENT;
+ mTaskbarIconScaleForPinning.updateValue(pinningValue);
+ mTaskbarIconTranslationYForPinning.updateValue(pinningValue);
+ mTaskbarIconTranslationXForPinning.updateValue(pinningValue);
mModelCallbacks.init(controllers);
if (mActivity.isUserSetupComplete()) {
@@ -181,6 +219,9 @@
mTaskbarIconAlpha.get(ALPHA_INDEX_SMALL_SCREEN)
.animateToValue(isPhoneButtonNavMode(mActivity) ? 0 : 1).start();
}
+ if (ENABLE_TASKBAR_PINNING.get()) {
+ mTaskbarView.addOnLayoutChangeListener(mTaskbarViewLayoutChangeListener);
+ }
}
/**
@@ -191,6 +232,9 @@
}
public void onDestroy() {
+ if (ENABLE_TASKBAR_PINNING.get()) {
+ mTaskbarView.removeOnLayoutChangeListener(mTaskbarViewLayoutChangeListener);
+ }
LauncherAppState.getInstance(mActivity).getModel().removeCallbacks(mModelCallbacks);
mActivity.removeOnDeviceProfileChangeListener(mDeviceProfileChangeListener);
mModelCallbacks.unregisterListeners();
@@ -253,6 +297,18 @@
return mTaskbarIconTranslationYForStash;
}
+ public AnimatedFloat getTaskbarIconScaleForPinning() {
+ return mTaskbarIconScaleForPinning;
+ }
+
+ public AnimatedFloat getTaskbarIconTranslationXForPinning() {
+ return mTaskbarIconTranslationXForPinning;
+ }
+
+ public AnimatedFloat getTaskbarIconTranslationYForPinning() {
+ return mTaskbarIconTranslationYForPinning;
+ }
+
/**
* Applies scale properties for the entire TaskbarView (rather than individual icons).
*/
@@ -263,6 +319,65 @@
}
/**
+ * Applies scale properties for the taskbar icons
+ */
+ private void updateTaskbarIconsScale() {
+ float scale = mTaskbarIconScaleForPinning.value;
+ View[] iconViews = mTaskbarView.getIconViews();
+
+ float finalScale;
+ if (mControllers.getSharedState().startTaskbarVariantIsTransient) {
+ finalScale = mapRange(scale, 1f, ((float) mPersistentIconSize / mTransientIconSize));
+ } else {
+ finalScale = mapRange(scale, ((float) mTransientIconSize / mPersistentIconSize), 1f);
+ }
+
+ for (int iconIndex = 0; iconIndex < iconViews.length; iconIndex++) {
+ iconViews[iconIndex].setScaleX(finalScale);
+ iconViews[iconIndex].setScaleY(finalScale);
+ }
+ }
+
+ private void updateTaskbarIconTranslationXForPinning() {
+ View[] iconViews = mTaskbarView.getIconViews();
+ float scale = mTaskbarIconTranslationXForPinning.value;
+ float taskbarCenterX =
+ mTaskbarView.getLeft() + (mTaskbarView.getRight() - mTaskbarView.getLeft()) / 2.0f;
+
+ float finalMarginScale = mapRange(scale, 0f, mTransientIconSize - mPersistentIconSize);
+
+ float transientTaskbarAllAppsOffset = mActivity.getResources().getDimension(
+ mTaskbarView.getAllAppsButtonTranslationXOffset(true));
+ float persistentTaskbarAllAppsOffset = mActivity.getResources().getDimension(
+ mTaskbarView.getAllAppsButtonTranslationXOffset(false));
+
+ float allAppIconTranslateRange = mapRange(scale, transientTaskbarAllAppsOffset,
+ persistentTaskbarAllAppsOffset);
+
+ float halfIconCount = iconViews.length / 2.0f;
+ for (int iconIndex = 0; iconIndex < iconViews.length; iconIndex++) {
+ View iconView = iconViews[iconIndex];
+ MultiTranslateDelegate translateDelegate =
+ ((Reorderable) iconView).getTranslateDelegate();
+ float iconCenterX =
+ iconView.getLeft() + (iconView.getRight() - iconView.getLeft()) / 2.0f;
+ if (iconCenterX <= taskbarCenterX) {
+ translateDelegate.getTranslationX(INDEX_TASKBAR_PINNING_ANIM).setValue(
+ finalMarginScale * (halfIconCount - iconIndex));
+ } else {
+ translateDelegate.getTranslationX(INDEX_TASKBAR_PINNING_ANIM).setValue(
+ -finalMarginScale * (iconIndex - halfIconCount));
+ }
+
+ if (iconView.equals(mTaskbarView.getAllAppsButtonView()) && iconViews.length > 1) {
+ ((IconButtonView) iconView).setTranslationXForTaskbarAllAppsIcon(
+ allAppIconTranslateRange);
+ }
+ }
+ }
+
+
+ /**
* Sets the translation of the TaskbarView during the swipe up gesture.
*/
public void setTranslationYForSwipe(float transY) {
@@ -282,10 +397,41 @@
mTaskbarView.setTranslationY(mTaskbarIconTranslationYForHome.value
+ mTaskbarIconTranslationYForStash.value
+ mTaskbarIconTranslationYForSwipe
+ + getTaskbarIconTranslationYForPinningValue()
+ mTaskbarIconTranslationYForSpringOnStash);
}
/**
+ * Computes translation y for taskbar pinning.
+ */
+ private float getTaskbarIconTranslationYForPinningValue() {
+ if (mControllers.getSharedState() == null) return 0f;
+
+ float scale = mTaskbarIconTranslationYForPinning.value;
+ float taskbarIconTranslationYForPinningValue;
+
+ // transY is calculated here by adding/subtracting the taskbar bottom margin
+ // aligning the icon bound to be at bottom of current taskbar view and then
+ // finally placing the icon in the middle of new taskbar background height.
+ if (mControllers.getSharedState().startTaskbarVariantIsTransient) {
+ float transY =
+ mTransientTaskbarDp.taskbarBottomMargin + (mTransientTaskbarDp.taskbarHeight
+ - mTaskbarView.getIconLayoutBounds().bottom)
+ - (mPersistentTaskbarDp.taskbarHeight
+ - mTransientTaskbarDp.taskbarIconSize) / 2f;
+ taskbarIconTranslationYForPinningValue = mapRange(scale, 0f, transY);
+ } else {
+ float transY =
+ -mTransientTaskbarDp.taskbarBottomMargin + (mPersistentTaskbarDp.taskbarHeight
+ - mTaskbarView.getIconLayoutBounds().bottom)
+ - (mTransientTaskbarDp.taskbarHeight
+ - mTransientTaskbarDp.taskbarIconSize) / 2f;
+ taskbarIconTranslationYForPinningValue = mapRange(scale, transY, 0f);
+ }
+ return taskbarIconTranslationYForPinningValue;
+ }
+
+ /**
* Updates the Taskbar's themed icons background according to the progress between in-app/home.
*/
protected void updateIconsBackground() {
@@ -471,6 +617,8 @@
mOnControllerPreCreateCallback.run();
DeviceProfile taskbarDp = mActivity.getDeviceProfile();
Rect hotseatPadding = launcherDp.getHotseatLayoutPadding(mActivity);
+ boolean isTransientTaskbar = DisplayController.isTransientTaskbar(mActivity);
+
float scaleUp = ((float) launcherDp.iconSizePx) / taskbarDp.taskbarIconSize;
int borderSpacing = launcherDp.hotseatBorderSpace;
int hotseatCellSize = DeviceProfile.calculateCellWidth(
@@ -497,6 +645,10 @@
setter.addOnFrameListener(anim -> mActivity.setTaskbarWindowHeight(
anim.getAnimatedFraction() > 0 ? expandedHeight : collapsedHeight));
+ mTaskbarBottomMargin = isTransientTaskbar
+ ? mTransientTaskbarDp.taskbarBottomMargin
+ : mPersistentTaskbarDp.taskbarBottomMargin;
+
for (int i = 0; i < mTaskbarView.getChildCount(); i++) {
View child = mTaskbarView.getChildAt(i);
boolean isAllAppsButton = child == mTaskbarView.getAllAppsButtonView();
@@ -507,7 +659,7 @@
// to avoid icons disappearing rather than fading out visually.
setter.setViewAlpha(child, 0, Interpolators.clampToProgress(LINEAR, 0.8f, 1f));
} else if ((isAllAppsButton && !FeatureFlags.ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT.get())
- || (isTaskbarDividerView && FeatureFlags.ENABLE_TASKBAR_PINNING.get())) {
+ || (isTaskbarDividerView && ENABLE_TASKBAR_PINNING.get())) {
if (!isToHome
&& mIsHotseatIconOnTopWhenAligned
&& mIsStashed) {
@@ -528,6 +680,8 @@
+ launcherDp.hotseatQsbWidth / 2f
: hotseatPadding.left - borderSpacing - launcherDp.hotseatQsbWidth / 2f;
float childCenter = (child.getLeft() + child.getRight()) / 2f;
+ childCenter += ((Reorderable) child).getTranslateDelegate().getTranslationX(
+ INDEX_TASKBAR_PINNING_ANIM).getValue();
float halfQsbIconWidthDiff =
(launcherDp.hotseatQsbWidth - taskbarDp.taskbarIconSize) / 2f;
float scale = ((float) taskbarDp.taskbarIconSize)
@@ -561,9 +715,9 @@
}
int positionInHotseat;
- if (isAllAppsButton) {
- // Note that there is no All Apps button in the hotseat, this position is only used
- // as its convenient for animation purposes.
+ if (isAllAppsButton || isTaskbarDividerView) {
+ // Note that there is no All Apps button or taskbar divider view in the hotseat,
+ // this position is only used as its convenient for animation purposes.
positionInHotseat = Utilities.isRtl(child.getResources())
? taskbarDp.numShownHotseatIcons
: -1;
@@ -587,10 +741,11 @@
+ hotseatCellSize / 2f;
}
float childCenter = (child.getLeft() + child.getRight()) / 2f;
+ childCenter += ((Reorderable) child).getTranslateDelegate().getTranslationX(
+ INDEX_TASKBAR_PINNING_ANIM).getValue();
float toX = hotseatIconCenter - childCenter;
if (child instanceof Reorderable) {
MultiTranslateDelegate mtd = ((Reorderable) child).getTranslateDelegate();
-
setter.setFloat(mtd.getTranslationX(INDEX_TASKBAR_ALIGNMENT_ANIM),
MULTI_PROPERTY_VALUE, toX, interpolator);
setter.setFloat(mtd.getTranslationY(INDEX_TASKBAR_ALIGNMENT_ANIM),
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
index d78ca88..e2f4f32 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
@@ -107,8 +107,7 @@
setter.setFloat(mRecentsView, TASK_SECONDARY_TRANSLATION, 0f,
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR));
- boolean exitingOverview = !FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()
- && !toState.overviewUi;
+ boolean exitingOverview = !FeatureFlags.enableSplitContextually() && !toState.overviewUi;
if (mRecentsView.isSplitSelectionActive() && exitingOverview) {
setter.add(mRecentsView.getSplitSelectController().getSplitAnimationController()
.createPlaceholderDismissAnim(mLauncher));
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 4c739fa..8b9eeb1 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -265,7 +265,7 @@
mAppTransitionManager.registerRemoteAnimations();
mAppTransitionManager.registerRemoteTransitions();
- if (ENABLE_HOME_TRANSITION_LISTENER.get()) {
+ if (FeatureFlags.enableHomeTransitionListener()) {
mHomeTransitionController = new HomeTransitionController(this);
mHomeTransitionController.registerHomeTransitionListener();
}
@@ -377,7 +377,7 @@
}
if ((changeBits & ACTIVITY_STATE_RESUMED) != 0) {
- if (!ENABLE_HOME_TRANSITION_LISTENER.get() && mTaskbarUIController != null) {
+ if (!FeatureFlags.enableHomeTransitionListener() && mTaskbarUIController != null) {
mTaskbarUIController.onLauncherVisibilityChanged(hasBeenResumed());
}
}
@@ -644,7 +644,7 @@
splitSelectSource.alreadyRunningTaskId = taskWasFound
? foundTask.key.id
: INVALID_TASK_ID;
- if (ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ if (FeatureFlags.enableSplitContextually()) {
startSplitToHome(splitSelectSource);
} else {
recentsView.initiateSplitSelect(splitSelectSource);
@@ -718,7 +718,7 @@
super.onPause();
- if (ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ if (FeatureFlags.enableSplitContextually()) {
// If Launcher pauses before both split apps are selected, exit split screen.
if (!mSplitSelectStateController.isBothSplitAppsConfirmed() &&
!mSplitSelectStateController.isLaunchingFirstAppFullscreen()) {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index b266bcd..f6cd30a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -195,7 +195,7 @@
() -> recentsView.finishRecentsAnimation(true /* toRecents */, null));
if (mStartState.overviewUi) {
new OverviewToHomeAnim(mLauncher, () -> onSwipeInteractionCompleted(mEndState),
- FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()
+ FeatureFlags.enableSplitContextually()
? mCancelSplitRunnable
: null)
.animateWithVelocity(velocity);
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 4dfa81d..9ac5426 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -89,6 +89,7 @@
import android.widget.Toast;
import android.window.PictureInPictureSurfaceTransaction;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
@@ -318,7 +319,7 @@
private final Runnable mOnDeferredActivityLaunch = this::onDeferredActivityLaunch;
- private SwipePipToHomeAnimator mSwipePipToHomeAnimator;
+ @Nullable private SwipePipToHomeAnimator mSwipePipToHomeAnimator;
protected boolean mIsSwipingPipToHome;
// TODO(b/195473090) no split PIP for now, remove once we have more clarity
// can try to have RectFSpringAnim evaluate multiple rects at once
@@ -677,6 +678,9 @@
if (Arrays.stream(runningTasks).anyMatch(Objects::isNull)) {
return;
}
+ if (mRecentsView == null) {
+ return;
+ }
mRecentsView.onGestureAnimationStart(runningTasks, mDeviceState.getRotationTouchHelper());
}
@@ -1264,8 +1268,8 @@
return isSwipeUp ? ALL_APPS : LAST_TASK;
}
if (!isSwipeUp) {
- final boolean isCenteredOnNewTask =
- mRecentsView.getDestinationPage() != mRecentsView.getRunningTaskIndex();
+ final boolean isCenteredOnNewTask = mRecentsView != null
+ && mRecentsView.getDestinationPage() != mRecentsView.getRunningTaskIndex();
return willGoToNewTask || isCenteredOnNewTask ? NEW_TASK : LAST_TASK;
}
@@ -1541,11 +1545,13 @@
HomeAnimationFactory homeAnimFactory =
createHomeAnimationFactory(cookies, duration, isTranslucent, appCanEnterPip,
runningTaskTarget);
- mIsSwipingPipToHome = !mIsSwipeForSplit && appCanEnterPip;
+ SwipePipToHomeAnimator swipePipToHomeAnimator = !mIsSwipeForSplit && appCanEnterPip
+ ? createWindowAnimationToPip(homeAnimFactory, runningTaskTarget, start)
+ : null;
+ mIsSwipingPipToHome = swipePipToHomeAnimator != null;
final RectFSpringAnim[] windowAnim;
if (mIsSwipingPipToHome) {
- mSwipePipToHomeAnimator = createWindowAnimationToPip(
- homeAnimFactory, runningTaskTarget, start);
+ mSwipePipToHomeAnimator = swipePipToHomeAnimator;
mSwipePipToHomeAnimators[0] = mSwipePipToHomeAnimator;
if (mSwipePipToHomeReleaseCheck != null) {
mSwipePipToHomeReleaseCheck.setCanRelease(false);
@@ -1553,6 +1559,9 @@
// grab a screenshot before the PipContentOverlay gets parented on top of the task
UI_HELPER_EXECUTOR.execute(() -> {
+ if (mRecentsAnimationController == null) {
+ return;
+ }
// Directly use top task, split to pip handled on shell side
final int taskId = mGestureState.getTopRunningTaskId();
mTaskSnapshotCache.put(taskId,
@@ -1670,6 +1679,10 @@
@Nullable
private SwipePipToHomeAnimator createWindowAnimationToPip(HomeAnimationFactory homeAnimFactory,
RemoteAnimationTarget runningTaskTarget, float startProgress) {
+ if (mRecentsView == null) {
+ // Overview was destroyed, bail early.
+ return null;
+ }
// Directly animate the app to PiP (picture-in-picture) mode
final ActivityManager.RunningTaskInfo taskInfo = runningTaskTarget.taskInfo;
final RecentsOrientedState orientationState = mRemoteTargetHandles[0].getTaskViewSimulator()
@@ -1810,7 +1823,8 @@
private void continueComputingRecentsScrollIfNecessary() {
if (!mGestureState.hasState(STATE_RECENTS_SCROLLING_FINISHED)
&& !mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)
- && !mCanceled) {
+ && !mCanceled
+ && mRecentsView != null) {
computeRecentsScrollIfInvisible();
mRecentsView.postOnAnimation(this::continueComputingRecentsScrollIfNecessary);
}
@@ -2112,7 +2126,7 @@
* from Launcher to WM.
*/
private void maybeAbortSwipePipToHome() {
- if (mIsSwipingPipToHome && mSwipePipToHomeAnimators[0] != null) {
+ if (mIsSwipingPipToHome && mSwipePipToHomeAnimator != null) {
SystemUiProxy.INSTANCE.get(mContext).abortSwipePipToHome(
mSwipePipToHomeAnimator.getTaskId(),
mSwipePipToHomeAnimator.getComponentName());
@@ -2126,7 +2140,10 @@
* This should happen before {@link #finishRecentsControllerToHome(Runnable)}.
*/
private void maybeFinishSwipePipToHome() {
- if (mIsSwipingPipToHome && mSwipePipToHomeAnimators[0] != null) {
+ if (mRecentsAnimationController == null) {
+ return;
+ }
+ if (mIsSwipingPipToHome && mSwipePipToHomeAnimator != null) {
mRecentsAnimationController.setFinishTaskTransaction(
mSwipePipToHomeAnimator.getTaskId(),
mSwipePipToHomeAnimator.getFinishTransaction(),
@@ -2150,7 +2167,7 @@
protected abstract void finishRecentsControllerToHome(Runnable callback);
private void setupLauncherUiAfterSwipeUpToRecentsAnimation() {
- if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) {
+ if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED) || mRecentsView == null) {
return;
}
endLauncherTransitionController();
@@ -2184,6 +2201,9 @@
}
protected void linkRecentsViewScroll() {
+ if (mRecentsView == null) {
+ return;
+ }
SurfaceTransactionApplier applier = new SurfaceTransactionApplier(mRecentsView);
runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTransformParams()
.setSyncTransactionApplier(applier));
@@ -2191,9 +2211,13 @@
mRecentsAnimationTargets.addReleaseCheck(applier));
mRecentsView.addOnScrollChangedListener(mOnRecentsScrollListener);
- runOnRecentsAnimationAndLauncherBound(() ->
- mRecentsView.setRecentsAnimationTargets(mRecentsAnimationController,
- mRecentsAnimationTargets));
+ runOnRecentsAnimationAndLauncherBound(() -> {
+ if (mRecentsView == null) {
+ return;
+ }
+ mRecentsView.setRecentsAnimationTargets(
+ mRecentsAnimationController, mRecentsAnimationTargets);
+ });
// Disable scrolling in RecentsView for trackpad 3-finger swipe up gesture.
if (!mGestureState.isThreeFingerTrackpadGesture()) {
@@ -2300,7 +2324,7 @@
}
@Override
- public void onTasksAppeared(RemoteAnimationTarget[] appearedTaskTargets) {
+ public void onTasksAppeared(@NonNull RemoteAnimationTarget[] appearedTaskTargets) {
if (mRecentsAnimationController != null) {
boolean hasStartedTaskBefore = Arrays.stream(appearedTaskTargets).anyMatch(
mGestureState.mLastStartedTaskIdPredicate);
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 3fdc7ba..8d26fd4 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -19,6 +19,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.Display.DEFAULT_DISPLAY;
+import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE;
import static com.android.launcher3.util.DisplayController.CHANGE_ALL;
import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION;
@@ -60,6 +61,8 @@
import androidx.annotation.BinderThread;
import androidx.annotation.NonNull;
+import com.android.launcher3.LauncherPrefs;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
import com.android.launcher3.util.DisplayController.Info;
@@ -86,8 +89,8 @@
static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
// TODO: Move to quickstep contract
- private static final float QUICKSTEP_TOUCH_SLOP_RATIO_TWO_BUTTON = 9;
- private static final float QUICKSTEP_TOUCH_SLOP_RATIO_GESTURAL = 2;
+ private static final float QUICKSTEP_TOUCH_SLOP_RATIO_TWO_BUTTON = 3f;
+ private static final float QUICKSTEP_TOUCH_SLOP_RATIO_GESTURAL = 1.414f;
private final Context mContext;
private final DisplayController mDisplayController;
@@ -546,15 +549,31 @@
/**
* Returns the touch slop for {@link InputConsumer}s to compare against before pilfering
- * pointers. Note that this is squared because it expects to be compared against
- * {@link com.android.launcher3.Utilities#squaredHypot} (to avoid square root on each event).
+ * pointers.
*/
- public float getSquaredTouchSlop() {
+ public float getTouchSlop() {
float slopMultiplier = isFullyGesturalNavMode()
? QUICKSTEP_TOUCH_SLOP_RATIO_GESTURAL
: QUICKSTEP_TOUCH_SLOP_RATIO_TWO_BUTTON;
float touchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
- return slopMultiplier * touchSlop * touchSlop;
+
+ if (FeatureFlags.CUSTOM_LPNH_THRESHOLDS.get()) {
+ float customSlopMultiplier =
+ LauncherPrefs.get(mContext).get(LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE) / 100f;
+ return customSlopMultiplier * slopMultiplier * touchSlop;
+ } else {
+ return slopMultiplier * touchSlop;
+ }
+ }
+
+ /**
+ * Returns the squared touch slop for {@link InputConsumer}s to compare against before pilfering
+ * pointers. Note that this is squared because it expects to be compared against
+ * {@link com.android.launcher3.Utilities#squaredHypot} (to avoid square root on each event).
+ */
+ public float getSquaredTouchSlop() {
+ float touchSlop = getTouchSlop();
+ return touchSlop * touchSlop;
}
public String getSystemUiStateString() {
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 468d96a..038a022 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -17,7 +17,6 @@
import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_HOME_TRANSITION_LISTENER;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
@@ -63,6 +62,7 @@
import com.android.internal.logging.InstanceId;
import com.android.internal.util.ScreenshotRequest;
import com.android.internal.view.AppearanceRegion;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.Preconditions;
import com.android.quickstep.util.ActiveGestureLog;
@@ -1048,7 +1048,7 @@
}
public void setHomeTransitionListener(IHomeTransitionListener listener) {
- if (!ENABLE_HOME_TRANSITION_LISTENER.get()) {
+ if (!FeatureFlags.enableHomeTransitionListener()) {
return;
}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index b2f04b8..98a9938 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -963,7 +963,8 @@
.append(SUBSTRING_PREFIX)
.append("Long press nav handle enabled, ")
.append("using NavHandleLongPressInputConsumer");
- base = new NavHandleLongPressInputConsumer(this, base, mInputMonitorCompat);
+ base = new NavHandleLongPressInputConsumer(this, base, mInputMonitorCompat,
+ mDeviceState);
}
if (mDeviceState.isBubblesExpanded()) {
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 059b0ce..95ce406 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -254,7 +254,7 @@
setOverviewSelectEnabled(false);
}
if (finalState != OVERVIEW_SPLIT_SELECT) {
- if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ if (FeatureFlags.enableSplitContextually()) {
mSplitSelectStateController.resetState();
} else {
resetFromSplitSelectionState();
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
index f11e537..32f7bd5 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
@@ -15,7 +15,6 @@
*/
package com.android.quickstep.inputconsumers;
-import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE;
import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_TIMEOUT_MS;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
@@ -28,6 +27,7 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.DisplayController;
import com.android.quickstep.InputConsumer;
+import com.android.quickstep.RecentsAnimationDeviceState;
import com.android.systemui.shared.system.InputMonitorCompat;
/**
@@ -47,23 +47,18 @@
private MotionEvent mCurrentDownEvent;
public NavHandleLongPressInputConsumer(Context context, InputConsumer delegate,
- InputMonitorCompat inputMonitor) {
+ InputMonitorCompat inputMonitor, RecentsAnimationDeviceState deviceState) {
super(delegate, inputMonitor);
mViewConfiguration = ViewConfiguration.get(context);
mNavHandleWidth = context.getResources().getDimensionPixelSize(
R.dimen.navigation_home_handle_width);
mScreenWidth = DisplayController.INSTANCE.get(context).getInfo().currentSize.x;
- float touchSlop;
if (FeatureFlags.CUSTOM_LPNH_THRESHOLDS.get()) {
- float customSlopMultiplier =
- LauncherPrefs.get(context).get(LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE) / 100f;
- touchSlop = mViewConfiguration.getScaledEdgeSlop() * customSlopMultiplier;
mLongPressTimeout = LauncherPrefs.get(context).get(LONG_PRESS_NAV_HANDLE_TIMEOUT_MS);
} else {
- touchSlop = mViewConfiguration.getScaledTouchSlop();
mLongPressTimeout = ViewConfiguration.getLongPressTimeout();
}
- mTouchSlopSquared = touchSlop * touchSlop;
+ mTouchSlopSquared = deviceState.getSquaredTouchSlop();
mNavHandleLongPressHandler = NavHandleLongPressHandler.newInstance(context);
}
@@ -87,17 +82,14 @@
}
}
case MotionEvent.ACTION_MOVE -> {
+ if (!MAIN_EXECUTOR.getHandler().hasCallbacks(mTriggerLongPress)) {
+ break;
+ }
+
float touchSlopSquared = mTouchSlopSquared;
float dx = ev.getX() - mCurrentDownEvent.getX();
float dy = ev.getY() - mCurrentDownEvent.getY();
double distanceSquared = (dx * dx) + (dy * dy);
- // If the gesture is ambiguous then require more movement before classifying this
- // as a NON long press gesture.
- if (ev.getClassification() == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE) {
- float ambiguousGestureMultiplier =
- mViewConfiguration.getScaledAmbiguousGestureMultiplier();
- touchSlopSquared *= ambiguousGestureMultiplier * ambiguousGestureMultiplier;
- }
if (distanceSquared > touchSlopSquared) {
cancelLongPress();
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 28c00eb..e724547 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -40,7 +40,6 @@
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
-import android.view.ViewConfiguration;
import androidx.annotation.UiThread;
@@ -154,7 +153,7 @@
boolean continuingPreviousGesture = mTaskAnimationManager.isRecentsAnimationRunning();
mIsDeferredDownTarget = !continuingPreviousGesture && isDeferredDownTarget;
- mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
+ mTouchSlop = mDeviceState.getTouchSlop();
mSquaredTouchSlop = mDeviceState.getSquaredTouchSlop();
mPassedPilferInputSlop = mPassedWindowMoveSlop = continuingPreviousGesture;
diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
index ae497f0..6ee65d4 100644
--- a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
+++ b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
@@ -300,7 +300,7 @@
pendingAnimation.addEndListener {
splitSelectStateController.launchInitialAppFullscreen {
- if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ if (FeatureFlags.enableSplitContextually()) {
splitSelectStateController.resetState()
} else if (resetCallback.isPresent) {
resetCallback.get().run()
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index 8e3b5ec..c873152 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -152,8 +152,7 @@
private final BackPressHandler mSplitBackHandler = new BackPressHandler() {
@Override
public boolean canHandleBack() {
- return FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get() &&
- isSplitSelectActive();
+ return FeatureFlags.enableSplitContextually() && isSplitSelectActive();
}
@Override
@@ -711,7 +710,7 @@
/**
* To be called whenever we exit split selection state. If
- * {@link FeatureFlags#ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE} is set, this should be the
+ * {@link FeatureFlags#enableSplitContextually()} is set, this should be the
* central way split is getting reset, which should then go through the callbacks to reset
* other state.
*/
diff --git a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
index 00b5621..1b80388 100644
--- a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
@@ -17,7 +17,6 @@
package com.android.quickstep.util;
import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.animation.Animator;
@@ -40,6 +39,7 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.data.PackageItemInfo;
@@ -192,7 +192,7 @@
private boolean shouldIgnoreSecondSplitLaunch() {
return (!ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS.get()
- && !ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()
+ && !FeatureFlags.enableSplitContextually()
&& !DesktopTaskView.DESKTOP_MODE_SUPPORTED)
|| !mController.isSplitSelectActive();
}
diff --git a/quickstep/src/com/android/quickstep/util/SurfaceTransactionApplier.java b/quickstep/src/com/android/quickstep/util/SurfaceTransactionApplier.java
index bb028a7..df5765c 100644
--- a/quickstep/src/com/android/quickstep/util/SurfaceTransactionApplier.java
+++ b/quickstep/src/com/android/quickstep/util/SurfaceTransactionApplier.java
@@ -25,6 +25,8 @@
import android.view.View.OnAttachStateChangeListener;
import android.view.ViewRootImpl;
+import androidx.annotation.NonNull;
+
import com.android.quickstep.RemoteAnimationTargets.ReleaseCheck;
/**
@@ -48,7 +50,7 @@
/**
* @param targetView The view in the surface that acts as synchronization anchor.
*/
- public SurfaceTransactionApplier(View targetView) {
+ public SurfaceTransactionApplier(@NonNull View targetView) {
if (targetView.isAttachedToWindow()) {
initialize(targetView);
} else {
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index fb9e640..7ff2de9 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -87,7 +87,7 @@
StateManager stateManager = mActivity.getStateManager();
animated &= stateManager.shouldAnimateStateChange();
stateManager.goToState(NORMAL, animated);
- if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ if (FeatureFlags.enableSplitContextually()) {
mSplitSelectStateController.getSplitAnimationController()
.playPlaceholderDismissAnim(mActivity);
}
@@ -232,7 +232,7 @@
@Override
protected boolean canLaunchFullscreenTask() {
- if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ if (FeatureFlags.enableSplitContextually()) {
return !mSplitSelectStateController.isSplitSelectActive();
} else {
return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 76e92de..2555ffa 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -1087,7 +1087,7 @@
mIPipAnimationListener);
mOrientationState.initListeners();
mTaskOverlayFactory.initListeners();
- if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ if (FeatureFlags.enableSplitContextually()) {
mSplitSelectStateController.registerSplitListener(mSplitSelectionListener);
}
}
@@ -1108,7 +1108,7 @@
mIPipAnimationListener.setActivityAndRecentsView(null, null);
mOrientationState.destroyListeners();
mTaskOverlayFactory.removeListeners();
- if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ if (FeatureFlags.enableSplitContextually()) {
mSplitSelectStateController.unregisterSplitListener(mSplitSelectionListener);
}
}
@@ -2422,7 +2422,7 @@
remoteTargetHandle.getTransformParams().setTargetSet(null);
remoteTargetHandle.getTaskViewSimulator().setDrawsBelowRecents(false);
});
- if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ if (!FeatureFlags.enableSplitContextually()) {
resetFromSplitSelectionState();
}
@@ -3311,7 +3311,7 @@
InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
} else {
// If transition to split select was interrupted, clean up to prevent glitches
- if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ if (FeatureFlags.enableSplitContextually()) {
mSplitSelectStateController.resetState();
} else {
resetFromSplitSelectionState();
@@ -4769,7 +4769,7 @@
pendingAnimation.addEndListener(aBoolean -> {
mSplitSelectStateController.launchSplitTasks(
aBoolean1 -> {
- if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ if (FeatureFlags.enableSplitContextually()) {
mSplitSelectStateController.resetState();
} else {
resetFromSplitSelectionState();
@@ -4798,7 +4798,7 @@
@SuppressLint("WrongCall")
protected void resetFromSplitSelectionState() {
if (mSplitSelectSource != null || mSplitHiddenTaskViewIndex != -1 ||
- FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ FeatureFlags.enableSplitContextually()) {
safeRemoveDragLayerView(mSplitSelectStateController.getFirstFloatingTaskView());
safeRemoveDragLayerView(mSecondFloatingTaskView);
safeRemoveDragLayerView(mSplitSelectStateController.getSplitInstructionsView());
@@ -4818,7 +4818,7 @@
setTaskViewsPrimarySplitTranslation(0);
setTaskViewsSecondarySplitTranslation(0);
- if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ if (!FeatureFlags.enableSplitContextually()) {
// When flag is on, this method gets called from resetState() call below, let's avoid
// infinite recursion today
mSplitSelectStateController.resetState();
diff --git a/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java b/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java
index 4ca02e0..e8f06ee 100644
--- a/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java
+++ b/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java
@@ -99,7 +99,7 @@
private void init() {
mTextView = findViewById(R.id.split_instructions_text);
- if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ if (!FeatureFlags.enableSplitContextually()) {
mTextView.setCompoundDrawables(null, null, null, null);
return;
}
@@ -138,7 +138,7 @@
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
- if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ if (!FeatureFlags.enableSplitContextually()) {
return;
}
@@ -150,7 +150,7 @@
@Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
- if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ if (!FeatureFlags.enableSplitContextually()) {
return super.performAccessibilityAction(action, arguments);
}
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
index 2c16c15..15b1e53 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
@@ -55,7 +55,7 @@
@Mock lateinit var taskbarOverlayController: TaskbarOverlayController
@Mock lateinit var taskbarEduTooltipController: TaskbarEduTooltipController
@Mock lateinit var keyboardQuickSwitchController: KeyboardQuickSwitchController
- @Mock lateinit var taskbarPinningController: TaskbarDividerPopupController
+ @Mock lateinit var taskbarPinningController: TaskbarPinningController
@Mock lateinit var optionalBubbleControllers: Optional<BubbleControllers>
lateinit var taskbarControllers: TaskbarControllers
diff --git a/quickstep/tests/src/com/android/quickstep/TaplOverviewIconAppChipMenuTest.java b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconAppChipMenuTest.java
index 15952c1..969da68 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplOverviewIconAppChipMenuTest.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconAppChipMenuTest.java
@@ -18,6 +18,7 @@
import com.android.launcher3.Flags;
import com.android.launcher3.InvariantDeviceProfile;
+import org.junit.After;
import org.junit.Before;
/**
@@ -35,4 +36,11 @@
executeOnLauncher(launcher -> InvariantDeviceProfile.INSTANCE.get(launcher).onConfigChanged(
launcher));
}
+
+ @After
+ public void tearDown() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_OVERVIEW_ICON_MENU);
+ executeOnLauncher(launcher -> InvariantDeviceProfile.INSTANCE.get(launcher).onConfigChanged(
+ launcher));
+ }
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index c0520c1..9255ff4 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1578,7 +1578,7 @@
}
}
- if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ if (FeatureFlags.enableSplitContextually()) {
handleSplitAnimationGoingToHome();
}
mOverlayManager.hideOverlay(isStarted() && !isForceInvisible());
diff --git a/src/com/android/launcher3/LauncherPrefs.kt b/src/com/android/launcher3/LauncherPrefs.kt
index c6a9283..4f8caab 100644
--- a/src/com/android/launcher3/LauncherPrefs.kt
+++ b/src/com/android/launcher3/LauncherPrefs.kt
@@ -20,11 +20,12 @@
import android.content.SharedPreferences
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import android.util.Log
-import android.view.ViewConfiguration
import androidx.annotation.VisibleForTesting
import com.android.launcher3.BuildConfig.WIDGET_ON_FIRST_SCREEN
import com.android.launcher3.LauncherFiles.DEVICE_PREFERENCES_KEY
import com.android.launcher3.LauncherFiles.SHARED_PREFERENCES_KEY
+import com.android.launcher3.config.FeatureFlags.LPNH_SLOP_PERCENTAGE
+import com.android.launcher3.config.FeatureFlags.LPNH_TIMEOUT_MS
import com.android.launcher3.model.DeviceGridState
import com.android.launcher3.pm.InstallSessionHelper
import com.android.launcher3.provider.RestoreDbTask
@@ -310,16 +311,16 @@
)
@JvmField
val LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE =
- nonRestorableItem(
- "pref_long_press_nav_handle_slop_multiplier",
- 100,
+ nonRestorableItem(
+ "pref_long_press_nav_handle_slop_percentage",
+ LPNH_SLOP_PERCENTAGE.get(),
EncryptionType.MOVE_TO_DEVICE_PROTECTED
- )
+ )
@JvmField
val LONG_PRESS_NAV_HANDLE_TIMEOUT_MS =
nonRestorableItem(
"pref_long_press_nav_handle_timeout_ms",
- ViewConfiguration.getLongPressTimeout(),
+ LPNH_TIMEOUT_MS.get(),
EncryptionType.MOVE_TO_DEVICE_PROTECTED
)
@JvmField
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 9c0a508..4e7ec0b 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -21,8 +21,11 @@
import static com.android.launcher3.config.FeatureFlags.FlagState.ENABLED;
import static com.android.launcher3.config.FeatureFlags.FlagState.TEAMFOOD;
import static com.android.launcher3.uioverrides.flags.FlagsFactory.getDebugFlag;
+import static com.android.launcher3.uioverrides.flags.FlagsFactory.getIntFlag;
import static com.android.launcher3.uioverrides.flags.FlagsFactory.getReleaseFlag;
+import android.view.ViewConfiguration;
+
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.BuildConfig;
@@ -113,9 +116,17 @@
"Allow entering All Apps from Overview (e.g. long swipe up from app)");
public static final BooleanFlag CUSTOM_LPNH_THRESHOLDS =
- getDebugFlag(301680992, "CUSTOM_LPNH_THRESHOLDS", DISABLED,
+ getReleaseFlag(301680992, "CUSTOM_LPNH_THRESHOLDS", DISABLED,
"Add dev options to customize the LPNH trigger slop and milliseconds");
+ public static final IntFlag LPNH_SLOP_PERCENTAGE =
+ getIntFlag(301680992, "LPNH_SLOP_PERCENTAGE", 100,
+ "Controls touch slop percentage for lpnh");
+
+ public static final IntFlag LPNH_TIMEOUT_MS =
+ getIntFlag(301680992, "LPNH_TIMEOUT_MS", ViewConfiguration.getLongPressTimeout(),
+ "Controls lpnh timeout in milliseconds");
+
public static final BooleanFlag ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS = getReleaseFlag(
270394468, "ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS", ENABLED,
"Enable option to show keyboard when going to all-apps");
@@ -202,9 +213,13 @@
public static final BooleanFlag ENABLE_TRANSIENT_TASKBAR = getDebugFlag(270395798,
"ENABLE_TRANSIENT_TASKBAR", ENABLED, "Enables transient taskbar.");
+ // Aconfig migration complete for ENABLE_TASKBAR_NO_RECREATION.
public static final BooleanFlag ENABLE_TASKBAR_NO_RECREATION = getDebugFlag(299193589,
"ENABLE_TASKBAR_NO_RECREATION", DISABLED,
"Enables taskbar with no recreation from lifecycle changes of TaskbarActivityContext.");
+ public static boolean enableTaskbarNoRecreate() {
+ return ENABLE_TASKBAR_NO_RECREATION.get() || Flags.enableTaskbarNoRecreate();
+ }
// TODO(Block 16): Clean up flags
// When enabled the promise icon is visible in all apps while installation an app.
@@ -301,10 +316,15 @@
"ENABLE_DYNAMIC_TASKBAR_THRESHOLDS", ENABLED,
"Enables taskbar thresholds that scale based on screen size.");
+ // Aconfig migration complete for ENABLE_HOME_TRANSITION_LISTENER.
public static final BooleanFlag ENABLE_HOME_TRANSITION_LISTENER = getDebugFlag(306053414,
- "ENABLE_HOME_TRANSITION_LISTENER", DISABLED,
+ "ENABLE_HOME_TRANSITION_LISTENER", TEAMFOOD,
"Enables launcher to listen to all transitions that include home activity.");
+ public static boolean enableHomeTransitionListener() {
+ return ENABLE_HOME_TRANSITION_LISTENER.get() || Flags.enableHomeTransitionListener();
+ }
+
// TODO(Block 21): Clean up flags
public static final BooleanFlag ENABLE_APP_ICON_FOR_INLINE_SHORTCUTS = getDebugFlag(270395087,
"ENABLE_APP_ICON_IN_INLINE_SHORTCUTS", DISABLED, "Show app icon for inline shortcut");
@@ -379,6 +399,10 @@
public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE = getDebugFlag(
270393453, "ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE", DISABLED,
"Enable initiating split screen from workspace to workspace.");
+ public static boolean enableSplitContextually() {
+ return ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get() ||
+ com.android.wm.shell.Flags.enableSplitContextual();
+ }
public static final BooleanFlag ENABLE_TRACKPAD_GESTURE = getDebugFlag(271010401,
"ENABLE_TRACKPAD_GESTURE", ENABLED, "Enables trackpad gesture.");
diff --git a/src/com/android/launcher3/model/DatabaseHelper.java b/src/com/android/launcher3/model/DatabaseHelper.java
index 8167b97..1360510 100644
--- a/src/com/android/launcher3/model/DatabaseHelper.java
+++ b/src/com/android/launcher3/model/DatabaseHelper.java
@@ -269,7 +269,6 @@
Favorites.CONTAINER, Favorites.CONTAINER_DESKTOP,
Favorites.CELLY, 0), null);
}
- return;
}
case 31: {
LauncherDbUtils.migrateLegacyShortcuts(mContext, db);
diff --git a/src/com/android/launcher3/touch/ItemLongClickListener.java b/src/com/android/launcher3/touch/ItemLongClickListener.java
index a09e5a4..0c322cc 100644
--- a/src/com/android/launcher3/touch/ItemLongClickListener.java
+++ b/src/com/android/launcher3/touch/ItemLongClickListener.java
@@ -138,8 +138,9 @@
// Return early if an item is already being dragged (e.g. when long-pressing two shortcuts)
if (launcher.getDragController().isDragging()) return false;
// Return early if user is in the middle of selecting split-screen apps
- if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get() &&
- launcher.isSplitSelectionEnabled()) return false;
+ if (FeatureFlags.enableSplitContextually() && launcher.isSplitSelectionEnabled()) {
+ return false;
+ }
return true;
}
diff --git a/src/com/android/launcher3/touch/WorkspaceTouchListener.java b/src/com/android/launcher3/touch/WorkspaceTouchListener.java
index 1232069..5b6c9e0 100644
--- a/src/com/android/launcher3/touch/WorkspaceTouchListener.java
+++ b/src/com/android/launcher3/touch/WorkspaceTouchListener.java
@@ -206,8 +206,7 @@
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
mLauncher.getStatsLogManager().logger().log(LAUNCHER_WORKSPACE_LONGPRESS);
mLauncher.showDefaultOptions(mTouchDownPoint.x, mTouchDownPoint.y);
- if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get() &&
- mLauncher.isSplitSelectionEnabled()) {
+ if (FeatureFlags.enableSplitContextually() && mLauncher.isSplitSelectionEnabled()) {
mLauncher.dismissSplitSelection();
}
} else {
diff --git a/src/com/android/launcher3/util/MultiTranslateDelegate.java b/src/com/android/launcher3/util/MultiTranslateDelegate.java
index 6f6392f..84ef445 100644
--- a/src/com/android/launcher3/util/MultiTranslateDelegate.java
+++ b/src/com/android/launcher3/util/MultiTranslateDelegate.java
@@ -36,6 +36,7 @@
// Specific for items in taskbar (icons, folders, qsb)
public static final int INDEX_TASKBAR_ALIGNMENT_ANIM = 3;
public static final int INDEX_TASKBAR_REVEAL_ANIM = 4;
+ public static final int INDEX_TASKBAR_PINNING_ANIM = 5;
// Affect all items inside of a MultipageCellLayout
public static final int INDEX_CELLAYOUT_MULTIPAGE_SPACING = 3;
@@ -46,7 +47,7 @@
// Specific for hotseat items when adjusting for bubbles
public static final int INDEX_BUBBLE_ADJUSTMENT_ANIM = 3;
- public static final int COUNT = 5;
+ public static final int COUNT = 6;
private final MultiPropertyFactory<View> mTranslationX;
private final MultiPropertyFactory<View> mTranslationY;
diff --git a/tests/src/com/android/launcher3/DeleteDropTargetTest.kt b/tests/src/com/android/launcher3/DeleteDropTargetTest.kt
index bcfb90b..46e66e4 100644
--- a/tests/src/com/android/launcher3/DeleteDropTargetTest.kt
+++ b/tests/src/com/android/launcher3/DeleteDropTargetTest.kt
@@ -32,9 +32,9 @@
buttonDropTarget.setTextMultiLine(false)
// No space for text
- assertThat(buttonDropTarget.isTextClippedVertically(30)).isTrue()
+ assertThat(buttonDropTarget.isTextClippedVertically(1)).isTrue()
// A lot of space for text so the text should not be clipped
- assertThat(buttonDropTarget.isTextClippedVertically(100)).isFalse()
+ assertThat(buttonDropTarget.isTextClippedVertically(1000)).isFalse()
}
}