Merge "Force showing navigation bar while IME is visible" into sc-dev
This commit is contained in:
@@ -86,6 +86,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
|
|||||||
private final InsetsState mInitialInsetsState;
|
private final InsetsState mInitialInsetsState;
|
||||||
private final @AnimationType int mAnimationType;
|
private final @AnimationType int mAnimationType;
|
||||||
private final @InsetsType int mTypes;
|
private final @InsetsType int mTypes;
|
||||||
|
private @InsetsType int mControllingTypes;
|
||||||
private final InsetsAnimationControlCallbacks mController;
|
private final InsetsAnimationControlCallbacks mController;
|
||||||
private final WindowInsetsAnimation mAnimation;
|
private final WindowInsetsAnimation mAnimation;
|
||||||
/** @see WindowInsetsAnimationController#hasZeroInsetsIme */
|
/** @see WindowInsetsAnimationController#hasZeroInsetsIme */
|
||||||
@@ -112,6 +113,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
|
|||||||
mControls = controls;
|
mControls = controls;
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
mTypes = types;
|
mTypes = types;
|
||||||
|
mControllingTypes = types;
|
||||||
mController = controller;
|
mController = controller;
|
||||||
mInitialInsetsState = new InsetsState(state, true /* copySources */);
|
mInitialInsetsState = new InsetsState(state, true /* copySources */);
|
||||||
if (frame != null) {
|
if (frame != null) {
|
||||||
@@ -186,6 +188,16 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
|
|||||||
return mTypes;
|
return mTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getControllingTypes() {
|
||||||
|
return mControllingTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyControlRevoked(@InsetsType int types) {
|
||||||
|
mControllingTypes &= ~types;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @AnimationType int getAnimationType() {
|
public @AnimationType int getAnimationType() {
|
||||||
return mAnimationType;
|
return mAnimationType;
|
||||||
|
|||||||
@@ -29,10 +29,21 @@ import android.view.WindowInsets.Type.InsetsType;
|
|||||||
public interface InsetsAnimationControlRunner {
|
public interface InsetsAnimationControlRunner {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The {@link InsetsType} the animation of this runner is controlling.
|
* @return The {@link InsetsType} the animation of this runner controls.
|
||||||
*/
|
*/
|
||||||
@InsetsType int getTypes();
|
@InsetsType int getTypes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The {@link InsetsType} the animation of this runner is controlling. This can be
|
||||||
|
* changed if a control is revoked.
|
||||||
|
*/
|
||||||
|
@InsetsType int getControllingTypes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies {@link InsetsType types} of control are getting revoked.
|
||||||
|
*/
|
||||||
|
void notifyControlRevoked(@InsetsType int types);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancels the animation.
|
* Cancels the animation.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -139,6 +139,17 @@ public class InsetsAnimationThreadControlRunner implements InsetsAnimationContro
|
|||||||
return mControl.getTypes();
|
return mControl.getTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@UiThread
|
||||||
|
public int getControllingTypes() {
|
||||||
|
return mControl.getControllingTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyControlRevoked(@InsetsType int types) {
|
||||||
|
mControl.notifyControlRevoked(types);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@UiThread
|
@UiThread
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
|
|||||||
@@ -1224,9 +1224,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
|||||||
}
|
}
|
||||||
|
|
||||||
void notifyControlRevoked(InsetsSourceConsumer consumer) {
|
void notifyControlRevoked(InsetsSourceConsumer consumer) {
|
||||||
|
final @InsetsType int types = toPublicType(consumer.getType());
|
||||||
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
|
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
|
||||||
InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner;
|
InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner;
|
||||||
if ((control.getTypes() & toPublicType(consumer.getType())) != 0) {
|
control.notifyControlRevoked(types);
|
||||||
|
if (control.getControllingTypes() == 0) {
|
||||||
cancelAnimation(control, true /* invokeCallback */);
|
cancelAnimation(control, true /* invokeCallback */);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
|||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
|
||||||
import static android.view.InsetsController.ANIMATION_TYPE_HIDE;
|
import static android.view.InsetsController.ANIMATION_TYPE_HIDE;
|
||||||
import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
|
import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
|
||||||
|
import static android.view.InsetsState.ITYPE_IME;
|
||||||
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
|
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
|
||||||
import static android.view.InsetsState.ITYPE_STATUS_BAR;
|
import static android.view.InsetsState.ITYPE_STATUS_BAR;
|
||||||
import static android.view.SyncRtSurfaceTransactionApplier.applyParams;
|
import static android.view.SyncRtSurfaceTransactionApplier.applyParams;
|
||||||
@@ -207,7 +208,8 @@ class InsetsPolicy {
|
|||||||
*/
|
*/
|
||||||
InsetsState getInsetsForWindow(WindowState target) {
|
InsetsState getInsetsForWindow(WindowState target) {
|
||||||
final InsetsState originalState = mStateController.getInsetsForWindow(target);
|
final InsetsState originalState = mStateController.getInsetsForWindow(target);
|
||||||
return adjustVisibilityForTransientTypes(originalState);
|
final InsetsState state = adjustVisibilityForTransientTypes(originalState);
|
||||||
|
return target.mIsImWindow ? adjustVisibilityForIme(state, state == originalState) : state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -237,6 +239,20 @@ class InsetsPolicy {
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Navigation bar insets is always visible to IME.
|
||||||
|
private static InsetsState adjustVisibilityForIme(InsetsState originalState,
|
||||||
|
boolean copyState) {
|
||||||
|
final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR);
|
||||||
|
if (originalNavSource != null && !originalNavSource.isVisible()) {
|
||||||
|
final InsetsState state = copyState ? new InsetsState(originalState) : originalState;
|
||||||
|
final InsetsSource navSource = new InsetsSource(originalNavSource);
|
||||||
|
navSource.setVisible(true);
|
||||||
|
state.addSource(navSource);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
return originalState;
|
||||||
|
}
|
||||||
|
|
||||||
void onInsetsModified(InsetsControlTarget caller) {
|
void onInsetsModified(InsetsControlTarget caller) {
|
||||||
mStateController.onInsetsModified(caller);
|
mStateController.onInsetsModified(caller);
|
||||||
checkAbortTransient(caller);
|
checkAbortTransient(caller);
|
||||||
@@ -245,17 +261,21 @@ class InsetsPolicy {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a control target modified the insets state. If the target set a insets source to
|
* Called when a control target modified the insets state. If the target set a insets source to
|
||||||
* visible while it is shown transiently, we need to abort the transient state.
|
* visible while it is shown transiently, we need to abort the transient state. While IME is
|
||||||
|
* requested visible, we also need to abort the transient state of navigation bar if it is shown
|
||||||
|
* transiently.
|
||||||
*
|
*
|
||||||
* @param caller who changed the insets state.
|
* @param caller who changed the insets state.
|
||||||
*/
|
*/
|
||||||
private void checkAbortTransient(InsetsControlTarget caller) {
|
private void checkAbortTransient(InsetsControlTarget caller) {
|
||||||
if (mShowingTransientTypes.size() != 0) {
|
if (mShowingTransientTypes.size() != 0) {
|
||||||
IntArray abortTypes = new IntArray();
|
final IntArray abortTypes = new IntArray();
|
||||||
|
final boolean imeRequestedVisible = caller.getRequestedVisibility(ITYPE_IME);
|
||||||
for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
|
for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
|
||||||
final @InternalInsetsType int type = mShowingTransientTypes.get(i);
|
final @InternalInsetsType int type = mShowingTransientTypes.get(i);
|
||||||
if (mStateController.isFakeTarget(type, caller)
|
if ((mStateController.isFakeTarget(type, caller)
|
||||||
&& caller.getRequestedVisibility(type)) {
|
&& caller.getRequestedVisibility(type))
|
||||||
|
|| (type == ITYPE_NAVIGATION_BAR && imeRequestedVisible)) {
|
||||||
mShowingTransientTypes.remove(i);
|
mShowingTransientTypes.remove(i);
|
||||||
abortTypes.add(type);
|
abortTypes.add(type);
|
||||||
}
|
}
|
||||||
@@ -330,6 +350,11 @@ class InsetsPolicy {
|
|||||||
|
|
||||||
private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin,
|
private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin,
|
||||||
boolean forceShowsSystemBarsForWindowingMode) {
|
boolean forceShowsSystemBarsForWindowingMode) {
|
||||||
|
final WindowState imeWin = mDisplayContent.mInputMethodWindow;
|
||||||
|
if (imeWin != null && imeWin.isVisible()) {
|
||||||
|
// Force showing navigation bar while IME is visible.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) {
|
if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) {
|
||||||
return mDummyControlTarget;
|
return mDummyControlTarget;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
|
|||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
|
||||||
|
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
|
||||||
import static android.view.InsetsState.ITYPE_STATUS_BAR;
|
import static android.view.InsetsState.ITYPE_STATUS_BAR;
|
||||||
import static android.view.Surface.ROTATION_0;
|
import static android.view.Surface.ROTATION_0;
|
||||||
import static android.view.Surface.ROTATION_270;
|
import static android.view.Surface.ROTATION_270;
|
||||||
@@ -78,6 +79,7 @@ import android.os.RemoteException;
|
|||||||
import android.platform.test.annotations.Presubmit;
|
import android.platform.test.annotations.Presubmit;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.InputWindowHandle;
|
import android.view.InputWindowHandle;
|
||||||
|
import android.view.InsetsSource;
|
||||||
import android.view.InsetsState;
|
import android.view.InsetsState;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
@@ -880,6 +882,22 @@ public class WindowStateTests extends WindowTestsBase {
|
|||||||
verify(app).notifyInsetsChanged();
|
verify(app).notifyInsetsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseTestDisplay(addWindows = { W_INPUT_METHOD, W_ACTIVITY })
|
||||||
|
@Test
|
||||||
|
public void testImeAlwaysReceivesVisibleNavigationBarInsets() {
|
||||||
|
final InsetsSource navSource = new InsetsSource(ITYPE_NAVIGATION_BAR);
|
||||||
|
mImeWindow.mAboveInsetsState.addSource(navSource);
|
||||||
|
mAppWindow.mAboveInsetsState.addSource(navSource);
|
||||||
|
|
||||||
|
navSource.setVisible(false);
|
||||||
|
assertTrue(mImeWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
|
||||||
|
assertFalse(mAppWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
|
||||||
|
|
||||||
|
navSource.setVisible(true);
|
||||||
|
assertTrue(mImeWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
|
||||||
|
assertTrue(mAppWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
|
||||||
|
}
|
||||||
|
|
||||||
@UseTestDisplay(addWindows = { W_ACTIVITY })
|
@UseTestDisplay(addWindows = { W_ACTIVITY })
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateImeControlTargetWhenLeavingMultiWindow() {
|
public void testUpdateImeControlTargetWhenLeavingMultiWindow() {
|
||||||
|
|||||||
Reference in New Issue
Block a user