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