From 2dfcf840aa5d99aceab969e99a76625a12aa9b56 Mon Sep 17 00:00:00 2001 From: Filip Gruszczynski Date: Sun, 25 Oct 2015 13:40:47 -0700 Subject: [PATCH] Align the freeform to docking animation. It was not aligned, because we didn't take into account that the docked window will be cropped by the status bar and navigation bar. We need to account for that when creating the animation. Bug: 24913915 Change-Id: Idb82eefa14d65fe3bf6b25a9bd94c12dc8cbe648 --- .../com/android/server/wm/AppTransition.java | 21 +++++++++++++------ .../server/wm/WindowManagerService.java | 17 ++++++++++++--- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index 7abc04801e1ab..a53bc22c5bbf9 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -1006,7 +1006,7 @@ public class AppTransition implements Dump { } private Animation createRelaunchAnimation(int appWidth, int appHeight, - Rect containingFrame) { + Rect containingFrame, Rect contentInsets) { getDefaultNextAppTransitionStartRect(mTmpFromClipRect); final int left = mTmpFromClipRect.left; final int top = mTmpFromClipRect.top; @@ -1016,7 +1016,11 @@ public class AppTransition implements Dump { float fromWidth = mTmpFromClipRect.width(); float toWidth = mTmpToClipRect.width(); float fromHeight = mTmpFromClipRect.height(); - float toHeight = mTmpToClipRect.height(); + // While the window might span the whole display, the actual content will be cropped to the + // system decoration frame, for example when the window is docked. We need to take into + // account the visible height when constructing the animation. + float toHeight = mTmpToClipRect.height() - contentInsets.top - contentInsets.bottom; + int translateAdjustment = 0; if (fromWidth <= toWidth && fromHeight <= toHeight) { // The final window is larger in both dimensions than current window (e.g. we are // maximizing), so we can simply unclip the new window and there will be no disappearing @@ -1026,12 +1030,17 @@ public class AppTransition implements Dump { // The disappearing window has one larger dimension. We need to apply scaling, so the // first frame of the entry animation matches the old window. set.addAnimation(new ScaleAnimation(fromWidth / toWidth, 1, fromHeight / toHeight, 1)); + // We might not be going exactly full screen, but instead be aligned under the status + // bar using cropping. We still need to account for the cropped part, which will also + // be scaled. + translateAdjustment = (int) (contentInsets.top * fromHeight / toHeight); } - // We might not be going exactly full screen, but instead be aligned under the status bar. - // We need to take this into account when creating the translate animation. + // We animate the translation from the old position of the removed window, to the new + // position of the added window. The latter might not be full screen, for example docked for + // docked windows. TranslateAnimation translate = new TranslateAnimation(left - containingFrame.left, - 0, top - containingFrame.top, 0); + 0, top - containingFrame.top - translateAdjustment, 0); set.addAnimation(translate); set.setDuration(DEFAULT_APP_TRANSITION_DURATION); set.setZAdjustment(Animation.ZORDER_TOP); @@ -1075,7 +1084,7 @@ public class AppTransition implements Dump { + " anim=" + a + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); } else if (transit == TRANSIT_ACTIVITY_RELAUNCH) { - a = createRelaunchAnimation(appWidth, appHeight, containingFrame); + a = createRelaunchAnimation(appWidth, appHeight, containingFrame, contentInsets); if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation:" + " anim=" + a + " nextAppTransition=" + mNextAppTransition diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index cd5fbb0a6b316..b5ba9154afce8 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2869,6 +2869,7 @@ public class WindowManagerService extends IWindowManager.Stub Rect surfaceInsets = null; final boolean fullscreen = win != null && win.isFullscreen(width, height); final boolean freeform = win != null && win.inFreeformWorkspace(); + final boolean docked = win != null && win.inDockedWorkspace(); if (win != null) { // Containing frame will usually cover the whole screen, including dialog windows. // For freeform workspace windows it will not cover the whole screen and it also @@ -2880,10 +2881,11 @@ public class WindowManagerService extends IWindowManager.Stub containingFrame.set(win.mContainingFrame); } surfaceInsets = win.getAttrs().surfaceInsets; - if (fullscreen) { + if (fullscreen || docked) { // For fullscreen windows use the window frames and insets to set the thumbnail - // clip. For none-fullscreen windows we use the app display region so the clip - // isn't affected by the window insets. + // clip. For non-fullscreen windows we use the app display region so the clip + // isn't affected by the window insets. Docked windows are cropped to the system + // decorations, so we need tell the animation about it too. contentInsets.set(win.mContentInsets); appFrame.set(win.mFrame); } else { @@ -2899,6 +2901,15 @@ public class WindowManagerService extends IWindowManager.Stub // screen gets the enter animation. Both appear in the mOpeningApps set. enter = false; } + if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "Loading animation for app transition." + + " transit=" + AppTransition.appTransitionToString(transit) + + " enter=" + enter + + " containingWidth=" + containingWidth + + " containingHeight=" + containingHeight + + " containingFrame=" + containingFrame + + " contentInsets=" + contentInsets + + " surfaceInsets=" + surfaceInsets + + " appFrame=" + appFrame); Animation a = mAppTransition.loadAnimation(lp, transit, enter, containingWidth, containingHeight, mCurConfiguration.orientation, containingFrame, contentInsets, surfaceInsets, appFrame, isVoiceInteraction, freeform, atoken.mTask.mTaskId);