1 package com.android.launcher3; 2 3 import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY; 4 5 import android.annotation.TargetApi; 6 import android.content.Context; 7 import android.graphics.Canvas; 8 import android.graphics.Rect; 9 import android.os.Build; 10 import android.util.AttributeSet; 11 import android.view.ViewDebug; 12 import android.view.WindowInsets; 13 14 import com.android.launcher3.graphics.SysUiScrim; 15 import com.android.launcher3.statemanager.StatefulActivity; 16 import com.android.launcher3.util.window.WindowManagerProxy; 17 18 import java.util.Collections; 19 import java.util.List; 20 21 public class LauncherRootView extends InsettableFrameLayout { 22 23 private final Rect mTempRect = new Rect(); 24 25 private final StatefulActivity mActivity; 26 27 @ViewDebug.ExportedProperty(category = "launcher") 28 private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT = 29 Collections.singletonList(new Rect()); 30 31 private WindowStateListener mWindowStateListener; 32 @ViewDebug.ExportedProperty(category = "launcher") 33 private boolean mDisallowBackGesture; 34 @ViewDebug.ExportedProperty(category = "launcher") 35 private boolean mForceHideBackArrow; 36 37 private final SysUiScrim mSysUiScrim; 38 LauncherRootView(Context context, AttributeSet attrs)39 public LauncherRootView(Context context, AttributeSet attrs) { 40 super(context, attrs); 41 mActivity = StatefulActivity.fromContext(context); 42 mSysUiScrim = new SysUiScrim(this); 43 } 44 handleSystemWindowInsets(Rect insets)45 private void handleSystemWindowInsets(Rect insets) { 46 // Update device profile before notifying the children. 47 mActivity.getDeviceProfile().updateInsets(insets); 48 boolean resetState = !insets.equals(mInsets); 49 setInsets(insets); 50 51 if (resetState) { 52 mActivity.getStateManager().reapplyState(true /* cancelCurrentAnimation */); 53 } 54 } 55 56 @Override onApplyWindowInsets(WindowInsets insets)57 public WindowInsets onApplyWindowInsets(WindowInsets insets) { 58 mActivity.handleConfigurationChanged(mActivity.getResources().getConfiguration()); 59 60 insets = WindowManagerProxy.INSTANCE.get(getContext()) 61 .normalizeWindowInsets(getContext(), insets, mTempRect); 62 handleSystemWindowInsets(mTempRect); 63 return insets; 64 } 65 66 @Override setInsets(Rect insets)67 public void setInsets(Rect insets) { 68 // If the insets haven't changed, this is a no-op. Avoid unnecessary layout caused by 69 // modifying child layout params. 70 if (!insets.equals(mInsets)) { 71 super.setInsets(insets); 72 mSysUiScrim.onInsetsChanged(insets); 73 } 74 } 75 dispatchInsets()76 public void dispatchInsets() { 77 mActivity.getDeviceProfile().updateInsets(mInsets); 78 super.setInsets(mInsets); 79 } 80 setWindowStateListener(WindowStateListener listener)81 public void setWindowStateListener(WindowStateListener listener) { 82 mWindowStateListener = listener; 83 } 84 85 @Override onWindowFocusChanged(boolean hasWindowFocus)86 public void onWindowFocusChanged(boolean hasWindowFocus) { 87 super.onWindowFocusChanged(hasWindowFocus); 88 if (mWindowStateListener != null) { 89 mWindowStateListener.onWindowFocusChanged(hasWindowFocus); 90 } 91 } 92 93 @Override onWindowVisibilityChanged(int visibility)94 protected void onWindowVisibilityChanged(int visibility) { 95 super.onWindowVisibilityChanged(visibility); 96 if (mWindowStateListener != null) { 97 mWindowStateListener.onWindowVisibilityChanged(visibility); 98 } 99 } 100 101 @Override dispatchDraw(Canvas canvas)102 protected void dispatchDraw(Canvas canvas) { 103 mSysUiScrim.draw(canvas); 104 super.dispatchDraw(canvas); 105 } 106 107 @Override onLayout(boolean changed, int l, int t, int r, int b)108 protected void onLayout(boolean changed, int l, int t, int r, int b) { 109 super.onLayout(changed, l, t, r, b); 110 SYSTEM_GESTURE_EXCLUSION_RECT.get(0).set(l, t, r, b); 111 setDisallowBackGesture(mDisallowBackGesture); 112 mSysUiScrim.setSize(r - l, b - t); 113 } 114 115 @TargetApi(Build.VERSION_CODES.Q) setForceHideBackArrow(boolean forceHideBackArrow)116 public void setForceHideBackArrow(boolean forceHideBackArrow) { 117 this.mForceHideBackArrow = forceHideBackArrow; 118 setDisallowBackGesture(mDisallowBackGesture); 119 } 120 121 @TargetApi(Build.VERSION_CODES.Q) setDisallowBackGesture(boolean disallowBackGesture)122 public void setDisallowBackGesture(boolean disallowBackGesture) { 123 if (!Utilities.ATLEAST_Q || SEPARATE_RECENTS_ACTIVITY.get()) { 124 return; 125 } 126 mDisallowBackGesture = disallowBackGesture; 127 setSystemGestureExclusionRects((mForceHideBackArrow || mDisallowBackGesture) 128 ? SYSTEM_GESTURE_EXCLUSION_RECT 129 : Collections.emptyList()); 130 } 131 getSysUiScrim()132 public SysUiScrim getSysUiScrim() { 133 return mSysUiScrim; 134 } 135 136 public interface WindowStateListener { 137 onWindowFocusChanged(boolean hasFocus)138 void onWindowFocusChanged(boolean hasFocus); 139 onWindowVisibilityChanged(int visibility)140 void onWindowVisibilityChanged(int visibility); 141 } 142 } 143