Merge "Allow some app windows to display above the IME."
This commit is contained in:
committed by
Android (Google) Code Review
commit
0730df7369
@@ -141,8 +141,6 @@ import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Utility class for keeping track of the WindowStates and other pertinent contents of a
|
||||
@@ -2546,7 +2544,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
if (!obscured) {
|
||||
final boolean isDisplayed = w.isDisplayedLw();
|
||||
|
||||
if (isDisplayed && w.isObscuringFullscreen(mDisplayInfo)) {
|
||||
if (isDisplayed && w.isObscuringDisplay()) {
|
||||
// This window completely covers everything behind it, so we want to leave all
|
||||
// of them as undimmed (for performance reasons).
|
||||
root.mObscuringWindow = w;
|
||||
@@ -2945,7 +2943,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
screenshotReady = true;
|
||||
}
|
||||
|
||||
if (ws.isObscuringFullscreen(mDisplayInfo)){
|
||||
if (ws.isObscuringDisplay()){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,8 @@ class WindowLayersController {
|
||||
private boolean mAnyLayerChanged;
|
||||
private int mHighestLayerInImeTargetBaseLayer;
|
||||
private WindowState mImeTarget;
|
||||
private boolean mAboveImeTarget;
|
||||
private ArrayDeque<WindowState> mAboveImeTargetAppWindows = new ArrayDeque();
|
||||
|
||||
final void assignWindowLayers(DisplayContent dc) {
|
||||
if (DEBUG_LAYERS) Slog.v(TAG_WM, "Assigning layers based",
|
||||
@@ -143,6 +145,8 @@ class WindowLayersController {
|
||||
|
||||
mImeTarget = mService.mInputMethodTarget;
|
||||
mHighestLayerInImeTargetBaseLayer = (mImeTarget != null) ? mImeTarget.mBaseLayer : 0;
|
||||
mAboveImeTarget = false;
|
||||
mAboveImeTargetAppWindows.clear();
|
||||
}
|
||||
|
||||
private void collectSpecialWindows(WindowState w) {
|
||||
@@ -157,6 +161,20 @@ class WindowLayersController {
|
||||
mInputMethodWindows.add(w);
|
||||
return;
|
||||
}
|
||||
if (mImeTarget != null) {
|
||||
if (w.getParentWindow() == mImeTarget && w.mSubLayer > 0) {
|
||||
// Child windows of the ime target with a positive sub-layer should be placed above
|
||||
// the IME.
|
||||
mAboveImeTargetAppWindows.add(w);
|
||||
} else if (mAboveImeTarget && w.mAppToken != null) {
|
||||
// windows of apps above the IME target should be placed above the IME.
|
||||
mAboveImeTargetAppWindows.add(w);
|
||||
}
|
||||
if (w == mImeTarget) {
|
||||
mAboveImeTarget = true;
|
||||
}
|
||||
}
|
||||
|
||||
final Task task = w.getTask();
|
||||
if (task == null) {
|
||||
return;
|
||||
@@ -211,6 +229,12 @@ class WindowLayersController {
|
||||
while (!mInputMethodWindows.isEmpty()) {
|
||||
layer = assignAndIncreaseLayerIfNeeded(mInputMethodWindows.remove(), layer);
|
||||
}
|
||||
|
||||
// Adjust app windows the should be displayed above the IME since they are above the IME
|
||||
// target.
|
||||
while (!mAboveImeTargetAppWindows.isEmpty()) {
|
||||
layer = assignAndIncreaseLayerIfNeeded(mAboveImeTargetAppWindows.remove(), layer);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -60,8 +60,6 @@ import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static android.app.ActivityManager.StackId;
|
||||
@@ -91,7 +89,6 @@ import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
|
||||
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
|
||||
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
|
||||
@@ -1654,18 +1651,16 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
&& (!mIsChildWindow || !getParentWindow().hasMoved());
|
||||
}
|
||||
|
||||
boolean isObscuringFullscreen(final DisplayInfo displayInfo) {
|
||||
boolean isObscuringDisplay() {
|
||||
Task task = getTask();
|
||||
if (task != null && task.mStack != null && !task.mStack.fillsParent()) {
|
||||
return false;
|
||||
}
|
||||
if (!isOpaqueDrawn() || !isFrameFullscreen(displayInfo)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return isOpaqueDrawn() && fillsDisplay();
|
||||
}
|
||||
|
||||
boolean isFrameFullscreen(final DisplayInfo displayInfo) {
|
||||
boolean fillsDisplay() {
|
||||
final DisplayInfo displayInfo = getDisplayInfo();
|
||||
return mFrame.left <= 0 && mFrame.top <= 0
|
||||
&& mFrame.right >= displayInfo.appWidth && mFrame.bottom >= displayInfo.appHeight;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@ import android.os.Trace;
|
||||
import android.util.Slog;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.MagnificationSpec;
|
||||
import android.view.Surface;
|
||||
import android.view.Surface.OutOfResourcesException;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.WindowManager;
|
||||
@@ -1108,10 +1107,9 @@ class WindowStateAnimator {
|
||||
|
||||
/**
|
||||
* Calculate the window-space crop rect and fill clipRect.
|
||||
* @return true if clipRect has been filled otherwise, no window space
|
||||
* crop should be applied.
|
||||
* @return true if clipRect has been filled otherwise, no window space crop should be applied.
|
||||
*/
|
||||
boolean calculateCrop(Rect clipRect) {
|
||||
private boolean calculateCrop(Rect clipRect) {
|
||||
final WindowState w = mWin;
|
||||
final DisplayContent displayContent = w.getDisplayContent();
|
||||
clipRect.setEmpty();
|
||||
@@ -1130,7 +1128,6 @@ class WindowStateAnimator {
|
||||
return false;
|
||||
}
|
||||
|
||||
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
|
||||
if (DEBUG_WINDOW_CROP) Slog.d(TAG,
|
||||
"Updating crop win=" + w + " mLastCrop=" + mLastClipRect);
|
||||
|
||||
@@ -1139,7 +1136,7 @@ class WindowStateAnimator {
|
||||
if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop win=" + w + " mDecorFrame="
|
||||
+ w.mDecorFrame + " mSystemDecorRect=" + mSystemDecorRect);
|
||||
|
||||
final boolean fullscreen = w.isFrameFullscreen(displayInfo);
|
||||
final boolean fullscreen = w.fillsDisplay();
|
||||
final boolean isFreeformResizing =
|
||||
w.isDragResizing() && w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.support.test.filters.SmallTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
|
||||
@@ -120,6 +121,62 @@ public class WindowLayersControllerTests extends WindowTestsBase {
|
||||
assertWindowLayerGreaterThan(sImeDialogWindow, sImeWindow);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAssignWindowLayers_ForImeWithAppTargetWithChildWindows() throws Exception {
|
||||
final WindowState imeAppTarget =
|
||||
createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "imeAppTarget");
|
||||
final WindowState imeAppTargetChildAboveWindow = createWindow(imeAppTarget,
|
||||
TYPE_APPLICATION_ATTACHED_DIALOG, imeAppTarget.mToken,
|
||||
"imeAppTargetChildAboveWindow");
|
||||
final WindowState imeAppTargetChildBelowWindow = createWindow(imeAppTarget,
|
||||
TYPE_APPLICATION_MEDIA_OVERLAY, imeAppTarget.mToken,
|
||||
"imeAppTargetChildBelowWindow");
|
||||
|
||||
sWm.mInputMethodTarget = imeAppTarget;
|
||||
sLayersController.assignWindowLayers(sDisplayContent);
|
||||
|
||||
// Ime should be above all app windows except for child windows that are z-ordered above it
|
||||
// and below system windows if it is targeting an app window.
|
||||
assertWindowLayerGreaterThan(sImeWindow, imeAppTarget);
|
||||
assertWindowLayerGreaterThan(imeAppTargetChildAboveWindow, sImeWindow);
|
||||
assertWindowLayerGreaterThan(sImeWindow, imeAppTargetChildBelowWindow);
|
||||
assertWindowLayerGreaterThan(sImeWindow, sChildAppWindow);
|
||||
assertWindowLayerGreaterThan(sImeWindow, sAppWindow);
|
||||
assertWindowLayerGreaterThan(sImeWindow, sDockedDividerWindow);
|
||||
assertWindowLayerGreaterThan(sNavBarWindow, sImeWindow);
|
||||
assertWindowLayerGreaterThan(sStatusBarWindow, sImeWindow);
|
||||
|
||||
// And, IME dialogs should always have an higher layer than the IME.
|
||||
assertWindowLayerGreaterThan(sImeDialogWindow, sImeWindow);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAssignWindowLayers_ForImeWithAppTargetAndAppAbove() throws Exception {
|
||||
final WindowState appBelowImeTarget =
|
||||
createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "appBelowImeTarget");
|
||||
final WindowState imeAppTarget =
|
||||
createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "imeAppTarget");
|
||||
final WindowState appAboveImeTarget =
|
||||
createWindow(null, TYPE_BASE_APPLICATION, sDisplayContent, "appAboveImeTarget");
|
||||
|
||||
sWm.mInputMethodTarget = imeAppTarget;
|
||||
sLayersController.assignWindowLayers(sDisplayContent);
|
||||
|
||||
// Ime should be above all app windows except for non-fullscreen app window above it and
|
||||
// below system windows if it is targeting an app window.
|
||||
assertWindowLayerGreaterThan(sImeWindow, imeAppTarget);
|
||||
assertWindowLayerGreaterThan(sImeWindow, appBelowImeTarget);
|
||||
assertWindowLayerGreaterThan(appAboveImeTarget, sImeWindow);
|
||||
assertWindowLayerGreaterThan(sImeWindow, sChildAppWindow);
|
||||
assertWindowLayerGreaterThan(sImeWindow, sAppWindow);
|
||||
assertWindowLayerGreaterThan(sImeWindow, sDockedDividerWindow);
|
||||
assertWindowLayerGreaterThan(sNavBarWindow, sImeWindow);
|
||||
assertWindowLayerGreaterThan(sStatusBarWindow, sImeWindow);
|
||||
|
||||
// And, IME dialogs should always have an higher layer than the IME.
|
||||
assertWindowLayerGreaterThan(sImeDialogWindow, sImeWindow);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAssignWindowLayers_ForImeNonAppImeTarget() throws Exception {
|
||||
final WindowState imeSystemOverlayTarget =
|
||||
|
||||
Reference in New Issue
Block a user