blob: e3aa758eae0a46678ee2f4a2faceab8446f3984d [file] [log] [blame]
Adam Cohena6d04922014-10-23 17:28:30 -07001package com.android.launcher3;
2
Alex Chaubbe6cf32021-10-12 15:52:36 +01003import static com.android.launcher3.ResourceUtils.INVALID_RESOURCE_HANDLE;
Sunny Goyala314d5a2020-05-20 20:34:04 -07004import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY;
Sunny Goyaled2d2bc2018-04-19 12:34:43 -07005
Sunny Goyal93264612015-11-23 11:47:50 -08006import android.annotation.TargetApi;
Adam Cohena6d04922014-10-23 17:28:30 -07007import android.content.Context;
Tony Wickham7eb5b532021-09-17 17:08:46 -07008import android.content.res.Resources;
Adam Cohen501e1392021-02-02 16:45:07 -08009import android.graphics.Canvas;
Tony Wickham7eb5b532021-09-17 17:08:46 -070010import android.graphics.Insets;
Adam Cohena6d04922014-10-23 17:28:30 -070011import android.graphics.Rect;
Tony Wickham12e8a342019-04-23 11:28:54 -070012import android.os.Build;
Adam Cohena6d04922014-10-23 17:28:30 -070013import android.util.AttributeSet;
Sunny Goyal4ffec482016-02-09 11:28:52 -080014import android.view.ViewDebug;
Sunny Goyal022b1822019-06-12 08:44:09 -070015import android.view.WindowInsets;
Adam Cohena6d04922014-10-23 17:28:30 -070016
Tony Wickham7eb5b532021-09-17 17:08:46 -070017import androidx.annotation.RequiresApi;
18
Adam Cohen501e1392021-02-02 16:45:07 -080019import com.android.launcher3.graphics.SysUiScrim;
Sunny Goyal9d89f752020-06-19 11:09:24 -070020import com.android.launcher3.statemanager.StatefulActivity;
Tony Wickham7eb5b532021-09-17 17:08:46 -070021import com.android.launcher3.uioverrides.ApiWrapper;
Sunny Goyal9d89f752020-06-19 11:09:24 -070022
Tony Wickham12e8a342019-04-23 11:28:54 -070023import java.util.Collections;
24import java.util.List;
25
Adam Cohena6d04922014-10-23 17:28:30 -070026public class LauncherRootView extends InsettableFrameLayout {
Sunny Goyal0abb36f2015-06-23 10:53:59 -070027
Sunny Goyal022b1822019-06-12 08:44:09 -070028 private final Rect mTempRect = new Rect();
29
Sunny Goyal9d89f752020-06-19 11:09:24 -070030 private final StatefulActivity mActivity;
Sunny Goyal07b69292018-01-08 14:19:34 -080031
Sunny Goyal745df7c2019-04-03 15:25:00 -070032 @ViewDebug.ExportedProperty(category = "launcher")
Tony Wickham12e8a342019-04-23 11:28:54 -070033 private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT =
34 Collections.singletonList(new Rect());
35
Sunny Goyal7185dd62018-03-14 17:51:49 -070036 private WindowStateListener mWindowStateListener;
Tony Wickham12e8a342019-04-23 11:28:54 -070037 @ViewDebug.ExportedProperty(category = "launcher")
38 private boolean mDisallowBackGesture;
Vinit Nayak9a846212019-09-05 11:47:12 -070039 @ViewDebug.ExportedProperty(category = "launcher")
40 private boolean mForceHideBackArrow;
Sunny Goyal93264612015-11-23 11:47:50 -080041
Sunny Goyal4ed0fb52021-04-26 09:52:47 -070042 private final SysUiScrim mSysUiScrim;
Adam Cohen501e1392021-02-02 16:45:07 -080043
Adam Cohena6d04922014-10-23 17:28:30 -070044 public LauncherRootView(Context context, AttributeSet attrs) {
45 super(context, attrs);
Sunny Goyal9d89f752020-06-19 11:09:24 -070046 mActivity = StatefulActivity.fromContext(context);
Sunny Goyal4ed0fb52021-04-26 09:52:47 -070047 mSysUiScrim = new SysUiScrim(this);
Adam Cohena6d04922014-10-23 17:28:30 -070048 }
49
Sunny Goyal022b1822019-06-12 08:44:09 -070050 private void handleSystemWindowInsets(Rect insets) {
Tony Wickham145b7fd2021-03-11 10:03:12 -080051 // Update device profile before notifying the children.
Tony Wickham21970cc2021-09-15 15:44:05 -070052 mActivity.getDeviceProfile().updateInsets(insets);
Sunny Goyalce8809a2018-01-18 14:02:47 -080053 boolean resetState = !insets.equals(mInsets);
Sunny Goyal906c6b22017-08-18 00:35:52 -070054 setInsets(insets);
55
Sunny Goyalce8809a2018-01-18 14:02:47 -080056 if (resetState) {
Sunny Goyal9d89f752020-06-19 11:09:24 -070057 mActivity.getStateManager().reapplyState(true /* cancelCurrentAnimation */);
Sunny Goyalce8809a2018-01-18 14:02:47 -080058 }
Sunny Goyal022b1822019-06-12 08:44:09 -070059 }
Sunny Goyal0abb36f2015-06-23 10:53:59 -070060
Sunny Goyal022b1822019-06-12 08:44:09 -070061 @Override
62 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
Tony Wickham7eb5b532021-09-17 17:08:46 -070063 if (Utilities.ATLEAST_R) {
64 insets = updateInsetsDueToTaskbar(insets);
65 Insets systemWindowInsets = insets.getInsetsIgnoringVisibility(
66 WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
67 mTempRect.set(systemWindowInsets.left, systemWindowInsets.top, systemWindowInsets.right,
68 systemWindowInsets.bottom);
69 } else {
70 mTempRect.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
71 insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
72 }
Sunny Goyal022b1822019-06-12 08:44:09 -070073 handleSystemWindowInsets(mTempRect);
Sunny Goyal786940a2020-06-02 02:31:31 -070074 return insets;
Adam Cohena6d04922014-10-23 17:28:30 -070075 }
Sunny Goyal0abb36f2015-06-23 10:53:59 -070076
Tony Wickham7eb5b532021-09-17 17:08:46 -070077 /**
78 * Taskbar provides nav bar and tappable insets. However, taskbar is not attached immediately,
79 * and can be destroyed and recreated. Thus, instead of relying on taskbar being present to
80 * get its insets, we calculate them ourselves so they are stable regardless of whether taskbar
81 * is currently attached.
82 *
Tony Wickham7eb5b532021-09-17 17:08:46 -070083 * @param oldInsets The system-provided insets, which we are modifying.
84 * @return The updated insets.
85 */
86 @RequiresApi(api = Build.VERSION_CODES.R)
87 private WindowInsets updateInsetsDueToTaskbar(WindowInsets oldInsets) {
88 if (!ApiWrapper.TASKBAR_DRAWN_IN_PROCESS) {
89 // 3P launchers based on Launcher3 should still be inset like normal.
90 return oldInsets;
91 }
92
93 WindowInsets.Builder updatedInsetsBuilder = new WindowInsets.Builder(oldInsets);
94
95 DeviceProfile dp = mActivity.getDeviceProfile();
96 Resources resources = getResources();
97
98 Insets oldNavInsets = oldInsets.getInsets(WindowInsets.Type.navigationBars());
99 Rect newNavInsets = new Rect(oldNavInsets.left, oldNavInsets.top, oldNavInsets.right,
100 oldNavInsets.bottom);
Tony Wickham21970cc2021-09-15 15:44:05 -0700101
102 if (dp.isLandscape) {
Alex Chaubbe6cf32021-10-12 15:52:36 +0100103 boolean isGesturalMode = ResourceUtils.getIntegerByName(
104 "config_navBarInteractionMode",
105 resources,
106 INVALID_RESOURCE_HANDLE) == 2;
107 if (dp.isTablet || isGesturalMode) {
Alex Chau6a7d1e22022-01-20 19:54:17 +0000108 newNavInsets.bottom = dp.isTaskbarPresent
109 ? 0
110 : ResourceUtils.getNavbarSize("navigation_bar_height_landscape", resources);
Tony Wickham7eb5b532021-09-17 17:08:46 -0700111 } else {
112 int navWidth = ResourceUtils.getNavbarSize("navigation_bar_width", resources);
113 if (dp.isSeascape()) {
114 newNavInsets.left = navWidth;
115 } else {
116 newNavInsets.right = navWidth;
117 }
118 }
119 } else {
Alex Chau6a7d1e22022-01-20 19:54:17 +0000120 newNavInsets.bottom = dp.isTaskbarPresent
121 ? 0
122 : ResourceUtils.getNavbarSize("navigation_bar_height", resources);
Tony Wickham7eb5b532021-09-17 17:08:46 -0700123 }
124 updatedInsetsBuilder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(newNavInsets));
125 updatedInsetsBuilder.setInsetsIgnoringVisibility(WindowInsets.Type.navigationBars(),
126 Insets.of(newNavInsets));
127
128 mActivity.updateWindowInsets(updatedInsetsBuilder, oldInsets);
129
130 return updatedInsetsBuilder.build();
131 }
132
Jon Mirandade43a712018-01-18 11:35:10 -0800133 @Override
134 public void setInsets(Rect insets) {
Sunny Goyalf8d56fc2018-01-31 15:18:11 -0800135 // If the insets haven't changed, this is a no-op. Avoid unnecessary layout caused by
136 // modifying child layout params.
137 if (!insets.equals(mInsets)) {
138 super.setInsets(insets);
Sunny Goyal4ed0fb52021-04-26 09:52:47 -0700139 mSysUiScrim.onInsetsChanged(insets);
Sunny Goyalf8d56fc2018-01-31 15:18:11 -0800140 }
Jon Mirandade43a712018-01-18 11:35:10 -0800141 }
142
Sunny Goyal07b69292018-01-08 14:19:34 -0800143 public void dispatchInsets() {
Sunny Goyal9d89f752020-06-19 11:09:24 -0700144 mActivity.getDeviceProfile().updateInsets(mInsets);
Sunny Goyalf8d56fc2018-01-31 15:18:11 -0800145 super.setInsets(mInsets);
Sunny Goyal07b69292018-01-08 14:19:34 -0800146 }
147
Sunny Goyal7185dd62018-03-14 17:51:49 -0700148 public void setWindowStateListener(WindowStateListener listener) {
149 mWindowStateListener = listener;
150 }
151
152 @Override
153 public void onWindowFocusChanged(boolean hasWindowFocus) {
154 super.onWindowFocusChanged(hasWindowFocus);
155 if (mWindowStateListener != null) {
156 mWindowStateListener.onWindowFocusChanged(hasWindowFocus);
157 }
158 }
159
160 @Override
161 protected void onWindowVisibilityChanged(int visibility) {
162 super.onWindowVisibilityChanged(visibility);
163 if (mWindowStateListener != null) {
164 mWindowStateListener.onWindowVisibilityChanged(visibility);
165 }
166 }
167
Adam Cohen501e1392021-02-02 16:45:07 -0800168 @Override
169 protected void dispatchDraw(Canvas canvas) {
Sunny Goyal4ed0fb52021-04-26 09:52:47 -0700170 mSysUiScrim.draw(canvas);
Adam Cohen501e1392021-02-02 16:45:07 -0800171 super.dispatchDraw(canvas);
172 }
173
Sunny Goyal745df7c2019-04-03 15:25:00 -0700174 @Override
Tony Wickham12e8a342019-04-23 11:28:54 -0700175 protected void onLayout(boolean changed, int l, int t, int r, int b) {
176 super.onLayout(changed, l, t, r, b);
177 SYSTEM_GESTURE_EXCLUSION_RECT.get(0).set(l, t, r, b);
178 setDisallowBackGesture(mDisallowBackGesture);
Sunny Goyal4ed0fb52021-04-26 09:52:47 -0700179 mSysUiScrim.setSize(r - l, b - t);
Tony Wickham12e8a342019-04-23 11:28:54 -0700180 }
181
182 @TargetApi(Build.VERSION_CODES.Q)
Vinit Nayak9a846212019-09-05 11:47:12 -0700183 public void setForceHideBackArrow(boolean forceHideBackArrow) {
184 this.mForceHideBackArrow = forceHideBackArrow;
185 setDisallowBackGesture(mDisallowBackGesture);
186 }
187
188 @TargetApi(Build.VERSION_CODES.Q)
Tony Wickham12e8a342019-04-23 11:28:54 -0700189 public void setDisallowBackGesture(boolean disallowBackGesture) {
Sunny Goyala314d5a2020-05-20 20:34:04 -0700190 if (!Utilities.ATLEAST_Q || SEPARATE_RECENTS_ACTIVITY.get()) {
Tony Wickham12e8a342019-04-23 11:28:54 -0700191 return;
192 }
193 mDisallowBackGesture = disallowBackGesture;
Vinit Nayak9a846212019-09-05 11:47:12 -0700194 setSystemGestureExclusionRects((mForceHideBackArrow || mDisallowBackGesture)
Tony Wickham12e8a342019-04-23 11:28:54 -0700195 ? SYSTEM_GESTURE_EXCLUSION_RECT
196 : Collections.emptyList());
197 }
198
Sunny Goyal4ed0fb52021-04-26 09:52:47 -0700199 public SysUiScrim getSysUiScrim() {
200 return mSysUiScrim;
201 }
202
Sunny Goyal7185dd62018-03-14 17:51:49 -0700203 public interface WindowStateListener {
204
205 void onWindowFocusChanged(boolean hasFocus);
206
207 void onWindowVisibilityChanged(int visibility);
208 }
Adam Cohen501e1392021-02-02 16:45:07 -0800209}