summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Tarandeep Singh <tarandeep@google.com> 2019-12-06 10:36:55 -0800
committer Taran Singh <tarandeep@google.com> 2019-12-13 23:34:22 +0000
commitbcba88c3258a400c84d74e084d514a28724080c4 (patch)
tree425b419a7b09434db0a4d9053c650a42023de146
parent4ad8cd5924862a106c5a1441e00a1996da31ace8 (diff)
Window with FLAG_NOT_FOCUSABLE cant be IME target.
Any window that sets FLAG_NOT_FOCUSABLE should not be considered IME target. IME subsystem starts input on a window when it receives focus, if window never intended to receive focus, it should not considered an IME target either. Also, fix the broken javadoc for ALT_FOCUSABLE_IM. Certain apps try to manually synchronize app window to IME insets by using ADJUST_NOTHING in main window and introducing a transparent window on top with FLAG_NOT_FOCUSABLE & ALT_FOCUS_IM to listen for IME insets. We will support this use case until new focus management takes care of it. Fix: 143898978 Bug: 140641950 Bug: 145812508 Bug: 141738570 Bug: 144619551 Test: atest WindowStateTests atest FocusHandlingTest atest WindowManager_LayoutParamsTest Also manually using steps: 1. Launch gmail compose activity 2. start typing in receipient field 3. verify that suggestions popup window w/ FLAG_NOT_FOCUSABLE doesn't become IME target. Change-Id: I941571c97145d77b0a59d030cf2a8c8318f3b59f
-rw-r--r--core/java/android/view/WindowManager.java25
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java28
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java23
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 */);