summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecoration.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleAnimator.kt101
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt35
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java5
7 files changed, 54 insertions, 118 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
index 2d7fec3a5302..5e8c1fe2aa8d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -445,4 +445,9 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
private static int getCaptionHeightIdStatic(@WindowingMode int windowingMode) {
return R.dimen.freeform_decor_caption_height;
}
+
+ @Override
+ int getCaptionViewId() {
+ return R.id.caption;
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecoration.java
index 88f64bca280d..3182745d813e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecoration.java
@@ -108,6 +108,11 @@ public class CarWindowDecoration extends WindowDecoration<WindowDecorLinearLayou
return new Rect();
}
+ @Override
+ int getCaptionViewId() {
+ return R.id.caption;
+ }
+
private void updateRelayoutParams(
RelayoutParams relayoutParams,
ActivityManager.RunningTaskInfo taskInfo,
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 813d0c6fcb6c..2a5315739396 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
@@ -1769,6 +1769,11 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
return loadDimensionPixelSize(mContext.getResources(), getCaptionHeightId(windowingMode));
}
+ @Override
+ int getCaptionViewId() {
+ return R.id.desktop_mode_caption;
+ }
+
void setAnimatingTaskResizeOrReposition(boolean animatingTaskResizeOrReposition) {
if (mRelayoutParams.mLayoutResId == R.layout.desktop_mode_app_handle) return;
final boolean inFullImmersive =
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 dc4a19e54df4..7baef2b2dc97 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
@@ -625,16 +625,32 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
*/
private void updateCaptionVisibility(View rootView, @NonNull RelayoutParams params) {
mIsCaptionVisible = params.mIsCaptionVisible;
+ setCaptionVisibility(rootView, mIsCaptionVisible);
}
void setTaskDragResizer(TaskDragResizer taskDragResizer) {
mTaskDragResizer = taskDragResizer;
}
+ // TODO(b/346441962): Move these three methods closer to implementing or View-level classes to
+ // keep implementation details more encapsulated.
+ private void setCaptionVisibility(View rootView, boolean visible) {
+ if (rootView == null) {
+ return;
+ }
+ final int v = visible ? View.VISIBLE : View.GONE;
+ final View captionView = rootView.findViewById(getCaptionViewId());
+ captionView.setVisibility(v);
+ }
+
int getCaptionHeightId(@WindowingMode int windowingMode) {
return Resources.ID_NULL;
}
+ int getCaptionViewId() {
+ return Resources.ID_NULL;
+ }
+
/**
* Obtains the {@link Display} instance for the display ID in {@link #mTaskInfo} if it exists or
* registers {@link #mOnDisplaysChangedListener} if it doesn't.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleAnimator.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleAnimator.kt
deleted file mode 100644
index f0a85306d177..000000000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleAnimator.kt
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2025 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.ObjectAnimator
-import android.view.View
-import android.view.View.Visibility
-import android.view.animation.PathInterpolator
-import android.widget.ImageButton
-import androidx.core.animation.doOnEnd
-import com.android.wm.shell.shared.animation.Interpolators
-
-/**
- * Animates the Desktop View's app handle.
- */
-class AppHandleAnimator(
- private val appHandleView: View,
- private val captionHandle: ImageButton,
-) {
- companion object {
- // Constants for animating the whole caption
- private const val APP_HANDLE_ALPHA_FADE_IN_ANIMATION_DURATION_MS: Long = 275L
- private const val APP_HANDLE_ALPHA_FADE_OUT_ANIMATION_DURATION_MS: Long = 340
- private val APP_HANDLE_ANIMATION_INTERPOLATOR = PathInterpolator(
- 0.4f,
- 0f,
- 0.2f,
- 1f
- )
-
- // Constants for animating the caption's handle
- private const val HANDLE_ANIMATION_DURATION: Long = 100
- private val HANDLE_ANIMATION_INTERPOLATOR = Interpolators.FAST_OUT_SLOW_IN
- }
-
- private var animator: ObjectAnimator? = null
-
- /** Animates the given caption view to the given visibility after a visibility change. */
- fun animateVisibilityChange(@Visibility visible: Int) {
- when (visible) {
- View.VISIBLE -> animateShowAppHandle()
- else -> animateHideAppHandle()
- }
- }
-
- /** Animate appearance/disappearance of caption's handle. */
- fun animateCaptionHandleAlpha(startValue: Float, endValue: Float) {
- cancel()
- animator = ObjectAnimator.ofFloat(captionHandle, View.ALPHA, startValue, endValue).apply {
- duration = HANDLE_ANIMATION_DURATION
- interpolator = HANDLE_ANIMATION_INTERPOLATOR
- start()
- }
- }
-
- private fun animateShowAppHandle() {
- cancel()
- appHandleView.alpha = 0f
- appHandleView.visibility = View.VISIBLE
- animator = ObjectAnimator.ofFloat(appHandleView, View.ALPHA, 1f).apply {
- duration = APP_HANDLE_ALPHA_FADE_IN_ANIMATION_DURATION_MS
- interpolator = APP_HANDLE_ANIMATION_INTERPOLATOR
- start()
- }
- }
-
- private fun animateHideAppHandle() {
- cancel()
- animator = ObjectAnimator.ofFloat(appHandleView, View.ALPHA, 0f).apply {
- duration = APP_HANDLE_ALPHA_FADE_OUT_ANIMATION_DURATION_MS
- interpolator = APP_HANDLE_ANIMATION_INTERPOLATOR
- doOnEnd {
- appHandleView.visibility = View.GONE
- }
- start()
- }
- }
-
- /**
- * Cancels any active animations.
- */
- fun cancel() {
- animator?.removeAllListeners()
- animator?.cancel()
- animator = null
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt
index 7ab3303be618..d9df899f8b40 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt
@@ -15,6 +15,7 @@
*/
package com.android.wm.shell.windowdecor.viewholder
+import android.animation.ObjectAnimator
import android.app.ActivityManager.RunningTaskInfo
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
import android.content.res.ColorStateList
@@ -39,8 +40,8 @@ import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.Accessibilit
import com.android.internal.policy.SystemBarUtils
import com.android.window.flags.Flags
import com.android.wm.shell.R
+import com.android.wm.shell.shared.animation.Interpolators
import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper
-import com.android.wm.shell.windowdecor.AppHandleAnimator
import com.android.wm.shell.windowdecor.WindowManagerWrapper
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer
@@ -56,6 +57,10 @@ internal class AppHandleViewHolder(
private val handler: Handler
) : WindowDecorationViewHolder<AppHandleViewHolder.HandleData>(rootView) {
+ companion object {
+ private const val CAPTION_HANDLE_ANIMATION_DURATION: Long = 100
+ }
+
data class HandleData(
val taskInfo: RunningTaskInfo,
val position: Point,
@@ -68,7 +73,6 @@ internal class AppHandleViewHolder(
private val captionView: View = rootView.requireViewById(R.id.desktop_mode_caption)
private val captionHandle: ImageButton = rootView.requireViewById(R.id.caption_handle)
private val inputManager = context.getSystemService(InputManager::class.java)
- private val animator: AppHandleAnimator = AppHandleAnimator(rootView, captionHandle)
private var statusBarInputLayerExists = false
// An invisible View that takes up the same coordinates as captionHandle but is layered
@@ -107,7 +111,6 @@ internal class AppHandleViewHolder(
height: Int,
isCaptionVisible: Boolean
) {
- setVisibility(isCaptionVisible)
captionHandle.imageTintList = ColorStateList.valueOf(getCaptionHandleBarColor(taskInfo))
this.taskInfo = taskInfo
// If handle is not in status bar region(i.e., bottom stage in vertical split),
@@ -129,11 +132,11 @@ internal class AppHandleViewHolder(
}
override fun onHandleMenuOpened() {
- animator.animateCaptionHandleAlpha(startValue = 1f, endValue = 0f)
+ animateCaptionHandleAlpha(startValue = 1f, endValue = 0f)
}
override fun onHandleMenuClosed() {
- animator.animateCaptionHandleAlpha(startValue = 0f, endValue = 1f)
+ animateCaptionHandleAlpha(startValue = 0f, endValue = 1f)
}
private fun createStatusBarInputLayer(handlePosition: Point,
@@ -237,16 +240,6 @@ internal class AppHandleViewHolder(
}
}
- private fun setVisibility(visible: Boolean) {
- val v = if (visible) View.VISIBLE else View.GONE
- if (captionView.visibility == v) return
- if (!DesktopModeFlags.ENABLE_DESKTOP_APP_HANDLE_ANIMATION.isTrue()) {
- captionView.visibility = v
- return
- }
- animator.animateVisibilityChange(v)
- }
-
private fun getCaptionHandleBarColor(taskInfo: RunningTaskInfo): Int {
return if (shouldUseLightCaptionColors(taskInfo)) {
context.getColor(R.color.desktop_mode_caption_handle_bar_light)
@@ -272,7 +265,15 @@ internal class AppHandleViewHolder(
} ?: false
}
- override fun close() {
- animator.cancel()
+ /** 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()
}
+
+ override fun close() {}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index d8d043eac1ee..a2927fa3527b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -1186,6 +1186,11 @@ public class WindowDecorationTests extends ShellTestCase {
}
@Override
+ int getCaptionViewId() {
+ return R.id.caption;
+ }
+
+ @Override
TestView inflateLayout(Context context, int layoutResId) {
if (layoutResId == R.layout.caption_layout) {
return mMockView;