1a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev/*
2a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev * Copyright (C) 2017 The Android Open Source Project
3a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev *
4a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev * Licensed under the Apache License, Version 2.0 (the "License");
5a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev * you may not use this file except in compliance with the License.
6a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev * You may obtain a copy of the License at
7a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev *
8a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev *      http://www.apache.org/licenses/LICENSE-2.0
9a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev *
10a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev * Unless required by applicable law or agreed to in writing, software
11a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev * distributed under the License is distributed on an "AS IS" BASIS,
12a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev * See the License for the specific language governing permissions and
14a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev * limitations under the License.
15a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev */
16a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.appcompat.widget;
18a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
19ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
20a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
21a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheevimport android.app.Activity;
22a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheevimport android.content.Context;
23a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheevimport android.content.ContextWrapper;
24a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheevimport android.content.res.Resources;
25a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheevimport android.graphics.PixelFormat;
26a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheevimport android.graphics.Rect;
27a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheevimport android.util.DisplayMetrics;
28a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheevimport android.util.Log;
29a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheevimport android.view.Gravity;
30a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheevimport android.view.LayoutInflater;
31a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheevimport android.view.View;
32b607c1d938533c862a0470eda3ffc25ecc8101d9Vladislav Kaznacheevimport android.view.ViewGroup;
33a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheevimport android.view.WindowManager;
34a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheevimport android.widget.TextView;
35a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
363de8a4e8305507475d7890205184946a25cf45e7Aurimas Liutikasimport androidx.annotation.RestrictTo;
373de8a4e8305507475d7890205184946a25cf45e7Aurimas Liutikasimport androidx.appcompat.R;
383de8a4e8305507475d7890205184946a25cf45e7Aurimas Liutikas
39a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev/**
40a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev * A popup window displaying a text message aligned to a specified view.
41a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev *
42a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev * @hide
43a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev */
44a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev@RestrictTo(LIBRARY_GROUP)
45a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheevclass TooltipPopup {
46a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    private static final String TAG = "TooltipPopup";
47a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
48a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    private final Context mContext;
49a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
50a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    private final View mContentView;
51a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    private final TextView mMessageView;
52a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
53a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    private final WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams();
54a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    private final Rect mTmpDisplayFrame = new Rect();
55a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    private final int[] mTmpAnchorPos = new int[2];
56a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    private final int[] mTmpAppPos = new int[2];
57a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
58a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    TooltipPopup(Context context) {
59a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        mContext = context;
60a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
617e4cce488592095f820da1bdf70497bb84b808f8Vladislav Kaznacheev        mContentView = LayoutInflater.from(mContext).inflate(R.layout.abc_tooltip, null);
62a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        mMessageView = (TextView) mContentView.findViewById(R.id.message);
63a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
64a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        mLayoutParams.setTitle(getClass().getSimpleName());
65a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        mLayoutParams.packageName = mContext.getPackageName();
66a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
67a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
68a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
69a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        mLayoutParams.format = PixelFormat.TRANSLUCENT;
70a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        mLayoutParams.windowAnimations = R.style.Animation_AppCompat_Tooltip;
71a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
72a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
73a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    }
74a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
75a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    void show(View anchorView, int anchorX, int anchorY, boolean fromTouch,
76a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            CharSequence tooltipText) {
77a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        if (isShowing()) {
78a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            hide();
79a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        }
80a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
81a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        mMessageView.setText(tooltipText);
82a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
83a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        computePosition(anchorView, anchorX, anchorY, fromTouch, mLayoutParams);
84a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
85a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
86a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        wm.addView(mContentView, mLayoutParams);
87a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    }
88a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
89a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    void hide() {
90a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        if (!isShowing()) {
91a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            return;
92a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        }
93a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
94a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
95a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        wm.removeView(mContentView);
96a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    }
97a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
98a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    boolean isShowing() {
99a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        return mContentView.getParent() != null;
100a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    }
101a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
102a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    private void computePosition(View anchorView, int anchorX, int anchorY, boolean fromTouch,
103a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            WindowManager.LayoutParams outParams) {
104b607c1d938533c862a0470eda3ffc25ecc8101d9Vladislav Kaznacheev        outParams.token = anchorView.getApplicationWindowToken();
105a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        final int tooltipPreciseAnchorThreshold = mContext.getResources().getDimensionPixelOffset(
106a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev                R.dimen.tooltip_precise_anchor_threshold);
107a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
108a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        final int offsetX;
109a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        if (anchorView.getWidth() >= tooltipPreciseAnchorThreshold) {
110a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            // Wide view. Align the tooltip horizontally to the precise X position.
111a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            offsetX = anchorX;
112a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        } else {
113a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            // Otherwise anchor the tooltip to the view center.
114a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            offsetX = anchorView.getWidth() / 2;  // Center on the view horizontally.
115a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        }
116a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
117a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        final int offsetBelow;
118a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        final int offsetAbove;
119a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        if (anchorView.getHeight() >= tooltipPreciseAnchorThreshold) {
120a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            // Tall view. Align the tooltip vertically to the precise Y position.
121a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            final int offsetExtra = mContext.getResources().getDimensionPixelOffset(
122a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev                    R.dimen.tooltip_precise_anchor_extra_offset);
123a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            offsetBelow = anchorY + offsetExtra;
124a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            offsetAbove = anchorY - offsetExtra;
125a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        } else {
126a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            // Otherwise anchor the tooltip to the view center.
127a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            offsetBelow = anchorView.getHeight();  // Place below the view in most cases.
128a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            offsetAbove = 0;  // Place above the view if the tooltip does not fit below.
129a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        }
130a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
131a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        outParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
132a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
133a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        final int tooltipOffset = mContext.getResources().getDimensionPixelOffset(
134a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev                fromTouch ? R.dimen.tooltip_y_offset_touch : R.dimen.tooltip_y_offset_non_touch);
135a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
136a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        final View appView = getAppRootView(anchorView);
137a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        if (appView == null) {
138a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            Log.e(TAG, "Cannot find app view");
139a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            return;
140a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        }
141a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        appView.getWindowVisibleDisplayFrame(mTmpDisplayFrame);
142a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        if (mTmpDisplayFrame.left < 0 && mTmpDisplayFrame.top < 0) {
143a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            // No meaningful display frame, the anchor view is probably in a subpanel
144a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            // (such as a popup window). Use the screen frame as a reasonable approximation.
145a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            final Resources res = mContext.getResources();
146a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            final int statusBarHeight;
147a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            int resourceId = res.getIdentifier("status_bar_height", "dimen", "android");
14827498b224061104ba9f5f388c7c838cf0bee4af4Adam Lesinski            if (resourceId != 0) {
149a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev                statusBarHeight = res.getDimensionPixelSize(resourceId);
150a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            } else {
151a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev                statusBarHeight = 0;
152a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            }
153a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            final DisplayMetrics metrics = res.getDisplayMetrics();
154a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            mTmpDisplayFrame.set(0, statusBarHeight, metrics.widthPixels, metrics.heightPixels);
155a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        }
156a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        appView.getLocationOnScreen(mTmpAppPos);
157a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
158a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        anchorView.getLocationOnScreen(mTmpAnchorPos);
159a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        mTmpAnchorPos[0] -= mTmpAppPos[0];
160a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        mTmpAnchorPos[1] -= mTmpAppPos[1];
161a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        // mTmpAnchorPos is now relative to the main app window.
162a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
163b607c1d938533c862a0470eda3ffc25ecc8101d9Vladislav Kaznacheev        outParams.x = mTmpAnchorPos[0] + offsetX - appView.getWidth() / 2;
164a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
165a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        final int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
166a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        mContentView.measure(spec, spec);
167a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        final int tooltipHeight = mContentView.getMeasuredHeight();
168a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
169a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        final int yAbove = mTmpAnchorPos[1] + offsetAbove - tooltipOffset - tooltipHeight;
170a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        final int yBelow = mTmpAnchorPos[1] + offsetBelow + tooltipOffset;
171a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        if (fromTouch) {
172a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            if (yAbove >= 0) {
173a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev                outParams.y = yAbove;
174a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            } else {
175a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev                outParams.y = yBelow;
176a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            }
177a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        } else {
178a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            if (yBelow + tooltipHeight <= mTmpDisplayFrame.height()) {
179a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev                outParams.y = yBelow;
180a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            } else {
181a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev                outParams.y = yAbove;
182a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            }
183a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        }
184a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    }
185a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev
186a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    private static View getAppRootView(View anchorView) {
187b607c1d938533c862a0470eda3ffc25ecc8101d9Vladislav Kaznacheev        View rootView = anchorView.getRootView();
188b607c1d938533c862a0470eda3ffc25ecc8101d9Vladislav Kaznacheev        ViewGroup.LayoutParams lp = rootView.getLayoutParams();
189b607c1d938533c862a0470eda3ffc25ecc8101d9Vladislav Kaznacheev        if (lp instanceof WindowManager.LayoutParams
190b607c1d938533c862a0470eda3ffc25ecc8101d9Vladislav Kaznacheev                && (((WindowManager.LayoutParams) lp).type
191b607c1d938533c862a0470eda3ffc25ecc8101d9Vladislav Kaznacheev                    == WindowManager.LayoutParams.TYPE_APPLICATION)) {
192b607c1d938533c862a0470eda3ffc25ecc8101d9Vladislav Kaznacheev            // This covers regular app windows and Dialog windows.
193b607c1d938533c862a0470eda3ffc25ecc8101d9Vladislav Kaznacheev            return rootView;
194b607c1d938533c862a0470eda3ffc25ecc8101d9Vladislav Kaznacheev        }
195b607c1d938533c862a0470eda3ffc25ecc8101d9Vladislav Kaznacheev        // For non-application window types (such as popup windows) try to find the main app window
196b607c1d938533c862a0470eda3ffc25ecc8101d9Vladislav Kaznacheev        // through the context.
197a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        Context context = anchorView.getContext();
198a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        while (context instanceof ContextWrapper) {
199a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            if (context instanceof Activity) {
200a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev                return ((Activity) context).getWindow().getDecorView();
201a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            } else {
202a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev                context = ((ContextWrapper) context).getBaseContext();
203a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev            }
204a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev        }
205b607c1d938533c862a0470eda3ffc25ecc8101d9Vladislav Kaznacheev        // Main app window not found, fall back to the anchor's root view. There is no guarantee
206b607c1d938533c862a0470eda3ffc25ecc8101d9Vladislav Kaznacheev        // that the tooltip position will be computed correctly.
207b607c1d938533c862a0470eda3ffc25ecc8101d9Vladislav Kaznacheev        return rootView;
208a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev    }
209a4c6825b4b077cb12adb4f14b825001b6fd0e865Vladislav Kaznacheev}
210