1b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird/*
2b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird * Copyright (C) 2017 The Android Open Source Project
3b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird *
4b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird * Licensed under the Apache License, Version 2.0 (the "License");
5b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird * you may not use this file except in compliance with the License.
6b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird * You may obtain a copy of the License at
7b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird *
8b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird *      http://www.apache.org/licenses/LICENSE-2.0
9b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird *
10b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird * Unless required by applicable law or agreed to in writing, software
11b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird * distributed under the License is distributed on an "AS IS" BASIS,
12b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird * See the License for the specific language governing permissions and
14b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird * limitations under the License.
15b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird */
16b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird
17b0506ca83c43837d58461be5b9117a6808a4cae4Evan Lairdpackage com.android.systemui;
18b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird
19b0506ca83c43837d58461be5b9117a6808a4cae4Evan Lairdimport android.content.Context;
20b0506ca83c43837d58461be5b9117a6808a4cae4Evan Lairdimport android.graphics.Region;
21b0506ca83c43837d58461be5b9117a6808a4cae4Evan Lairdimport android.graphics.Region.Op;
22b0506ca83c43837d58461be5b9117a6808a4cae4Evan Lairdimport android.util.AttributeSet;
23b0506ca83c43837d58461be5b9117a6808a4cae4Evan Lairdimport android.view.View;
24b0506ca83c43837d58461be5b9117a6808a4cae4Evan Lairdimport android.view.ViewTreeObserver;
25b0506ca83c43837d58461be5b9117a6808a4cae4Evan Lairdimport android.view.ViewTreeObserver.InternalInsetsInfo;
26b0506ca83c43837d58461be5b9117a6808a4cae4Evan Lairdimport android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
27b0506ca83c43837d58461be5b9117a6808a4cae4Evan Lairdimport android.widget.FrameLayout;
28b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird
29b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird/**
30b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird * Frame layout that will intercept the touches of children if they want to
31b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird */
32b0506ca83c43837d58461be5b9117a6808a4cae4Evan Lairdpublic class RegionInterceptingFrameLayout extends FrameLayout {
33b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird    public RegionInterceptingFrameLayout(Context context) {
34b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird        super(context);
35b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird    }
36b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird
37b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird    public RegionInterceptingFrameLayout(Context context, AttributeSet attrs) {
38b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird        super(context, attrs);
39b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird    }
40b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird
41b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird    public RegionInterceptingFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
42b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird        super(context, attrs, defStyleAttr);
43b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird    }
44b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird
45b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird    public RegionInterceptingFrameLayout(Context context, AttributeSet attrs, int defStyleAttr,
46b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird            int defStyleRes) {
47b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird        super(context, attrs, defStyleAttr, defStyleRes);
48b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird    }
49b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird
50b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird    @Override
51b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird    protected void onAttachedToWindow() {
52b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird        super.onAttachedToWindow();
53b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird        getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsListener);
54b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird    }
55b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird
56b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird    @Override
57b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird    protected void onDetachedFromWindow() {
58b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird        super.onDetachedFromWindow();
59b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird        getViewTreeObserver().removeOnComputeInternalInsetsListener(mInsetsListener);
60b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird    }
61b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird
62b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird    private final OnComputeInternalInsetsListener mInsetsListener = internalInsetsInfo -> {
63b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird        internalInsetsInfo.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
64b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird        internalInsetsInfo.touchableRegion.setEmpty();
65b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird        for (int i = 0; i < getChildCount(); i++) {
66b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird            View child = getChildAt(i);
67b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird            if (!(child instanceof RegionInterceptableView)) {
68b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird                continue;
69b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird            }
70b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird            RegionInterceptableView riv = (RegionInterceptableView) child;
71b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird            if (!riv.shouldInterceptTouch()) {
72b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird                continue;
73b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird            }
74b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird            Region unionRegion = riv.getInterceptRegion();
75b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird            if (unionRegion == null) {
76b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird                continue;
77b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird            }
78b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird
79b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird            internalInsetsInfo.touchableRegion.op(riv.getInterceptRegion(), Op.UNION);
80b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird        }
81b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird    };
82b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird
83b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird    public interface RegionInterceptableView {
84b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird        default public boolean shouldInterceptTouch() {
85b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird            return false;
86b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird        }
87b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird
88b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird        public Region getInterceptRegion();
89b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird    }
90b0506ca83c43837d58461be5b9117a6808a4cae4Evan Laird}
91