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