Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package com.android.systemui.stackdivider; |
| 18 | |
Michael Wright | f9d9ce77 | 2016-05-13 17:44:16 +0100 | [diff] [blame] | 19 | import static android.view.PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW; |
| 20 | import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW; |
Matthew Ng | 62c7846 | 2018-04-09 14:43:21 -0700 | [diff] [blame] | 21 | import static android.view.WindowManager.DOCKED_RIGHT; |
Jorim Jaggi | d47e7e1 | 2016-03-01 09:57:38 +0100 | [diff] [blame] | 22 | |
Tony Huang | 89d580c | 2020-03-26 14:10:26 +0800 | [diff] [blame] | 23 | import android.animation.AnimationHandler; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 24 | import android.animation.Animator; |
| 25 | import android.animation.AnimatorListenerAdapter; |
| 26 | import android.animation.ValueAnimator; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 27 | import android.annotation.Nullable; |
| 28 | import android.content.Context; |
| 29 | import android.content.res.Configuration; |
Evan Rosky | 0f4db1b | 2020-04-28 16:20:00 -0700 | [diff] [blame] | 30 | import android.graphics.Matrix; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 31 | import android.graphics.Rect; |
Evan Rosky | 1283728 | 2020-04-27 19:12:25 -0700 | [diff] [blame] | 32 | import android.graphics.Region; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 33 | import android.graphics.Region.Op; |
Filip Gruszczynski | f6d8e9e | 2015-11-12 13:39:20 -0800 | [diff] [blame] | 34 | import android.hardware.display.DisplayManager; |
Jorim Jaggi | 88afd02 | 2016-02-24 21:11:08 -0500 | [diff] [blame] | 35 | import android.os.Bundle; |
Jorim Jaggi | a6c05d5 | 2016-05-27 00:31:21 -0700 | [diff] [blame] | 36 | import android.os.Handler; |
Evan Rosky | 0f4db1b | 2020-04-28 16:20:00 -0700 | [diff] [blame] | 37 | import android.os.RemoteException; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 38 | import android.util.AttributeSet; |
Evan Rosky | fdc71c4 | 2020-03-13 18:23:08 -0700 | [diff] [blame] | 39 | import android.util.Slog; |
Filip Gruszczynski | f6d8e9e | 2015-11-12 13:39:20 -0800 | [diff] [blame] | 40 | import android.view.Display; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 41 | import android.view.MotionEvent; |
Jun Mukai | d4eaef7 | 2015-10-30 15:54:33 -0700 | [diff] [blame] | 42 | import android.view.PointerIcon; |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 43 | import android.view.SurfaceControl; |
| 44 | import android.view.SurfaceControl.Transaction; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 45 | import android.view.VelocityTracker; |
| 46 | import android.view.View; |
| 47 | import android.view.View.OnTouchListener; |
Jorim Jaggi | d8fb3ac | 2016-01-05 15:37:42 +0100 | [diff] [blame] | 48 | import android.view.ViewConfiguration; |
Evan Rosky | 3613854 | 2020-05-01 18:02:11 -0700 | [diff] [blame] | 49 | import android.view.ViewRootImpl; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 50 | import android.view.ViewTreeObserver.InternalInsetsInfo; |
| 51 | import android.view.ViewTreeObserver.OnComputeInternalInsetsListener; |
| 52 | import android.view.WindowManager; |
Jorim Jaggi | 88afd02 | 2016-02-24 21:11:08 -0500 | [diff] [blame] | 53 | import android.view.accessibility.AccessibilityNodeInfo; |
| 54 | import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 55 | import android.view.animation.Interpolator; |
| 56 | import android.view.animation.PathInterpolator; |
| 57 | import android.widget.FrameLayout; |
Gus Prevas | ab33679 | 2018-11-14 13:52:20 -0500 | [diff] [blame] | 58 | |
Tony Huang | 89d580c | 2020-03-26 14:10:26 +0800 | [diff] [blame] | 59 | import com.android.internal.graphics.SfVsyncFrameCallbackProvider; |
Jorim Jaggi | 29379ec | 2016-04-11 23:43:42 -0700 | [diff] [blame] | 60 | import com.android.internal.logging.MetricsLogger; |
Tamas Berghammer | 383db5eb | 2016-06-22 15:21:38 +0100 | [diff] [blame] | 61 | import com.android.internal.logging.nano.MetricsProto.MetricsEvent; |
Jorim Jaggi | 737af72 | 2015-12-31 10:42:27 +0100 | [diff] [blame] | 62 | import com.android.internal.policy.DividerSnapAlgorithm; |
Winson | c0d7058 | 2016-01-29 10:24:39 -0800 | [diff] [blame] | 63 | import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget; |
Jorim Jaggi | 737af72 | 2015-12-31 10:42:27 +0100 | [diff] [blame] | 64 | import com.android.internal.policy.DockedDividerUtils; |
Sunny Goyal | 2148254 | 2020-05-05 16:34:17 -0700 | [diff] [blame] | 65 | import com.android.systemui.Dependency; |
Jorim Jaggi | ea4a19f | 2016-02-03 21:31:27 -0800 | [diff] [blame] | 66 | import com.android.systemui.Interpolators; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 67 | import com.android.systemui.R; |
Sunny Goyal | 2148254 | 2020-05-05 16:34:17 -0700 | [diff] [blame] | 68 | import com.android.systemui.recents.OverviewProxyService; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 69 | import com.android.systemui.statusbar.FlingAnimationUtils; |
| 70 | |
Evan Rosky | c0eec05 | 2020-03-06 18:54:55 -0800 | [diff] [blame] | 71 | import java.util.function.Consumer; |
| 72 | |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 73 | /** |
| 74 | * Docked stack divider. |
| 75 | */ |
| 76 | public class DividerView extends FrameLayout implements OnTouchListener, |
| 77 | OnComputeInternalInsetsListener { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 78 | private static final String TAG = "DividerView"; |
Evan Rosky | fdc71c4 | 2020-03-13 18:23:08 -0700 | [diff] [blame] | 79 | private static final boolean DEBUG = Divider.DEBUG; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 80 | |
Winson Chung | 67f5c8b | 2018-09-24 12:09:19 -0700 | [diff] [blame] | 81 | public interface DividerCallbacks { |
| 82 | void onDraggingStart(); |
| 83 | void onDraggingEnd(); |
| 84 | void growRecents(); |
| 85 | } |
| 86 | |
Jorim Jaggi | 514b2cf | 2016-01-04 13:06:34 +0100 | [diff] [blame] | 87 | static final long TOUCH_ANIMATION_DURATION = 150; |
| 88 | static final long TOUCH_RELEASE_ANIMATION_DURATION = 200; |
Jorim Jaggi | 514b2cf | 2016-01-04 13:06:34 +0100 | [diff] [blame] | 89 | |
Jorim Jaggi | db21bbd | 2016-04-18 15:32:07 -0700 | [diff] [blame] | 90 | public static final int INVALID_RECENTS_GROW_TARGET = -1; |
| 91 | |
Jorim Jaggi | 29379ec | 2016-04-11 23:43:42 -0700 | [diff] [blame] | 92 | private static final int LOG_VALUE_RESIZE_50_50 = 0; |
| 93 | private static final int LOG_VALUE_RESIZE_DOCKED_SMALLER = 1; |
| 94 | private static final int LOG_VALUE_RESIZE_DOCKED_LARGER = 2; |
| 95 | |
| 96 | private static final int LOG_VALUE_UNDOCK_MAX_DOCKED = 0; |
| 97 | private static final int LOG_VALUE_UNDOCK_MAX_OTHER = 1; |
| 98 | |
Jorim Jaggi | dc249c4 | 2015-12-15 14:57:31 -0800 | [diff] [blame] | 99 | private static final int TASK_POSITION_SAME = Integer.MAX_VALUE; |
| 100 | |
Jorim Jaggi | 50cd636 | 2016-01-22 17:18:29 -0800 | [diff] [blame] | 101 | /** |
Jorim Jaggi | 42625d1b | 2016-02-11 20:11:07 -0800 | [diff] [blame] | 102 | * How much the background gets scaled when we are in the minimized dock state. |
| 103 | */ |
Jorim Jaggi | 2917dc4 | 2016-04-11 11:39:13 -0700 | [diff] [blame] | 104 | private static final float MINIMIZE_DOCK_SCALE = 0f; |
Jorim Jaggi | 698e763 | 2016-04-13 21:02:22 -0700 | [diff] [blame] | 105 | private static final float ADJUSTED_FOR_IME_SCALE = 0.5f; |
Jorim Jaggi | 42625d1b | 2016-02-11 20:11:07 -0800 | [diff] [blame] | 106 | |
Jorim Jaggi | e435e98 | 2015-12-30 13:54:32 +0100 | [diff] [blame] | 107 | private static final PathInterpolator SLOWDOWN_INTERPOLATOR = |
| 108 | new PathInterpolator(0.5f, 1f, 0.5f, 1f); |
Jorim Jaggi | 8f8155b | 2016-01-25 19:45:42 -0800 | [diff] [blame] | 109 | private static final PathInterpolator DIM_INTERPOLATOR = |
| 110 | new PathInterpolator(.23f, .87f, .52f, -0.11f); |
Jorim Jaggi | 7b45839 | 2016-04-20 16:42:06 -0700 | [diff] [blame] | 111 | private static final Interpolator IME_ADJUST_INTERPOLATOR = |
| 112 | new PathInterpolator(0.2f, 0f, 0.1f, 1f); |
Jorim Jaggi | e435e98 | 2015-12-30 13:54:32 +0100 | [diff] [blame] | 113 | |
Jorim Jaggi | 514b2cf | 2016-01-04 13:06:34 +0100 | [diff] [blame] | 114 | private DividerHandleView mHandle; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 115 | private View mBackground; |
Jorim Jaggi | 2917dc4 | 2016-04-11 11:39:13 -0700 | [diff] [blame] | 116 | private MinimizedDockShadow mMinimizedShadow; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 117 | private int mStartX; |
| 118 | private int mStartY; |
| 119 | private int mStartPosition; |
| 120 | private int mDockSide; |
Jorim Jaggi | d8fb3ac | 2016-01-05 15:37:42 +0100 | [diff] [blame] | 121 | private boolean mMoving; |
| 122 | private int mTouchSlop; |
Jorim Jaggi | e161f08 | 2016-02-05 14:26:16 -0800 | [diff] [blame] | 123 | private boolean mBackgroundLifted; |
Matthew Ng | e15352e | 2016-12-20 15:36:29 -0800 | [diff] [blame] | 124 | private boolean mIsInMinimizeInteraction; |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 125 | SnapTarget mSnapTargetBeforeMinimized; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 126 | |
| 127 | private int mDividerInsets; |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 128 | private final Display mDefaultDisplay; |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 129 | |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 130 | private int mDividerSize; |
| 131 | private int mTouchElevation; |
Jorim Jaggi | e370e15 | 2016-04-15 14:13:33 -0700 | [diff] [blame] | 132 | private int mLongPressEntraceAnimDuration; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 133 | |
Jorim Jaggi | dc249c4 | 2015-12-15 14:57:31 -0800 | [diff] [blame] | 134 | private final Rect mDockedRect = new Rect(); |
| 135 | private final Rect mDockedTaskRect = new Rect(); |
| 136 | private final Rect mOtherTaskRect = new Rect(); |
| 137 | private final Rect mOtherRect = new Rect(); |
| 138 | private final Rect mDockedInsetRect = new Rect(); |
| 139 | private final Rect mOtherInsetRect = new Rect(); |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 140 | private final Rect mLastResizeRect = new Rect(); |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 141 | private final Rect mTmpRect = new Rect(); |
Evan Rosky | 3613854 | 2020-05-01 18:02:11 -0700 | [diff] [blame] | 142 | private WindowManagerProxy mWindowManagerProxy; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 143 | private DividerWindowManager mWindowManager; |
| 144 | private VelocityTracker mVelocityTracker; |
| 145 | private FlingAnimationUtils mFlingAnimationUtils; |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 146 | private SplitDisplayLayout mSplitLayout; |
Evan Rosky | c3a5090 | 2020-05-19 13:36:28 -0700 | [diff] [blame] | 147 | private DividerImeController mImeController; |
Winson Chung | 67f5c8b | 2018-09-24 12:09:19 -0700 | [diff] [blame] | 148 | private DividerCallbacks mCallback; |
Tony Huang | 89d580c | 2020-03-26 14:10:26 +0800 | [diff] [blame] | 149 | private final AnimationHandler mAnimationHandler = new AnimationHandler(); |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 150 | |
Jorim Jaggi | cdb06ca | 2016-01-25 19:15:12 -0800 | [diff] [blame] | 151 | private boolean mGrowRecents; |
Jorim Jaggi | 899327f | 2016-02-25 20:44:18 -0500 | [diff] [blame] | 152 | private ValueAnimator mCurrentAnimator; |
| 153 | private boolean mEntranceAnimationRunning; |
Jorim Jaggi | 47ee9ad | 2016-04-11 21:51:11 -0700 | [diff] [blame] | 154 | private boolean mExitAnimationRunning; |
| 155 | private int mExitStartPosition; |
Jorim Jaggi | ef92d6f | 2016-03-25 22:07:16 -0700 | [diff] [blame] | 156 | private boolean mDockedStackMinimized; |
Matthew Ng | e15352e | 2016-12-20 15:36:29 -0800 | [diff] [blame] | 157 | private boolean mHomeStackResizable; |
Jorim Jaggi | 698e763 | 2016-04-13 21:02:22 -0700 | [diff] [blame] | 158 | private boolean mAdjustedForIme; |
Jorim Jaggi | a6c05d5 | 2016-05-27 00:31:21 -0700 | [diff] [blame] | 159 | private DividerState mState; |
Jorim Jaggi | dbe6fdb | 2016-07-29 17:16:03 +0200 | [diff] [blame] | 160 | |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 161 | private SplitScreenTaskOrganizer mTiles; |
| 162 | boolean mFirstLayout = true; |
| 163 | int mDividerPositionX; |
| 164 | int mDividerPositionY; |
Winson Chung | 67f5c8b | 2018-09-24 12:09:19 -0700 | [diff] [blame] | 165 | |
Evan Rosky | 0f4db1b | 2020-04-28 16:20:00 -0700 | [diff] [blame] | 166 | private final Matrix mTmpMatrix = new Matrix(); |
| 167 | private final float[] mTmpValues = new float[9]; |
| 168 | |
Wale Ogunwale | 15ba151 | 2017-06-06 08:31:17 -0700 | [diff] [blame] | 169 | // The view is removed or in the process of been removed from the system. |
| 170 | private boolean mRemoved; |
| 171 | |
Evan Rosky | e5fb45a | 2020-03-09 10:51:27 -0700 | [diff] [blame] | 172 | // Whether the surface for this view has been hidden regardless of actual visibility. This is |
| 173 | // used interact with keyguard. |
| 174 | private boolean mSurfaceHidden = false; |
| 175 | |
Tony Huang | 89d580c | 2020-03-26 14:10:26 +0800 | [diff] [blame] | 176 | private final Handler mHandler = new Handler(); |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 177 | |
Jorim Jaggi | 88afd02 | 2016-02-24 21:11:08 -0500 | [diff] [blame] | 178 | private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() { |
| 179 | @Override |
| 180 | public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { |
| 181 | super.onInitializeAccessibilityNodeInfo(host, info); |
Matthew Ng | 6317df6 | 2018-05-04 15:42:54 -0700 | [diff] [blame] | 182 | final DividerSnapAlgorithm snapAlgorithm = getSnapAlgorithm(); |
Jorim Jaggi | 88afd02 | 2016-02-24 21:11:08 -0500 | [diff] [blame] | 183 | if (isHorizontalDivision()) { |
Winson | ce9630d | 2016-04-19 11:33:04 -0700 | [diff] [blame] | 184 | info.addAction(new AccessibilityAction(R.id.action_move_tl_full, |
| 185 | mContext.getString(R.string.accessibility_action_divider_top_full))); |
Matthew Ng | 6317df6 | 2018-05-04 15:42:54 -0700 | [diff] [blame] | 186 | if (snapAlgorithm.isFirstSplitTargetAvailable()) { |
Winson | ce9630d | 2016-04-19 11:33:04 -0700 | [diff] [blame] | 187 | info.addAction(new AccessibilityAction(R.id.action_move_tl_70, |
| 188 | mContext.getString(R.string.accessibility_action_divider_top_70))); |
| 189 | } |
Matthew Ng | 6317df6 | 2018-05-04 15:42:54 -0700 | [diff] [blame] | 190 | if (snapAlgorithm.showMiddleSplitTargetForAccessibility()) { |
| 191 | // Only show the middle target if there are more than 1 split target |
| 192 | info.addAction(new AccessibilityAction(R.id.action_move_tl_50, |
Winson | ce9630d | 2016-04-19 11:33:04 -0700 | [diff] [blame] | 193 | mContext.getString(R.string.accessibility_action_divider_top_50))); |
Matthew Ng | 6317df6 | 2018-05-04 15:42:54 -0700 | [diff] [blame] | 194 | } |
| 195 | if (snapAlgorithm.isLastSplitTargetAvailable()) { |
Winson | ce9630d | 2016-04-19 11:33:04 -0700 | [diff] [blame] | 196 | info.addAction(new AccessibilityAction(R.id.action_move_tl_30, |
| 197 | mContext.getString(R.string.accessibility_action_divider_top_30))); |
| 198 | } |
| 199 | info.addAction(new AccessibilityAction(R.id.action_move_rb_full, |
| 200 | mContext.getString(R.string.accessibility_action_divider_bottom_full))); |
Jorim Jaggi | 88afd02 | 2016-02-24 21:11:08 -0500 | [diff] [blame] | 201 | } else { |
Winson | ce9630d | 2016-04-19 11:33:04 -0700 | [diff] [blame] | 202 | info.addAction(new AccessibilityAction(R.id.action_move_tl_full, |
| 203 | mContext.getString(R.string.accessibility_action_divider_left_full))); |
Matthew Ng | 6317df6 | 2018-05-04 15:42:54 -0700 | [diff] [blame] | 204 | if (snapAlgorithm.isFirstSplitTargetAvailable()) { |
Winson | ce9630d | 2016-04-19 11:33:04 -0700 | [diff] [blame] | 205 | info.addAction(new AccessibilityAction(R.id.action_move_tl_70, |
| 206 | mContext.getString(R.string.accessibility_action_divider_left_70))); |
| 207 | } |
Matthew Ng | 6317df6 | 2018-05-04 15:42:54 -0700 | [diff] [blame] | 208 | if (snapAlgorithm.showMiddleSplitTargetForAccessibility()) { |
| 209 | // Only show the middle target if there are more than 1 split target |
| 210 | info.addAction(new AccessibilityAction(R.id.action_move_tl_50, |
Winson | ce9630d | 2016-04-19 11:33:04 -0700 | [diff] [blame] | 211 | mContext.getString(R.string.accessibility_action_divider_left_50))); |
Matthew Ng | 6317df6 | 2018-05-04 15:42:54 -0700 | [diff] [blame] | 212 | } |
| 213 | if (snapAlgorithm.isLastSplitTargetAvailable()) { |
Winson | ce9630d | 2016-04-19 11:33:04 -0700 | [diff] [blame] | 214 | info.addAction(new AccessibilityAction(R.id.action_move_tl_30, |
| 215 | mContext.getString(R.string.accessibility_action_divider_left_30))); |
| 216 | } |
| 217 | info.addAction(new AccessibilityAction(R.id.action_move_rb_full, |
| 218 | mContext.getString(R.string.accessibility_action_divider_right_full))); |
Jorim Jaggi | 88afd02 | 2016-02-24 21:11:08 -0500 | [diff] [blame] | 219 | } |
| 220 | } |
| 221 | |
| 222 | @Override |
| 223 | public boolean performAccessibilityAction(View host, int action, Bundle args) { |
Winson | ce9630d | 2016-04-19 11:33:04 -0700 | [diff] [blame] | 224 | int currentPosition = getCurrentPosition(); |
| 225 | SnapTarget nextTarget = null; |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 226 | DividerSnapAlgorithm snapAlgorithm = mSplitLayout.getSnapAlgorithm(); |
Jason Monk | 05dd567 | 2018-08-09 09:38:21 -0400 | [diff] [blame] | 227 | if (action == R.id.action_move_tl_full) { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 228 | nextTarget = snapAlgorithm.getDismissEndTarget(); |
Jason Monk | 05dd567 | 2018-08-09 09:38:21 -0400 | [diff] [blame] | 229 | } else if (action == R.id.action_move_tl_70) { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 230 | nextTarget = snapAlgorithm.getLastSplitTarget(); |
Jason Monk | 05dd567 | 2018-08-09 09:38:21 -0400 | [diff] [blame] | 231 | } else if (action == R.id.action_move_tl_50) { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 232 | nextTarget = snapAlgorithm.getMiddleTarget(); |
Jason Monk | 05dd567 | 2018-08-09 09:38:21 -0400 | [diff] [blame] | 233 | } else if (action == R.id.action_move_tl_30) { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 234 | nextTarget = snapAlgorithm.getFirstSplitTarget(); |
Jason Monk | 05dd567 | 2018-08-09 09:38:21 -0400 | [diff] [blame] | 235 | } else if (action == R.id.action_move_rb_full) { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 236 | nextTarget = snapAlgorithm.getDismissStartTarget(); |
Winson | ce9630d | 2016-04-19 11:33:04 -0700 | [diff] [blame] | 237 | } |
| 238 | if (nextTarget != null) { |
Jorim Jaggi | 88afd02 | 2016-02-24 21:11:08 -0500 | [diff] [blame] | 239 | startDragging(true /* animate */, false /* touching */); |
Winson | ce9630d | 2016-04-19 11:33:04 -0700 | [diff] [blame] | 240 | stopDragging(currentPosition, nextTarget, 250, Interpolators.FAST_OUT_SLOW_IN); |
Jorim Jaggi | 88afd02 | 2016-02-24 21:11:08 -0500 | [diff] [blame] | 241 | return true; |
| 242 | } |
| 243 | return super.performAccessibilityAction(host, action, args); |
| 244 | } |
| 245 | }; |
| 246 | |
Jorim Jaggi | e661f40 | 2016-03-25 19:11:35 -0700 | [diff] [blame] | 247 | private final Runnable mResetBackgroundRunnable = new Runnable() { |
| 248 | @Override |
| 249 | public void run() { |
| 250 | resetBackground(); |
| 251 | } |
| 252 | }; |
| 253 | |
Evan Rosky | 0f4db1b | 2020-04-28 16:20:00 -0700 | [diff] [blame] | 254 | private Runnable mUpdateEmbeddedMatrix = () -> { |
| 255 | if (getViewRootImpl() == null) { |
| 256 | return; |
| 257 | } |
| 258 | if (isHorizontalDivision()) { |
| 259 | mTmpMatrix.setTranslate(0, mDividerPositionY - mDividerInsets); |
| 260 | } else { |
| 261 | mTmpMatrix.setTranslate(mDividerPositionX - mDividerInsets, 0); |
| 262 | } |
| 263 | mTmpMatrix.getValues(mTmpValues); |
| 264 | try { |
| 265 | getViewRootImpl().getAccessibilityEmbeddedConnection().setScreenMatrix(mTmpValues); |
| 266 | } catch (RemoteException e) { |
| 267 | } |
| 268 | }; |
| 269 | |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 270 | public DividerView(Context context) { |
Matthew Ng | a10a9db | 2017-05-23 15:00:56 -0700 | [diff] [blame] | 271 | this(context, null); |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 272 | } |
| 273 | |
| 274 | public DividerView(Context context, @Nullable AttributeSet attrs) { |
Matthew Ng | a10a9db | 2017-05-23 15:00:56 -0700 | [diff] [blame] | 275 | this(context, attrs, 0); |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 276 | } |
| 277 | |
| 278 | public DividerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { |
Matthew Ng | a10a9db | 2017-05-23 15:00:56 -0700 | [diff] [blame] | 279 | this(context, attrs, defStyleAttr, 0); |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 280 | } |
| 281 | |
| 282 | public DividerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, |
| 283 | int defStyleRes) { |
| 284 | super(context, attrs, defStyleAttr, defStyleRes); |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 285 | final DisplayManager displayManager = |
| 286 | (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE); |
| 287 | mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY); |
Tony Huang | 89d580c | 2020-03-26 14:10:26 +0800 | [diff] [blame] | 288 | mAnimationHandler.setProvider(new SfVsyncFrameCallbackProvider()); |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 289 | } |
| 290 | |
| 291 | @Override |
| 292 | protected void onFinishInflate() { |
| 293 | super.onFinishInflate(); |
Alan Viverette | 51efddb | 2017-04-05 10:00:01 -0400 | [diff] [blame] | 294 | mHandle = findViewById(R.id.docked_divider_handle); |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 295 | mBackground = findViewById(R.id.docked_divider_background); |
Alan Viverette | 51efddb | 2017-04-05 10:00:01 -0400 | [diff] [blame] | 296 | mMinimizedShadow = findViewById(R.id.minimized_dock_shadow); |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 297 | mHandle.setOnTouchListener(this); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 298 | final int dividerWindowWidth = getResources().getDimensionPixelSize( |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 299 | com.android.internal.R.dimen.docked_stack_divider_thickness); |
| 300 | mDividerInsets = getResources().getDimensionPixelSize( |
| 301 | com.android.internal.R.dimen.docked_stack_divider_insets); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 302 | mDividerSize = dividerWindowWidth - 2 * mDividerInsets; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 303 | mTouchElevation = getResources().getDimensionPixelSize( |
| 304 | R.dimen.docked_stack_divider_lift_elevation); |
Jorim Jaggi | e370e15 | 2016-04-15 14:13:33 -0700 | [diff] [blame] | 305 | mLongPressEntraceAnimDuration = getResources().getInteger( |
| 306 | R.integer.long_press_dock_anim_duration); |
Jorim Jaggi | cdb06ca | 2016-01-25 19:15:12 -0800 | [diff] [blame] | 307 | mGrowRecents = getResources().getBoolean(R.bool.recents_grow_in_multiwindow); |
Jorim Jaggi | d8fb3ac | 2016-01-05 15:37:42 +0100 | [diff] [blame] | 308 | mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop(); |
Dave Mankoff | 1373fdb | 2019-12-18 14:04:37 -0500 | [diff] [blame] | 309 | mFlingAnimationUtils = new FlingAnimationUtils(getResources().getDisplayMetrics(), 0.3f); |
Jorim Jaggi | e48f428 | 2015-11-06 17:32:44 +0100 | [diff] [blame] | 310 | boolean landscape = getResources().getConfiguration().orientation |
| 311 | == Configuration.ORIENTATION_LANDSCAPE; |
Jun Mukai | d4eaef7 | 2015-10-30 15:54:33 -0700 | [diff] [blame] | 312 | mHandle.setPointerIcon(PointerIcon.getSystemIcon(getContext(), |
Michael Wright | f9d9ce77 | 2016-05-13 17:44:16 +0100 | [diff] [blame] | 313 | landscape ? TYPE_HORIZONTAL_DOUBLE_ARROW : TYPE_VERTICAL_DOUBLE_ARROW)); |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 314 | getViewTreeObserver().addOnComputeInternalInsetsListener(this); |
Jorim Jaggi | 88afd02 | 2016-02-24 21:11:08 -0500 | [diff] [blame] | 315 | mHandle.setAccessibilityDelegate(mHandleDelegate); |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 316 | } |
| 317 | |
Jorim Jaggi | 81fe2d1 | 2015-12-21 14:45:18 +0100 | [diff] [blame] | 318 | @Override |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 319 | protected void onAttachedToWindow() { |
| 320 | super.onAttachedToWindow(); |
Matthew Ng | 597bcbb | 2017-09-07 17:17:38 -0700 | [diff] [blame] | 321 | |
| 322 | // Save the current target if not minimized once attached to window |
Evan Rosky | 89c285e | 2020-06-17 21:21:53 -0700 | [diff] [blame] | 323 | if (mDockSide != WindowManager.DOCKED_INVALID && !mIsInMinimizeInteraction) { |
Matthew Ng | 597bcbb | 2017-09-07 17:17:38 -0700 | [diff] [blame] | 324 | saveSnapTargetBeforeMinimized(mSnapTargetBeforeMinimized); |
| 325 | } |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 326 | mFirstLayout = true; |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 327 | } |
| 328 | |
Wale Ogunwale | 15ba151 | 2017-06-06 08:31:17 -0700 | [diff] [blame] | 329 | void onDividerRemoved() { |
| 330 | mRemoved = true; |
Winson Chung | 67f5c8b | 2018-09-24 12:09:19 -0700 | [diff] [blame] | 331 | mCallback = null; |
Wale Ogunwale | 15ba151 | 2017-06-06 08:31:17 -0700 | [diff] [blame] | 332 | } |
| 333 | |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 334 | @Override |
Jorim Jaggi | 8eb8a32 | 2016-04-05 18:03:56 -0700 | [diff] [blame] | 335 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { |
Evan Rosky | 1283728 | 2020-04-27 19:12:25 -0700 | [diff] [blame] | 336 | super.onLayout(changed, left, top, right, bottom); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 337 | if (mFirstLayout) { |
| 338 | // Wait for first layout so that the ViewRootImpl surface has been created. |
| 339 | initializeSurfaceState(); |
| 340 | mFirstLayout = false; |
| 341 | } |
Jorim Jaggi | 2917dc4 | 2016-04-11 11:39:13 -0700 | [diff] [blame] | 342 | int minimizeLeft = 0; |
| 343 | int minimizeTop = 0; |
| 344 | if (mDockSide == WindowManager.DOCKED_TOP) { |
| 345 | minimizeTop = mBackground.getTop(); |
| 346 | } else if (mDockSide == WindowManager.DOCKED_LEFT) { |
| 347 | minimizeLeft = mBackground.getLeft(); |
| 348 | } else if (mDockSide == WindowManager.DOCKED_RIGHT) { |
| 349 | minimizeLeft = mBackground.getRight() - mMinimizedShadow.getWidth(); |
| 350 | } |
| 351 | mMinimizedShadow.layout(minimizeLeft, minimizeTop, |
| 352 | minimizeLeft + mMinimizedShadow.getMeasuredWidth(), |
| 353 | minimizeTop + mMinimizedShadow.getMeasuredHeight()); |
Jorim Jaggi | 8eb8a32 | 2016-04-05 18:03:56 -0700 | [diff] [blame] | 354 | if (changed) { |
Sunny Goyal | 2148254 | 2020-05-05 16:34:17 -0700 | [diff] [blame] | 355 | notifySplitScreenBoundsChanged(); |
Jorim Jaggi | 8eb8a32 | 2016-04-05 18:03:56 -0700 | [diff] [blame] | 356 | } |
| 357 | } |
| 358 | |
Winson Chung | 67f5c8b | 2018-09-24 12:09:19 -0700 | [diff] [blame] | 359 | public void injectDependencies(DividerWindowManager windowManager, DividerState dividerState, |
Evan Rosky | c3a5090 | 2020-05-19 13:36:28 -0700 | [diff] [blame] | 360 | DividerCallbacks callback, SplitScreenTaskOrganizer tiles, SplitDisplayLayout sdl, |
Evan Rosky | 3613854 | 2020-05-01 18:02:11 -0700 | [diff] [blame] | 361 | DividerImeController imeController, WindowManagerProxy wmProxy) { |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 362 | mWindowManager = windowManager; |
Jorim Jaggi | a6c05d5 | 2016-05-27 00:31:21 -0700 | [diff] [blame] | 363 | mState = dividerState; |
Winson Chung | 67f5c8b | 2018-09-24 12:09:19 -0700 | [diff] [blame] | 364 | mCallback = callback; |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 365 | mTiles = tiles; |
| 366 | mSplitLayout = sdl; |
Evan Rosky | c3a5090 | 2020-05-19 13:36:28 -0700 | [diff] [blame] | 367 | mImeController = imeController; |
Evan Rosky | 3613854 | 2020-05-01 18:02:11 -0700 | [diff] [blame] | 368 | mWindowManagerProxy = wmProxy; |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 369 | |
| 370 | if (mState.mRatioPositionBeforeMinimized == 0) { |
| 371 | // Set the middle target as the initial state |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 372 | mSnapTargetBeforeMinimized = mSplitLayout.getSnapAlgorithm().getMiddleTarget(); |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 373 | } else { |
| 374 | repositionSnapTargetBeforeMinimized(); |
| 375 | } |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 376 | } |
| 377 | |
Matthew Ng | c603a50 | 2018-04-18 17:14:22 -0700 | [diff] [blame] | 378 | public Rect getNonMinimizedSplitScreenSecondaryBounds() { |
Sunny Goyal | 2148254 | 2020-05-05 16:34:17 -0700 | [diff] [blame] | 379 | mOtherTaskRect.set(mSplitLayout.mSecondary); |
Matthew Ng | c603a50 | 2018-04-18 17:14:22 -0700 | [diff] [blame] | 380 | return mOtherTaskRect; |
| 381 | } |
| 382 | |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 383 | private boolean inSplitMode() { |
| 384 | return getVisibility() == VISIBLE; |
| 385 | } |
| 386 | |
| 387 | /** Unlike setVisible, this directly hides the surface without changing view visibility. */ |
| 388 | void setHidden(boolean hidden) { |
Evan Rosky | e5fb45a | 2020-03-09 10:51:27 -0700 | [diff] [blame] | 389 | if (mSurfaceHidden == hidden) { |
| 390 | return; |
| 391 | } |
| 392 | mSurfaceHidden = hidden; |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 393 | post(() -> { |
| 394 | final SurfaceControl sc = getWindowSurfaceControl(); |
| 395 | if (sc == null) { |
| 396 | return; |
| 397 | } |
| 398 | Transaction t = mTiles.getTransaction(); |
| 399 | if (hidden) { |
| 400 | t.hide(sc); |
| 401 | } else { |
| 402 | t.show(sc); |
| 403 | } |
Evan Rosky | c3a5090 | 2020-05-19 13:36:28 -0700 | [diff] [blame] | 404 | mImeController.setDimsHidden(t, hidden); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 405 | t.apply(); |
| 406 | mTiles.releaseTransaction(t); |
| 407 | }); |
| 408 | } |
| 409 | |
Evan Rosky | e5fb45a | 2020-03-09 10:51:27 -0700 | [diff] [blame] | 410 | boolean isHidden() { |
| 411 | return mSurfaceHidden; |
| 412 | } |
| 413 | |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 414 | public boolean startDragging(boolean animate, boolean touching) { |
Jorim Jaggi | 0c79041 | 2016-02-19 16:38:49 -0800 | [diff] [blame] | 415 | cancelFlingAnimation(); |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 416 | if (touching) { |
| 417 | mHandle.setTouching(true, animate); |
| 418 | } |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 419 | mDockSide = mSplitLayout.getPrimarySplitSide(); |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 420 | |
Jorim Jaggi | 9511b0f | 2016-01-29 19:12:44 -0800 | [diff] [blame] | 421 | mWindowManagerProxy.setResizing(true); |
Jorim Jaggi | 9511b0f | 2016-01-29 19:12:44 -0800 | [diff] [blame] | 422 | if (touching) { |
Jorim Jaggi | e161f08 | 2016-02-05 14:26:16 -0800 | [diff] [blame] | 423 | mWindowManager.setSlippery(false); |
Jorim Jaggi | 9511b0f | 2016-01-29 19:12:44 -0800 | [diff] [blame] | 424 | liftBackground(); |
Jorim Jaggi | dd98d41 | 2015-11-18 15:57:38 -0800 | [diff] [blame] | 425 | } |
Winson Chung | 67f5c8b | 2018-09-24 12:09:19 -0700 | [diff] [blame] | 426 | if (mCallback != null) { |
| 427 | mCallback.onDraggingStart(); |
| 428 | } |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 429 | return inSplitMode(); |
Jorim Jaggi | dd98d41 | 2015-11-18 15:57:38 -0800 | [diff] [blame] | 430 | } |
| 431 | |
Jorim Jaggi | 29379ec | 2016-04-11 23:43:42 -0700 | [diff] [blame] | 432 | public void stopDragging(int position, float velocity, boolean avoidDismissStart, |
| 433 | boolean logMetrics) { |
Jorim Jaggi | 514b2cf | 2016-01-04 13:06:34 +0100 | [diff] [blame] | 434 | mHandle.setTouching(false, true /* animate */); |
Jorim Jaggi | 29379ec | 2016-04-11 23:43:42 -0700 | [diff] [blame] | 435 | fling(position, velocity, avoidDismissStart, logMetrics); |
Jorim Jaggi | dd98d41 | 2015-11-18 15:57:38 -0800 | [diff] [blame] | 436 | mWindowManager.setSlippery(true); |
| 437 | releaseBackground(); |
| 438 | } |
| 439 | |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 440 | public void stopDragging(int position, SnapTarget target, long duration, |
| 441 | Interpolator interpolator) { |
Jorim Jaggi | 545c5c2 | 2016-04-12 18:59:45 -0700 | [diff] [blame] | 442 | stopDragging(position, target, duration, 0 /* startDelay*/, 0 /* endDelay */, interpolator); |
| 443 | } |
| 444 | |
| 445 | public void stopDragging(int position, SnapTarget target, long duration, |
| 446 | Interpolator interpolator, long endDelay) { |
| 447 | stopDragging(position, target, duration, 0 /* startDelay*/, endDelay, interpolator); |
Jorim Jaggi | ea4a19f | 2016-02-03 21:31:27 -0800 | [diff] [blame] | 448 | } |
| 449 | |
| 450 | public void stopDragging(int position, SnapTarget target, long duration, long startDelay, |
Jorim Jaggi | 545c5c2 | 2016-04-12 18:59:45 -0700 | [diff] [blame] | 451 | long endDelay, Interpolator interpolator) { |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 452 | mHandle.setTouching(false, true /* animate */); |
Jorim Jaggi | 545c5c2 | 2016-04-12 18:59:45 -0700 | [diff] [blame] | 453 | flingTo(position, target, duration, startDelay, endDelay, interpolator); |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 454 | mWindowManager.setSlippery(true); |
| 455 | releaseBackground(); |
| 456 | } |
| 457 | |
Jorim Jaggi | 9511b0f | 2016-01-29 19:12:44 -0800 | [diff] [blame] | 458 | private void stopDragging() { |
| 459 | mHandle.setTouching(false, true /* animate */); |
| 460 | mWindowManager.setSlippery(true); |
| 461 | releaseBackground(); |
| 462 | } |
| 463 | |
| 464 | private void updateDockSide() { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 465 | mDockSide = mSplitLayout.getPrimarySplitSide(); |
Jorim Jaggi | 2917dc4 | 2016-04-11 11:39:13 -0700 | [diff] [blame] | 466 | mMinimizedShadow.setDockSide(mDockSide); |
Jorim Jaggi | 9511b0f | 2016-01-29 19:12:44 -0800 | [diff] [blame] | 467 | } |
| 468 | |
Jorim Jaggi | defd922 | 2016-02-03 18:28:49 -0800 | [diff] [blame] | 469 | public DividerSnapAlgorithm getSnapAlgorithm() { |
Evan Rosky | 89c285e | 2020-06-17 21:21:53 -0700 | [diff] [blame] | 470 | return mDockedStackMinimized ? mSplitLayout.getMinimizedSnapAlgorithm(mHomeStackResizable) |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 471 | : mSplitLayout.getSnapAlgorithm(); |
Jorim Jaggi | dc249c4 | 2015-12-15 14:57:31 -0800 | [diff] [blame] | 472 | } |
| 473 | |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 474 | public int getCurrentPosition() { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 475 | return isHorizontalDivision() ? mDividerPositionY : mDividerPositionX; |
| 476 | } |
| 477 | |
| 478 | public boolean isMinimized() { |
| 479 | return mDockedStackMinimized; |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 480 | } |
| 481 | |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 482 | @Override |
| 483 | public boolean onTouch(View v, MotionEvent event) { |
| 484 | convertToScreenCoordinates(event); |
| 485 | final int action = event.getAction() & MotionEvent.ACTION_MASK; |
| 486 | switch (action) { |
| 487 | case MotionEvent.ACTION_DOWN: |
| 488 | mVelocityTracker = VelocityTracker.obtain(); |
| 489 | mVelocityTracker.addMovement(event); |
| 490 | mStartX = (int) event.getX(); |
| 491 | mStartY = (int) event.getY(); |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 492 | boolean result = startDragging(true /* animate */, true /* touching */); |
Jorim Jaggi | 9511b0f | 2016-01-29 19:12:44 -0800 | [diff] [blame] | 493 | if (!result) { |
| 494 | |
| 495 | // Weren't able to start dragging successfully, so cancel it again. |
| 496 | stopDragging(); |
| 497 | } |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 498 | mStartPosition = getCurrentPosition(); |
Jorim Jaggi | d8fb3ac | 2016-01-05 15:37:42 +0100 | [diff] [blame] | 499 | mMoving = false; |
Jorim Jaggi | dd98d41 | 2015-11-18 15:57:38 -0800 | [diff] [blame] | 500 | return result; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 501 | case MotionEvent.ACTION_MOVE: |
| 502 | mVelocityTracker.addMovement(event); |
| 503 | int x = (int) event.getX(); |
| 504 | int y = (int) event.getY(); |
Jorim Jaggi | d8fb3ac | 2016-01-05 15:37:42 +0100 | [diff] [blame] | 505 | boolean exceededTouchSlop = |
| 506 | isHorizontalDivision() && Math.abs(y - mStartY) > mTouchSlop |
| 507 | || (!isHorizontalDivision() && Math.abs(x - mStartX) > mTouchSlop); |
| 508 | if (!mMoving && exceededTouchSlop) { |
| 509 | mStartX = x; |
| 510 | mStartY = y; |
| 511 | mMoving = true; |
| 512 | } |
| 513 | if (mMoving && mDockSide != WindowManager.DOCKED_INVALID) { |
Matthew Ng | e15352e | 2016-12-20 15:36:29 -0800 | [diff] [blame] | 514 | SnapTarget snapTarget = getSnapAlgorithm().calculateSnapTarget( |
Wale Ogunwale | ef676d8 | 2016-03-18 12:51:55 -0700 | [diff] [blame] | 515 | mStartPosition, 0 /* velocity */, false /* hardDismiss */); |
Evan Rosky | 3613854 | 2020-05-01 18:02:11 -0700 | [diff] [blame] | 516 | resizeStackSurfaces(calculatePosition(x, y), mStartPosition, snapTarget, |
| 517 | null /* transaction */); |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 518 | } |
| 519 | break; |
| 520 | case MotionEvent.ACTION_UP: |
| 521 | case MotionEvent.ACTION_CANCEL: |
| 522 | mVelocityTracker.addMovement(event); |
| 523 | |
| 524 | x = (int) event.getRawX(); |
| 525 | y = (int) event.getRawY(); |
| 526 | |
| 527 | mVelocityTracker.computeCurrentVelocity(1000); |
Jorim Jaggi | dd98d41 | 2015-11-18 15:57:38 -0800 | [diff] [blame] | 528 | int position = calculatePosition(x, y); |
| 529 | stopDragging(position, isHorizontalDivision() ? mVelocityTracker.getYVelocity() |
Jorim Jaggi | 29379ec | 2016-04-11 23:43:42 -0700 | [diff] [blame] | 530 | : mVelocityTracker.getXVelocity(), false /* avoidDismissStart */, |
| 531 | true /* log */); |
Jorim Jaggi | d8fb3ac | 2016-01-05 15:37:42 +0100 | [diff] [blame] | 532 | mMoving = false; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 533 | break; |
| 534 | } |
| 535 | return true; |
| 536 | } |
| 537 | |
Jorim Jaggi | 29379ec | 2016-04-11 23:43:42 -0700 | [diff] [blame] | 538 | private void logResizeEvent(SnapTarget snapTarget) { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 539 | if (snapTarget == mSplitLayout.getSnapAlgorithm().getDismissStartTarget()) { |
Jorim Jaggi | 29379ec | 2016-04-11 23:43:42 -0700 | [diff] [blame] | 540 | MetricsLogger.action( |
| 541 | mContext, MetricsEvent.ACTION_WINDOW_UNDOCK_MAX, dockSideTopLeft(mDockSide) |
| 542 | ? LOG_VALUE_UNDOCK_MAX_OTHER |
| 543 | : LOG_VALUE_UNDOCK_MAX_DOCKED); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 544 | } else if (snapTarget == mSplitLayout.getSnapAlgorithm().getDismissEndTarget()) { |
Jorim Jaggi | 29379ec | 2016-04-11 23:43:42 -0700 | [diff] [blame] | 545 | MetricsLogger.action( |
| 546 | mContext, MetricsEvent.ACTION_WINDOW_UNDOCK_MAX, dockSideBottomRight(mDockSide) |
| 547 | ? LOG_VALUE_UNDOCK_MAX_OTHER |
| 548 | : LOG_VALUE_UNDOCK_MAX_DOCKED); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 549 | } else if (snapTarget == mSplitLayout.getSnapAlgorithm().getMiddleTarget()) { |
Jorim Jaggi | 29379ec | 2016-04-11 23:43:42 -0700 | [diff] [blame] | 550 | MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE, |
| 551 | LOG_VALUE_RESIZE_50_50); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 552 | } else if (snapTarget == mSplitLayout.getSnapAlgorithm().getFirstSplitTarget()) { |
Jorim Jaggi | 29379ec | 2016-04-11 23:43:42 -0700 | [diff] [blame] | 553 | MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE, |
| 554 | dockSideTopLeft(mDockSide) |
| 555 | ? LOG_VALUE_RESIZE_DOCKED_SMALLER |
| 556 | : LOG_VALUE_RESIZE_DOCKED_LARGER); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 557 | } else if (snapTarget == mSplitLayout.getSnapAlgorithm().getLastSplitTarget()) { |
Jorim Jaggi | 29379ec | 2016-04-11 23:43:42 -0700 | [diff] [blame] | 558 | MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE, |
| 559 | dockSideTopLeft(mDockSide) |
| 560 | ? LOG_VALUE_RESIZE_DOCKED_LARGER |
| 561 | : LOG_VALUE_RESIZE_DOCKED_SMALLER); |
| 562 | } |
| 563 | } |
| 564 | |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 565 | private void convertToScreenCoordinates(MotionEvent event) { |
| 566 | event.setLocation(event.getRawX(), event.getRawY()); |
| 567 | } |
| 568 | |
Jorim Jaggi | 29379ec | 2016-04-11 23:43:42 -0700 | [diff] [blame] | 569 | private void fling(int position, float velocity, boolean avoidDismissStart, |
| 570 | boolean logMetrics) { |
Matthew Ng | e15352e | 2016-12-20 15:36:29 -0800 | [diff] [blame] | 571 | DividerSnapAlgorithm currentSnapAlgorithm = getSnapAlgorithm(); |
| 572 | SnapTarget snapTarget = currentSnapAlgorithm.calculateSnapTarget(position, velocity); |
| 573 | if (avoidDismissStart && snapTarget == currentSnapAlgorithm.getDismissStartTarget()) { |
| 574 | snapTarget = currentSnapAlgorithm.getFirstSplitTarget(); |
Jorim Jaggi | df012d5 | 2016-01-15 22:40:13 -0800 | [diff] [blame] | 575 | } |
Jorim Jaggi | 29379ec | 2016-04-11 23:43:42 -0700 | [diff] [blame] | 576 | if (logMetrics) { |
| 577 | logResizeEvent(snapTarget); |
| 578 | } |
Jorim Jaggi | 545c5c2 | 2016-04-12 18:59:45 -0700 | [diff] [blame] | 579 | ValueAnimator anim = getFlingAnimator(position, snapTarget, 0 /* endDelay */); |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 580 | mFlingAnimationUtils.apply(anim, position, snapTarget.position, velocity); |
| 581 | anim.start(); |
| 582 | } |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 583 | |
Jorim Jaggi | ea4a19f | 2016-02-03 21:31:27 -0800 | [diff] [blame] | 584 | private void flingTo(int position, SnapTarget target, long duration, long startDelay, |
Jorim Jaggi | 545c5c2 | 2016-04-12 18:59:45 -0700 | [diff] [blame] | 585 | long endDelay, Interpolator interpolator) { |
| 586 | ValueAnimator anim = getFlingAnimator(position, target, endDelay); |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 587 | anim.setDuration(duration); |
Jorim Jaggi | ea4a19f | 2016-02-03 21:31:27 -0800 | [diff] [blame] | 588 | anim.setStartDelay(startDelay); |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 589 | anim.setInterpolator(interpolator); |
| 590 | anim.start(); |
| 591 | } |
| 592 | |
Jorim Jaggi | 545c5c2 | 2016-04-12 18:59:45 -0700 | [diff] [blame] | 593 | private ValueAnimator getFlingAnimator(int position, final SnapTarget snapTarget, |
| 594 | final long endDelay) { |
Matthew Ng | e15352e | 2016-12-20 15:36:29 -0800 | [diff] [blame] | 595 | if (mCurrentAnimator != null) { |
| 596 | cancelFlingAnimation(); |
| 597 | updateDockSide(); |
| 598 | } |
Evan Rosky | fdc71c4 | 2020-03-13 18:23:08 -0700 | [diff] [blame] | 599 | if (DEBUG) Slog.d(TAG, "Getting fling " + position + "->" + snapTarget.position); |
Jorim Jaggi | 069dfe6 | 2016-05-04 17:24:47 -0700 | [diff] [blame] | 600 | final boolean taskPositionSameAtEnd = snapTarget.flag == SnapTarget.FLAG_NONE; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 601 | ValueAnimator anim = ValueAnimator.ofInt(position, snapTarget.position); |
Tony Huang | 89d580c | 2020-03-26 14:10:26 +0800 | [diff] [blame] | 602 | anim.addUpdateListener(animation -> resizeStackSurfaces((int) animation.getAnimatedValue(), |
Jorim Jaggi | 069dfe6 | 2016-05-04 17:24:47 -0700 | [diff] [blame] | 603 | taskPositionSameAtEnd && animation.getAnimatedFraction() == 1f |
| 604 | ? TASK_POSITION_SAME |
Jorim Jaggi | dbe6fdb | 2016-07-29 17:16:03 +0200 | [diff] [blame] | 605 | : snapTarget.taskPosition, |
Evan Rosky | 3613854 | 2020-05-01 18:02:11 -0700 | [diff] [blame] | 606 | snapTarget, null /* transaction */)); |
Evan Rosky | c0eec05 | 2020-03-06 18:54:55 -0800 | [diff] [blame] | 607 | Consumer<Boolean> endAction = cancelled -> { |
Evan Rosky | fdc71c4 | 2020-03-13 18:23:08 -0700 | [diff] [blame] | 608 | if (DEBUG) Slog.d(TAG, "End Fling " + cancelled + " min:" + mIsInMinimizeInteraction); |
Evan Rosky | c0eec05 | 2020-03-06 18:54:55 -0800 | [diff] [blame] | 609 | final boolean wasMinimizeInteraction = mIsInMinimizeInteraction; |
| 610 | // Reset minimized divider position after unminimized state animation finishes. |
| 611 | if (!cancelled && !mDockedStackMinimized && mIsInMinimizeInteraction) { |
| 612 | mIsInMinimizeInteraction = false; |
| 613 | } |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 614 | boolean dismissed = commitSnapFlags(snapTarget); |
Jorim Jaggi | 545c5c2 | 2016-04-12 18:59:45 -0700 | [diff] [blame] | 615 | mWindowManagerProxy.setResizing(false); |
Matthew Ng | d411f6c | 2017-07-26 11:09:35 -0700 | [diff] [blame] | 616 | updateDockSide(); |
Jorim Jaggi | 545c5c2 | 2016-04-12 18:59:45 -0700 | [diff] [blame] | 617 | mCurrentAnimator = null; |
| 618 | mEntranceAnimationRunning = false; |
| 619 | mExitAnimationRunning = false; |
Evan Rosky | c0eec05 | 2020-03-06 18:54:55 -0800 | [diff] [blame] | 620 | if (!dismissed && !wasMinimizeInteraction) { |
| 621 | WindowManagerProxy.applyResizeSplits(snapTarget.position, mSplitLayout); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 622 | } |
Winson Chung | 67f5c8b | 2018-09-24 12:09:19 -0700 | [diff] [blame] | 623 | if (mCallback != null) { |
| 624 | mCallback.onDraggingEnd(); |
| 625 | } |
Matthew Ng | 597bcbb | 2017-09-07 17:17:38 -0700 | [diff] [blame] | 626 | |
| 627 | // Record last snap target the divider moved to |
Evan Rosky | 89c285e | 2020-06-17 21:21:53 -0700 | [diff] [blame] | 628 | if (!mIsInMinimizeInteraction) { |
chaviw | ee947f2 | 2018-03-27 16:49:27 -0700 | [diff] [blame] | 629 | // The last snapTarget position can be negative when the last divider position was |
| 630 | // offscreen. In that case, save the middle (default) SnapTarget so calculating next |
| 631 | // position isn't negative. |
| 632 | final SnapTarget saveTarget; |
| 633 | if (snapTarget.position < 0) { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 634 | saveTarget = mSplitLayout.getSnapAlgorithm().getMiddleTarget(); |
chaviw | ee947f2 | 2018-03-27 16:49:27 -0700 | [diff] [blame] | 635 | } else { |
| 636 | saveTarget = snapTarget; |
| 637 | } |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 638 | final DividerSnapAlgorithm snapAlgo = mSplitLayout.getSnapAlgorithm(); |
| 639 | if (saveTarget.position != snapAlgo.getDismissEndTarget().position |
| 640 | && saveTarget.position != snapAlgo.getDismissStartTarget().position) { |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 641 | saveSnapTargetBeforeMinimized(saveTarget); |
| 642 | } |
Matthew Ng | 597bcbb | 2017-09-07 17:17:38 -0700 | [diff] [blame] | 643 | } |
Sunny Goyal | 2148254 | 2020-05-05 16:34:17 -0700 | [diff] [blame] | 644 | notifySplitScreenBoundsChanged(); |
Jorim Jaggi | 545c5c2 | 2016-04-12 18:59:45 -0700 | [diff] [blame] | 645 | }; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 646 | anim.addListener(new AnimatorListenerAdapter() { |
Jorim Jaggi | 545c5c2 | 2016-04-12 18:59:45 -0700 | [diff] [blame] | 647 | |
| 648 | private boolean mCancelled; |
| 649 | |
| 650 | @Override |
| 651 | public void onAnimationCancel(Animator animation) { |
| 652 | mCancelled = true; |
| 653 | } |
| 654 | |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 655 | @Override |
| 656 | public void onAnimationEnd(Animator animation) { |
Jorim Jaggi | dbe6fdb | 2016-07-29 17:16:03 +0200 | [diff] [blame] | 657 | long delay = 0; |
| 658 | if (endDelay != 0) { |
| 659 | delay = endDelay; |
| 660 | } else if (mCancelled) { |
| 661 | delay = 0; |
Jorim Jaggi | dbe6fdb | 2016-07-29 17:16:03 +0200 | [diff] [blame] | 662 | } |
| 663 | if (delay == 0) { |
Evan Rosky | c0eec05 | 2020-03-06 18:54:55 -0800 | [diff] [blame] | 664 | endAction.accept(mCancelled); |
Jorim Jaggi | 545c5c2 | 2016-04-12 18:59:45 -0700 | [diff] [blame] | 665 | } else { |
Evan Rosky | c0eec05 | 2020-03-06 18:54:55 -0800 | [diff] [blame] | 666 | final Boolean cancelled = mCancelled; |
Evan Rosky | fdc71c4 | 2020-03-13 18:23:08 -0700 | [diff] [blame] | 667 | if (DEBUG) Slog.d(TAG, "Posting endFling " + cancelled + " d:" + delay + "ms"); |
Evan Rosky | c0eec05 | 2020-03-06 18:54:55 -0800 | [diff] [blame] | 668 | mHandler.postDelayed(() -> endAction.accept(cancelled), delay); |
Jorim Jaggi | 545c5c2 | 2016-04-12 18:59:45 -0700 | [diff] [blame] | 669 | } |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 670 | } |
| 671 | }); |
Tony Huang | 89d580c | 2020-03-26 14:10:26 +0800 | [diff] [blame] | 672 | anim.setAnimationHandler(mAnimationHandler); |
Jorim Jaggi | 0c79041 | 2016-02-19 16:38:49 -0800 | [diff] [blame] | 673 | mCurrentAnimator = anim; |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 674 | return anim; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 675 | } |
| 676 | |
Sunny Goyal | 2148254 | 2020-05-05 16:34:17 -0700 | [diff] [blame] | 677 | private void notifySplitScreenBoundsChanged() { |
| 678 | mOtherTaskRect.set(mSplitLayout.mSecondary); |
| 679 | |
Evan Rosky | 27634c4 | 2020-06-22 10:46:05 -0700 | [diff] [blame] | 680 | mTmpRect.set(mHandle.getLeft(), mHandle.getTop(), mHandle.getRight(), mHandle.getBottom()); |
| 681 | if (isHorizontalDivision()) { |
| 682 | mTmpRect.offsetTo(0, mDividerPositionY); |
| 683 | } else { |
| 684 | mTmpRect.offsetTo(mDividerPositionX, 0); |
| 685 | } |
| 686 | mWindowManagerProxy.setTouchRegion(mTmpRect); |
| 687 | |
Sunny Goyal | 2148254 | 2020-05-05 16:34:17 -0700 | [diff] [blame] | 688 | mTmpRect.set(mSplitLayout.mDisplayLayout.stableInsets()); |
| 689 | switch (mSplitLayout.getPrimarySplitSide()) { |
| 690 | case WindowManager.DOCKED_LEFT: |
| 691 | mTmpRect.left = 0; |
| 692 | break; |
| 693 | case WindowManager.DOCKED_RIGHT: |
| 694 | mTmpRect.right = 0; |
| 695 | break; |
| 696 | case WindowManager.DOCKED_TOP: |
| 697 | mTmpRect.top = 0; |
| 698 | break; |
| 699 | } |
| 700 | Dependency.get(OverviewProxyService.class) |
| 701 | .notifySplitScreenBoundsChanged(mOtherTaskRect, mTmpRect); |
| 702 | } |
| 703 | |
Jorim Jaggi | 0c79041 | 2016-02-19 16:38:49 -0800 | [diff] [blame] | 704 | private void cancelFlingAnimation() { |
| 705 | if (mCurrentAnimator != null) { |
| 706 | mCurrentAnimator.cancel(); |
| 707 | } |
| 708 | } |
| 709 | |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 710 | private boolean commitSnapFlags(SnapTarget target) { |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 711 | if (target.flag == SnapTarget.FLAG_NONE) { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 712 | return false; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 713 | } |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 714 | final boolean dismissOrMaximize; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 715 | if (target.flag == SnapTarget.FLAG_DISMISS_START) { |
| 716 | dismissOrMaximize = mDockSide == WindowManager.DOCKED_LEFT |
| 717 | || mDockSide == WindowManager.DOCKED_TOP; |
| 718 | } else { |
| 719 | dismissOrMaximize = mDockSide == WindowManager.DOCKED_RIGHT |
| 720 | || mDockSide == WindowManager.DOCKED_BOTTOM; |
| 721 | } |
Evan Rosky | 3613854 | 2020-05-01 18:02:11 -0700 | [diff] [blame] | 722 | mWindowManagerProxy.dismissOrMaximizeDocked(mTiles, mSplitLayout, dismissOrMaximize); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 723 | Transaction t = mTiles.getTransaction(); |
| 724 | setResizeDimLayer(t, true /* primary */, 0f); |
| 725 | setResizeDimLayer(t, false /* primary */, 0f); |
| 726 | t.apply(); |
| 727 | mTiles.releaseTransaction(t); |
| 728 | return true; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 729 | } |
| 730 | |
| 731 | private void liftBackground() { |
Jorim Jaggi | e161f08 | 2016-02-05 14:26:16 -0800 | [diff] [blame] | 732 | if (mBackgroundLifted) { |
| 733 | return; |
| 734 | } |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 735 | if (isHorizontalDivision()) { |
Jorim Jaggi | 79b39f0 | 2015-12-17 20:04:31 -0800 | [diff] [blame] | 736 | mBackground.animate().scaleY(1.4f); |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 737 | } else { |
Jorim Jaggi | 79b39f0 | 2015-12-17 20:04:31 -0800 | [diff] [blame] | 738 | mBackground.animate().scaleX(1.4f); |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 739 | } |
| 740 | mBackground.animate() |
Jorim Jaggi | ea4a19f | 2016-02-03 21:31:27 -0800 | [diff] [blame] | 741 | .setInterpolator(Interpolators.TOUCH_RESPONSE) |
Jorim Jaggi | 514b2cf | 2016-01-04 13:06:34 +0100 | [diff] [blame] | 742 | .setDuration(TOUCH_ANIMATION_DURATION) |
| 743 | .translationZ(mTouchElevation) |
| 744 | .start(); |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 745 | |
| 746 | // Lift handle as well so it doesn't get behind the background, even though it doesn't |
| 747 | // cast shadow. |
| 748 | mHandle.animate() |
Jorim Jaggi | ea4a19f | 2016-02-03 21:31:27 -0800 | [diff] [blame] | 749 | .setInterpolator(Interpolators.TOUCH_RESPONSE) |
Jorim Jaggi | 514b2cf | 2016-01-04 13:06:34 +0100 | [diff] [blame] | 750 | .setDuration(TOUCH_ANIMATION_DURATION) |
| 751 | .translationZ(mTouchElevation) |
| 752 | .start(); |
Jorim Jaggi | e161f08 | 2016-02-05 14:26:16 -0800 | [diff] [blame] | 753 | mBackgroundLifted = true; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 754 | } |
| 755 | |
| 756 | private void releaseBackground() { |
Jorim Jaggi | e161f08 | 2016-02-05 14:26:16 -0800 | [diff] [blame] | 757 | if (!mBackgroundLifted) { |
| 758 | return; |
| 759 | } |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 760 | mBackground.animate() |
Jorim Jaggi | ea4a19f | 2016-02-03 21:31:27 -0800 | [diff] [blame] | 761 | .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) |
Jorim Jaggi | 514b2cf | 2016-01-04 13:06:34 +0100 | [diff] [blame] | 762 | .setDuration(TOUCH_RELEASE_ANIMATION_DURATION) |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 763 | .translationZ(0) |
| 764 | .scaleX(1f) |
Jorim Jaggi | 514b2cf | 2016-01-04 13:06:34 +0100 | [diff] [blame] | 765 | .scaleY(1f) |
| 766 | .start(); |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 767 | mHandle.animate() |
Jorim Jaggi | ea4a19f | 2016-02-03 21:31:27 -0800 | [diff] [blame] | 768 | .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) |
Jorim Jaggi | 514b2cf | 2016-01-04 13:06:34 +0100 | [diff] [blame] | 769 | .setDuration(TOUCH_RELEASE_ANIMATION_DURATION) |
| 770 | .translationZ(0) |
| 771 | .start(); |
Jorim Jaggi | e161f08 | 2016-02-05 14:26:16 -0800 | [diff] [blame] | 772 | mBackgroundLifted = false; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 773 | } |
| 774 | |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 775 | private void initializeSurfaceState() { |
| 776 | int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position; |
| 777 | // Recalculate the split-layout's internal tile bounds |
| 778 | mSplitLayout.resizeSplits(midPos); |
| 779 | Transaction t = mTiles.getTransaction(); |
| 780 | if (mDockedStackMinimized) { |
Evan Rosky | 89c285e | 2020-06-17 21:21:53 -0700 | [diff] [blame] | 781 | int position = mSplitLayout.getMinimizedSnapAlgorithm(mHomeStackResizable) |
| 782 | .getMiddleTarget().position; |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 783 | calculateBoundsForPosition(position, mDockSide, mDockedRect); |
| 784 | calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide), |
| 785 | mOtherRect); |
| 786 | mDividerPositionX = mDividerPositionY = position; |
| 787 | resizeSplitSurfaces(t, mDockedRect, mSplitLayout.mPrimary, |
| 788 | mOtherRect, mSplitLayout.mSecondary); |
| 789 | } else { |
| 790 | resizeSplitSurfaces(t, mSplitLayout.mPrimary, null, |
| 791 | mSplitLayout.mSecondary, null); |
| 792 | } |
| 793 | setResizeDimLayer(t, true /* primary */, 0.f /* alpha */); |
| 794 | setResizeDimLayer(t, false /* secondary */, 0.f /* alpha */); |
| 795 | t.apply(); |
| 796 | mTiles.releaseTransaction(t); |
Evan Rosky | 1283728 | 2020-04-27 19:12:25 -0700 | [diff] [blame] | 797 | |
| 798 | // Get the actually-visible bar dimensions (relative to full window). This is a thin |
| 799 | // bar going through the center. |
| 800 | final Rect dividerBar = isHorizontalDivision() |
| 801 | ? new Rect(0, mDividerInsets, mSplitLayout.mDisplayLayout.width(), |
| 802 | mDividerInsets + mDividerSize) |
| 803 | : new Rect(mDividerInsets, 0, mDividerInsets + mDividerSize, |
| 804 | mSplitLayout.mDisplayLayout.height()); |
| 805 | final Region touchRegion = new Region(dividerBar); |
| 806 | // Add in the "draggable" portion. While not visible, this is an expanded area that the |
| 807 | // user can interact with. |
| 808 | touchRegion.union(new Rect(mHandle.getLeft(), mHandle.getTop(), |
| 809 | mHandle.getRight(), mHandle.getBottom())); |
| 810 | mWindowManager.setTouchRegion(touchRegion); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 811 | } |
Jorim Jaggi | 42625d1b | 2016-02-11 20:11:07 -0800 | [diff] [blame] | 812 | |
Evan Rosky | 3613854 | 2020-05-01 18:02:11 -0700 | [diff] [blame] | 813 | void setMinimizedDockStack(boolean minimized, boolean isHomeStackResizable, |
| 814 | Transaction t) { |
Matthew Ng | e15352e | 2016-12-20 15:36:29 -0800 | [diff] [blame] | 815 | mHomeStackResizable = isHomeStackResizable; |
Jorim Jaggi | 42625d1b | 2016-02-11 20:11:07 -0800 | [diff] [blame] | 816 | updateDockSide(); |
Jorim Jaggi | e661f40 | 2016-03-25 19:11:35 -0700 | [diff] [blame] | 817 | if (!minimized) { |
| 818 | resetBackground(); |
Jorim Jaggi | 42625d1b | 2016-02-11 20:11:07 -0800 | [diff] [blame] | 819 | } |
Jorim Jaggi | 2917dc4 | 2016-04-11 11:39:13 -0700 | [diff] [blame] | 820 | mMinimizedShadow.setAlpha(minimized ? 1f : 0f); |
Evan Rosky | 89c285e | 2020-06-17 21:21:53 -0700 | [diff] [blame] | 821 | if (mDockedStackMinimized != minimized) { |
Matthew Ng | aa2b620 | 2017-02-10 14:48:21 -0800 | [diff] [blame] | 822 | mDockedStackMinimized = minimized; |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 823 | if (mSplitLayout.mDisplayLayout.rotation() != mDefaultDisplay.getRotation()) { |
Matthew Ng | 4c76a1c | 2018-05-14 12:45:08 -0700 | [diff] [blame] | 824 | // Splitscreen to minimize is about to starts after rotating landscape to seascape, |
Sunny Goyal | 2148254 | 2020-05-05 16:34:17 -0700 | [diff] [blame] | 825 | // update display info and snap algorithm targets |
Matthew Ng | 4c76a1c | 2018-05-14 12:45:08 -0700 | [diff] [blame] | 826 | repositionSnapTargetBeforeMinimized(); |
Matthew Ng | 4c76a1c | 2018-05-14 12:45:08 -0700 | [diff] [blame] | 827 | } |
Matthew Ng | a51dcaa | 2018-05-07 15:36:06 -0700 | [diff] [blame] | 828 | if (mIsInMinimizeInteraction != minimized || mCurrentAnimator != null) { |
| 829 | cancelFlingAnimation(); |
Matthew Ng | 04f3430 | 2017-04-27 16:28:49 -0700 | [diff] [blame] | 830 | if (minimized) { |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 831 | // Relayout to recalculate the divider shadow when minimizing |
| 832 | requestLayout(); |
Matthew Ng | 04f3430 | 2017-04-27 16:28:49 -0700 | [diff] [blame] | 833 | mIsInMinimizeInteraction = true; |
Evan Rosky | 89c285e | 2020-06-17 21:21:53 -0700 | [diff] [blame] | 834 | resizeStackSurfaces(mSplitLayout.getMinimizedSnapAlgorithm(mHomeStackResizable) |
| 835 | .getMiddleTarget(), t); |
Matthew Ng | 04f3430 | 2017-04-27 16:28:49 -0700 | [diff] [blame] | 836 | } else { |
Evan Rosky | 3613854 | 2020-05-01 18:02:11 -0700 | [diff] [blame] | 837 | resizeStackSurfaces(mSnapTargetBeforeMinimized, t); |
Matthew Ng | 04f3430 | 2017-04-27 16:28:49 -0700 | [diff] [blame] | 838 | mIsInMinimizeInteraction = false; |
| 839 | } |
Matthew Ng | e15352e | 2016-12-20 15:36:29 -0800 | [diff] [blame] | 840 | } |
Matthew Ng | e15352e | 2016-12-20 15:36:29 -0800 | [diff] [blame] | 841 | } |
Jorim Jaggi | 42625d1b | 2016-02-11 20:11:07 -0800 | [diff] [blame] | 842 | } |
| 843 | |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 844 | void enterSplitMode(boolean isHomeStackResizable) { |
| 845 | post(() -> { |
| 846 | final SurfaceControl sc = getWindowSurfaceControl(); |
| 847 | if (sc == null) { |
| 848 | return; |
| 849 | } |
| 850 | Transaction t = mTiles.getTransaction(); |
| 851 | t.show(sc).apply(); |
| 852 | mTiles.releaseTransaction(t); |
| 853 | }); |
Evan Rosky | 89c285e | 2020-06-17 21:21:53 -0700 | [diff] [blame] | 854 | |
| 855 | SnapTarget miniMid = |
| 856 | mSplitLayout.getMinimizedSnapAlgorithm(isHomeStackResizable).getMiddleTarget(); |
| 857 | if (mDockedStackMinimized) { |
| 858 | mDividerPositionY = mDividerPositionX = miniMid.position; |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 859 | } |
| 860 | } |
| 861 | |
| 862 | /** |
| 863 | * Tries to grab a surface control from ViewRootImpl. If this isn't available for some reason |
| 864 | * (ie. the window isn't ready yet), it will get the surfacecontrol that the WindowlessWM has |
| 865 | * assigned to it. |
| 866 | */ |
| 867 | private SurfaceControl getWindowSurfaceControl() { |
Evan Rosky | 3613854 | 2020-05-01 18:02:11 -0700 | [diff] [blame] | 868 | final ViewRootImpl root = getViewRootImpl(); |
| 869 | if (root == null) { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 870 | return null; |
| 871 | } |
Evan Rosky | 3613854 | 2020-05-01 18:02:11 -0700 | [diff] [blame] | 872 | SurfaceControl out = root.getSurfaceControl(); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 873 | if (out != null && out.isValid()) { |
| 874 | return out; |
| 875 | } |
| 876 | return mWindowManager.mSystemWindows.getViewSurface(this); |
| 877 | } |
| 878 | |
| 879 | void exitSplitMode() { |
| 880 | // Reset tile bounds |
Evan Rosky | 3613854 | 2020-05-01 18:02:11 -0700 | [diff] [blame] | 881 | final SurfaceControl sc = getWindowSurfaceControl(); |
| 882 | if (sc == null) { |
| 883 | return; |
| 884 | } |
| 885 | Transaction t = mTiles.getTransaction(); |
| 886 | t.hide(sc).apply(); |
| 887 | mTiles.releaseTransaction(t); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 888 | int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position; |
| 889 | WindowManagerProxy.applyResizeSplits(midPos, mSplitLayout); |
| 890 | } |
| 891 | |
Matthew Ng | e15352e | 2016-12-20 15:36:29 -0800 | [diff] [blame] | 892 | public void setMinimizedDockStack(boolean minimized, long animDuration, |
| 893 | boolean isHomeStackResizable) { |
Evan Rosky | fdc71c4 | 2020-03-13 18:23:08 -0700 | [diff] [blame] | 894 | if (DEBUG) Slog.d(TAG, "setMinDock: " + mDockedStackMinimized + "->" + minimized); |
Matthew Ng | e15352e | 2016-12-20 15:36:29 -0800 | [diff] [blame] | 895 | mHomeStackResizable = isHomeStackResizable; |
Jorim Jaggi | 42625d1b | 2016-02-11 20:11:07 -0800 | [diff] [blame] | 896 | updateDockSide(); |
Evan Rosky | 89c285e | 2020-06-17 21:21:53 -0700 | [diff] [blame] | 897 | if (mDockedStackMinimized != minimized) { |
Matthew Ng | e15352e | 2016-12-20 15:36:29 -0800 | [diff] [blame] | 898 | mIsInMinimizeInteraction = true; |
Matthew Ng | e15352e | 2016-12-20 15:36:29 -0800 | [diff] [blame] | 899 | mDockedStackMinimized = minimized; |
Matthew Ng | f9989e2 | 2017-04-24 17:14:14 -0700 | [diff] [blame] | 900 | stopDragging(minimized |
Matthew Ng | 597bcbb | 2017-09-07 17:17:38 -0700 | [diff] [blame] | 901 | ? mSnapTargetBeforeMinimized.position |
Matthew Ng | f9989e2 | 2017-04-24 17:14:14 -0700 | [diff] [blame] | 902 | : getCurrentPosition(), |
| 903 | minimized |
Evan Rosky | 89c285e | 2020-06-17 21:21:53 -0700 | [diff] [blame] | 904 | ? mSplitLayout.getMinimizedSnapAlgorithm(mHomeStackResizable) |
| 905 | .getMiddleTarget() |
Matthew Ng | 597bcbb | 2017-09-07 17:17:38 -0700 | [diff] [blame] | 906 | : mSnapTargetBeforeMinimized, |
Matthew Ng | e15352e | 2016-12-20 15:36:29 -0800 | [diff] [blame] | 907 | animDuration, Interpolators.FAST_OUT_SLOW_IN, 0); |
Matthew Ng | f9989e2 | 2017-04-24 17:14:14 -0700 | [diff] [blame] | 908 | setAdjustedForIme(false, animDuration); |
Jorim Jaggi | 42625d1b | 2016-02-11 20:11:07 -0800 | [diff] [blame] | 909 | } |
Jorim Jaggi | e661f40 | 2016-03-25 19:11:35 -0700 | [diff] [blame] | 910 | if (!minimized) { |
| 911 | mBackground.animate().withEndAction(mResetBackgroundRunnable); |
| 912 | } |
Jorim Jaggi | 42625d1b | 2016-02-11 20:11:07 -0800 | [diff] [blame] | 913 | mBackground.animate() |
| 914 | .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) |
| 915 | .setDuration(animDuration) |
| 916 | .start(); |
| 917 | } |
| 918 | |
Evan Rosky | c0eec05 | 2020-03-06 18:54:55 -0800 | [diff] [blame] | 919 | // Needed to end any currently playing animations when they might compete with other anims |
| 920 | // (specifically, IME adjust animation immediately after leaving minimized). Someday maybe |
| 921 | // these can be unified, but not today. |
| 922 | void finishAnimations() { |
| 923 | if (mCurrentAnimator != null) { |
| 924 | mCurrentAnimator.end(); |
| 925 | } |
| 926 | } |
| 927 | |
Jorim Jaggi | 698e763 | 2016-04-13 21:02:22 -0700 | [diff] [blame] | 928 | public void setAdjustedForIme(boolean adjustedForIme, long animDuration) { |
Evan Rosky | 9572920 | 2020-02-21 10:16:08 -0800 | [diff] [blame] | 929 | if (mAdjustedForIme == adjustedForIme) { |
| 930 | return; |
| 931 | } |
Jorim Jaggi | 698e763 | 2016-04-13 21:02:22 -0700 | [diff] [blame] | 932 | updateDockSide(); |
| 933 | mHandle.animate() |
Jorim Jaggi | 7b45839 | 2016-04-20 16:42:06 -0700 | [diff] [blame] | 934 | .setInterpolator(IME_ADJUST_INTERPOLATOR) |
Jorim Jaggi | 698e763 | 2016-04-13 21:02:22 -0700 | [diff] [blame] | 935 | .setDuration(animDuration) |
| 936 | .alpha(adjustedForIme ? 0f : 1f) |
| 937 | .start(); |
| 938 | if (mDockSide == WindowManager.DOCKED_TOP) { |
| 939 | mBackground.setPivotY(0); |
| 940 | mBackground.animate() |
Jorim Jaggi | 7b45839 | 2016-04-20 16:42:06 -0700 | [diff] [blame] | 941 | .scaleY(adjustedForIme ? ADJUSTED_FOR_IME_SCALE : 1f); |
Jorim Jaggi | 698e763 | 2016-04-13 21:02:22 -0700 | [diff] [blame] | 942 | } |
| 943 | if (!adjustedForIme) { |
| 944 | mBackground.animate().withEndAction(mResetBackgroundRunnable); |
| 945 | } |
| 946 | mBackground.animate() |
Jorim Jaggi | 7b45839 | 2016-04-20 16:42:06 -0700 | [diff] [blame] | 947 | .setInterpolator(IME_ADJUST_INTERPOLATOR) |
Jorim Jaggi | 698e763 | 2016-04-13 21:02:22 -0700 | [diff] [blame] | 948 | .setDuration(animDuration) |
| 949 | .start(); |
| 950 | mAdjustedForIme = adjustedForIme; |
| 951 | } |
| 952 | |
Matthew Ng | 597bcbb | 2017-09-07 17:17:38 -0700 | [diff] [blame] | 953 | private void saveSnapTargetBeforeMinimized(SnapTarget target) { |
| 954 | mSnapTargetBeforeMinimized = target; |
| 955 | mState.mRatioPositionBeforeMinimized = (float) target.position / |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 956 | (isHorizontalDivision() ? mSplitLayout.mDisplayLayout.height() |
| 957 | : mSplitLayout.mDisplayLayout.width()); |
Matthew Ng | ca3168b | 2017-05-24 16:40:31 -0700 | [diff] [blame] | 958 | } |
| 959 | |
Jorim Jaggi | e661f40 | 2016-03-25 19:11:35 -0700 | [diff] [blame] | 960 | private void resetBackground() { |
| 961 | mBackground.setPivotX(mBackground.getWidth() / 2); |
| 962 | mBackground.setPivotY(mBackground.getHeight() / 2); |
| 963 | mBackground.setScaleX(1f); |
| 964 | mBackground.setScaleY(1f); |
Jorim Jaggi | 2917dc4 | 2016-04-11 11:39:13 -0700 | [diff] [blame] | 965 | mMinimizedShadow.setAlpha(0f); |
Jorim Jaggi | e661f40 | 2016-03-25 19:11:35 -0700 | [diff] [blame] | 966 | } |
| 967 | |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 968 | @Override |
| 969 | protected void onConfigurationChanged(Configuration newConfig) { |
| 970 | super.onConfigurationChanged(newConfig); |
Matthew Ng | 62c7846 | 2018-04-09 14:43:21 -0700 | [diff] [blame] | 971 | } |
| 972 | |
| 973 | private void repositionSnapTargetBeforeMinimized() { |
| 974 | int position = (int) (mState.mRatioPositionBeforeMinimized * |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 975 | (isHorizontalDivision() ? mSplitLayout.mDisplayLayout.height() |
| 976 | : mSplitLayout.mDisplayLayout.width())); |
Matthew Ng | 62c7846 | 2018-04-09 14:43:21 -0700 | [diff] [blame] | 977 | |
| 978 | // Set the snap target before minimized but do not save until divider is attached and not |
| 979 | // minimized because it does not know its minimized state yet. |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 980 | mSnapTargetBeforeMinimized = |
| 981 | mSplitLayout.getSnapAlgorithm().calculateNonDismissingSnapTarget(position); |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 982 | } |
| 983 | |
| 984 | private int calculatePosition(int touchX, int touchY) { |
| 985 | return isHorizontalDivision() ? calculateYPosition(touchY) : calculateXPosition(touchX); |
| 986 | } |
| 987 | |
Jorim Jaggi | dd98d41 | 2015-11-18 15:57:38 -0800 | [diff] [blame] | 988 | public boolean isHorizontalDivision() { |
| 989 | return getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 990 | } |
| 991 | |
| 992 | private int calculateXPosition(int touchX) { |
| 993 | return mStartPosition + touchX - mStartX; |
| 994 | } |
| 995 | |
| 996 | private int calculateYPosition(int touchY) { |
| 997 | return mStartPosition + touchY - mStartY; |
| 998 | } |
| 999 | |
Jorim Jaggi | dc249c4 | 2015-12-15 14:57:31 -0800 | [diff] [blame] | 1000 | private void alignTopLeft(Rect containingRect, Rect rect) { |
| 1001 | int width = rect.width(); |
| 1002 | int height = rect.height(); |
| 1003 | rect.set(containingRect.left, containingRect.top, |
| 1004 | containingRect.left + width, containingRect.top + height); |
| 1005 | } |
| 1006 | |
| 1007 | private void alignBottomRight(Rect containingRect, Rect rect) { |
| 1008 | int width = rect.width(); |
| 1009 | int height = rect.height(); |
| 1010 | rect.set(containingRect.right - width, containingRect.bottom - height, |
| 1011 | containingRect.right, containingRect.bottom); |
| 1012 | } |
| 1013 | |
Jorim Jaggi | 737af72 | 2015-12-31 10:42:27 +0100 | [diff] [blame] | 1014 | public void calculateBoundsForPosition(int position, int dockSide, Rect outRect) { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1015 | DockedDividerUtils.calculateBoundsForPosition(position, dockSide, outRect, |
| 1016 | mSplitLayout.mDisplayLayout.width(), mSplitLayout.mDisplayLayout.height(), |
| 1017 | mDividerSize); |
Jorim Jaggi | 737af72 | 2015-12-31 10:42:27 +0100 | [diff] [blame] | 1018 | } |
| 1019 | |
Evan Rosky | 3613854 | 2020-05-01 18:02:11 -0700 | [diff] [blame] | 1020 | private void resizeStackSurfaces(SnapTarget taskSnapTarget, Transaction t) { |
| 1021 | resizeStackSurfaces(taskSnapTarget.position, taskSnapTarget.position, taskSnapTarget, t); |
Matthew Ng | 597bcbb | 2017-09-07 17:17:38 -0700 | [diff] [blame] | 1022 | } |
| 1023 | |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1024 | void resizeSplitSurfaces(Transaction t, Rect dockedRect, Rect otherRect) { |
| 1025 | resizeSplitSurfaces(t, dockedRect, null, otherRect, null); |
| 1026 | } |
| 1027 | |
| 1028 | private void resizeSplitSurfaces(Transaction t, Rect dockedRect, Rect dockedTaskRect, |
| 1029 | Rect otherRect, Rect otherTaskRect) { |
| 1030 | dockedTaskRect = dockedTaskRect == null ? dockedRect : dockedTaskRect; |
| 1031 | otherTaskRect = otherTaskRect == null ? otherRect : otherTaskRect; |
| 1032 | |
Tony Huang | 0bbb7ef | 2020-03-24 18:24:54 +0800 | [diff] [blame] | 1033 | mDividerPositionX = mSplitLayout.getPrimarySplitSide() == DOCKED_RIGHT |
| 1034 | ? otherRect.right : dockedRect.right; |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1035 | mDividerPositionY = dockedRect.bottom; |
| 1036 | |
Evan Rosky | fdc71c4 | 2020-03-13 18:23:08 -0700 | [diff] [blame] | 1037 | if (DEBUG) { |
| 1038 | Slog.d(TAG, "Resizing split surfaces: " + dockedRect + " " + dockedTaskRect |
| 1039 | + " " + otherRect + " " + otherTaskRect); |
| 1040 | } |
| 1041 | |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1042 | t.setPosition(mTiles.mPrimarySurface, dockedTaskRect.left, dockedTaskRect.top); |
| 1043 | Rect crop = new Rect(dockedRect); |
| 1044 | crop.offsetTo(-Math.min(dockedTaskRect.left - dockedRect.left, 0), |
| 1045 | -Math.min(dockedTaskRect.top - dockedRect.top, 0)); |
| 1046 | t.setWindowCrop(mTiles.mPrimarySurface, crop); |
| 1047 | t.setPosition(mTiles.mSecondarySurface, otherTaskRect.left, otherTaskRect.top); |
| 1048 | crop.set(otherRect); |
| 1049 | crop.offsetTo(-(otherTaskRect.left - otherRect.left), |
| 1050 | -(otherTaskRect.top - otherRect.top)); |
| 1051 | t.setWindowCrop(mTiles.mSecondarySurface, crop); |
| 1052 | final SurfaceControl dividerCtrl = getWindowSurfaceControl(); |
| 1053 | if (dividerCtrl != null) { |
| 1054 | if (isHorizontalDivision()) { |
| 1055 | t.setPosition(dividerCtrl, 0, mDividerPositionY - mDividerInsets); |
| 1056 | } else { |
| 1057 | t.setPosition(dividerCtrl, mDividerPositionX - mDividerInsets, 0); |
| 1058 | } |
| 1059 | } |
Evan Rosky | 0f4db1b | 2020-04-28 16:20:00 -0700 | [diff] [blame] | 1060 | if (getViewRootImpl() != null) { |
| 1061 | mHandler.removeCallbacks(mUpdateEmbeddedMatrix); |
| 1062 | mHandler.post(mUpdateEmbeddedMatrix); |
| 1063 | } |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1064 | } |
| 1065 | |
| 1066 | void setResizeDimLayer(Transaction t, boolean primary, float alpha) { |
| 1067 | SurfaceControl dim = primary ? mTiles.mPrimaryDim : mTiles.mSecondaryDim; |
Evan Rosky | e5fb45a | 2020-03-09 10:51:27 -0700 | [diff] [blame] | 1068 | if (alpha <= 0.001f) { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1069 | t.hide(dim); |
| 1070 | } else { |
| 1071 | t.setAlpha(dim, alpha); |
| 1072 | t.show(dim); |
| 1073 | } |
| 1074 | } |
| 1075 | |
Evan Rosky | 3613854 | 2020-05-01 18:02:11 -0700 | [diff] [blame] | 1076 | void resizeStackSurfaces(int position, int taskPosition, SnapTarget taskSnapTarget, |
| 1077 | Transaction transaction) { |
Wale Ogunwale | 15ba151 | 2017-06-06 08:31:17 -0700 | [diff] [blame] | 1078 | if (mRemoved) { |
| 1079 | // This divider view has been removed so shouldn't have any additional influence. |
| 1080 | return; |
| 1081 | } |
Jorim Jaggi | dc249c4 | 2015-12-15 14:57:31 -0800 | [diff] [blame] | 1082 | calculateBoundsForPosition(position, mDockSide, mDockedRect); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1083 | calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide), |
| 1084 | mOtherRect); |
Jorim Jaggi | dc249c4 | 2015-12-15 14:57:31 -0800 | [diff] [blame] | 1085 | |
Jorim Jaggi | e370e15 | 2016-04-15 14:13:33 -0700 | [diff] [blame] | 1086 | if (mDockedRect.equals(mLastResizeRect) && !mEntranceAnimationRunning) { |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 1087 | return; |
| 1088 | } |
Jorim Jaggi | c97ba49 | 2015-11-06 22:00:18 +0100 | [diff] [blame] | 1089 | |
| 1090 | // Make sure shadows are updated |
Jorim Jaggi | e161f08 | 2016-02-05 14:26:16 -0800 | [diff] [blame] | 1091 | if (mBackground.getZ() > 0f) { |
| 1092 | mBackground.invalidate(); |
| 1093 | } |
Jorim Jaggi | c97ba49 | 2015-11-06 22:00:18 +0100 | [diff] [blame] | 1094 | |
Evan Rosky | 3613854 | 2020-05-01 18:02:11 -0700 | [diff] [blame] | 1095 | final boolean ownTransaction = transaction == null; |
| 1096 | final Transaction t = ownTransaction ? mTiles.getTransaction() : transaction; |
Jorim Jaggi | dc249c4 | 2015-12-15 14:57:31 -0800 | [diff] [blame] | 1097 | mLastResizeRect.set(mDockedRect); |
Evan Rosky | 89c285e | 2020-06-17 21:21:53 -0700 | [diff] [blame] | 1098 | if (mIsInMinimizeInteraction) { |
Matthew Ng | 597bcbb | 2017-09-07 17:17:38 -0700 | [diff] [blame] | 1099 | calculateBoundsForPosition(mSnapTargetBeforeMinimized.position, mDockSide, |
| 1100 | mDockedTaskRect); |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 1101 | calculateBoundsForPosition(mSnapTargetBeforeMinimized.position, |
| 1102 | DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect); |
Matthew Ng | 62c7846 | 2018-04-09 14:43:21 -0700 | [diff] [blame] | 1103 | |
| 1104 | // Move a right-docked-app to line up with the divider while dragging it |
| 1105 | if (mDockSide == DOCKED_RIGHT) { |
Sunny Goyal | 2148254 | 2020-05-05 16:34:17 -0700 | [diff] [blame] | 1106 | mDockedTaskRect.offset(Math.max(position, -mDividerSize) |
Matthew Ng | 62c7846 | 2018-04-09 14:43:21 -0700 | [diff] [blame] | 1107 | - mDockedTaskRect.left + mDividerSize, 0); |
| 1108 | } |
Evan Rosky | 89c285e | 2020-06-17 21:21:53 -0700 | [diff] [blame] | 1109 | resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect); |
Evan Rosky | 3613854 | 2020-05-01 18:02:11 -0700 | [diff] [blame] | 1110 | if (ownTransaction) { |
| 1111 | t.apply(); |
| 1112 | mTiles.releaseTransaction(t); |
| 1113 | } |
Matthew Ng | e15352e | 2016-12-20 15:36:29 -0800 | [diff] [blame] | 1114 | return; |
| 1115 | } |
| 1116 | |
Jorim Jaggi | 899327f | 2016-02-25 20:44:18 -0500 | [diff] [blame] | 1117 | if (mEntranceAnimationRunning && taskPosition != TASK_POSITION_SAME) { |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 1118 | calculateBoundsForPosition(taskPosition, mDockSide, mDockedTaskRect); |
Matthew Ng | 62c7846 | 2018-04-09 14:43:21 -0700 | [diff] [blame] | 1119 | |
| 1120 | // Move a docked app if from the right in position with the divider up to insets |
| 1121 | if (mDockSide == DOCKED_RIGHT) { |
Sunny Goyal | 2148254 | 2020-05-05 16:34:17 -0700 | [diff] [blame] | 1122 | mDockedTaskRect.offset(Math.max(position, -mDividerSize) |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 1123 | - mDockedTaskRect.left + mDividerSize, 0); |
Matthew Ng | 62c7846 | 2018-04-09 14:43:21 -0700 | [diff] [blame] | 1124 | } |
Jorim Jaggi | 899327f | 2016-02-25 20:44:18 -0500 | [diff] [blame] | 1125 | calculateBoundsForPosition(taskPosition, DockedDividerUtils.invertDockSide(mDockSide), |
| 1126 | mOtherTaskRect); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1127 | resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect); |
Jorim Jaggi | 47ee9ad | 2016-04-11 21:51:11 -0700 | [diff] [blame] | 1128 | } else if (mExitAnimationRunning && taskPosition != TASK_POSITION_SAME) { |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 1129 | calculateBoundsForPosition(taskPosition, mDockSide, mDockedTaskRect); |
| 1130 | mDockedInsetRect.set(mDockedTaskRect); |
Jorim Jaggi | 47ee9ad | 2016-04-11 21:51:11 -0700 | [diff] [blame] | 1131 | calculateBoundsForPosition(mExitStartPosition, |
| 1132 | DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect); |
Jorim Jaggi | 545c5c2 | 2016-04-12 18:59:45 -0700 | [diff] [blame] | 1133 | mOtherInsetRect.set(mOtherTaskRect); |
| 1134 | applyExitAnimationParallax(mOtherTaskRect, position); |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 1135 | |
| 1136 | // Move a right-docked-app to line up with the divider while dragging it |
| 1137 | if (mDockSide == DOCKED_RIGHT) { |
Sunny Goyal | 2148254 | 2020-05-05 16:34:17 -0700 | [diff] [blame] | 1138 | mDockedTaskRect.offset(position + mDividerSize, 0); |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 1139 | } |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1140 | resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect); |
Jorim Jaggi | 899327f | 2016-02-25 20:44:18 -0500 | [diff] [blame] | 1141 | } else if (taskPosition != TASK_POSITION_SAME) { |
Winson | 3e87474 | 2016-01-07 10:08:17 -0800 | [diff] [blame] | 1142 | calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide), |
| 1143 | mOtherRect); |
| 1144 | int dockSideInverted = DockedDividerUtils.invertDockSide(mDockSide); |
Jorim Jaggi | e435e98 | 2015-12-30 13:54:32 +0100 | [diff] [blame] | 1145 | int taskPositionDocked = |
| 1146 | restrictDismissingTaskPosition(taskPosition, mDockSide, taskSnapTarget); |
| 1147 | int taskPositionOther = |
| 1148 | restrictDismissingTaskPosition(taskPosition, dockSideInverted, taskSnapTarget); |
| 1149 | calculateBoundsForPosition(taskPositionDocked, mDockSide, mDockedTaskRect); |
| 1150 | calculateBoundsForPosition(taskPositionOther, dockSideInverted, mOtherTaskRect); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1151 | mTmpRect.set(0, 0, mSplitLayout.mDisplayLayout.width(), |
| 1152 | mSplitLayout.mDisplayLayout.height()); |
Jorim Jaggi | dc249c4 | 2015-12-15 14:57:31 -0800 | [diff] [blame] | 1153 | alignTopLeft(mDockedRect, mDockedTaskRect); |
| 1154 | alignTopLeft(mOtherRect, mOtherTaskRect); |
| 1155 | mDockedInsetRect.set(mDockedTaskRect); |
| 1156 | mOtherInsetRect.set(mOtherTaskRect); |
Jorim Jaggi | e435e98 | 2015-12-30 13:54:32 +0100 | [diff] [blame] | 1157 | if (dockSideTopLeft(mDockSide)) { |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 1158 | alignTopLeft(mTmpRect, mDockedInsetRect); |
| 1159 | alignBottomRight(mTmpRect, mOtherInsetRect); |
Jorim Jaggi | dc249c4 | 2015-12-15 14:57:31 -0800 | [diff] [blame] | 1160 | } else { |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 1161 | alignBottomRight(mTmpRect, mDockedInsetRect); |
| 1162 | alignTopLeft(mTmpRect, mOtherInsetRect); |
Jorim Jaggi | dc249c4 | 2015-12-15 14:57:31 -0800 | [diff] [blame] | 1163 | } |
Jorim Jaggi | e435e98 | 2015-12-30 13:54:32 +0100 | [diff] [blame] | 1164 | applyDismissingParallax(mDockedTaskRect, mDockSide, taskSnapTarget, position, |
| 1165 | taskPositionDocked); |
| 1166 | applyDismissingParallax(mOtherTaskRect, dockSideInverted, taskSnapTarget, position, |
| 1167 | taskPositionOther); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1168 | resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect); |
Jorim Jaggi | dc249c4 | 2015-12-15 14:57:31 -0800 | [diff] [blame] | 1169 | } else { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1170 | resizeSplitSurfaces(t, mDockedRect, null, mOtherRect, null); |
Jorim Jaggi | dc249c4 | 2015-12-15 14:57:31 -0800 | [diff] [blame] | 1171 | } |
Matthew Ng | e15352e | 2016-12-20 15:36:29 -0800 | [diff] [blame] | 1172 | SnapTarget closestDismissTarget = getSnapAlgorithm().getClosestDismissTarget(position); |
Jorim Jaggi | 1b12ef5 | 2016-01-29 16:49:55 -0800 | [diff] [blame] | 1173 | float dimFraction = getDimFraction(position, closestDismissTarget); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1174 | setResizeDimLayer(t, isDismissTargetPrimary(closestDismissTarget), dimFraction); |
Evan Rosky | 3613854 | 2020-05-01 18:02:11 -0700 | [diff] [blame] | 1175 | if (ownTransaction) { |
| 1176 | t.apply(); |
| 1177 | mTiles.releaseTransaction(t); |
| 1178 | } |
Jorim Jaggi | 1b12ef5 | 2016-01-29 16:49:55 -0800 | [diff] [blame] | 1179 | } |
| 1180 | |
Jorim Jaggi | 545c5c2 | 2016-04-12 18:59:45 -0700 | [diff] [blame] | 1181 | private void applyExitAnimationParallax(Rect taskRect, int position) { |
| 1182 | if (mDockSide == WindowManager.DOCKED_TOP) { |
| 1183 | taskRect.offset(0, (int) ((position - mExitStartPosition) * 0.25f)); |
| 1184 | } else if (mDockSide == WindowManager.DOCKED_LEFT) { |
| 1185 | taskRect.offset((int) ((position - mExitStartPosition) * 0.25f), 0); |
| 1186 | } else if (mDockSide == WindowManager.DOCKED_RIGHT) { |
| 1187 | taskRect.offset((int) ((mExitStartPosition - position) * 0.25f), 0); |
| 1188 | } |
| 1189 | } |
| 1190 | |
Jorim Jaggi | 1b12ef5 | 2016-01-29 16:49:55 -0800 | [diff] [blame] | 1191 | private float getDimFraction(int position, SnapTarget dismissTarget) { |
Jorim Jaggi | 899327f | 2016-02-25 20:44:18 -0500 | [diff] [blame] | 1192 | if (mEntranceAnimationRunning) { |
| 1193 | return 0f; |
| 1194 | } |
Matthew Ng | e15352e | 2016-12-20 15:36:29 -0800 | [diff] [blame] | 1195 | float fraction = getSnapAlgorithm().calculateDismissingFraction(position); |
Jorim Jaggi | 8f8155b | 2016-01-25 19:45:42 -0800 | [diff] [blame] | 1196 | fraction = Math.max(0, Math.min(fraction, 1f)); |
| 1197 | fraction = DIM_INTERPOLATOR.getInterpolation(fraction); |
Jorim Jaggi | 1b12ef5 | 2016-01-29 16:49:55 -0800 | [diff] [blame] | 1198 | return fraction; |
| 1199 | } |
| 1200 | |
| 1201 | /** |
Jorim Jaggi | e435e98 | 2015-12-30 13:54:32 +0100 | [diff] [blame] | 1202 | * When the snap target is dismissing one side, make sure that the dismissing side doesn't get |
| 1203 | * 0 size. |
| 1204 | */ |
| 1205 | private int restrictDismissingTaskPosition(int taskPosition, int dockSide, |
| 1206 | SnapTarget snapTarget) { |
| 1207 | if (snapTarget.flag == SnapTarget.FLAG_DISMISS_START && dockSideTopLeft(dockSide)) { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1208 | return Math.max(mSplitLayout.getSnapAlgorithm().getFirstSplitTarget().position, |
| 1209 | mStartPosition); |
Jorim Jaggi | e435e98 | 2015-12-30 13:54:32 +0100 | [diff] [blame] | 1210 | } else if (snapTarget.flag == SnapTarget.FLAG_DISMISS_END |
| 1211 | && dockSideBottomRight(dockSide)) { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1212 | return Math.min(mSplitLayout.getSnapAlgorithm().getLastSplitTarget().position, |
| 1213 | mStartPosition); |
Jorim Jaggi | e435e98 | 2015-12-30 13:54:32 +0100 | [diff] [blame] | 1214 | } else { |
| 1215 | return taskPosition; |
| 1216 | } |
| 1217 | } |
| 1218 | |
| 1219 | /** |
| 1220 | * Applies a parallax to the task when dismissing. |
| 1221 | */ |
| 1222 | private void applyDismissingParallax(Rect taskRect, int dockSide, SnapTarget snapTarget, |
| 1223 | int position, int taskPosition) { |
| 1224 | float fraction = Math.min(1, Math.max(0, |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1225 | mSplitLayout.getSnapAlgorithm().calculateDismissingFraction(position))); |
Jorim Jaggi | e435e98 | 2015-12-30 13:54:32 +0100 | [diff] [blame] | 1226 | SnapTarget dismissTarget = null; |
| 1227 | SnapTarget splitTarget = null; |
Jorim Jaggi | 8dccd23 | 2016-03-25 18:10:14 -0700 | [diff] [blame] | 1228 | int start = 0; |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1229 | if (position <= mSplitLayout.getSnapAlgorithm().getLastSplitTarget().position |
Jorim Jaggi | e435e98 | 2015-12-30 13:54:32 +0100 | [diff] [blame] | 1230 | && dockSideTopLeft(dockSide)) { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1231 | dismissTarget = mSplitLayout.getSnapAlgorithm().getDismissStartTarget(); |
| 1232 | splitTarget = mSplitLayout.getSnapAlgorithm().getFirstSplitTarget(); |
Jorim Jaggi | 8dccd23 | 2016-03-25 18:10:14 -0700 | [diff] [blame] | 1233 | start = taskPosition; |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1234 | } else if (position >= mSplitLayout.getSnapAlgorithm().getLastSplitTarget().position |
Jorim Jaggi | e435e98 | 2015-12-30 13:54:32 +0100 | [diff] [blame] | 1235 | && dockSideBottomRight(dockSide)) { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1236 | dismissTarget = mSplitLayout.getSnapAlgorithm().getDismissEndTarget(); |
| 1237 | splitTarget = mSplitLayout.getSnapAlgorithm().getLastSplitTarget(); |
Jorim Jaggi | 8dccd23 | 2016-03-25 18:10:14 -0700 | [diff] [blame] | 1238 | start = splitTarget.position; |
Jorim Jaggi | e435e98 | 2015-12-30 13:54:32 +0100 | [diff] [blame] | 1239 | } |
| 1240 | if (dismissTarget != null && fraction > 0f |
| 1241 | && isDismissing(splitTarget, position, dockSide)) { |
Jorim Jaggi | 1b12ef5 | 2016-01-29 16:49:55 -0800 | [diff] [blame] | 1242 | fraction = calculateParallaxDismissingFraction(fraction, dockSide); |
Jorim Jaggi | 8dccd23 | 2016-03-25 18:10:14 -0700 | [diff] [blame] | 1243 | int offsetPosition = (int) (start + |
Jorim Jaggi | e435e98 | 2015-12-30 13:54:32 +0100 | [diff] [blame] | 1244 | fraction * (dismissTarget.position - splitTarget.position)); |
| 1245 | int width = taskRect.width(); |
| 1246 | int height = taskRect.height(); |
| 1247 | switch (dockSide) { |
| 1248 | case WindowManager.DOCKED_LEFT: |
| 1249 | taskRect.left = offsetPosition - width; |
| 1250 | taskRect.right = offsetPosition; |
| 1251 | break; |
| 1252 | case WindowManager.DOCKED_RIGHT: |
| 1253 | taskRect.left = offsetPosition + mDividerSize; |
| 1254 | taskRect.right = offsetPosition + width + mDividerSize; |
| 1255 | break; |
| 1256 | case WindowManager.DOCKED_TOP: |
| 1257 | taskRect.top = offsetPosition - height; |
| 1258 | taskRect.bottom = offsetPosition; |
| 1259 | break; |
| 1260 | case WindowManager.DOCKED_BOTTOM: |
| 1261 | taskRect.top = offsetPosition + mDividerSize; |
| 1262 | taskRect.bottom = offsetPosition + height + mDividerSize; |
| 1263 | break; |
| 1264 | } |
| 1265 | } |
| 1266 | } |
| 1267 | |
| 1268 | /** |
| 1269 | * @return for a specified {@code fraction}, this returns an adjusted value that simulates a |
| 1270 | * slowing down parallax effect |
| 1271 | */ |
Jorim Jaggi | 1b12ef5 | 2016-01-29 16:49:55 -0800 | [diff] [blame] | 1272 | private static float calculateParallaxDismissingFraction(float fraction, int dockSide) { |
| 1273 | float result = SLOWDOWN_INTERPOLATOR.getInterpolation(fraction) / 3.5f; |
| 1274 | |
| 1275 | // Less parallax at the top, just because. |
| 1276 | if (dockSide == WindowManager.DOCKED_TOP) { |
| 1277 | result /= 2f; |
| 1278 | } |
| 1279 | return result; |
Jorim Jaggi | e435e98 | 2015-12-30 13:54:32 +0100 | [diff] [blame] | 1280 | } |
| 1281 | |
| 1282 | private static boolean isDismissing(SnapTarget snapTarget, int position, int dockSide) { |
| 1283 | if (dockSide == WindowManager.DOCKED_TOP || dockSide == WindowManager.DOCKED_LEFT) { |
| 1284 | return position < snapTarget.position; |
| 1285 | } else { |
| 1286 | return position > snapTarget.position; |
| 1287 | } |
| 1288 | } |
| 1289 | |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1290 | private boolean isDismissTargetPrimary(SnapTarget dismissTarget) { |
| 1291 | return (dismissTarget.flag == SnapTarget.FLAG_DISMISS_START && dockSideTopLeft(mDockSide)) |
Jorim Jaggi | 8dccd23 | 2016-03-25 18:10:14 -0700 | [diff] [blame] | 1292 | || (dismissTarget.flag == SnapTarget.FLAG_DISMISS_END |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1293 | && dockSideBottomRight(mDockSide)); |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 1294 | } |
| 1295 | |
Jorim Jaggi | e435e98 | 2015-12-30 13:54:32 +0100 | [diff] [blame] | 1296 | /** |
| 1297 | * @return true if and only if {@code dockSide} is top or left |
| 1298 | */ |
| 1299 | private static boolean dockSideTopLeft(int dockSide) { |
| 1300 | return dockSide == WindowManager.DOCKED_TOP || dockSide == WindowManager.DOCKED_LEFT; |
| 1301 | } |
| 1302 | |
| 1303 | /** |
| 1304 | * @return true if and only if {@code dockSide} is bottom or right |
| 1305 | */ |
| 1306 | private static boolean dockSideBottomRight(int dockSide) { |
| 1307 | return dockSide == WindowManager.DOCKED_BOTTOM || dockSide == WindowManager.DOCKED_RIGHT; |
| 1308 | } |
| 1309 | |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 1310 | @Override |
| 1311 | public void onComputeInternalInsets(InternalInsetsInfo inoutInfo) { |
| 1312 | inoutInfo.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_REGION); |
| 1313 | inoutInfo.touchableRegion.set(mHandle.getLeft(), mHandle.getTop(), mHandle.getRight(), |
| 1314 | mHandle.getBottom()); |
| 1315 | inoutInfo.touchableRegion.op(mBackground.getLeft(), mBackground.getTop(), |
| 1316 | mBackground.getRight(), mBackground.getBottom(), Op.UNION); |
| 1317 | } |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 1318 | |
Jorim Jaggi | db21bbd | 2016-04-18 15:32:07 -0700 | [diff] [blame] | 1319 | /** |
| 1320 | * Checks whether recents will grow when invoked. This happens in multi-window when recents is |
| 1321 | * very small. When invoking recents, we shrink the docked stack so recents has more space. |
| 1322 | * |
| 1323 | * @return the position of the divider when recents grows, or |
| 1324 | * {@link #INVALID_RECENTS_GROW_TARGET} if recents won't grow |
| 1325 | */ |
| 1326 | public int growsRecents() { |
| 1327 | boolean result = mGrowRecents |
Jorim Jaggi | ddb449e | 2017-05-12 16:32:58 +0200 | [diff] [blame] | 1328 | && mDockSide == WindowManager.DOCKED_TOP |
Jorim Jaggi | db21bbd | 2016-04-18 15:32:07 -0700 | [diff] [blame] | 1329 | && getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position; |
| 1330 | if (result) { |
| 1331 | return getSnapAlgorithm().getMiddleTarget().position; |
| 1332 | } else { |
| 1333 | return INVALID_RECENTS_GROW_TARGET; |
| 1334 | } |
| 1335 | } |
| 1336 | |
Winson Chung | 67f5c8b | 2018-09-24 12:09:19 -0700 | [diff] [blame] | 1337 | void onRecentsActivityStarting() { |
Jorim Jaggi | ef496ea | 2017-05-13 23:16:44 +0200 | [diff] [blame] | 1338 | if (mGrowRecents && mDockSide == WindowManager.DOCKED_TOP |
Qiushi.Han | 9170ca8 | 2016-10-10 13:31:48 +0800 | [diff] [blame] | 1339 | && getSnapAlgorithm().getMiddleTarget() != getSnapAlgorithm().getLastSplitTarget() |
Jorim Jaggi | cdb06ca | 2016-01-25 19:15:12 -0800 | [diff] [blame] | 1340 | && getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position) { |
Jorim Jaggi | a6c05d5 | 2016-05-27 00:31:21 -0700 | [diff] [blame] | 1341 | mState.growAfterRecentsDrawn = true; |
Jorim Jaggi | cdb06ca | 2016-01-25 19:15:12 -0800 | [diff] [blame] | 1342 | startDragging(false /* animate */, false /* touching */); |
| 1343 | } |
| 1344 | } |
| 1345 | |
Winson Chung | 67f5c8b | 2018-09-24 12:09:19 -0700 | [diff] [blame] | 1346 | void onDockedFirstAnimationFrame() { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1347 | saveSnapTargetBeforeMinimized(mSplitLayout.getSnapAlgorithm().getMiddleTarget()); |
Winson Chung | 37b2024 | 2017-09-26 11:51:08 -0700 | [diff] [blame] | 1348 | } |
| 1349 | |
Winson Chung | 67f5c8b | 2018-09-24 12:09:19 -0700 | [diff] [blame] | 1350 | void onDockedTopTask() { |
| 1351 | mState.growAfterRecentsDrawn = false; |
| 1352 | mState.animateAfterRecentsDrawn = true; |
| 1353 | startDragging(false /* animate */, false /* touching */); |
Jorim Jaggi | 899327f | 2016-02-25 20:44:18 -0500 | [diff] [blame] | 1354 | updateDockSide(); |
Jorim Jaggi | 899327f | 2016-02-25 20:44:18 -0500 | [diff] [blame] | 1355 | mEntranceAnimationRunning = true; |
Jorim Jaggi | e525a35 | 2016-05-27 16:56:55 -0700 | [diff] [blame] | 1356 | |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1357 | resizeStackSurfaces(calculatePositionForInsetBounds(), |
| 1358 | mSplitLayout.getSnapAlgorithm().getMiddleTarget().position, |
Evan Rosky | 3613854 | 2020-05-01 18:02:11 -0700 | [diff] [blame] | 1359 | mSplitLayout.getSnapAlgorithm().getMiddleTarget(), |
| 1360 | null /* transaction */); |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 1361 | } |
| 1362 | |
Winson Chung | 67f5c8b | 2018-09-24 12:09:19 -0700 | [diff] [blame] | 1363 | void onRecentsDrawn() { |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 1364 | updateDockSide(); |
| 1365 | final int position = calculatePositionForInsetBounds(); |
Jorim Jaggi | a6c05d5 | 2016-05-27 00:31:21 -0700 | [diff] [blame] | 1366 | if (mState.animateAfterRecentsDrawn) { |
| 1367 | mState.animateAfterRecentsDrawn = false; |
Jorim Jaggi | 545c5c2 | 2016-04-12 18:59:45 -0700 | [diff] [blame] | 1368 | |
Jorim Jaggi | a6c05d5 | 2016-05-27 00:31:21 -0700 | [diff] [blame] | 1369 | mHandler.post(() -> { |
Jorim Jaggi | c5887ea | 2016-05-13 18:21:48 -0700 | [diff] [blame] | 1370 | // Delay switching resizing mode because this might cause jank in recents animation |
| 1371 | // that's longer than this animation. |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 1372 | stopDragging(position, getSnapAlgorithm().getMiddleTarget(), |
Jorim Jaggi | c5887ea | 2016-05-13 18:21:48 -0700 | [diff] [blame] | 1373 | mLongPressEntraceAnimDuration, Interpolators.FAST_OUT_SLOW_IN, |
| 1374 | 200 /* endDelay */); |
| 1375 | }); |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 1376 | } |
Jorim Jaggi | a6c05d5 | 2016-05-27 00:31:21 -0700 | [diff] [blame] | 1377 | if (mState.growAfterRecentsDrawn) { |
| 1378 | mState.growAfterRecentsDrawn = false; |
Jorim Jaggi | 9511b0f | 2016-01-29 19:12:44 -0800 | [diff] [blame] | 1379 | updateDockSide(); |
Winson Chung | 67f5c8b | 2018-09-24 12:09:19 -0700 | [diff] [blame] | 1380 | if (mCallback != null) { |
| 1381 | mCallback.growRecents(); |
| 1382 | } |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 1383 | stopDragging(position, getSnapAlgorithm().getMiddleTarget(), 336, |
Jorim Jaggi | 545c5c2 | 2016-04-12 18:59:45 -0700 | [diff] [blame] | 1384 | Interpolators.FAST_OUT_SLOW_IN); |
Jorim Jaggi | ea4a19f | 2016-02-03 21:31:27 -0800 | [diff] [blame] | 1385 | } |
| 1386 | } |
| 1387 | |
Winson Chung | 67f5c8b | 2018-09-24 12:09:19 -0700 | [diff] [blame] | 1388 | void onUndockingTask() { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1389 | int dockSide = mSplitLayout.getPrimarySplitSide(); |
Evan Rosky | 89c285e | 2020-06-17 21:21:53 -0700 | [diff] [blame] | 1390 | if (inSplitMode()) { |
Jorim Jaggi | ea4a19f | 2016-02-03 21:31:27 -0800 | [diff] [blame] | 1391 | startDragging(false /* animate */, false /* touching */); |
| 1392 | SnapTarget target = dockSideTopLeft(dockSide) |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1393 | ? mSplitLayout.getSnapAlgorithm().getDismissEndTarget() |
| 1394 | : mSplitLayout.getSnapAlgorithm().getDismissStartTarget(); |
Jorim Jaggi | ea4a19f | 2016-02-03 21:31:27 -0800 | [diff] [blame] | 1395 | |
| 1396 | // Don't start immediately - give a little bit time to settle the drag resize change. |
Jorim Jaggi | 47ee9ad | 2016-04-11 21:51:11 -0700 | [diff] [blame] | 1397 | mExitAnimationRunning = true; |
| 1398 | mExitStartPosition = getCurrentPosition(); |
| 1399 | stopDragging(mExitStartPosition, target, 336 /* duration */, 100 /* startDelay */, |
Jorim Jaggi | 545c5c2 | 2016-04-12 18:59:45 -0700 | [diff] [blame] | 1400 | 0 /* endDelay */, Interpolators.FAST_OUT_SLOW_IN); |
Jorim Jaggi | cdb06ca | 2016-01-25 19:15:12 -0800 | [diff] [blame] | 1401 | } |
Jorim Jaggi | 11cc01d | 2016-01-22 19:39:23 -0800 | [diff] [blame] | 1402 | } |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 1403 | |
| 1404 | private int calculatePositionForInsetBounds() { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 1405 | mSplitLayout.mDisplayLayout.getStableBounds(mTmpRect); |
Matthew Ng | 3030712 | 2018-04-13 11:36:34 -0700 | [diff] [blame] | 1406 | return DockedDividerUtils.calculatePositionForBounds(mTmpRect, mDockSide, mDividerSize); |
| 1407 | } |
Jorim Jaggi | 1fcbab6 | 2015-11-04 16:39:50 +0100 | [diff] [blame] | 1408 | } |