Merge "Dispatch separate navigation bar frame to IME"
This commit is contained in:
@@ -1244,6 +1244,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
return mDisplayRotation;
|
||||
}
|
||||
|
||||
void setInsetProvider(@InternalInsetsType int type, WindowState win,
|
||||
@Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider){
|
||||
setInsetProvider(type, win, frameProvider, null /* imeFrameProvider */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks a window as providing insets for the rest of the windows in the system.
|
||||
*
|
||||
@@ -1251,10 +1256,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
* @param win The window.
|
||||
* @param frameProvider Function to compute the frame, or {@code null} if the just the frame of
|
||||
* the window should be taken.
|
||||
* @param imeFrameProvider Function to compute the frame when dispatching insets to the IME, or
|
||||
* {@code null} if the normal frame should be taken.
|
||||
*/
|
||||
void setInsetProvider(@InternalInsetsType int type, WindowState win,
|
||||
@Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) {
|
||||
mInsetsStateController.getSourceProvider(type).setWindow(win, frameProvider);
|
||||
@Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider,
|
||||
@Nullable TriConsumer<DisplayFrames, WindowState, Rect> imeFrameProvider) {
|
||||
mInsetsStateController.getSourceProvider(type).setWindow(win, frameProvider,
|
||||
imeFrameProvider);
|
||||
}
|
||||
|
||||
InsetsStateController getInsetsStateController() {
|
||||
@@ -3283,7 +3292,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
}
|
||||
computeImeTarget(true /* updateImeTarget */);
|
||||
mInsetsStateController.getSourceProvider(ITYPE_IME).setWindow(win,
|
||||
null /* frameProvider */);
|
||||
null /* frameProvider */, null /* imeFrameProvider */);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1026,7 +1026,12 @@ public class DisplayPolicy {
|
||||
- getNavigationBarHeight(displayFrames.mRotation,
|
||||
mDisplayContent.getConfiguration().uiMode);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// For IME we use regular frame.
|
||||
(displayFrames, windowState, inOutFrame) ->
|
||||
inOutFrame.set(windowState.getFrameLw()));
|
||||
|
||||
mDisplayContent.setInsetProvider(ITYPE_BOTTOM_GESTURES, win,
|
||||
(displayFrames, windowState, inOutFrame) -> {
|
||||
inOutFrame.top -= mBottomGestureAdditionalInset;
|
||||
|
||||
@@ -34,6 +34,7 @@ import android.util.proto.ProtoOutputStream;
|
||||
import android.view.InsetsSource;
|
||||
import android.view.InsetsSourceControl;
|
||||
import android.view.InsetsState;
|
||||
import android.view.InsetsState.InternalInsetsType;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SurfaceControl.Transaction;
|
||||
|
||||
@@ -61,6 +62,8 @@ class InsetsSourceProvider {
|
||||
|
||||
private @Nullable ControlAdapter mAdapter;
|
||||
private TriConsumer<DisplayFrames, WindowState, Rect> mFrameProvider;
|
||||
private TriConsumer<DisplayFrames, WindowState, Rect> mImeFrameProvider;
|
||||
private final Rect mImeOverrideFrame = new Rect();
|
||||
|
||||
/** The visibility override from the current controlling window. */
|
||||
private boolean mClientVisible;
|
||||
@@ -111,9 +114,12 @@ class InsetsSourceProvider {
|
||||
* @param win The window that links to this source.
|
||||
* @param frameProvider Based on display frame state and the window, calculates the resulting
|
||||
* frame that should be reported to clients.
|
||||
* @param imeFrameProvider Based on display frame state and the window, calculates the resulting
|
||||
* frame that should be reported to IME.
|
||||
*/
|
||||
void setWindow(@Nullable WindowState win,
|
||||
@Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) {
|
||||
@Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider,
|
||||
@Nullable TriConsumer<DisplayFrames, WindowState, Rect> imeFrameProvider) {
|
||||
if (mWin != null) {
|
||||
if (mControllable) {
|
||||
mWin.setControllableInsetProvider(null);
|
||||
@@ -126,6 +132,7 @@ class InsetsSourceProvider {
|
||||
}
|
||||
mWin = win;
|
||||
mFrameProvider = frameProvider;
|
||||
mImeFrameProvider = imeFrameProvider;
|
||||
if (win == null) {
|
||||
setServerVisible(false);
|
||||
mSource.setFrame(new Rect());
|
||||
@@ -162,6 +169,12 @@ class InsetsSourceProvider {
|
||||
}
|
||||
mSource.setFrame(mTmpRect);
|
||||
|
||||
if (mImeFrameProvider != null) {
|
||||
mImeOverrideFrame.set(mWin.getFrameLw());
|
||||
mImeFrameProvider.accept(mWin.getDisplayContent().mDisplayFrames, mWin,
|
||||
mImeOverrideFrame);
|
||||
}
|
||||
|
||||
if (mWin.mGivenVisibleInsets.left != 0 || mWin.mGivenVisibleInsets.top != 0
|
||||
|| mWin.mGivenVisibleInsets.right != 0 || mWin.mGivenVisibleInsets.bottom != 0) {
|
||||
mTmpRect.set(mWin.getFrameLw());
|
||||
@@ -303,6 +316,21 @@ class InsetsSourceProvider {
|
||||
return sNewInsetsMode == NEW_INSETS_MODE_NONE || mClientVisible;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether this provider uses a different frame to dispatch to the IME.
|
||||
*/
|
||||
boolean overridesImeFrame() {
|
||||
return mImeFrameProvider != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Rect to dispatch to the IME as frame. Only valid if {@link #overridesImeFrame()}
|
||||
* returns {@code true}.
|
||||
*/
|
||||
Rect getImeOverrideFrame() {
|
||||
return mImeOverrideFrame;
|
||||
}
|
||||
|
||||
private class ControlAdapter implements AnimationAdapter {
|
||||
|
||||
private SurfaceControl mCapturedLeash;
|
||||
|
||||
@@ -88,6 +88,20 @@ class InsetsStateController {
|
||||
state.removeSource(ITYPE_IME);
|
||||
state.removeSource(ITYPE_STATUS_BAR);
|
||||
}
|
||||
|
||||
// IME needs different frames for certain cases (e.g. navigation bar in gesture nav).
|
||||
if (type == ITYPE_IME) {
|
||||
for (int i = mProviders.size() - 1; i >= 0; i--) {
|
||||
InsetsSourceProvider otherProvider = mProviders.valueAt(i);
|
||||
if (otherProvider.overridesImeFrame()) {
|
||||
InsetsSource override =
|
||||
new InsetsSource(state.getSource(otherProvider.getSource().getType()));
|
||||
override.setFrame(otherProvider.getImeOverrideFrame());
|
||||
state.addSource(override);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ public class InsetsSourceProviderTest extends WindowTestsBase {
|
||||
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
|
||||
statusBar.getFrameLw().set(0, 0, 500, 100);
|
||||
statusBar.mHasSurface = true;
|
||||
mProvider.setWindow(statusBar, null);
|
||||
mProvider.setWindow(statusBar, null, null);
|
||||
mProvider.onPostLayout();
|
||||
assertEquals(new Rect(0, 0, 500, 100), mProvider.getSource().getFrame());
|
||||
assertEquals(Insets.of(0, 100, 0, 0),
|
||||
@@ -74,7 +74,7 @@ public class InsetsSourceProviderTest extends WindowTestsBase {
|
||||
ime.getGivenContentInsetsLw().set(0, 0, 0, 60);
|
||||
ime.getGivenVisibleInsetsLw().set(0, 0, 0, 75);
|
||||
ime.mHasSurface = true;
|
||||
mProvider.setWindow(ime, null);
|
||||
mProvider.setWindow(ime, null, null);
|
||||
mProvider.onPostLayout();
|
||||
assertEquals(new Rect(0, 0, 500, 40), mProvider.getSource().getFrame());
|
||||
assertEquals(new Rect(0, 0, 500, 25), mProvider.getSource().getVisibleFrame());
|
||||
@@ -89,7 +89,7 @@ public class InsetsSourceProviderTest extends WindowTestsBase {
|
||||
public void testPostLayout_invisible() {
|
||||
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
|
||||
statusBar.getFrameLw().set(0, 0, 500, 100);
|
||||
mProvider.setWindow(statusBar, null);
|
||||
mProvider.setWindow(statusBar, null, null);
|
||||
mProvider.onPostLayout();
|
||||
assertEquals(Insets.NONE, mProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500),
|
||||
false /* ignoreVisibility */));
|
||||
@@ -102,7 +102,7 @@ public class InsetsSourceProviderTest extends WindowTestsBase {
|
||||
mProvider.setWindow(statusBar,
|
||||
(displayFrames, windowState, rect) -> {
|
||||
rect.set(10, 10, 20, 20);
|
||||
});
|
||||
}, null);
|
||||
mProvider.onPostLayout();
|
||||
assertEquals(new Rect(10, 10, 20, 20), mProvider.getSource().getFrame());
|
||||
}
|
||||
@@ -112,7 +112,7 @@ public class InsetsSourceProviderTest extends WindowTestsBase {
|
||||
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
|
||||
final WindowState target = createWindow(null, TYPE_APPLICATION, "target");
|
||||
statusBar.getFrameLw().set(0, 0, 500, 100);
|
||||
mProvider.setWindow(statusBar, null);
|
||||
mProvider.setWindow(statusBar, null, null);
|
||||
mProvider.updateControlForTarget(target, false /* force */);
|
||||
assertNotNull(mProvider.getControl(target));
|
||||
mProvider.updateControlForTarget(null, false /* force */);
|
||||
@@ -124,7 +124,7 @@ public class InsetsSourceProviderTest extends WindowTestsBase {
|
||||
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
|
||||
final WindowState target = createWindow(null, TYPE_APPLICATION, "target");
|
||||
statusBar.getFrameLw().set(0, 0, 500, 100);
|
||||
mProvider.setWindow(statusBar, null);
|
||||
mProvider.setWindow(statusBar, null, null);
|
||||
mProvider.updateControlForFakeTarget(target);
|
||||
assertNotNull(mProvider.getControl(target));
|
||||
assertNull(mProvider.getControl(target).getLeash());
|
||||
@@ -137,7 +137,7 @@ public class InsetsSourceProviderTest extends WindowTestsBase {
|
||||
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
|
||||
final WindowState target = createWindow(null, TYPE_APPLICATION, "target");
|
||||
statusBar.getFrameLw().set(0, 0, 500, 100);
|
||||
mProvider.setWindow(statusBar, null);
|
||||
mProvider.setWindow(statusBar, null, null);
|
||||
mProvider.updateControlForTarget(target, false /* force */);
|
||||
InsetsState state = new InsetsState();
|
||||
state.getSource(ITYPE_STATUS_BAR).setVisible(false);
|
||||
@@ -150,7 +150,7 @@ public class InsetsSourceProviderTest extends WindowTestsBase {
|
||||
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
|
||||
final WindowState target = createWindow(null, TYPE_APPLICATION, "target");
|
||||
statusBar.getFrameLw().set(0, 0, 500, 100);
|
||||
mProvider.setWindow(statusBar, null);
|
||||
mProvider.setWindow(statusBar, null, null);
|
||||
InsetsState state = new InsetsState();
|
||||
state.getSource(ITYPE_STATUS_BAR).setVisible(false);
|
||||
mProvider.onInsetsModified(target, state.getSource(ITYPE_STATUS_BAR));
|
||||
|
||||
@@ -21,26 +21,26 @@ import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
|
||||
import static android.view.InsetsState.ITYPE_STATUS_BAR;
|
||||
import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.view.InsetsSource;
|
||||
import android.view.InsetsSourceControl;
|
||||
import android.view.InsetsState;
|
||||
import android.view.test.InsetsModeSession;
|
||||
|
||||
import androidx.test.filters.FlakyTest;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import androidx.test.filters.FlakyTest;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
@SmallTest
|
||||
@FlakyTest(detail = "Promote to pre-submit once confirmed stable.")
|
||||
@Presubmit
|
||||
@@ -65,7 +65,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
|
||||
public void testStripForDispatch_notOwn() {
|
||||
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
|
||||
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
|
||||
getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null);
|
||||
getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
|
||||
statusBar.setControllableInsetProvider(getController().getSourceProvider(ITYPE_STATUS_BAR));
|
||||
assertNotNull(getController().getInsetsForDispatch(app).getSource(ITYPE_STATUS_BAR));
|
||||
}
|
||||
@@ -74,7 +74,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
|
||||
public void testStripForDispatch_own() {
|
||||
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
|
||||
mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR)
|
||||
.setWindow(statusBar, null);
|
||||
.setWindow(statusBar, null, null);
|
||||
statusBar.setControllableInsetProvider(getController().getSourceProvider(ITYPE_STATUS_BAR));
|
||||
final InsetsState state = getController().getInsetsForDispatch(statusBar);
|
||||
for (int i = state.getSourcesCount() - 1; i >= 0; i--) {
|
||||
@@ -88,19 +88,36 @@ public class InsetsStateControllerTest extends WindowTestsBase {
|
||||
final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar");
|
||||
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
|
||||
final WindowState ime = createWindow(null, TYPE_APPLICATION, "ime");
|
||||
getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null);
|
||||
getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null);
|
||||
getController().getSourceProvider(ITYPE_IME).setWindow(ime, null);
|
||||
getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
|
||||
getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null, null);
|
||||
getController().getSourceProvider(ITYPE_IME).setWindow(ime, null, null);
|
||||
assertEquals(0, getController().getInsetsForDispatch(navBar).getSourcesCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImeForDispatch() {
|
||||
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
|
||||
final WindowState ime = createWindow(null, TYPE_APPLICATION, "ime");
|
||||
InsetsSourceProvider statusBarProvider =
|
||||
getController().getSourceProvider(ITYPE_STATUS_BAR);
|
||||
statusBarProvider.setWindow(statusBar, null, ((displayFrames, windowState, rect) ->
|
||||
rect.set(0, 1, 2, 3)));
|
||||
getController().getSourceProvider(ITYPE_IME).setWindow(ime, null, null);
|
||||
statusBar.setControllableInsetProvider(statusBarProvider);
|
||||
|
||||
statusBarProvider.onPostLayout();
|
||||
|
||||
final InsetsState state = getController().getInsetsForDispatch(ime);
|
||||
assertEquals(new Rect(0, 1, 2, 3), state.getSource(ITYPE_STATUS_BAR).getFrame());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBarControllingWinChanged() {
|
||||
final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar");
|
||||
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
|
||||
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
|
||||
getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null);
|
||||
getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null);
|
||||
getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
|
||||
getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null, null);
|
||||
getController().onBarControlTargetChanged(app, null, app, null);
|
||||
InsetsSourceControl[] controls = getController().getControlsForDispatch(app);
|
||||
assertEquals(2, controls.length);
|
||||
@@ -110,7 +127,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
|
||||
public void testControlRevoked() {
|
||||
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
|
||||
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
|
||||
getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null);
|
||||
getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
|
||||
getController().onBarControlTargetChanged(app, null, null, null);
|
||||
assertNotNull(getController().getControlsForDispatch(app));
|
||||
getController().onBarControlTargetChanged(null, null, null, null);
|
||||
@@ -122,7 +139,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
|
||||
public void testControlRevoked_animation() {
|
||||
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
|
||||
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
|
||||
getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null);
|
||||
getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
|
||||
getController().onBarControlTargetChanged(app, null, null, null);
|
||||
assertNotNull(getController().getControlsForDispatch(app));
|
||||
statusBar.cancelAnimation();
|
||||
|
||||
@@ -425,7 +425,7 @@ public class WindowStateTests extends WindowTestsBase {
|
||||
statusBar.mHasSurface = true;
|
||||
assertTrue(statusBar.isVisible());
|
||||
mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR)
|
||||
.setWindow(statusBar, null /* frameProvider */);
|
||||
.setWindow(statusBar, null /* frameProvider */, null /* imeFrameProvider */);
|
||||
mDisplayContent.getInsetsStateController().onBarControlTargetChanged(
|
||||
app, null /* fakeTopControlling */, app, null /* fakeNavControlling */);
|
||||
final InsetsSource source = new InsetsSource(ITYPE_STATUS_BAR);
|
||||
|
||||
Reference in New Issue
Block a user