blob: e6c2d0c9c526f720e9969fda8380fa3f482ef8ea [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 Goyal745df7c2019-04-03 15:25:00 -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;
Sunny Goyal745df7c2019-04-03 15:25:00 -070014import android.graphics.RectF;
Tony Wickham12e8a342019-04-23 11:28:54 -070015import android.os.Build;
Adam Cohena6d04922014-10-23 17:28:30 -070016import android.util.AttributeSet;
Sunny Goyal745df7c2019-04-03 15:25:00 -070017import android.view.MotionEvent;
Sunny Goyal93264612015-11-23 11:47:50 -080018import android.view.View;
Sunny Goyal4ffec482016-02-09 11:28:52 -080019import android.view.ViewDebug;
Sunny Goyal745df7c2019-04-03 15:25:00 -070020import android.view.WindowInsets;
Adam Cohena6d04922014-10-23 17:28:30 -070021
Tony Wickham12e8a342019-04-23 11:28:54 -070022import java.util.Collections;
23import java.util.List;
24
Adam Cohena6d04922014-10-23 17:28:30 -070025public class LauncherRootView extends InsettableFrameLayout {
Sunny Goyal0abb36f2015-06-23 10:53:59 -070026
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")
35 private final RectF mTouchExcludeRegion = new RectF();
36
Tony Wickham12e8a342019-04-23 11:28:54 -070037 @ViewDebug.ExportedProperty(category = "launcher")
38 private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT =
39 Collections.singletonList(new Rect());
40
Sunny Goyal93264612015-11-23 11:47:50 -080041 private View mAlignedView;
Sunny Goyal7185dd62018-03-14 17:51:49 -070042 private WindowStateListener mWindowStateListener;
Tony Wickham12e8a342019-04-23 11:28:54 -070043 @ViewDebug.ExportedProperty(category = "launcher")
44 private boolean mDisallowBackGesture;
Sunny Goyal93264612015-11-23 11:47:50 -080045
Adam Cohena6d04922014-10-23 17:28:30 -070046 public LauncherRootView(Context context, AttributeSet attrs) {
47 super(context, attrs);
Sunny Goyal0abb36f2015-06-23 10:53:59 -070048
49 mOpaquePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
50 mOpaquePaint.setColor(Color.BLACK);
51 mOpaquePaint.setStyle(Paint.Style.FILL);
Sunny Goyal07b69292018-01-08 14:19:34 -080052
53 mLauncher = Launcher.getLauncher(context);
Adam Cohena6d04922014-10-23 17:28:30 -070054 }
55
56 @Override
Sunny Goyal93264612015-11-23 11:47:50 -080057 protected void onFinishInflate() {
58 if (getChildCount() > 0) {
59 // LauncherRootView contains only one child, which should be aligned
60 // based on the horizontal insets.
61 mAlignedView = getChildAt(0);
62 }
63 super.onFinishInflate();
64 }
65
66 @TargetApi(23)
67 @Override
Adam Cohena6d04922014-10-23 17:28:30 -070068 protected boolean fitSystemWindows(Rect insets) {
Sunny Goyal9001b102018-05-07 11:09:13 -070069 mConsumedInsets.setEmpty();
70 boolean drawInsetBar = false;
Sunny Goyal8c48d8b2019-01-25 15:10:18 -080071 if (mLauncher.isInMultiWindowMode()
Sunny Goyal9001b102018-05-07 11:09:13 -070072 && (insets.left > 0 || insets.right > 0 || insets.bottom > 0)) {
73 mConsumedInsets.left = insets.left;
74 mConsumedInsets.right = insets.right;
75 mConsumedInsets.bottom = insets.bottom;
76 insets = new Rect(0, insets.top, 0, 0);
77 drawInsetBar = true;
78 } else if ((insets.right > 0 || insets.left > 0) &&
Sunny Goyal8c48d8b2019-01-25 15:10:18 -080079 getContext().getSystemService(ActivityManager.class).isLowRamDevice()) {
Sunny Goyal9001b102018-05-07 11:09:13 -070080 mConsumedInsets.left = insets.left;
81 mConsumedInsets.right = insets.right;
Sunny Goyal906c6b22017-08-18 00:35:52 -070082 insets = new Rect(0, insets.top, 0, insets.bottom);
Sunny Goyal9001b102018-05-07 11:09:13 -070083 drawInsetBar = true;
Sunny Goyal906c6b22017-08-18 00:35:52 -070084 }
Sunny Goyal9001b102018-05-07 11:09:13 -070085
Sunny Goyal07b69292018-01-08 14:19:34 -080086 mLauncher.getSystemUiController().updateUiState(
Sunny Goyal9001b102018-05-07 11:09:13 -070087 UI_STATE_ROOT_VIEW, drawInsetBar ? FLAG_DARK_NAV : 0);
Sunny Goyal93264612015-11-23 11:47:50 -080088
Sunny Goyal07b69292018-01-08 14:19:34 -080089 // Update device profile before notifying th children.
90 mLauncher.getDeviceProfile().updateInsets(insets);
Sunny Goyalce8809a2018-01-18 14:02:47 -080091 boolean resetState = !insets.equals(mInsets);
Sunny Goyal906c6b22017-08-18 00:35:52 -070092 setInsets(insets);
93
94 if (mAlignedView != null) {
Sunny Goyal9001b102018-05-07 11:09:13 -070095 // Apply margins on aligned view to handle consumed insets.
Sunny Goyal93264612015-11-23 11:47:50 -080096 MarginLayoutParams lp = (MarginLayoutParams) mAlignedView.getLayoutParams();
Sunny Goyal9001b102018-05-07 11:09:13 -070097 if (lp.leftMargin != mConsumedInsets.left || lp.rightMargin != mConsumedInsets.right ||
98 lp.bottomMargin != mConsumedInsets.bottom) {
99 lp.leftMargin = mConsumedInsets.left;
100 lp.rightMargin = mConsumedInsets.right;
101 lp.topMargin = mConsumedInsets.top;
102 lp.bottomMargin = mConsumedInsets.bottom;
Sunny Goyal93264612015-11-23 11:47:50 -0800103 mAlignedView.setLayoutParams(lp);
104 }
105 }
Sunny Goyalce8809a2018-01-18 14:02:47 -0800106 if (resetState) {
Sunny Goyaled2d2bc2018-04-19 12:34:43 -0700107 mLauncher.getStateManager().reapplyState(true /* cancelCurrentAnimation */);
Sunny Goyalce8809a2018-01-18 14:02:47 -0800108 }
Sunny Goyal0abb36f2015-06-23 10:53:59 -0700109
Adam Cohena6d04922014-10-23 17:28:30 -0700110 return true; // I'll take it from here
111 }
Sunny Goyal0abb36f2015-06-23 10:53:59 -0700112
Jon Mirandade43a712018-01-18 11:35:10 -0800113 @Override
114 public void setInsets(Rect insets) {
Sunny Goyalf8d56fc2018-01-31 15:18:11 -0800115 // If the insets haven't changed, this is a no-op. Avoid unnecessary layout caused by
116 // modifying child layout params.
117 if (!insets.equals(mInsets)) {
118 super.setInsets(insets);
119 }
Jon Mirandade43a712018-01-18 11:35:10 -0800120 }
121
Sunny Goyal07b69292018-01-08 14:19:34 -0800122 public void dispatchInsets() {
Sunny Goyal34778042018-04-11 16:31:31 -0700123 mLauncher.getDeviceProfile().updateInsets(mInsets);
Sunny Goyalf8d56fc2018-01-31 15:18:11 -0800124 super.setInsets(mInsets);
Sunny Goyal07b69292018-01-08 14:19:34 -0800125 }
126
Sunny Goyal0abb36f2015-06-23 10:53:59 -0700127 @Override
128 protected void dispatchDraw(Canvas canvas) {
129 super.dispatchDraw(canvas);
130
131 // If the right inset is opaque, draw a black rectangle to ensure that is stays opaque.
Sunny Goyal9001b102018-05-07 11:09:13 -0700132 if (mConsumedInsets.right > 0) {
133 int width = getWidth();
134 canvas.drawRect(width - mConsumedInsets.right, 0, width, getHeight(), mOpaquePaint);
135 }
136 if (mConsumedInsets.left > 0) {
137 canvas.drawRect(0, 0, mConsumedInsets.left, getHeight(), mOpaquePaint);
138 }
139 if (mConsumedInsets.bottom > 0) {
140 int height = getHeight();
141 canvas.drawRect(0, height - mConsumedInsets.bottom, getWidth(), height, mOpaquePaint);
Sunny Goyal0abb36f2015-06-23 10:53:59 -0700142 }
143 }
Sunny Goyal7185dd62018-03-14 17:51:49 -0700144
145 public void setWindowStateListener(WindowStateListener listener) {
146 mWindowStateListener = listener;
147 }
148
149 @Override
150 public void onWindowFocusChanged(boolean hasWindowFocus) {
151 super.onWindowFocusChanged(hasWindowFocus);
152 if (mWindowStateListener != null) {
153 mWindowStateListener.onWindowFocusChanged(hasWindowFocus);
154 }
155 }
156
157 @Override
158 protected void onWindowVisibilityChanged(int visibility) {
159 super.onWindowVisibilityChanged(visibility);
160 if (mWindowStateListener != null) {
161 mWindowStateListener.onWindowVisibilityChanged(visibility);
162 }
163 }
164
Sunny Goyal745df7c2019-04-03 15:25:00 -0700165 @Override
166 public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
167 if (Utilities.ATLEAST_Q) {
168 Insets gestureInsets = insets.getMandatorySystemGestureInsets();
169 mTouchExcludeRegion.set(gestureInsets.left, gestureInsets.top,
170 gestureInsets.right, gestureInsets.bottom);
171 }
172 return super.dispatchApplyWindowInsets(insets);
173 }
174
175 @Override
176 public boolean dispatchTouchEvent(MotionEvent ev) {
177 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
178 float x = ev.getX();
179 float y = ev.getY();
180 if (y < mTouchExcludeRegion.top
181 || x < mTouchExcludeRegion.left
182 || x > (getWidth() - mTouchExcludeRegion.right)
183 || y > (getHeight() - mTouchExcludeRegion.bottom)) {
184 return false;
185 }
186 }
187 return super.dispatchTouchEvent(ev);
188 }
189
Tony Wickham12e8a342019-04-23 11:28:54 -0700190 @Override
191 protected void onLayout(boolean changed, int l, int t, int r, int b) {
192 super.onLayout(changed, l, t, r, b);
193 SYSTEM_GESTURE_EXCLUSION_RECT.get(0).set(l, t, r, b);
194 setDisallowBackGesture(mDisallowBackGesture);
195 }
196
197 @TargetApi(Build.VERSION_CODES.Q)
198 public void setDisallowBackGesture(boolean disallowBackGesture) {
199 if (!Utilities.ATLEAST_Q) {
200 return;
201 }
202 mDisallowBackGesture = disallowBackGesture;
203 setSystemGestureExclusionRects(mDisallowBackGesture
204 ? SYSTEM_GESTURE_EXCLUSION_RECT
205 : Collections.emptyList());
206 }
207
Sunny Goyal7185dd62018-03-14 17:51:49 -0700208 public interface WindowStateListener {
209
210 void onWindowFocusChanged(boolean hasFocus);
211
212 void onWindowVisibilityChanged(int visibility);
213 }
vadimtbd0f1162019-04-23 18:09:09 -0700214
215 @Override
216 public void requestLayout() {
217 super.requestLayout();
218 if (com.android.launcher3.TestProtocol.sDebugTracing) {
219 android.util.Log.d(com.android.launcher3.TestProtocol.NO_DRAG_TAG,
220 "requestLayout @ " + android.util.Log.getStackTraceString(
221 new Throwable()));
222 }
223 }
Adam Cohena6d04922014-10-23 17:28:30 -0700224}