diff options
3 files changed, 47 insertions, 29 deletions
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index d40f8325c320..4f38b5409379 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1288,14 +1288,11 @@ public interface WindowManager extends ViewManager { * set for you by Window as described in {@link Window#setFlags}.*/ public static final int FLAG_LAYOUT_INSET_DECOR = 0x00010000; - /** Window flag: invert the state of {@link #FLAG_NOT_FOCUSABLE} with - * respect to how this window interacts with the current method. That - * is, if FLAG_NOT_FOCUSABLE is set and this flag is set, then the - * window will behave as if it needs to interact with the input method - * and thus be placed behind/away from it; if FLAG_NOT_FOCUSABLE is - * not set and this flag is set, then the window will behave as if it - * doesn't need to interact with the input method and can be placed - * to use more space and cover the input method. + /** Window flag: When set, input method can't interact with the focusable window + * and can be placed to use more space and cover the input method. + * Note: When combined with {@link #FLAG_NOT_FOCUSABLE}, this flag has no + * effect since input method cannot interact with windows having {@link #FLAG_NOT_FOCUSABLE} + * flag set. */ public static final int FLAG_ALT_FOCUSABLE_IM = 0x00020000; @@ -1993,16 +1990,12 @@ public interface WindowManager extends ViewManager { * * @param flags The current window manager flags. * - * @return Returns true if such a window should be behind/interact - * with an input method, false if not. + * @return Returns {@code true} if such a window should be behind/interact + * with an input method, {@code false} if not. */ public static boolean mayUseInputMethod(int flags) { - switch (flags&(FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)) { - case 0: - case FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM: - return true; - } - return false; + return (flags & FLAG_NOT_FOCUSABLE) != FLAG_NOT_FOCUSABLE + && (flags & FLAG_ALT_FOCUSABLE_IM) != FLAG_ALT_FOCUSABLE_IM; } /** diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 6a1aa02a6c79..9707435909c8 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2163,13 +2163,27 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return false; } - final int fl = mAttrs.flags & (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM); - final int type = mAttrs.type; - - // Can only be an IME target if both FLAG_NOT_FOCUSABLE and FLAG_ALT_FOCUSABLE_IM are set or - // both are cleared...and not a starting window. - if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM) - && type != TYPE_APPLICATION_STARTING) { + if (PixelFormat.formatHasAlpha(mAttrs.format)) { + // Support legacy use cases where transparent windows can still be ime target with + // FLAG_NOT_FOCUSABLE and ALT_FOCUSABLE_IM set. + // Certain apps listen for IME insets using transparent windows and ADJUST_NOTHING to + // manually synchronize app content to IME animation b/144619551. + // TODO(b/145812508): remove this once new focus management is complete b/141738570 + final int fl = mAttrs.flags & (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM); + final int type = mAttrs.type; + + // Can only be an IME target if both FLAG_NOT_FOCUSABLE and FLAG_ALT_FOCUSABLE_IM are + // set or both are cleared...and not a starting window. + if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM) + && type != TYPE_APPLICATION_STARTING) { + return false; + } + } else if (!WindowManager.LayoutParams.mayUseInputMethod(mAttrs.flags) + || mAttrs.type == TYPE_APPLICATION_STARTING) { + // Can be an IME target only if: + // 1. FLAG_NOT_FOCUSABLE is not set + // 2. FLAG_ALT_FOCUSABLE_IM is not set + // 3. not a starting window. return false; } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index 72baedb5ed66..8ade4d27e495 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -61,6 +61,7 @@ import static org.mockito.Mockito.when; import android.graphics.Insets; import android.graphics.Matrix; +import android.graphics.PixelFormat; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.util.Size; @@ -222,8 +223,7 @@ public class WindowStateTests extends WindowTestsBase { final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow"); final WindowState imeWindow = createWindow(null, TYPE_INPUT_METHOD, "imeWindow"); - // Setting FLAG_NOT_FOCUSABLE without FLAG_ALT_FOCUSABLE_IM prevents the window from being - // an IME target. + // Setting FLAG_NOT_FOCUSABLE prevents the window from being an IME target. appWindow.mAttrs.flags |= FLAG_NOT_FOCUSABLE; imeWindow.mAttrs.flags |= FLAG_NOT_FOCUSABLE; @@ -231,7 +231,7 @@ public class WindowStateTests extends WindowTestsBase { appWindow.setHasSurface(true); imeWindow.setHasSurface(true); - // Windows without flags (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM) can't be IME targets + // Windows with FLAG_NOT_FOCUSABLE can't be IME targets assertFalse(appWindow.canBeImeTarget()); assertFalse(imeWindow.canBeImeTarget()); @@ -239,11 +239,22 @@ public class WindowStateTests extends WindowTestsBase { appWindow.mAttrs.flags |= (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM); imeWindow.mAttrs.flags |= (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM); - // Visible app window with flags can be IME target while an IME window can never be an IME - // target regardless of its visibility or flags. - assertTrue(appWindow.canBeImeTarget()); + // Visible app window with flags FLAG_NOT_FOCUSABLE or FLAG_ALT_FOCUSABLE_IM can't be IME + // target while an IME window can never be an IME target regardless of its visibility + // or flags. + assertFalse(appWindow.canBeImeTarget()); assertFalse(imeWindow.canBeImeTarget()); + // b/145812508: special legacy use-case for transparent/translucent windows. + appWindow.mAttrs.format = PixelFormat.TRANSPARENT; + assertTrue(appWindow.canBeImeTarget()); + + appWindow.mAttrs.format = PixelFormat.OPAQUE; + appWindow.mAttrs.flags &= ~FLAG_ALT_FOCUSABLE_IM; + assertFalse(appWindow.canBeImeTarget()); + appWindow.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE; + assertTrue(appWindow.canBeImeTarget()); + // Make windows invisible appWindow.hideLw(false /* doAnimation */); imeWindow.hideLw(false /* doAnimation */); |