Misc fixes for window moving and resizing
- Do not skip resizeTask if we're starting or ending drag. We need
the relayout because surface mode is changing.
- When we're changing the surface mode, need to wait for the first
draw to finish before we can modify shown frame. Otherwise there
could be 1 old frame displayed with new position, which makes the
window position look a bit off.
- Clean up dragResizing/dragResizeChanged flags.
Change-Id: Ia396d6b88fd616ad57aa8cd24ca7e1161add7205
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index d3cea8d..0a3391c 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -3061,7 +3061,12 @@
return;
}
- if (task.mBounds != null && task.mBounds.equals(bounds)) {
+ // TODO: change resizedByUser to an enum (or bitmask?) to indicate the origin of
+ // this resize (eg. systemResize, userResize, forcedResized).
+ // If the resize is a drag-resize by user, let it go through even if the bounds
+ // is not changing, as we might need a relayout due to surface size change
+ // (to/from fullscreen).
+ if (task.mBounds != null && task.mBounds.equals(bounds) && !resizedByUser) {
// Nothing to do here...
return;
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index cc9efdb..58f0448 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -72,6 +72,12 @@
// For handling display rotations.
private Rect mTmpRect2 = new Rect();
+ // Whether the task is currently being drag-resized
+ private boolean mDragResizing;
+
+ // Whether the task is starting or ending to be drag-resized
+ private boolean mDragResizeChanging;
+
// The particular window with FLAG_DIM_BEHIND set. If null, hide mDimLayer.
WindowStateAnimator mDimWinAnimator;
// Used to support {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND}
@@ -227,10 +233,34 @@
return boundsChange;
}
+ boolean resizeLocked(Rect bounds, Configuration configuration) {
+ int boundsChanged = setBounds(bounds, configuration);
+ if (mDragResizeChanging) {
+ boundsChanged |= BOUNDS_CHANGE_SIZE;
+ mDragResizeChanging = false;
+ }
+ if (boundsChanged == BOUNDS_CHANGE_NONE) {
+ return false;
+ }
+ if ((boundsChanged & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
+ resizeWindows();
+ }
+ return true;
+ }
+
void getBounds(Rect out) {
out.set(mBounds);
}
+ void setDragResizing(boolean dragResizing) {
+ mDragResizeChanging = mDragResizing != dragResizing;
+ mDragResizing = dragResizing;
+ }
+
+ boolean isDragResizing() {
+ return mDragResizing;
+ }
+
void updateDisplayInfo(final DisplayContent displayContent) {
if (displayContent == null) {
return;
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 17b56ba..5487349 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -86,8 +86,7 @@
private int mMinVisibleWidth;
private int mMinVisibleHeight;
- private int mTaskId;
- private TaskStack mStack;
+ private Task mTask;
private boolean mResizing;
private final Rect mWindowOriginalBounds = new Rect();
private final Rect mWindowDragBounds = new Rect();
@@ -136,7 +135,7 @@
}
try {
mService.mActivityManager.resizeTask(
- mTaskId, mWindowDragBounds, true /* resizedByUser */);
+ mTask.mTaskId, mWindowDragBounds, true /* resizedByUser */);
} catch(RemoteException e) {}
} break;
@@ -156,21 +155,29 @@
}
if (endDrag) {
- mResizing = false;
+ synchronized (mService.mWindowMap) {
+ endDragLocked();
+ }
try {
- mService.mActivityManager.resizeTask(
- mTaskId, mWindowDragBounds, true /* resizedByUser */);
+ if (mResizing) {
+ // We were using fullscreen surface during resizing. Request
+ // resizeTask() one last time to restore surface to window size.
+ mService.mActivityManager.resizeTask(
+ mTask.mTaskId, mWindowDragBounds, true /* resizedByUser */);
+ }
+
+ if (mCurrentDimSide != CTRL_NONE) {
+ final int createMode = mCurrentDimSide == CTRL_LEFT
+ ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
+ : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
+ mService.mActivityManager.moveTaskToDockedStack(
+ mTask.mTaskId, createMode, true /*toTop*/);
+ }
} catch(RemoteException e) {}
+
// Post back to WM to handle clean-ups. We still need the input
// event handler for the last finishInputEvent()!
mService.mH.sendEmptyMessage(H.FINISH_TASK_POSITIONING);
- if (mCurrentDimSide != CTRL_NONE) {
- final int createMode = mCurrentDimSide == CTRL_LEFT
- ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
- : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
- mService.mActivityManager.moveTaskToDockedStack(
- mTaskId, createMode, true /*toTop*/);
- }
}
handled = true;
} catch (Exception e) {
@@ -291,10 +298,6 @@
mService.resumeRotationLocked();
}
- boolean isTaskResizing(final Task task) {
- return mResizing && task != null && mTaskId == task.mTaskId;
- }
-
void startDragLocked(WindowState win, boolean resize, float startX, float startY) {
if (DEBUG_TASK_POSITIONING) {
Slog.d(TAG, "startDragLocked: win=" + win + ", resize=" + resize
@@ -318,13 +321,16 @@
mResizing = true;
}
- final Task task = win.getTask();
- mTaskId = task.mTaskId;
- mStack = task.mStack;
+ mTask = win.getTask();
mStartDragX = startX;
mStartDragY = startY;
- mService.getTaskBounds(mTaskId, mWindowOriginalBounds);
+ mService.getTaskBounds(mTask.mTaskId, mWindowOriginalBounds);
+ }
+
+ private void endDragLocked() {
+ mResizing = false;
+ mTask.setDragResizing(false);
}
/** Returns true if the move operation should be ended. */
@@ -354,11 +360,12 @@
bottom = Math.max(top + mMinVisibleHeight, bottom + deltaY);
}
mWindowDragBounds.set(left, top, right, bottom);
+ mTask.setDragResizing(true);
return false;
}
// This is a moving operation.
- mStack.getBounds(mTmpRect);
+ mTask.mStack.getBounds(mTmpRect);
mTmpRect.inset(mMinVisibleWidth, mMinVisibleHeight);
if (!mTmpRect.contains((int) x, (int) y)) {
// We end the moving operation if position is outside the stack bounds.
@@ -397,13 +404,13 @@
* shouldn't be shown.
*/
private int getDimSide(int x) {
- if (mStack.mStackId != FREEFORM_WORKSPACE_STACK_ID
- || !mStack.isFullscreen()
+ if (mTask.mStack.mStackId != FREEFORM_WORKSPACE_STACK_ID
+ || !mTask.mStack.isFullscreen()
|| mService.mCurConfiguration.orientation != ORIENTATION_LANDSCAPE) {
return CTRL_NONE;
}
- mStack.getBounds(mTmpRect);
+ mTask.mStack.getBounds(mTmpRect);
if (x - mSideMargin <= mTmpRect.left) {
return CTRL_LEFT;
}
@@ -415,7 +422,7 @@
}
private void showDimLayer() {
- mStack.getBounds(mTmpRect);
+ mTask.mStack.getBounds(mTmpRect);
if (mCurrentDimSide == CTRL_LEFT) {
mTmpRect.right = mTmpRect.centerX();
} else if (mCurrentDimSide == CTRL_RIGHT) {
@@ -433,7 +440,7 @@
@Override /** {@link DimLayer.DimLayerUser} */
public DisplayInfo getDisplayInfo() {
- return mStack.getDisplayInfo();
+ return mTask.mStack.getDisplayInfo();
}
private int getDragLayerLocked() {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 5bf296e..ffc848d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2589,9 +2589,13 @@
}
}
- dragResizing = win.isDragResizing();
- if (win.mDragResizing != dragResizing) {
- win.mDragResizing = dragResizing;
+ // If we're starting a drag-resize, we'll be changing the surface size as well as
+ // notifying the client to render to with an offset from the surface's top-left.
+ // Do a screen freeze, and keep the old surface until the the first frame drawn to
+ // the new surface comes back, so that we avoid a flash due to mismatching surface
+ // setups on window manager side and client side.
+ if (win.isDragResizeChanged()) {
+ win.setDragResizing();
if (win.mHasSurface) {
winAnimator.mDestroyPendingSurfaceUponRedraw = true;
winAnimator.mSurfaceDestroyDeferred = true;
@@ -2600,6 +2604,7 @@
toBeDisplayed = true;
}
}
+ dragResizing = win.isDragResizing();
try {
if (!win.mHasSurface) {
surfaceChanged = true;
@@ -4688,16 +4693,10 @@
throw new IllegalArgumentException("resizeTask: taskId " + taskId
+ " not found.");
}
- final int boundsChanged = task.setBounds(bounds, configuration);
- if (boundsChanged != Task.BOUNDS_CHANGE_NONE) {
- if ((boundsChanged & Task.BOUNDS_CHANGE_SIZE) == Task.BOUNDS_CHANGE_SIZE) {
- task.resizeWindows();
- }
- if (relayout) {
- task.getDisplayContent().layoutNeeded = true;
- mWindowPlacerLocked.performSurfacePlacement();
- }
+ if (task.resizeLocked(bounds, configuration) && relayout) {
+ task.getDisplayContent().layoutNeeded = true;
+ mWindowPlacerLocked.performSurfacePlacement();
}
}
}
@@ -8480,7 +8479,7 @@
Slog.v(TAG, "Win " + w + " config changed: "
+ mCurConfiguration);
}
- final boolean dragResizingChanged = w.mDragResizing != w.isDragResizing();
+ final boolean dragResizingChanged = w.isDragResizeChanged();
if (localLOGV) Slog.v(TAG, "Resizing " + w
+ ": configChanged=" + configChanged
+ " dragResizingChanged=" + dragResizingChanged
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index fa28eba..7ed5249 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -129,6 +129,7 @@
boolean mAttachedHidden; // is our parent window hidden?
boolean mWallpaperVisible; // for wallpaper, what was last vis report?
boolean mDragResizing;
+ boolean mDragResizeChanging;
RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks;
@@ -1691,9 +1692,18 @@
return task != null && task.inFreeformWorkspace();
}
- boolean isDragResizing() {
+ boolean isDragResizeChanged() {
final Task task = getTask();
- return mService.mTaskPositioner != null && mService.mTaskPositioner.isTaskResizing(task);
+ return task != null && mDragResizing != task.isDragResizing();
+ }
+
+ void setDragResizing() {
+ final Task task = getTask();
+ mDragResizing = task != null && task.isDragResizing();
+ }
+
+ boolean isDragResizing() {
+ return mDragResizing;
}
void dump(PrintWriter pw, String prefix, boolean dumpAll) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index e6fef2f..07e1fce 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -818,7 +818,7 @@
// so that we don't need to reallocate during the process. This also prevents
// buffer drops due to size mismatch.
final DisplayInfo displayInfo = w.getDisplayInfo();
- if (displayInfo != null && w.mDragResizing) {
+ if (displayInfo != null && w.isDragResizing()) {
left = 0;
top = 0;
width = displayInfo.logicalWidth;
@@ -1211,6 +1211,13 @@
return;
} else if (mIsWallpaper && mService.mWindowPlacerLocked.mWallpaperActionPending) {
return;
+ } else if (mWin.isDragResizeChanged()) {
+ // This window is awaiting a relayout because user just started (or ended)
+ // drag-resizing. The shown frame (which affects surface size and pos)
+ // should not be updated until we get next finished draw with the new surface.
+ // Otherwise one or two frames rendered with old settings would be displayed
+ // with new geometry.
+ return;
}
if (WindowManagerService.localLOGV) Slog.v(
@@ -1333,7 +1340,7 @@
final boolean fullscreen = w.isFullscreen(displayInfo.appWidth, displayInfo.appHeight);
final Rect clipRect = mTmpClipRect;
- if (w.mDragResizing) {
+ if (w.isDragResizing()) {
// When we're doing a drag-resizing, the surface is set up to cover full screen.
// Set the clip rect to be the same size so that we don't get any scaling.
clipRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
@@ -1423,7 +1430,7 @@
// so that we don't need to reallocate during the process. This also prevents
// buffer drops due to size mismatch.
final DisplayInfo displayInfo = w.getDisplayInfo();
- if (displayInfo != null && w.mDragResizing) {
+ if (displayInfo != null && w.isDragResizing()) {
left = 0;
top = 0;
width = displayInfo.logicalWidth;