blob: 4e34bbc11453e77a8218891afbe7f0c5aef2074a [file] [log] [blame]
Jorim Jaggi1fcbab62015-11-04 16:39:50 +01001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.stackdivider;
18
Michael Wrightf9d9ce772016-05-13 17:44:16 +010019import static android.view.PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW;
20import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;
Jorim Jaggid47e7e12016-03-01 09:57:38 +010021
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010022import android.animation.Animator;
23import android.animation.AnimatorListenerAdapter;
24import android.animation.ValueAnimator;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010025import android.annotation.Nullable;
Jorim Jaggi50981592015-12-29 17:54:12 +010026import android.app.ActivityManager.StackId;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010027import android.content.Context;
28import android.content.res.Configuration;
29import android.graphics.Rect;
30import android.graphics.Region.Op;
Filip Gruszczynskif6d8e9e2015-11-12 13:39:20 -080031import android.hardware.display.DisplayManager;
Jorim Jaggi88afd022016-02-24 21:11:08 -050032import android.os.Bundle;
Jorim Jaggia6c05d52016-05-27 00:31:21 -070033import android.os.Handler;
Jorim Jaggidbe6fdb2016-07-29 17:16:03 +020034import android.os.Message;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010035import android.util.AttributeSet;
Filip Gruszczynskif6d8e9e2015-11-12 13:39:20 -080036import android.view.Display;
37import android.view.DisplayInfo;
Jorim Jaggid47e7e12016-03-01 09:57:38 +010038import android.view.GestureDetector;
Jorim Jaggid47e7e12016-03-01 09:57:38 +010039import android.view.GestureDetector.SimpleOnGestureListener;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010040import android.view.MotionEvent;
Jun Mukaid4eaef72015-10-30 15:54:33 -070041import android.view.PointerIcon;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010042import android.view.VelocityTracker;
43import android.view.View;
44import android.view.View.OnTouchListener;
Jorim Jaggid8fb3ac2016-01-05 15:37:42 +010045import android.view.ViewConfiguration;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010046import android.view.ViewTreeObserver.InternalInsetsInfo;
47import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
Jorim Jaggi81fe2d12015-12-21 14:45:18 +010048import android.view.WindowInsets;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010049import android.view.WindowManager;
Jorim Jaggi88afd022016-02-24 21:11:08 -050050import android.view.accessibility.AccessibilityNodeInfo;
51import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010052import android.view.animation.Interpolator;
53import android.view.animation.PathInterpolator;
54import android.widget.FrameLayout;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010055
Jorim Jaggi29379ec2016-04-11 23:43:42 -070056import com.android.internal.logging.MetricsLogger;
57import com.android.internal.logging.MetricsProto.MetricsEvent;
Jorim Jaggi737af722015-12-31 10:42:27 +010058import com.android.internal.policy.DividerSnapAlgorithm;
Winsonc0d70582016-01-29 10:24:39 -080059import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
Jorim Jaggi737af722015-12-31 10:42:27 +010060import com.android.internal.policy.DockedDividerUtils;
Jorim Jaggiea4a19f2016-02-03 21:31:27 -080061import com.android.systemui.Interpolators;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010062import com.android.systemui.R;
Jorim Jaggid47e7e12016-03-01 09:57:38 +010063import com.android.systemui.recents.Recents;
Jorim Jaggi11cc01d2016-01-22 19:39:23 -080064import com.android.systemui.recents.events.EventBus;
Jorim Jaggi899327f2016-02-25 20:44:18 -050065import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
Jorim Jaggicdb06ca2016-01-25 19:15:12 -080066import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
Jorim Jaggiea4a19f2016-02-03 21:31:27 -080067import com.android.systemui.recents.events.activity.UndockingTaskEvent;
Jorim Jaggi11cc01d2016-01-22 19:39:23 -080068import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
Jorim Jaggidb21bbd2016-04-18 15:32:07 -070069import com.android.systemui.recents.events.ui.RecentsGrowingEvent;
Jorim Jaggid47e7e12016-03-01 09:57:38 +010070import com.android.systemui.recents.misc.SystemServicesProxy;
Jorim Jaggi2adba072016-03-03 13:43:39 +010071import com.android.systemui.stackdivider.events.StartedDragingEvent;
72import com.android.systemui.stackdivider.events.StoppedDragingEvent;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010073import com.android.systemui.statusbar.FlingAnimationUtils;
Jorim Jaggicdb06ca2016-01-25 19:15:12 -080074import com.android.systemui.statusbar.phone.NavigationBarGestureHelper;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010075
76/**
77 * Docked stack divider.
78 */
79public class DividerView extends FrameLayout implements OnTouchListener,
80 OnComputeInternalInsetsListener {
81
Jorim Jaggi514b2cf2016-01-04 13:06:34 +010082 static final long TOUCH_ANIMATION_DURATION = 150;
83 static final long TOUCH_RELEASE_ANIMATION_DURATION = 200;
Jorim Jaggi514b2cf2016-01-04 13:06:34 +010084
Jorim Jaggidb21bbd2016-04-18 15:32:07 -070085 public static final int INVALID_RECENTS_GROW_TARGET = -1;
86
Jorim Jaggi29379ec2016-04-11 23:43:42 -070087 private static final int LOG_VALUE_RESIZE_50_50 = 0;
88 private static final int LOG_VALUE_RESIZE_DOCKED_SMALLER = 1;
89 private static final int LOG_VALUE_RESIZE_DOCKED_LARGER = 2;
90
91 private static final int LOG_VALUE_UNDOCK_MAX_DOCKED = 0;
92 private static final int LOG_VALUE_UNDOCK_MAX_OTHER = 1;
93
Jorim Jaggidc249c42015-12-15 14:57:31 -080094 private static final int TASK_POSITION_SAME = Integer.MAX_VALUE;
Jorim Jaggi68855982016-03-25 18:46:30 -070095 private static final boolean SWAPPING_ENABLED = false;
Jorim Jaggidc249c42015-12-15 14:57:31 -080096
Jorim Jaggi50cd6362016-01-22 17:18:29 -080097 /**
Jorim Jaggi42625d1b2016-02-11 20:11:07 -080098 * How much the background gets scaled when we are in the minimized dock state.
99 */
Jorim Jaggi2917dc42016-04-11 11:39:13 -0700100 private static final float MINIMIZE_DOCK_SCALE = 0f;
Jorim Jaggi698e7632016-04-13 21:02:22 -0700101 private static final float ADJUSTED_FOR_IME_SCALE = 0.5f;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800102
Jorim Jaggie435e982015-12-30 13:54:32 +0100103 private static final PathInterpolator SLOWDOWN_INTERPOLATOR =
104 new PathInterpolator(0.5f, 1f, 0.5f, 1f);
Jorim Jaggi8f8155b2016-01-25 19:45:42 -0800105 private static final PathInterpolator DIM_INTERPOLATOR =
106 new PathInterpolator(.23f, .87f, .52f, -0.11f);
Jorim Jaggi7b458392016-04-20 16:42:06 -0700107 private static final Interpolator IME_ADJUST_INTERPOLATOR =
108 new PathInterpolator(0.2f, 0f, 0.1f, 1f);
Jorim Jaggie435e982015-12-30 13:54:32 +0100109
Jorim Jaggidbe6fdb2016-07-29 17:16:03 +0200110 private static final long ONE_MS_IN_NS = 1000000;
111 private static final long ONE_S_IN_NS = ONE_MS_IN_NS * 1000;
112
113 private static final int MSG_RESIZE_STACK = 0;
114
Jorim Jaggi514b2cf2016-01-04 13:06:34 +0100115 private DividerHandleView mHandle;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100116 private View mBackground;
Jorim Jaggi2917dc42016-04-11 11:39:13 -0700117 private MinimizedDockShadow mMinimizedShadow;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100118 private int mStartX;
119 private int mStartY;
120 private int mStartPosition;
121 private int mDockSide;
122 private final int[] mTempInt2 = new int[2];
Jorim Jaggid8fb3ac2016-01-05 15:37:42 +0100123 private boolean mMoving;
124 private int mTouchSlop;
Jorim Jaggie161f082016-02-05 14:26:16 -0800125 private boolean mBackgroundLifted;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100126
127 private int mDividerInsets;
128 private int mDisplayWidth;
129 private int mDisplayHeight;
130 private int mDividerWindowWidth;
131 private int mDividerSize;
132 private int mTouchElevation;
Jorim Jaggie370e152016-04-15 14:13:33 -0700133 private int mLongPressEntraceAnimDuration;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100134
Jorim Jaggidc249c42015-12-15 14:57:31 -0800135 private final Rect mDockedRect = new Rect();
136 private final Rect mDockedTaskRect = new Rect();
137 private final Rect mOtherTaskRect = new Rect();
138 private final Rect mOtherRect = new Rect();
139 private final Rect mDockedInsetRect = new Rect();
140 private final Rect mOtherInsetRect = new Rect();
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100141 private final Rect mLastResizeRect = new Rect();
Jorim Jaggi899327f2016-02-25 20:44:18 -0500142 private final Rect mDisplayRect = new Rect();
Jorim Jaggi870ab5a2015-12-02 18:37:54 -0800143 private final WindowManagerProxy mWindowManagerProxy = WindowManagerProxy.getInstance();
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100144 private DividerWindowManager mWindowManager;
145 private VelocityTracker mVelocityTracker;
146 private FlingAnimationUtils mFlingAnimationUtils;
Jorim Jaggidc249c42015-12-15 14:57:31 -0800147 private DividerSnapAlgorithm mSnapAlgorithm;
Jorim Jaggi81fe2d12015-12-21 14:45:18 +0100148 private final Rect mStableInsets = new Rect();
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100149
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800150 private boolean mGrowRecents;
Jorim Jaggi899327f2016-02-25 20:44:18 -0500151 private ValueAnimator mCurrentAnimator;
152 private boolean mEntranceAnimationRunning;
Jorim Jaggi47ee9ad2016-04-11 21:51:11 -0700153 private boolean mExitAnimationRunning;
154 private int mExitStartPosition;
Jorim Jaggid47e7e12016-03-01 09:57:38 +0100155 private GestureDetector mGestureDetector;
Jorim Jaggief92d6f2016-03-25 22:07:16 -0700156 private boolean mDockedStackMinimized;
Jorim Jaggi698e7632016-04-13 21:02:22 -0700157 private boolean mAdjustedForIme;
Jorim Jaggia6c05d52016-05-27 00:31:21 -0700158 private DividerState mState;
Jorim Jaggidbe6fdb2016-07-29 17:16:03 +0200159
160 /**
161 * The offset between vsync-app and vsync-surfaceflinger. See
162 * {@link #calculateAppSurfaceFlingerVsyncOffsetMs} why this is necessary.
163 */
164 private long mSurfaceFlingerOffsetMs;
165
166 private final Handler mHandler = new Handler() {
167 @Override
168 public void handleMessage(Message msg) {
169 switch (msg.what) {
170 case MSG_RESIZE_STACK:
171 resizeStack(msg.arg1, msg.arg2, (SnapTarget) msg.obj);
172 break;
173 default:
174 super.handleMessage(msg);
175 }
176 }
177 };
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800178
Jorim Jaggi88afd022016-02-24 21:11:08 -0500179 private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() {
180 @Override
181 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
182 super.onInitializeAccessibilityNodeInfo(host, info);
183 if (isHorizontalDivision()) {
Winsonce9630d2016-04-19 11:33:04 -0700184 info.addAction(new AccessibilityAction(R.id.action_move_tl_full,
185 mContext.getString(R.string.accessibility_action_divider_top_full)));
186 if (mSnapAlgorithm.isFirstSplitTargetAvailable()) {
187 info.addAction(new AccessibilityAction(R.id.action_move_tl_70,
188 mContext.getString(R.string.accessibility_action_divider_top_70)));
189 }
190 info.addAction(new AccessibilityAction(R.id.action_move_tl_50,
191 mContext.getString(R.string.accessibility_action_divider_top_50)));
192 if (mSnapAlgorithm.isLastSplitTargetAvailable()) {
193 info.addAction(new AccessibilityAction(R.id.action_move_tl_30,
194 mContext.getString(R.string.accessibility_action_divider_top_30)));
195 }
196 info.addAction(new AccessibilityAction(R.id.action_move_rb_full,
197 mContext.getString(R.string.accessibility_action_divider_bottom_full)));
Jorim Jaggi88afd022016-02-24 21:11:08 -0500198 } else {
Winsonce9630d2016-04-19 11:33:04 -0700199 info.addAction(new AccessibilityAction(R.id.action_move_tl_full,
200 mContext.getString(R.string.accessibility_action_divider_left_full)));
201 if (mSnapAlgorithm.isFirstSplitTargetAvailable()) {
202 info.addAction(new AccessibilityAction(R.id.action_move_tl_70,
203 mContext.getString(R.string.accessibility_action_divider_left_70)));
204 }
205 info.addAction(new AccessibilityAction(R.id.action_move_tl_50,
206 mContext.getString(R.string.accessibility_action_divider_left_50)));
207 if (mSnapAlgorithm.isLastSplitTargetAvailable()) {
208 info.addAction(new AccessibilityAction(R.id.action_move_tl_30,
209 mContext.getString(R.string.accessibility_action_divider_left_30)));
210 }
211 info.addAction(new AccessibilityAction(R.id.action_move_rb_full,
212 mContext.getString(R.string.accessibility_action_divider_right_full)));
Jorim Jaggi88afd022016-02-24 21:11:08 -0500213 }
214 }
215
216 @Override
217 public boolean performAccessibilityAction(View host, int action, Bundle args) {
Winsonce9630d2016-04-19 11:33:04 -0700218 int currentPosition = getCurrentPosition();
219 SnapTarget nextTarget = null;
220 switch (action) {
221 case R.id.action_move_tl_full:
222 nextTarget = mSnapAlgorithm.getDismissEndTarget();
223 break;
224 case R.id.action_move_tl_70:
225 nextTarget = mSnapAlgorithm.getLastSplitTarget();
226 break;
227 case R.id.action_move_tl_50:
228 nextTarget = mSnapAlgorithm.getMiddleTarget();
229 break;
230 case R.id.action_move_tl_30:
231 nextTarget = mSnapAlgorithm.getFirstSplitTarget();
232 break;
233 case R.id.action_move_rb_full:
234 nextTarget = mSnapAlgorithm.getDismissStartTarget();
235 break;
236 }
237 if (nextTarget != null) {
Jorim Jaggi88afd022016-02-24 21:11:08 -0500238 startDragging(true /* animate */, false /* touching */);
Winsonce9630d2016-04-19 11:33:04 -0700239 stopDragging(currentPosition, nextTarget, 250, Interpolators.FAST_OUT_SLOW_IN);
Jorim Jaggi88afd022016-02-24 21:11:08 -0500240 return true;
241 }
242 return super.performAccessibilityAction(host, action, args);
243 }
244 };
245
Jorim Jaggie661f402016-03-25 19:11:35 -0700246 private final Runnable mResetBackgroundRunnable = new Runnable() {
247 @Override
248 public void run() {
249 resetBackground();
250 }
251 };
252
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100253 public DividerView(Context context) {
254 super(context);
255 }
256
257 public DividerView(Context context, @Nullable AttributeSet attrs) {
258 super(context, attrs);
259 }
260
261 public DividerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
262 super(context, attrs, defStyleAttr);
263 }
264
265 public DividerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
266 int defStyleRes) {
267 super(context, attrs, defStyleAttr, defStyleRes);
268 }
269
270 @Override
271 protected void onFinishInflate() {
272 super.onFinishInflate();
Jorim Jaggi514b2cf2016-01-04 13:06:34 +0100273 mHandle = (DividerHandleView) findViewById(R.id.docked_divider_handle);
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100274 mBackground = findViewById(R.id.docked_divider_background);
Jorim Jaggi2917dc42016-04-11 11:39:13 -0700275 mMinimizedShadow = (MinimizedDockShadow) findViewById(R.id.minimized_dock_shadow);
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100276 mHandle.setOnTouchListener(this);
277 mDividerWindowWidth = getResources().getDimensionPixelSize(
278 com.android.internal.R.dimen.docked_stack_divider_thickness);
279 mDividerInsets = getResources().getDimensionPixelSize(
280 com.android.internal.R.dimen.docked_stack_divider_insets);
281 mDividerSize = mDividerWindowWidth - 2 * mDividerInsets;
282 mTouchElevation = getResources().getDimensionPixelSize(
283 R.dimen.docked_stack_divider_lift_elevation);
Jorim Jaggie370e152016-04-15 14:13:33 -0700284 mLongPressEntraceAnimDuration = getResources().getInteger(
285 R.integer.long_press_dock_anim_duration);
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800286 mGrowRecents = getResources().getBoolean(R.bool.recents_grow_in_multiwindow);
Jorim Jaggid8fb3ac2016-01-05 15:37:42 +0100287 mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100288 mFlingAnimationUtils = new FlingAnimationUtils(getContext(), 0.3f);
289 updateDisplayInfo();
Jorim Jaggie48f4282015-11-06 17:32:44 +0100290 boolean landscape = getResources().getConfiguration().orientation
291 == Configuration.ORIENTATION_LANDSCAPE;
Jun Mukaid4eaef72015-10-30 15:54:33 -0700292 mHandle.setPointerIcon(PointerIcon.getSystemIcon(getContext(),
Michael Wrightf9d9ce772016-05-13 17:44:16 +0100293 landscape ? TYPE_HORIZONTAL_DOUBLE_ARROW : TYPE_VERTICAL_DOUBLE_ARROW));
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100294 getViewTreeObserver().addOnComputeInternalInsetsListener(this);
Jorim Jaggi88afd022016-02-24 21:11:08 -0500295 mHandle.setAccessibilityDelegate(mHandleDelegate);
Jorim Jaggid47e7e12016-03-01 09:57:38 +0100296 mGestureDetector = new GestureDetector(mContext, new SimpleOnGestureListener() {
297 @Override
298 public boolean onSingleTapUp(MotionEvent e) {
Jorim Jaggi68855982016-03-25 18:46:30 -0700299 if (SWAPPING_ENABLED) {
300 updateDockSide();
301 SystemServicesProxy ssp = Recents.getSystemServices();
302 if (mDockSide != WindowManager.DOCKED_INVALID
Winsond46b7272016-04-20 11:54:27 -0700303 && !ssp.isRecentsActivityVisible()) {
Jorim Jaggi68855982016-03-25 18:46:30 -0700304 mWindowManagerProxy.swapTasks();
305 return true;
306 }
Jorim Jaggid47e7e12016-03-01 09:57:38 +0100307 }
308 return false;
309 }
310 });
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100311 }
312
Jorim Jaggi81fe2d12015-12-21 14:45:18 +0100313 @Override
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800314 protected void onAttachedToWindow() {
315 super.onAttachedToWindow();
316 EventBus.getDefault().register(this);
Jorim Jaggidbe6fdb2016-07-29 17:16:03 +0200317 mSurfaceFlingerOffsetMs = calculateAppSurfaceFlingerVsyncOffsetMs();
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800318 }
319
320 @Override
321 protected void onDetachedFromWindow() {
322 super.onDetachedFromWindow();
323 EventBus.getDefault().unregister(this);
324 }
325
Jorim Jaggidbe6fdb2016-07-29 17:16:03 +0200326 /**
327 * This method calculates the offset between vsync-surfaceflinger and vsync-app. If vsync-app
328 * is a couple of milliseconds before vsync-sf, a touch or animation event that causes the
329 * stacks to be resized are sometimes processed before the vsync-sf tick, and sometimes after,
330 * which leads to jank. Figure out this difference here and then post all the touch/animation
331 * events to start being processed at vsync-sf.
332 *
333 * @return The offset between vsync-app and vsync-sf, or 0 if vsync app happens after vsync-sf.
334 */
335 private long calculateAppSurfaceFlingerVsyncOffsetMs() {
336 Display display = getDisplay();
337
338 // Calculate vsync offset from SurfaceFlinger.
339 // See frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:getDisplayConfigs
340 long vsyncPeriod = (long) (ONE_S_IN_NS / display.getRefreshRate());
341 long sfVsyncOffset = vsyncPeriod - (display.getPresentationDeadlineNanos() - ONE_MS_IN_NS);
342 return Math.max(0, (sfVsyncOffset - display.getAppVsyncOffsetNanos()) / ONE_MS_IN_NS);
343 }
344
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800345 @Override
Jorim Jaggi81fe2d12015-12-21 14:45:18 +0100346 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
Jorim Jaggi1b12ef52016-01-29 16:49:55 -0800347 if (mStableInsets.left != insets.getStableInsetLeft()
348 || mStableInsets.top != insets.getStableInsetTop()
349 || mStableInsets.right != insets.getStableInsetRight()
350 || mStableInsets.bottom != insets.getStableInsetBottom()) {
351 mStableInsets.set(insets.getStableInsetLeft(), insets.getStableInsetTop(),
352 insets.getStableInsetRight(), insets.getStableInsetBottom());
353 if (mSnapAlgorithm != null) {
354 mSnapAlgorithm = null;
Jorim Jaggidefd9222016-02-03 18:28:49 -0800355 initializeSnapAlgorithm();
Jorim Jaggi1b12ef52016-01-29 16:49:55 -0800356 }
357 }
Jorim Jaggi81fe2d12015-12-21 14:45:18 +0100358 return super.onApplyWindowInsets(insets);
359 }
360
Jorim Jaggi8eb8a322016-04-05 18:03:56 -0700361 @Override
362 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
363 super.onLayout(changed, left, top, right, bottom);
Jorim Jaggi2917dc42016-04-11 11:39:13 -0700364 int minimizeLeft = 0;
365 int minimizeTop = 0;
366 if (mDockSide == WindowManager.DOCKED_TOP) {
367 minimizeTop = mBackground.getTop();
368 } else if (mDockSide == WindowManager.DOCKED_LEFT) {
369 minimizeLeft = mBackground.getLeft();
370 } else if (mDockSide == WindowManager.DOCKED_RIGHT) {
371 minimizeLeft = mBackground.getRight() - mMinimizedShadow.getWidth();
372 }
373 mMinimizedShadow.layout(minimizeLeft, minimizeTop,
374 minimizeLeft + mMinimizedShadow.getMeasuredWidth(),
375 minimizeTop + mMinimizedShadow.getMeasuredHeight());
Jorim Jaggi8eb8a322016-04-05 18:03:56 -0700376 if (changed) {
377 mWindowManagerProxy.setTouchRegion(new Rect(mHandle.getLeft(), mHandle.getTop(),
378 mHandle.getRight(), mHandle.getBottom()));
379 }
380 }
381
Jorim Jaggia6c05d52016-05-27 00:31:21 -0700382 public void injectDependencies(DividerWindowManager windowManager, DividerState dividerState) {
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100383 mWindowManager = windowManager;
Jorim Jaggia6c05d52016-05-27 00:31:21 -0700384 mState = dividerState;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100385 }
386
Jorim Jaggidd98d412015-11-18 15:57:38 -0800387 public WindowManagerProxy getWindowManagerProxy() {
388 return mWindowManagerProxy;
389 }
390
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800391 public boolean startDragging(boolean animate, boolean touching) {
Jorim Jaggi0c790412016-02-19 16:38:49 -0800392 cancelFlingAnimation();
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800393 if (touching) {
394 mHandle.setTouching(true, animate);
395 }
Jorim Jaggidd98d412015-11-18 15:57:38 -0800396 mDockSide = mWindowManagerProxy.getDockSide();
Jorim Jaggidefd9222016-02-03 18:28:49 -0800397 initializeSnapAlgorithm();
Jorim Jaggi9511b0f2016-01-29 19:12:44 -0800398 mWindowManagerProxy.setResizing(true);
Jorim Jaggi9511b0f2016-01-29 19:12:44 -0800399 if (touching) {
Jorim Jaggie161f082016-02-05 14:26:16 -0800400 mWindowManager.setSlippery(false);
Jorim Jaggi9511b0f2016-01-29 19:12:44 -0800401 liftBackground();
Jorim Jaggidd98d412015-11-18 15:57:38 -0800402 }
Jorim Jaggi2adba072016-03-03 13:43:39 +0100403 EventBus.getDefault().send(new StartedDragingEvent());
Jorim Jaggi9511b0f2016-01-29 19:12:44 -0800404 return mDockSide != WindowManager.DOCKED_INVALID;
Jorim Jaggidd98d412015-11-18 15:57:38 -0800405 }
406
Jorim Jaggi29379ec2016-04-11 23:43:42 -0700407 public void stopDragging(int position, float velocity, boolean avoidDismissStart,
408 boolean logMetrics) {
Jorim Jaggi514b2cf2016-01-04 13:06:34 +0100409 mHandle.setTouching(false, true /* animate */);
Jorim Jaggi29379ec2016-04-11 23:43:42 -0700410 fling(position, velocity, avoidDismissStart, logMetrics);
Jorim Jaggidd98d412015-11-18 15:57:38 -0800411 mWindowManager.setSlippery(true);
412 releaseBackground();
413 }
414
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800415 public void stopDragging(int position, SnapTarget target, long duration,
416 Interpolator interpolator) {
Jorim Jaggi545c5c22016-04-12 18:59:45 -0700417 stopDragging(position, target, duration, 0 /* startDelay*/, 0 /* endDelay */, interpolator);
418 }
419
420 public void stopDragging(int position, SnapTarget target, long duration,
421 Interpolator interpolator, long endDelay) {
422 stopDragging(position, target, duration, 0 /* startDelay*/, endDelay, interpolator);
Jorim Jaggiea4a19f2016-02-03 21:31:27 -0800423 }
424
425 public void stopDragging(int position, SnapTarget target, long duration, long startDelay,
Jorim Jaggi545c5c22016-04-12 18:59:45 -0700426 long endDelay, Interpolator interpolator) {
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800427 mHandle.setTouching(false, true /* animate */);
Jorim Jaggi545c5c22016-04-12 18:59:45 -0700428 flingTo(position, target, duration, startDelay, endDelay, interpolator);
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800429 mWindowManager.setSlippery(true);
430 releaseBackground();
431 }
432
Jorim Jaggi9511b0f2016-01-29 19:12:44 -0800433 private void stopDragging() {
434 mHandle.setTouching(false, true /* animate */);
435 mWindowManager.setSlippery(true);
436 releaseBackground();
437 }
438
439 private void updateDockSide() {
440 mDockSide = mWindowManagerProxy.getDockSide();
Jorim Jaggi2917dc42016-04-11 11:39:13 -0700441 mMinimizedShadow.setDockSide(mDockSide);
Jorim Jaggi9511b0f2016-01-29 19:12:44 -0800442 }
443
Jorim Jaggidefd9222016-02-03 18:28:49 -0800444 private void initializeSnapAlgorithm() {
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800445 if (mSnapAlgorithm == null) {
446 mSnapAlgorithm = new DividerSnapAlgorithm(getContext().getResources(), mDisplayWidth,
447 mDisplayHeight, mDividerSize, isHorizontalDivision(), mStableInsets);
448 }
Jorim Jaggidefd9222016-02-03 18:28:49 -0800449 }
450
451 public DividerSnapAlgorithm getSnapAlgorithm() {
452 initializeSnapAlgorithm();
Jorim Jaggidc249c42015-12-15 14:57:31 -0800453 return mSnapAlgorithm;
454 }
455
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800456 public int getCurrentPosition() {
457 getLocationOnScreen(mTempInt2);
458 if (isHorizontalDivision()) {
459 return mTempInt2[1] + mDividerInsets;
460 } else {
461 return mTempInt2[0] + mDividerInsets;
462 }
463 }
464
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100465 @Override
466 public boolean onTouch(View v, MotionEvent event) {
467 convertToScreenCoordinates(event);
Jorim Jaggid47e7e12016-03-01 09:57:38 +0100468 mGestureDetector.onTouchEvent(event);
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100469 final int action = event.getAction() & MotionEvent.ACTION_MASK;
470 switch (action) {
471 case MotionEvent.ACTION_DOWN:
472 mVelocityTracker = VelocityTracker.obtain();
473 mVelocityTracker.addMovement(event);
474 mStartX = (int) event.getX();
475 mStartY = (int) event.getY();
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800476 boolean result = startDragging(true /* animate */, true /* touching */);
Jorim Jaggi9511b0f2016-01-29 19:12:44 -0800477 if (!result) {
478
479 // Weren't able to start dragging successfully, so cancel it again.
480 stopDragging();
481 }
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800482 mStartPosition = getCurrentPosition();
Jorim Jaggid8fb3ac2016-01-05 15:37:42 +0100483 mMoving = false;
Jorim Jaggidd98d412015-11-18 15:57:38 -0800484 return result;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100485 case MotionEvent.ACTION_MOVE:
486 mVelocityTracker.addMovement(event);
487 int x = (int) event.getX();
488 int y = (int) event.getY();
Jorim Jaggid8fb3ac2016-01-05 15:37:42 +0100489 boolean exceededTouchSlop =
490 isHorizontalDivision() && Math.abs(y - mStartY) > mTouchSlop
491 || (!isHorizontalDivision() && Math.abs(x - mStartX) > mTouchSlop);
492 if (!mMoving && exceededTouchSlop) {
493 mStartX = x;
494 mStartY = y;
495 mMoving = true;
496 }
497 if (mMoving && mDockSide != WindowManager.DOCKED_INVALID) {
Wale Ogunwaleef676d82016-03-18 12:51:55 -0700498 SnapTarget snapTarget = mSnapAlgorithm.calculateSnapTarget(
499 mStartPosition, 0 /* velocity */, false /* hardDismiss */);
Jorim Jaggidbe6fdb2016-07-29 17:16:03 +0200500 resizeStackDelayed(calculatePosition(x, y), mStartPosition, snapTarget);
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100501 }
502 break;
503 case MotionEvent.ACTION_UP:
504 case MotionEvent.ACTION_CANCEL:
505 mVelocityTracker.addMovement(event);
506
507 x = (int) event.getRawX();
508 y = (int) event.getRawY();
509
510 mVelocityTracker.computeCurrentVelocity(1000);
Jorim Jaggidd98d412015-11-18 15:57:38 -0800511 int position = calculatePosition(x, y);
512 stopDragging(position, isHorizontalDivision() ? mVelocityTracker.getYVelocity()
Jorim Jaggi29379ec2016-04-11 23:43:42 -0700513 : mVelocityTracker.getXVelocity(), false /* avoidDismissStart */,
514 true /* log */);
Jorim Jaggid8fb3ac2016-01-05 15:37:42 +0100515 mMoving = false;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100516 break;
517 }
518 return true;
519 }
520
Jorim Jaggi29379ec2016-04-11 23:43:42 -0700521 private void logResizeEvent(SnapTarget snapTarget) {
522 if (snapTarget == mSnapAlgorithm.getDismissStartTarget()) {
523 MetricsLogger.action(
524 mContext, MetricsEvent.ACTION_WINDOW_UNDOCK_MAX, dockSideTopLeft(mDockSide)
525 ? LOG_VALUE_UNDOCK_MAX_OTHER
526 : LOG_VALUE_UNDOCK_MAX_DOCKED);
527 } else if (snapTarget == mSnapAlgorithm.getDismissEndTarget()) {
528 MetricsLogger.action(
529 mContext, MetricsEvent.ACTION_WINDOW_UNDOCK_MAX, dockSideBottomRight(mDockSide)
530 ? LOG_VALUE_UNDOCK_MAX_OTHER
531 : LOG_VALUE_UNDOCK_MAX_DOCKED);
532 } else if (snapTarget == mSnapAlgorithm.getMiddleTarget()) {
533 MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE,
534 LOG_VALUE_RESIZE_50_50);
535 } else if (snapTarget == mSnapAlgorithm.getFirstSplitTarget()) {
536 MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE,
537 dockSideTopLeft(mDockSide)
538 ? LOG_VALUE_RESIZE_DOCKED_SMALLER
539 : LOG_VALUE_RESIZE_DOCKED_LARGER);
540 } else if (snapTarget == mSnapAlgorithm.getLastSplitTarget()) {
541 MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE,
542 dockSideTopLeft(mDockSide)
543 ? LOG_VALUE_RESIZE_DOCKED_LARGER
544 : LOG_VALUE_RESIZE_DOCKED_SMALLER);
545 }
546 }
547
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100548 private void convertToScreenCoordinates(MotionEvent event) {
549 event.setLocation(event.getRawX(), event.getRawY());
550 }
551
Jorim Jaggi29379ec2016-04-11 23:43:42 -0700552 private void fling(int position, float velocity, boolean avoidDismissStart,
553 boolean logMetrics) {
Jorim Jaggidf012d52016-01-15 22:40:13 -0800554 SnapTarget snapTarget = mSnapAlgorithm.calculateSnapTarget(position, velocity);
555 if (avoidDismissStart && snapTarget == mSnapAlgorithm.getDismissStartTarget()) {
556 snapTarget = mSnapAlgorithm.getFirstSplitTarget();
557 }
Jorim Jaggi29379ec2016-04-11 23:43:42 -0700558 if (logMetrics) {
559 logResizeEvent(snapTarget);
560 }
Jorim Jaggi545c5c22016-04-12 18:59:45 -0700561 ValueAnimator anim = getFlingAnimator(position, snapTarget, 0 /* endDelay */);
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800562 mFlingAnimationUtils.apply(anim, position, snapTarget.position, velocity);
563 anim.start();
564 }
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100565
Jorim Jaggiea4a19f2016-02-03 21:31:27 -0800566 private void flingTo(int position, SnapTarget target, long duration, long startDelay,
Jorim Jaggi545c5c22016-04-12 18:59:45 -0700567 long endDelay, Interpolator interpolator) {
568 ValueAnimator anim = getFlingAnimator(position, target, endDelay);
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800569 anim.setDuration(duration);
Jorim Jaggiea4a19f2016-02-03 21:31:27 -0800570 anim.setStartDelay(startDelay);
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800571 anim.setInterpolator(interpolator);
572 anim.start();
573 }
574
Jorim Jaggi545c5c22016-04-12 18:59:45 -0700575 private ValueAnimator getFlingAnimator(int position, final SnapTarget snapTarget,
576 final long endDelay) {
Jorim Jaggi069dfe62016-05-04 17:24:47 -0700577 final boolean taskPositionSameAtEnd = snapTarget.flag == SnapTarget.FLAG_NONE;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100578 ValueAnimator anim = ValueAnimator.ofInt(position, snapTarget.position);
Jorim Jaggidbe6fdb2016-07-29 17:16:03 +0200579 anim.addUpdateListener(animation -> resizeStackDelayed((int) animation.getAnimatedValue(),
Jorim Jaggi069dfe62016-05-04 17:24:47 -0700580 taskPositionSameAtEnd && animation.getAnimatedFraction() == 1f
581 ? TASK_POSITION_SAME
Jorim Jaggidbe6fdb2016-07-29 17:16:03 +0200582 : snapTarget.taskPosition,
583 snapTarget));
Jorim Jaggi545c5c22016-04-12 18:59:45 -0700584 Runnable endAction = () -> {
585 commitSnapFlags(snapTarget);
586 mWindowManagerProxy.setResizing(false);
587 mDockSide = WindowManager.DOCKED_INVALID;
588 mCurrentAnimator = null;
589 mEntranceAnimationRunning = false;
590 mExitAnimationRunning = false;
591 EventBus.getDefault().send(new StoppedDragingEvent());
592 };
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100593 anim.addListener(new AnimatorListenerAdapter() {
Jorim Jaggi545c5c22016-04-12 18:59:45 -0700594
595 private boolean mCancelled;
596
597 @Override
598 public void onAnimationCancel(Animator animation) {
Jorim Jaggidbe6fdb2016-07-29 17:16:03 +0200599 mHandler.removeMessages(MSG_RESIZE_STACK);
Jorim Jaggi545c5c22016-04-12 18:59:45 -0700600 mCancelled = true;
601 }
602
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100603 @Override
604 public void onAnimationEnd(Animator animation) {
Jorim Jaggidbe6fdb2016-07-29 17:16:03 +0200605 long delay = 0;
606 if (endDelay != 0) {
607 delay = endDelay;
608 } else if (mCancelled) {
609 delay = 0;
610 } else if (mSurfaceFlingerOffsetMs != 0) {
611 delay = mSurfaceFlingerOffsetMs;
612 }
613 if (delay == 0) {
Jorim Jaggi545c5c22016-04-12 18:59:45 -0700614 endAction.run();
615 } else {
Jorim Jaggidbe6fdb2016-07-29 17:16:03 +0200616 mHandler.postDelayed(endAction, delay);
Jorim Jaggi545c5c22016-04-12 18:59:45 -0700617 }
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100618 }
619 });
Jorim Jaggi0c790412016-02-19 16:38:49 -0800620 mCurrentAnimator = anim;
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800621 return anim;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100622 }
623
Jorim Jaggi0c790412016-02-19 16:38:49 -0800624 private void cancelFlingAnimation() {
625 if (mCurrentAnimator != null) {
626 mCurrentAnimator.cancel();
627 }
628 }
629
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100630 private void commitSnapFlags(SnapTarget target) {
631 if (target.flag == SnapTarget.FLAG_NONE) {
632 return;
633 }
634 boolean dismissOrMaximize;
635 if (target.flag == SnapTarget.FLAG_DISMISS_START) {
636 dismissOrMaximize = mDockSide == WindowManager.DOCKED_LEFT
637 || mDockSide == WindowManager.DOCKED_TOP;
638 } else {
639 dismissOrMaximize = mDockSide == WindowManager.DOCKED_RIGHT
640 || mDockSide == WindowManager.DOCKED_BOTTOM;
641 }
642 if (dismissOrMaximize) {
643 mWindowManagerProxy.dismissDockedStack();
644 } else {
645 mWindowManagerProxy.maximizeDockedStack();
646 }
Jorim Jaggi50981592015-12-29 17:54:12 +0100647 mWindowManagerProxy.setResizeDimLayer(false, -1, 0f);
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100648 }
649
650 private void liftBackground() {
Jorim Jaggie161f082016-02-05 14:26:16 -0800651 if (mBackgroundLifted) {
652 return;
653 }
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100654 if (isHorizontalDivision()) {
Jorim Jaggi79b39f02015-12-17 20:04:31 -0800655 mBackground.animate().scaleY(1.4f);
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100656 } else {
Jorim Jaggi79b39f02015-12-17 20:04:31 -0800657 mBackground.animate().scaleX(1.4f);
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100658 }
659 mBackground.animate()
Jorim Jaggiea4a19f2016-02-03 21:31:27 -0800660 .setInterpolator(Interpolators.TOUCH_RESPONSE)
Jorim Jaggi514b2cf2016-01-04 13:06:34 +0100661 .setDuration(TOUCH_ANIMATION_DURATION)
662 .translationZ(mTouchElevation)
663 .start();
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100664
665 // Lift handle as well so it doesn't get behind the background, even though it doesn't
666 // cast shadow.
667 mHandle.animate()
Jorim Jaggiea4a19f2016-02-03 21:31:27 -0800668 .setInterpolator(Interpolators.TOUCH_RESPONSE)
Jorim Jaggi514b2cf2016-01-04 13:06:34 +0100669 .setDuration(TOUCH_ANIMATION_DURATION)
670 .translationZ(mTouchElevation)
671 .start();
Jorim Jaggie161f082016-02-05 14:26:16 -0800672 mBackgroundLifted = true;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100673 }
674
675 private void releaseBackground() {
Jorim Jaggie161f082016-02-05 14:26:16 -0800676 if (!mBackgroundLifted) {
677 return;
678 }
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100679 mBackground.animate()
Jorim Jaggiea4a19f2016-02-03 21:31:27 -0800680 .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
Jorim Jaggi514b2cf2016-01-04 13:06:34 +0100681 .setDuration(TOUCH_RELEASE_ANIMATION_DURATION)
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100682 .translationZ(0)
683 .scaleX(1f)
Jorim Jaggi514b2cf2016-01-04 13:06:34 +0100684 .scaleY(1f)
685 .start();
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100686 mHandle.animate()
Jorim Jaggiea4a19f2016-02-03 21:31:27 -0800687 .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
Jorim Jaggi514b2cf2016-01-04 13:06:34 +0100688 .setDuration(TOUCH_RELEASE_ANIMATION_DURATION)
689 .translationZ(0)
690 .start();
Jorim Jaggie161f082016-02-05 14:26:16 -0800691 mBackgroundLifted = false;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100692 }
693
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800694
695 public void setMinimizedDockStack(boolean minimized) {
696 updateDockSide();
697 mHandle.setAlpha(minimized ? 0f : 1f);
Jorim Jaggie661f402016-03-25 19:11:35 -0700698 if (!minimized) {
699 resetBackground();
700 } else if (mDockSide == WindowManager.DOCKED_TOP) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800701 mBackground.setPivotY(0);
Jorim Jaggie661f402016-03-25 19:11:35 -0700702 mBackground.setScaleY(MINIMIZE_DOCK_SCALE);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800703 } else if (mDockSide == WindowManager.DOCKED_LEFT
704 || mDockSide == WindowManager.DOCKED_RIGHT) {
705 mBackground.setPivotX(mDockSide == WindowManager.DOCKED_LEFT
706 ? 0
707 : mBackground.getWidth());
Jorim Jaggie661f402016-03-25 19:11:35 -0700708 mBackground.setScaleX(MINIMIZE_DOCK_SCALE);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800709 }
Jorim Jaggi2917dc42016-04-11 11:39:13 -0700710 mMinimizedShadow.setAlpha(minimized ? 1f : 0f);
Jorim Jaggief92d6f2016-03-25 22:07:16 -0700711 mDockedStackMinimized = minimized;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800712 }
713
714 public void setMinimizedDockStack(boolean minimized, long animDuration) {
715 updateDockSide();
716 mHandle.animate()
717 .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
718 .setDuration(animDuration)
719 .alpha(minimized ? 0f : 1f)
720 .start();
721 if (mDockSide == WindowManager.DOCKED_TOP) {
722 mBackground.setPivotY(0);
723 mBackground.animate()
724 .scaleY(minimized ? MINIMIZE_DOCK_SCALE : 1f);
725 } else if (mDockSide == WindowManager.DOCKED_LEFT
726 || mDockSide == WindowManager.DOCKED_RIGHT) {
727 mBackground.setPivotX(mDockSide == WindowManager.DOCKED_LEFT
728 ? 0
729 : mBackground.getWidth());
730 mBackground.animate()
731 .scaleX(minimized ? MINIMIZE_DOCK_SCALE : 1f);
732 }
Jorim Jaggie661f402016-03-25 19:11:35 -0700733 if (!minimized) {
734 mBackground.animate().withEndAction(mResetBackgroundRunnable);
735 }
Jorim Jaggi2917dc42016-04-11 11:39:13 -0700736 mMinimizedShadow.animate()
737 .alpha(minimized ? 1f : 0f)
738 .setInterpolator(Interpolators.ALPHA_IN)
739 .setDuration(animDuration)
740 .start();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800741 mBackground.animate()
742 .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
743 .setDuration(animDuration)
744 .start();
Jorim Jaggief92d6f2016-03-25 22:07:16 -0700745 mDockedStackMinimized = minimized;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800746 }
747
Jorim Jaggi698e7632016-04-13 21:02:22 -0700748 public void setAdjustedForIme(boolean adjustedForIme) {
749 updateDockSide();
750 mHandle.setAlpha(adjustedForIme ? 0f : 1f);
751 if (!adjustedForIme) {
752 resetBackground();
753 } else if (mDockSide == WindowManager.DOCKED_TOP) {
754 mBackground.setPivotY(0);
Jorim Jaggi7b458392016-04-20 16:42:06 -0700755 mBackground.setScaleY(ADJUSTED_FOR_IME_SCALE);
Jorim Jaggi698e7632016-04-13 21:02:22 -0700756 }
757 mAdjustedForIme = adjustedForIme;
758 }
759
760 public void setAdjustedForIme(boolean adjustedForIme, long animDuration) {
761 updateDockSide();
762 mHandle.animate()
Jorim Jaggi7b458392016-04-20 16:42:06 -0700763 .setInterpolator(IME_ADJUST_INTERPOLATOR)
Jorim Jaggi698e7632016-04-13 21:02:22 -0700764 .setDuration(animDuration)
765 .alpha(adjustedForIme ? 0f : 1f)
766 .start();
767 if (mDockSide == WindowManager.DOCKED_TOP) {
768 mBackground.setPivotY(0);
769 mBackground.animate()
Jorim Jaggi7b458392016-04-20 16:42:06 -0700770 .scaleY(adjustedForIme ? ADJUSTED_FOR_IME_SCALE : 1f);
Jorim Jaggi698e7632016-04-13 21:02:22 -0700771 }
772 if (!adjustedForIme) {
773 mBackground.animate().withEndAction(mResetBackgroundRunnable);
774 }
775 mBackground.animate()
Jorim Jaggi7b458392016-04-20 16:42:06 -0700776 .setInterpolator(IME_ADJUST_INTERPOLATOR)
Jorim Jaggi698e7632016-04-13 21:02:22 -0700777 .setDuration(animDuration)
778 .start();
779 mAdjustedForIme = adjustedForIme;
780 }
781
Jorim Jaggie661f402016-03-25 19:11:35 -0700782 private void resetBackground() {
783 mBackground.setPivotX(mBackground.getWidth() / 2);
784 mBackground.setPivotY(mBackground.getHeight() / 2);
785 mBackground.setScaleX(1f);
786 mBackground.setScaleY(1f);
Jorim Jaggi2917dc42016-04-11 11:39:13 -0700787 mMinimizedShadow.setAlpha(0f);
Jorim Jaggie661f402016-03-25 19:11:35 -0700788 }
789
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100790 @Override
791 protected void onConfigurationChanged(Configuration newConfig) {
792 super.onConfigurationChanged(newConfig);
793 updateDisplayInfo();
794 }
795
Jorim Jaggi2917dc42016-04-11 11:39:13 -0700796
797 public void notifyDockSideChanged(int newDockSide) {
798 mDockSide = newDockSide;
799 mMinimizedShadow.setDockSide(mDockSide);
800 requestLayout();
801 }
802
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100803 private void updateDisplayInfo() {
Filip Gruszczynskif6d8e9e2015-11-12 13:39:20 -0800804 final DisplayManager displayManager =
805 (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
806 Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
807 final DisplayInfo info = new DisplayInfo();
808 display.getDisplayInfo(info);
809 mDisplayWidth = info.logicalWidth;
810 mDisplayHeight = info.logicalHeight;
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800811 mSnapAlgorithm = null;
Jorim Jaggidefd9222016-02-03 18:28:49 -0800812 initializeSnapAlgorithm();
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100813 }
814
815 private int calculatePosition(int touchX, int touchY) {
816 return isHorizontalDivision() ? calculateYPosition(touchY) : calculateXPosition(touchX);
817 }
818
Jorim Jaggidd98d412015-11-18 15:57:38 -0800819 public boolean isHorizontalDivision() {
820 return getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100821 }
822
823 private int calculateXPosition(int touchX) {
824 return mStartPosition + touchX - mStartX;
825 }
826
827 private int calculateYPosition(int touchY) {
828 return mStartPosition + touchY - mStartY;
829 }
830
Jorim Jaggidc249c42015-12-15 14:57:31 -0800831 private void alignTopLeft(Rect containingRect, Rect rect) {
832 int width = rect.width();
833 int height = rect.height();
834 rect.set(containingRect.left, containingRect.top,
835 containingRect.left + width, containingRect.top + height);
836 }
837
838 private void alignBottomRight(Rect containingRect, Rect rect) {
839 int width = rect.width();
840 int height = rect.height();
841 rect.set(containingRect.right - width, containingRect.bottom - height,
842 containingRect.right, containingRect.bottom);
843 }
844
Jorim Jaggi737af722015-12-31 10:42:27 +0100845 public void calculateBoundsForPosition(int position, int dockSide, Rect outRect) {
846 DockedDividerUtils.calculateBoundsForPosition(position, dockSide, outRect, mDisplayWidth,
847 mDisplayHeight, mDividerSize);
848 }
849
Jorim Jaggidbe6fdb2016-07-29 17:16:03 +0200850 public void resizeStackDelayed(int position, int taskPosition, SnapTarget taskSnapTarget) {
851 if (mSurfaceFlingerOffsetMs != 0) {
852 Message message = mHandler.obtainMessage(MSG_RESIZE_STACK, position, taskPosition,
853 taskSnapTarget);
854 message.setAsynchronous(true);
855 mHandler.sendMessageDelayed(message, mSurfaceFlingerOffsetMs);
856 } else {
857 resizeStack(position, taskPosition, taskSnapTarget);
858 }
859 }
860
Jorim Jaggie435e982015-12-30 13:54:32 +0100861 public void resizeStack(int position, int taskPosition, SnapTarget taskSnapTarget) {
Jorim Jaggidc249c42015-12-15 14:57:31 -0800862 calculateBoundsForPosition(position, mDockSide, mDockedRect);
863
Jorim Jaggie370e152016-04-15 14:13:33 -0700864 if (mDockedRect.equals(mLastResizeRect) && !mEntranceAnimationRunning) {
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100865 return;
866 }
Jorim Jaggic97ba492015-11-06 22:00:18 +0100867
868 // Make sure shadows are updated
Jorim Jaggie161f082016-02-05 14:26:16 -0800869 if (mBackground.getZ() > 0f) {
870 mBackground.invalidate();
871 }
Jorim Jaggic97ba492015-11-06 22:00:18 +0100872
Jorim Jaggidc249c42015-12-15 14:57:31 -0800873 mLastResizeRect.set(mDockedRect);
Jorim Jaggi899327f2016-02-25 20:44:18 -0500874 if (mEntranceAnimationRunning && taskPosition != TASK_POSITION_SAME) {
875 if (mCurrentAnimator != null) {
876 calculateBoundsForPosition(taskPosition, mDockSide, mDockedTaskRect);
877 } else {
878 calculateBoundsForPosition(isHorizontalDivision() ? mDisplayHeight : mDisplayWidth,
879 mDockSide, mDockedTaskRect);
880 }
881 calculateBoundsForPosition(taskPosition, DockedDividerUtils.invertDockSide(mDockSide),
882 mOtherTaskRect);
883 mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, null,
884 mOtherTaskRect, null);
Jorim Jaggi47ee9ad2016-04-11 21:51:11 -0700885 } else if (mExitAnimationRunning && taskPosition != TASK_POSITION_SAME) {
886 calculateBoundsForPosition(taskPosition,
887 mDockSide, mDockedTaskRect);
888 calculateBoundsForPosition(mExitStartPosition,
889 DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect);
Jorim Jaggi545c5c22016-04-12 18:59:45 -0700890 mOtherInsetRect.set(mOtherTaskRect);
891 applyExitAnimationParallax(mOtherTaskRect, position);
Jorim Jaggi47ee9ad2016-04-11 21:51:11 -0700892 mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, null,
Jorim Jaggi545c5c22016-04-12 18:59:45 -0700893 mOtherTaskRect, mOtherInsetRect);
Jorim Jaggi899327f2016-02-25 20:44:18 -0500894 } else if (taskPosition != TASK_POSITION_SAME) {
Winson3e874742016-01-07 10:08:17 -0800895 calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide),
896 mOtherRect);
897 int dockSideInverted = DockedDividerUtils.invertDockSide(mDockSide);
Jorim Jaggie435e982015-12-30 13:54:32 +0100898 int taskPositionDocked =
899 restrictDismissingTaskPosition(taskPosition, mDockSide, taskSnapTarget);
900 int taskPositionOther =
901 restrictDismissingTaskPosition(taskPosition, dockSideInverted, taskSnapTarget);
902 calculateBoundsForPosition(taskPositionDocked, mDockSide, mDockedTaskRect);
903 calculateBoundsForPosition(taskPositionOther, dockSideInverted, mOtherTaskRect);
Jorim Jaggi899327f2016-02-25 20:44:18 -0500904 mDisplayRect.set(0, 0, mDisplayWidth, mDisplayHeight);
Jorim Jaggidc249c42015-12-15 14:57:31 -0800905 alignTopLeft(mDockedRect, mDockedTaskRect);
906 alignTopLeft(mOtherRect, mOtherTaskRect);
907 mDockedInsetRect.set(mDockedTaskRect);
908 mOtherInsetRect.set(mOtherTaskRect);
Jorim Jaggie435e982015-12-30 13:54:32 +0100909 if (dockSideTopLeft(mDockSide)) {
Jorim Jaggi899327f2016-02-25 20:44:18 -0500910 alignTopLeft(mDisplayRect, mDockedInsetRect);
911 alignBottomRight(mDisplayRect, mOtherInsetRect);
Jorim Jaggidc249c42015-12-15 14:57:31 -0800912 } else {
Jorim Jaggi899327f2016-02-25 20:44:18 -0500913 alignBottomRight(mDisplayRect, mDockedInsetRect);
914 alignTopLeft(mDisplayRect, mOtherInsetRect);
Jorim Jaggidc249c42015-12-15 14:57:31 -0800915 }
Jorim Jaggie435e982015-12-30 13:54:32 +0100916 applyDismissingParallax(mDockedTaskRect, mDockSide, taskSnapTarget, position,
917 taskPositionDocked);
918 applyDismissingParallax(mOtherTaskRect, dockSideInverted, taskSnapTarget, position,
919 taskPositionOther);
Jorim Jaggidc249c42015-12-15 14:57:31 -0800920 mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, mDockedInsetRect,
921 mOtherTaskRect, mOtherInsetRect);
922 } else {
923 mWindowManagerProxy.resizeDockedStack(mDockedRect, null, null, null, null);
924 }
Jorim Jaggi1b12ef52016-01-29 16:49:55 -0800925 SnapTarget closestDismissTarget = mSnapAlgorithm.getClosestDismissTarget(position);
926 float dimFraction = getDimFraction(position, closestDismissTarget);
927 mWindowManagerProxy.setResizeDimLayer(dimFraction != 0f,
928 getStackIdForDismissTarget(closestDismissTarget),
929 dimFraction);
930 }
931
Jorim Jaggi545c5c22016-04-12 18:59:45 -0700932 private void applyExitAnimationParallax(Rect taskRect, int position) {
933 if (mDockSide == WindowManager.DOCKED_TOP) {
934 taskRect.offset(0, (int) ((position - mExitStartPosition) * 0.25f));
935 } else if (mDockSide == WindowManager.DOCKED_LEFT) {
936 taskRect.offset((int) ((position - mExitStartPosition) * 0.25f), 0);
937 } else if (mDockSide == WindowManager.DOCKED_RIGHT) {
938 taskRect.offset((int) ((mExitStartPosition - position) * 0.25f), 0);
939 }
940 }
941
Jorim Jaggi1b12ef52016-01-29 16:49:55 -0800942 private float getDimFraction(int position, SnapTarget dismissTarget) {
Jorim Jaggi899327f2016-02-25 20:44:18 -0500943 if (mEntranceAnimationRunning) {
944 return 0f;
945 }
Jorim Jaggi50981592015-12-29 17:54:12 +0100946 float fraction = mSnapAlgorithm.calculateDismissingFraction(position);
Jorim Jaggi8f8155b2016-01-25 19:45:42 -0800947 fraction = Math.max(0, Math.min(fraction, 1f));
948 fraction = DIM_INTERPOLATOR.getInterpolation(fraction);
Jorim Jaggi1b12ef52016-01-29 16:49:55 -0800949 if (hasInsetsAtDismissTarget(dismissTarget)) {
950
951 // Less darkening with system insets.
952 fraction *= 0.8f;
953 }
954 return fraction;
955 }
956
957 /**
958 * @return true if and only if there are system insets at the location of the dismiss target
959 */
960 private boolean hasInsetsAtDismissTarget(SnapTarget dismissTarget) {
961 if (isHorizontalDivision()) {
962 if (dismissTarget == mSnapAlgorithm.getDismissStartTarget()) {
963 return mStableInsets.top != 0;
964 } else {
965 return mStableInsets.bottom != 0;
966 }
967 } else {
968 if (dismissTarget == mSnapAlgorithm.getDismissStartTarget()) {
969 return mStableInsets.left != 0;
970 } else {
971 return mStableInsets.right != 0;
972 }
973 }
Jorim Jaggi50981592015-12-29 17:54:12 +0100974 }
975
Jorim Jaggie435e982015-12-30 13:54:32 +0100976 /**
977 * When the snap target is dismissing one side, make sure that the dismissing side doesn't get
978 * 0 size.
979 */
980 private int restrictDismissingTaskPosition(int taskPosition, int dockSide,
981 SnapTarget snapTarget) {
982 if (snapTarget.flag == SnapTarget.FLAG_DISMISS_START && dockSideTopLeft(dockSide)) {
Jorim Jaggi069dfe62016-05-04 17:24:47 -0700983 return Math.max(mSnapAlgorithm.getFirstSplitTarget().position, mStartPosition);
Jorim Jaggie435e982015-12-30 13:54:32 +0100984 } else if (snapTarget.flag == SnapTarget.FLAG_DISMISS_END
985 && dockSideBottomRight(dockSide)) {
Jorim Jaggi069dfe62016-05-04 17:24:47 -0700986 return Math.min(mSnapAlgorithm.getLastSplitTarget().position, mStartPosition);
Jorim Jaggie435e982015-12-30 13:54:32 +0100987 } else {
988 return taskPosition;
989 }
990 }
991
992 /**
993 * Applies a parallax to the task when dismissing.
994 */
995 private void applyDismissingParallax(Rect taskRect, int dockSide, SnapTarget snapTarget,
996 int position, int taskPosition) {
997 float fraction = Math.min(1, Math.max(0,
998 mSnapAlgorithm.calculateDismissingFraction(position)));
999 SnapTarget dismissTarget = null;
1000 SnapTarget splitTarget = null;
Jorim Jaggi8dccd232016-03-25 18:10:14 -07001001 int start = 0;
1002 if (position <= mSnapAlgorithm.getLastSplitTarget().position
Jorim Jaggie435e982015-12-30 13:54:32 +01001003 && dockSideTopLeft(dockSide)) {
1004 dismissTarget = mSnapAlgorithm.getDismissStartTarget();
1005 splitTarget = mSnapAlgorithm.getFirstSplitTarget();
Jorim Jaggi8dccd232016-03-25 18:10:14 -07001006 start = taskPosition;
1007 } else if (position >= mSnapAlgorithm.getLastSplitTarget().position
Jorim Jaggie435e982015-12-30 13:54:32 +01001008 && dockSideBottomRight(dockSide)) {
1009 dismissTarget = mSnapAlgorithm.getDismissEndTarget();
1010 splitTarget = mSnapAlgorithm.getLastSplitTarget();
Jorim Jaggi8dccd232016-03-25 18:10:14 -07001011 start = splitTarget.position;
Jorim Jaggie435e982015-12-30 13:54:32 +01001012 }
1013 if (dismissTarget != null && fraction > 0f
1014 && isDismissing(splitTarget, position, dockSide)) {
Jorim Jaggi1b12ef52016-01-29 16:49:55 -08001015 fraction = calculateParallaxDismissingFraction(fraction, dockSide);
Jorim Jaggi8dccd232016-03-25 18:10:14 -07001016 int offsetPosition = (int) (start +
Jorim Jaggie435e982015-12-30 13:54:32 +01001017 fraction * (dismissTarget.position - splitTarget.position));
1018 int width = taskRect.width();
1019 int height = taskRect.height();
1020 switch (dockSide) {
1021 case WindowManager.DOCKED_LEFT:
1022 taskRect.left = offsetPosition - width;
1023 taskRect.right = offsetPosition;
1024 break;
1025 case WindowManager.DOCKED_RIGHT:
1026 taskRect.left = offsetPosition + mDividerSize;
1027 taskRect.right = offsetPosition + width + mDividerSize;
1028 break;
1029 case WindowManager.DOCKED_TOP:
1030 taskRect.top = offsetPosition - height;
1031 taskRect.bottom = offsetPosition;
1032 break;
1033 case WindowManager.DOCKED_BOTTOM:
1034 taskRect.top = offsetPosition + mDividerSize;
1035 taskRect.bottom = offsetPosition + height + mDividerSize;
1036 break;
1037 }
1038 }
1039 }
1040
1041 /**
1042 * @return for a specified {@code fraction}, this returns an adjusted value that simulates a
1043 * slowing down parallax effect
1044 */
Jorim Jaggi1b12ef52016-01-29 16:49:55 -08001045 private static float calculateParallaxDismissingFraction(float fraction, int dockSide) {
1046 float result = SLOWDOWN_INTERPOLATOR.getInterpolation(fraction) / 3.5f;
1047
1048 // Less parallax at the top, just because.
1049 if (dockSide == WindowManager.DOCKED_TOP) {
1050 result /= 2f;
1051 }
1052 return result;
Jorim Jaggie435e982015-12-30 13:54:32 +01001053 }
1054
1055 private static boolean isDismissing(SnapTarget snapTarget, int position, int dockSide) {
1056 if (dockSide == WindowManager.DOCKED_TOP || dockSide == WindowManager.DOCKED_LEFT) {
1057 return position < snapTarget.position;
1058 } else {
1059 return position > snapTarget.position;
1060 }
1061 }
1062
Jorim Jaggi50981592015-12-29 17:54:12 +01001063 private int getStackIdForDismissTarget(SnapTarget dismissTarget) {
Jorim Jaggi8dccd232016-03-25 18:10:14 -07001064 if ((dismissTarget.flag == SnapTarget.FLAG_DISMISS_START && dockSideTopLeft(mDockSide))
1065 || (dismissTarget.flag == SnapTarget.FLAG_DISMISS_END
1066 && dockSideBottomRight(mDockSide))) {
Jorim Jaggi50981592015-12-29 17:54:12 +01001067 return StackId.DOCKED_STACK_ID;
1068 } else {
Jorim Jaggi8dccd232016-03-25 18:10:14 -07001069 return StackId.HOME_STACK_ID;
Jorim Jaggi50981592015-12-29 17:54:12 +01001070 }
Jorim Jaggi1fcbab62015-11-04 16:39:50 +01001071 }
1072
Jorim Jaggie435e982015-12-30 13:54:32 +01001073 /**
1074 * @return true if and only if {@code dockSide} is top or left
1075 */
1076 private static boolean dockSideTopLeft(int dockSide) {
1077 return dockSide == WindowManager.DOCKED_TOP || dockSide == WindowManager.DOCKED_LEFT;
1078 }
1079
1080 /**
1081 * @return true if and only if {@code dockSide} is bottom or right
1082 */
1083 private static boolean dockSideBottomRight(int dockSide) {
1084 return dockSide == WindowManager.DOCKED_BOTTOM || dockSide == WindowManager.DOCKED_RIGHT;
1085 }
1086
Jorim Jaggi1fcbab62015-11-04 16:39:50 +01001087 @Override
1088 public void onComputeInternalInsets(InternalInsetsInfo inoutInfo) {
1089 inoutInfo.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
1090 inoutInfo.touchableRegion.set(mHandle.getLeft(), mHandle.getTop(), mHandle.getRight(),
1091 mHandle.getBottom());
1092 inoutInfo.touchableRegion.op(mBackground.getLeft(), mBackground.getTop(),
1093 mBackground.getRight(), mBackground.getBottom(), Op.UNION);
1094 }
Jorim Jaggi11cc01d2016-01-22 19:39:23 -08001095
Jorim Jaggidb21bbd2016-04-18 15:32:07 -07001096 /**
1097 * Checks whether recents will grow when invoked. This happens in multi-window when recents is
1098 * very small. When invoking recents, we shrink the docked stack so recents has more space.
1099 *
1100 * @return the position of the divider when recents grows, or
1101 * {@link #INVALID_RECENTS_GROW_TARGET} if recents won't grow
1102 */
1103 public int growsRecents() {
1104 boolean result = mGrowRecents
1105 && mWindowManagerProxy.getDockSide() == WindowManager.DOCKED_TOP
1106 && getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position;
1107 if (result) {
1108 return getSnapAlgorithm().getMiddleTarget().position;
1109 } else {
1110 return INVALID_RECENTS_GROW_TARGET;
1111 }
1112 }
1113
Jorim Jaggicdb06ca2016-01-25 19:15:12 -08001114 public final void onBusEvent(RecentsActivityStartingEvent recentsActivityStartingEvent) {
1115 if (mGrowRecents && getWindowManagerProxy().getDockSide() == WindowManager.DOCKED_TOP
Qiushi.Han9170ca82016-10-10 13:31:48 +08001116 && getSnapAlgorithm().getMiddleTarget() != getSnapAlgorithm().getLastSplitTarget()
Jorim Jaggicdb06ca2016-01-25 19:15:12 -08001117 && getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position) {
Jorim Jaggia6c05d52016-05-27 00:31:21 -07001118 mState.growAfterRecentsDrawn = true;
Jorim Jaggicdb06ca2016-01-25 19:15:12 -08001119 startDragging(false /* animate */, false /* touching */);
1120 }
1121 }
1122
Jorim Jaggi899327f2016-02-25 20:44:18 -05001123 public final void onBusEvent(DockedTopTaskEvent event) {
1124 if (event.dragMode == NavigationBarGestureHelper.DRAG_MODE_NONE) {
Jorim Jaggia6c05d52016-05-27 00:31:21 -07001125 mState.growAfterRecentsDrawn = false;
1126 mState.animateAfterRecentsDrawn = true;
Jorim Jaggicdb06ca2016-01-25 19:15:12 -08001127 startDragging(false /* animate */, false /* touching */);
1128 }
Jorim Jaggi899327f2016-02-25 20:44:18 -05001129 updateDockSide();
1130 int position = DockedDividerUtils.calculatePositionForBounds(event.initialRect,
1131 mDockSide, mDividerSize);
1132 mEntranceAnimationRunning = true;
Jorim Jaggie525a352016-05-27 16:56:55 -07001133
1134 // Insets might not have been fetched yet, so fetch manually if needed.
1135 if (mStableInsets.isEmpty()) {
1136 SystemServicesProxy.getInstance(mContext).getStableInsets(mStableInsets);
1137 mSnapAlgorithm = null;
1138 initializeSnapAlgorithm();
1139 }
1140
Jorim Jaggi899327f2016-02-25 20:44:18 -05001141 resizeStack(position, mSnapAlgorithm.getMiddleTarget().position,
1142 mSnapAlgorithm.getMiddleTarget());
Jorim Jaggi11cc01d2016-01-22 19:39:23 -08001143 }
1144
1145 public final void onBusEvent(RecentsDrawnEvent drawnEvent) {
Jorim Jaggia6c05d52016-05-27 00:31:21 -07001146 if (mState.animateAfterRecentsDrawn) {
1147 mState.animateAfterRecentsDrawn = false;
Jorim Jaggi9511b0f2016-01-29 19:12:44 -08001148 updateDockSide();
Jorim Jaggi545c5c22016-04-12 18:59:45 -07001149
Jorim Jaggia6c05d52016-05-27 00:31:21 -07001150 mHandler.post(() -> {
Jorim Jaggic5887ea2016-05-13 18:21:48 -07001151 // Delay switching resizing mode because this might cause jank in recents animation
1152 // that's longer than this animation.
1153 stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(),
1154 mLongPressEntraceAnimDuration, Interpolators.FAST_OUT_SLOW_IN,
1155 200 /* endDelay */);
1156 });
Jorim Jaggi11cc01d2016-01-22 19:39:23 -08001157 }
Jorim Jaggia6c05d52016-05-27 00:31:21 -07001158 if (mState.growAfterRecentsDrawn) {
1159 mState.growAfterRecentsDrawn = false;
Jorim Jaggi9511b0f2016-01-29 19:12:44 -08001160 updateDockSide();
Jorim Jaggidb21bbd2016-04-18 15:32:07 -07001161 EventBus.getDefault().send(new RecentsGrowingEvent());
1162 stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(), 336,
Jorim Jaggi545c5c22016-04-12 18:59:45 -07001163 Interpolators.FAST_OUT_SLOW_IN);
Jorim Jaggiea4a19f2016-02-03 21:31:27 -08001164 }
1165 }
1166
1167 public final void onBusEvent(UndockingTaskEvent undockingTaskEvent) {
1168 int dockSide = mWindowManagerProxy.getDockSide();
Jorim Jaggief92d6f2016-03-25 22:07:16 -07001169 if (dockSide != WindowManager.DOCKED_INVALID && !mDockedStackMinimized) {
Jorim Jaggiea4a19f2016-02-03 21:31:27 -08001170 startDragging(false /* animate */, false /* touching */);
1171 SnapTarget target = dockSideTopLeft(dockSide)
1172 ? mSnapAlgorithm.getDismissEndTarget()
1173 : mSnapAlgorithm.getDismissStartTarget();
1174
1175 // Don't start immediately - give a little bit time to settle the drag resize change.
Jorim Jaggi47ee9ad2016-04-11 21:51:11 -07001176 mExitAnimationRunning = true;
1177 mExitStartPosition = getCurrentPosition();
1178 stopDragging(mExitStartPosition, target, 336 /* duration */, 100 /* startDelay */,
Jorim Jaggi545c5c22016-04-12 18:59:45 -07001179 0 /* endDelay */, Interpolators.FAST_OUT_SLOW_IN);
Jorim Jaggicdb06ca2016-01-25 19:15:12 -08001180 }
Jorim Jaggi11cc01d2016-01-22 19:39:23 -08001181 }
Jorim Jaggi1fcbab62015-11-04 16:39:50 +01001182}