blob: f26cfe872e8fe78f72f1258b6fd200569f3821ed [file] [log] [blame]
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 final SysUiScrim mSysUiScrim;
public LauncherRootView(Context context, AttributeSet attrs) {
super(context, attrs);
mActivity = StatefulActivity.fromContext(context);
mSysUiScrim = new SysUiScrim(this);
}
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);
mSysUiScrim.onInsetsChanged(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);
}
}
@Override
protected void dispatchDraw(Canvas canvas) {
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);
mSysUiScrim.setSize(r - l, b - t);
}
@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 SysUiScrim getSysUiScrim() {
return mSysUiScrim;
}
public interface WindowStateListener {
void onWindowFocusChanged(boolean hasFocus);
void onWindowVisibilityChanged(int visibility);
}
}