blob: ce1795aa1112286653b81884b95cd00e54d84474 [file] [log] [blame]
Adam Cohena6d04922014-10-23 17:28:30 -07001package com.android.launcher3;
2
Sunny Goyaled2d2bc2018-04-19 12:34:43 -07003import static com.android.launcher3.util.SystemUiController.FLAG_DARK_NAV;
4import static com.android.launcher3.util.SystemUiController.UI_STATE_ROOT_VIEW;
5
Sunny Goyal93264612015-11-23 11:47:50 -08006import android.annotation.TargetApi;
7import android.app.ActivityManager;
Adam Cohena6d04922014-10-23 17:28:30 -07008import android.content.Context;
Sunny Goyal0abb36f2015-06-23 10:53:59 -07009import android.graphics.Canvas;
10import android.graphics.Color;
Sunny Goyal022b1822019-06-12 08:44:09 -070011import android.graphics.Insets;
Sunny Goyal0abb36f2015-06-23 10:53:59 -070012import android.graphics.Paint;
Adam Cohena6d04922014-10-23 17:28:30 -070013import android.graphics.Rect;
Tony Wickham12e8a342019-04-23 11:28:54 -070014import android.os.Build;
Adam Cohena6d04922014-10-23 17:28:30 -070015import android.util.AttributeSet;
Sunny Goyal93264612015-11-23 11:47:50 -080016import android.view.View;
Sunny Goyal4ffec482016-02-09 11:28:52 -080017import android.view.ViewDebug;
Sunny Goyal022b1822019-06-12 08:44:09 -070018import android.view.WindowInsets;
Adam Cohena6d04922014-10-23 17:28:30 -070019
Tony Wickham12e8a342019-04-23 11:28:54 -070020import java.util.Collections;
21import java.util.List;
22
Adam Cohena6d04922014-10-23 17:28:30 -070023public class LauncherRootView extends InsettableFrameLayout {
Sunny Goyal0abb36f2015-06-23 10:53:59 -070024
Sunny Goyal022b1822019-06-12 08:44:09 -070025 private final Rect mTempRect = new Rect();
26
Sunny Goyal07b69292018-01-08 14:19:34 -080027 private final Launcher mLauncher;
28
Sunny Goyal0abb36f2015-06-23 10:53:59 -070029 private final Paint mOpaquePaint;
Sunny Goyal9001b102018-05-07 11:09:13 -070030
Sunny Goyal4ffec482016-02-09 11:28:52 -080031 @ViewDebug.ExportedProperty(category = "launcher")
Sunny Goyal9001b102018-05-07 11:09:13 -070032 private final Rect mConsumedInsets = new Rect();
Sunny Goyal0abb36f2015-06-23 10:53:59 -070033
Sunny Goyal745df7c2019-04-03 15:25:00 -070034 @ViewDebug.ExportedProperty(category = "launcher")
Tony Wickham12e8a342019-04-23 11:28:54 -070035 private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT =
36 Collections.singletonList(new Rect());
37
Sunny Goyal93264612015-11-23 11:47:50 -080038 private View mAlignedView;
Sunny Goyal7185dd62018-03-14 17:51:49 -070039 private WindowStateListener mWindowStateListener;
Tony Wickham12e8a342019-04-23 11:28:54 -070040 @ViewDebug.ExportedProperty(category = "launcher")
41 private boolean mDisallowBackGesture;
Vinit Nayak9a846212019-09-05 11:47:12 -070042 @ViewDebug.ExportedProperty(category = "launcher")
43 private boolean mForceHideBackArrow;
Sunny Goyal93264612015-11-23 11:47:50 -080044
Adam Cohena6d04922014-10-23 17:28:30 -070045 public LauncherRootView(Context context, AttributeSet attrs) {
46 super(context, attrs);
Sunny Goyal0abb36f2015-06-23 10:53:59 -070047
48 mOpaquePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
49 mOpaquePaint.setColor(Color.BLACK);
50 mOpaquePaint.setStyle(Paint.Style.FILL);
Sunny Goyal07b69292018-01-08 14:19:34 -080051
52 mLauncher = Launcher.getLauncher(context);
Adam Cohena6d04922014-10-23 17:28:30 -070053 }
54
55 @Override
Sunny Goyal93264612015-11-23 11:47:50 -080056 protected void onFinishInflate() {
57 if (getChildCount() > 0) {
58 // LauncherRootView contains only one child, which should be aligned
59 // based on the horizontal insets.
60 mAlignedView = getChildAt(0);
61 }
62 super.onFinishInflate();
63 }
64
Sunny Goyal022b1822019-06-12 08:44:09 -070065 private void handleSystemWindowInsets(Rect insets) {
Sunny Goyal9001b102018-05-07 11:09:13 -070066 mConsumedInsets.setEmpty();
67 boolean drawInsetBar = false;
Sunny Goyal8c48d8b2019-01-25 15:10:18 -080068 if (mLauncher.isInMultiWindowMode()
Sunny Goyal9001b102018-05-07 11:09:13 -070069 && (insets.left > 0 || insets.right > 0 || insets.bottom > 0)) {
70 mConsumedInsets.left = insets.left;
71 mConsumedInsets.right = insets.right;
72 mConsumedInsets.bottom = insets.bottom;
Sunny Goyal022b1822019-06-12 08:44:09 -070073 insets.set(0, insets.top, 0, 0);
Sunny Goyal9001b102018-05-07 11:09:13 -070074 drawInsetBar = true;
75 } else if ((insets.right > 0 || insets.left > 0) &&
Sunny Goyal8c48d8b2019-01-25 15:10:18 -080076 getContext().getSystemService(ActivityManager.class).isLowRamDevice()) {
Sunny Goyal9001b102018-05-07 11:09:13 -070077 mConsumedInsets.left = insets.left;
78 mConsumedInsets.right = insets.right;
Sunny Goyal022b1822019-06-12 08:44:09 -070079 insets.set(0, insets.top, 0, insets.bottom);
Sunny Goyal9001b102018-05-07 11:09:13 -070080 drawInsetBar = true;
Sunny Goyal906c6b22017-08-18 00:35:52 -070081 }
Sunny Goyal9001b102018-05-07 11:09:13 -070082
Sunny Goyal07b69292018-01-08 14:19:34 -080083 mLauncher.getSystemUiController().updateUiState(
Sunny Goyal9001b102018-05-07 11:09:13 -070084 UI_STATE_ROOT_VIEW, drawInsetBar ? FLAG_DARK_NAV : 0);
Sunny Goyal93264612015-11-23 11:47:50 -080085
Sunny Goyal07b69292018-01-08 14:19:34 -080086 // Update device profile before notifying th children.
Sunny Goyalae6e3182019-04-30 12:04:37 -070087 mLauncher.updateInsets(insets);
Sunny Goyalce8809a2018-01-18 14:02:47 -080088 boolean resetState = !insets.equals(mInsets);
Sunny Goyal906c6b22017-08-18 00:35:52 -070089 setInsets(insets);
90
91 if (mAlignedView != null) {
Sunny Goyal9001b102018-05-07 11:09:13 -070092 // Apply margins on aligned view to handle consumed insets.
Sunny Goyal93264612015-11-23 11:47:50 -080093 MarginLayoutParams lp = (MarginLayoutParams) mAlignedView.getLayoutParams();
Sunny Goyal9001b102018-05-07 11:09:13 -070094 if (lp.leftMargin != mConsumedInsets.left || lp.rightMargin != mConsumedInsets.right ||
95 lp.bottomMargin != mConsumedInsets.bottom) {
96 lp.leftMargin = mConsumedInsets.left;
97 lp.rightMargin = mConsumedInsets.right;
98 lp.topMargin = mConsumedInsets.top;
99 lp.bottomMargin = mConsumedInsets.bottom;
Sunny Goyal93264612015-11-23 11:47:50 -0800100 mAlignedView.setLayoutParams(lp);
101 }
102 }
Sunny Goyalce8809a2018-01-18 14:02:47 -0800103 if (resetState) {
Sunny Goyaled2d2bc2018-04-19 12:34:43 -0700104 mLauncher.getStateManager().reapplyState(true /* cancelCurrentAnimation */);
Sunny Goyalce8809a2018-01-18 14:02:47 -0800105 }
Sunny Goyal022b1822019-06-12 08:44:09 -0700106 }
Sunny Goyal0abb36f2015-06-23 10:53:59 -0700107
Sunny Goyal022b1822019-06-12 08:44:09 -0700108 @Override
109 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
110 mTempRect.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
111 insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
112 handleSystemWindowInsets(mTempRect);
113 if (Utilities.ATLEAST_Q) {
114 return insets.inset(mConsumedInsets.left, mConsumedInsets.top,
115 mConsumedInsets.right, mConsumedInsets.bottom);
116 } else {
117 return insets.replaceSystemWindowInsets(mTempRect);
118 }
Adam Cohena6d04922014-10-23 17:28:30 -0700119 }
Sunny Goyal0abb36f2015-06-23 10:53:59 -0700120
Jon Mirandade43a712018-01-18 11:35:10 -0800121 @Override
122 public void setInsets(Rect insets) {
Sunny Goyalf8d56fc2018-01-31 15:18:11 -0800123 // If the insets haven't changed, this is a no-op. Avoid unnecessary layout caused by
124 // modifying child layout params.
125 if (!insets.equals(mInsets)) {
126 super.setInsets(insets);
127 }
Jon Mirandade43a712018-01-18 11:35:10 -0800128 }
129
Sunny Goyal07b69292018-01-08 14:19:34 -0800130 public void dispatchInsets() {
Sunny Goyalae6e3182019-04-30 12:04:37 -0700131 mLauncher.updateInsets(mInsets);
Sunny Goyalf8d56fc2018-01-31 15:18:11 -0800132 super.setInsets(mInsets);
Sunny Goyal07b69292018-01-08 14:19:34 -0800133 }
134
Sunny Goyal0abb36f2015-06-23 10:53:59 -0700135 @Override
136 protected void dispatchDraw(Canvas canvas) {
137 super.dispatchDraw(canvas);
138
139 // If the right inset is opaque, draw a black rectangle to ensure that is stays opaque.
Sunny Goyal9001b102018-05-07 11:09:13 -0700140 if (mConsumedInsets.right > 0) {
141 int width = getWidth();
142 canvas.drawRect(width - mConsumedInsets.right, 0, width, getHeight(), mOpaquePaint);
143 }
144 if (mConsumedInsets.left > 0) {
145 canvas.drawRect(0, 0, mConsumedInsets.left, getHeight(), mOpaquePaint);
146 }
147 if (mConsumedInsets.bottom > 0) {
148 int height = getHeight();
149 canvas.drawRect(0, height - mConsumedInsets.bottom, getWidth(), height, mOpaquePaint);
Sunny Goyal0abb36f2015-06-23 10:53:59 -0700150 }
151 }
Sunny Goyal7185dd62018-03-14 17:51:49 -0700152
153 public void setWindowStateListener(WindowStateListener listener) {
154 mWindowStateListener = listener;
155 }
156
157 @Override
158 public void onWindowFocusChanged(boolean hasWindowFocus) {
159 super.onWindowFocusChanged(hasWindowFocus);
160 if (mWindowStateListener != null) {
161 mWindowStateListener.onWindowFocusChanged(hasWindowFocus);
162 }
163 }
164
165 @Override
166 protected void onWindowVisibilityChanged(int visibility) {
167 super.onWindowVisibilityChanged(visibility);
168 if (mWindowStateListener != null) {
169 mWindowStateListener.onWindowVisibilityChanged(visibility);
170 }
171 }
172
Sunny Goyal745df7c2019-04-03 15:25:00 -0700173 @Override
Tony Wickham12e8a342019-04-23 11:28:54 -0700174 protected void onLayout(boolean changed, int l, int t, int r, int b) {
175 super.onLayout(changed, l, t, r, b);
176 SYSTEM_GESTURE_EXCLUSION_RECT.get(0).set(l, t, r, b);
177 setDisallowBackGesture(mDisallowBackGesture);
178 }
179
180 @TargetApi(Build.VERSION_CODES.Q)
Vinit Nayak9a846212019-09-05 11:47:12 -0700181 public void setForceHideBackArrow(boolean forceHideBackArrow) {
182 this.mForceHideBackArrow = forceHideBackArrow;
183 setDisallowBackGesture(mDisallowBackGesture);
184 }
185
186 @TargetApi(Build.VERSION_CODES.Q)
Tony Wickham12e8a342019-04-23 11:28:54 -0700187 public void setDisallowBackGesture(boolean disallowBackGesture) {
188 if (!Utilities.ATLEAST_Q) {
189 return;
190 }
191 mDisallowBackGesture = disallowBackGesture;
Vinit Nayak9a846212019-09-05 11:47:12 -0700192 setSystemGestureExclusionRects((mForceHideBackArrow || mDisallowBackGesture)
Tony Wickham12e8a342019-04-23 11:28:54 -0700193 ? SYSTEM_GESTURE_EXCLUSION_RECT
194 : Collections.emptyList());
195 }
196
Sunny Goyal7185dd62018-03-14 17:51:49 -0700197 public interface WindowStateListener {
198
199 void onWindowFocusChanged(boolean hasFocus);
200
201 void onWindowVisibilityChanged(int visibility);
202 }
Adam Cohena6d04922014-10-23 17:28:30 -0700203}