1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
19import android.graphics.Rect;
20import android.graphics.Region;
21import android.hardware.input.InputManager;
22import android.view.MotionEvent;
23import android.view.WindowManagerPolicy.PointerEventListener;
24
25import com.android.server.wm.WindowManagerService.H;
26
27import static android.view.PointerIcon.TYPE_NOT_SPECIFIED;
28import static android.view.PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW;
29import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;
30import static android.view.PointerIcon.TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW;
31import static android.view.PointerIcon.TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW;
32
33public class TaskTapPointerEventListener implements PointerEventListener {
34
35    final private Region mTouchExcludeRegion = new Region();
36    private final WindowManagerService mService;
37    private final DisplayContent mDisplayContent;
38    private final Rect mTmpRect = new Rect();
39    private int mPointerIconType = TYPE_NOT_SPECIFIED;
40
41    public TaskTapPointerEventListener(WindowManagerService service,
42            DisplayContent displayContent) {
43        mService = service;
44        mDisplayContent = displayContent;
45    }
46
47    @Override
48    public void onPointerEvent(MotionEvent motionEvent) {
49        final int action = motionEvent.getAction();
50        switch (action & MotionEvent.ACTION_MASK) {
51            case MotionEvent.ACTION_DOWN: {
52                final int x = (int) motionEvent.getX();
53                final int y = (int) motionEvent.getY();
54
55                synchronized (this) {
56                    if (!mTouchExcludeRegion.contains(x, y)) {
57                        mService.mH.obtainMessage(H.TAP_OUTSIDE_TASK,
58                                x, y, mDisplayContent).sendToTarget();
59                    }
60                }
61            }
62            break;
63
64            case MotionEvent.ACTION_HOVER_MOVE: {
65                final int x = (int) motionEvent.getX();
66                final int y = (int) motionEvent.getY();
67                final Task task = mDisplayContent.findTaskForResizePoint(x, y);
68                int iconType = TYPE_NOT_SPECIFIED;
69                if (task != null) {
70                    task.getDimBounds(mTmpRect);
71                    if (!mTmpRect.isEmpty() && !mTmpRect.contains(x, y)) {
72                        if (x < mTmpRect.left) {
73                            iconType =
74                                (y < mTmpRect.top) ? TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW :
75                                (y > mTmpRect.bottom) ? TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW :
76                                TYPE_HORIZONTAL_DOUBLE_ARROW;
77                        } else if (x > mTmpRect.right) {
78                            iconType =
79                                (y < mTmpRect.top) ? TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW :
80                                (y > mTmpRect.bottom) ? TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW :
81                                TYPE_HORIZONTAL_DOUBLE_ARROW;
82                        } else if (y < mTmpRect.top || y > mTmpRect.bottom) {
83                            iconType = TYPE_VERTICAL_DOUBLE_ARROW;
84                        }
85                    }
86                }
87                if (mPointerIconType != iconType) {
88                    mPointerIconType = iconType;
89                    if (mPointerIconType == TYPE_NOT_SPECIFIED) {
90                        // Find the underlying window and ask it restore the pointer icon.
91                        mService.mH.obtainMessage(H.RESTORE_POINTER_ICON,
92                                x, y, mDisplayContent).sendToTarget();
93                    } else {
94                        InputManager.getInstance().setPointerIconType(mPointerIconType);
95                    }
96                }
97            }
98            break;
99        }
100    }
101
102    void setTouchExcludeRegion(Region newRegion) {
103        synchronized (this) {
104           mTouchExcludeRegion.set(newRegion);
105        }
106    }
107}
108