Don't move PiP towards a corner after user manually moved it.

With keep clear areas flag on, PiP will gravitate towards one of the
bottom corners of the screen if possible. However, once a user moves
PiP manually, it will only continue to avoid occluding keep clear
areas, but no longer move downwards. This also happens if user resized
the window.

This can be disabled by turning the newly introduced sysprop flag.

Bug: 258529269
Test: manually

Change-Id: Ieaa292c54762d5cd005bcdf7eab48d6082e5c3a9
This commit is contained in:
Mateusz Cicheński
2022-11-30 01:16:34 +00:00
parent 2971d9f3e0
commit 76d2b200ae
3 changed files with 46 additions and 19 deletions

View File

@@ -97,6 +97,8 @@ public class PipBoundsState {
private int mShelfHeight;
/** Whether the user has resized the PIP manually. */
private boolean mHasUserResizedPip;
/** Whether the user has moved the PIP manually. */
private boolean mHasUserMovedPip;
/**
* Areas defined by currently visible apps that they prefer to keep clear from overlays such as
* the PiP. Restricted areas may only move the PiP a limited amount from its anchor position.
@@ -279,6 +281,7 @@ public class PipBoundsState {
if (changed) {
clearReentryState();
setHasUserResizedPip(false);
setHasUserMovedPip(false);
}
}
@@ -442,6 +445,16 @@ public class PipBoundsState {
mHasUserResizedPip = hasUserResizedPip;
}
/** Returns whether the user has moved the PIP. */
public boolean hasUserMovedPip() {
return mHasUserMovedPip;
}
/** Set whether the user has moved the PIP. */
public void setHasUserMovedPip(boolean hasUserMovedPip) {
mHasUserMovedPip = hasUserMovedPip;
}
/**
* Registers a callback when the minimal size of PIP that is set by the app changes.
*/
@@ -577,6 +590,8 @@ public class PipBoundsState {
pw.println(innerPrefix + "mImeHeight=" + mImeHeight);
pw.println(innerPrefix + "mIsShelfShowing=" + mIsShelfShowing);
pw.println(innerPrefix + "mShelfHeight=" + mShelfHeight);
pw.println(innerPrefix + "mHasUserMovedPip=" + mHasUserMovedPip);
pw.println(innerPrefix + "mHasUserResizedPip=" + mHasUserResizedPip);
if (mPipReentryState == null) {
pw.println(innerPrefix + "mPipReentryState=null");
} else {

View File

@@ -19,6 +19,7 @@ package com.android.wm.shell.pip.phone;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.os.SystemProperties;
import android.util.ArraySet;
import android.view.Gravity;
@@ -34,6 +35,10 @@ import java.util.Set;
*/
public class PhonePipKeepClearAlgorithm implements PipKeepClearAlgorithm {
private boolean mKeepClearAreaGravityEnabled =
SystemProperties.getBoolean(
"persist.wm.debug.enable_pip_keep_clear_algorithm_gravity", false);
protected int mKeepClearAreasPadding;
public PhonePipKeepClearAlgorithm(Context context) {
@@ -53,31 +58,36 @@ public class PhonePipKeepClearAlgorithm implements PipKeepClearAlgorithm {
Rect startingBounds = pipBoundsState.getBounds().isEmpty()
? pipBoundsAlgorithm.getEntryDestinationBoundsIgnoringKeepClearAreas()
: pipBoundsState.getBounds();
float snapFraction = pipBoundsAlgorithm.getSnapFraction(startingBounds);
int verticalGravity = Gravity.BOTTOM;
int horizontalGravity;
if (snapFraction >= 0.5f && snapFraction < 2.5f) {
horizontalGravity = Gravity.RIGHT;
} else {
horizontalGravity = Gravity.LEFT;
}
// push the bounds based on the gravity
Rect insets = new Rect();
pipBoundsAlgorithm.getInsetBounds(insets);
if (pipBoundsState.isImeShowing()) {
insets.bottom -= pipBoundsState.getImeHeight();
}
Rect pushedBounds = new Rect(startingBounds);
if (verticalGravity == Gravity.BOTTOM) {
pushedBounds.offsetTo(pushedBounds.left,
insets.bottom - pushedBounds.height());
Rect pipBounds = new Rect(startingBounds);
// move PiP towards corner if user hasn't moved it manually or the flag is on
if (mKeepClearAreaGravityEnabled
|| (!pipBoundsState.hasUserMovedPip() && !pipBoundsState.hasUserResizedPip())) {
float snapFraction = pipBoundsAlgorithm.getSnapFraction(startingBounds);
int verticalGravity = Gravity.BOTTOM;
int horizontalGravity;
if (snapFraction >= 0.5f && snapFraction < 2.5f) {
horizontalGravity = Gravity.RIGHT;
} else {
horizontalGravity = Gravity.LEFT;
}
if (verticalGravity == Gravity.BOTTOM) {
pipBounds.offsetTo(pipBounds.left,
insets.bottom - pipBounds.height());
}
if (horizontalGravity == Gravity.RIGHT) {
pipBounds.offsetTo(insets.right - pipBounds.width(), pipBounds.top);
} else {
pipBounds.offsetTo(insets.left, pipBounds.top);
}
}
if (horizontalGravity == Gravity.RIGHT) {
pushedBounds.offsetTo(insets.right - pushedBounds.width(), pushedBounds.top);
} else {
pushedBounds.offsetTo(insets.left, pushedBounds.top);
}
return findUnoccludedPosition(pushedBounds, pipBoundsState.getRestrictedKeepClearAreas(),
return findUnoccludedPosition(pipBounds, pipBoundsState.getRestrictedKeepClearAreas(),
pipBoundsState.getUnrestrictedKeepClearAreas(), insets);
}

View File

@@ -875,6 +875,8 @@ public class PipTouchHandler {
}
if (touchState.isDragging()) {
mPipBoundsState.setHasUserMovedPip(true);
// Move the pinned stack freely
final PointF lastDelta = touchState.getLastTouchDelta();
float lastX = mStartPosition.x + mDelta.x;