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