RecentsViewTouchHandler.java revision 2364f26dc24191e5bfbab45bc1bdf9babe13af80
1/* 2 * Copyright (C) 2014 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.systemui.recents.views; 18 19import android.content.res.Configuration; 20import android.graphics.Point; 21import android.view.MotionEvent; 22import com.android.systemui.recents.RecentsConfiguration; 23import com.android.systemui.recents.events.EventBus; 24import com.android.systemui.recents.events.ui.dragndrop.DragDockStateChangedEvent; 25import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent; 26import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent; 27import com.android.systemui.recents.misc.ReferenceCountedTrigger; 28import com.android.systemui.recents.model.Task; 29import com.android.systemui.recents.model.TaskStack; 30 31 32/** 33 * Represents the dock regions for each orientation. 34 */ 35class DockRegion { 36 public static TaskStack.DockState[] PHONE_LANDSCAPE = { 37 TaskStack.DockState.LEFT 38 }; 39 public static TaskStack.DockState[] PHONE_PORTRAIT = { 40 // We only allow docking to the top for now 41 TaskStack.DockState.TOP 42 }; 43 public static TaskStack.DockState[] TABLET_LANDSCAPE = { 44 TaskStack.DockState.LEFT 45 }; 46 public static TaskStack.DockState[] TABLET_PORTRAIT = PHONE_PORTRAIT; 47} 48 49/** 50 * Handles touch events for a RecentsView. 51 */ 52class RecentsViewTouchHandler { 53 54 private RecentsView mRv; 55 56 private Task mDragTask; 57 private TaskView mTaskView; 58 private DragView mDragView; 59 60 private Point mDownPos = new Point(); 61 private boolean mDragging; 62 private TaskStack.DockState mLastDockState = TaskStack.DockState.NONE; 63 64 public RecentsViewTouchHandler(RecentsView rv) { 65 mRv = rv; 66 } 67 68 /** 69 * Returns the preferred dock states for the current orientation. 70 */ 71 public TaskStack.DockState[] getDockStatesForCurrentOrientation() { 72 boolean isLandscape = mRv.getResources().getConfiguration().orientation == 73 Configuration.ORIENTATION_LANDSCAPE; 74 RecentsConfiguration config = RecentsConfiguration.getInstance(); 75 TaskStack.DockState[] dockStates = isLandscape ? 76 (config.isLargeScreen ? DockRegion.TABLET_LANDSCAPE : DockRegion.PHONE_LANDSCAPE) : 77 (config.isLargeScreen ? DockRegion.TABLET_PORTRAIT : DockRegion.PHONE_PORTRAIT); 78 return dockStates; 79 } 80 81 /** Touch preprocessing for handling below */ 82 public boolean onInterceptTouchEvent(MotionEvent ev) { 83 handleTouchEvent(ev); 84 return mDragging; 85 } 86 87 /** Handles touch events once we have intercepted them */ 88 public boolean onTouchEvent(MotionEvent ev) { 89 handleTouchEvent(ev); 90 return mDragging; 91 } 92 93 /**** Events ****/ 94 95 public final void onBusEvent(DragStartEvent event) { 96 mRv.getParent().requestDisallowInterceptTouchEvent(true); 97 mDragging = true; 98 mDragTask = event.task; 99 mTaskView = event.taskView; 100 mDragView = event.dragView; 101 102 float x = mDownPos.x - mDragView.getTopLeftOffset().x; 103 float y = mDownPos.y - mDragView.getTopLeftOffset().y; 104 mDragView.setTranslationX(x); 105 mDragView.setTranslationY(y); 106 } 107 108 public final void onBusEvent(DragEndEvent event) { 109 mDragging = false; 110 mDragTask = null; 111 mTaskView = null; 112 mDragView = null; 113 mLastDockState = TaskStack.DockState.NONE; 114 } 115 116 /** 117 * Handles dragging touch events 118 * @param ev 119 */ 120 private void handleTouchEvent(MotionEvent ev) { 121 boolean isLandscape = mRv.getResources().getConfiguration().orientation == 122 Configuration.ORIENTATION_LANDSCAPE; 123 int action = ev.getAction(); 124 switch (action & MotionEvent.ACTION_MASK) { 125 case MotionEvent.ACTION_DOWN: 126 mDownPos.set((int) ev.getX(), (int) ev.getY()); 127 break; 128 case MotionEvent.ACTION_MOVE: { 129 if (mDragging) { 130 int width = mRv.getMeasuredWidth(); 131 int height = mRv.getMeasuredHeight(); 132 float evX = ev.getX(); 133 float evY = ev.getY(); 134 float x = evX - mDragView.getTopLeftOffset().x; 135 float y = evY - mDragView.getTopLeftOffset().y; 136 137 // Update the dock state 138 TaskStack.DockState[] dockStates = getDockStatesForCurrentOrientation(); 139 TaskStack.DockState foundDockState = TaskStack.DockState.NONE; 140 for (int i = dockStates.length - 1; i >= 0; i--) { 141 TaskStack.DockState state = dockStates[i]; 142 if (state.touchAreaContainsPoint(width, height, evX, evY)) { 143 foundDockState = state; 144 break; 145 } 146 } 147 if (mLastDockState != foundDockState) { 148 mLastDockState = foundDockState; 149 EventBus.getDefault().send(new DragDockStateChangedEvent(mDragTask, 150 foundDockState)); 151 } 152 153 mDragView.setTranslationX(x); 154 mDragView.setTranslationY(y); 155 } 156 break; 157 } 158 case MotionEvent.ACTION_UP: 159 case MotionEvent.ACTION_CANCEL: { 160 if (mDragging) { 161 ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger( 162 mRv.getContext(), null, null, null); 163 postAnimationTrigger.increment(); 164 EventBus.getDefault().send(new DragEndEvent(mDragTask, mTaskView, mDragView, 165 mLastDockState, postAnimationTrigger)); 166 postAnimationTrigger.decrement(); 167 break; 168 } 169 } 170 } 171 } 172} 173