Move PiP swiftly in response to IME with keep clear areas flag enabled.

If the keep clear algorithm is enabled, PiP window will avoid the
keep clear areas and move away from occluding keyboard.

When IME is shown, we trigger the movement right away, for a smoother
experience.
If there is another animation ongoing, we delay moving PiP again, so
that it's more smooth overall.
Finally, we always apply gravity bottom with keep clear areas flag on,
so that it goes back down after IME dismiss.

Test: manually, http://recall/-/blXo3gy66k4fDYh7gFkrpe
Bug: 183746978

Change-Id: I32c52e4b6dd3c083b2168fda6a8b3b13facdac69
This commit is contained in:
Mateusz Cicheński
2022-09-14 17:52:20 +00:00
parent 66f5377be9
commit 62f6fe2294
4 changed files with 60 additions and 16 deletions

View File

@@ -324,6 +324,19 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
return mPipTransitionController;
}
/**
* Returns true if the PiP window is currently being animated.
*/
public boolean isAnimating() {
// TODO(b/183746978) move this to PipAnimationController, and inject that in PipController
PipAnimationController.PipTransitionAnimator animator =
mPipAnimationController.getCurrentAnimator();
if (animator != null && animator.isRunning()) {
return true;
}
return false;
}
public Rect getCurrentOrAnimatingBounds() {
PipAnimationController.PipTransitionAnimator animator =
mPipAnimationController.getCurrentAnimator();

View File

@@ -54,13 +54,8 @@ public class PhonePipKeepClearAlgorithm implements PipKeepClearAlgorithm {
? pipBoundsAlgorithm.getEntryDestinationBoundsIgnoringKeepClearAreas()
: pipBoundsState.getBounds();
float snapFraction = pipBoundsAlgorithm.getSnapFraction(startingBounds);
int verticalGravity;
int verticalGravity = Gravity.BOTTOM;
int horizontalGravity;
if (snapFraction < 1.5f || snapFraction >= 3.5f) {
verticalGravity = Gravity.NO_GRAVITY;
} else {
verticalGravity = Gravity.BOTTOM;
}
if (snapFraction >= 0.5f && snapFraction < 2.5f) {
horizontalGravity = Gravity.RIGHT;
} else {

View File

@@ -149,7 +149,42 @@ public class PipController implements PipTransitionController.PipTransitionCallb
private final Rect mTmpInsetBounds = new Rect();
private final int mEnterAnimationDuration;
private final Runnable mMovePipInResponseToKeepClearAreasChangeCallback;
private final Runnable mMovePipInResponseToKeepClearAreasChangeCallback =
this::onKeepClearAreasChangedCallback;
private void onKeepClearAreasChangedCallback() {
if (!mEnablePipKeepClearAlgorithm) {
// early bail out if the keep clear areas feature is disabled
return;
}
// if there is another animation ongoing, wait for it to finish and try again
if (mPipTaskOrganizer.isAnimating()) {
mMainExecutor.removeCallbacks(
mMovePipInResponseToKeepClearAreasChangeCallback);
mMainExecutor.executeDelayed(
mMovePipInResponseToKeepClearAreasChangeCallback,
PIP_KEEP_CLEAR_AREAS_DELAY);
return;
}
updatePipPositionForKeepClearAreas();
}
private void updatePipPositionForKeepClearAreas() {
if (!mEnablePipKeepClearAlgorithm) {
// early bail out if the keep clear areas feature is disabled
return;
}
// only move if already in pip, other transitions account for keep clear areas
if (mPipTransitionState.hasEnteredPip()) {
Rect destBounds = mPipKeepClearAlgorithm.adjust(mPipBoundsState,
mPipBoundsAlgorithm);
// only move if the bounds are actually different
if (destBounds != mPipBoundsState.getBounds()) {
mPipTaskOrganizer.scheduleAnimateResizePip(destBounds,
mEnterAnimationDuration, null);
}
}
}
private boolean mIsInFixedRotation;
private PipAnimationListener mPinnedStackAnimationRecentsCallback;
@@ -302,6 +337,9 @@ public class PipController implements PipTransitionController.PipTransitionCallb
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
mPipBoundsState.setImeVisibility(imeVisible, imeHeight);
mTouchHandler.onImeVisibilityChanged(imeVisible, imeHeight);
if (imeVisible) {
updatePipPositionForKeepClearAreas();
}
}
@Override
@@ -414,15 +452,6 @@ public class PipController implements PipTransitionController.PipTransitionCallb
mEnterAnimationDuration = mContext.getResources()
.getInteger(R.integer.config_pipEnterAnimationDuration);
mMovePipInResponseToKeepClearAreasChangeCallback = () -> {
// only move if already in pip, other transitions account for keep clear areas
if (mPipTransitionState.hasEnteredPip()) {
Rect destBounds = mPipKeepClearAlgorithm.adjust(mPipBoundsState,
mPipBoundsAlgorithm);
mPipTaskOrganizer.scheduleAnimateResizePip(destBounds,
mEnterAnimationDuration, null);
}
};
mPipParamsChangedForwarder = pipParamsChangedForwarder;
mDisplayInsetsController = displayInsetsController;

View File

@@ -34,6 +34,7 @@ import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.SystemProperties;
import android.provider.DeviceConfig;
import android.util.Size;
import android.view.DisplayCutout;
@@ -70,6 +71,9 @@ public class PipTouchHandler {
private static final String TAG = "PipTouchHandler";
private static final float DEFAULT_STASH_VELOCITY_THRESHOLD = 18000.f;
private static final boolean ENABLE_PIP_KEEP_CLEAR_ALGORITHM =
SystemProperties.getBoolean("persist.wm.debug.enable_pip_keep_clear_algorithm", false);
// Allow PIP to resize to a slightly bigger state upon touch
private boolean mEnableResize;
private final Context mContext;
@@ -426,6 +430,9 @@ public class PipTouchHandler {
if (mTouchState.isUserInteracting()) {
// Defer the update of the current movement bounds until after the user finishes
// touching the screen
} else if (ENABLE_PIP_KEEP_CLEAR_ALGORITHM) {
// Ignore moving PiP if keep clear algorithm is enabled, since IME and shelf height
// now are accounted for in the keep clear algorithm calculations
} else {
final boolean isExpanded = mMenuState == MENU_STATE_FULL && willResizeMenu();
final Rect toMovementBounds = new Rect();