blob: e738eb7af179e28f245991805ebf3a8c1aa7ef43 [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;
Adam Cohena6d04922014-10-23 17:28:30 -070015import android.util.AttributeSet;
Sunny Goyal745df7c2019-04-03 15:25:00 -070016import android.view.MotionEvent;
Sunny Goyal93264612015-11-23 11:47:50 -080017import android.view.View;
Sunny Goyal4ffec482016-02-09 11:28:52 -080018import android.view.ViewDebug;
Sunny Goyal745df7c2019-04-03 15:25:00 -070019import android.view.WindowInsets;
Adam Cohena6d04922014-10-23 17:28:30 -070020
21public class LauncherRootView extends InsettableFrameLayout {
Sunny Goyal0abb36f2015-06-23 10:53:59 -070022
Sunny Goyal07b69292018-01-08 14:19:34 -080023 private final Launcher mLauncher;
24
Sunny Goyal0abb36f2015-06-23 10:53:59 -070025 private final Paint mOpaquePaint;
Sunny Goyal9001b102018-05-07 11:09:13 -070026
Sunny Goyal4ffec482016-02-09 11:28:52 -080027 @ViewDebug.ExportedProperty(category = "launcher")
Sunny Goyal9001b102018-05-07 11:09:13 -070028 private final Rect mConsumedInsets = new Rect();
Sunny Goyal0abb36f2015-06-23 10:53:59 -070029
Sunny Goyal745df7c2019-04-03 15:25:00 -070030 @ViewDebug.ExportedProperty(category = "launcher")
31 private final RectF mTouchExcludeRegion = new RectF();
32
Sunny Goyal93264612015-11-23 11:47:50 -080033 private View mAlignedView;
Sunny Goyal7185dd62018-03-14 17:51:49 -070034 private WindowStateListener mWindowStateListener;
Sunny Goyal93264612015-11-23 11:47:50 -080035
Adam Cohena6d04922014-10-23 17:28:30 -070036 public LauncherRootView(Context context, AttributeSet attrs) {
37 super(context, attrs);
Sunny Goyal0abb36f2015-06-23 10:53:59 -070038
39 mOpaquePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
40 mOpaquePaint.setColor(Color.BLACK);
41 mOpaquePaint.setStyle(Paint.Style.FILL);
Sunny Goyal07b69292018-01-08 14:19:34 -080042
43 mLauncher = Launcher.getLauncher(context);
Adam Cohena6d04922014-10-23 17:28:30 -070044 }
45
46 @Override
Sunny Goyal93264612015-11-23 11:47:50 -080047 protected void onFinishInflate() {
48 if (getChildCount() > 0) {
49 // LauncherRootView contains only one child, which should be aligned
50 // based on the horizontal insets.
51 mAlignedView = getChildAt(0);
52 }
53 super.onFinishInflate();
54 }
55
56 @TargetApi(23)
57 @Override
Adam Cohena6d04922014-10-23 17:28:30 -070058 protected boolean fitSystemWindows(Rect insets) {
Sunny Goyal9001b102018-05-07 11:09:13 -070059 mConsumedInsets.setEmpty();
60 boolean drawInsetBar = false;
Sunny Goyal8c48d8b2019-01-25 15:10:18 -080061 if (mLauncher.isInMultiWindowMode()
Sunny Goyal9001b102018-05-07 11:09:13 -070062 && (insets.left > 0 || insets.right > 0 || insets.bottom > 0)) {
63 mConsumedInsets.left = insets.left;
64 mConsumedInsets.right = insets.right;
65 mConsumedInsets.bottom = insets.bottom;
66 insets = new Rect(0, insets.top, 0, 0);
67 drawInsetBar = true;
68 } else if ((insets.right > 0 || insets.left > 0) &&
Sunny Goyal8c48d8b2019-01-25 15:10:18 -080069 getContext().getSystemService(ActivityManager.class).isLowRamDevice()) {
Sunny Goyal9001b102018-05-07 11:09:13 -070070 mConsumedInsets.left = insets.left;
71 mConsumedInsets.right = insets.right;
Sunny Goyal906c6b22017-08-18 00:35:52 -070072 insets = new Rect(0, insets.top, 0, insets.bottom);
Sunny Goyal9001b102018-05-07 11:09:13 -070073 drawInsetBar = true;
Sunny Goyal906c6b22017-08-18 00:35:52 -070074 }
Sunny Goyal9001b102018-05-07 11:09:13 -070075
Sunny Goyal07b69292018-01-08 14:19:34 -080076 mLauncher.getSystemUiController().updateUiState(
Sunny Goyal9001b102018-05-07 11:09:13 -070077 UI_STATE_ROOT_VIEW, drawInsetBar ? FLAG_DARK_NAV : 0);
Sunny Goyal93264612015-11-23 11:47:50 -080078
Sunny Goyal07b69292018-01-08 14:19:34 -080079 // Update device profile before notifying th children.
80 mLauncher.getDeviceProfile().updateInsets(insets);
Sunny Goyalce8809a2018-01-18 14:02:47 -080081 boolean resetState = !insets.equals(mInsets);
Sunny Goyal906c6b22017-08-18 00:35:52 -070082 setInsets(insets);
83
84 if (mAlignedView != null) {
Sunny Goyal9001b102018-05-07 11:09:13 -070085 // Apply margins on aligned view to handle consumed insets.
Sunny Goyal93264612015-11-23 11:47:50 -080086 MarginLayoutParams lp = (MarginLayoutParams) mAlignedView.getLayoutParams();
Sunny Goyal9001b102018-05-07 11:09:13 -070087 if (lp.leftMargin != mConsumedInsets.left || lp.rightMargin != mConsumedInsets.right ||
88 lp.bottomMargin != mConsumedInsets.bottom) {
89 lp.leftMargin = mConsumedInsets.left;
90 lp.rightMargin = mConsumedInsets.right;
91 lp.topMargin = mConsumedInsets.top;
92 lp.bottomMargin = mConsumedInsets.bottom;
Sunny Goyal93264612015-11-23 11:47:50 -080093 mAlignedView.setLayoutParams(lp);
94 }
95 }
Sunny Goyalce8809a2018-01-18 14:02:47 -080096 if (resetState) {
Sunny Goyaled2d2bc2018-04-19 12:34:43 -070097 mLauncher.getStateManager().reapplyState(true /* cancelCurrentAnimation */);
Sunny Goyalce8809a2018-01-18 14:02:47 -080098 }
Sunny Goyal0abb36f2015-06-23 10:53:59 -070099
Adam Cohena6d04922014-10-23 17:28:30 -0700100 return true; // I'll take it from here
101 }
Sunny Goyal0abb36f2015-06-23 10:53:59 -0700102
Jon Mirandade43a712018-01-18 11:35:10 -0800103 @Override
104 public void setInsets(Rect insets) {
Sunny Goyalf8d56fc2018-01-31 15:18:11 -0800105 // If the insets haven't changed, this is a no-op. Avoid unnecessary layout caused by
106 // modifying child layout params.
107 if (!insets.equals(mInsets)) {
108 super.setInsets(insets);
109 }
Jon Mirandade43a712018-01-18 11:35:10 -0800110 }
111
Sunny Goyal07b69292018-01-08 14:19:34 -0800112 public void dispatchInsets() {
Sunny Goyal34778042018-04-11 16:31:31 -0700113 mLauncher.getDeviceProfile().updateInsets(mInsets);
Sunny Goyalf8d56fc2018-01-31 15:18:11 -0800114 super.setInsets(mInsets);
Sunny Goyal07b69292018-01-08 14:19:34 -0800115 }
116
Sunny Goyal0abb36f2015-06-23 10:53:59 -0700117 @Override
118 protected void dispatchDraw(Canvas canvas) {
119 super.dispatchDraw(canvas);
120
121 // If the right inset is opaque, draw a black rectangle to ensure that is stays opaque.
Sunny Goyal9001b102018-05-07 11:09:13 -0700122 if (mConsumedInsets.right > 0) {
123 int width = getWidth();
124 canvas.drawRect(width - mConsumedInsets.right, 0, width, getHeight(), mOpaquePaint);
125 }
126 if (mConsumedInsets.left > 0) {
127 canvas.drawRect(0, 0, mConsumedInsets.left, getHeight(), mOpaquePaint);
128 }
129 if (mConsumedInsets.bottom > 0) {
130 int height = getHeight();
131 canvas.drawRect(0, height - mConsumedInsets.bottom, getWidth(), height, mOpaquePaint);
Sunny Goyal0abb36f2015-06-23 10:53:59 -0700132 }
133 }
Sunny Goyal7185dd62018-03-14 17:51:49 -0700134
135 public void setWindowStateListener(WindowStateListener listener) {
136 mWindowStateListener = listener;
137 }
138
139 @Override
140 public void onWindowFocusChanged(boolean hasWindowFocus) {
141 super.onWindowFocusChanged(hasWindowFocus);
142 if (mWindowStateListener != null) {
143 mWindowStateListener.onWindowFocusChanged(hasWindowFocus);
144 }
145 }
146
147 @Override
148 protected void onWindowVisibilityChanged(int visibility) {
149 super.onWindowVisibilityChanged(visibility);
150 if (mWindowStateListener != null) {
151 mWindowStateListener.onWindowVisibilityChanged(visibility);
152 }
153 }
154
Sunny Goyal745df7c2019-04-03 15:25:00 -0700155 @Override
156 public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
157 if (Utilities.ATLEAST_Q) {
158 Insets gestureInsets = insets.getMandatorySystemGestureInsets();
159 mTouchExcludeRegion.set(gestureInsets.left, gestureInsets.top,
160 gestureInsets.right, gestureInsets.bottom);
161 }
162 return super.dispatchApplyWindowInsets(insets);
163 }
164
165 @Override
166 public boolean dispatchTouchEvent(MotionEvent ev) {
167 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
168 float x = ev.getX();
169 float y = ev.getY();
170 if (y < mTouchExcludeRegion.top
171 || x < mTouchExcludeRegion.left
172 || x > (getWidth() - mTouchExcludeRegion.right)
173 || y > (getHeight() - mTouchExcludeRegion.bottom)) {
174 return false;
175 }
176 }
177 return super.dispatchTouchEvent(ev);
178 }
179
Sunny Goyal7185dd62018-03-14 17:51:49 -0700180 public interface WindowStateListener {
181
182 void onWindowFocusChanged(boolean hasFocus);
183
184 void onWindowVisibilityChanged(int visibility);
185 }
Adam Cohena6d04922014-10-23 17:28:30 -0700186}