Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0506ca8 authored by Evan Laird's avatar Evan Laird
Browse files

Intercept touches in the emulated DisplayCutout

Added a RegionInterceptingFrameLayout that can add the regions of its
children to the touchable region of the inernal insets, and added
DisplayCutoutView as a RegionInterceptableView child.

Test: taps inside the DisplayCutout view do nothing
Change-Id: I86120b39084da2b686d9954b4b16ea94efbd0f95
Fixes: 74946584
parent 8506821d
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@
** See the License for the specific language governing permissions and
** limitations under the License.
-->
<FrameLayout
<com.android.systemui.RegionInterceptingFrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
@@ -32,4 +32,4 @@
        android:tint="#ff000000"
        android:layout_gravity="right|bottom"
        android:src="@drawable/rounded" />
</FrameLayout>
</com.android.systemui.RegionInterceptingFrameLayout>
+90 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui;

import android.content.Context;
import android.graphics.Region;
import android.graphics.Region.Op;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.InternalInsetsInfo;
import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
import android.widget.FrameLayout;

/**
 * Frame layout that will intercept the touches of children if they want to
 */
public class RegionInterceptingFrameLayout extends FrameLayout {
    public RegionInterceptingFrameLayout(Context context) {
        super(context);
    }

    public RegionInterceptingFrameLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public RegionInterceptingFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public RegionInterceptingFrameLayout(Context context, AttributeSet attrs, int defStyleAttr,
            int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsListener);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        getViewTreeObserver().removeOnComputeInternalInsetsListener(mInsetsListener);
    }

    private final OnComputeInternalInsetsListener mInsetsListener = internalInsetsInfo -> {
        internalInsetsInfo.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
        internalInsetsInfo.touchableRegion.setEmpty();
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            if (!(child instanceof RegionInterceptableView)) {
                continue;
            }
            RegionInterceptableView riv = (RegionInterceptableView) child;
            if (!riv.shouldInterceptTouch()) {
                continue;
            }
            Region unionRegion = riv.getInterceptRegion();
            if (unionRegion == null) {
                continue;
            }

            internalInsetsInfo.touchableRegion.op(riv.getInterceptRegion(), Op.UNION);
        }
    };

    public interface RegionInterceptableView {
        default public boolean shouldInterceptTouch() {
            return false;
        }

        public Region getInterceptRegion();
    }
}
+18 −3
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;

import com.android.systemui.RegionInterceptingFrameLayout.RegionInterceptableView;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
import com.android.systemui.plugins.qs.QS;
@@ -229,8 +230,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
                ViewGroup.LayoutParams.MATCH_PARENT,
                LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                        | WindowManager.LayoutParams.FLAG_SLIPPERY
@@ -309,7 +309,8 @@ public class ScreenDecorations extends SystemUI implements Tunable {
        }
    }

    public static class DisplayCutoutView extends View implements DisplayManager.DisplayListener {
    public static class DisplayCutoutView extends View implements DisplayManager.DisplayListener,
            RegionInterceptableView {

        private final DisplayInfo mInfo = new DisplayInfo();
        private final Paint mPaint = new Paint();
@@ -459,5 +460,19 @@ public class ScreenDecorations extends SystemUI implements Tunable {
                }
            }
        }

        @Override
        public boolean shouldInterceptTouch() {
            return mInfo.displayCutout != null && getVisibility() == VISIBLE;
        }

        @Override
        public Region getInterceptRegion() {
            if (mInfo.displayCutout == null) {
                return null;
            }

            return mInfo.displayCutout.getBounds();
        }
    }
}