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