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