content: /*
   * Copyright (C) 2013 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.android.server.wm;
  
  import static android.view.PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW;
  import static android.view.PointerIcon.TYPE_NOT_SPECIFIED;
  import static android.view.PointerIcon.TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW;
  import static android.view.PointerIcon.TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW;
  import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;
  
  import android.graphics.Rect;
  import android.graphics.Region;
  import android.hardware.input.InputManager;
  import android.view.MotionEvent;
  import android.view.WindowManagerPolicyConstants.PointerEventListener;
  
  import com.android.server.wm.WindowManagerService.H;
  
  /**
   * 1. Adjust the top most focus display if touch down on some display.
   * 2. Adjust the pointer icon when cursor moves to the task bounds.
   */
  public class TaskTapPointerEventListener implements PointerEventListener {
  
      private final Region mTouchExcludeRegion = new Region();
      private final WindowManagerService mService;
      private final DisplayContent mDisplayContent;
      private final Rect mTmpRect = new Rect();
      private int mPointerIconType = TYPE_NOT_SPECIFIED;
  
      public TaskTapPointerEventListener(WindowManagerService service,
              DisplayContent displayContent) {
          mService = service;
          mDisplayContent = displayContent;
      }
  
      @Override
      public void onPointerEvent(MotionEvent motionEvent) {
          switch (motionEvent.getActionMasked()) {
              case MotionEvent.ACTION_DOWN: {
                  final int x = (int) motionEvent.getX();
                  final int y = (int) motionEvent.getY();
  
                  synchronized (this) {
                      if (!mTouchExcludeRegion.contains(x, y)) {
                          mService.mTaskPositioningController.handleTapOutsideTask(
                                  mDisplayContent, x, y);
                      }
                  }
              }
              break;
              case MotionEvent.ACTION_HOVER_ENTER:
              case MotionEvent.ACTION_HOVER_MOVE: {
                  final int x = (int) motionEvent.getX();
                  final int y = (int) motionEvent.getY();
                  final Task task = mDisplayContent.findTaskForResizePoint(x, y);
                  int iconType = TYPE_NOT_SPECIFIED;
                  if (task != null) {
                      task.getDimBounds(mTmpRect);
                      if (!mTmpRect.isEmpty() && !mTmpRect.contains(x, y)) {
                          if (x < mTmpRect.left) {
                              iconType =
                                  (y < mTmpRect.top) ? TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW :
                                  (y > mTmpRect.bottom) ? TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW :
                                  TYPE_HORIZONTAL_DOUBLE_ARROW;
                          } else if (x > mTmpRect.right) {
                              iconType =
                                  (y < mTmpRect.top) ? TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW :
                                  (y > mTmpRect.bottom) ? TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW :
                                  TYPE_HORIZONTAL_DOUBLE_ARROW;
                          } else if (y < mTmpRect.top || y > mTmpRect.bottom) {
                              iconType = TYPE_VERTICAL_DOUBLE_ARROW;
                          }
                      }
                  }
                  if (mPointerIconType != iconType) {
                      mPointerIconType = iconType;
                      if (mPointerIconType == TYPE_NOT_SPECIFIED) {
                          // Find the underlying window and ask it restore the pointer icon.
                          mService.mH.removeMessages(H.RESTORE_POINTER_ICON);
                          mService.mH.obtainMessage(H.RESTORE_POINTER_ICON,
                                  x, y, mDisplayContent).sendToTarget();
                      } else {
                          InputManager.getInstance().setPointerIconType(mPointerIconType);
                      }
                  }
              }
              break;
              case MotionEvent.ACTION_HOVER_EXIT: {
                  final int x = (int) motionEvent.getX();
                  final int y = (int) motionEvent.getY();
                  if (mPointerIconType != TYPE_NOT_SPECIFIED) {
                      mPointerIconType = TYPE_NOT_SPECIFIED;
                      // Find the underlying window and ask it to restore the pointer icon.
                      mService.mH.removeMessages(H.RESTORE_POINTER_ICON);
                      mService.mH.obtainMessage(H.RESTORE_POINTER_ICON,
                              x, y, mDisplayContent).sendToTarget();
                  }
              }
              break;
          }
      }
  
      void setTouchExcludeRegion(Region newRegion) {
          synchronized (this) {
             mTouchExcludeRegion.set(newRegion);
          }
      }
  }
  