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