Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 631b2848 authored by Jagrut Desai's avatar Jagrut Desai
Browse files

Taskbar pinning animation with no recreate

Test: Manual, Visual
Bug: 265436799
Flag: LEGACY ENABLE_TASKBAR_PINNING DISABLED

Change-Id: I84a4d1efdb0bd4a0f856fa1f46b6489ef54a3841
parent 927c78f2
Loading
Loading
Loading
Loading
+45 −9
Original line number Diff line number Diff line
@@ -173,13 +173,16 @@ public class TaskbarActivityContext extends BaseTaskbarContext {

    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);
@@ -274,7 +277,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
                        : TaskbarRecentAppsController.DEFAULT,
                new TaskbarEduTooltipController(this),
                new KeyboardQuickSwitchController(),
                new TaskbarDividerPopupController(this),
                new TaskbarPinningController(this),
                bubbleControllersOptional);
    }

@@ -306,6 +309,30 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
                    deviceProfile.iconSizePx = deviceProfile.taskbarIconSize;
                    deviceProfile.updateIconSize(1f, getResources());
                }).build();

        if (DisplayController.isTransientTaskbar(this)) {
            mTransientTaskbarDeviceProfile = mDeviceProfile;
            mPersistentTaskbarDeviceProfile = mDeviceProfile
                    .toBuilder(this)
                    .withDimensionsOverride(deviceProfile -> {
                        // Update icon size
                        deviceProfile.iconSizePx = deviceProfile.taskbarIconSize;
                        deviceProfile.updateIconSize(1f, getResources());
                    })
                    .setIsTransientTaskbar(false)
                    .build();
        } else {
            mPersistentTaskbarDeviceProfile = mDeviceProfile;
            mTransientTaskbarDeviceProfile = mDeviceProfile
                    .toBuilder(this)
                    .withDimensionsOverride(deviceProfile -> {
                        // Update icon size
                        deviceProfile.iconSizePx = deviceProfile.taskbarIconSize;
                        deviceProfile.updateIconSize(1f, getResources());
                    })
                    .setIsTransientTaskbar(true)
                    .build();
        }
        mNavMode = DisplayController.getNavigationMode(this);
    }

@@ -391,6 +418,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {

    /**
     * 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 title The window title to pass to the created WindowManager.LayoutParams.
     */
@@ -878,6 +906,14 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
        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.
+131 −66
Original line number Diff line number Diff line
@@ -29,26 +29,38 @@ import com.android.launcher3.Utilities
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

/** 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 +87,6 @@ class TaskbarBackgroundRenderer(context: TaskbarActivityContext) {
        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,7 +95,8 @@ class TaskbarBackgroundRenderer(context: TaskbarActivityContext) {
    }

    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 +108,7 @@ class TaskbarBackgroundRenderer(context: TaskbarActivityContext) {
     * @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,11 +132,31 @@ class TaskbarBackgroundRenderer(context: TaskbarActivityContext) {

    /** 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)
        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 {
            canvas.translate(0f, canvas.height - maxPersistentTaskbarHeight)
            // Draw the background behind taskbar content.
            canvas.drawRect(0f, 0f, canvas.width.toFloat(), backgroundHeight, paint)
            canvas.drawRect(0f, 0f, canvas.width.toFloat(), maxPersistentTaskbarHeight, paint)
        }

        // Draw the inverted rounded corners above the taskbar.
        canvas.translate(0f, -leftCornerRadius)
@@ -138,17 +164,54 @@ class TaskbarBackgroundRenderer(context: TaskbarActivityContext) {
        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
    }

    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, stashedHandleHeight.toFloat(), maxBackgroundHeight)
            mapRange(progress, backgroundHeightWhileAnimating, maxTransientTaskbarHeight)
        val fullWidth = transientBackgroundBounds.width()
            val newWidth = mapRange(progress, stashedHandleWidth.toFloat(), fullWidth.toFloat())

        // .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)
@@ -159,7 +222,11 @@ class TaskbarBackgroundRenderer(context: TaskbarActivityContext) {
                bottomMarginProgress +
                translationYForSwipe +
                translationYForStash +
                    -mapRange(1f - progress, 0f, stashedHandleHeight / 2f)
                -mapRange(
                    1f - progress,
                    0f,
                    if (isAnimatingPinning) 0f else stashedHandleHeight / 2f
                )

        // Draw shadow.
        val newShadowAlpha =
@@ -182,8 +249,6 @@ class TaskbarBackgroundRenderer(context: TaskbarActivityContext) {

        canvas.drawRoundRect(lastDrawnTransientRect, radius, radius, paint)
    }
        canvas.restore()
    }

    /**
     * Sets the width percentage to inset the transient taskbar's background from the left and from
+3 −3
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ public class TaskbarControllers {
    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 @@ public class TaskbarControllers {
            TaskbarRecentAppsController taskbarRecentAppsController,
            TaskbarEduTooltipController taskbarEduTooltipController,
            KeyboardQuickSwitchController keyboardQuickSwitchController,
            TaskbarDividerPopupController taskbarPinningController,
            TaskbarPinningController taskbarPinningController,
            Optional<BubbleControllers> bubbleControllers) {
        this.taskbarActivityContext = taskbarActivityContext;
        this.taskbarDragController = taskbarDragController;
@@ -171,7 +171,7 @@ public class TaskbarControllers {
        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[] {
+0 −8
Original line number Diff line number Diff line
@@ -75,12 +75,6 @@ constructor(
    /** 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 @@ constructor(

    private fun onClickAlwaysShowTaskbarSwitchOption() {
        didPreferenceChange = true
        changePreference()
        changePreference = {}
        // Allow switch animation to finish and then close the popup.
        postDelayed(DIVIDER_POPUP_CLOSING_DELAY) {
            if (isOpen) {
+20 −0
Original line number Diff line number Diff line
@@ -73,6 +73,8 @@ public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
    private SafeCloseable mViewCaptureCloseable;

    private float mTaskbarBackgroundOffset;
    private float mTaskbarBackgroundProgress;
    private boolean mIsAnimatingTaskbarPinning = false;

    private final MultiPropertyFactory<TaskbarDragLayer> mTaskbarBackgroundAlpha;

@@ -162,10 +164,19 @@ public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
        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);
    }
@@ -174,6 +185,15 @@ public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
        return mTaskbarBackgroundAlpha.get(INDEX_STASH_ANIM);
    }

    /**
     * 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.
Loading