• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.server.wm;
18 
19 import static android.view.PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW;
20 import static android.view.PointerIcon.TYPE_NOT_SPECIFIED;
21 import static android.view.PointerIcon.TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW;
22 import static android.view.PointerIcon.TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW;
23 import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;
24 
25 import android.graphics.Rect;
26 import android.graphics.Region;
27 import android.hardware.input.InputManager;
28 import android.view.MotionEvent;
29 import android.view.WindowManagerPolicyConstants.PointerEventListener;
30 
31 import com.android.server.wm.WindowManagerService.H;
32 
33 /**
34  * 1. Adjust the top most focus display if touch down on some display.
35  * 2. Adjust the pointer icon when cursor moves to the task bounds.
36  */
37 public class TaskTapPointerEventListener implements PointerEventListener {
38 
39     private final Region mTouchExcludeRegion = new Region();
40     private final WindowManagerService mService;
41     private final DisplayContent mDisplayContent;
42     private final Rect mTmpRect = new Rect();
43     private int mPointerIconType = TYPE_NOT_SPECIFIED;
44 
TaskTapPointerEventListener(WindowManagerService service, DisplayContent displayContent)45     public TaskTapPointerEventListener(WindowManagerService service,
46             DisplayContent displayContent) {
47         mService = service;
48         mDisplayContent = displayContent;
49     }
50 
restorePointerIcon(int x, int y)51     private void restorePointerIcon(int x, int y) {
52         if (mPointerIconType != TYPE_NOT_SPECIFIED) {
53             mPointerIconType = TYPE_NOT_SPECIFIED;
54             // Find the underlying window and ask it to restore the pointer icon.
55             mService.mH.removeMessages(H.RESTORE_POINTER_ICON);
56             mService.mH.obtainMessage(H.RESTORE_POINTER_ICON,
57                     x, y, mDisplayContent).sendToTarget();
58         }
59     }
60 
61     @Override
onPointerEvent(MotionEvent motionEvent)62     public void onPointerEvent(MotionEvent motionEvent) {
63         switch (motionEvent.getActionMasked()) {
64             case MotionEvent.ACTION_DOWN: {
65                 final int x = (int) motionEvent.getX();
66                 final int y = (int) motionEvent.getY();
67 
68                 synchronized (this) {
69                     if (!mTouchExcludeRegion.contains(x, y)) {
70                         mService.mTaskPositioningController.handleTapOutsideTask(
71                                 mDisplayContent, x, y);
72                     }
73                 }
74             }
75             break;
76             case MotionEvent.ACTION_HOVER_ENTER:
77             case MotionEvent.ACTION_HOVER_MOVE: {
78                 final int x = (int) motionEvent.getX();
79                 final int y = (int) motionEvent.getY();
80                 if (mTouchExcludeRegion.contains(x, y)) {
81                     restorePointerIcon(x, y);
82                     break;
83                 }
84                 final Task task = mDisplayContent.findTaskForResizePoint(x, y);
85                 int iconType = TYPE_NOT_SPECIFIED;
86                 if (task != null) {
87                     task.getDimBounds(mTmpRect);
88                     if (!mTmpRect.isEmpty() && !mTmpRect.contains(x, y)) {
89                         if (x < mTmpRect.left) {
90                             iconType =
91                                 (y < mTmpRect.top) ? TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW :
92                                 (y > mTmpRect.bottom) ? TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW :
93                                 TYPE_HORIZONTAL_DOUBLE_ARROW;
94                         } else if (x > mTmpRect.right) {
95                             iconType =
96                                 (y < mTmpRect.top) ? TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW :
97                                 (y > mTmpRect.bottom) ? TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW :
98                                 TYPE_HORIZONTAL_DOUBLE_ARROW;
99                         } else if (y < mTmpRect.top || y > mTmpRect.bottom) {
100                             iconType = TYPE_VERTICAL_DOUBLE_ARROW;
101                         }
102                     }
103                 }
104                 if (mPointerIconType != iconType) {
105                     mPointerIconType = iconType;
106                     if (mPointerIconType == TYPE_NOT_SPECIFIED) {
107                         // Find the underlying window and ask it restore the pointer icon.
108                         mService.mH.removeMessages(H.RESTORE_POINTER_ICON);
109                         mService.mH.obtainMessage(H.RESTORE_POINTER_ICON,
110                                 x, y, mDisplayContent).sendToTarget();
111                     } else {
112                         InputManager.getInstance().setPointerIconType(mPointerIconType);
113                     }
114                 }
115             }
116             break;
117             case MotionEvent.ACTION_HOVER_EXIT: {
118                 final int x = (int) motionEvent.getX();
119                 final int y = (int) motionEvent.getY();
120                 restorePointerIcon(x, y);
121             }
122             break;
123         }
124     }
125 
setTouchExcludeRegion(Region newRegion)126     void setTouchExcludeRegion(Region newRegion) {
127         synchronized (this) {
128            mTouchExcludeRegion.set(newRegion);
129         }
130     }
131 }
132