Merge "Moved adding to display WindowList to DisplayContent"
This commit is contained in:
committed by
Android (Google) Code Review
commit
3cece22080
@@ -27,9 +27,14 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
|
||||
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_TOAST;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
@@ -44,6 +49,7 @@ import android.util.DisplayMetrics;
|
||||
import android.util.Slog;
|
||||
import android.view.Display;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.IWindow;
|
||||
import android.view.Surface;
|
||||
import android.view.animation.Animation;
|
||||
|
||||
@@ -828,4 +834,264 @@ class DisplayContent {
|
||||
if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
|
||||
return null;
|
||||
}
|
||||
|
||||
int addAppWindowToWindowList(final WindowState win) {
|
||||
final IWindow client = win.mClient;
|
||||
|
||||
WindowList tokenWindowList = getTokenWindowsOnDisplay(win.mToken);
|
||||
if (!tokenWindowList.isEmpty()) {
|
||||
return addAppWindowExisting(win, tokenWindowList);
|
||||
}
|
||||
|
||||
// No windows from this token on this display
|
||||
if (mService.localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window "
|
||||
+ client.asBinder() + " (token=" + this + ")");
|
||||
|
||||
final WindowToken wToken = win.mToken;
|
||||
|
||||
// Figure out where the window should go, based on the order of applications.
|
||||
final GetWindowOnDisplaySearchResults result = new GetWindowOnDisplaySearchResults();
|
||||
for (int i = mStacks.size() - 1; i >= 0; --i) {
|
||||
final TaskStack stack = mStacks.get(i);
|
||||
stack.getWindowOnDisplayBeforeToken(this, wToken, result);
|
||||
if (result.reachedToken) {
|
||||
// We have reach the token we are interested in. End search.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WindowState pos = result.foundWindow;
|
||||
|
||||
// We now know the index into the apps. If we found an app window above, that gives us the
|
||||
// position; else we need to look some more.
|
||||
if (pos != null) {
|
||||
// Move behind any windows attached to this one.
|
||||
final WindowToken atoken = mService.mTokenMap.get(pos.mClient.asBinder());
|
||||
if (atoken != null) {
|
||||
tokenWindowList = getTokenWindowsOnDisplay(atoken);
|
||||
final int NC = tokenWindowList.size();
|
||||
if (NC > 0) {
|
||||
WindowState bottom = tokenWindowList.get(0);
|
||||
if (bottom.mSubLayer < 0) {
|
||||
pos = bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
addWindowToListBefore(win, pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Continue looking down until we find the first token that has windows on this display.
|
||||
result.reset();
|
||||
for (int i = mStacks.size() - 1; i >= 0; --i) {
|
||||
final TaskStack stack = mStacks.get(i);
|
||||
stack.getWindowOnDisplayAfterToken(this, wToken, result);
|
||||
if (result.foundWindow != null) {
|
||||
// We have found a window after the token. End search.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pos = result.foundWindow;
|
||||
|
||||
if (pos != null) {
|
||||
// Move in front of any windows attached to this one.
|
||||
final WindowToken atoken = mService.mTokenMap.get(pos.mClient.asBinder());
|
||||
if (atoken != null) {
|
||||
final WindowState top = atoken.getTopWindow();
|
||||
if (top != null && top.mSubLayer >= 0) {
|
||||
pos = top;
|
||||
}
|
||||
}
|
||||
addWindowToListAfter(win, pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Just search for the start of this layer.
|
||||
final int myLayer = win.mBaseLayer;
|
||||
int i;
|
||||
for (i = mWindows.size() - 1; i >= 0; --i) {
|
||||
final WindowState w = mWindows.get(i);
|
||||
// Dock divider shares the base layer with application windows, but we want to always
|
||||
// keep it above the application windows. The sharing of the base layer is intended
|
||||
// for window animations, which need to be above the dock divider for the duration
|
||||
// of the animation.
|
||||
if (w.mBaseLayer <= myLayer && w.mAttrs.type != TYPE_DOCK_DIVIDER) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
|
||||
"Based on layer: Adding window " + win + " at " + (i + 1) + " of "
|
||||
+ mWindows.size());
|
||||
mWindows.add(i + 1, win);
|
||||
mService.mWindowsChanged = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Adds this non-app window to the window list. */
|
||||
void addNonAppWindowToWindowList(WindowState win) {
|
||||
// Figure out where window should go, based on layer.
|
||||
int i;
|
||||
for (i = mWindows.size() - 1; i >= 0; i--) {
|
||||
final WindowState otherWin = mWindows.get(i);
|
||||
if (otherWin.getBaseType() != TYPE_WALLPAPER && otherWin.mBaseLayer <= win.mBaseLayer) {
|
||||
// Wallpaper wanders through the window list, for example to position itself
|
||||
// directly behind keyguard. Because of this it will break the ordering based on
|
||||
// WindowState.mBaseLayer. There might windows with higher mBaseLayer behind it and
|
||||
// we don't want the new window to appear above them. An example of this is adding
|
||||
// of the docked stack divider. Consider a scenario with the following ordering (top
|
||||
// to bottom): keyguard, wallpaper, assist preview, apps. We want the dock divider
|
||||
// to land below the assist preview, so the dock divider must ignore the wallpaper,
|
||||
// with which it shares the base layer.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
|
||||
"Free window: Adding window " + this + " at " + i + " of " + mWindows.size());
|
||||
mWindows.add(i, win);
|
||||
mService.mWindowsChanged = true;
|
||||
}
|
||||
|
||||
void addChildWindowToWindowList(WindowState win) {
|
||||
final WindowState parentWindow = win.getParentWindow();
|
||||
|
||||
WindowList windowsOnSameDisplay = getTokenWindowsOnDisplay(win.mToken);
|
||||
|
||||
// Figure out this window's ordering relative to the parent window.
|
||||
final int wCount = windowsOnSameDisplay.size();
|
||||
final int sublayer = win.mSubLayer;
|
||||
int largestSublayer = Integer.MIN_VALUE;
|
||||
WindowState windowWithLargestSublayer = null;
|
||||
int i;
|
||||
for (i = 0; i < wCount; i++) {
|
||||
WindowState w = windowsOnSameDisplay.get(i);
|
||||
final int wSublayer = w.mSubLayer;
|
||||
if (wSublayer >= largestSublayer) {
|
||||
largestSublayer = wSublayer;
|
||||
windowWithLargestSublayer = w;
|
||||
}
|
||||
if (sublayer < 0) {
|
||||
// For negative sublayers, we go below all windows in the same sublayer.
|
||||
if (wSublayer >= sublayer) {
|
||||
addWindowToListBefore(win, wSublayer >= 0 ? parentWindow : w);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// For positive sublayers, we go above all windows in the same sublayer.
|
||||
if (wSublayer > sublayer) {
|
||||
addWindowToListBefore(win, w);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i >= wCount) {
|
||||
if (sublayer < 0) {
|
||||
addWindowToListBefore(win, parentWindow);
|
||||
} else {
|
||||
addWindowToListAfter(win,
|
||||
largestSublayer >= 0 ? windowWithLargestSublayer : parentWindow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Return the list of Windows on this display associated with the input token. */
|
||||
WindowList getTokenWindowsOnDisplay(WindowToken token) {
|
||||
final WindowList windowList = new WindowList();
|
||||
final int count = mWindows.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final WindowState win = mWindows.get(i);
|
||||
if (win.mToken == token) {
|
||||
windowList.add(win);
|
||||
}
|
||||
}
|
||||
return windowList;
|
||||
}
|
||||
|
||||
private int addAppWindowExisting(WindowState win, WindowList tokenWindowList) {
|
||||
|
||||
int tokenWindowsPos;
|
||||
// If this application has existing windows, we simply place the new window on top of
|
||||
// them... but keep the starting window on top.
|
||||
if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
|
||||
// Base windows go behind everything else.
|
||||
final WindowState lowestWindow = tokenWindowList.get(0);
|
||||
addWindowToListBefore(win, lowestWindow);
|
||||
tokenWindowsPos = win.mToken.getWindowIndex(lowestWindow);
|
||||
} else {
|
||||
final AppWindowToken atoken = win.mAppToken;
|
||||
final int windowListPos = tokenWindowList.size();
|
||||
final WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
|
||||
if (atoken != null && lastWindow == atoken.startingWindow) {
|
||||
addWindowToListBefore(win, lastWindow);
|
||||
tokenWindowsPos = win.mToken.getWindowIndex(lastWindow);
|
||||
} else {
|
||||
int newIdx = findIdxBasedOnAppTokens(win);
|
||||
// There is a window above this one associated with the same apptoken note that the
|
||||
// window could be a floating window that was created later or a window at the top
|
||||
// of the list of windows associated with this token.
|
||||
if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
|
||||
"not Base app: Adding window " + win + " at " + (newIdx + 1) + " of "
|
||||
+ mWindows.size());
|
||||
mWindows.add(newIdx + 1, win);
|
||||
if (newIdx < 0) {
|
||||
// No window from token found on win's display.
|
||||
tokenWindowsPos = 0;
|
||||
} else {
|
||||
tokenWindowsPos = win.mToken.getWindowIndex(mWindows.get(newIdx)) + 1;
|
||||
}
|
||||
mService.mWindowsChanged = true;
|
||||
}
|
||||
}
|
||||
return tokenWindowsPos;
|
||||
}
|
||||
|
||||
/** Places the first input window after the second input window in the window list. */
|
||||
private void addWindowToListAfter(WindowState first, WindowState second) {
|
||||
final int i = mWindows.indexOf(second);
|
||||
if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
|
||||
"Adding window " + this + " at " + (i + 1) + " of " + mWindows.size()
|
||||
+ " (after " + second + ")");
|
||||
mWindows.add(i + 1, first);
|
||||
mService.mWindowsChanged = true;
|
||||
}
|
||||
|
||||
/** Places the first input window before the second input window in the window list. */
|
||||
private void addWindowToListBefore(WindowState first, WindowState second) {
|
||||
int i = mWindows.indexOf(second);
|
||||
if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
|
||||
"Adding window " + this + " at " + i + " of " + mWindows.size()
|
||||
+ " (before " + second + ")");
|
||||
if (i < 0) {
|
||||
Slog.w(TAG_WM, "addWindowToListBefore: Unable to find " + second + " in " + mWindows);
|
||||
i = 0;
|
||||
}
|
||||
mWindows.add(i, first);
|
||||
mService.mWindowsChanged = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method finds out the index of a window that has the same app token as win. used for z
|
||||
* ordering the windows in mWindows
|
||||
*/
|
||||
private int findIdxBasedOnAppTokens(WindowState win) {
|
||||
for(int j = mWindows.size() - 1; j >= 0; j--) {
|
||||
final WindowState wentry = mWindows.get(j);
|
||||
if(wentry.mAppToken == win.mAppToken) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static final class GetWindowOnDisplaySearchResults {
|
||||
boolean reachedToken;
|
||||
WindowState foundWindow;
|
||||
|
||||
void reset() {
|
||||
reachedToken = false;
|
||||
foundWindow = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -689,6 +689,46 @@ class Task implements DimLayer.DimLayerUser {
|
||||
return mAppTokens.indexOf(first) > mAppTokens.indexOf(second);
|
||||
}
|
||||
|
||||
void getWindowOnDisplayBeforeToken(DisplayContent dc, WindowToken token,
|
||||
DisplayContent.GetWindowOnDisplaySearchResults result) {
|
||||
for (int i = mAppTokens.size() - 1; i >= 0; --i) {
|
||||
final AppWindowToken current = mAppTokens.get(i);
|
||||
if (current == token) {
|
||||
// We have reach the token we are interested in. End search.
|
||||
result.reachedToken = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// We haven't reached the token yet; if this token is not going to the bottom and
|
||||
// has windows on this display, then it is a candidate for what we are looking for.
|
||||
final WindowList tokenWindowList = dc.getTokenWindowsOnDisplay(current);
|
||||
if (!current.sendingToBottom && tokenWindowList.size() > 0) {
|
||||
result.foundWindow = tokenWindowList.get(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void getWindowOnDisplayAfterToken(DisplayContent dc, WindowToken token,
|
||||
DisplayContent.GetWindowOnDisplaySearchResults result) {
|
||||
for (int i = mAppTokens.size() - 1; i >= 0; --i) {
|
||||
final AppWindowToken current = mAppTokens.get(i);
|
||||
if (!result.reachedToken) {
|
||||
if (current == token) {
|
||||
// We have reached the token we are interested in. Get whichever window occurs
|
||||
// after it that is on the same display.
|
||||
result.reachedToken = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
final WindowList tokenWindowList = dc.getTokenWindowsOnDisplay(current);
|
||||
if (tokenWindowList.size() > 0) {
|
||||
result.foundWindow = tokenWindowList.get(tokenWindowList.size() - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean fillsParent() {
|
||||
return mFullscreen || !StackId.isTaskResizeAllowed(mStack.mStackId);
|
||||
}
|
||||
|
||||
@@ -1320,6 +1320,30 @@ public class TaskStack implements DimLayer.DimLayerUser,
|
||||
return mTasks.indexOf(first) > mTasks.indexOf(second);
|
||||
}
|
||||
|
||||
void getWindowOnDisplayBeforeToken(DisplayContent dc, WindowToken token,
|
||||
DisplayContent.GetWindowOnDisplaySearchResults result) {
|
||||
for (int i = mTasks.size() - 1; i >= 0; --i) {
|
||||
final Task task = mTasks.get(i);
|
||||
task.getWindowOnDisplayBeforeToken(dc, token, result);
|
||||
if (result.reachedToken) {
|
||||
// We have reach the token we are interested in. End search.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void getWindowOnDisplayAfterToken(DisplayContent dc, WindowToken token,
|
||||
DisplayContent.GetWindowOnDisplaySearchResults result) {
|
||||
for (int i = mTasks.size() - 1; i >= 0; --i) {
|
||||
final Task task = mTasks.get(i);
|
||||
task.getWindowOnDisplayAfterToken(dc, token, result);
|
||||
if (result.foundWindow != null) {
|
||||
// We have found a window after the token. End search.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove once switched to use WindowContainer
|
||||
int getOrientation() {
|
||||
if (!StackId.canSpecifyOrientation(mStackId)) {
|
||||
|
||||
@@ -3980,60 +3980,6 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Places this window after the input window in the window list. */
|
||||
void addWindowToListAfter(WindowState pos) {
|
||||
final WindowList windows = pos.getWindowList();
|
||||
final int i = windows.indexOf(pos);
|
||||
if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
|
||||
"Adding window " + this + " at " + (i+1) + " of " + windows.size()
|
||||
+ " (after " + pos + ")");
|
||||
windows.add(i+1, this);
|
||||
mService.mWindowsChanged = true;
|
||||
}
|
||||
|
||||
/** Places this window before the input window in the window list. */
|
||||
void addWindowToListBefore(WindowState pos) {
|
||||
final WindowList windows = pos.getWindowList();
|
||||
int i = windows.indexOf(pos);
|
||||
if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
|
||||
"Adding window " + this + " at " + i + " of " + windows.size()
|
||||
+ " (before " + pos + ")");
|
||||
if (i < 0) {
|
||||
Slog.w(TAG_WM, "addWindowToListBefore: Unable to find " + pos + " in " + windows);
|
||||
i = 0;
|
||||
}
|
||||
windows.add(i, this);
|
||||
mService.mWindowsChanged = true;
|
||||
}
|
||||
|
||||
/** Adds this non-app window to the window list. */
|
||||
void addNonAppWindowToList() {
|
||||
final WindowList windows = getWindowList();
|
||||
|
||||
// Figure out where window should go, based on layer.
|
||||
int i;
|
||||
for (i = windows.size() - 1; i >= 0; i--) {
|
||||
final WindowState otherWin = windows.get(i);
|
||||
if (otherWin.getBaseType() != TYPE_WALLPAPER && otherWin.mBaseLayer <= mBaseLayer) {
|
||||
// Wallpaper wanders through the window list, for example to position itself
|
||||
// directly behind keyguard. Because of this it will break the ordering based on
|
||||
// WindowState.mBaseLayer. There might windows with higher mBaseLayer behind it and
|
||||
// we don't want the new window to appear above them. An example of this is adding
|
||||
// of the docked stack divider. Consider a scenario with the following ordering (top
|
||||
// to bottom): keyguard, wallpaper, assist preview, apps. We want the dock divider
|
||||
// to land below the assist preview, so the dock divider must ignore the wallpaper,
|
||||
// with which it shares the base layer.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
|
||||
"Free window: Adding window " + this + " at " + i + " of " + windows.size());
|
||||
windows.add(i, this);
|
||||
mService.mWindowsChanged = true;
|
||||
}
|
||||
|
||||
void updateReportedVisibility(UpdateReportedVisibilityResults results) {
|
||||
for (int i = mChildren.size() - 1; i >= 0; --i) {
|
||||
final WindowState c = (WindowState) mChildren.get(i);
|
||||
|
||||
@@ -147,7 +147,6 @@ class WindowToken extends WindowContainer {
|
||||
return highestAnimLayer;
|
||||
}
|
||||
|
||||
/* package level access for test. */
|
||||
WindowState getTopWindow() {
|
||||
if (mChildren.isEmpty()) {
|
||||
return null;
|
||||
@@ -160,7 +159,6 @@ class WindowToken extends WindowContainer {
|
||||
* @param target The window to search for.
|
||||
* @return The index of win in windows or of the window that is an ancestor of win.
|
||||
*/
|
||||
/* package level access for test. */
|
||||
int getWindowIndex(WindowState target) {
|
||||
for (int i = mChildren.size() - 1; i >= 0; --i) {
|
||||
final WindowState w = (WindowState) mChildren.get(i);
|
||||
@@ -171,256 +169,28 @@ class WindowToken extends WindowContainer {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of Windows in this token on the given Display.
|
||||
* @param displayContent The display we are interested in.
|
||||
* @return List of windows from token that are on displayContent.
|
||||
*/
|
||||
private WindowList getTokenWindowsOnDisplay(DisplayContent displayContent) {
|
||||
final WindowList windowList = new WindowList();
|
||||
final WindowList displayWindows = displayContent.getWindowList();
|
||||
final int count = displayWindows.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final WindowState win = displayWindows.get(i);
|
||||
if (win.mToken == this) {
|
||||
windowList.add(win);
|
||||
}
|
||||
}
|
||||
return windowList;
|
||||
}
|
||||
|
||||
// TODO: Now that we are no longer adding child windows to token directly, the rest of the code
|
||||
// in this method doesn't really belong here, but is it difficult to move at the moment. Need to
|
||||
// re-evaluate when figuring-out what to do about display window list.
|
||||
private void addChildWindow(final WindowState win) {
|
||||
final DisplayContent displayContent = win.getDisplayContent();
|
||||
if (displayContent == null) {
|
||||
return;
|
||||
}
|
||||
final WindowState parentWindow = win.getParentWindow();
|
||||
|
||||
WindowList windowsOnSameDisplay = getTokenWindowsOnDisplay(displayContent);
|
||||
|
||||
// Figure out this window's ordering relative to the parent window.
|
||||
final int wCount = windowsOnSameDisplay.size();
|
||||
final int sublayer = win.mSubLayer;
|
||||
int largestSublayer = Integer.MIN_VALUE;
|
||||
WindowState windowWithLargestSublayer = null;
|
||||
int i;
|
||||
for (i = 0; i < wCount; i++) {
|
||||
WindowState w = windowsOnSameDisplay.get(i);
|
||||
final int wSublayer = w.mSubLayer;
|
||||
if (wSublayer >= largestSublayer) {
|
||||
largestSublayer = wSublayer;
|
||||
windowWithLargestSublayer = w;
|
||||
}
|
||||
if (sublayer < 0) {
|
||||
// For negative sublayers, we go below all windows in the same sublayer.
|
||||
if (wSublayer >= sublayer) {
|
||||
win.addWindowToListBefore(wSublayer >= 0 ? parentWindow : w);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// For positive sublayers, we go above all windows in the same sublayer.
|
||||
if (wSublayer > sublayer) {
|
||||
win.addWindowToListBefore(w);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i >= wCount) {
|
||||
if (sublayer < 0) {
|
||||
win.addWindowToListBefore(parentWindow);
|
||||
} else {
|
||||
win.addWindowToListAfter(
|
||||
largestSublayer >= 0 ? windowWithLargestSublayer : parentWindow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addWindow(final WindowState win) {
|
||||
if (DEBUG_FOCUS) Slog.d(TAG_WM, "addWindow: win=" + win + " Callers=" + Debug.getCallers(5));
|
||||
|
||||
final DisplayContent dc = win.getDisplayContent();
|
||||
if (!win.isChildWindow()) {
|
||||
int tokenWindowsPos = 0;
|
||||
if (asAppWindowToken() != null) {
|
||||
tokenWindowsPos = addAppWindow(win);
|
||||
} else {
|
||||
win.addNonAppWindowToList();
|
||||
if (dc != null) {
|
||||
if (asAppWindowToken() != null) {
|
||||
tokenWindowsPos = dc.addAppWindowToWindowList(win);
|
||||
} else {
|
||||
dc.addNonAppWindowToWindowList(win);
|
||||
}
|
||||
}
|
||||
if (!mChildren.contains(win)) {
|
||||
if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
|
||||
mChildren.add(tokenWindowsPos, win);
|
||||
}
|
||||
} else {
|
||||
addChildWindow(win);
|
||||
} else if (dc != null) {
|
||||
dc.addChildWindowToWindowList(win);
|
||||
}
|
||||
}
|
||||
|
||||
private int addAppWindow(final WindowState win) {
|
||||
final DisplayContent displayContent = win.getDisplayContent();
|
||||
if (displayContent == null) {
|
||||
// It doesn't matter this display is going away.
|
||||
return 0;
|
||||
}
|
||||
final IWindow client = win.mClient;
|
||||
|
||||
final WindowList windows = displayContent.getWindowList();
|
||||
WindowList tokenWindowList = getTokenWindowsOnDisplay(displayContent);
|
||||
int tokenWindowsPos = 0;
|
||||
if (!tokenWindowList.isEmpty()) {
|
||||
return addAppWindowExisting(win, windows, tokenWindowList);
|
||||
}
|
||||
|
||||
// No windows from this token on this display
|
||||
if (mService.localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window "
|
||||
+ client.asBinder() + " (token=" + this + ")");
|
||||
|
||||
// Figure out where the window should go, based on the order of applications.
|
||||
WindowState pos = null;
|
||||
|
||||
final ArrayList<Task> tasks = displayContent.getTasks();
|
||||
int taskNdx;
|
||||
int tokenNdx = -1;
|
||||
for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
|
||||
AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
|
||||
for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
|
||||
final AppWindowToken t = tokens.get(tokenNdx);
|
||||
if (t == this) {
|
||||
--tokenNdx;
|
||||
if (tokenNdx < 0) {
|
||||
--taskNdx;
|
||||
if (taskNdx >= 0) {
|
||||
tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// We haven't reached the token yet; if this token is not going to the bottom and
|
||||
// has windows on this display, we can use it as an anchor for when we do reach the
|
||||
// token.
|
||||
tokenWindowList = getTokenWindowsOnDisplay(displayContent);
|
||||
if (!t.sendingToBottom && tokenWindowList.size() > 0) {
|
||||
pos = tokenWindowList.get(0);
|
||||
}
|
||||
}
|
||||
if (tokenNdx >= 0) {
|
||||
// early exit
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We now know the index into the apps. If we found an app window above, that gives us the
|
||||
// position; else we need to look some more.
|
||||
if (pos != null) {
|
||||
// Move behind any windows attached to this one.
|
||||
final WindowToken atoken = mService.mTokenMap.get(pos.mClient.asBinder());
|
||||
if (atoken != null) {
|
||||
tokenWindowList = atoken.getTokenWindowsOnDisplay(displayContent);
|
||||
final int NC = tokenWindowList.size();
|
||||
if (NC > 0) {
|
||||
WindowState bottom = tokenWindowList.get(0);
|
||||
if (bottom.mSubLayer < 0) {
|
||||
pos = bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
win.addWindowToListBefore(pos);
|
||||
return tokenWindowsPos;
|
||||
}
|
||||
|
||||
// Continue looking down until we find the first token that has windows on this display.
|
||||
for ( ; taskNdx >= 0; --taskNdx) {
|
||||
AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
|
||||
for ( ; tokenNdx >= 0; --tokenNdx) {
|
||||
final WindowToken t = tokens.get(tokenNdx);
|
||||
tokenWindowList = t.getTokenWindowsOnDisplay(displayContent);
|
||||
final int NW = tokenWindowList.size();
|
||||
if (NW > 0) {
|
||||
pos = tokenWindowList.get(NW-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tokenNdx >= 0) {
|
||||
// found
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos != null) {
|
||||
// Move in front of any windows attached to this one.
|
||||
final WindowToken atoken = mService.mTokenMap.get(pos.mClient.asBinder());
|
||||
if (atoken != null) {
|
||||
final WindowState top = atoken.getTopWindow();
|
||||
if (top != null && top.mSubLayer >= 0) {
|
||||
pos = top;
|
||||
}
|
||||
}
|
||||
win.addWindowToListAfter(pos);
|
||||
return tokenWindowsPos;
|
||||
}
|
||||
|
||||
// Just search for the start of this layer.
|
||||
final int myLayer = win.mBaseLayer;
|
||||
int i;
|
||||
for (i = windows.size() - 1; i >= 0; --i) {
|
||||
WindowState w = windows.get(i);
|
||||
// Dock divider shares the base layer with application windows, but we want to always
|
||||
// keep it above the application windows. The sharing of the base layer is intended
|
||||
// for window animations, which need to be above the dock divider for the duration
|
||||
// of the animation.
|
||||
if (w.mBaseLayer <= myLayer && w.mAttrs.type != TYPE_DOCK_DIVIDER) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
|
||||
"Based on layer: Adding window " + win + " at " + (i + 1) + " of "
|
||||
+ windows.size());
|
||||
windows.add(i + 1, win);
|
||||
mService.mWindowsChanged = true;
|
||||
return tokenWindowsPos;
|
||||
}
|
||||
|
||||
private int addAppWindowExisting(
|
||||
WindowState win, WindowList windowList, WindowList tokenWindowList) {
|
||||
|
||||
int tokenWindowsPos;
|
||||
// If this application has existing windows, we simply place the new window on top of
|
||||
// them... but keep the starting window on top.
|
||||
if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
|
||||
// Base windows go behind everything else.
|
||||
final WindowState lowestWindow = tokenWindowList.get(0);
|
||||
win.addWindowToListBefore(lowestWindow);
|
||||
tokenWindowsPos = getWindowIndex(lowestWindow);
|
||||
} else {
|
||||
final AppWindowToken atoken = win.mAppToken;
|
||||
final int windowListPos = tokenWindowList.size();
|
||||
final WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
|
||||
if (atoken != null && lastWindow == atoken.startingWindow) {
|
||||
win.addWindowToListBefore(lastWindow);
|
||||
tokenWindowsPos = getWindowIndex(lastWindow);
|
||||
} else {
|
||||
int newIdx = findIdxBasedOnAppTokens(win);
|
||||
// There is a window above this one associated with the same apptoken note that the
|
||||
// window could be a floating window that was created later or a window at the top
|
||||
// of the list of windows associated with this token.
|
||||
if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
|
||||
"not Base app: Adding window " + win + " at " + (newIdx + 1) + " of "
|
||||
+ windowList.size());
|
||||
windowList.add(newIdx + 1, win);
|
||||
if (newIdx < 0) {
|
||||
// No window from token found on win's display.
|
||||
tokenWindowsPos = 0;
|
||||
} else {
|
||||
tokenWindowsPos = getWindowIndex(windowList.get(newIdx)) + 1;
|
||||
}
|
||||
mService.mWindowsChanged = true;
|
||||
}
|
||||
}
|
||||
return tokenWindowsPos;
|
||||
}
|
||||
|
||||
int reAddAppWindows(DisplayContent displayContent, int index) {
|
||||
final int count = mChildren.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
@@ -434,21 +204,6 @@ class WindowToken extends WindowContainer {
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method finds out the index of a window that has the same app token as win. used for z
|
||||
* ordering the windows in mWindows
|
||||
*/
|
||||
private int findIdxBasedOnAppTokens(WindowState win) {
|
||||
final WindowList windows = win.getWindowList();
|
||||
for(int j = windows.size() - 1; j >= 0; j--) {
|
||||
final WindowState wentry = windows.get(j);
|
||||
if(wentry.mAppToken == win.mAppToken) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Return the first window in the token window list that isn't a starting window or null. */
|
||||
WindowState getFirstNonStartingWindow() {
|
||||
final int count = mChildren.size();
|
||||
|
||||
Reference in New Issue
Block a user