Files
Lawnchair/quickstep/src/com/android/launcher3/taskbar/TaskbarPinningController.kt
T
Ahmed Fakhry ad6fee6111 Implement isInDesktopMode*()
This CL does the following:
- Adds new methods `isInDesktopMode()` and
  `isInDesktopModeAndNotInOverview()` to `DesktopVisibilityController`.
- These two methods rely on the new multi-desks impl when the flags are
  enabled.
- Makes the existing `areDesktopTasksVisible()` and
  `areDesktopTasksVisibleAndNotInOverview()` private, and migrates all
  the usages to the new methods.
- The new methods uses the old methods if the flags are disabled.

A companion NexusLauncher CL is at ag/31601363.

Bug: 394182435
Test: m
Flag: com.android.window.flags.enable_multiple_desktops_frontend
Flag: com.android.window.flags.enable_multiple_desktops_backend
Change-Id: I29ff38f984bfe2f68a120f84e1a75fa36b739258
2025-02-12 21:18:51 +00:00

174 lines
7.5 KiB
Kotlin

/*
* 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.annotation.SuppressLint
import android.view.View
import androidx.annotation.VisibleForTesting
import androidx.core.animation.doOnEnd
import com.android.app.animation.Interpolators
import com.android.launcher3.LauncherPrefs
import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING
import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING_IN_DESKTOP_MODE
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
import kotlin.jvm.optionals.getOrNull
/** 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 lateinit var launcherPrefs: LauncherPrefs
private val statsLogManager = context.statsLogManager
@VisibleForTesting var isAnimatingTaskbarPinning = false
@VisibleForTesting lateinit var onCloseCallback: (preferenceChanged: Boolean) -> Unit
@SuppressLint("VisibleForTests")
fun init(taskbarControllers: TaskbarControllers, sharedState: TaskbarSharedState) {
controllers = taskbarControllers
taskbarSharedState = sharedState
launcherPrefs = context.launcherPrefs
onCloseCallback =
fun(didPreferenceChange: Boolean) {
statsLogManager.logger().log(LAUNCHER_TASKBAR_DIVIDER_MENU_CLOSE)
context.dragLayer.post { context.onPopupVisibilityChanged(false) }
if (!didPreferenceChange) {
return
}
val shouldPinTaskbar =
if (
controllers.taskbarDesktopModeController.isInDesktopModeAndNotInOverview(
context.displayId
)
) {
!launcherPrefs.get(TASKBAR_PINNING_IN_DESKTOP_MODE)
} else {
!launcherPrefs.get(TASKBAR_PINNING)
}
val animateToValue =
if (shouldPinTaskbar) {
statsLogManager.logger().log(LAUNCHER_TASKBAR_PINNED)
PINNING_PERSISTENT
} else {
statsLogManager.logger().log(LAUNCHER_TASKBAR_UNPINNED)
PINNING_TRANSIENT
}
taskbarSharedState.taskbarWasPinned = animateToValue == PINNING_TRANSIENT
animateTaskbarPinning(animateToValue)
}
}
fun showPinningView(view: View, horizontalPosition: Float = -1f) {
context.isTaskbarWindowFullscreen = true
view.post {
val popupView = getPopupView(view, horizontalPosition)
popupView.requestFocus()
popupView.onCloseCallback = onCloseCallback
context.onPopupVisibilityChanged(true)
popupView.show()
statsLogManager.logger().log(LAUNCHER_TASKBAR_DIVIDER_MENU_OPEN)
}
}
@VisibleForTesting
fun getPopupView(view: View, horizontalPosition: Float = -1f): TaskbarDividerPopupView<*> {
return createAndPopulate(view, context, horizontalPosition)
}
@VisibleForTesting
fun animateTaskbarPinning(animateToValue: Float) {
val taskbarViewController = controllers.taskbarViewController
val animatorSet =
getAnimatorSetForTaskbarPinningAnimation(animateToValue).apply {
doOnEnd { recreateTaskbarAndUpdatePinningValue() }
duration = PINNING_ANIMATION_DURATION
}
controllers.taskbarOverlayController.hideWindow()
updateIsAnimatingTaskbarPinningAndNotifyTaskbarDragLayer(true)
taskbarViewController.animateAwayNotificationDotsDuringTaskbarPinningAnimation()
animatorSet.start()
}
@VisibleForTesting
fun getAnimatorSetForTaskbarPinningAnimation(animateToValue: Float): AnimatorSet {
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),
)
controllers.bubbleControllers.getOrNull()?.bubbleBarViewController?.let {
// if bubble bar is not visible no need to add it`s animations
if (!it.isBubbleBarVisible) return@let
animatorSet.playTogether(it.bubbleBarPinning.animateToValue(animateToValue))
}
animatorSet.interpolator = Interpolators.EMPHASIZED
return animatorSet
}
private fun updateIsAnimatingTaskbarPinningAndNotifyTaskbarDragLayer(isAnimating: Boolean) {
isAnimatingTaskbarPinning = isAnimating
context.dragLayer.setAnimatingTaskbarPinning(isAnimating)
}
@VisibleForTesting
fun recreateTaskbarAndUpdatePinningValue() {
updateIsAnimatingTaskbarPinningAndNotifyTaskbarDragLayer(false)
if (
controllers.taskbarDesktopModeController.isInDesktopModeAndNotInOverview(
context.displayId
)
) {
launcherPrefs.put(
TASKBAR_PINNING_IN_DESKTOP_MODE,
!launcherPrefs.get(TASKBAR_PINNING_IN_DESKTOP_MODE),
)
} else {
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))
pw.println(
"$prefix\tTASKBAR_PINNING_IN_DESKTOP_MODE shared pref in desktop mode =" +
launcherPrefs.get(TASKBAR_PINNING_IN_DESKTOP_MODE)
)
}
companion object {
const val PINNING_PERSISTENT = 1f
const val PINNING_TRANSIENT = 0f
const val PINNING_ANIMATION_DURATION = 600L
}
}