131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/*
231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * you may not use this file except in compliance with the License.
631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * You may obtain a copy of the License at
731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * See the License for the specific language governing permissions and
1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * limitations under the License.
1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17325dc23624160689e59fbac708cf6f222b20d025Daniel Sandlerpackage com.android.launcher3;
1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chungimport android.content.ComponentName;
2000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.content.Context;
216e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chungimport android.content.res.Resources;
2200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.graphics.Bitmap;
23b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chungimport android.graphics.Point;
24043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.graphics.PointF;
2500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.graphics.Rect;
2600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.os.Handler;
270280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.os.IBinder;
2800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.util.Log;
294390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyalimport android.view.HapticFeedbackConstants;
304390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyalimport android.view.KeyEvent;
314390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyalimport android.view.MotionEvent;
324390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyalimport android.view.VelocityTracker;
334390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyalimport android.view.View;
344390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyalimport android.view.ViewConfiguration;
3500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.view.inputmethod.InputMethodManager;
36c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen
37091440a9cb9d4f42406631004aa484cbb79214caAdam Cohenimport com.android.launcher3.util.Thunk;
38091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen
39c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohenimport java.util.ArrayList;
404390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyalimport java.util.HashSet;
4131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
4231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
4300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * Class for initiating a drag within a view or across multiple views.
4431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
4500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratopublic class DragController {
462e5c432a0aa7e83031575df73bed43a297e2eed3Joe Onorato    private static final String TAG = "Launcher.DragController";
472e5c432a0aa7e83031575df73bed43a297e2eed3Joe Onorato
4800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** Indicates the drag is a move.  */
4900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public static int DRAG_ACTION_MOVE = 0;
5000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
5100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** Indicates the drag is a copy.  */
5200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public static int DRAG_ACTION_COPY = 1;
5300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
544846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    public static final int SCROLL_DELAY = 500;
554846193300245c8c0a1f9bde3175f273df044309Sunny Goyal    public static final int RESCROLL_DELAY = PagedView.PAGE_SNAP_ANIMATION_DURATION + 150;
5600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
5700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private static final boolean PROFILE_DRAWING_DURING_DRAG = false;
5800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
5900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private static final int SCROLL_OUTSIDE_ZONE = 0;
6000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private static final int SCROLL_WAITING_IN_ZONE = 1;
6100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
6254fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy    static final int SCROLL_NONE = -1;
631262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    static final int SCROLL_LEFT = 0;
641262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    static final int SCROLL_RIGHT = 1;
6500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
66043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private static final float MAX_FLING_DEGREES = 35f;
67043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
68091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk Launcher mLauncher;
6900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private Handler mHandler;
7000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
7100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    // temporaries to avoid gc thrash
7200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private Rect mRectTemp = new Rect();
7300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private final int[] mCoordinatesTemp = new int[2];
747066003b2032a49ae5e59dab9b706259bdeb7e6eSunny Goyal    private final boolean mIsRtl;
7500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
7600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** Whether or not we're dragging. */
7700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private boolean mDragging;
7800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
79c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen    /** Whether or not this is an accessible drag operation */
80c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen    private boolean mIsAccessibleDrag;
81c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen
8200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** X coordinate of the down event. */
83e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen    private int mMotionDownX;
8400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
8500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** Y coordinate of the down event. */
86e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen    private int mMotionDownY;
8700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
88658db74c24817892f1a379b16620744f38f60e40Joe Onorato    /** the area at the edge of the screen that makes the workspace go left
89658db74c24817892f1a379b16620744f38f60e40Joe Onorato     *   or right while you're dragging.
90658db74c24817892f1a379b16620744f38f60e40Joe Onorato     */
91658db74c24817892f1a379b16620744f38f60e40Joe Onorato    private int mScrollZone;
92658db74c24817892f1a379b16620744f38f60e40Joe Onorato
939932a9b1e66fed4b5f38ce50f13d56331bbdcd7eAdam Cohen    private DropTarget.DragObject mDragObject;
9400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
9500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** Who can receive drop events */
9600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private ArrayList<DropTarget> mDropTargets = new ArrayList<DropTarget>();
974ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy    private ArrayList<DragListener> mListeners = new ArrayList<DragListener>();
98043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private DropTarget mFlingToDeleteDropTarget;
9900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
10000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** The window token used as the parent for the DragView. */
10100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private IBinder mWindowToken;
10200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
10300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** The view that will be scrolled when dragging to the left and right edges of the screen. */
10400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private View mScrollView;
10500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
106ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    private View mMoveTarget;
107ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy
108091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk DragScroller mDragScroller;
109091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk int mScrollState = SCROLL_OUTSIDE_ZONE;
11000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private ScrollRunnable mScrollRunnable = new ScrollRunnable();
11100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
11200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private DropTarget mLastDropTarget;
11300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
11400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private InputMethodManager mInputMethodManager;
11500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
116091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk int mLastTouch[] = new int[2];
117091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk long mLastTouchUpTime = -1;
118091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk int mDistanceSinceScroll = 0;
119a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy
120273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung    private int mTmpPoint[] = new int[2];
121273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung    private Rect mDragLayerRect = new Rect();
122273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung
123043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    protected int mFlingToDeleteThresholdVelocity;
124043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private VelocityTracker mVelocityTracker;
125043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
12631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
12731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Interface to receive notifications when a drag starts or stops
12831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
129fa401a10e7e9341daf6f3c5949bf9331902c26d0Sunny Goyal    public interface DragListener {
13031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        /**
13131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         * A drag has begun
13253b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini         *
13331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         * @param source An object representing where the drag originated
13431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         * @param info The data associated with the object that is being dragged
13531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         * @param dragAction The drag action: either {@link DragController#DRAG_ACTION_MOVE}
13631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         *        or {@link DragController#DRAG_ACTION_COPY}
13731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         */
1385162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato        void onDragStart(DragSource source, Object info, int dragAction);
13953b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini
14031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        /**
141e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung         * The drag has ended
14231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         */
14331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        void onDragEnd();
14431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
14531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
14631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
14700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Used to create a new DragLayer from XML.
14800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *
14900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * @param context The application's context.
15031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
1518dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    public DragController(Launcher launcher) {
1526e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung        Resources r = launcher.getResources();
1538dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mLauncher = launcher;
15400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mHandler = new Handler();
1556e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung        mScrollZone = r.getDimensionPixelSize(R.dimen.scroll_zone);
156043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mVelocityTracker = VelocityTracker.obtain();
157043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
1586e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung        float density = r.getDisplayMetrics().density;
1596e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung        mFlingToDeleteThresholdVelocity =
1606e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung                (int) (r.getInteger(R.integer.config_flingToDeleteMinVelocity) * density);
1617066003b2032a49ae5e59dab9b706259bdeb7e6eSunny Goyal        mIsRtl = Utilities.isRtl(r);
16200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
16331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1641262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    public boolean dragging() {
1651262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        return mDragging;
1661262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    }
1671262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
16831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
1695162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     * Starts a drag.
170a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     *
17131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param v The view that is being dragged
172e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * @param bmp The bitmap that represents the view being dragged
173e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * @param source An object representing where the drag originated
174e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * @param dragInfo The data associated with the object that is being dragged
175e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
176e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     *        {@link #DRAG_ACTION_COPY}
177f52abd7758b8f245522936e941336e574debabf5Sunny Goyal     * @param viewImageBounds the position of the image inside the view
178e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
179e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     *          Makes dragging feel more precise, e.g. you can clip out a transparent border
180e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     */
181f52abd7758b8f245522936e941336e574debabf5Sunny Goyal    public void startDrag(View v, Bitmap bmp, DragSource source, Object dragInfo,
182f52abd7758b8f245522936e941336e574debabf5Sunny Goyal            Rect viewImageBounds, int dragAction, float initialDragViewScale) {
183e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        int[] loc = mCoordinatesTemp;
1848dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mLauncher.getDragLayer().getLocationInDragLayer(v, loc);
185f52abd7758b8f245522936e941336e574debabf5Sunny Goyal        int dragLayerX = loc[0] + viewImageBounds.left
186f52abd7758b8f245522936e941336e574debabf5Sunny Goyal                + (int) ((initialDragViewScale * bmp.getWidth() - bmp.getWidth()) / 2);
187f52abd7758b8f245522936e941336e574debabf5Sunny Goyal        int dragLayerY = loc[1] + viewImageBounds.top
188f52abd7758b8f245522936e941336e574debabf5Sunny Goyal                + (int) ((initialDragViewScale * bmp.getHeight() - bmp.getHeight()) / 2);
189e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
19005713af127d765cc28a8b2fd548a90347c90d6cbMichael Jurka        startDrag(bmp, dragLayerX, dragLayerY, source, dragInfo, dragAction, null,
191c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen                null, initialDragViewScale, false);
192e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
193e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        if (dragAction == DRAG_ACTION_MOVE) {
194e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung            v.setVisibility(View.GONE);
195e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        }
196e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    }
197e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
198e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    /**
199e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * Starts a drag.
200e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     *
2015162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     * @param b The bitmap to display as the drag image.  It will be re-scaled to the
2025162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     *          enlarged size.
2038dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen     * @param dragLayerX The x position in the DragLayer of the left-top of the bitmap.
2048dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen     * @param dragLayerY The y position in the DragLayer of the left-top of the bitmap.
2055162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     * @param source An object representing where the drag originated
206ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy     * @param dragInfo The data associated with the object that is being dragged
2075162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
2085162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     *        {@link #DRAG_ACTION_COPY}
209a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     * @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
210a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     *          Makes dragging feel more precise, e.g. you can clip out a transparent border
211c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen     * @param accessible whether this drag should occur in accessibility mode
212a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     */
213eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung    public DragView startDrag(Bitmap b, int dragLayerX, int dragLayerY,
21472d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung            DragSource source, Object dragInfo, int dragAction, Point dragOffset, Rect dragRegion,
215c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen            float initialDragViewScale, boolean accessible) {
21600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (PROFILE_DRAWING_DURING_DRAG) {
21700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            android.os.Debug.startMethodTracing("Launcher");
21800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
21900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
22000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        // Hide soft keyboard, if visible
22100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (mInputMethodManager == null) {
22200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            mInputMethodManager = (InputMethodManager)
2238dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                    mLauncher.getSystemService(Context.INPUT_METHOD_SERVICE);
22400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
22500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mInputMethodManager.hideSoftInputFromWindow(mWindowToken, 0);
22600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
2274ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy        for (DragListener listener : mListeners) {
2284ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy            listener.onDragStart(source, dragInfo, dragAction);
22900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
23000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
2318dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        final int registrationX = mMotionDownX - dragLayerX;
2328dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        final int registrationY = mMotionDownY - dragLayerY;
23300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
234a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left;
235a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top;
236e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen
23700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragging = true;
238c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        mIsAccessibleDrag = accessible;
239cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen
2409932a9b1e66fed4b5f38ce50f13d56331bbdcd7eAdam Cohen        mDragObject = new DropTarget.DragObject();
2419932a9b1e66fed4b5f38ce50f13d56331bbdcd7eAdam Cohen
242bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        mDragObject.dragComplete = false;
243c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        if (mIsAccessibleDrag) {
244c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen            // For an accessible drag, we assume the view is being dragged from the center.
245c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen            mDragObject.xOffset = b.getWidth() / 2;
246c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen            mDragObject.yOffset = b.getHeight() / 2;
247c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen            mDragObject.accessibleDrag = true;
248c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        } else {
249c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen            mDragObject.xOffset = mMotionDownX - (dragLayerX + dragRegionLeft);
250c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen            mDragObject.yOffset = mMotionDownY - (dragLayerY + dragRegionTop);
251c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        }
252c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen
253cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.dragSource = source;
254cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.dragInfo = dragInfo;
25500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
2568dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        final DragView dragView = mDragObject.dragView = new DragView(mLauncher, b, registrationX,
25772d598400da7cef9c7fc4f99bb1fcd7ff0710011Winson Chung                registrationY, 0, 0, b.getWidth(), b.getHeight(), initialDragViewScale);
258a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
259b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung        if (dragOffset != null) {
260b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung            dragView.setDragVisualizeOffset(new Point(dragOffset));
261b8c69f3c17a40adc2d85e8e996f754c383c293dcWinson Chung        }
262a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        if (dragRegion != null) {
263e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen            dragView.setDragRegion(new Rect(dragRegion));
264a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
265a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
266780fe59a7af8b12fbdcd7f6841edaa7f2c2e019dWinson Chung        mLauncher.getDragLayer().performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
2678dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        dragView.show(mMotionDownX, mMotionDownY);
2688dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        handleMoveEvent(mMotionDownX, mMotionDownY);
269eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung        return dragView;
27000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
27100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
27200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
27300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Draw the view into a bitmap.
27400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
275120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen    Bitmap getViewBitmap(View v) {
27600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.clearFocus();
27700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.setPressed(false);
27800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
27900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        boolean willNotCache = v.willNotCacheDrawing();
28000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.setWillNotCacheDrawing(false);
28100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
28200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        // Reset the drawing cache background color to fully transparent
28300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        // for the duration of this operation
28400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        int color = v.getDrawingCacheBackgroundColor();
28500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.setDrawingCacheBackgroundColor(0);
286120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen        float alpha = v.getAlpha();
287120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen        v.setAlpha(1.0f);
28800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
28900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (color != 0) {
29000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            v.destroyDrawingCache();
29100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
29200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.buildDrawingCache();
29300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        Bitmap cacheBitmap = v.getDrawingCache();
2943f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler        if (cacheBitmap == null) {
2953f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler            Log.e(TAG, "failed getViewBitmap(" + v + ")", new RuntimeException());
2963f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler            return null;
2973f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler        }
29800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
29900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
30000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
30100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        // Restore the view
30200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.destroyDrawingCache();
303120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen        v.setAlpha(alpha);
30400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.setWillNotCacheDrawing(willNotCache);
30500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.setDrawingCacheBackgroundColor(color);
30600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
30700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return bitmap;
30800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
30900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
31000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
31100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Call this from a drag source view like this:
31200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *
31300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * <pre>
31400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *  @Override
31500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *  public boolean dispatchKeyEvent(KeyEvent event) {
31600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *      return mDragController.dispatchKeyEvent(this, event)
31700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *              || super.dispatchKeyEvent(event);
31800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * </pre>
31900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
32000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public boolean dispatchKeyEvent(KeyEvent event) {
32100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return mDragging;
32200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
32300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
324304dcde0e301c2f1a0b2bdc80ea8617930691b6eWinson Chung    public boolean isDragging() {
325304dcde0e301c2f1a0b2bdc80ea8617930691b6eWinson Chung        return mDragging;
326304dcde0e301c2f1a0b2bdc80ea8617930691b6eWinson Chung    }
327304dcde0e301c2f1a0b2bdc80ea8617930691b6eWinson Chung
32824b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato    /**
32924b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato     * Stop dragging without dropping.
33024b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato     */
33124b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato    public void cancelDrag() {
332621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung        if (mDragging) {
333c07918d0053fc7d2a19d7b013565a5d2e7d4af51Winson Chung            if (mLastDropTarget != null) {
334c07918d0053fc7d2a19d7b013565a5d2e7d4af51Winson Chung                mLastDropTarget.onDragExit(mDragObject);
335c07918d0053fc7d2a19d7b013565a5d2e7d4af51Winson Chung            }
33641bb19d2775836e30ebf42f681b4617bc71600aaWinson Chung            mDragObject.deferDragViewCleanupPostAnimation = false;
33736cc09b07b19198f4ea886583cef462ade27192cAdam Cohen            mDragObject.cancelled = true;
338bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            mDragObject.dragComplete = true;
339a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung            mDragObject.dragSource.onDropCompleted(null, mDragObject, false, false);
340621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung        }
34124b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato        endDrag();
34224b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato    }
3434390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal    public void onAppsRemoved(final ArrayList<String> packageNames, HashSet<ComponentName> cns) {
344a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung        // Cancel the current drag if we are removing an app that we are dragging
345a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung        if (mDragObject != null) {
346a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung            Object rawDragInfo = mDragObject.dragInfo;
347a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung            if (rawDragInfo instanceof ShortcutInfo) {
348a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung                ShortcutInfo dragInfo = (ShortcutInfo) rawDragInfo;
3494390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                for (ComponentName componentName : cns) {
3507bcadad93f97e79d95ae879fe165de2e2371f613Michael Jurka                    // Added null checks to prevent NPE we've seen in the wild
3514390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                    if (dragInfo != null && dragInfo.intent != null) {
352df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung                        ComponentName cn = dragInfo.intent.getComponent();
3534390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                        boolean isSameComponent = cn != null && (cn.equals(componentName) ||
35460e1efe032821235c04376088494b44dfde4b62eAdam Cohen                                packageNames.contains(cn.getPackageName()));
35583892cc0768bd6d7f0827886e9e7a2eb3eed2b01Winson Chung                        if (isSameComponent) {
35611a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung                            cancelDrag();
35711a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung                            return;
35811a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung                        }
359a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung                    }
360a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung                }
361a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung            }
362a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung        }
363a182096cb20e0580dfca6661b2e5871c8886c834Winson Chung    }
36424b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato
36500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private void endDrag() {
36600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (mDragging) {
36700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            mDragging = false;
368c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen            mIsAccessibleDrag = false;
369aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung            clearScrollRunnable();
370043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            boolean isDeferred = false;
371cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            if (mDragObject.dragView != null) {
372043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                isDeferred = mDragObject.deferDragViewCleanupPostAnimation;
373043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                if (!isDeferred) {
3747bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                    mDragObject.dragView.remove();
3757bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                }
376cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                mDragObject.dragView = null;
37700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
378043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
379043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            // Only end the drag if we are not deferred
380043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            if (!isDeferred) {
381f406615354a92367481a60966b6b873cae37fe4cSunny Goyal                for (DragListener listener : new ArrayList<>(mListeners)) {
382043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    listener.onDragEnd();
383043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                }
384043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            }
385043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
386043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
387043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        releaseVelocityTracker();
388043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
389043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
390043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    /**
391043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     * This only gets called as a result of drag view cleanup being deferred in endDrag();
392043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     */
393043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    void onDeferredEndDrag(DragView dragView) {
394043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        dragView.remove();
395043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
3961e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka        if (mDragObject.deferDragViewCleanupPostAnimation) {
3971e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka            // If we skipped calling onDragEnd() before, do it now
398f406615354a92367481a60966b6b873cae37fe4cSunny Goyal            for (DragListener listener : new ArrayList<>(mListeners)) {
3991e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka                listener.onDragEnd();
4001e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka            }
40100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
40200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
40300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
404fa401a10e7e9341daf6f3c5949bf9331902c26d0Sunny Goyal    public void onDeferredEndFling(DropTarget.DragObject d) {
405a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        d.dragSource.onFlingToDeleteCompleted();
406a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung    }
407a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung
40800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
409273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung     * Clamps the position to the drag layer bounds.
410273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung     */
411273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung    private int[] getClampedDragLayerPos(float x, float y) {
412273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        mLauncher.getDragLayer().getLocalVisibleRect(mDragLayerRect);
413273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        mTmpPoint[0] = (int) Math.max(mDragLayerRect.left, Math.min(x, mDragLayerRect.right - 1));
414273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        mTmpPoint[1] = (int) Math.max(mDragLayerRect.top, Math.min(y, mDragLayerRect.bottom - 1));
415273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        return mTmpPoint;
416273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung    }
417273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung
418a2413751e3a698aef9c87411a639637883856939Winson Chung    long getLastGestureUpTime() {
419a2413751e3a698aef9c87411a639637883856939Winson Chung        if (mDragging) {
420a2413751e3a698aef9c87411a639637883856939Winson Chung            return System.currentTimeMillis();
421a2413751e3a698aef9c87411a639637883856939Winson Chung        } else {
422a2413751e3a698aef9c87411a639637883856939Winson Chung            return mLastTouchUpTime;
423a2413751e3a698aef9c87411a639637883856939Winson Chung        }
424a2413751e3a698aef9c87411a639637883856939Winson Chung    }
425a2413751e3a698aef9c87411a639637883856939Winson Chung
426a2413751e3a698aef9c87411a639637883856939Winson Chung    void resetLastGestureUpTime() {
427a2413751e3a698aef9c87411a639637883856939Winson Chung        mLastTouchUpTime = -1;
428a2413751e3a698aef9c87411a639637883856939Winson Chung    }
429a2413751e3a698aef9c87411a639637883856939Winson Chung
430273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung    /**
43100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Call this from a drag source view.
43200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
43300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public boolean onInterceptTouchEvent(MotionEvent ev) {
4343a9fcedbcd235372cd2ab64f825a0b5b3937f59eMichael Jurka        @SuppressWarnings("all") // suppress dead code warning
4353a9fcedbcd235372cd2ab64f825a0b5b3937f59eMichael Jurka        final boolean debug = false;
4363a9fcedbcd235372cd2ab64f825a0b5b3937f59eMichael Jurka        if (debug) {
437a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato            Log.d(Launcher.TAG, "DragController.onInterceptTouchEvent " + ev + " mDragging="
4389c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    + mDragging);
4399c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        }
44000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
441c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        if (mIsAccessibleDrag) {
442c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen            return false;
443c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        }
444c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen
445043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Update the velocity tracker
446043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        acquireVelocityTrackerAndAddMovement(ev);
447043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
448043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final int action = ev.getAction();
449273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        final int[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
450273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        final int dragLayerX = dragLayerPos[0];
451273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        final int dragLayerY = dragLayerPos[1];
45200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
45300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        switch (action) {
45400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            case MotionEvent.ACTION_MOVE:
45500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                break;
45600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            case MotionEvent.ACTION_DOWN:
45700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                // Remember location of down touch
4588dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                mMotionDownX = dragLayerX;
4598dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                mMotionDownY = dragLayerY;
46000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mLastDropTarget = null;
46100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                break;
46200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            case MotionEvent.ACTION_UP:
463a2413751e3a698aef9c87411a639637883856939Winson Chung                mLastTouchUpTime = System.currentTimeMillis();
46400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                if (mDragging) {
465043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    PointF vec = isFlingingToDelete(mDragObject.dragSource);
4661a70cef9884270f2f0a760f079a10fdfb1544c98Sunny Goyal                    if (!DeleteDropTarget.supportsDrop(mDragObject.dragInfo)) {
4677c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen                        vec = null;
4687c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen                    }
469043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    if (vec != null) {
470043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                        dropOnFlingToDeleteTarget(dragLayerX, dragLayerY, vec);
471043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    } else {
472043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                        drop(dragLayerX, dragLayerY);
473043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    }
47400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                }
47500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                endDrag();
47600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                break;
477621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung            case MotionEvent.ACTION_CANCEL:
478621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung                cancelDrag();
479621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung                break;
48000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
48100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
48200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return mDragging;
48300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
48400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
48500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
486ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy     * Sets the view that should handle move events.
487ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy     */
488ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    void setMoveTarget(View view) {
489ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy        mMoveTarget = view;
490ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    }
491ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy
492ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    public boolean dispatchUnhandledMove(View focused, int direction) {
493ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy        return mMoveTarget != null && mMoveTarget.dispatchUnhandledMove(focused, direction);
494ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    }
495ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy
496aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung    private void clearScrollRunnable() {
497aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung        mHandler.removeCallbacks(mScrollRunnable);
498aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung        if (mScrollState == SCROLL_WAITING_IN_ZONE) {
499aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung            mScrollState = SCROLL_OUTSIDE_ZONE;
500aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung            mScrollRunnable.setDirection(SCROLL_RIGHT);
501aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung            mDragScroller.onExitScrollArea();
502360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung            mLauncher.getDragLayer().onExitScrollArea();
503aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung        }
504aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung    }
505aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung
506de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy    private void handleMoveEvent(int x, int y) {
507cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.dragView.move(x, y);
508de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy
509de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        // Drop on someone?
510de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        final int[] coordinates = mCoordinatesTemp;
511de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        DropTarget dropTarget = findDropTarget(x, y, coordinates);
512cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.x = coordinates[0];
513cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.y = coordinates[1];
51425460a1d5cb473033408c9e76898bb77e785c66fWinson Chung        checkTouchMove(dropTarget);
51525460a1d5cb473033408c9e76898bb77e785c66fWinson Chung
51625460a1d5cb473033408c9e76898bb77e785c66fWinson Chung        // Check if we are hovering over the scroll areas
517f7a29e83f06909b378dba39c83a522375682710aSunny Goyal        mDistanceSinceScroll += Math.hypot(mLastTouch[0] - x, mLastTouch[1] - y);
51825460a1d5cb473033408c9e76898bb77e785c66fWinson Chung        mLastTouch[0] = x;
51925460a1d5cb473033408c9e76898bb77e785c66fWinson Chung        mLastTouch[1] = y;
52025460a1d5cb473033408c9e76898bb77e785c66fWinson Chung        checkScrollState(x, y);
52125460a1d5cb473033408c9e76898bb77e785c66fWinson Chung    }
52225460a1d5cb473033408c9e76898bb77e785c66fWinson Chung
52325460a1d5cb473033408c9e76898bb77e785c66fWinson Chung    public void forceTouchMove() {
52425460a1d5cb473033408c9e76898bb77e785c66fWinson Chung        int[] dummyCoordinates = mCoordinatesTemp;
52525460a1d5cb473033408c9e76898bb77e785c66fWinson Chung        DropTarget dropTarget = findDropTarget(mLastTouch[0], mLastTouch[1], dummyCoordinates);
5264ef75f523c5b2bfed37bf1ed4bd2bcf8bda8b502Adam Cohen        mDragObject.x = dummyCoordinates[0];
5274ef75f523c5b2bfed37bf1ed4bd2bcf8bda8b502Adam Cohen        mDragObject.y = dummyCoordinates[1];
52825460a1d5cb473033408c9e76898bb77e785c66fWinson Chung        checkTouchMove(dropTarget);
52925460a1d5cb473033408c9e76898bb77e785c66fWinson Chung    }
53025460a1d5cb473033408c9e76898bb77e785c66fWinson Chung
53125460a1d5cb473033408c9e76898bb77e785c66fWinson Chung    private void checkTouchMove(DropTarget dropTarget) {
532de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        if (dropTarget != null) {
533de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            if (mLastDropTarget != dropTarget) {
534de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                if (mLastDropTarget != null) {
535cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                    mLastDropTarget.onDragExit(mDragObject);
536de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                }
537cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                dropTarget.onDragEnter(mDragObject);
538de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            }
539cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            dropTarget.onDragOver(mDragObject);
540de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        } else {
541de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            if (mLastDropTarget != null) {
542cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                mLastDropTarget.onDragExit(mDragObject);
543de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            }
544de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        }
545de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        mLastDropTarget = dropTarget;
54625460a1d5cb473033408c9e76898bb77e785c66fWinson Chung    }
547de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy
548091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk void checkScrollState(int x, int y) {
5498dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        final int slop = ViewConfiguration.get(mLauncher).getScaledWindowTouchSlop();
550aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung        final int delay = mDistanceSinceScroll < slop ? RESCROLL_DELAY : SCROLL_DELAY;
551fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung        final DragLayer dragLayer = mLauncher.getDragLayer();
5527066003b2032a49ae5e59dab9b706259bdeb7e6eSunny Goyal        final int forwardDirection = mIsRtl ? SCROLL_RIGHT : SCROLL_LEFT;
5537066003b2032a49ae5e59dab9b706259bdeb7e6eSunny Goyal        final int backwardsDirection = mIsRtl ? SCROLL_LEFT : SCROLL_RIGHT;
554a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy
5553f4e1423804d64a38cb69e4511d7b80783564827Winson Chung        if (x < mScrollZone) {
556aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung            if (mScrollState == SCROLL_OUTSIDE_ZONE) {
557de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                mScrollState = SCROLL_WAITING_IN_ZONE;
558fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung                if (mDragScroller.onEnterScrollArea(x, y, forwardDirection)) {
559fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung                    dragLayer.onEnterScrollArea(forwardDirection);
560fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung                    mScrollRunnable.setDirection(forwardDirection);
561aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung                    mHandler.postDelayed(mScrollRunnable, delay);
5623e0839e5f830ab7e64223ebe186d97729eda3e22Winson Chung                }
563de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            }
5643f4e1423804d64a38cb69e4511d7b80783564827Winson Chung        } else if (x > mScrollView.getWidth() - mScrollZone) {
565aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung            if (mScrollState == SCROLL_OUTSIDE_ZONE) {
566de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                mScrollState = SCROLL_WAITING_IN_ZONE;
567fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung                if (mDragScroller.onEnterScrollArea(x, y, backwardsDirection)) {
568fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung                    dragLayer.onEnterScrollArea(backwardsDirection);
569fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung                    mScrollRunnable.setDirection(backwardsDirection);
570aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung                    mHandler.postDelayed(mScrollRunnable, delay);
5713e0839e5f830ab7e64223ebe186d97729eda3e22Winson Chung                }
572de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            }
573de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        } else {
574aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung            clearScrollRunnable();
575de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        }
576de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy    }
577de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy
578ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    /**
57900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Call this from a drag source view.
58000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
58100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public boolean onTouchEvent(MotionEvent ev) {
582c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        if (!mDragging || mIsAccessibleDrag) {
58300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            return false;
58400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
58500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
586043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Update the velocity tracker
587043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        acquireVelocityTrackerAndAddMovement(ev);
588043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
58900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        final int action = ev.getAction();
590273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        final int[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
591273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        final int dragLayerX = dragLayerPos[0];
592273c1022405bcc5e0840450b9195622e7476c9ddWinson Chung        final int dragLayerY = dragLayerPos[1];
59300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
59400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        switch (action) {
59500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        case MotionEvent.ACTION_DOWN:
59600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            // Remember where the motion event started
5978dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            mMotionDownX = dragLayerX;
5988dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            mMotionDownY = dragLayerY;
59900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
6008dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            if ((dragLayerX < mScrollZone) || (dragLayerX > mScrollView.getWidth() - mScrollZone)) {
60100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mScrollState = SCROLL_WAITING_IN_ZONE;
60200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
60300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            } else {
60400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mScrollState = SCROLL_OUTSIDE_ZONE;
60500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
60653b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini            handleMoveEvent(dragLayerX, dragLayerY);
60700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            break;
60800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        case MotionEvent.ACTION_MOVE:
6098dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            handleMoveEvent(dragLayerX, dragLayerY);
61000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            break;
61100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        case MotionEvent.ACTION_UP:
612b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy            // Ensure that we've processed a move event at the current pointer location.
6138dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            handleMoveEvent(dragLayerX, dragLayerY);
6143bc21c35fa167ac233e19df0c9a01b0a07173ed8Winson Chung            mHandler.removeCallbacks(mScrollRunnable);
615043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
61600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            if (mDragging) {
617043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                PointF vec = isFlingingToDelete(mDragObject.dragSource);
6181a70cef9884270f2f0a760f079a10fdfb1544c98Sunny Goyal                if (!DeleteDropTarget.supportsDrop(mDragObject.dragInfo)) {
619947dc5431981e40ffc8d687604f7777d35915034Adam Cohen                    vec = null;
620947dc5431981e40ffc8d687604f7777d35915034Adam Cohen                }
621043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                if (vec != null) {
622043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    dropOnFlingToDeleteTarget(dragLayerX, dragLayerY, vec);
623043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                } else {
624043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    drop(dragLayerX, dragLayerY);
625043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                }
62600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
62700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            endDrag();
62800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            break;
62900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        case MotionEvent.ACTION_CANCEL:
6303bc21c35fa167ac233e19df0c9a01b0a07173ed8Winson Chung            mHandler.removeCallbacks(mScrollRunnable);
63124b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato            cancelDrag();
632621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung            break;
63300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
63400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
63500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return true;
63600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
63700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
638043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    /**
639c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen     * Since accessible drag and drop won't cause the same sequence of touch events, we manually
640c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen     * inject the appropriate state.
641c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen     */
642c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen    public void prepareAccessibleDrag(int x, int y) {
643c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        mMotionDownX = x;
644c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        mMotionDownY = y;
645c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        mLastDropTarget = null;
646c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen    }
647c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen
648c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen    /**
649c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen     * As above, since accessible drag and drop won't cause the same sequence of touch events,
650c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen     * we manually ensure appropriate drag and drop events get emulated for accessible drag.
651c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen     */
652c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen    public void completeAccessibleDrag(int[] location) {
653c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        final int[] coordinates = mCoordinatesTemp;
654c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen
655c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        // We make sure that we prime the target for drop.
656c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        DropTarget dropTarget = findDropTarget(location[0], location[1], coordinates);
657c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        mDragObject.x = coordinates[0];
658c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        mDragObject.y = coordinates[1];
659c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        checkTouchMove(dropTarget);
660c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen
661e9b651eef1b9f3647eba94f833bff3fc52f5956bSunny Goyal        dropTarget.prepareAccessibilityDrop();
662c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        // Perform the drop
663c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        drop(location[0], location[1]);
664c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen        endDrag();
665c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen    }
666c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen
667c9735cff2e558aa3f3810e49c15ef13049b9429cAdam Cohen    /**
668043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     * Determines whether the user flung the current item to delete it.
669043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     *
670043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     * @return the vector at which the item was flung, or null if no fling was detected.
671043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     */
672043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private PointF isFlingingToDelete(DragSource source) {
673043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mFlingToDeleteDropTarget == null) return null;
674043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (!source.supportsFlingToDelete()) return null;
675043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
676043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        ViewConfiguration config = ViewConfiguration.get(mLauncher);
677043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mVelocityTracker.computeCurrentVelocity(1000, config.getScaledMaximumFlingVelocity());
678043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
679043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mVelocityTracker.getYVelocity() < mFlingToDeleteThresholdVelocity) {
680043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            // Do a quick dot product test to ensure that we are flinging upwards
681043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            PointF vel = new PointF(mVelocityTracker.getXVelocity(),
682043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    mVelocityTracker.getYVelocity());
683043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            PointF upVec = new PointF(0f, -1f);
684043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            float theta = (float) Math.acos(((vel.x * upVec.x) + (vel.y * upVec.y)) /
685043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    (vel.length() * upVec.length()));
686043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            if (theta <= Math.toRadians(MAX_FLING_DEGREES)) {
687043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                return vel;
688043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            }
689043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
690043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        return null;
691043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
692043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
693043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private void dropOnFlingToDeleteTarget(float x, float y, PointF vel) {
694043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final int[] coordinates = mCoordinatesTemp;
695043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
696043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDragObject.x = coordinates[0];
697043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDragObject.y = coordinates[1];
698043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
699043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Clean up dragging on the target if it's not the current fling delete target otherwise,
700043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // start dragging to it.
701043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mLastDropTarget != null && mFlingToDeleteDropTarget != mLastDropTarget) {
702043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mLastDropTarget.onDragExit(mDragObject);
703043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
704043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
705043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Drop onto the fling-to-delete target
706043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        boolean accepted = false;
707043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mFlingToDeleteDropTarget.onDragEnter(mDragObject);
708232decb008661d82ed2ca6d5f3080ee5a50d3be1Winson Chung        // We must set dragComplete to true _only_ after we "enter" the fling-to-delete target for
709232decb008661d82ed2ca6d5f3080ee5a50d3be1Winson Chung        // "drop"
710232decb008661d82ed2ca6d5f3080ee5a50d3be1Winson Chung        mDragObject.dragComplete = true;
711043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mFlingToDeleteDropTarget.onDragExit(mDragObject);
712043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mFlingToDeleteDropTarget.acceptDrop(mDragObject)) {
713ddec73471eb6cc1f15eb9421a205bb2362509075Sunny Goyal            mFlingToDeleteDropTarget.onFlingToDelete(mDragObject, vel);
714043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            accepted = true;
715043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
716a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        mDragObject.dragSource.onDropCompleted((View) mFlingToDeleteDropTarget, mDragObject, true,
717043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                accepted);
718043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
719043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
720b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy    private void drop(float x, float y) {
72100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        final int[] coordinates = mCoordinatesTemp;
722b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy        final DropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates);
72300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
724cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.x = coordinates[0];
725cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.y = coordinates[1];
726b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy        boolean accepted = false;
72700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (dropTarget != null) {
728bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            mDragObject.dragComplete = true;
729cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            dropTarget.onDragExit(mDragObject);
730cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            if (dropTarget.acceptDrop(mDragObject)) {
731cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                dropTarget.onDrop(mDragObject);
732b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy                accepted = true;
73300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
73400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
735a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        mDragObject.dragSource.onDropCompleted((View) dropTarget, mDragObject, false, accepted);
73600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
73700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
73800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private DropTarget findDropTarget(int x, int y, int[] dropCoordinates) {
73900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        final Rect r = mRectTemp;
74000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
74100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        final ArrayList<DropTarget> dropTargets = mDropTargets;
74200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        final int count = dropTargets.size();
74300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        for (int i=count-1; i>=0; i--) {
744440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DropTarget target = dropTargets.get(i);
7450280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            if (!target.isDropEnabled())
7460280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                continue;
7470280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
7487d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            target.getHitRectRelativeToDragLayer(r);
749440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
750cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            mDragObject.x = x;
751cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            mDragObject.y = y;
75200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            if (r.contains(x, y)) {
753440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
7547d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen                dropCoordinates[0] = x;
7557d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen                dropCoordinates[1] = y;
7567d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen                mLauncher.getDragLayer().mapCoordInSelfToDescendent((View) target, dropCoordinates);
757440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
75800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                return target;
75900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
76000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
76100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return null;
76200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
76300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
76400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setDragScoller(DragScroller scroller) {
76500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragScroller = scroller;
76600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
76700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
76800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setWindowToken(IBinder token) {
76900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mWindowToken = token;
77000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
77100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
77231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
77331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Sets the drag listner which will be notified when a drag starts or ends.
77431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
7754ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy    public void addDragListener(DragListener l) {
7764ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy        mListeners.add(l);
77700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
77800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
77931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
78031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Remove a previously installed drag listener.
78131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
78200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void removeDragListener(DragListener l) {
7834ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy        mListeners.remove(l);
78400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
78500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
78600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
78700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Add a DropTarget to the list of potential places to receive drop events.
78800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
78900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void addDropTarget(DropTarget target) {
79000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDropTargets.add(target);
79100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
79200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
79300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
79400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Don't send drop events to <em>target</em> any more.
79500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
79600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void removeDropTarget(DropTarget target) {
79700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDropTargets.remove(target);
79800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
79900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
80000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
801043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     * Sets the current fling-to-delete drop target.
802043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     */
803043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    public void setFlingToDeleteDropTarget(DropTarget target) {
804043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mFlingToDeleteDropTarget = target;
805043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
806043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
807043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private void acquireVelocityTrackerAndAddMovement(MotionEvent ev) {
808043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mVelocityTracker == null) {
809043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mVelocityTracker = VelocityTracker.obtain();
810043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
811043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mVelocityTracker.addMovement(ev);
812043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
813043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
814043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private void releaseVelocityTracker() {
815043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mVelocityTracker != null) {
816043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mVelocityTracker.recycle();
817043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mVelocityTracker = null;
818043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
819043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
820043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
821043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    /**
82200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Set which view scrolls for touch events near the edge of the screen.
82300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
82400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setScrollView(View v) {
82500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mScrollView = v;
82600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
82700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
8285f445425606b2c27276a79e9e871cf7f67b1b719Patrick Dubroy    DragView getDragView() {
829cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        return mDragObject.dragView;
8305f445425606b2c27276a79e9e871cf7f67b1b719Patrick Dubroy    }
8315f445425606b2c27276a79e9e871cf7f67b1b719Patrick Dubroy
83200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private class ScrollRunnable implements Runnable {
83300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        private int mDirection;
83400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
83500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        ScrollRunnable() {
83600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
83700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
83800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        public void run() {
83900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            if (mDragScroller != null) {
84000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                if (mDirection == SCROLL_LEFT) {
84100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    mDragScroller.scrollLeft();
84200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                } else {
84300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    mDragScroller.scrollRight();
84400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                }
84500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mScrollState = SCROLL_OUTSIDE_ZONE;
846a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy                mDistanceSinceScroll = 0;
847a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy                mDragScroller.onExitScrollArea();
848360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung                mLauncher.getDragLayer().onExitScrollArea();
849aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung
850aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung                if (isDragging()) {
85125460a1d5cb473033408c9e76898bb77e785c66fWinson Chung                    // Check the scroll again so that we can requeue the scroller if necessary
85225460a1d5cb473033408c9e76898bb77e785c66fWinson Chung                    checkScrollState(mLastTouch[0], mLastTouch[1]);
853aa15ffe60e28b923ebf3e3162ce427ca6feae803Winson Chung                }
85400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
85500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
85600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
85700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        void setDirection(int direction) {
85800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            mDirection = direction;
85900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
86000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
86131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
862