RecentsViewTouchHandler.java revision be7607af8875236b9cf7bdb5f5aa089c207529af
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            TaskStack.DockState.TOP, TaskStack.DockState.BOTTOM
40    };
41}
42
43/**
44 * Handles touch events for a RecentsView.
45 */
46class RecentsViewTouchHandler {
47
48    private RecentsView mRv;
49
50    private Task mDragTask;
51    private TaskView mTaskView;
52    private DragView mDragView;
53
54    private Point mDownPos = new Point();
55    private boolean mDragging;
56    private TaskStack.DockState mLastDockState;
57
58    public RecentsViewTouchHandler(RecentsView rv) {
59        mRv = rv;
60    }
61
62    /** Touch preprocessing for handling below */
63    public boolean onInterceptTouchEvent(MotionEvent ev) {
64        int action = ev.getAction();
65        switch (action & MotionEvent.ACTION_MASK) {
66            case MotionEvent.ACTION_DOWN:
67                mDownPos.set((int) ev.getX(), (int) ev.getY());
68                break;
69        }
70        return mDragging;
71    }
72
73    /** Handles touch events once we have intercepted them */
74    public boolean onTouchEvent(MotionEvent ev) {
75        if (!mDragging) return false;
76
77        boolean isLandscape = mRv.getResources().getConfiguration().orientation ==
78                Configuration.ORIENTATION_LANDSCAPE;
79        int action = ev.getAction();
80        switch (action & MotionEvent.ACTION_MASK) {
81            case MotionEvent.ACTION_DOWN:
82                mDownPos.set((int) ev.getX(), (int) ev.getY());
83                break;
84            case MotionEvent.ACTION_MOVE: {
85                int width = mRv.getMeasuredWidth();
86                int height = mRv.getMeasuredHeight();
87                float evX = ev.getX();
88                float evY = ev.getY();
89                float x = evX - mDragView.getTopLeftOffset().x;
90                float y = evY - mDragView.getTopLeftOffset().y;
91
92                // Update the dock state
93                TaskStack.DockState[] dockStates = isLandscape ?
94                        DockRegion.LANDSCAPE : DockRegion.PORTRAIT;
95                TaskStack.DockState foundDockState = null;
96                for (int i = 0; i < dockStates.length; i++) {
97                    TaskStack.DockState state = dockStates[i];
98                    if (state.touchAreaContainsPoint(width, height, evX, evY)) {
99                        foundDockState = state;
100                        break;
101                    }
102                }
103                if (mLastDockState != foundDockState) {
104                    mLastDockState = foundDockState;
105                    EventBus.getDefault().send(new DragDockStateChangedEvent(mDragTask,
106                            foundDockState));
107                }
108
109                mDragView.setTranslationX(x);
110                mDragView.setTranslationY(y);
111                break;
112            }
113            case MotionEvent.ACTION_UP:
114            case MotionEvent.ACTION_CANCEL: {
115                ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger(
116                        mRv.getContext(), null, null, null);
117                postAnimationTrigger.increment();
118                EventBus.getDefault().send(new DragEndEvent(mDragTask, mTaskView, mDragView,
119                        mLastDockState, postAnimationTrigger));
120                postAnimationTrigger.decrement();
121                break;
122            }
123        }
124        return true;
125    }
126
127    /**** Events ****/
128
129    public final void onBusEvent(DragStartEvent event) {
130        mRv.getParent().requestDisallowInterceptTouchEvent(true);
131        mDragging = true;
132        mDragTask = event.task;
133        mTaskView = event.taskView;
134        mDragView = event.dragView;
135
136        float x = mDownPos.x - mDragView.getTopLeftOffset().x;
137        float y = mDownPos.y - mDragView.getTopLeftOffset().y;
138        mDragView.setTranslationX(x);
139        mDragView.setTranslationY(y);
140    }
141
142    public final void onBusEvent(DragEndEvent event) {
143        mDragging = false;
144        mDragTask = null;
145        mTaskView = null;
146        mDragView = null;
147        mLastDockState = null;
148    }
149}
150