blob: 7de2ee4eedb5bcbf137ce88c7af6852b41767fc5 [file] [log] [blame]
Adam Cohena6d04922014-10-23 17:28:30 -07001package com.android.launcher3;
2
Sunny Goyala314d5a2020-05-20 20:34:04 -07003import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY;
Sunny Goyaled2d2bc2018-04-19 12:34:43 -07004
Sunny Goyal93264612015-11-23 11:47:50 -08005import android.annotation.TargetApi;
Adam Cohena6d04922014-10-23 17:28:30 -07006import android.content.Context;
Tony Wickham7eb5b532021-09-17 17:08:46 -07007import android.content.res.Resources;
Adam Cohen501e1392021-02-02 16:45:07 -08008import android.graphics.Canvas;
Tony Wickham7eb5b532021-09-17 17:08:46 -07009import android.graphics.Insets;
Adam Cohena6d04922014-10-23 17:28:30 -070010import android.graphics.Rect;
Tony Wickham12e8a342019-04-23 11:28:54 -070011import android.os.Build;
Adam Cohena6d04922014-10-23 17:28:30 -070012import android.util.AttributeSet;
Sunny Goyal4ffec482016-02-09 11:28:52 -080013import android.view.ViewDebug;
Sunny Goyal022b1822019-06-12 08:44:09 -070014import android.view.WindowInsets;
Adam Cohena6d04922014-10-23 17:28:30 -070015
Tony Wickham7eb5b532021-09-17 17:08:46 -070016import androidx.annotation.RequiresApi;
17
Adam Cohen501e1392021-02-02 16:45:07 -080018import com.android.launcher3.graphics.SysUiScrim;
Sunny Goyal9d89f752020-06-19 11:09:24 -070019import com.android.launcher3.statemanager.StatefulActivity;
Tony Wickham7eb5b532021-09-17 17:08:46 -070020import com.android.launcher3.uioverrides.ApiWrapper;
Sunny Goyal9d89f752020-06-19 11:09:24 -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 Goyal022b1822019-06-12 08:44:09 -070027 private final Rect mTempRect = new Rect();
28
Sunny Goyal9d89f752020-06-19 11:09:24 -070029 private final StatefulActivity mActivity;
Sunny Goyal07b69292018-01-08 14:19:34 -080030
Sunny Goyal745df7c2019-04-03 15:25:00 -070031 @ViewDebug.ExportedProperty(category = "launcher")
Tony Wickham12e8a342019-04-23 11:28:54 -070032 private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT =
33 Collections.singletonList(new Rect());
34
Sunny Goyal7185dd62018-03-14 17:51:49 -070035 private WindowStateListener mWindowStateListener;
Tony Wickham12e8a342019-04-23 11:28:54 -070036 @ViewDebug.ExportedProperty(category = "launcher")
37 private boolean mDisallowBackGesture;
Vinit Nayak9a846212019-09-05 11:47:12 -070038 @ViewDebug.ExportedProperty(category = "launcher")
39 private boolean mForceHideBackArrow;
Sunny Goyal93264612015-11-23 11:47:50 -080040
Sunny Goyal4ed0fb52021-04-26 09:52:47 -070041 private final SysUiScrim mSysUiScrim;
Adam Cohen501e1392021-02-02 16:45:07 -080042
Adam Cohena6d04922014-10-23 17:28:30 -070043 public LauncherRootView(Context context, AttributeSet attrs) {
44 super(context, attrs);
Sunny Goyal9d89f752020-06-19 11:09:24 -070045 mActivity = StatefulActivity.fromContext(context);
Sunny Goyal4ed0fb52021-04-26 09:52:47 -070046 mSysUiScrim = new SysUiScrim(this);
Adam Cohena6d04922014-10-23 17:28:30 -070047 }
48
Sunny Goyal022b1822019-06-12 08:44:09 -070049 private void handleSystemWindowInsets(Rect insets) {
Tony Wickham145b7fd2021-03-11 10:03:12 -080050 // Update device profile before notifying the children.
Tony Wickham21970cc2021-09-15 15:44:05 -070051 mActivity.getDeviceProfile().updateInsets(insets);
Sunny Goyalce8809a2018-01-18 14:02:47 -080052 boolean resetState = !insets.equals(mInsets);
Sunny Goyal906c6b22017-08-18 00:35:52 -070053 setInsets(insets);
54
Sunny Goyalce8809a2018-01-18 14:02:47 -080055 if (resetState) {
Sunny Goyal9d89f752020-06-19 11:09:24 -070056 mActivity.getStateManager().reapplyState(true /* cancelCurrentAnimation */);
Sunny Goyalce8809a2018-01-18 14:02:47 -080057 }
Sunny Goyal022b1822019-06-12 08:44:09 -070058 }
Sunny Goyal0abb36f2015-06-23 10:53:59 -070059
Sunny Goyal022b1822019-06-12 08:44:09 -070060 @Override
61 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
Tony Wickham7eb5b532021-09-17 17:08:46 -070062 if (Utilities.ATLEAST_R) {
63 insets = updateInsetsDueToTaskbar(insets);
64 Insets systemWindowInsets = insets.getInsetsIgnoringVisibility(
65 WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
66 mTempRect.set(systemWindowInsets.left, systemWindowInsets.top, systemWindowInsets.right,
67 systemWindowInsets.bottom);
68 } else {
69 mTempRect.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
70 insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
71 }
Sunny Goyal022b1822019-06-12 08:44:09 -070072 handleSystemWindowInsets(mTempRect);
Sunny Goyal786940a2020-06-02 02:31:31 -070073 return insets;
Adam Cohena6d04922014-10-23 17:28:30 -070074 }
Sunny Goyal0abb36f2015-06-23 10:53:59 -070075
Tony Wickham7eb5b532021-09-17 17:08:46 -070076 /**
77 * Taskbar provides nav bar and tappable insets. However, taskbar is not attached immediately,
78 * and can be destroyed and recreated. Thus, instead of relying on taskbar being present to
79 * get its insets, we calculate them ourselves so they are stable regardless of whether taskbar
80 * is currently attached.
81 *
Tony Wickham7eb5b532021-09-17 17:08:46 -070082 * @param oldInsets The system-provided insets, which we are modifying.
83 * @return The updated insets.
84 */
85 @RequiresApi(api = Build.VERSION_CODES.R)
86 private WindowInsets updateInsetsDueToTaskbar(WindowInsets oldInsets) {
87 if (!ApiWrapper.TASKBAR_DRAWN_IN_PROCESS) {
88 // 3P launchers based on Launcher3 should still be inset like normal.
89 return oldInsets;
90 }
91
92 WindowInsets.Builder updatedInsetsBuilder = new WindowInsets.Builder(oldInsets);
93
94 DeviceProfile dp = mActivity.getDeviceProfile();
95 Resources resources = getResources();
96
97 Insets oldNavInsets = oldInsets.getInsets(WindowInsets.Type.navigationBars());
98 Rect newNavInsets = new Rect(oldNavInsets.left, oldNavInsets.top, oldNavInsets.right,
99 oldNavInsets.bottom);
Tony Wickham21970cc2021-09-15 15:44:05 -0700100
101 if (dp.isLandscape) {
Tony Wickham7eb5b532021-09-17 17:08:46 -0700102 if (dp.isTablet) {
103 newNavInsets.bottom = ResourceUtils.getNavbarSize(
104 "navigation_bar_height_landscape", resources);
105 } else {
106 int navWidth = ResourceUtils.getNavbarSize("navigation_bar_width", resources);
107 if (dp.isSeascape()) {
108 newNavInsets.left = navWidth;
109 } else {
110 newNavInsets.right = navWidth;
111 }
112 }
113 } else {
114 newNavInsets.bottom = ResourceUtils.getNavbarSize("navigation_bar_height", resources);
115 }
116 updatedInsetsBuilder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(newNavInsets));
117 updatedInsetsBuilder.setInsetsIgnoringVisibility(WindowInsets.Type.navigationBars(),
118 Insets.of(newNavInsets));
119
120 mActivity.updateWindowInsets(updatedInsetsBuilder, oldInsets);
121
122 return updatedInsetsBuilder.build();
123 }
124
Jon Mirandade43a712018-01-18 11:35:10 -0800125 @Override
126 public void setInsets(Rect insets) {
Sunny Goyalf8d56fc2018-01-31 15:18:11 -0800127 // If the insets haven't changed, this is a no-op. Avoid unnecessary layout caused by
128 // modifying child layout params.
129 if (!insets.equals(mInsets)) {
130 super.setInsets(insets);
Sunny Goyal4ed0fb52021-04-26 09:52:47 -0700131 mSysUiScrim.onInsetsChanged(insets);
Sunny Goyalf8d56fc2018-01-31 15:18:11 -0800132 }
Jon Mirandade43a712018-01-18 11:35:10 -0800133 }
134
Sunny Goyal07b69292018-01-08 14:19:34 -0800135 public void dispatchInsets() {
Sunny Goyal9d89f752020-06-19 11:09:24 -0700136 mActivity.getDeviceProfile().updateInsets(mInsets);
Sunny Goyalf8d56fc2018-01-31 15:18:11 -0800137 super.setInsets(mInsets);
Sunny Goyal07b69292018-01-08 14:19:34 -0800138 }
139
Sunny Goyal7185dd62018-03-14 17:51:49 -0700140 public void setWindowStateListener(WindowStateListener listener) {
141 mWindowStateListener = listener;
142 }
143
144 @Override
145 public void onWindowFocusChanged(boolean hasWindowFocus) {
146 super.onWindowFocusChanged(hasWindowFocus);
147 if (mWindowStateListener != null) {
148 mWindowStateListener.onWindowFocusChanged(hasWindowFocus);
149 }
150 }
151
152 @Override
153 protected void onWindowVisibilityChanged(int visibility) {
154 super.onWindowVisibilityChanged(visibility);
155 if (mWindowStateListener != null) {
156 mWindowStateListener.onWindowVisibilityChanged(visibility);
157 }
158 }
159
Adam Cohen501e1392021-02-02 16:45:07 -0800160 @Override
161 protected void dispatchDraw(Canvas canvas) {
Sunny Goyal4ed0fb52021-04-26 09:52:47 -0700162 mSysUiScrim.draw(canvas);
Adam Cohen501e1392021-02-02 16:45:07 -0800163 super.dispatchDraw(canvas);
164 }
165
Sunny Goyal745df7c2019-04-03 15:25:00 -0700166 @Override
Tony Wickham12e8a342019-04-23 11:28:54 -0700167 protected void onLayout(boolean changed, int l, int t, int r, int b) {
168 super.onLayout(changed, l, t, r, b);
169 SYSTEM_GESTURE_EXCLUSION_RECT.get(0).set(l, t, r, b);
170 setDisallowBackGesture(mDisallowBackGesture);
Sunny Goyal4ed0fb52021-04-26 09:52:47 -0700171 mSysUiScrim.setSize(r - l, b - t);
Tony Wickham12e8a342019-04-23 11:28:54 -0700172 }
173
174 @TargetApi(Build.VERSION_CODES.Q)
Vinit Nayak9a846212019-09-05 11:47:12 -0700175 public void setForceHideBackArrow(boolean forceHideBackArrow) {
176 this.mForceHideBackArrow = forceHideBackArrow;
177 setDisallowBackGesture(mDisallowBackGesture);
178 }
179
180 @TargetApi(Build.VERSION_CODES.Q)
Tony Wickham12e8a342019-04-23 11:28:54 -0700181 public void setDisallowBackGesture(boolean disallowBackGesture) {
Sunny Goyala314d5a2020-05-20 20:34:04 -0700182 if (!Utilities.ATLEAST_Q || SEPARATE_RECENTS_ACTIVITY.get()) {
Tony Wickham12e8a342019-04-23 11:28:54 -0700183 return;
184 }
185 mDisallowBackGesture = disallowBackGesture;
Vinit Nayak9a846212019-09-05 11:47:12 -0700186 setSystemGestureExclusionRects((mForceHideBackArrow || mDisallowBackGesture)
Tony Wickham12e8a342019-04-23 11:28:54 -0700187 ? SYSTEM_GESTURE_EXCLUSION_RECT
188 : Collections.emptyList());
189 }
190
Sunny Goyal4ed0fb52021-04-26 09:52:47 -0700191 public SysUiScrim getSysUiScrim() {
192 return mSysUiScrim;
193 }
194
Sunny Goyal7185dd62018-03-14 17:51:49 -0700195 public interface WindowStateListener {
196
197 void onWindowFocusChanged(boolean hasFocus);
198
199 void onWindowVisibilityChanged(int visibility);
200 }
Adam Cohen501e1392021-02-02 16:45:07 -0800201}