| package com.android.launcher3; |
| |
| import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY; |
| |
| import android.annotation.TargetApi; |
| import android.content.Context; |
| import android.graphics.Canvas; |
| import android.graphics.Rect; |
| import android.os.Build; |
| import android.util.AttributeSet; |
| import android.view.ViewDebug; |
| import android.view.WindowInsets; |
| |
| import com.android.launcher3.graphics.SysUiScrim; |
| import com.android.launcher3.statemanager.StatefulActivity; |
| |
| import java.util.Collections; |
| import java.util.List; |
| |
| public class LauncherRootView extends InsettableFrameLayout { |
| |
| private final Rect mTempRect = new Rect(); |
| |
| private final StatefulActivity mActivity; |
| |
| @ViewDebug.ExportedProperty(category = "launcher") |
| private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT = |
| Collections.singletonList(new Rect()); |
| |
| private WindowStateListener mWindowStateListener; |
| @ViewDebug.ExportedProperty(category = "launcher") |
| private boolean mDisallowBackGesture; |
| @ViewDebug.ExportedProperty(category = "launcher") |
| private boolean mForceHideBackArrow; |
| |
| private SysUiScrim mSysUiScrim; |
| |
| public LauncherRootView(Context context, AttributeSet attrs) { |
| super(context, attrs); |
| mActivity = StatefulActivity.fromContext(context); |
| } |
| |
| private void handleSystemWindowInsets(Rect insets) { |
| DeviceProfile dp = mActivity.getDeviceProfile(); |
| |
| // Taskbar provides insets, but we don't want that for most Launcher elements so remove it. |
| mTempRect.set(insets); |
| insets = mTempRect; |
| insets.bottom = Math.max(0, insets.bottom - dp.nonOverlappingTaskbarInset); |
| |
| // Update device profile before notifying the children. |
| dp.updateInsets(insets); |
| boolean resetState = !insets.equals(mInsets); |
| setInsets(insets); |
| |
| if (resetState) { |
| mActivity.getStateManager().reapplyState(true /* cancelCurrentAnimation */); |
| } |
| } |
| |
| @Override |
| public WindowInsets onApplyWindowInsets(WindowInsets insets) { |
| mTempRect.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), |
| insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom()); |
| handleSystemWindowInsets(mTempRect); |
| return insets; |
| } |
| |
| @Override |
| public void setInsets(Rect insets) { |
| // If the insets haven't changed, this is a no-op. Avoid unnecessary layout caused by |
| // modifying child layout params. |
| if (!insets.equals(mInsets)) { |
| super.setInsets(insets); |
| } |
| } |
| |
| public void dispatchInsets() { |
| mActivity.getDeviceProfile().updateInsets(mInsets); |
| super.setInsets(mInsets); |
| } |
| |
| public void setWindowStateListener(WindowStateListener listener) { |
| mWindowStateListener = listener; |
| } |
| |
| @Override |
| public void onWindowFocusChanged(boolean hasWindowFocus) { |
| super.onWindowFocusChanged(hasWindowFocus); |
| if (mWindowStateListener != null) { |
| mWindowStateListener.onWindowFocusChanged(hasWindowFocus); |
| } |
| } |
| |
| @Override |
| protected void onWindowVisibilityChanged(int visibility) { |
| super.onWindowVisibilityChanged(visibility); |
| if (mWindowStateListener != null) { |
| mWindowStateListener.onWindowVisibilityChanged(visibility); |
| } |
| } |
| |
| public void setSysUiScrim(SysUiScrim scrim) { |
| mSysUiScrim = scrim; |
| } |
| |
| @Override |
| protected void dispatchDraw(Canvas canvas) { |
| if (mSysUiScrim != null) { |
| mSysUiScrim.draw(canvas); |
| } |
| super.dispatchDraw(canvas); |
| } |
| |
| @Override |
| protected void onLayout(boolean changed, int l, int t, int r, int b) { |
| super.onLayout(changed, l, t, r, b); |
| SYSTEM_GESTURE_EXCLUSION_RECT.get(0).set(l, t, r, b); |
| setDisallowBackGesture(mDisallowBackGesture); |
| } |
| |
| @TargetApi(Build.VERSION_CODES.Q) |
| public void setForceHideBackArrow(boolean forceHideBackArrow) { |
| this.mForceHideBackArrow = forceHideBackArrow; |
| setDisallowBackGesture(mDisallowBackGesture); |
| } |
| |
| @TargetApi(Build.VERSION_CODES.Q) |
| public void setDisallowBackGesture(boolean disallowBackGesture) { |
| if (!Utilities.ATLEAST_Q || SEPARATE_RECENTS_ACTIVITY.get()) { |
| return; |
| } |
| mDisallowBackGesture = disallowBackGesture; |
| setSystemGestureExclusionRects((mForceHideBackArrow || mDisallowBackGesture) |
| ? SYSTEM_GESTURE_EXCLUSION_RECT |
| : Collections.emptyList()); |
| } |
| |
| public interface WindowStateListener { |
| |
| void onWindowFocusChanged(boolean hasFocus); |
| |
| void onWindowVisibilityChanged(int visibility); |
| } |
| } |