Dim stack while dismissing
When dismissing the docked or fullscreen stack, a dim layer is introduced for a nicer visual effect. Change-Id: I9f12e331e978208aa9fd9e9883b3c8a36d4da3a0
This commit is contained in:
@@ -361,4 +361,13 @@ interface IWindowManager
|
||||
* the docked stack gets added/removed.
|
||||
*/
|
||||
void registerDockedStackListener(IDockedStackListener listener);
|
||||
|
||||
/**
|
||||
* Updates the dim layer used while resizing.
|
||||
*
|
||||
* @param visible Whether the dim layer should be visible.
|
||||
* @param targetStackId The id of the task stack the dim layer should be placed on.
|
||||
* @param alpha The translucency of the dim layer, between 0 and 1.
|
||||
*/
|
||||
void setResizeDimLayer(boolean visible, int targetStackId, float alpha);
|
||||
}
|
||||
|
||||
@@ -100,6 +100,24 @@ public class DividerSnapAlgorithm {
|
||||
}
|
||||
}
|
||||
|
||||
public float calculateDismissingFraction(int position) {
|
||||
if (position < mFirstSplitTarget.position) {
|
||||
return 1f - (float) position / mFirstSplitTarget.position;
|
||||
} else if (position > mLastSplitTarget.position) {
|
||||
return (float) (position - mLastSplitTarget.position)
|
||||
/ (mDismissEndTarget.position - mLastSplitTarget.position);
|
||||
}
|
||||
return 0f;
|
||||
}
|
||||
|
||||
public SnapTarget getClosestDismissTarget(int position) {
|
||||
if (position - mDismissStartTarget.position < mDismissEndTarget.position - position) {
|
||||
return mDismissStartTarget;
|
||||
} else {
|
||||
return mDismissEndTarget;
|
||||
}
|
||||
}
|
||||
|
||||
private SnapTarget snap(int position) {
|
||||
int minIndex = -1;
|
||||
int minDistance = Integer.MAX_VALUE;
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.animation.ValueAnimator.AnimatorUpdateListener;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager.StackId;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
@@ -60,6 +61,8 @@ public class DividerView extends FrameLayout implements OnTouchListener,
|
||||
private static final String TAG = "DividerView";
|
||||
|
||||
private static final int TASK_POSITION_SAME = Integer.MAX_VALUE;
|
||||
private static final float DIM_START_FRACTION = 0.5f;
|
||||
private static final float DIM_DAMP_FACTOR = 1.7f;
|
||||
|
||||
private ImageButton mHandle;
|
||||
private View mBackground;
|
||||
@@ -264,6 +267,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
|
||||
} else {
|
||||
mWindowManagerProxy.maximizeDockedStack();
|
||||
}
|
||||
mWindowManagerProxy.setResizeDimLayer(false, -1, 0f);
|
||||
}
|
||||
|
||||
private void liftBackground() {
|
||||
@@ -420,6 +424,21 @@ public class DividerView extends FrameLayout implements OnTouchListener,
|
||||
} else {
|
||||
mWindowManagerProxy.resizeDockedStack(mDockedRect, null, null, null, null);
|
||||
}
|
||||
float fraction = mSnapAlgorithm.calculateDismissingFraction(position);
|
||||
fraction = Math.max(0,
|
||||
Math.min((fraction / DIM_START_FRACTION - 1f) / DIM_DAMP_FACTOR, 1f));
|
||||
mWindowManagerProxy.setResizeDimLayer(fraction != 0f,
|
||||
getStackIdForDismissTarget(mSnapAlgorithm.getClosestDismissTarget(position)),
|
||||
fraction);
|
||||
}
|
||||
|
||||
private int getStackIdForDismissTarget(SnapTarget dismissTarget) {
|
||||
if (dismissTarget.flag == SnapTarget.FLAG_DISMISS_START &&
|
||||
(mDockSide == WindowManager.DOCKED_LEFT || mDockSide == WindowManager.DOCKED_TOP)) {
|
||||
return StackId.DOCKED_STACK_ID;
|
||||
} else {
|
||||
return StackId.FULLSCREEN_WORKSPACE_STACK_ID;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -51,6 +51,11 @@ public class WindowManagerProxy {
|
||||
private final Rect mTmpRect3 = new Rect();
|
||||
private final Rect mTmpRect4 = new Rect();
|
||||
private final Rect mTmpRect5 = new Rect();
|
||||
|
||||
private boolean mDimLayerVisible;
|
||||
private int mDimLayerTargetStack;
|
||||
private float mDimLayerAlpha;
|
||||
|
||||
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
|
||||
|
||||
private final Runnable mResizeRunnable = new Runnable() {
|
||||
@@ -98,6 +103,18 @@ public class WindowManagerProxy {
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable mDimLayerRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
WindowManagerGlobal.getWindowManagerService().setResizeDimLayer(mDimLayerVisible,
|
||||
mDimLayerTargetStack, mDimLayerAlpha);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed to resize stack: " + e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private WindowManagerProxy() {
|
||||
}
|
||||
|
||||
@@ -162,4 +179,11 @@ public class WindowManagerProxy {
|
||||
}
|
||||
return DOCKED_INVALID;
|
||||
}
|
||||
|
||||
public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
|
||||
mDimLayerVisible = visible;
|
||||
mDimLayerTargetStack = targetStackId;
|
||||
mDimLayerAlpha = alpha;
|
||||
mExecutor.execute(mDimLayerRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,14 @@ import android.graphics.Rect;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.IDockedStackListener;
|
||||
import android.view.SurfaceControl;
|
||||
|
||||
import com.android.server.wm.DimLayer.DimLayerUser;
|
||||
|
||||
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
|
||||
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
|
||||
import static android.view.WindowManager.DOCKED_BOTTOM;
|
||||
import static android.view.WindowManager.DOCKED_LEFT;
|
||||
import static android.view.WindowManager.DOCKED_RIGHT;
|
||||
@@ -34,7 +39,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
/**
|
||||
* Keeps information about the docked stack divider.
|
||||
*/
|
||||
public class DockedStackDividerController {
|
||||
public class DockedStackDividerController implements DimLayerUser {
|
||||
|
||||
private static final String TAG = TAG_WITH_CLASS_NAME ? "DockedStackDividerController" : TAG_WM;
|
||||
|
||||
@@ -48,6 +53,7 @@ public class DockedStackDividerController {
|
||||
private boolean mLastVisibility = false;
|
||||
private final RemoteCallbackList<IDockedStackListener> mDockedStackListeners
|
||||
= new RemoteCallbackList<>();
|
||||
private final DimLayer mDimLayer;
|
||||
|
||||
DockedStackDividerController(Context context, DisplayContent displayContent) {
|
||||
mDisplayContent = displayContent;
|
||||
@@ -55,6 +61,7 @@ public class DockedStackDividerController {
|
||||
com.android.internal.R.dimen.docked_stack_divider_thickness);
|
||||
mDividerInsets = context.getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.docked_stack_divider_insets);
|
||||
mDimLayer = new DimLayer(displayContent.mService, this, displayContent.getDisplayId());
|
||||
}
|
||||
|
||||
boolean isResizing() {
|
||||
@@ -85,6 +92,9 @@ public class DockedStackDividerController {
|
||||
}
|
||||
mLastVisibility = visible;
|
||||
notifyDockedDividerVisibilityChanged(visible);
|
||||
if (!visible) {
|
||||
setResizeDimLayer(false, INVALID_STACK_ID, 0f);
|
||||
}
|
||||
}
|
||||
|
||||
boolean wasVisible() {
|
||||
@@ -158,4 +168,38 @@ public class DockedStackDividerController {
|
||||
notifyDockedStackExistsChanged(
|
||||
mDisplayContent.mService.mStackIdToStack.get(DOCKED_STACK_ID) != null);
|
||||
}
|
||||
|
||||
void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
|
||||
SurfaceControl.openTransaction();
|
||||
TaskStack stack = mDisplayContent.mService.mStackIdToStack.get(targetStackId);
|
||||
if (visible && stack != null) {
|
||||
stack.getDimBounds(mTmpRect);
|
||||
mDimLayer.setBounds(mTmpRect);
|
||||
mDimLayer.show(mDisplayContent.mService.mLayersController.getResizeDimLayer(), alpha,
|
||||
0 /* duration */);
|
||||
} else {
|
||||
mDimLayer.hide();
|
||||
}
|
||||
SurfaceControl.closeTransaction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFullscreen() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisplayInfo getDisplayInfo() {
|
||||
return mDisplayContent.getDisplayInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDimBounds(Rect outBounds) {
|
||||
// This dim layer user doesn't need this.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toShortString() {
|
||||
return TAG;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
package com.android.server.wm;
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
import static com.android.server.wm.WindowManagerService.WINDOW_LAYER_MULTIPLIER;
|
||||
package com.android.server.wm;
|
||||
|
||||
import android.app.ActivityManager.StackId;
|
||||
import android.util.Slog;
|
||||
@@ -11,6 +22,11 @@ import android.view.Display;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
import static com.android.server.wm.WindowManagerService.WINDOW_LAYER_MULTIPLIER;
|
||||
|
||||
/**
|
||||
* Controller for assigning layers to windows on the display.
|
||||
*
|
||||
@@ -133,6 +149,14 @@ public class WindowLayersController {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The layer used for dimming the apps when dismissing docked/fullscreen stack. Just
|
||||
* above all application surfaces.
|
||||
*/
|
||||
int getResizeDimLayer() {
|
||||
return mDockDivider.mLayer - 1;
|
||||
}
|
||||
|
||||
private void logDebugLayers(WindowList windows) {
|
||||
for (int i = 0, n = windows.size(); i < n; i++) {
|
||||
final WindowState w = windows.get(i);
|
||||
@@ -175,6 +199,11 @@ public class WindowLayersController {
|
||||
// For pinned and docked stack window, we want to make them above other windows
|
||||
// also when these windows are animating.
|
||||
layer = assignAndIncreaseLayerIfNeeded(mDockedWindow, layer);
|
||||
|
||||
// Leave some space here so the dim layer while dismissing docked/fullscreen stack has space
|
||||
// below the divider but above the app windows. It needs to be below the divider in because
|
||||
// the divider sometimes overlaps the app windows.
|
||||
layer++;
|
||||
layer = assignAndIncreaseLayerIfNeeded(mDockDivider, layer);
|
||||
// We know that we will be animating a relaunching window in the near future,
|
||||
// which will receive a z-order increase. We want the replaced window to
|
||||
|
||||
@@ -10209,6 +10209,14 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
|
||||
synchronized (mWindowMap) {
|
||||
getDefaultDisplayContentLocked().getDockedDividerController().setResizeDimLayer(
|
||||
visible, targetStackId, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTaskResizeable(int taskId, boolean resizeable) {
|
||||
synchronized (mWindowMap) {
|
||||
Task task = mTaskIdToTask.get(taskId);
|
||||
|
||||
Reference in New Issue
Block a user