Merge "Move IME to a host display when target's display is reparented"
This commit is contained in:
@@ -122,6 +122,7 @@ import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
|
||||
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
|
||||
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
|
||||
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
|
||||
import static com.android.server.wm.ProtoLogGroup.WM_ERROR;
|
||||
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
|
||||
import static com.android.server.wm.RootWindowContainer.TAG_STATES;
|
||||
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
|
||||
@@ -3416,6 +3417,57 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
&& 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the window which can host IME if IME target cannot host it.
|
||||
* e.g. IME target cannot host IME when it's display has a parent display OR when display
|
||||
* doesn't support IME/system decorations.
|
||||
*
|
||||
* @param target current IME target.
|
||||
* @return {@link WindowState} that can host IME.
|
||||
* @see DisplayContent#getImeControlTarget()
|
||||
*/
|
||||
WindowState getImeHostOrFallback(WindowState target) {
|
||||
if (target != null && target.getDisplayContent().canShowIme()) {
|
||||
return target;
|
||||
}
|
||||
|
||||
// host is in non-default display that doesn't support system decor, default to
|
||||
// default display's StatusBar to control IME.
|
||||
// TODO: (b/148234093)find a better host OR control IME animation/visibility directly
|
||||
// because it won't work when statusbar isn't available.
|
||||
return mWmService.getDefaultDisplayContentLocked().getDisplayPolicy().getStatusBar();
|
||||
}
|
||||
|
||||
boolean canShowIme() {
|
||||
if (isUntrustedVirtualDisplay()) {
|
||||
return false;
|
||||
}
|
||||
return mWmService.mDisplayWindowSettings.shouldShowImeLocked(this)
|
||||
|| mWmService.mForceDesktopModeOnExternalDisplays;
|
||||
}
|
||||
|
||||
private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim) {
|
||||
if (target == mInputMethodTarget && mInputMethodTargetWaitingAnim == targetWaitingAnim) {
|
||||
return;
|
||||
|
||||
@@ -25,6 +25,13 @@ import android.view.WindowInsets.Type.InsetsType;
|
||||
interface InsetsControlTarget {
|
||||
void notifyInsetsControlChanged();
|
||||
|
||||
/**
|
||||
* @return {@link WindowState} of this target, if any.
|
||||
*/
|
||||
default WindowState getWindow() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the control target to show inset sources.
|
||||
*
|
||||
|
||||
@@ -222,6 +222,12 @@ class InsetsSourceProvider {
|
||||
// to control the window for now.
|
||||
return;
|
||||
}
|
||||
if (target != null && target.getWindow() != null) {
|
||||
// ime control target could be a different window.
|
||||
// Refer WindowState#getImeControlTarget().
|
||||
target = target.getWindow().getImeControlTarget();
|
||||
}
|
||||
|
||||
if (mWin == null) {
|
||||
mControlTarget = target;
|
||||
return;
|
||||
|
||||
@@ -6991,8 +6991,15 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
|
||||
}
|
||||
boolean show;
|
||||
final DisplayContent dc = mRoot.getDisplayContent(displayId);
|
||||
if (dc == null) {
|
||||
ProtoLog.w(WM_ERROR,
|
||||
"Attempted to get IME flag of a display that does not exist: %d",
|
||||
displayId);
|
||||
return false;
|
||||
}
|
||||
synchronized (mGlobalLock) {
|
||||
show = shouldShowImeSystemWindowUncheckedLocked(displayId);
|
||||
show = dc.canShowIme();
|
||||
}
|
||||
|
||||
return show;
|
||||
@@ -7405,15 +7412,13 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
@Override
|
||||
public void showImePostLayout(IBinder imeTargetWindowToken) {
|
||||
synchronized (mGlobalLock) {
|
||||
final WindowState imeTarget = mWindowMap.get(imeTargetWindowToken);
|
||||
WindowState imeTarget = mWindowMap.get(imeTargetWindowToken);
|
||||
if (imeTarget == null) {
|
||||
return;
|
||||
}
|
||||
final int displayId = imeTarget.getDisplayId();
|
||||
if (!shouldShowImeSystemWindowUncheckedLocked(displayId)) {
|
||||
return;
|
||||
}
|
||||
imeTarget = imeTarget.getImeControlTarget();
|
||||
|
||||
final int displayId = imeTarget.getDisplayId();
|
||||
mRoot.getDisplayContent(displayId).getInsetsStateController().getImeSourceProvider()
|
||||
.scheduleShowImePostLayout(imeTarget);
|
||||
}
|
||||
@@ -7423,12 +7428,16 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
public void hideIme(int displayId) {
|
||||
synchronized (mGlobalLock) {
|
||||
final DisplayContent dc = mRoot.getDisplayContent(displayId);
|
||||
if (dc != null && dc.mInputMethodTarget != null) {
|
||||
if (dc != null) {
|
||||
WindowState imeTarget = dc.getImeControlTarget();
|
||||
if (imeTarget == null) {
|
||||
return;
|
||||
}
|
||||
// If there was a pending IME show(), reset it as IME has been
|
||||
// requested to be hidden.
|
||||
dc.getInsetsStateController().getImeSourceProvider().abortShowImePostLayout();
|
||||
dc.mInputMethodControlTarget.hideInsets(WindowInsets.Type.ime(),
|
||||
true /* fromIme */);
|
||||
imeTarget.getDisplayContent().getInsetsStateController().getImeSourceProvider()
|
||||
.abortShowImePostLayout();
|
||||
imeTarget.hideInsets(WindowInsets.Type.ime(), true /* fromIme */);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7936,21 +7945,6 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean shouldShowImeSystemWindowUncheckedLocked(final int displayId) {
|
||||
final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
|
||||
if (displayContent == null) {
|
||||
ProtoLog.w(WM_ERROR,
|
||||
"Attempted to get IME flag of a display that does not exist: %d",
|
||||
displayId);
|
||||
return false;
|
||||
}
|
||||
if (displayContent.isUntrustedVirtualDisplay()) {
|
||||
return false;
|
||||
}
|
||||
return mDisplayWindowSettings.shouldShowImeLocked(displayContent)
|
||||
|| mForceDesktopModeOnExternalDisplays;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getWindowInsets(WindowManager.LayoutParams attrs,
|
||||
int displayId, Rect outContentInsets, Rect outStableInsets,
|
||||
|
||||
@@ -3517,6 +3517,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowState getWindow() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showInsets(@InsetsType int types, boolean fromIme) {
|
||||
try {
|
||||
@@ -5334,6 +5339,24 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get IME target that should host IME when this window's display has a parent.
|
||||
* Note: IME is never hosted by a display that has a parent.
|
||||
* When window calling
|
||||
* {@link android.view.inputmethod.InputMethodManager#showSoftInput(View, int)} is unknown,
|
||||
* use {@link DisplayContent#getImeControlTarget()} instead.
|
||||
*
|
||||
* @return {@link WindowState} of host that controls the IME.
|
||||
* When window is doesn't have a parent, it is returned as-is.
|
||||
*/
|
||||
WindowState getImeControlTarget() {
|
||||
final DisplayContent dc = getDisplayContent();
|
||||
final WindowState parentWindow = dc.getParentWindow();
|
||||
|
||||
// If target's display has a parent, IME is displayed in the parent display.
|
||||
return dc.getImeHostOrFallback(parentWindow != null ? parentWindow : this);
|
||||
}
|
||||
|
||||
@Override
|
||||
void assignLayer(Transaction t, int layer) {
|
||||
// See comment in assignRelativeLayerForImeTargetChild
|
||||
|
||||
@@ -110,7 +110,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
|
||||
beforeCreateDisplay();
|
||||
|
||||
context.getDisplay().getDisplayInfo(mDisplayInfo);
|
||||
mDisplayContent = createNewDisplay();
|
||||
mDisplayContent = createNewDisplay(true /* supportIme */);
|
||||
|
||||
// Set-up some common windows.
|
||||
mCommonWindows = new HashSet<>();
|
||||
@@ -349,16 +349,29 @@ class WindowTestsBase extends SystemServiceTestsBase {
|
||||
return WindowTestUtils.createTaskInStack(mWm, stack, userId);
|
||||
}
|
||||
|
||||
/** Creates a {@link DisplayContent} and adds it to the system. */
|
||||
/** Creates a {@link DisplayContent} that supports IME and adds it to the system. */
|
||||
DisplayContent createNewDisplay() {
|
||||
return createNewDisplay(mDisplayInfo);
|
||||
return createNewDisplay(true /* supportIme */);
|
||||
}
|
||||
|
||||
/** Creates a {@link DisplayContent} and adds it to the system. */
|
||||
private DisplayContent createNewDisplay(boolean supportIme) {
|
||||
return createNewDisplay(mDisplayInfo, supportIme);
|
||||
}
|
||||
|
||||
/** Creates a {@link DisplayContent} that supports IME and adds it to the system. */
|
||||
DisplayContent createNewDisplay(DisplayInfo info) {
|
||||
return createNewDisplay(info, true /* supportIme */);
|
||||
}
|
||||
|
||||
/** Creates a {@link DisplayContent} and adds it to the system. */
|
||||
private DisplayContent createNewDisplay(DisplayInfo info, boolean supportIme) {
|
||||
final DisplayContent display =
|
||||
new TestDisplayContent.Builder(mWm.mAtmService, info).build();
|
||||
return display.mDisplayContent;
|
||||
final DisplayContent dc = display.mDisplayContent;
|
||||
// this display can show IME.
|
||||
dc.mWmService.mDisplayWindowSettings.setShouldShowImeLocked(dc, supportIme);
|
||||
return dc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -372,7 +385,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
|
||||
DisplayInfo displayInfo = new DisplayInfo();
|
||||
displayInfo.copyFrom(mDisplayInfo);
|
||||
displayInfo.state = displayState;
|
||||
return createNewDisplay(displayInfo);
|
||||
return createNewDisplay(displayInfo, true /* supportIme */);
|
||||
}
|
||||
|
||||
/** Creates a {@link com.android.server.wm.WindowTestUtils.TestWindowState} */
|
||||
@@ -389,7 +402,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
|
||||
displayInfo.copyFrom(mDisplayInfo);
|
||||
displayInfo.type = Display.TYPE_VIRTUAL;
|
||||
displayInfo.ownerUid = SYSTEM_UID;
|
||||
return createNewDisplay(displayInfo);
|
||||
return createNewDisplay(displayInfo, false /* supportIme */);
|
||||
}
|
||||
|
||||
/** Sets the default minimum task size to 1 so that tests can use small task sizes */
|
||||
|
||||
Reference in New Issue
Block a user