From c0eec05ed584c88c9543c60fdff166f3cbf72682 Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Fri, 6 Mar 2020 18:54:55 -0800 Subject: [PATCH] Fix up interractions between Adjust for IME and minimize These aren't compatible at the moment, but at the very least prevent them from running at the same time so that switching between secondary adjusted to recents works. This works by augmenting the divider's ime handling with a paused state. When paused, it will keep track of ime changes, but it won't apply them to the divider until it's resumed. Despite this, the interraction is still quite glitchy, but at least it ends up in the right end-states. A full fix for this will require a significant rewrite of the whole DividerView's bounds handling. Bug: 150781668 Test: Open 2 apps in splits. show IME in secondary, then swipe-up to recents. While not perfect, it should work. Change-Id: I4e7a6b9ed04b38edb83655b2326de4448124b904 --- .../systemui/stackdivider/Divider.java | 65 ++++++++++++++++--- .../systemui/stackdivider/DividerView.java | 40 +++++++----- 2 files changed, 79 insertions(+), 26 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java index ea5ec05030675..63bd076924fa8 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java @@ -173,6 +173,9 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, @Nullable private ValueAnimator mAnimation = null; + private boolean mPaused = true; + private boolean mPausedTargetAdjusted = false; + private boolean getSecondaryHasFocus(int displayId) { try { IWindowContainer imeSplit = ActivityTaskManager.getTaskOrganizerController() @@ -185,6 +188,14 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, return false; } + private void updateDimTargets() { + final boolean splitIsVisible = !mView.isHidden(); + mTargetPrimaryDim = (mSecondaryHasFocus && mTargetShown && splitIsVisible) + ? ADJUSTED_NONFOCUS_DIM : 0.f; + mTargetSecondaryDim = (!mSecondaryHasFocus && mTargetShown && splitIsVisible) + ? ADJUSTED_NONFOCUS_DIM : 0.f; + } + @Override public void onImeStartPositioning(int displayId, int hiddenTop, int shownTop, boolean imeShouldShow, SurfaceControl.Transaction t) { @@ -193,7 +204,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, } final boolean splitIsVisible = !mView.isHidden(); mSecondaryHasFocus = getSecondaryHasFocus(displayId); - mTargetAdjusted = splitIsVisible && imeShouldShow && mSecondaryHasFocus + final boolean targetAdjusted = splitIsVisible && imeShouldShow && mSecondaryHasFocus && !mSplitLayout.mDisplayLayout.isLandscape(); mHiddenTop = hiddenTop; mShownTop = shownTop; @@ -201,10 +212,12 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, if (mLastAdjustTop < 0) { mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop; } - mTargetPrimaryDim = (mSecondaryHasFocus && mTargetShown && splitIsVisible) - ? ADJUSTED_NONFOCUS_DIM : 0.f; - mTargetSecondaryDim = (!mSecondaryHasFocus && mTargetShown && splitIsVisible) - ? ADJUSTED_NONFOCUS_DIM : 0.f; + if (mPaused) { + mPausedTargetAdjusted = targetAdjusted; + return; + } + mTargetAdjusted = targetAdjusted; + updateDimTargets(); if (mAnimation != null || (mImeWasShown && imeShouldShow && mTargetAdjusted != mAdjusted)) { // We need to animate adjustment independently of the IME position, so @@ -259,7 +272,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, @Override public void onImePositionChanged(int displayId, int imeTop, SurfaceControl.Transaction t) { - if (mAnimation != null || !inSplitMode()) { + if (mAnimation != null || !inSplitMode() || mPaused) { // Not synchronized with IME anymore, so return. return; } @@ -271,7 +284,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, @Override public void onImeEndPositioning(int displayId, boolean cancelled, SurfaceControl.Transaction t) { - if (mAnimation != null || !inSplitMode()) { + if (mAnimation != null || !inSplitMode() || mPaused) { // Not synchronized with IME anymore, so return. return; } @@ -279,7 +292,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, } private void onProgress(float progress, SurfaceControl.Transaction t) { - if (mTargetAdjusted != mAdjusted) { + if (mTargetAdjusted != mAdjusted && !mPaused) { final float fraction = mTargetAdjusted ? progress : 1.f - progress; mLastAdjustTop = (int) (fraction * mShownTop + (1.f - fraction) * mHiddenTop); mSplitLayout.updateAdjustedBounds(mLastAdjustTop, mHiddenTop, mShownTop); @@ -342,6 +355,32 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, }); mAnimation.start(); } + + /** Completely aborts/resets adjustment state */ + public void pause(int displayId) { + mHandler.post(() -> { + mPaused = true; + mPausedTargetAdjusted = mTargetAdjusted; + mTargetAdjusted = false; + mTargetPrimaryDim = mTargetSecondaryDim = 0.f; + updateImeAdjustState(); + startAsyncAnimation(); + }); + } + + public void resume(int displayId) { + mHandler.post(() -> { + mPaused = false; + mTargetAdjusted = mPausedTargetAdjusted; + updateDimTargets(); + if (mTargetAdjusted && mView != null) { + // End unminimize animations since they conflict with adjustment animations. + mView.finishAnimations(); + } + updateImeAdjustState(); + startAsyncAnimation(); + }); + } } private final DividerImeController mImePositionProcessor = new DividerImeController(); @@ -544,7 +583,17 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, // Sync state to DividerView if it exists. if (mView != null) { + final int displayId = mView.getDisplay() != null + ? mView.getDisplay().getDisplayId() : DEFAULT_DISPLAY; + // pause ime here (before updateMinimizedDockedStack) + if (mMinimized) { + mImePositionProcessor.pause(displayId); + } mView.setMinimizedDockStack(minimized, getAnimDuration(), homeStackResizable); + if (!mMinimized) { + // afterwards so it can end any animations started in view + mImePositionProcessor.resume(displayId); + } } updateTouchable(); WindowManagerProxy.applyContainerTransaction(wct); diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 4114bb9d055da..0d6403d94515f 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -67,6 +67,8 @@ import com.android.systemui.R; import com.android.systemui.shared.system.WindowManagerWrapper; import com.android.systemui.statusbar.FlingAnimationUtils; +import java.util.function.Consumer; + /** * Docked stack divider. */ @@ -634,16 +636,20 @@ public class DividerView extends FrameLayout implements OnTouchListener, ? TASK_POSITION_SAME : snapTarget.taskPosition, snapTarget)); - Runnable endAction = () -> { + Consumer endAction = cancelled -> { + final boolean wasMinimizeInteraction = mIsInMinimizeInteraction; + // Reset minimized divider position after unminimized state animation finishes. + if (!cancelled && !mDockedStackMinimized && mIsInMinimizeInteraction) { + mIsInMinimizeInteraction = false; + } boolean dismissed = commitSnapFlags(snapTarget); mWindowManagerProxy.setResizing(false); updateDockSide(); mCurrentAnimator = null; mEntranceAnimationRunning = false; mExitAnimationRunning = false; - if (!dismissed) { - WindowManagerProxy.applyResizeSplits((mIsInMinimizeInteraction - ? mSnapTargetBeforeMinimized : snapTarget).position, mSplitLayout); + if (!dismissed && !wasMinimizeInteraction) { + WindowManagerProxy.applyResizeSplits(snapTarget.position, mSplitLayout); } if (mCallback != null) { mCallback.onDraggingEnd(); @@ -667,12 +673,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, } } }; - Runnable notCancelledEndAction = () -> { - // Reset minimized divider position after unminimized state animation finishes - if (!mDockedStackMinimized && mIsInMinimizeInteraction) { - mIsInMinimizeInteraction = false; - } - }; anim.addListener(new AnimatorListenerAdapter() { private boolean mCancelled; @@ -694,15 +694,10 @@ public class DividerView extends FrameLayout implements OnTouchListener, delay = mSfChoreographer.getSurfaceFlingerOffsetMs(); } if (delay == 0) { - if (!mCancelled) { - notCancelledEndAction.run(); - } - endAction.run(); + endAction.accept(mCancelled); } else { - if (!mCancelled) { - mHandler.postDelayed(notCancelledEndAction, delay); - } - mHandler.postDelayed(endAction, delay); + final Boolean cancelled = mCancelled; + mHandler.postDelayed(() -> endAction.accept(cancelled), delay); } } }); @@ -946,6 +941,15 @@ public class DividerView extends FrameLayout implements OnTouchListener, .start(); } + // Needed to end any currently playing animations when they might compete with other anims + // (specifically, IME adjust animation immediately after leaving minimized). Someday maybe + // these can be unified, but not today. + void finishAnimations() { + if (mCurrentAnimator != null) { + mCurrentAnimator.end(); + } + } + public void setAdjustedForIme(boolean adjustedForIme, long animDuration) { if (mAdjustedForIme == adjustedForIme) { return;