Check embedded windows for IME target

When checking IME target, if the main window can't be IME target but the
embedded window can be, the IME will not be z ordered correctly. The IME
should be updated so it's z ordered to the embedded window. Since the
embedded window is in a different display, we set the IME target to the
host to avoid any issues with IME target being on a different display.

Test: WindowStateTests#testCanWindowWithEmbeddedDisplayBeImeTarget
Test: Host window with flag FLAG_NOT_FOCUSABLE and embedded without. IME
can be shown for the embedded window
Bug: 156785479

Change-Id: Id46dc8be16f1a00dd31d79cc61bfcb83a2515888
This commit is contained in:
chaviw
2020-05-19 13:57:43 -07:00
parent f13d436c2e
commit 50dbc983bf
2 changed files with 42 additions and 0 deletions

View File

@@ -2262,7 +2262,29 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mHasSurface = hasSurface;
}
/**
* Checks whether one of the Windows in a Display embedded in this Window can be an IME target.
*/
private boolean canWindowInEmbeddedDisplayBeImeTarget() {
final int embeddedDisplayContentsSize = mEmbeddedDisplayContents.size();
for (int i = embeddedDisplayContentsSize - 1; i >= 0; i--) {
final DisplayContent edc = mEmbeddedDisplayContents.valueAt(i);
if (edc.forAllWindows(WindowState::canBeImeTarget, true)) {
return true;
}
}
return false;
}
boolean canBeImeTarget() {
// If any of the embedded windows can be the IME target, this window will be the final IME
// target. This is because embedded windows are on a different display in WM so it would
// cause confusion trying to set the IME to a window on a different display. Instead, just
// make the host window the IME target.
if (canWindowInEmbeddedDisplayBeImeTarget()) {
return true;
}
if (mIsImWindow) {
// IME windows can't be IME targets. IME targets are required to be below the IME
// windows and that wouldn't be possible if the IME window is its own target...silly.

View File

@@ -269,6 +269,26 @@ public class WindowStateTests extends WindowTestsBase {
assertTrue(stack.shouldIgnoreInput());
}
@Test
public void testCanWindowWithEmbeddedDisplayBeImeTarget() {
final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
final WindowState imeWindow = createWindow(null, TYPE_INPUT_METHOD, "imeWindow");
imeWindow.setHasSurface(true);
appWindow.setHasSurface(true);
appWindow.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
assertFalse(appWindow.canBeImeTarget());
DisplayContent secondDisplay = createNewDisplay();
final WindowState embeddedWindow = createWindow(null, TYPE_APPLICATION, secondDisplay,
"embeddedWindow");
appWindow.addEmbeddedDisplayContent(secondDisplay);
embeddedWindow.setHasSurface(true);
embeddedWindow.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE;
assertTrue(appWindow.canBeImeTarget());
}
@Test
public void testGetWindow() {
final WindowState root = createWindow(null, TYPE_APPLICATION, "root");