From 2d886505bbe6f2f6f6fd7058f6f707b182d580ec Mon Sep 17 00:00:00 2001 From: Mady Mellor Date: Wed, 4 Aug 2021 16:46:20 -0700 Subject: [PATCH] Fix up back press with bubbles manage menu or user education If manage menu is open or user education for the manage menu is showing, hitting back would close the whole bubble. Instead it should just close the manage menu, or the user education view. Also fixed a couple of cases where user education should animate away. Test: manual - hit back while manage menu or manage menu user education is open, the bubble should stay open & the menu should hide. - hit back while stack education is open & check that back works normally after it goes away Bug: 195556909 Change-Id: I60f2bedbf5dd45847139c4e89c900ee7cc54318f --- .../wm/shell/bubbles/BubbleController.java | 12 +++++-- .../wm/shell/bubbles/BubbleExpandedView.java | 2 +- .../bubbles/BubbleOverflowContainerView.java | 4 +-- .../wm/shell/bubbles/BubbleStackView.java | 26 ++++++++++++-- .../wm/shell/bubbles/StackEducationView.kt | 34 ++++++++++++++++++- 5 files changed, 68 insertions(+), 10 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java index e7764ea1a21e6..95b80df7fcbd2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java @@ -636,10 +636,16 @@ public class BubbleController { } } - /** For the overflow to be focusable & receive key events the flags must be update. **/ - void updateWindowFlagsForOverflow(boolean showingOverflow) { + /** + * In some situations bubble's should be able to receive key events for back: + * - when the bubble overflow is showing + * - when the user education for the stack is showing. + * + * @param interceptBack whether back should be intercepted or not. + */ + void updateWindowFlagsForBackpress(boolean interceptBack) { if (mStackView != null && mAddedToWindowManager) { - mWmLayoutParams.flags = showingOverflow + mWmLayoutParams.flags = interceptBack ? 0 : WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java index 252b588ec63f9..4ac7dcf3d23a1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java @@ -228,7 +228,7 @@ public class BubbleExpandedView extends LinearLayout { @Override public void onBackPressedOnTaskRoot(int taskId) { if (mTaskId == taskId && mStackView.isExpanded()) { - mController.collapseStack(); + mStackView.onBackPressed(); } } }; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java index ede42285d9cdb..5e9d97f23c577 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java @@ -142,7 +142,7 @@ public class BubbleOverflowContainerView extends LinearLayout { super.onAttachedToWindow(); if (mController != null) { // For the overflow to get key events (e.g. back press) we need to adjust the flags - mController.updateWindowFlagsForOverflow(true); + mController.updateWindowFlagsForBackpress(true); } setOnKeyListener(mKeyListener); } @@ -151,7 +151,7 @@ public class BubbleOverflowContainerView extends LinearLayout { protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (mController != null) { - mController.updateWindowFlagsForOverflow(false); + mController.updateWindowFlagsForBackpress(false); } setOnKeyListener(null); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java index 9e108ea911c6b..3d2505ef76999 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java @@ -927,8 +927,10 @@ public class BubbleStackView extends FrameLayout setOnClickListener(view -> { if (mShowingManage) { showManageMenu(false /* show */); + } else if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) { + mManageEduView.hide(); } else if (mStackEduView != null && mStackEduView.getVisibility() == VISIBLE) { - mStackEduView.hide(false); + mStackEduView.hide(false /* isExpanding */); } else if (mBubbleData.isExpanded()) { mBubbleData.setExpanded(false); } @@ -1158,7 +1160,7 @@ public class BubbleStackView extends FrameLayout return false; } if (mStackEduView == null) { - mStackEduView = new StackEducationView(mContext, mPositioner); + mStackEduView = new StackEducationView(mContext, mPositioner, mBubbleController); addView(mStackEduView); } mBubbleContainer.bringToFront(); @@ -1169,7 +1171,7 @@ public class BubbleStackView extends FrameLayout private void updateUserEdu() { if (mStackEduView != null && mStackEduView.getVisibility() == VISIBLE) { removeView(mStackEduView); - mStackEduView = new StackEducationView(mContext, mPositioner); + mStackEduView = new StackEducationView(mContext, mPositioner, mBubbleController); addView(mStackEduView); mBubbleContainer.bringToFront(); // Stack appears on top of the stack education mStackEduView.show(mPositioner.getDefaultStartPosition()); @@ -1732,6 +1734,21 @@ public class BubbleStackView extends FrameLayout notifyExpansionChanged(mExpandedBubble, mIsExpanded); } + /** + * Called when back press occurs while bubbles are expanded. + */ + public void onBackPressed() { + if (mIsExpanded) { + if (mShowingManage) { + showManageMenu(false); + } else if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) { + mManageEduView.hide(); + } else { + setExpanded(false); + } + } + } + void setBubbleVisibility(Bubble b, boolean visible) { if (b.getIconView() != null) { b.getIconView().setVisibility(visible ? VISIBLE : GONE); @@ -1957,6 +1974,9 @@ public class BubbleStackView extends FrameLayout private void animateCollapse() { cancelDelayedExpandCollapseSwitchAnimations(); + if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) { + mManageEduView.hide(); + } // Hide the menu if it's visible. showManageMenu(false); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt index cb660004062dc..f6a90b7a76cda 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt @@ -18,8 +18,10 @@ package com.android.wm.shell.bubbles import android.content.Context import android.graphics.Color import android.graphics.PointF +import android.view.KeyEvent import android.view.LayoutInflater import android.view.View +import android.view.View.OnKeyListener import android.view.ViewGroup import android.widget.LinearLayout import android.widget.TextView @@ -31,7 +33,11 @@ import com.android.wm.shell.animation.Interpolators * User education view to highlight the collapsed stack of bubbles. * Shown only the first time a user taps the stack. */ -class StackEducationView constructor(context: Context, positioner: BubblePositioner) +class StackEducationView constructor( + context: Context, + positioner: BubblePositioner, + controller: BubbleController +) : LinearLayout(context) { private val TAG = if (BubbleDebugConfig.TAG_WITH_CLASS_NAME) "BubbleStackEducationView" @@ -41,6 +47,7 @@ class StackEducationView constructor(context: Context, positioner: BubblePositio private val ANIMATE_DURATION_SHORT: Long = 40 private val positioner: BubblePositioner = positioner + private val controller: BubbleController = controller private val view by lazy { findViewById(R.id.stack_education_layout) } private val titleTextView by lazy { findViewById(R.id.stack_education_title) } @@ -71,6 +78,28 @@ class StackEducationView constructor(context: Context, positioner: BubblePositio setTextColor() } + override fun onAttachedToWindow() { + super.onAttachedToWindow() + setFocusableInTouchMode(true) + setOnKeyListener(object : OnKeyListener { + override fun onKey(v: View?, keyCode: Int, event: KeyEvent): Boolean { + // if the event is a key down event on the enter button + if (event.action == KeyEvent.ACTION_UP && + keyCode == KeyEvent.KEYCODE_BACK && !isHiding) { + hide(false) + return true + } + return false + } + }) + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + setOnKeyListener(null) + controller.updateWindowFlagsForBackpress(false /* interceptBack */) + } + private fun setTextColor() { val ta = mContext.obtainStyledAttributes(intArrayOf(android.R.attr.colorAccent, android.R.attr.textColorPrimaryInverse)) @@ -98,6 +127,7 @@ class StackEducationView constructor(context: Context, positioner: BubblePositio fun show(stackPosition: PointF): Boolean { if (visibility == VISIBLE) return false + controller.updateWindowFlagsForBackpress(true /* interceptBack */) layoutParams.width = if (positioner.isLargeScreen) context.resources.getDimensionPixelSize( R.dimen.bubbles_user_education_width_large_screen) @@ -106,6 +136,7 @@ class StackEducationView constructor(context: Context, positioner: BubblePositio setAlpha(0f) setVisibility(View.VISIBLE) post { + requestFocus() with(view) { if (resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_LTR) { setPadding(positioner.bubbleSize + paddingRight, paddingTop, paddingRight, @@ -134,6 +165,7 @@ class StackEducationView constructor(context: Context, positioner: BubblePositio fun hide(isExpanding: Boolean) { if (visibility != VISIBLE || isHiding) return + controller.updateWindowFlagsForBackpress(false /* interceptBack */) animate() .alpha(0f) .setDuration(if (isExpanding) ANIMATE_DURATION_SHORT else ANIMATE_DURATION)