Merge "Some cleanups for window cropping functionality."

This commit is contained in:
TreeHugger Robot
2016-11-30 00:24:12 +00:00
committed by Android (Google) Code Review
3 changed files with 277 additions and 133 deletions

View File

@@ -3190,7 +3190,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
boolean isDockedResizing() {
return mDragResizing && getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER;
return (mDragResizing && getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER)
|| (isChildWindow() && getParentWindow().isDockedResizing());
}
void dump(PrintWriter pw, String prefix, boolean dumpAll) {
@@ -4144,6 +4145,105 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
}
/**
* Calculate the window crop according to system decor policy. In general this is
* the system decor rect (see #calculateSystemDecorRect), but we also have some
* special cases. This rectangle is in screen space.
*/
void calculatePolicyCrop(Rect policyCrop) {
final DisplayContent displayContent = getDisplayContent();
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
if (!isDefaultDisplay()) {
// On a different display there is no system decor. Crop the window
// by the screen boundaries.
// TODO(multi-display)
policyCrop.set(0, 0, mCompatFrame.width(), mCompatFrame.height());
policyCrop.intersect(-mCompatFrame.left, -mCompatFrame.top,
displayInfo.logicalWidth - mCompatFrame.left,
displayInfo.logicalHeight - mCompatFrame.top);
} else if (mLayer >= mService.mSystemDecorLayer) {
// Above the decor layer is easy, just use the entire window
policyCrop.set(0, 0, mCompatFrame.width(), mCompatFrame.height());
} else if (mDecorFrame.isEmpty()) {
// Windows without policy decor aren't cropped.
policyCrop.set(0, 0, mCompatFrame.width(), mCompatFrame.height());
} else {
// Crop to the system decor specified by policy.
calculateSystemDecorRect(policyCrop);
}
}
/**
* The system decor rect is the region of the window which is not covered
* by system decorations.
*/
private void calculateSystemDecorRect(Rect systemDecorRect) {
final Rect decorRect = mDecorFrame;
final int width = mFrame.width();
final int height = mFrame.height();
// Compute the offset of the window in relation to the decor rect.
final int left = mXOffset + mFrame.left;
final int top = mYOffset + mFrame.top;
// Initialize the decor rect to the entire frame.
if (isDockedResizing()) {
// If we are resizing with the divider, the task bounds might be smaller than the
// stack bounds. The system decor is used to clip to the task bounds, which we don't
// want in this case in order to avoid holes.
//
// We take care to not shrink the width, for surfaces which are larger than
// the display region. Of course this area will not eventually be visible
// but if we truncate the width now, we will calculate incorrectly
// when adjusting to the stack bounds.
final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
systemDecorRect.set(0, 0,
Math.max(width, displayInfo.logicalWidth),
Math.max(height, displayInfo.logicalHeight));
} else {
systemDecorRect.set(0, 0, width, height);
}
// If a freeform window is animating from a position where it would be cutoff, it would be
// cutoff during the animation. We don't want that, so for the duration of the animation
// we ignore the decor cropping and depend on layering to position windows correctly.
final boolean cropToDecor = !(inFreeformWorkspace() && isAnimatingLw());
if (cropToDecor) {
// Intersect with the decor rect, offsetted by window position.
systemDecorRect.intersect(decorRect.left - left, decorRect.top - top,
decorRect.right - left, decorRect.bottom - top);
}
// If size compatibility is being applied to the window, the
// surface is scaled relative to the screen. Also apply this
// scaling to the crop rect. We aren't using the standard rect
// scale function because we want to round things to make the crop
// always round to a larger rect to ensure we don't crop too
// much and hide part of the window that should be seen.
if (mEnforceSizeCompat && mInvGlobalScale != 1.0f) {
final float scale = mInvGlobalScale;
systemDecorRect.left = (int) (systemDecorRect.left * scale - 0.5f);
systemDecorRect.top = (int) (systemDecorRect.top * scale - 0.5f);
systemDecorRect.right = (int) ((systemDecorRect.right + 1) * scale - 0.5f);
systemDecorRect.bottom = (int) ((systemDecorRect.bottom + 1) * scale - 0.5f);
}
}
/**
* Expand the given rectangle by this windows surface insets. This
* takes you from the 'window size' to the 'surface size'.
* The surface insets are positive in each direction, so we inset by
* the inverse.
*/
void expandForSurfaceInsets(Rect r) {
r.inset(-mAttrs.surfaceInsets.left,
-mAttrs.surfaceInsets.top,
-mAttrs.surfaceInsets.right,
-mAttrs.surfaceInsets.bottom);
}
// TODO: Hack to work around the number of states AppWindowToken needs to access without having
// access to its windows children. Need to investigate re-writing
// {@link AppWindowToken#updateReportedVisibilityLocked} so this can be removed.

