summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java30
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenuAnimator.kt245
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeWindowDecorationViewHolder.kt6
8 files changed, 321 insertions, 9 deletions
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml
index ee9f070f6765..87e0b2867090 100644
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml
@@ -22,6 +22,7 @@
android:orientation="vertical">
<LinearLayout
+ android:id="@+id/app_info_pill"
android:layout_width="match_parent"
android:layout_height="@dimen/desktop_mode_handle_menu_app_info_pill_height"
android:layout_marginTop="@dimen/desktop_mode_handle_menu_margin_top"
@@ -66,6 +67,7 @@
</LinearLayout>
<LinearLayout
+ android:id="@+id/windowing_pill"
android:layout_width="match_parent"
android:layout_height="@dimen/desktop_mode_handle_menu_windowing_pill_height"
android:layout_marginTop="@dimen/desktop_mode_handle_menu_pill_spacing_margin"
@@ -116,6 +118,7 @@
</LinearLayout>
<LinearLayout
+ android:id="@+id/more_actions_pill"
android:layout_width="match_parent"
android:layout_height="@dimen/desktop_mode_handle_menu_more_actions_pill_height"
android:layout_marginTop="@dimen/desktop_mode_handle_menu_pill_spacing_margin"
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index bb262d3df07f..3aed9ebc6c5e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -455,7 +455,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
}
/**
- * Create and display handle menu window
+ * Create and display handle menu window.
*/
void createHandleMenu() {
mHandleMenu = new HandleMenu.Builder(this)
@@ -466,15 +466,18 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
.setLayoutId(mRelayoutParams.mLayoutResId)
.setCaptionPosition(mRelayoutParams.mCaptionX, mRelayoutParams.mCaptionY)
.setWindowingButtonsVisible(DesktopModeStatus.isEnabled())
+ .setCaptionHeight(mResult.mCaptionHeight)
.build();
+ mWindowDecorViewHolder.onHandleMenuOpened();
mHandleMenu.show();
}
/**
- * Close the handle menu window
+ * Close the handle menu window.
*/
void closeHandleMenu() {
if (!isHandleMenuActive()) return;
+ mWindowDecorViewHolder.onHandleMenuClosed();
mHandleMenu.close();
mHandleMenu = null;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java
index 15f8f1cfadf2..6391518b5911 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java
@@ -71,10 +71,13 @@ class HandleMenu {
private int mMenuHeight;
private int mMenuWidth;
+ private final int mCaptionHeight;
+
HandleMenu(WindowDecoration parentDecor, int layoutResId, int captionX, int captionY,
View.OnClickListener onClickListener, View.OnTouchListener onTouchListener,
- Drawable appIcon, CharSequence appName, boolean shouldShowWindowingPill) {
+ Drawable appIcon, CharSequence appName, boolean shouldShowWindowingPill,
+ int captionHeight) {
mParentDecor = parentDecor;
mContext = mParentDecor.mDecorWindowContext;
mTaskInfo = mParentDecor.mTaskInfo;
@@ -86,6 +89,7 @@ class HandleMenu {
mAppIcon = appIcon;
mAppName = appName;
mShouldShowWindowingPill = shouldShowWindowingPill;
+ mCaptionHeight = captionHeight;
loadHandleMenuDimensions();
updateHandleMenuPillPositions();
}
@@ -98,6 +102,7 @@ class HandleMenu {
ssg.addTransaction(t);
ssg.markSyncReady();
setupHandleMenu();
+ animateHandleMenu();
}
private void createHandleMenuWindow(SurfaceControl.Transaction t, SurfaceSyncGroup ssg) {
@@ -109,6 +114,21 @@ class HandleMenu {
}
/**
+ * Animates the appearance of the handle menu and its three pills.
+ */
+ private void animateHandleMenu() {
+ final View handleMenuView = mHandleMenuWindow.mWindowViewHost.getView();
+ final HandleMenuAnimator handleMenuAnimator = new HandleMenuAnimator(handleMenuView,
+ mMenuWidth, mCaptionHeight);
+ if (mTaskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
+ || mTaskInfo.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW) {
+ handleMenuAnimator.animateCaptionHandleExpandToOpen();
+ } else {
+ handleMenuAnimator.animateOpen();
+ }
+ }
+
+ /**
* Set up all three pills of the handle menu: app info pill, windowing pill, & more actions
* pill.
*/
@@ -322,6 +342,7 @@ class HandleMenu {
private int mCaptionX;
private int mCaptionY;
private boolean mShowWindowingPill;
+ private int mCaptionHeight;
Builder(@NonNull WindowDecoration parent) {
@@ -364,9 +385,14 @@ class HandleMenu {
return this;
}
+ Builder setCaptionHeight(int captionHeight) {
+ mCaptionHeight = captionHeight;
+ return this;
+ }
+
HandleMenu build() {
return new HandleMenu(mParent, mLayoutId, mCaptionX, mCaptionY, mOnClickListener,
- mOnTouchListener, mAppIcon, mName, mShowWindowingPill);
+ mOnTouchListener, mAppIcon, mName, mShowWindowingPill, mCaptionHeight);
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenuAnimator.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenuAnimator.kt
new file mode 100644
index 000000000000..531de1f79ea8
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenuAnimator.kt
@@ -0,0 +1,245 @@
+/*
+ * 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.wm.shell.windowdecor
+
+import android.animation.Animator
+import android.animation.AnimatorSet
+import android.animation.ObjectAnimator
+import android.view.View
+import android.view.View.ALPHA
+import android.view.View.SCALE_X
+import android.view.View.SCALE_Y
+import android.view.View.TRANSLATION_Y
+import android.view.View.TRANSLATION_Z
+import android.view.ViewGroup
+import androidx.core.view.children
+import com.android.wm.shell.R
+import com.android.wm.shell.animation.Interpolators
+
+/** Animates the Handle Menu opening. */
+class HandleMenuAnimator(
+ private val handleMenu: View,
+ private val menuWidth: Int,
+ private val captionHeight: Float
+) {
+ companion object {
+ private const val MENU_Y_TRANSLATION_DURATION: Long = 150
+ private const val HEADER_NONFREEFORM_SCALE_DURATION: Long = 150
+ private const val HEADER_FREEFORM_SCALE_DURATION: Long = 217
+ private const val HEADER_ELEVATION_DURATION: Long = 83
+ private const val HEADER_CONTENT_ALPHA_DURATION: Long = 100
+ private const val BODY_SCALE_DURATION: Long = 180
+ private const val BODY_ALPHA_DURATION: Long = 150
+ private const val BODY_ELEVATION_DURATION: Long = 83
+ private const val BODY_CONTENT_ALPHA_DURATION: Long = 167
+
+ private const val ELEVATION_DELAY: Long = 33
+ private const val HEADER_CONTENT_ALPHA_DELAY: Long = 67
+ private const val BODY_SCALE_DELAY: Long = 50
+ private const val BODY_ALPHA_DELAY: Long = 133
+
+ private const val HALF_INITIAL_SCALE: Float = 0.5f
+ private const val NONFREEFORM_HEADER_INITIAL_SCALE_X: Float = 0.6f
+ private const val NONFREEFORM_HEADER_INITIAL_SCALE_Y: Float = 0.05f
+ }
+
+ private val animators: MutableList<Animator> = mutableListOf()
+
+ private val appInfoPill: ViewGroup = handleMenu.requireViewById(R.id.app_info_pill)
+ private val windowingPill: ViewGroup = handleMenu.requireViewById(R.id.windowing_pill)
+ private val moreActionsPill: ViewGroup = handleMenu.requireViewById(R.id.more_actions_pill)
+
+ /** Animates the opening of the handle menu. */
+ fun animateOpen() {
+ prepareMenuForAnimation()
+ appInfoPillExpand()
+ animateAppInfoPill()
+ animateWindowingPill()
+ animateMoreActionsPill()
+ runAnimations()
+ }
+
+ /**
+ * Animates the opening of the handle menu. The caption handle in full screen and split screen
+ * will expand until it assumes the shape of the app info pill. Then, the other two pills will
+ * appear.
+ */
+ fun animateCaptionHandleExpandToOpen() {
+ prepareMenuForAnimation()
+ captionHandleExpandIntoAppInfoPill()
+ animateAppInfoPill()
+ animateWindowingPill()
+ animateMoreActionsPill()
+ runAnimations()
+ }
+
+ /**
+ * Prepares the handle menu for animation. Presets the opacity of necessary menu components.
+ * Presets pivots of handle menu and body pills for scaling animation.
+ */
+ private fun prepareMenuForAnimation() {
+ // Preset opacity
+ appInfoPill.children.forEach { it.alpha = 0f }
+ windowingPill.alpha = 0f
+ moreActionsPill.alpha = 0f
+
+ // Setup pivots.
+ handleMenu.pivotX = menuWidth / 2f
+ handleMenu.pivotY = 0f
+
+ windowingPill.pivotX = menuWidth / 2f
+ windowingPill.pivotY = appInfoPill.measuredHeight.toFloat()
+
+ moreActionsPill.pivotX = menuWidth / 2f
+ moreActionsPill.pivotY = appInfoPill.measuredHeight.toFloat()
+ }
+
+ private fun animateAppInfoPill() {
+ // Header Elevation Animation
+ animators +=
+ ObjectAnimator.ofFloat(appInfoPill, TRANSLATION_Z, 1f).apply {
+ startDelay = ELEVATION_DELAY
+ duration = HEADER_ELEVATION_DURATION
+ }
+
+ // Content Opacity Animation
+ appInfoPill.children.forEach {
+ animators +=
+ ObjectAnimator.ofFloat(it, ALPHA, 1f).apply {
+ startDelay = HEADER_CONTENT_ALPHA_DELAY
+ duration = HEADER_CONTENT_ALPHA_DURATION
+ }
+ }
+ }
+
+ private fun captionHandleExpandIntoAppInfoPill() {
+ // Header scaling animation
+ animators +=
+ ObjectAnimator.ofFloat(appInfoPill, SCALE_X, NONFREEFORM_HEADER_INITIAL_SCALE_X, 1f)
+ .apply { duration = HEADER_NONFREEFORM_SCALE_DURATION }
+
+ animators +=
+ ObjectAnimator.ofFloat(appInfoPill, SCALE_Y, NONFREEFORM_HEADER_INITIAL_SCALE_Y, 1f)
+ .apply { duration = HEADER_NONFREEFORM_SCALE_DURATION }
+
+ // Downward y-translation animation
+ val yStart: Float = -captionHeight / 2
+ animators +=
+ ObjectAnimator.ofFloat(handleMenu, TRANSLATION_Y, yStart, 0f).apply {
+ duration = MENU_Y_TRANSLATION_DURATION
+ }
+ }
+
+ private fun appInfoPillExpand() {
+ // Header scaling animation
+ animators +=
+ ObjectAnimator.ofFloat(appInfoPill, SCALE_X, HALF_INITIAL_SCALE, 1f).apply {
+ duration = HEADER_FREEFORM_SCALE_DURATION
+ }
+
+ animators +=
+ ObjectAnimator.ofFloat(appInfoPill, SCALE_Y, HALF_INITIAL_SCALE, 1f).apply {
+ duration = HEADER_FREEFORM_SCALE_DURATION
+ }
+ }
+
+ private fun animateWindowingPill() {
+ // Windowing X & Y Scaling Animation
+ animators +=
+ ObjectAnimator.ofFloat(windowingPill, SCALE_X, HALF_INITIAL_SCALE, 1f).apply {
+ startDelay = BODY_SCALE_DELAY
+ duration = BODY_SCALE_DURATION
+ }
+
+ animators +=
+ ObjectAnimator.ofFloat(windowingPill, SCALE_Y, HALF_INITIAL_SCALE, 1f).apply {
+ startDelay = BODY_SCALE_DELAY
+ duration = BODY_SCALE_DURATION
+ }
+
+ // Windowing Opacity Animation
+ animators +=
+ ObjectAnimator.ofFloat(windowingPill, ALPHA, 1f).apply {
+ startDelay = BODY_ALPHA_DELAY
+ duration = BODY_ALPHA_DURATION
+ }
+
+ // Windowing Elevation Animation
+ animators +=
+ ObjectAnimator.ofFloat(windowingPill, TRANSLATION_Z, 1f).apply {
+ startDelay = ELEVATION_DELAY
+ duration = BODY_ELEVATION_DURATION
+ }
+
+ // Windowing Content Opacity Animation
+ windowingPill.children.forEach {
+ animators +=
+ ObjectAnimator.ofFloat(it, ALPHA, 1f).apply {
+ startDelay = BODY_ALPHA_DELAY
+ duration = BODY_CONTENT_ALPHA_DURATION
+ interpolator = Interpolators.FAST_OUT_SLOW_IN
+ }
+ }
+ }
+
+ private fun animateMoreActionsPill() {
+ // More Actions X & Y Scaling Animation
+ animators +=
+ ObjectAnimator.ofFloat(moreActionsPill, SCALE_X, HALF_INITIAL_SCALE, 1f).apply {
+ startDelay = BODY_SCALE_DELAY
+ duration = BODY_SCALE_DURATION
+ }
+
+ animators +=
+ ObjectAnimator.ofFloat(moreActionsPill, SCALE_Y, HALF_INITIAL_SCALE, 1f).apply {
+ startDelay = BODY_SCALE_DELAY
+ duration = BODY_SCALE_DURATION
+ }
+
+ // More Actions Opacity Animation
+ animators +=
+ ObjectAnimator.ofFloat(moreActionsPill, ALPHA, 1f).apply {
+ startDelay = BODY_ALPHA_DELAY
+ duration = BODY_ALPHA_DURATION
+ }
+
+ // More Actions Elevation Animation
+ animators +=
+ ObjectAnimator.ofFloat(moreActionsPill, TRANSLATION_Z, 1f).apply {
+ startDelay = ELEVATION_DELAY
+ duration = BODY_ELEVATION_DURATION
+ }
+
+ // More Actions Content Opacity Animation
+ moreActionsPill.children.forEach {
+ animators +=
+ ObjectAnimator.ofFloat(it, ALPHA, 1f).apply {
+ startDelay = BODY_ALPHA_DELAY
+ duration = BODY_CONTENT_ALPHA_DURATION
+ interpolator = Interpolators.FAST_OUT_SLOW_IN
+ }
+ }
+ }
+
+ /** Runs the list of animators concurrently. */
+ private fun runAnimations() {
+ val animatorSet = AnimatorSet()
+ animatorSet.playTogether(animators)
+ animatorSet.start()
+ animators.clear()
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 044c0331282c..634b7558c7d8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -269,10 +269,10 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
.build();
}
- final int captionHeight = loadDimensionPixelSize(resources, params.mCaptionHeightId);
+ outResult.mCaptionHeight = loadDimensionPixelSize(resources, params.mCaptionHeightId);
final int captionWidth = taskBounds.width();
- startT.setWindowCrop(mCaptionContainerSurface, captionWidth, captionHeight)
+ startT.setWindowCrop(mCaptionContainerSurface, captionWidth, outResult.mCaptionHeight)
.setLayer(mCaptionContainerSurface, CAPTION_LAYER_Z_ORDER)
.show(mCaptionContainerSurface);
@@ -283,7 +283,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
mCaptionInsetsRect.set(taskBounds);
if (mIsCaptionVisible) {
mCaptionInsetsRect.bottom =
- mCaptionInsetsRect.top + captionHeight + params.mCaptionY;
+ mCaptionInsetsRect.top + outResult.mCaptionHeight + params.mCaptionY;
wct.addInsetsSource(mTaskInfo.token,
mOwner, 0 /* index */, WindowInsets.Type.captionBar(), mCaptionInsetsRect);
wct.addInsetsSource(mTaskInfo.token,
@@ -348,7 +348,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
// Caption view
mCaptionWindowManager.setConfiguration(taskConfig);
final WindowManager.LayoutParams lp =
- new WindowManager.LayoutParams(captionWidth, captionHeight,
+ new WindowManager.LayoutParams(captionWidth, outResult.mCaptionHeight,
WindowManager.LayoutParams.TYPE_APPLICATION,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT);
lp.setTitle("Caption of Task=" + mTaskInfo.taskId);
@@ -569,6 +569,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
}
static class RelayoutResult<T extends View & TaskFocusStateConsumer> {
+ int mCaptionHeight;
int mWidth;
int mHeight;
T mRootView;
@@ -576,6 +577,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
void reset() {
mWidth = 0;
mHeight = 0;
+ mCaptionHeight = 0;
mRootView = null;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt
index 6b59ccec5148..400dec4df506 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt
@@ -48,7 +48,6 @@ internal class DesktopModeAppControlsWindowDecorationViewHolder(
}
override fun bindData(taskInfo: RunningTaskInfo) {
-
val captionDrawable = captionView.background as GradientDrawable
taskInfo.taskDescription?.statusBarColor?.let {
captionDrawable.setColor(it)
@@ -63,6 +62,10 @@ internal class DesktopModeAppControlsWindowDecorationViewHolder(
appNameTextView.setTextColor(getCaptionAppNameTextColor(taskInfo))
}
+ override fun onHandleMenuOpened() {}
+
+ override fun onHandleMenuClosed() {}
+
private fun getCaptionAppNameTextColor(taskInfo: RunningTaskInfo): Int {
return if (shouldUseLightCaptionColors(taskInfo)) {
context.getColor(R.color.desktop_mode_caption_app_name_light)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt
index 9374ac95e83d..9dc86db4f59b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt
@@ -1,11 +1,13 @@
package com.android.wm.shell.windowdecor.viewholder
+import android.animation.ObjectAnimator
import android.app.ActivityManager.RunningTaskInfo
import android.content.res.ColorStateList
import android.graphics.drawable.GradientDrawable
import android.view.View
import android.widget.ImageButton
import com.android.wm.shell.R
+import com.android.wm.shell.animation.Interpolators
/**
* A desktop mode window decoration used when the window is in full "focus" (i.e. fullscreen). It
@@ -17,6 +19,10 @@ internal class DesktopModeFocusedWindowDecorationViewHolder(
onCaptionButtonClickListener: View.OnClickListener
) : DesktopModeWindowDecorationViewHolder(rootView) {
+ companion object {
+ private const val CAPTION_HANDLE_ANIMATION_DURATION: Long = 100
+ }
+
private val captionView: View = rootView.requireViewById(R.id.desktop_mode_caption)
private val captionHandle: ImageButton = rootView.requireViewById(R.id.caption_handle)
@@ -35,6 +41,14 @@ internal class DesktopModeFocusedWindowDecorationViewHolder(
captionHandle.imageTintList = ColorStateList.valueOf(getCaptionHandleBarColor(taskInfo))
}
+ override fun onHandleMenuOpened() {
+ animateCaptionHandleAlpha(startValue = 0f, endValue = 1f)
+ }
+
+ override fun onHandleMenuClosed() {
+ animateCaptionHandleAlpha(startValue = 1f, endValue = 0f)
+ }
+
private fun getCaptionHandleBarColor(taskInfo: RunningTaskInfo): Int {
return if (shouldUseLightCaptionColors(taskInfo)) {
context.getColor(R.color.desktop_mode_caption_handle_bar_light)
@@ -42,4 +56,14 @@ internal class DesktopModeFocusedWindowDecorationViewHolder(
context.getColor(R.color.desktop_mode_caption_handle_bar_dark)
}
}
+
+ /** Animate appearance/disappearance of caption handle as the handle menu is animated. */
+ private fun animateCaptionHandleAlpha(startValue: Float, endValue: Float) {
+ val animator =
+ ObjectAnimator.ofFloat(captionHandle, View.ALPHA, startValue, endValue).apply {
+ duration = CAPTION_HANDLE_ANIMATION_DURATION
+ interpolator = Interpolators.FAST_OUT_SLOW_IN
+ }
+ animator.start()
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeWindowDecorationViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeWindowDecorationViewHolder.kt
index 49e8d15dcc02..8b405f02ef29 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeWindowDecorationViewHolder.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeWindowDecorationViewHolder.kt
@@ -35,4 +35,10 @@ internal abstract class DesktopModeWindowDecorationViewHolder(rootView: View) {
}
} ?: false
}
+
+ /** Callback when the handle menu is opened. */
+ abstract fun onHandleMenuOpened()
+
+ /** Callback when the handle menu is closed. */
+ abstract fun onHandleMenuClosed()
}