Update bubble bar location in shell

Send wmshell updates about bubble bar position when it is dragged
across the center divide.

Bug: 330585397
Flag: ACONFIG com.android.wm.shell.enable_bubble_bar DEVELOPMENT
Test: manual
  - with bubble bar on home screen
      - long press and drag bubble bar around on same side, no drop
        target
      - release the bubble bar, it snaps back to the original position
      - long press and drag bubble bar to other side, see drop target at
        the corner
      - release bubble bar, it snaps to the new side
      - long press and drag bubble bar to other side and back, see the
        drop target visible, release, snaps back to the original
        position
  - repeat above steps from an app, swipe up taskbar for bubble bar
Change-Id: I88faf641b9c07a19cfbb7a1feb8170a64269ac1f
This commit is contained in:
Ats Jenk
2024-03-29 09:53:59 -07:00
parent 1bc33421de
commit 2ae49c6cab
4 changed files with 137 additions and 21 deletions
@@ -220,7 +220,7 @@ public class BubbleBarController extends IBubblesListener.Stub {
mBubbleStashedHandleViewController.setHiddenForBubbles(
!sBubbleBarEnabled || mBubbles.isEmpty());
mBubbleBarViewController.setUpdateSelectedBubbleAfterCollapse(
key -> setSelectedBubble(mBubbles.get(key)));
key -> setSelectedBubbleInternal(mBubbles.get(key)));
});
}
@@ -390,7 +390,7 @@ public class BubbleBarController extends IBubblesListener.Stub {
}
}
if (bubbleToSelect != null) {
setSelectedBubble(bubbleToSelect);
setSelectedBubbleInternal(bubbleToSelect);
if (previouslySelectedBubble == null) {
mBubbleStashController.animateToInitialState(update.expanded);
}
@@ -409,8 +409,7 @@ public class BubbleBarController extends IBubblesListener.Stub {
if (update.bubbleBarLocation != mBubbleBarViewController.getBubbleBarLocation()) {
// Animate when receiving updates. Skip it if we received the initial state.
boolean animate = !update.initialState;
mBubbleBarViewController.setBubbleBarLocation(update.bubbleBarLocation, animate);
mBubbleStashController.setBubbleBarLocation(update.bubbleBarLocation);
updateBubbleBarLocationInternal(update.bubbleBarLocation, animate);
}
}
}
@@ -436,7 +435,7 @@ public class BubbleBarController extends IBubblesListener.Stub {
/** Updates the currently selected bubble for launcher views and tells WMShell to show it. */
public void showAndSelectBubble(BubbleBarItem b) {
if (DEBUG) Log.w(TAG, "showingSelectedBubble: " + b.getKey());
setSelectedBubble(b);
setSelectedBubbleInternal(b);
showSelectedBubble();
}
@@ -445,7 +444,7 @@ public class BubbleBarController extends IBubblesListener.Stub {
* WMShell that the selection has changed, that should go through either
* {@link #showSelectedBubble()} or {@link #showAndSelectBubble(BubbleBarItem)}.
*/
private void setSelectedBubble(BubbleBarItem b) {
private void setSelectedBubbleInternal(BubbleBarItem b) {
if (!Objects.equals(b, mSelectedBubble)) {
if (DEBUG) Log.w(TAG, "selectingBubble: " + b.getKey());
mSelectedBubble = b;
@@ -464,6 +463,21 @@ public class BubbleBarController extends IBubblesListener.Stub {
return null;
}
/**
* Set a new bubble bar location.
* <p>
* Updates the value locally in Launcher and in WMShell.
*/
public void updateBubbleBarLocation(BubbleBarLocation location) {
updateBubbleBarLocationInternal(location, false /* animate */);
mSystemUiProxy.setBubbleBarLocation(location);
}
private void updateBubbleBarLocationInternal(BubbleBarLocation location, boolean animate) {
mBubbleBarViewController.setBubbleBarLocation(location, animate);
mBubbleStashController.setBubbleBarLocation(location);
}
//
// Loading data for the bubbles
//
@@ -24,7 +24,9 @@ import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.PointF;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.LayoutDirection;
@@ -108,6 +110,7 @@ public class BubbleBarView extends FrameLayout {
private final float mIconSize;
// The elevation of the bubbles within the bar
private final float mBubbleElevation;
private final float mDragElevation;
private final int mPointerSize;
// Whether the bar is expanded (i.e. the bubble activity is being displayed).
@@ -138,11 +141,15 @@ public class BubbleBarView extends FrameLayout {
@Nullable
private Consumer<String> mUpdateSelectedBubbleAfterCollapse;
private boolean mDragging;
@Nullable
private BubbleView mDraggedBubbleView;
private int mPreviousLayoutDirection = LayoutDirection.UNDEFINED;
private boolean mLocationChangePending;
public BubbleBarView(Context context) {
this(context, null);
}
@@ -163,6 +170,7 @@ public class BubbleBarView extends FrameLayout {
mIconSpacing = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_spacing);
mIconSize = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_size);
mBubbleElevation = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_elevation);
mDragElevation = getResources().getDimensionPixelSize(R.dimen.bubblebar_drag_elevation);
mPointerSize = getResources().getDimensionPixelSize(R.dimen.bubblebar_pointer_size);
setClipToPadding(false);
@@ -237,12 +245,13 @@ public class BubbleBarView extends FrameLayout {
}
}
@SuppressLint("RtlHardcoded")
private void onBubbleBarLocationChanged() {
mLocationChangePending = false;
final boolean onLeft = mBubbleBarLocation.isOnLeft(isLayoutRtl());
mBubbleBarBackground.setAnchorLeft(onLeft);
mRelativePivotX = onLeft ? 0f : 1f;
ViewGroup.LayoutParams layoutParams = getLayoutParams();
if (layoutParams instanceof LayoutParams lp) {
if (getLayoutParams() instanceof LayoutParams lp) {
lp.gravity = Gravity.BOTTOM | (onLeft ? Gravity.LEFT : Gravity.RIGHT);
setLayoutParams(lp);
}
@@ -267,11 +276,82 @@ public class BubbleBarView extends FrameLayout {
}
}
/**
* Set whether this view is being currently being dragged
*/
public void setIsDragging(boolean dragging) {
if (mDragging == dragging) {
return;
}
mDragging = dragging;
setElevation(dragging ? mDragElevation : mBubbleElevation);
if (!dragging && mLocationChangePending) {
// During drag finish animation we may update the translation x value to shift the
// bubble to the new drop target. Clear the translation here.
setTranslationX(0f);
onBubbleBarLocationChanged();
}
}
/**
* Adjust resting position for the bubble bar while it is being dragged.
* <p>
* Bubble bar is laid out on left or right side of the screen. When it is being dragged to
* the opposite side, the resting position should be on that side. Calculate any additional
* translation that may be required to move the bubble bar to the new side.
*
* @param restingPosition relative resting position of the bubble bar from the laid out position
*/
@SuppressLint("RtlHardcoded")
void adjustRelativeRestingPosition(PointF restingPosition) {
final boolean locationOnLeft = mBubbleBarLocation.isOnLeft(isLayoutRtl());
// Bubble bar is placed left or right with gravity. Check where it is currently.
final int absoluteGravity = Gravity.getAbsoluteGravity(
((LayoutParams) getLayoutParams()).gravity, getLayoutDirection());
final boolean gravityOnLeft =
(absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.LEFT;
// Bubble bar is pinned to the same side per gravity and the desired location.
// Resting translation does not need to be adjusted.
if (locationOnLeft == gravityOnLeft) {
return;
}
// Bubble bar is laid out on left or right side of the screen. And the desired new
// location is on the other side. Calculate x translation value required to shift the
// bubble bar from one side to the other.
float x = getDistanceFromOtherSide();
if (locationOnLeft) {
// New location is on the left, shift left
// before -> |......ooo.| after -> |.ooo......|
restingPosition.x = -x;
} else {
// New location is on the right, shift right
// before -> |.ooo......| after -> |......ooo.|
restingPosition.x = x;
}
}
private float getDistanceFromOtherSide() {
// Calculate the shift needed to position the bubble bar on the other side
int displayWidth = getResources().getDisplayMetrics().widthPixels;
int margin = 0;
if (getLayoutParams() instanceof MarginLayoutParams lp) {
margin += lp.leftMargin;
margin += lp.rightMargin;
}
return (float) (displayWidth - getWidth() - margin);
}
private void setBubbleBarLocationInternal(BubbleBarLocation bubbleBarLocation) {
if (bubbleBarLocation != mBubbleBarLocation) {
mBubbleBarLocation = bubbleBarLocation;
onBubbleBarLocationChanged();
invalidate();
if (mDragging) {
mLocationChangePending = true;
} else {
onBubbleBarLocationChanged();
invalidate();
}
}
}
@@ -25,7 +25,6 @@ import android.view.ViewConfiguration;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.R;
import com.android.launcher3.taskbar.TaskbarActivityContext;
/**
@@ -55,9 +54,8 @@ public class BubbleDragController {
mBubbleBarViewController = bubbleControllers.bubbleBarViewController;
mBubbleDismissController = bubbleControllers.bubbleDismissController;
mBubbleBarPinController = bubbleControllers.bubbleBarPinController;
mBubbleBarPinController.setListener(location -> {
// TODO(b/330585397): update bubble bar location in shell
});
mBubbleBarPinController.setListener(
bubbleControllers.bubbleBarController::updateBubbleBarLocation);
mBubbleDismissController.setListener(
stuck -> mBubbleBarPinController.setDropTargetHidden(stuck));
}
@@ -96,11 +94,8 @@ public class BubbleDragController {
@SuppressLint("ClickableViewAccessibility")
public void setupBubbleBarView(@NonNull BubbleBarView bubbleBarView) {
PointF initialRelativePivot = new PointF();
final int restingElevation = bubbleBarView.getResources().getDimensionPixelSize(
R.dimen.bubblebar_elevation);
final int dragElevation = bubbleBarView.getResources().getDimensionPixelSize(
R.dimen.bubblebar_drag_elevation);
bubbleBarView.setOnTouchListener(new BubbleTouchListener() {
@Override
protected boolean onTouchDown(@NonNull View view, @NonNull MotionEvent event) {
if (bubbleBarView.isExpanded()) return false;
@@ -114,7 +109,7 @@ public class BubbleDragController {
// By default the bubble bar view pivot is in bottom right corner, while dragging
// it should be centered in order to align it with the dismiss target view
bubbleBarView.setRelativePivot(/* x = */ 0.5f, /* y = */ 0.5f);
bubbleBarView.setElevation(dragElevation);
bubbleBarView.setIsDragging(true);
mBubbleBarPinController.onDragStart(
bubbleBarView.getBubbleBarLocation().isOnLeft(bubbleBarView.isLayoutRtl()));
}
@@ -138,7 +133,14 @@ public class BubbleDragController {
void onDragEnd() {
// Restoring the initial pivot for the bubble bar view
bubbleBarView.setRelativePivot(initialRelativePivot.x, initialRelativePivot.y);
bubbleBarView.setElevation(restingElevation);
bubbleBarView.setIsDragging(false);
}
@Override
protected PointF getRestingPosition() {
PointF restingPosition = super.getRestingPosition();
bubbleBarView.adjustRelativeRestingPosition(restingPosition);
return restingPosition;
}
});
}
@@ -226,6 +228,13 @@ public class BubbleDragController {
protected void onDragDismiss() {
}
/**
* Get the resting position of the view when drag is released
*/
protected PointF getRestingPosition() {
return mViewInitialPosition;
}
@Override
@SuppressLint("ClickableViewAccessibility")
public boolean onTouch(@NonNull View view, @NonNull MotionEvent event) {
@@ -353,7 +362,7 @@ public class BubbleDragController {
mAnimator.animateDismiss(mViewInitialPosition, onComplete);
} else {
onDragRelease();
mAnimator.animateToInitialState(mViewInitialPosition, getCurrentVelocity(),
mAnimator.animateToInitialState(getRestingPosition(), getCurrentVelocity(),
onComplete);
}
mBubbleDismissController.hideDismissView();
@@ -82,6 +82,7 @@ import com.android.systemui.unfold.progress.IUnfoldTransitionListener;
import com.android.wm.shell.back.IBackAnimation;
import com.android.wm.shell.bubbles.IBubbles;
import com.android.wm.shell.bubbles.IBubblesListener;
import com.android.wm.shell.common.bubbles.BubbleBarLocation;
import com.android.wm.shell.common.pip.IPip;
import com.android.wm.shell.common.pip.IPipAnimationListener;
import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition;
@@ -808,6 +809,18 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle {
}
}
/**
* Tells SysUI to update the bubble bar location to the new location.
* @param location new location for the bubble bar
*/
public void setBubbleBarLocation(BubbleBarLocation location) {
try {
mBubbles.setBubbleBarLocation(location);
} catch (RemoteException e) {
Log.w(TAG, "Failed call setBubbleBarLocation");
}
}
//
// Splitscreen
//