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