diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index d146e5e8ce27b..cd196072e981c 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -167,6 +167,7 @@ public abstract class WallpaperService extends Service { final Rect mDispatchedOutsets = new Rect(); final Rect mFinalSystemInsets = new Rect(); final Rect mFinalStableInsets = new Rect(); + final Rect mBackdropFrame = new Rect(); final Configuration mConfiguration = new Configuration(); final WindowManager.LayoutParams mLayout @@ -675,8 +676,8 @@ public abstract class WallpaperService extends Service { final int relayoutResult = mSession.relayout( mWindow, mWindow.mSeq, mLayout, mWidth, mHeight, View.VISIBLE, 0, mWinFrame, mOverscanInsets, mContentInsets, - mVisibleInsets, mStableInsets, mOutsets, mConfiguration, - mSurfaceHolder.mSurface); + mVisibleInsets, mStableInsets, mOutsets, mBackdropFrame, + mConfiguration, mSurfaceHolder.mSurface); if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface + ", frame=" + mWinFrame); diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index b3cd8c11f0f94..bea36c0a2d43d 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -81,6 +81,8 @@ interface IWindowSession { * so complex relayout of the window should not happen based on them. * @param outOutsets Rect in which is placed the dead area of the screen that we would like to * treat as real display. Example of such area is a chin in some models of wearable devices. + * @param outBackdropFrame Rect which is used draw the resizing background during a resize + * operation. * @param outConfiguration New configuration of window, if it is now * becoming visible and the global configuration has changed since it * was last displayed. @@ -93,7 +95,8 @@ interface IWindowSession { int requestedWidth, int requestedHeight, int viewVisibility, int flags, out Rect outFrame, out Rect outOverscanInsets, out Rect outContentInsets, out Rect outVisibleInsets, out Rect outStableInsets, - out Rect outOutsets, out Configuration outConfig, out Surface outSurface); + out Rect outOutsets, out Rect outBackdropFrame, out Configuration outConfig, + out Surface outSurface); /** * Position a window relative to it's parent (attached) window without triggering diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index f4fa98029be7d..0981e697d5b62 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -107,6 +107,7 @@ public class SurfaceView extends View { final Rect mContentInsets = new Rect(); final Rect mStableInsets = new Rect(); final Rect mOutsets = new Rect(); + final Rect mBackdropFrame = new Rect(); final Configuration mConfiguration = new Configuration(); static final int KEEP_SCREEN_ON_MSG = 1; @@ -529,8 +530,8 @@ public class SurfaceView extends View { visible ? VISIBLE : GONE, WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY, mWinFrame, mOverscanInsets, mContentInsets, - mVisibleInsets, mStableInsets, mOutsets, mConfiguration, - mNewSurface); + mVisibleInsets, mStableInsets, mOutsets, mBackdropFrame, + mConfiguration, mNewSurface); if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { reportDrawNeeded = true; } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 90e9f1bd53996..9c19bf14a8bd5 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -17,6 +17,7 @@ package android.view; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY; +import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY; @@ -1953,29 +1954,7 @@ public final class ViewRootImpl implements ViewParent, // in the attach info. We translate only the window frame since on window move // the window manager tells us only for the new frame but the insets are the // same and we do not want to translate them more than once. - - // TODO: Well, we are checking whether the frame has changed similarly - // to how this is done for the insets. This is however incorrect since - // the insets and the frame are translated. For example, the old frame - // was (1, 1 - 1, 1) and was translated to say (2, 2 - 2, 2), now the new - // reported frame is (2, 2 - 2, 2) which implies no change but this is not - // true since we are comparing a not translated value to a translated one. - // This scenario is rare but we may want to fix that. - - final boolean windowMoved = (mAttachInfo.mWindowLeft != frame.left - || mAttachInfo.mWindowTop != frame.top); - if (windowMoved) { - if (mTranslator != null) { - mTranslator.translateRectInScreenToAppWinFrame(frame); - } - mAttachInfo.mWindowLeft = frame.left; - mAttachInfo.mWindowTop = frame.top; - - // Update the light position for the new window offsets. - if (mAttachInfo.mHardwareRenderer != null) { - mAttachInfo.mHardwareRenderer.setLightCenter(mAttachInfo); - } - } + maybeHandleWindowMove(frame); } final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw); @@ -2140,6 +2119,31 @@ public final class ViewRootImpl implements ViewParent, mIsInTraversal = false; } + private void maybeHandleWindowMove(Rect frame) { + + // TODO: Well, we are checking whether the frame has changed similarly + // to how this is done for the insets. This is however incorrect since + // the insets and the frame are translated. For example, the old frame + // was (1, 1 - 1, 1) and was translated to say (2, 2 - 2, 2), now the new + // reported frame is (2, 2 - 2, 2) which implies no change but this is not + // true since we are comparing a not translated value to a translated one. + // This scenario is rare but we may want to fix that. + + final boolean windowMoved = mAttachInfo.mWindowLeft != frame.left + || mAttachInfo.mWindowTop != frame.top; + if (windowMoved) { + if (mTranslator != null) { + mTranslator.translateRectInScreenToAppWinFrame(frame); + } + mAttachInfo.mWindowLeft = frame.left; + mAttachInfo.mWindowTop = frame.top; + + // Update the light position for the new window offsets. + if (mAttachInfo.mHardwareRenderer != null) { + mAttachInfo.mHardwareRenderer.setLightCenter(mAttachInfo); + } + } + } private void handleOutOfResourcesException(Surface.OutOfResourcesException e) { Log.e(mTag, "OutOfResourcesException initializing HW surface", e); try { @@ -3403,12 +3407,16 @@ public final class ViewRootImpl implements ViewParent, // Suppress layouts during resizing - a correct layout will happen when resizing // is done, and this just increases system load. - boolean suppress = mDragResizing && mResizeMode == RESIZE_MODE_DOCKED_DIVIDER; + boolean isDockedDivider = mWindowAttributes.type == TYPE_DOCK_DIVIDER; + boolean suppress = (mDragResizing && mResizeMode == RESIZE_MODE_DOCKED_DIVIDER) + || isDockedDivider; if (!suppress) { if (mView != null) { forceLayout(mView); } requestLayout(); + } else { + maybeHandleWindowMove(mWinFrame); } } break; @@ -5522,7 +5530,8 @@ public final class ViewRootImpl implements ViewParent, (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets, - mPendingStableInsets, mPendingOutsets, mPendingConfiguration, mSurface); + mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingConfiguration, + mSurface); //Log.d(mTag, "<<<<<< BACK FROM relayout"); if (restore) { params.restore(); diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java index 161f873267d0e..2294d40d318d4 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java @@ -26,6 +26,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY; import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; /** @@ -50,6 +51,7 @@ public class DividerWindowManager { | FLAG_WATCH_OUTSIDE_TOUCH | FLAG_SPLIT_TOUCH | FLAG_SLIPPERY, PixelFormat.TRANSLUCENT); mLp.setTitle(WINDOW_TITLE); + mLp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION; view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 1b6957d9e5541..ac384240e2a3a 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -203,15 +203,14 @@ final class Session extends IWindowSession.Stub public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, - Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Configuration - outConfig, - Surface outSurface) { + Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Rect outBackdropFrame, + Configuration outConfig, Surface outSurface) { if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from " + Binder.getCallingPid()); int res = mService.relayoutWindow(this, window, seq, attrs, requestedWidth, requestedHeight, viewFlags, flags, outFrame, outOverscanInsets, outContentInsets, outVisibleInsets, - outStableInsets, outsets, outConfig, outSurface); + outStableInsets, outsets, outBackdropFrame, outConfig, outSurface); if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to " + Binder.getCallingPid()); return res; diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index bdaa05b2592fd..4fa38561423cf 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2561,8 +2561,8 @@ public class WindowManagerService extends IWindowManager.Stub WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, - Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Configuration outConfig, - Surface outSurface) { + Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame, + Configuration outConfig, Surface outSurface) { int result = 0; boolean configChanged; boolean hasStatusBarPermission = @@ -2749,6 +2749,7 @@ public class WindowManagerService extends IWindowManager.Stub outVisibleInsets.set(win.mVisibleInsets); outStableInsets.set(win.mStableInsets); outOutsets.set(win.mOutsets); + outBackdropFrame.set(win.getBackdropFrame(win.mFrame)); if (localLOGV) Slog.v( TAG_WM, "Relayout given client " + client.asBinder() + ", requestedWidth=" + requestedWidth diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index afbaf00652a5a..ff86aaeceb621 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -729,6 +729,9 @@ final class WindowState implements WindowManagerPolicy.WindowState { // will return the correct value to the renderer. mDisplayContent.getDockedDividerController().positionDockedStackedDivider(mFrame); mContentFrame.set(mFrame); + if (!mFrame.equals(mLastFrame)) { + mMovedByResize = true; + } } } else { mContentFrame.set(Math.max(mContentFrame.left, frame.left), @@ -752,15 +755,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { Math.max(frame.right - mOverscanFrame.right, 0), Math.max(frame.bottom - mOverscanFrame.bottom, 0)); - mContentInsets.set(mContentFrame.left - frame.left, - mContentFrame.top - frame.top, - frame.right - mContentFrame.right, - frame.bottom - mContentFrame.bottom); - mVisibleInsets.set(mVisibleFrame.left - frame.left, - mVisibleFrame.top - frame.top, - frame.right - mVisibleFrame.right, - frame.bottom - mVisibleFrame.bottom); if (mAttrs.type == TYPE_DOCK_DIVIDER) { @@ -770,7 +765,22 @@ final class WindowState implements WindowManagerPolicy.WindowState { Math.max(mStableFrame.top - mDisplayFrame.top, 0), Math.max(mDisplayFrame.right - mStableFrame.right, 0), Math.max(mDisplayFrame.bottom - mStableFrame.bottom, 0)); + + // The divider doesn't care about insets in any case, so set it to empty so we don't + // trigger a relayout when moving it. + mContentInsets.setEmpty(); + mVisibleInsets.setEmpty(); } else { + mContentInsets.set(mContentFrame.left - frame.left, + mContentFrame.top - frame.top, + frame.right - mContentFrame.right, + frame.bottom - mContentFrame.bottom); + + mVisibleInsets.set(mVisibleFrame.left - frame.left, + mVisibleFrame.top - frame.top, + frame.right - mVisibleFrame.right, + frame.bottom - mVisibleFrame.bottom); + mStableInsets.set(Math.max(mStableFrame.left - frame.left, 0), Math.max(mStableFrame.top - frame.top, 0), Math.max(frame.right - mStableFrame.right, 0), @@ -1993,21 +2003,24 @@ final class WindowState implements WindowManagerPolicy.WindowState { Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } - private void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets, - Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, - Configuration newConfig) throws RemoteException { - DisplayInfo displayInfo = getDisplayInfo(); - mTmpRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight); + Rect getBackdropFrame(Rect frame) { // When the task is docked, we send fullscreen sized backDropFrame as soon as resizing // start even if we haven't received the relayout window, so that the client requests // the relayout sooner. When dragging stops, backDropFrame needs to stay fullscreen // until the window to small size, otherwise the multithread renderer will shift last // one or more frame to wrong offset. So here we send fullscreen backdrop if either // isDragResizing() or isDragResizeChanged() is true. + DisplayInfo displayInfo = getDisplayInfo(); + mTmpRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight); boolean resizing = isDragResizing() || isDragResizeChanged(); - final Rect backDropFrame = (inFreeformWorkspace() || !resizing) ? frame : mTmpRect; + return (inFreeformWorkspace() || !resizing) ? frame : mTmpRect; + } + + private void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets, + Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, + Configuration newConfig) throws RemoteException { mClient.resized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets, outsets, - reportDraw, newConfig, backDropFrame); + reportDraw, newConfig, getBackdropFrame(frame)); } public void registerFocusObserver(IWindowFocusObserver observer) {