DecorCaptionView.java revision 3dec081967db3c0e906ff272d632618e260b6413
161b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne/*
261b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * Copyright (C) 2015 The Android Open Source Project
361b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne *
461b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * Licensed under the Apache License, Version 2.0 (the "License");
561b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * you may not use this file except in compliance with the License.
661b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * You may obtain a copy of the License at
761b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne *
861b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne *      http://www.apache.org/licenses/LICENSE-2.0
961b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne *
1061b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * Unless required by applicable law or agreed to in writing, software
1161b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * distributed under the License is distributed on an "AS IS" BASIS,
1261b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1361b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * See the License for the specific language governing permissions and
1461b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * limitations under the License.
1561b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne */
1661b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne
1761b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhnepackage com.android.internal.widget;
1861b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne
193797c22ea16e932329ebffdc7e7ce09f9ecd9545Wale Ogunwaleimport static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
203797c22ea16e932329ebffdc7e7ce09f9ecd9545Wale Ogunwale
2161b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhneimport android.content.Context;
22a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynskiimport android.graphics.Color;
23a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynskiimport android.graphics.Rect;
2461b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhneimport android.os.RemoteException;
2561b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhneimport android.util.AttributeSet;
26a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynskiimport android.util.Log;
27a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynskiimport android.view.GestureDetector;
2881c524a66480d44b51600abee24c28d66603f15eSkuhneimport android.view.MotionEvent;
2961b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhneimport android.view.View;
30a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynskiimport android.view.ViewConfiguration;
3161b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhneimport android.view.ViewGroup;
32f4dd71a2657d23d12d5fe6e5e1273aab65d80ca4Stefan Kuhneimport android.view.ViewOutlineProvider;
33f4dd71a2657d23d12d5fe6e5e1273aab65d80ca4Stefan Kuhneimport android.view.Window;
3461b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne
3561b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhneimport com.android.internal.R;
3661b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhneimport com.android.internal.policy.PhoneWindow;
3761b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne
38a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynskiimport java.util.ArrayList;
39a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski
4061b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne/**
4162a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale * This class represents the special screen elements to control a window on freeform
4262a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale * environment.
4361b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * As such this class handles the following things:
4461b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * <ul>
4561b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * <li>The caption, containing the system buttons like maximize, close and such as well as
4661b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * allowing the user to drag the window around.</li>
47a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * </ul>
48a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * After creating the view, the function {@link #setPhoneWindow} needs to be called to make
4961b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * the connection to it's owning PhoneWindow.
5061b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * Note: At this time the application can change various attributes of the DecorView which
5161b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * will break things (in settle/unexpected ways):
5261b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * <ul>
5361b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * <li>setOutlineProvider</li>
5461b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * <li>setSurfaceFormat</li>
5561b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * <li>..</li>
5661b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne * </ul>
57a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski *
58a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * Although this ViewGroup has only two direct sub-Views, its behavior is more complex due to
59a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * overlaying caption on the content and drawing.
60a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski *
61a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * First, no matter where the content View gets added, it will always be the first child and the
62a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * caption will be the second. This way the caption will always be drawn on top of the content when
63a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * overlaying is enabled.
64a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski *
65a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * Second, the touch dispatch is customized to handle overlaying. This is what happens when touch
66a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * is dispatched on the caption area while overlaying it on content:
67a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * <ul>
68a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * <li>DecorCaptionView.onInterceptTouchEvent() will try intercepting the touch events if the
69a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * down action is performed on top close or maximize buttons; the reason for that is we want these
70a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * buttons to always work.</li>
71a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * <li>The content View will receive the touch event. Mind that content is actually underneath the
72a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * caption, so we need to introduce our own dispatch ordering. We achieve this by overriding
73a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * {@link #buildTouchDispatchChildList()}.</li>
74a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * <li>If the touch event is not consumed by the content View, it will go to the caption View
75a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * and the dragging logic will be executed.</li>
76a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski * </ul>
7761b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne */
78a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynskipublic class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
79a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        GestureDetector.OnGestureListener {
8062a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale    private final static String TAG = "DecorCaptionView";
8161b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne    private PhoneWindow mOwner = null;
8262a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale    private boolean mShow = false;
8381c524a66480d44b51600abee24c28d66603f15eSkuhne
8481c524a66480d44b51600abee24c28d66603f15eSkuhne    // True if the window is being dragged.
8581c524a66480d44b51600abee24c28d66603f15eSkuhne    private boolean mDragging = false;
8681c524a66480d44b51600abee24c28d66603f15eSkuhne
8781c524a66480d44b51600abee24c28d66603f15eSkuhne    // True when the left mouse button got released while dragging.
8881c524a66480d44b51600abee24c28d66603f15eSkuhne    private boolean mLeftMouseButtonReleased;
8981c524a66480d44b51600abee24c28d66603f15eSkuhne
9063250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    private boolean mOverlayWithAppContent = false;
9163250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski
9263250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    private View mCaption;
9363250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    private View mContent;
94a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    private View mMaximize;
95a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    private View mClose;
96a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski
97a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    // Fields for detecting drag events.
98a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    private int mTouchDownX;
99a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    private int mTouchDownY;
100a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    private boolean mCheckForDragging;
101a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    private int mDragSlop;
102a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski
103a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    // Fields for detecting and intercepting click events on close/maximize.
104a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    private ArrayList<View> mTouchDispatchList = new ArrayList<>(2);
105a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    // We use the gesture detector to detect clicks on close/maximize buttons and to be consistent
106a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    // with existing click detection.
107a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    private GestureDetector mGestureDetector;
108a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    private final Rect mCloseRect = new Rect();
109a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    private final Rect mMaximizeRect = new Rect();
110a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    private View mClickTarget;
11163250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski
11262a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale    public DecorCaptionView(Context context) {
11361b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne        super(context);
114a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        init(context);
11561b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne    }
11661b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne
11762a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale    public DecorCaptionView(Context context, AttributeSet attrs) {
11861b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne        super(context, attrs);
119a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        init(context);
12061b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne    }
12161b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne
12262a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale    public DecorCaptionView(Context context, AttributeSet attrs, int defStyle) {
12361b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne        super(context, attrs, defStyle);
124a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        init(context);
125a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    }
126a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski
127a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    private void init(Context context) {
128a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        mDragSlop = ViewConfiguration.get(context).getScaledTouchSlop();
129a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        mGestureDetector = new GestureDetector(context, this);
13061b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne    }
13161b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne
13263250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    @Override
13363250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    protected void onFinishInflate() {
13463250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        super.onFinishInflate();
13563250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        mCaption = getChildAt(0);
13663250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    }
13763250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski
13862a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale    public void setPhoneWindow(PhoneWindow owner, boolean show) {
13961b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne        mOwner = owner;
14062a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale        mShow = show;
14163250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        mOverlayWithAppContent = owner.getOverlayDecorCaption();
142a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        if (mOverlayWithAppContent) {
143a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            // The caption is covering the content, so we make its background transparent to make
144a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            // the content visible.
145a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            mCaption.setBackgroundColor(Color.TRANSPARENT);
146a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        }
147f7b882c9c64418f1aacf4ffb73e8a3f92fed15deSkuhne        updateCaptionVisibility();
14861b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne        // By changing the outline provider to BOUNDS, the window can remove its
14961b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne        // background without removing the shadow.
15061b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne        mOwner.getDecorView().setOutlineProvider(ViewOutlineProvider.BOUNDS);
151a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        mMaximize = findViewById(R.id.maximize_window);
152a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        mClose = findViewById(R.id.close_window);
153a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    }
154b816087962aba0019b022303330f03b897b580edSkuhne
155a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    @Override
156a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    public boolean onInterceptTouchEvent(MotionEvent ev) {
157a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        // If the user starts touch on the maximize/close buttons, we immediately intercept, so
158a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        // that these buttons are always clickable.
159a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
160a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            final int x = (int) ev.getX();
161a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            final int y = (int) ev.getY();
162a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            if (mMaximizeRect.contains(x, y)) {
163a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski                mClickTarget = mMaximize;
164a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            }
165a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            if (mCloseRect.contains(x, y)) {
166a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski                mClickTarget = mClose;
167a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            }
168a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        }
169a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        return mClickTarget != null;
170a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    }
171a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski
172a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    @Override
173a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    public boolean onTouchEvent(MotionEvent event) {
174a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        if (mClickTarget != null) {
175a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            mGestureDetector.onTouchEvent(event);
176a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            final int action = event.getAction();
177a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
178a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski                mClickTarget = null;
179a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            }
180a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            return true;
181a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        }
182a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        return false;
18361b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne    }
18461b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne
18581c524a66480d44b51600abee24c28d66603f15eSkuhne    @Override
186509ea6b28576c9dd7766bfa4878159c21a971cebChong Zhang    public boolean onTouch(View v, MotionEvent e) {
18781c524a66480d44b51600abee24c28d66603f15eSkuhne        // Note: There are no mixed events. When a new device gets used (e.g. 1. Mouse, 2. touch)
18881c524a66480d44b51600abee24c28d66603f15eSkuhne        // the old input device events get cancelled first. So no need to remember the kind of
18981c524a66480d44b51600abee24c28d66603f15eSkuhne        // input device we are listening to.
190a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        final int x = (int) e.getX();
191a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        final int y = (int) e.getY();
19281c524a66480d44b51600abee24c28d66603f15eSkuhne        switch (e.getActionMasked()) {
19381c524a66480d44b51600abee24c28d66603f15eSkuhne            case MotionEvent.ACTION_DOWN:
19462a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale                if (!mShow) {
19562a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale                    // When there is no caption we should not react to anything.
196a635a26716d98af90e8f6fded34b28983cdb58eaSkuhne                    return false;
197a635a26716d98af90e8f6fded34b28983cdb58eaSkuhne                }
198a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski                // Checking for a drag action is started if we aren't dragging already and the
199a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski                // starting event is either a left mouse button or any other input device.
200a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski                if (((e.getToolType(e.getActionIndex()) != MotionEvent.TOOL_TYPE_MOUSE ||
201a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski                        (e.getButtonState() & MotionEvent.BUTTON_PRIMARY) != 0))) {
202a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski                    mCheckForDragging = true;
203a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski                    mTouchDownX = x;
204a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski                    mTouchDownY = y;
20581c524a66480d44b51600abee24c28d66603f15eSkuhne                }
20681c524a66480d44b51600abee24c28d66603f15eSkuhne                break;
20781c524a66480d44b51600abee24c28d66603f15eSkuhne
20881c524a66480d44b51600abee24c28d66603f15eSkuhne            case MotionEvent.ACTION_MOVE:
209a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski                if (!mDragging && mCheckForDragging && passedSlop(x, y)) {
210a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski                    mCheckForDragging = false;
211a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski                    mDragging = true;
212a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski                    mLeftMouseButtonReleased = false;
213a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski                    startMovingTask(e.getRawX(), e.getRawY());
214a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski                } else if (mDragging && !mLeftMouseButtonReleased) {
21581c524a66480d44b51600abee24c28d66603f15eSkuhne                    if (e.getToolType(e.getActionIndex()) == MotionEvent.TOOL_TYPE_MOUSE &&
21681c524a66480d44b51600abee24c28d66603f15eSkuhne                            (e.getButtonState() & MotionEvent.BUTTON_PRIMARY) == 0) {
21781c524a66480d44b51600abee24c28d66603f15eSkuhne                        // There is no separate mouse button up call and if the user mixes mouse
21881c524a66480d44b51600abee24c28d66603f15eSkuhne                        // button drag actions, we stop dragging once he releases the button.
21981c524a66480d44b51600abee24c28d66603f15eSkuhne                        mLeftMouseButtonReleased = true;
22081c524a66480d44b51600abee24c28d66603f15eSkuhne                        break;
22181c524a66480d44b51600abee24c28d66603f15eSkuhne                    }
22281c524a66480d44b51600abee24c28d66603f15eSkuhne                }
22381c524a66480d44b51600abee24c28d66603f15eSkuhne                break;
22481c524a66480d44b51600abee24c28d66603f15eSkuhne
22581c524a66480d44b51600abee24c28d66603f15eSkuhne            case MotionEvent.ACTION_UP:
22681c524a66480d44b51600abee24c28d66603f15eSkuhne            case MotionEvent.ACTION_CANCEL:
227a5a93eea9b696ad57c77b6855681a317865c565cSkuhne                if (!mDragging) {
228a5a93eea9b696ad57c77b6855681a317865c565cSkuhne                    break;
22981c524a66480d44b51600abee24c28d66603f15eSkuhne                }
230a5a93eea9b696ad57c77b6855681a317865c565cSkuhne                // Abort the ongoing dragging.
231a5a93eea9b696ad57c77b6855681a317865c565cSkuhne                mDragging = false;
232a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski                return !mCheckForDragging;
23381c524a66480d44b51600abee24c28d66603f15eSkuhne        }
234a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        return mDragging || mCheckForDragging;
235a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    }
236a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski
237a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    @Override
238a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    public ArrayList<View> buildTouchDispatchChildList() {
239a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        mTouchDispatchList.ensureCapacity(3);
240a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        if (mCaption != null) {
241a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            mTouchDispatchList.add(mCaption);
242a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        }
243a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        if (mContent != null) {
244a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            mTouchDispatchList.add(mContent);
245a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        }
246a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        return mTouchDispatchList;
247a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    }
248a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski
249a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    private boolean passedSlop(int x, int y) {
250a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        return Math.abs(x - mTouchDownX) > mDragSlop || Math.abs(y - mTouchDownY) > mDragSlop;
25181c524a66480d44b51600abee24c28d66603f15eSkuhne    }
25281c524a66480d44b51600abee24c28d66603f15eSkuhne
253f4dd71a2657d23d12d5fe6e5e1273aab65d80ca4Stefan Kuhne    /**
25462a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale     * The phone window configuration has changed and the caption needs to be updated.
25562a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale     * @param show True if the caption should be shown.
2562b547c3f30d3fdfd9b544972051a32b9aa4135cfWale Ogunwale     */
25762a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale    public void onConfigurationChanged(boolean show) {
25862a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale        mShow = show;
259f7b882c9c64418f1aacf4ffb73e8a3f92fed15deSkuhne        updateCaptionVisibility();
260f4dd71a2657d23d12d5fe6e5e1273aab65d80ca4Stefan Kuhne    }
261f4dd71a2657d23d12d5fe6e5e1273aab65d80ca4Stefan Kuhne
26261b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne    @Override
263f7b882c9c64418f1aacf4ffb73e8a3f92fed15deSkuhne    public void addView(View child, int index, ViewGroup.LayoutParams params) {
26463250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        if (!(params instanceof MarginLayoutParams)) {
26563250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski            throw new IllegalArgumentException(
26663250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski                    "params " + params + " must subclass MarginLayoutParams");
26763250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        }
268f4dd71a2657d23d12d5fe6e5e1273aab65d80ca4Stefan Kuhne        // Make sure that we never get more then one client area in our view.
26961b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne        if (index >= 2 || getChildCount() >= 2) {
27062a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale            throw new IllegalStateException("DecorCaptionView can only handle 1 client view");
27161b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne        }
27263250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        // To support the overlaying content in the caption, we need to put the content view as the
27363250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        // first child to get the right Z-Ordering.
27463250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        super.addView(child, 0, params);
27563250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        mContent = child;
27663250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    }
27763250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski
27863250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    @Override
27963250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
28063250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        final int captionHeight;
28163250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        if (mCaption.getVisibility() != View.GONE) {
28263250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski            measureChildWithMargins(mCaption, widthMeasureSpec, 0, heightMeasureSpec, 0);
28363250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski            captionHeight = mCaption.getMeasuredHeight();
28463250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        } else {
28563250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski            captionHeight = 0;
28663250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        }
28763250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        if (mContent != null) {
28863250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski            if (mOverlayWithAppContent) {
28963250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski                measureChildWithMargins(mContent, widthMeasureSpec, 0, heightMeasureSpec, 0);
29063250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski            } else {
29163250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski                measureChildWithMargins(mContent, widthMeasureSpec, 0, heightMeasureSpec,
29263250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski                        captionHeight);
29363250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski            }
29463250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        }
29563250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski
29663250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
29763250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski                MeasureSpec.getSize(heightMeasureSpec));
29861b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne    }
29961b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne
30063250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    @Override
30163250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
30263250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        final int captionHeight;
30363250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        if (mCaption.getVisibility() != View.GONE) {
30463250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski            mCaption.layout(0, 0, mCaption.getMeasuredWidth(), mCaption.getMeasuredHeight());
30563250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski            captionHeight = mCaption.getBottom() - mCaption.getTop();
306a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            mMaximize.getHitRect(mMaximizeRect);
307a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            mClose.getHitRect(mCloseRect);
30863250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        } else {
30963250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski            captionHeight = 0;
310a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            mMaximizeRect.setEmpty();
311a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            mCloseRect.setEmpty();
31263250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        }
31363250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski
31463250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        if (mContent != null) {
31563250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski            if (mOverlayWithAppContent) {
31663250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski                mContent.layout(0, 0, mContent.getMeasuredWidth(), mContent.getMeasuredHeight());
31763250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski            } else {
31863250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski                mContent.layout(0, captionHeight, mContent.getMeasuredWidth(),
31963250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski                        captionHeight + mContent.getMeasuredHeight());
32063250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski            }
32163250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        }
3223dec081967db3c0e906ff272d632618e260b6413Filip Gruszczynski
3233dec081967db3c0e906ff272d632618e260b6413Filip Gruszczynski        // This assumes that the caption bar is at the top.
3243dec081967db3c0e906ff272d632618e260b6413Filip Gruszczynski        mOwner.notifyRestrictedCaptionAreaCallback(mMaximize.getLeft(), mMaximize.getTop(),
3253dec081967db3c0e906ff272d632618e260b6413Filip Gruszczynski                mClose.getRight(), mClose.getBottom());
32663250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    }
327f4dd71a2657d23d12d5fe6e5e1273aab65d80ca4Stefan Kuhne    /**
328f4dd71a2657d23d12d5fe6e5e1273aab65d80ca4Stefan Kuhne     * Determine if the workspace is entirely covered by the window.
329f4dd71a2657d23d12d5fe6e5e1273aab65d80ca4Stefan Kuhne     * @return Returns true when the window is filling the entire screen/workspace.
330f4dd71a2657d23d12d5fe6e5e1273aab65d80ca4Stefan Kuhne     **/
33161b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne    private boolean isFillingScreen() {
33261b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne        return (0 != ((getWindowSystemUiVisibility() | getSystemUiVisibility()) &
33361b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne                (View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
33461b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne                        View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_LOW_PROFILE)));
33561b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne    }
33661b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne
337f4dd71a2657d23d12d5fe6e5e1273aab65d80ca4Stefan Kuhne    /**
338f7b882c9c64418f1aacf4ffb73e8a3f92fed15deSkuhne     * Updates the visibility of the caption.
339f7b882c9c64418f1aacf4ffb73e8a3f92fed15deSkuhne     **/
340f7b882c9c64418f1aacf4ffb73e8a3f92fed15deSkuhne    private void updateCaptionVisibility() {
34162a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale        // Don't show the caption if the window has e.g. entered full screen.
34262a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale        boolean invisible = isFillingScreen() || !mShow;
34363250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        mCaption.setVisibility(invisible ? GONE : VISIBLE);
34463250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        mCaption.setOnTouchListener(this);
34561b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne    }
3461b42057707dce8039326492e89a766f397043aa8Stefan Kuhne
347f4dd71a2657d23d12d5fe6e5e1273aab65d80ca4Stefan Kuhne    /**
348f4dd71a2657d23d12d5fe6e5e1273aab65d80ca4Stefan Kuhne     * Maximize the window by moving it to the maximized workspace stack.
349f4dd71a2657d23d12d5fe6e5e1273aab65d80ca4Stefan Kuhne     **/
3501b42057707dce8039326492e89a766f397043aa8Stefan Kuhne    private void maximizeWindow() {
351ce2faa5871e3bf5ec8407506df18bed209dd824cSkuhne        Window.WindowControllerCallback callback = mOwner.getWindowControllerCallback();
3521b42057707dce8039326492e89a766f397043aa8Stefan Kuhne        if (callback != null) {
3531b42057707dce8039326492e89a766f397043aa8Stefan Kuhne            try {
3543797c22ea16e932329ebffdc7e7ce09f9ecd9545Wale Ogunwale                callback.changeWindowStack(FULLSCREEN_WORKSPACE_STACK_ID);
3551b42057707dce8039326492e89a766f397043aa8Stefan Kuhne            } catch (RemoteException ex) {
3561b42057707dce8039326492e89a766f397043aa8Stefan Kuhne                Log.e(TAG, "Cannot change task workspace.");
3571b42057707dce8039326492e89a766f397043aa8Stefan Kuhne            }
3581b42057707dce8039326492e89a766f397043aa8Stefan Kuhne        }
3591b42057707dce8039326492e89a766f397043aa8Stefan Kuhne    }
3608cc5a74c9049423260a14e0ebb44a052ef8f4e2aWale Ogunwale
36162a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale    public boolean isCaptionShowing() {
36262a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale        return mShow;
3638cc5a74c9049423260a14e0ebb44a052ef8f4e2aWale Ogunwale    }
3648cc5a74c9049423260a14e0ebb44a052ef8f4e2aWale Ogunwale
36562a91d67cee99998c941c76ad1a61acf1bb40b77Wale Ogunwale    public int getCaptionHeight() {
36663250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        return (mCaption != null) ? mCaption.getHeight() : 0;
36763250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    }
36863250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski
36963250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    public void removeContentView() {
37063250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        if (mContent != null) {
37163250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski            removeView(mContent);
37263250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski            mContent = null;
37363250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        }
37463250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    }
37563250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski
37663250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    public View getCaption() {
37763250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        return mCaption;
37863250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    }
37963250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski
38063250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    @Override
38163250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    public LayoutParams generateLayoutParams(AttributeSet attrs) {
38263250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        return new MarginLayoutParams(getContext(), attrs);
38363250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    }
38463250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski
38563250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    @Override
38663250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    protected LayoutParams generateDefaultLayoutParams() {
38763250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        return new MarginLayoutParams(MarginLayoutParams.MATCH_PARENT,
38863250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski                MarginLayoutParams.MATCH_PARENT);
38963250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    }
39063250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski
39163250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    @Override
39263250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    protected LayoutParams generateLayoutParams(LayoutParams p) {
39363250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        return new MarginLayoutParams(p);
39463250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    }
39563250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski
39663250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    @Override
39763250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
39863250651ca4656fc1b9e9ffb9c48d481df80454dFilip Gruszczynski        return p instanceof MarginLayoutParams;
3998cc5a74c9049423260a14e0ebb44a052ef8f4e2aWale Ogunwale    }
400a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski
401a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    @Override
402a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    public boolean onDown(MotionEvent e) {
403a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        return false;
404a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    }
405a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski
406a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    @Override
407a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    public void onShowPress(MotionEvent e) {
408a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski
409a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    }
410a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski
411a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    @Override
412a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    public boolean onSingleTapUp(MotionEvent e) {
413a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        if (mClickTarget == mMaximize) {
414a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            maximizeWindow();
415a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        } else if (mClickTarget == mClose) {
416a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski            mOwner.dispatchOnWindowDismissed(true /*finishTask*/);
417a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        }
418a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        return true;
419a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    }
420a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski
421a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    @Override
422a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
423a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        return false;
424a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    }
425a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski
426a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    @Override
427a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    public void onLongPress(MotionEvent e) {
428a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski
429a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    }
430a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski
431a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    @Override
432a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
433a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski        return false;
434a33bdf372cf045aa55db841307c64d30a50ab60dFilip Gruszczynski    }
43561b47bb267dec696e1bb11f7c5eb6b9d2f4bd096Stefan Kuhne}
436