View File

@@ -22,6 +22,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static com.android.server.wm.AppWindowAnimator.sDummyAnimation;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
@@ -1068,99 +1069,75 @@ class WindowStateAnimator {
}
}
private void calculateSystemDecorRect() {
final WindowState w = mWin;
final Rect decorRect = w.mDecorFrame;
final int width = w.mFrame.width();
final int height = w.mFrame.height();
// Compute the offset of the window in relation to the decor rect.
final int left = w.mXOffset + w.mFrame.left;
final int top = w.mYOffset + w.mFrame.top;
// Initialize the decor rect to the entire frame.
if (w.isDockedResizing() ||
(w.isChildWindow() && w.getParentWindow().isDockedResizing())) {
// If we are resizing with the divider, the task bounds might be smaller than the
// stack bounds. The system decor is used to clip to the task bounds, which we don't
// want in this case in order to avoid holes.
//
// We take care to not shrink the width, for surfaces which are larger than
// the display region. Of course this area will not eventually be visible
// but if we truncate the width now, we will calculate incorrectly
// when adjusting to the stack bounds.
final DisplayInfo displayInfo = w.getDisplayContent().getDisplayInfo();
mSystemDecorRect.set(0, 0,
Math.max(width, displayInfo.logicalWidth),
Math.max(height, displayInfo.logicalHeight));
} else {
mSystemDecorRect.set(0, 0, width, height);
}
// If a freeform window is animating from a position where it would be cutoff, it would be
// cutoff during the animation. We don't want that, so for the duration of the animation
// we ignore the decor cropping and depend on layering to position windows correctly.
final boolean cropToDecor = !(w.inFreeformWorkspace() && w.isAnimatingLw());
if (cropToDecor) {
// Intersect with the decor rect, offsetted by window position.
mSystemDecorRect.intersect(decorRect.left - left, decorRect.top - top,
decorRect.right - left, decorRect.bottom - top);
}
// If size compatibility is being applied to the window, the
// surface is scaled relative to the screen. Also apply this
// scaling to the crop rect. We aren't using the standard rect
// scale function because we want to round things to make the crop
// always round to a larger rect to ensure we don't crop too
// much and hide part of the window that should be seen.
if (w.mEnforceSizeCompat && w.mInvGlobalScale != 1.0f) {
final float scale = w.mInvGlobalScale;
mSystemDecorRect.left = (int) (mSystemDecorRect.left * scale - 0.5f);
mSystemDecorRect.top = (int) (mSystemDecorRect.top * scale - 0.5f);
mSystemDecorRect.right = (int) ((mSystemDecorRect.right + 1) * scale - 0.5f);
mSystemDecorRect.bottom = (int) ((mSystemDecorRect.bottom + 1) * scale - 0.5f);
}
/**
* In some scenarios we use a screen space clip rect (so called, final clip rect)
* to crop to stack bounds. Generally because it's easier to deal with while
* animating.
*
* @return True in scenarios where we use the final clip rect for stack clipping.
*/
private boolean useFinalClipRect() {
return (isAnimationSet() && resolveStackClip() == STACK_CLIP_AFTER_ANIM)
|| mDestroyPreservedSurfaceUponRedraw || mWin.inPinnedWorkspace();
}
void calculateSurfaceWindowCrop(Rect clipRect, Rect finalClipRect) {
/**
* Calculate the screen-space crop rect and fill finalClipRect.
* @return true if finalClipRect has been filled, otherwise,
* no screen space crop should be applied.
*/
private boolean calculateFinalCrop(Rect finalClipRect) {
final WindowState w = mWin;
final DisplayContent displayContent = w.getDisplayContent();
finalClipRect.setEmpty();
if (displayContent == null) {
clipRect.setEmpty();
finalClipRect.setEmpty();
return;
return false;
}
if (!shouldCropToStackBounds() || !useFinalClipRect()) {
return false;
}
// Task is non-null per shouldCropToStackBounds
final TaskStack stack = w.getTask().mStack;
stack.getDimBounds(finalClipRect);
w.expandForSurfaceInsets(finalClipRect);
return true;
}
/**
* Calculate the window-space crop rect and fill clipRect.
* @return true if clipRect has been filled otherwise, no window space
* crop should be applied.
*/
boolean calculateCrop(Rect clipRect) {
final WindowState w = mWin;
final DisplayContent displayContent = w.getDisplayContent();
clipRect.setEmpty();
if (displayContent == null) {
return false;
}
if (w.inPinnedWorkspace()) {
return false;
}
// If we're animating, the wallpaper should only
// be updated at the end of the animation.
if (w.mAttrs.type == TYPE_WALLPAPER) {
return false;
}
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
if (DEBUG_WINDOW_CROP) Slog.d(TAG,
"Updating crop win=" + w + " mLastCrop=" + mLastClipRect);
// Need to recompute a new system decor rect each time.
if (!w.isDefaultDisplay()) {
// On a different display there is no system decor. Crop the window
// by the screen boundaries.
mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
mSystemDecorRect.intersect(-w.mCompatFrame.left, -w.mCompatFrame.top,
displayInfo.logicalWidth - w.mCompatFrame.left,
displayInfo.logicalHeight - w.mCompatFrame.top);
} else if (w.mLayer >= mService.mSystemDecorLayer) {
// Above the decor layer is easy, just use the entire window.
mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
} else if (w.mDecorFrame.isEmpty()) {
// Windows without policy decor aren't cropped.
mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
} else if (w.mAttrs.type == LayoutParams.TYPE_WALLPAPER && mAnimator.isAnimating()) {
// If we're animating, the wallpaper crop should only be updated at the end of the
// animation.
mTmpClipRect.set(mSystemDecorRect);
calculateSystemDecorRect();
mSystemDecorRect.union(mTmpClipRect);
} else {
// Crop to the system decor specified by policy.
calculateSystemDecorRect();
if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop win=" + w + " mDecorFrame="
+ w.mDecorFrame + " mSystemDecorRect=" + mSystemDecorRect);
}
w.calculatePolicyCrop(mSystemDecorRect);
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 isFreeformResizing =
@@ -1178,12 +1155,7 @@ class WindowStateAnimator {
clipRect.offset(w.mShownPosition.x, w.mShownPosition.y);
}
// Expand the clip rect for surface insets.
final WindowManager.LayoutParams attrs = w.mAttrs;
clipRect.left -= attrs.surfaceInsets.left;
clipRect.top -= attrs.surfaceInsets.top;
clipRect.right += attrs.surfaceInsets.right;
clipRect.bottom += attrs.surfaceInsets.bottom;
w.expandForSurfaceInsets(clipRect);
if (mHasClipRect && fullscreen) {
// We intersect the clip rect specified by the transformation with the expanded system
@@ -1193,10 +1165,11 @@ class WindowStateAnimator {
}
// The clip rect was generated assuming (0,0) as the window origin,
// so we need to translate to match the actual surface coordinates.
clipRect.offset(attrs.surfaceInsets.left, attrs.surfaceInsets.top);
clipRect.offset(w.mAttrs.surfaceInsets.left, w.mAttrs.surfaceInsets.top);
finalClipRect.setEmpty();
adjustCropToStackBounds(w, clipRect, finalClipRect, isFreeformResizing);
if (!useFinalClipRect()) {
adjustCropToStackBounds(clipRect, isFreeformResizing);
}
if (DEBUG_WINDOW_CROP) Slog.d(TAG,
"win=" + w + " Clip rect after stack adjustment=" + clipRect);
@@ -1206,10 +1179,11 @@ class WindowStateAnimator {
if (w.hasJustMovedInStack() && mLastClipRect.isEmpty() && !clipRect.isEmpty()) {
clipRect.setEmpty();
}
return true;
}
void updateSurfaceWindowCrop(Rect clipRect, Rect finalClipRect, boolean recoveringMemory) {
if (DEBUG_WINDOW_CROP) Slog.d(TAG, "updateSurfaceWindowCrop: win=" + mWin
private void applyCrop(Rect clipRect, Rect finalClipRect, boolean recoveringMemory) {
if (DEBUG_WINDOW_CROP) Slog.d(TAG, "applyCrop: win=" + mWin
+ " clipRect=" + clipRect + " finalClipRect=" + finalClipRect);
if (clipRect != null) {
if (!clipRect.equals(mLastClipRect)) {
@@ -1219,6 +1193,11 @@ class WindowStateAnimator {
} else {
mSurfaceController.clearCropInTransaction(recoveringMemory);
}
if (finalClipRect == null) {
finalClipRect = mService.mTmpRect;
finalClipRect.setEmpty();
}
if (!finalClipRect.equals(mLastFinalClipRect)) {
mLastFinalClipRect.set(finalClipRect);
mSurfaceController.setFinalCropInTransaction(finalClipRect);
@@ -1236,9 +1215,9 @@ class WindowStateAnimator {
return mStackClip;
}
}
private void adjustCropToStackBounds(WindowState w, Rect clipRect, Rect finalClipRect,
boolean isFreeformResizing) {
private boolean shouldCropToStackBounds() {
final WindowState w = mWin;
final DisplayContent displayContent = w.getDisplayContent();
if (displayContent != null && !displayContent.isDefaultDisplay) {
// There are some windows that live on other displays while their app and main window
@@ -1246,22 +1225,32 @@ class WindowStateAnimator {
// to the stack bounds which is only currently supported on the default display.
// TODO(multi-display): Need to support cropping to stack bounds on other displays
// when we have stacks on other displays.
return;
return false;
}
final Task task = w.getTask();
if (task == null || !task.cropWindowsToStackBounds()) {
return;
return false;
}
final int stackClip = resolveStackClip();
// It's animating and we don't want to clip it to stack bounds during animation - abort.
if (isAnimationSet() && stackClip == STACK_CLIP_NONE) {
return false;
}
return true;
}
private void adjustCropToStackBounds(Rect clipRect,
boolean isFreeformResizing) {
final WindowState w = mWin;
if (!shouldCropToStackBounds()) {
return;
}
final TaskStack stack = task.mStack;
final TaskStack stack = w.getTask().mStack;
stack.getDimBounds(mTmpStackBounds);
final Rect surfaceInsets = w.getAttrs().surfaceInsets;
// When we resize we use the big surface approach, which means we can't trust the
@@ -1272,34 +1261,25 @@ class WindowStateAnimator {
final int frameY = isFreeformResizing ? (int) mSurfaceController.getY() :
w.mFrame.top + mWin.mYOffset - surfaceInsets.top;
// If we are animating, we either apply the clip before applying all the animation
// transformation or after all the transformation.
final boolean useFinalClipRect = isAnimationSet() && stackClip == STACK_CLIP_AFTER_ANIM
|| mDestroyPreservedSurfaceUponRedraw;
// We need to do some acrobatics with surface position, because their clip region is
// relative to the inside of the surface, but the stack bounds aren't.
if (useFinalClipRect) {
finalClipRect.set(mTmpStackBounds);
} else {
if (StackId.hasWindowShadow(stack.mStackId)
&& !StackId.isTaskResizeAllowed(stack.mStackId)) {
if (StackId.hasWindowShadow(stack.mStackId)
&& !StackId.isTaskResizeAllowed(stack.mStackId)) {
// The windows in this stack display drop shadows and the fill the entire stack
// area. Adjust the stack bounds we will use to cropping take into account the
// offsets we use to display the drop shadow so it doesn't get cropped.
mTmpStackBounds.inset(-surfaceInsets.left, -surfaceInsets.top,
-surfaceInsets.right, -surfaceInsets.bottom);
}
clipRect.left = Math.max(0,
Math.max(mTmpStackBounds.left, frameX + clipRect.left) - frameX);
clipRect.top = Math.max(0,
Math.max(mTmpStackBounds.top, frameY + clipRect.top) - frameY);
clipRect.right = Math.max(0,
Math.min(mTmpStackBounds.right, frameX + clipRect.right) - frameX);
clipRect.bottom = Math.max(0,
Math.min(mTmpStackBounds.bottom, frameY + clipRect.bottom) - frameY);
}
clipRect.left = Math.max(0,
Math.max(mTmpStackBounds.left, frameX + clipRect.left) - frameX);
clipRect.top = Math.max(0,
Math.max(mTmpStackBounds.top, frameY + clipRect.top) - frameY);
clipRect.right = Math.max(0,
Math.min(mTmpStackBounds.right, frameX + clipRect.right) - frameX);
clipRect.bottom = Math.max(0,
Math.min(mTmpStackBounds.bottom, frameY + clipRect.bottom) - frameY);
}
void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
@@ -1339,7 +1319,13 @@ class WindowStateAnimator {
// updates until a resize occurs.
mService.markForSeamlessRotation(w, w.mSeamlesslyRotated && !mSurfaceResized);
calculateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect);
Rect clipRect = null, finalClipRect = null;
if (calculateCrop(mTmpClipRect)) {
clipRect = mTmpClipRect;
}
if (calculateFinalCrop(mTmpFinalClipRect)) {
finalClipRect = mTmpFinalClipRect;
}
float surfaceWidth = mSurfaceController.getWidth();
float surfaceHeight = mSurfaceController.getHeight();
@@ -1404,16 +1390,8 @@ class WindowStateAnimator {
mSurfaceController.forceScaleableInTransaction(false);
}
Rect clipRect = mTmpClipRect;
if (w.inPinnedWorkspace()) {
clipRect = null;
task.mStack.getDimBounds(mTmpFinalClipRect);
mTmpFinalClipRect.inset(-w.mAttrs.surfaceInsets.left, -w.mAttrs.surfaceInsets.top,
-w.mAttrs.surfaceInsets.right, -w.mAttrs.surfaceInsets.bottom);
}
if (!w.mSeamlesslyRotated) {
updateSurfaceWindowCrop(clipRect, mTmpFinalClipRect, recoveringMemory);
applyCrop(clipRect, finalClipRect, recoveringMemory);
mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * mExtraHScale,
mDtDx * w.mVScale * mExtraVScale,
mDsDy * w.mHScale * mExtraHScale,
@@ -1571,8 +1549,7 @@ class WindowStateAnimator {
mService.openSurfaceTransaction();
mSurfaceController.setPositionInTransaction(mWin.mFrame.left + left,
mWin.mFrame.top + top, false);
calculateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect);
updateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect, false);
applyCrop(null, null, false);
} catch (RuntimeException e) {
Slog.w(TAG, "Error positioning surface of " + mWin
+ " pos=(" + left + "," + top + ")", e);

View File

@@ -27,6 +27,7 @@ import android.platform.test.annotations.Presubmit;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.IWindow;
import android.view.WindowManager;
@@ -53,6 +54,7 @@ public class WindowFrameTests {
class WindowStateWithTask extends WindowState {
final Task mTask;
boolean mDockedResizingForTest = false;
WindowStateWithTask(WindowManager.LayoutParams attrs, Task t) {
super(sWm, null, mIWindow, mWindowToken, null, 0, 0, attrs, 0, 0);
mTask = t;
@@ -62,6 +64,11 @@ public class WindowFrameTests {
Task getTask() {
return mTask;
}
@Override
boolean isDockedResizing() {
return mDockedResizingForTest;
}
};
class TaskWithBounds extends Task {
@@ -92,6 +99,10 @@ public class WindowFrameTests {
public void setUp() throws Exception {
final Context context = InstrumentationRegistry.getTargetContext();
sWm = TestWindowManagerPolicy.getWindowManagerService(context);
// Just any non zero value.
sWm.mSystemDecorLayer = 10000;
mWindowToken = new WindowToken(sWm, new Binder(), 0, false,
sWm.getDefaultDisplayContentLocked());
mStubStack = new TaskStack(sWm, 0);
@@ -274,7 +285,63 @@ public class WindowFrameTests {
assertRect(w.mContentInsets, 0, 0, 100, 100);
}
private WindowState createWindow(Task task, int width, int height) {
@Test
public void testCalculatePolicyCrop() {
final WindowStateWithTask w = createWindow(
new TaskWithBounds(null), FILL_PARENT, FILL_PARENT);
w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
final Rect pf = new Rect(0, 0, 1000, 1000);
final Rect df = pf;
final Rect of = df;
final Rect cf = new Rect(pf);
// Produce some insets
cf.top += 50;
cf.bottom -= 100;
final Rect vf = cf;
final Rect sf = vf;
// We use a decor content frame with insets to produce cropping.
Rect dcf = cf;
final Rect policyCrop = new Rect();
w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null);
w.calculatePolicyCrop(policyCrop);
// If we were above system decor we wouldnt' get any cropping though
w.mLayer = sWm.mSystemDecorLayer + 1;
w.calculatePolicyCrop(policyCrop);
assertRect(policyCrop, 0, 0, 1000, 1000);
w.mLayer = 1;
dcf.setEmpty();
// Likewise with no decor frame we would get no crop
w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null);
w.calculatePolicyCrop(policyCrop);
assertRect(policyCrop, 0, 0, 1000, 1000);
// Now we set up a window which doesn't fill the entire decor frame.
// Normally it would be cropped to it's frame but in the case of docked resizing
// we need to account for the fact the windows surface will be made
// fullscreen and thus also make the crop fullscreen.
w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
w.mAttrs.width = 500;
w.mAttrs.height = 500;
w.mRequestedWidth = 500;
w.mRequestedHeight = 500;
w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf);
w.calculatePolicyCrop(policyCrop);
// Normally the crop is shrunk from the decor frame
// to the computed window frame.
assertRect(policyCrop, 0, 0, 500, 500);
w.mDockedResizingForTest = true;
w.calculatePolicyCrop(policyCrop);
// But if we are docked resizing it won't be.
final DisplayInfo displayInfo = w.getDisplayContent().getDisplayInfo();
assertRect(policyCrop, 0, 0, 1000, 1000);
}
private WindowStateWithTask createWindow(Task task, int width, int height) {
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
attrs.width = width;
attrs.height = height;