Merge "Only give DisplayInsetsController control over IME in split-screen" into rvc-dev am: 7844ca2d72 am: 45047d66fc
Change-Id: I01cc87372ccdbce93a1438df698d96a95d5afdb2
This commit is contained in:
@@ -26,6 +26,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
|||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
||||||
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_SECONDARY;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
||||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
|
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
|
||||||
@@ -141,6 +142,7 @@ import android.annotation.NonNull;
|
|||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.ActivityManagerInternal;
|
import android.app.ActivityManagerInternal;
|
||||||
|
import android.app.WindowConfiguration;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
import android.content.pm.ActivityInfo.ScreenOrientation;
|
import android.content.pm.ActivityInfo.ScreenOrientation;
|
||||||
@@ -3370,34 +3372,18 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isImeControlledByApp() {
|
||||||
|
return mInputMethodTarget != null && !WindowConfiguration.isSplitScreenWindowingMode(
|
||||||
|
mInputMethodTarget.getWindowingMode());
|
||||||
|
}
|
||||||
|
|
||||||
boolean isImeAttachedToApp() {
|
boolean isImeAttachedToApp() {
|
||||||
return (mInputMethodTarget != null && mInputMethodTarget.mActivityRecord != null
|
return isImeControlledByApp()
|
||||||
|
&& mInputMethodTarget.mActivityRecord != null
|
||||||
&& mInputMethodTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
|
&& mInputMethodTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
|
||||||
// An activity with override bounds should be letterboxed inside its parent bounds,
|
// An activity with override bounds should be letterboxed inside its parent bounds,
|
||||||
// so it doesn't fill the screen.
|
// so it doesn't fill the screen.
|
||||||
&& mInputMethodTarget.mActivityRecord.matchParentBounds());
|
&& mInputMethodTarget.mActivityRecord.matchParentBounds();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get IME target that should host IME when this display that is reparented to another
|
|
||||||
* WindowState.
|
|
||||||
* IME is never displayed in a child display.
|
|
||||||
* Use {@link WindowState#getImeControlTarget()} when IME target window
|
|
||||||
* which originally called
|
|
||||||
* {@link android.view.inputmethod.InputMethodManager#showSoftInput(View, int)} is known.
|
|
||||||
*
|
|
||||||
* @return {@link WindowState} of host that controls IME.
|
|
||||||
* {@code null} when {@param dc} is not a virtual display.
|
|
||||||
* @see DisplayContent#reparent
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
WindowState getImeControlTarget() {
|
|
||||||
WindowState imeTarget = mInputMethodTarget;
|
|
||||||
if (imeTarget != null) {
|
|
||||||
return imeTarget.getImeControlTarget();
|
|
||||||
}
|
|
||||||
|
|
||||||
return getInsetsStateController().getImeSourceProvider().getControlTarget().getWindow();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -3407,7 +3393,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
*
|
*
|
||||||
* @param target current IME target.
|
* @param target current IME target.
|
||||||
* @return {@link WindowState} that can host IME.
|
* @return {@link WindowState} that can host IME.
|
||||||
* @see DisplayContent#getImeControlTarget()
|
|
||||||
*/
|
*/
|
||||||
WindowState getImeHostOrFallback(WindowState target) {
|
WindowState getImeHostOrFallback(WindowState target) {
|
||||||
if (target != null && target.getDisplayContent().canShowIme()) {
|
if (target != null && target.getDisplayContent().canShowIme()) {
|
||||||
@@ -3448,8 +3433,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
/**
|
/**
|
||||||
* The IME input target is the window which receives input from IME. It is also a candidate
|
* The IME input target is the window which receives input from IME. It is also a candidate
|
||||||
* which controls the visibility and animation of the input method window.
|
* which controls the visibility and animation of the input method window.
|
||||||
*
|
|
||||||
* @param target the window that receives input from IME.
|
|
||||||
*/
|
*/
|
||||||
void setInputMethodInputTarget(WindowState target) {
|
void setInputMethodInputTarget(WindowState target) {
|
||||||
if (mInputMethodInputTarget != target) {
|
if (mInputMethodInputTarget != target) {
|
||||||
@@ -3459,12 +3442,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateImeControlTarget() {
|
private void updateImeControlTarget() {
|
||||||
if (!isImeAttachedToApp() && mRemoteInsetsControlTarget != null) {
|
mInputMethodControlTarget = computeImeControlTarget();
|
||||||
mInputMethodControlTarget = mRemoteInsetsControlTarget;
|
|
||||||
} else {
|
|
||||||
// Otherwise, we just use the ime input target
|
|
||||||
mInputMethodControlTarget = mInputMethodInputTarget;
|
|
||||||
}
|
|
||||||
mInsetsStateController.onImeControlTargetChanged(mInputMethodControlTarget);
|
mInsetsStateController.onImeControlTargetChanged(mInputMethodControlTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3476,6 +3454,19 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the window where we hand IME control to.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
InsetsControlTarget computeImeControlTarget() {
|
||||||
|
if (!isImeControlledByApp() && mRemoteInsetsControlTarget != null) {
|
||||||
|
return mRemoteInsetsControlTarget;
|
||||||
|
} else {
|
||||||
|
// Otherwise, we just use the ime target as received from IME.
|
||||||
|
return mInputMethodInputTarget;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the window the IME should be attached to.
|
* Computes the window the IME should be attached to.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
@@ -84,10 +85,13 @@ import android.platform.test.annotations.Presubmit;
|
|||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.view.DisplayCutout;
|
import android.view.DisplayCutout;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
|
import android.view.IDisplayWindowInsetsController;
|
||||||
import android.view.IDisplayWindowRotationCallback;
|
import android.view.IDisplayWindowRotationCallback;
|
||||||
import android.view.IDisplayWindowRotationController;
|
import android.view.IDisplayWindowRotationController;
|
||||||
import android.view.ISystemGestureExclusionListener;
|
import android.view.ISystemGestureExclusionListener;
|
||||||
import android.view.IWindowManager;
|
import android.view.IWindowManager;
|
||||||
|
import android.view.InsetsSourceControl;
|
||||||
|
import android.view.InsetsState;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import android.view.SurfaceControl.Transaction;
|
import android.view.SurfaceControl.Transaction;
|
||||||
@@ -810,26 +814,20 @@ public class DisplayContentTests extends WindowTestsBase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testComputeImeParent_app() throws Exception {
|
public void testComputeImeParent_app() throws Exception {
|
||||||
try (final InsetsModeSession session =
|
|
||||||
new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
|
|
||||||
final DisplayContent dc = createNewDisplay();
|
final DisplayContent dc = createNewDisplay();
|
||||||
dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
|
dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
|
||||||
assertEquals(dc.mInputMethodTarget.mActivityRecord.getSurfaceControl(),
|
assertEquals(dc.mInputMethodTarget.mActivityRecord.getSurfaceControl(),
|
||||||
dc.computeImeParent());
|
dc.computeImeParent());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testComputeImeParent_app_notFullscreen() throws Exception {
|
public void testComputeImeParent_app_notFullscreen() throws Exception {
|
||||||
try (final InsetsModeSession session =
|
|
||||||
new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
|
|
||||||
final DisplayContent dc = createNewDisplay();
|
final DisplayContent dc = createNewDisplay();
|
||||||
dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
|
dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
|
||||||
dc.mInputMethodTarget.setWindowingMode(
|
dc.mInputMethodTarget.setWindowingMode(
|
||||||
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
|
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
|
||||||
assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent());
|
assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testComputeImeParent_app_notMatchParentBounds() {
|
public void testComputeImeParent_app_notMatchParentBounds() {
|
||||||
@@ -843,12 +841,61 @@ public class DisplayContentTests extends WindowTestsBase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testComputeImeParent_noApp() throws Exception {
|
public void testComputeImeParent_noApp() throws Exception {
|
||||||
try (final InsetsModeSession session =
|
|
||||||
new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
|
|
||||||
final DisplayContent dc = createNewDisplay();
|
final DisplayContent dc = createNewDisplay();
|
||||||
dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
|
dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
|
||||||
assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent());
|
assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testComputeImeControlTarget() throws Exception {
|
||||||
|
final DisplayContent dc = createNewDisplay();
|
||||||
|
dc.setRemoteInsetsController(createDisplayWindowInsetsController());
|
||||||
|
dc.mInputMethodInputTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
|
||||||
|
dc.mInputMethodTarget = dc.mInputMethodInputTarget;
|
||||||
|
assertEquals(dc.mInputMethodInputTarget, dc.computeImeControlTarget());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testComputeImeControlTarget_splitscreen() throws Exception {
|
||||||
|
final DisplayContent dc = createNewDisplay();
|
||||||
|
dc.mInputMethodInputTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
|
||||||
|
dc.mInputMethodInputTarget.setWindowingMode(
|
||||||
|
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
|
||||||
|
dc.mInputMethodTarget = dc.mInputMethodInputTarget;
|
||||||
|
dc.setRemoteInsetsController(createDisplayWindowInsetsController());
|
||||||
|
assertNotEquals(dc.mInputMethodInputTarget, dc.computeImeControlTarget());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testComputeImeControlTarget_notMatchParentBounds() throws Exception {
|
||||||
|
spyOn(mAppWindow.mActivityRecord);
|
||||||
|
doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
|
||||||
|
mDisplayContent.mInputMethodInputTarget = mAppWindow;
|
||||||
|
mDisplayContent.mInputMethodTarget = mDisplayContent.mInputMethodInputTarget;
|
||||||
|
mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController());
|
||||||
|
assertEquals(mAppWindow, mDisplayContent.computeImeControlTarget());
|
||||||
|
}
|
||||||
|
|
||||||
|
private IDisplayWindowInsetsController createDisplayWindowInsetsController() {
|
||||||
|
return new IDisplayWindowInsetsController.Stub() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void insetsChanged(InsetsState insetsState) throws RemoteException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void insetsControlChanged(InsetsState insetsState,
|
||||||
|
InsetsSourceControl[] insetsSourceControls) throws RemoteException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showInsets(int i, boolean b) throws RemoteException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hideInsets(int i, boolean b) throws RemoteException {
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user