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