DragLayer.java revision dec3a908bfa395095e80e4a532cff98612b624de
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
17fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevpackage com.android.launcher3.dragndrop;
1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.Animator;
20716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.AnimatorListenerAdapter;
21716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.TimeInterpolator;
22716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.ValueAnimator;
23716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.ValueAnimator.AnimatorUpdateListener;
2431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
25716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.content.res.Resources;
26360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chungimport android.graphics.Canvas;
270fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyalimport android.graphics.Color;
286788269814a678af976dfc7d6135993e172ce586Adam Cohenimport android.graphics.Rect;
2995cdb3a0211650e76adb451588ce89fd585b178fTony Wickhamimport android.graphics.Region;
3031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet;
3126279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkeyimport android.view.KeyEvent;
3208ca40f97670ad56ea01a81a439e89a484f9fdb5Sunny Goyalimport android.view.LayoutInflater;
3326279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkeyimport android.view.MotionEvent;
3426279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkeyimport android.view.View;
3526279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkeyimport android.view.ViewGroup;
363371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohenimport android.view.accessibility.AccessibilityEvent;
373371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohenimport android.view.accessibility.AccessibilityManager;
38716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.view.animation.DecelerateInterpolator;
393e8f811f31a2275e778244427271f77f4116c08bAdam Cohenimport android.view.animation.Interpolator;
4031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.widget.FrameLayout;
41ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohenimport android.widget.TextView;
4231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
43740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyalimport com.android.launcher3.AbstractFloatingView;
44fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.AppWidgetResizeFrame;
45fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.CellLayout;
461bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickhamimport com.android.launcher3.DropTargetBar;
47740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyalimport com.android.launcher3.ExtendedEditText;
48fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.InsettableFrameLayout;
49fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.Launcher;
50fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.LauncherAppWidgetHostView;
51dadb304b4682998c43b9c07bef45b9a9380f3287Tony Wickhamimport com.android.launcher3.PinchToOverviewListener;
52f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.R;
53fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.ShortcutAndWidgetContainer;
54fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.Utilities;
55645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Songimport com.android.launcher3.allapps.AllAppsTransitionController;
569c43182ff1d095b1bbaacedefe6e0f4c2deb17e3Tony Wickhamimport com.android.launcher3.config.FeatureFlags;
57261194387beebaa7927ec4e310274218b651494dSunny Goyalimport com.android.launcher3.folder.Folder;
58261194387beebaa7927ec4e310274218b651494dSunny Goyalimport com.android.launcher3.folder.FolderIcon;
593333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyalimport com.android.launcher3.keyboard.ViewGroupFocusHelper;
60091440a9cb9d4f42406631004aa484cbb79214caAdam Cohenimport com.android.launcher3.util.Thunk;
61645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Songimport com.android.launcher3.util.TouchController;
62bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
631d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohenimport java.util.ArrayList;
646788269814a678af976dfc7d6135993e172ce586Adam Cohen
6531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
660e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka * A ViewGroup that coordinates dragging across its descendants
6731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
68a6d0492e5f0dd4e1b43d4034a770241dc65f8f8cAdam Cohenpublic class DragLayer extends InsettableFrameLayout {
690fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyal
70b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal    public static final int ANIMATION_END_DISAPPEAR = 0;
71b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal    public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
72b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal
730fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyal    // Scrim color without any alpha component.
740fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyal    private static final int SCRIM_COLOR = Color.BLACK & 0x00FFFFFF;
750fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyal
76b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal    private final int[] mTmpXY = new int[2];
77b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal
78091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk DragController mDragController;
7931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
80716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private Launcher mLauncher;
81716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
826788269814a678af976dfc7d6135993e172ce586Adam Cohen    // Variables relating to resizing widgets
837066003b2032a49ae5e59dab9b706259bdeb7e6eSunny Goyal    private final boolean mIsRtl;
846788269814a678af976dfc7d6135993e172ce586Adam Cohen    private AppWidgetResizeFrame mCurrentResizeFrame;
85716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
86716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    // Variables relating to animation of views after drop
87716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private ValueAnimator mDropAnim = null;
88b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal    private final TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
89091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk DragView mDropView = null;
90091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk int mAnchorViewInitialScrollX = 0;
91091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk View mAnchorView = null;
928dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen
933371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean mHoverPointClosesFolder = false;
94b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal    private final Rect mHitRect = new Rect();
9595cdb3a0211650e76adb451588ce89fd585b178fTony Wickham    private final Rect mHighlightRect = new Rect();
966788269814a678af976dfc7d6135993e172ce586Adam Cohen
97b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    private TouchCompleteListener mTouchCompleteListener;
98b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen
99432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen    private int mTopViewIndex;
1002d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen    private int mChildCountOnLastUpdate = -1;
10155bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi
1026c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen    // Darkening scrim
1036c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen    private float mBackgroundAlpha = 0;
1046c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen
1050f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    // Related to adjacent page hints
1060f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    private final Rect mScrollChildPosition = new Rect();
1073333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal    private final ViewGroupFocusHelper mFocusIndicatorHelper;
1083333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal
109dadb304b4682998c43b9c07bef45b9a9380f3287Tony Wickham    // Related to pinch-to-go-to-overview gesture.
1109c43182ff1d095b1bbaacedefe6e0f4c2deb17e3Tony Wickham    private PinchToOverviewListener mPinchListener = null;
111645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song
112645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    // Handles all apps pull up interaction
113645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    private AllAppsTransitionController mAllAppsController;
114645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song
115645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    private TouchController mActiveController;
11631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
11731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to create a new DragLayer from XML.
11831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
11931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1200e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
12131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
12231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public DragLayer(Context context, AttributeSet attrs) {
12331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs);
124be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung
125be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung        // Disable multitouch across the workspace/all apps/customize tray
126be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung        setMotionEventSplittingEnabled(false);
12721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        setChildrenDrawingOrderEnabled(true);
128360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
129f5440cbd6c0525769d24b890e16313a728831e04Sunny Goyal        mIsRtl = Utilities.isRtl(getResources());
1303333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal        mFocusIndicatorHelper = new ViewGroupFocusHelper(this);
13131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
13231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
133645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    public void setup(Launcher launcher, DragController dragController,
134645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            AllAppsTransitionController allAppsTransitionController) {
1354c98d9235d164680186180974719f551cf935d08Winson Chung        mLauncher = launcher;
136645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        mDragController = dragController;
137645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        mAllAppsController = allAppsTransitionController;
138dadb304b4682998c43b9c07bef45b9a9380f3287Tony Wickham
139e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham        boolean isAccessibilityEnabled = ((AccessibilityManager) mLauncher.getSystemService(
140e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham                Context.ACCESSIBILITY_SERVICE)).isEnabled();
141e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham        onAccessibilityStateChanged(isAccessibilityEnabled);
14231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
14376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
1443333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal    public ViewGroupFocusHelper getFocusIndicatorHelper() {
1453333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal        return mFocusIndicatorHelper;
1463333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal    }
1473333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal
14831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
14931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean dispatchKeyEvent(KeyEvent event) {
15000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
15131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
15231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
153e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham    public void onAccessibilityStateChanged(boolean isAccessibilityEnabled) {
154e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham        mPinchListener = FeatureFlags.LAUNCHER3_DISABLE_PINCH_TO_OVERVIEW || isAccessibilityEnabled
155e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham                ? null : new PinchToOverviewListener(mLauncher);
156e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham    }
157e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham
1587744169812e0d35531e9de258785af1f2ec9bed3Hyunyoung Song    public boolean isEventOverPageIndicator(MotionEvent ev) {
159740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal        return isEventOverView(mLauncher.getWorkspace().getPageIndicator(), ev);
1607744169812e0d35531e9de258785af1f2ec9bed3Hyunyoung Song    }
1617744169812e0d35531e9de258785af1f2ec9bed3Hyunyoung Song
162a9a8a4221709cc3fda48fd80d4213d25183b8bf7Hyunyoung Song    public boolean isEventOverHotseat(MotionEvent ev) {
1631bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        return isEventOverView(mLauncher.getHotseat(), ev);
164a9a8a4221709cc3fda48fd80d4213d25183b8bf7Hyunyoung Song    }
165a9a8a4221709cc3fda48fd80d4213d25183b8bf7Hyunyoung Song
1663371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean isEventOverFolder(Folder folder, MotionEvent ev) {
1671bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        return isEventOverView(folder, ev);
1683371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
1693371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
170ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal    private boolean isEventOverDropTargetBar(MotionEvent ev) {
1711bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        return isEventOverView(mLauncher.getDropTargetBar(), ev);
1721bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham    }
1731bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
17458a9c4b7d2aa3772f56fea32f82cf29d410dc499Hyunyoung Song    public boolean isEventOverView(View view, MotionEvent ev) {
1751bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham        getDescendantRectRelativeToSelf(view, mHitRect);
17647328fd53f43fd0c2ed14ad925dd04483f9229a0Sunny Goyal        return mHitRect.contains((int) ev.getX(), (int) ev.getY());
177ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal    }
178ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal
17976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    private boolean handleTouchDown(MotionEvent ev, boolean intercept) {
180740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal        AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mLauncher);
181740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal        if (topView != null && intercept) {
182740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal            ExtendedEditText textView = topView.getActiveTextView();
183740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal            if (textView != null) {
184740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal                if (!isEventOverView(textView, ev)) {
185740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal                    textView.dispatchBackKey();
186740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal                    return true;
187740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal                }
188740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal            } else if (!isEventOverView(topView, ev)) {
1892f2104ccdfd0f47d20e959982c52d36dfc7760ffTony Wickham                if (isInAccessibleDrag()) {
1902f2104ccdfd0f47d20e959982c52d36dfc7760ffTony Wickham                    // Do not close the container if in drag and drop.
1912f2104ccdfd0f47d20e959982c52d36dfc7760ffTony Wickham                    if (!isEventOverDropTargetBar(ev)) {
1922f2104ccdfd0f47d20e959982c52d36dfc7760ffTony Wickham                        return true;
1932f2104ccdfd0f47d20e959982c52d36dfc7760ffTony Wickham                    }
1942f2104ccdfd0f47d20e959982c52d36dfc7760ffTony Wickham                } else {
195740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal                    topView.close(true);
196740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal
1972f2104ccdfd0f47d20e959982c52d36dfc7760ffTony Wickham                    // We let touches on the original icon go through so that users can launch
1982f2104ccdfd0f47d20e959982c52d36dfc7760ffTony Wickham                    // the app with one tap if they don't find a shortcut they want.
199740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal                    View extendedTouch = topView.getExtendedTouchView();
200740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal                    return extendedTouch == null || !isEventOverView(extendedTouch, ev);
201ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                }
20276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            }
2032801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        }
2046788269814a678af976dfc7d6135993e172ce586Adam Cohen        return false;
2056788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
2066788269814a678af976dfc7d6135993e172ce586Adam Cohen
20731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
20831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onInterceptTouchEvent(MotionEvent ev) {
209b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        int action = ev.getAction();
210b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen
211b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        if (action == MotionEvent.ACTION_DOWN) {
212c001cf562017d08cd48b67de8f377ca08881e70eHyunyoung Song            // Cancel discovery bounce animation when a user start interacting on anywhere on
213c001cf562017d08cd48b67de8f377ca08881e70eHyunyoung Song            // dray layer even if mAllAppsController is NOT the active controller.
214c001cf562017d08cd48b67de8f377ca08881e70eHyunyoung Song            // TODO: handle other input other than touch
215c001cf562017d08cd48b67de8f377ca08881e70eHyunyoung Song            mAllAppsController.cancelDiscoveryAnimation();
21676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            if (handleTouchDown(ev, true)) {
2176788269814a678af976dfc7d6135993e172ce586Adam Cohen                return true;
218d1837cc69eb222371afdd30890f7215d117510f2Patrick Dubroy            }
219b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
220b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            if (mTouchCompleteListener != null) {
221b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen                mTouchCompleteListener.onTouchComplete();
222b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            }
223b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            mTouchCompleteListener = null;
2241b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen        }
22598cbd62e1f6d57ccef1758fb82dd245f7354fb73Tony Wickham        mActiveController = null;
22698cbd62e1f6d57ccef1758fb82dd245f7354fb73Tony Wickham
2276ad72f02fd233f2294222477102e83d721100493Sunny Goyal        if (mCurrentResizeFrame != null
2286ad72f02fd233f2294222477102e83d721100493Sunny Goyal                && mCurrentResizeFrame.onControllerInterceptTouchEvent(ev)) {
2296ad72f02fd233f2294222477102e83d721100493Sunny Goyal            mActiveController = mCurrentResizeFrame;
2306ad72f02fd233f2294222477102e83d721100493Sunny Goyal            return true;
2316ad72f02fd233f2294222477102e83d721100493Sunny Goyal        } else {
2326ad72f02fd233f2294222477102e83d721100493Sunny Goyal            clearResizeFrame();
2336ad72f02fd233f2294222477102e83d721100493Sunny Goyal        }
2346ad72f02fd233f2294222477102e83d721100493Sunny Goyal
2356ad72f02fd233f2294222477102e83d721100493Sunny Goyal        if (mDragController.onControllerInterceptTouchEvent(ev)) {
236645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            mActiveController = mDragController;
237645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            return true;
238645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        }
2391bce7fd342875be8f7c1f82c8cf21d0199c8d544Tony Wickham
2406ad72f02fd233f2294222477102e83d721100493Sunny Goyal        if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && mAllAppsController.onControllerInterceptTouchEvent(ev)) {
241645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            mActiveController = mAllAppsController;
242645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            return true;
243645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        }
244645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song
2456ad72f02fd233f2294222477102e83d721100493Sunny Goyal        if (mPinchListener != null && mPinchListener.onControllerInterceptTouchEvent(ev)) {
246c5b31965d9bcb4c9899e2d1c45b5c95c70bac9f2Tony Wickham            // Stop listening for scrolling etc. (onTouchEvent() handles the rest of the pinch.)
247645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            mActiveController = mPinchListener;
248c5b31965d9bcb4c9899e2d1c45b5c95c70bac9f2Tony Wickham            return true;
249dadb304b4682998c43b9c07bef45b9a9380f3287Tony Wickham        }
250645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        return false;
25131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
25231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
25331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
2543371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    public boolean onInterceptHoverEvent(MotionEvent ev) {
255023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka        if (mLauncher == null || mLauncher.getWorkspace() == null) {
256023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka            return false;
257023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka        }
258740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal        Folder currentFolder = Folder.getOpen(mLauncher);
2593371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        if (currentFolder == null) {
2603371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            return false;
2613371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        } else {
2628b805b17158886035b38261eb611d8641701ae43Michael Jurka                AccessibilityManager accessibilityManager = (AccessibilityManager)
2638b805b17158886035b38261eb611d8641701ae43Michael Jurka                        getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
2648b805b17158886035b38261eb611d8641701ae43Michael Jurka            if (accessibilityManager.isTouchExplorationEnabled()) {
2653371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                final int action = ev.getAction();
266ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                boolean isOverFolderOrSearchBar;
2673371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                switch (action) {
2683371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                    case MotionEvent.ACTION_HOVER_ENTER:
269ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                        isOverFolderOrSearchBar = isEventOverFolder(currentFolder, ev) ||
270ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                            (isInAccessibleDrag() && isEventOverDropTargetBar(ev));
271ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                        if (!isOverFolderOrSearchBar) {
2723371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
2733371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            mHoverPointClosesFolder = true;
2743371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
2753371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        }
276693fbc7f1737d89f11f9ab81558c109f0883ab0eMihail Dumitrescu                        mHoverPointClosesFolder = false;
277693fbc7f1737d89f11f9ab81558c109f0883ab0eMihail Dumitrescu                        break;
2783371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                    case MotionEvent.ACTION_HOVER_MOVE:
279ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                        isOverFolderOrSearchBar = isEventOverFolder(currentFolder, ev) ||
280ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                            (isInAccessibleDrag() && isEventOverDropTargetBar(ev));
281ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                        if (!isOverFolderOrSearchBar && !mHoverPointClosesFolder) {
2823371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
2833371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            mHoverPointClosesFolder = true;
2843371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
285ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                        } else if (!isOverFolderOrSearchBar) {
2863371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
2873371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        }
288693fbc7f1737d89f11f9ab81558c109f0883ab0eMihail Dumitrescu                        mHoverPointClosesFolder = false;
2893371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                }
2903371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            }
2913371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
2923371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
2933371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
2943371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
2953371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private void sendTapOutsideFolderAccessibilityEvent(boolean isEditingName) {
29652851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal        int stringId = isEditingName ? R.string.folder_tap_to_rename : R.string.folder_tap_to_close;
29752851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal        Utilities.sendCustomAccessibilityEvent(
29852851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal                this, AccessibilityEvent.TYPE_VIEW_FOCUSED, getContext().getString(stringId));
29983ca480941b3dd635b62347008fc8d7859d82002Winson Chung    }
30083ca480941b3dd635b62347008fc8d7859d82002Winson Chung
301ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal    private boolean isInAccessibleDrag() {
302ae50284e0a838139c67caf0064a0977c871497faSunny Goyal        return mLauncher.getAccessibilityDelegate().isInAccessibleDrag();
303ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal    }
304ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal
30583ca480941b3dd635b62347008fc8d7859d82002Winson Chung    @Override
30683ca480941b3dd635b62347008fc8d7859d82002Winson Chung    public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
3077d552c8b18cfad9f32fb5028c53960a9f19dc0a8Sunny Goyal        // Shortcuts can appear above folder
308740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal        View topView = AbstractFloatingView.getTopOpenView(mLauncher);
3097d552c8b18cfad9f32fb5028c53960a9f19dc0a8Sunny Goyal        if (topView != null) {
31052851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            if (child == topView) {
31152851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal                return super.onRequestSendAccessibilityEvent(child, event);
31252851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            }
31352851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            if (isInAccessibleDrag() && child instanceof DropTargetBar) {
31452851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal                return super.onRequestSendAccessibilityEvent(child, event);
31552851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            }
31652851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            // Skip propagating onRequestSendAccessibilityEvent for all other children
31752851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            // which are not topView
31852851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            return false;
31983ca480941b3dd635b62347008fc8d7859d82002Winson Chung        }
32083ca480941b3dd635b62347008fc8d7859d82002Winson Chung        return super.onRequestSendAccessibilityEvent(child, event);
32183ca480941b3dd635b62347008fc8d7859d82002Winson Chung    }
32283ca480941b3dd635b62347008fc8d7859d82002Winson Chung
32383ca480941b3dd635b62347008fc8d7859d82002Winson Chung    @Override
32483ca480941b3dd635b62347008fc8d7859d82002Winson Chung    public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) {
325740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal        View topView = AbstractFloatingView.getTopOpenView(mLauncher);
32652851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal        if (topView != null) {
32752851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            // Only add the top view as a child for accessibility when it is open
32852851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            childrenForAccessibility.add(topView);
329ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal
330ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal            if (isInAccessibleDrag()) {
33147328fd53f43fd0c2ed14ad925dd04483f9229a0Sunny Goyal                childrenForAccessibility.add(mLauncher.getDropTargetBar());
332ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal            }
33383ca480941b3dd635b62347008fc8d7859d82002Winson Chung        } else {
33483ca480941b3dd635b62347008fc8d7859d82002Winson Chung            super.addChildrenForAccessibility(childrenForAccessibility);
33583ca480941b3dd635b62347008fc8d7859d82002Winson Chung        }
3363371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
3373371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
3383371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    @Override
3393371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    public boolean onHoverEvent(MotionEvent ev) {
3403371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        // If we've received this, we've already done the necessary handling
3413371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        // in onInterceptHoverEvent. Return true to consume the event.
3423371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
3433371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
3443371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
3453371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    @Override
34631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
3476788269814a678af976dfc7d6135993e172ce586Adam Cohen        int action = ev.getAction();
3486788269814a678af976dfc7d6135993e172ce586Adam Cohen
349b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        if (action == MotionEvent.ACTION_DOWN) {
350b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            if (handleTouchDown(ev, false)) {
351b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen                return true;
352b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            }
353b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
354b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            if (mTouchCompleteListener != null) {
355b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen                mTouchCompleteListener.onTouchComplete();
3566788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
357b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            mTouchCompleteListener = null;
3586788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3596788269814a678af976dfc7d6135993e172ce586Adam Cohen
360645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        if (mActiveController != null) {
3616ad72f02fd233f2294222477102e83d721100493Sunny Goyal            return mActiveController.onControllerTouchEvent(ev);
362645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        }
363645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        return false;
36491a9c9636f10f1e12cd1f660b2e330634fbdc7dcRomain Guy    }
365ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy
36635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    /**
36735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * Determine the rect of the descendant in this DragLayer's coordinates
36835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     *
36935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param descendant The descendant whose coordinates we want to find.
37035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param r The rect into which to place the results.
37135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @return The factor by which this descendant is scaled relative to this DragLayer.
37235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     */
373ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen    public float getDescendantRectRelativeToSelf(View descendant, Rect r) {
374716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mTmpXY[0] = 0;
375716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mTmpXY[1] = 0;
376ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        float scale = getDescendantCoordRelativeToSelf(descendant, mTmpXY);
3777d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
3788dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        r.set(mTmpXY[0], mTmpXY[1],
3797d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen                (int) (mTmpXY[0] + scale * descendant.getMeasuredWidth()),
3807d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen                (int) (mTmpXY[1] + scale * descendant.getMeasuredHeight()));
381ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        return scale;
382716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
38376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
384307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen    public float getLocationInDragLayer(View child, int[] loc) {
38535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        loc[0] = 0;
38635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        loc[1] = 0;
387307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        return getDescendantCoordRelativeToSelf(child, loc);
38835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    }
38935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen
3907d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    public float getDescendantCoordRelativeToSelf(View descendant, int[] coord) {
3917d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        return getDescendantCoordRelativeToSelf(descendant, coord, false);
3927d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    }
3937d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
39435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    /**
39535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * Given a coordinate relative to the descendant, find the coordinate in this DragLayer's
39635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * coordinates.
39735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     *
39835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param descendant The descendant to which the passed coordinate is relative.
39935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param coord The coordinate that we want mapped.
4007d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen     * @param includeRootScroll Whether or not to account for the scroll of the root descendant:
4017d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen     *          sometimes this is relevant as in a child's coordinates within the root descendant.
402307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen     * @return The factor by which this descendant is scaled relative to this DragLayer. Caution
403307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen     *         this scale factor is assumed to be equal in X and Y, and so if at any point this
404307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen     *         assumption fails, we will need to return a pair of scale factors.
40535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     */
4067d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    public float getDescendantCoordRelativeToSelf(View descendant, int[] coord,
4077d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            boolean includeRootScroll) {
408e8b5d20d94cb03878137a7fdf65d7a88270b73f8Sunny Goyal        return Utilities.getDescendantCoordRelativeToAncestor(descendant, this,
409c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung                coord, includeRootScroll);
410c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung    }
411c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung
4127d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    /**
4137d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen     * Inverse of {@link #getDescendantCoordRelativeToSelf(View, int[])}.
4147d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen     */
4155e0e94f0b2ae79770dd07b66441fda6e063e64eaSunny Goyal    public void mapCoordInSelfToDescendant(View descendant, int[] coord) {
4165e0e94f0b2ae79770dd07b66441fda6e063e64eaSunny Goyal        Utilities.mapCoordInSelfToDescendant(descendant, this, coord);
41776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    }
41876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
4193e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    public void getViewRectRelativeToSelf(View v, Rect r) {
4203e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int[] loc = new int[2];
4218dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        getLocationInWindow(loc);
4223e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int x = loc[0];
4233e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int y = loc[1];
424716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
4258dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        v.getLocationInWindow(loc);
4263e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int vX = loc[0];
4273e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int vY = loc[1];
428716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
4293e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int left = vX - x;
4303e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int top = vY - y;
4313e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        r.set(left, top, left + v.getMeasuredWidth(), top + v.getMeasuredHeight());
432716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
433716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
434ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    @Override
435ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    public boolean dispatchUnhandledMove(View focused, int direction) {
4368dd5168b0582a20a4ede5ccfd21d227118fd9743Tony Wickham        // Consume the unhandled move if a container is open, to avoid switching pages underneath.
437740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal        boolean isContainerOpen = AbstractFloatingView.getTopOpenView(mLauncher) != null;
4388dd5168b0582a20a4ede5ccfd21d227118fd9743Tony Wickham        return isContainerOpen || mDragController.dispatchUnhandledMove(focused, direction);
439ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    }
440120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen
441bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    @Override
442bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    public LayoutParams generateLayoutParams(AttributeSet attrs) {
443bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        return new LayoutParams(getContext(), attrs);
444bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    }
445bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
446bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    @Override
447bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    protected LayoutParams generateDefaultLayoutParams() {
448bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
449bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    }
450bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
451bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    // Override to allow type-checking of LayoutParams.
452bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    @Override
453bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
454bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        return p instanceof LayoutParams;
455bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    }
456bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
457bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    @Override
458bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
459bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        return new LayoutParams(p);
460bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    }
461bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
462bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    public static class LayoutParams extends InsettableFrameLayout.LayoutParams {
4636788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int x, y;
4646788269814a678af976dfc7d6135993e172ce586Adam Cohen        public boolean customPosition = false;
4656788269814a678af976dfc7d6135993e172ce586Adam Cohen
466bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        public LayoutParams(Context c, AttributeSet attrs) {
467bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen            super(c, attrs);
468bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        }
469bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
4706788269814a678af976dfc7d6135993e172ce586Adam Cohen        public LayoutParams(int width, int height) {
4716788269814a678af976dfc7d6135993e172ce586Adam Cohen            super(width, height);
4726788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4736788269814a678af976dfc7d6135993e172ce586Adam Cohen
474bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        public LayoutParams(ViewGroup.LayoutParams lp) {
475bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen            super(lp);
476bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        }
477bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
4786788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setWidth(int width) {
4796788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.width = width;
4806788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4816788269814a678af976dfc7d6135993e172ce586Adam Cohen
4826788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getWidth() {
4836788269814a678af976dfc7d6135993e172ce586Adam Cohen            return width;
4846788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4856788269814a678af976dfc7d6135993e172ce586Adam Cohen
4866788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setHeight(int height) {
4876788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.height = height;
4886788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4896788269814a678af976dfc7d6135993e172ce586Adam Cohen
4906788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getHeight() {
4916788269814a678af976dfc7d6135993e172ce586Adam Cohen            return height;
4926788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4936788269814a678af976dfc7d6135993e172ce586Adam Cohen
4946788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setX(int x) {
4956788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.x = x;
4966788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4976788269814a678af976dfc7d6135993e172ce586Adam Cohen
4986788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getX() {
4996788269814a678af976dfc7d6135993e172ce586Adam Cohen            return x;
5006788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5016788269814a678af976dfc7d6135993e172ce586Adam Cohen
5026788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setY(int y) {
5036788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.y = y;
5046788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5056788269814a678af976dfc7d6135993e172ce586Adam Cohen
5066788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getY() {
5076788269814a678af976dfc7d6135993e172ce586Adam Cohen            return y;
5086788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5096788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
5106788269814a678af976dfc7d6135993e172ce586Adam Cohen
5116788269814a678af976dfc7d6135993e172ce586Adam Cohen    protected void onLayout(boolean changed, int l, int t, int r, int b) {
5126788269814a678af976dfc7d6135993e172ce586Adam Cohen        super.onLayout(changed, l, t, r, b);
5136788269814a678af976dfc7d6135993e172ce586Adam Cohen        int count = getChildCount();
5146788269814a678af976dfc7d6135993e172ce586Adam Cohen        for (int i = 0; i < count; i++) {
5156788269814a678af976dfc7d6135993e172ce586Adam Cohen            View child = getChildAt(i);
5166788269814a678af976dfc7d6135993e172ce586Adam Cohen            final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
5176788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (flp instanceof LayoutParams) {
5186788269814a678af976dfc7d6135993e172ce586Adam Cohen                final LayoutParams lp = (LayoutParams) flp;
5196788269814a678af976dfc7d6135993e172ce586Adam Cohen                if (lp.customPosition) {
5206788269814a678af976dfc7d6135993e172ce586Adam Cohen                    child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height);
5216788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
5226788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
5236788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5246788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
5256788269814a678af976dfc7d6135993e172ce586Adam Cohen
5266ad72f02fd233f2294222477102e83d721100493Sunny Goyal    public void clearResizeFrame() {
5276ad72f02fd233f2294222477102e83d721100493Sunny Goyal        if (mCurrentResizeFrame != null) {
5286ad72f02fd233f2294222477102e83d721100493Sunny Goyal            mCurrentResizeFrame.commitResize();
5296ad72f02fd233f2294222477102e83d721100493Sunny Goyal            removeView(mCurrentResizeFrame);
5306ad72f02fd233f2294222477102e83d721100493Sunny Goyal            mCurrentResizeFrame = null;
5316788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5326788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
5336788269814a678af976dfc7d6135993e172ce586Adam Cohen
5346ad72f02fd233f2294222477102e83d721100493Sunny Goyal    public void addResizeFrame(LauncherAppWidgetHostView widget, CellLayout cellLayout) {
5356ad72f02fd233f2294222477102e83d721100493Sunny Goyal        clearResizeFrame();
5366788269814a678af976dfc7d6135993e172ce586Adam Cohen
53708ca40f97670ad56ea01a81a439e89a484f9fdb5Sunny Goyal        mCurrentResizeFrame = (AppWidgetResizeFrame) LayoutInflater.from(mLauncher)
53808ca40f97670ad56ea01a81a439e89a484f9fdb5Sunny Goyal                .inflate(R.layout.app_widget_resize_frame, this, false);
53908ca40f97670ad56ea01a81a439e89a484f9fdb5Sunny Goyal        mCurrentResizeFrame.setupForWidget(widget, cellLayout, this);
54008ca40f97670ad56ea01a81a439e89a484f9fdb5Sunny Goyal        ((LayoutParams) mCurrentResizeFrame.getLayoutParams()).customPosition = true;
5416788269814a678af976dfc7d6135993e172ce586Adam Cohen
54208ca40f97670ad56ea01a81a439e89a484f9fdb5Sunny Goyal        addView(mCurrentResizeFrame);
5436ad72f02fd233f2294222477102e83d721100493Sunny Goyal        mCurrentResizeFrame.snapToWidget(false);
5446788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
545716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
5467bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    public void animateViewIntoPosition(DragView dragView, final int[] pos, float alpha,
5477bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            float scaleX, float scaleY, int animationEndStyle, Runnable onFinishRunnable,
5487bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            int duration) {
549b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        Rect r = new Rect();
550b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        getViewRectRelativeToSelf(dragView, r);
551b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        final int fromX = r.left;
552b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        final int fromY = r.top;
553b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen
5547bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        animateViewIntoPosition(dragView, fromX, fromY, pos[0], pos[1], alpha, 1, 1, scaleX, scaleY,
555ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                onFinishRunnable, animationEndStyle, duration, null);
556ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
557ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
558557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung    public void animateViewIntoPosition(DragView dragView, final View child,
55928f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen            final Runnable onFinishAnimationRunnable, View anchorView) {
56028f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen        animateViewIntoPosition(dragView, child, -1, onFinishAnimationRunnable, anchorView);
561ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen    }
562ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen
563ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen    public void animateViewIntoPosition(DragView dragView, final View child, int duration,
5646441de0ec2a71862798dd51180d0811b42edd514Adam Cohen            final Runnable onFinishAnimationRunnable, View anchorView) {
565a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka        ShortcutAndWidgetContainer parentChildren = (ShortcutAndWidgetContainer) child.getParent();
566716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        CellLayout.LayoutParams lp =  (CellLayout.LayoutParams) child.getLayoutParams();
567eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung        parentChildren.measureChild(child);
568716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
5693e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        Rect r = new Rect();
5703e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        getViewRectRelativeToSelf(dragView, r);
571716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
572716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        int coord[] = new int[2];
573307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        float childScale = child.getScaleX();
574307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        coord[0] = lp.x + (int) (child.getMeasuredWidth() * (1 - childScale) / 2);
575307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        coord[1] = lp.y + (int) (child.getMeasuredHeight() * (1 - childScale) / 2);
576eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung
5778dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        // Since the child hasn't necessarily been laid out, we force the lp to be updated with
578ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        // the correct coordinates (above) and use these to determine the final location
579557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        float scale = getDescendantCoordRelativeToSelf((View) child.getParent(), coord);
580307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        // We need to account for the scale of the child itself, as the above only accounts for
581307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        // for the scale in parents.
582307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        scale *= childScale;
583ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        int toX = coord[0];
584ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        int toY = coord[1];
585eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung        float toScale = scale;
5864497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn        if (child instanceof TextView) {
5874497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            TextView tv = (TextView) child;
588eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung            // Account for the source scale of the icon (ie. from AllApps to Workspace, in which
589eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung            // the workspace may have smaller icon bounds).
590eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung            toScale = scale / dragView.getIntrinsicIconScaleFactor();
5914497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn
5924497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            // The child may be scaled (always about the center of the view) so to account for it,
5934497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            // we have to offset the position by the scaled size.  Once we do that, we can center
5944497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            // the drag view about the scaled child view.
595eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung            toY += Math.round(toScale * tv.getPaddingTop());
596eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung            toY -= dragView.getMeasuredHeight() * (1 - toScale) / 2;
59795abbb330ce9bbaf23594245f0f8a795c8118038Sunny Goyal            if (dragView.getDragVisualizeOffset() != null) {
59895abbb330ce9bbaf23594245f0f8a795c8118038Sunny Goyal                toY -=  Math.round(toScale * dragView.getDragVisualizeOffset().y);
59995abbb330ce9bbaf23594245f0f8a795c8118038Sunny Goyal            }
60095abbb330ce9bbaf23594245f0f8a795c8118038Sunny Goyal
6014497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
6024497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn        } else if (child instanceof FolderIcon) {
603ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            // Account for holographic blur padding on the drag view
6045f8afe6280eae34620067696173e71943e1a30a3Winson Chung            toY += Math.round(scale * (child.getPaddingTop() - dragView.getDragRegionTop()));
605c9c57631a985a8e1a4eac17ef0952bd344e281a2Jon Miranda            toY -= scale * dragView.getBlurSizeOutline() / 2;
606307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen            toY -= (1 - scale) * dragView.getMeasuredHeight() / 2;
607ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            // Center in the x coordinate about the target's drawable
608ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
609ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        } else {
610ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            toY -= (Math.round(scale * (dragView.getHeight() - child.getMeasuredHeight()))) / 2;
611ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            toX -= (Math.round(scale * (dragView.getMeasuredWidth()
612ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen                    - child.getMeasuredWidth()))) / 2;
613ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        }
614716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
615ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        final int fromX = r.left;
616ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        final int fromY = r.top;
617716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        child.setVisibility(INVISIBLE);
6188dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        Runnable onCompleteRunnable = new Runnable() {
6198dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            public void run() {
6208dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                child.setVisibility(VISIBLE);
621d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                if (onFinishAnimationRunnable != null) {
622d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                    onFinishAnimationRunnable.run();
623d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                }
6248dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            }
6258dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        };
626eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung        animateViewIntoPosition(dragView, fromX, fromY, toX, toY, 1, 1, 1, toScale, toScale,
627d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                onCompleteRunnable, ANIMATION_END_DISAPPEAR, duration, anchorView);
628557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung    }
629557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung
630d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen    public void animateViewIntoPosition(final DragView view, final int fromX, final int fromY,
631ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            final int toX, final int toY, float finalAlpha, float initScaleX, float initScaleY,
632ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            float finalScaleX, float finalScaleY, Runnable onCompleteRunnable,
633ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            int animationEndStyle, int duration, View anchorView) {
6348dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        Rect from = new Rect(fromX, fromY, fromX +
6358dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                view.getMeasuredWidth(), fromY + view.getMeasuredHeight());
6363e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        Rect to = new Rect(toX, toY, toX + view.getMeasuredWidth(), toY + view.getMeasuredHeight());
637ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        animateView(view, from, to, finalAlpha, initScaleX, initScaleY, finalScaleX, finalScaleY, duration,
638ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                null, null, onCompleteRunnable, animationEndStyle, anchorView);
6393e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    }
6403e8f811f31a2275e778244427271f77f4116c08bAdam Cohen
641b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen    /**
642b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * This method animates a view at the end of a drag and drop animation.
643b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *
644b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param view The view to be animated. This view is drawn directly into DragLayer, and so
645b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        doesn't need to be a child of DragLayer.
646b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param from The initial location of the view. Only the left and top parameters are used.
647b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param to The final location of the view. Only the left and top parameters are used. This
648b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        location doesn't account for scaling, and so should be centered about the desired
649b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        final location (including scaling).
650b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param finalAlpha The final alpha of the view, in case we want it to fade as it animates.
6516178f13e2d1f0c1a89cea74538b51993ef3439e3Sunny Goyal     * @param finalScaleX The final scale of the view. The view is scaled about its center.
6526178f13e2d1f0c1a89cea74538b51993ef3439e3Sunny Goyal     * @param finalScaleY The final scale of the view. The view is scaled about its center.
653b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param duration The duration of the animation.
654b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param motionInterpolator The interpolator to use for the location of the view.
655b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param alphaInterpolator The interpolator to use for the alpha of the view.
656b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param onCompleteRunnable Optional runnable to run on animation completion.
6576178f13e2d1f0c1a89cea74538b51993ef3439e3Sunny Goyal     * @param animationEndStyle Whether or not to fade out the view once the animation completes.
6586178f13e2d1f0c1a89cea74538b51993ef3439e3Sunny Goyal     *        {@link #ANIMATION_END_DISAPPEAR} or {@link #ANIMATION_END_REMAIN_VISIBLE}.
6596441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     * @param anchorView If not null, this represents the view which the animated view stays
6606441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     *        anchored to in case scrolling is currently taking place. Note: currently this is
6616441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     *        only used for the X dimension for the case of the workspace.
662b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     */
6637bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    public void animateView(final DragView view, final Rect from, final Rect to,
6647bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final float finalAlpha, final float initScaleX, final float initScaleY,
6657bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final float finalScaleX, final float finalScaleY, int duration,
6667bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final Interpolator motionInterpolator, final Interpolator alphaInterpolator,
6677bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final Runnable onCompleteRunnable, final int animationEndStyle, View anchorView) {
6687bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
669716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        // Calculate the duration of the animation based on the object's distance
670f7a29e83f06909b378dba39c83a522375682710aSunny Goyal        final float dist = (float) Math.hypot(to.left - from.left, to.top - from.top);
671716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        final Resources res = getResources();
672716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        final float maxDist = (float) res.getInteger(R.integer.config_dropAnimMaxDist);
6733e8f811f31a2275e778244427271f77f4116c08bAdam Cohen
6743e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        // If duration < 0, this is a cue to compute the duration based on the distance
6753e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        if (duration < 0) {
676dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal            duration = res.getInteger(R.integer.config_dropAnimMaxDuration);
677dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal            if (dist < maxDist) {
678dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal                duration *= mCubicEaseOutInterpolator.getInterpolation(dist / maxDist);
6793e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            }
680dec3a908bfa395095e80e4a532cff98612b624deSunny Goyal            duration = Math.max(duration, res.getInteger(R.integer.config_dropAnimMinDuration));
681716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        }
682716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
683043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Fall back to cubic ease out interpolator for the animation if none is specified
684043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        TimeInterpolator interpolator = null;
6853e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        if (alphaInterpolator == null || motionInterpolator == null) {
686043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            interpolator = mCubicEaseOutInterpolator;
6873e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        }
688716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
689043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Animate the view
6907bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        final float initAlpha = view.getAlpha();
691043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float dropViewScale = view.getScaleX();
692043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        AnimatorUpdateListener updateCb = new AnimatorUpdateListener() {
693043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            @Override
694716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen            public void onAnimationUpdate(ValueAnimator animation) {
695716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen                final float percent = (Float) animation.getAnimatedValue();
6967bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                final int width = view.getMeasuredWidth();
6977bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                final int height = view.getMeasuredHeight();
698716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
6993e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                float alphaPercent = alphaInterpolator == null ? percent :
7003e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                        alphaInterpolator.getInterpolation(percent);
7013e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                float motionPercent = motionInterpolator == null ? percent :
7023e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                        motionInterpolator.getInterpolation(percent);
703a1cdab039292f3d809528c0e2e38580b37864d8dWinson Chung
7047bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float initialScaleX = initScaleX * dropViewScale;
7057bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float initialScaleY = initScaleY * dropViewScale;
7067bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float scaleX = finalScaleX * percent + initialScaleX * (1 - percent);
7077bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float scaleY = finalScaleY * percent + initialScaleY * (1 - percent);
7087bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float alpha = finalAlpha * alphaPercent + initAlpha * (1 - alphaPercent);
7097bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
7107bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float fromLeft = from.left + (initialScaleX - 1f) * width / 2;
7117bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float fromTop = from.top + (initialScaleY - 1f) * height / 2;
7127bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
7137bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int x = (int) (fromLeft + Math.round(((to.left - fromLeft) * motionPercent)));
7147bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int y = (int) (fromTop + Math.round(((to.top - fromTop) * motionPercent)));
7157bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
71628f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen                int anchorAdjust = mAnchorView == null ? 0 : (int) (mAnchorView.getScaleX() *
71728f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen                    (mAnchorViewInitialScrollX - mAnchorView.getScrollX()));
71828f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen
71928f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen                int xPos = x - mDropView.getScrollX() + anchorAdjust;
7207bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int yPos = y - mDropView.getScrollY();
7217bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
7227bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setTranslationX(xPos);
7237bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setTranslationY(yPos);
7247bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setScaleX(scaleX);
7257bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setScaleY(scaleY);
7267bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setAlpha(alpha);
727716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen            }
728043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        };
729043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        animateView(view, updateCb, duration, interpolator, onCompleteRunnable, animationEndStyle,
730043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                anchorView);
731043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
732043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
733043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    public void animateView(final DragView view, AnimatorUpdateListener updateCb, int duration,
734043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            TimeInterpolator interpolator, final Runnable onCompleteRunnable,
735043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            final int animationEndStyle, View anchorView) {
736043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Clean up the previous animations
737043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mDropAnim != null) mDropAnim.cancel();
738043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
739043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Show the drop view if it was previously hidden
740043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropView = view;
741043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropView.cancelAnimation();
742d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev        mDropView.requestLayout();
743043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
744043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Set the anchor view if the page is scrolling
745043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (anchorView != null) {
746043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mAnchorViewInitialScrollX = anchorView.getScrollX();
747043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
748043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mAnchorView = anchorView;
749043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
750043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Create and start the animation
751043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim = new ValueAnimator();
752043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setInterpolator(interpolator);
753043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setDuration(duration);
754043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setFloatValues(0f, 1f);
755043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.addUpdateListener(updateCb);
7563e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        mDropAnim.addListener(new AnimatorListenerAdapter() {
7573e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            public void onAnimationEnd(Animator animation) {
7588dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                if (onCompleteRunnable != null) {
7598dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                    onCompleteRunnable.run();
7608dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                }
761ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                switch (animationEndStyle) {
762ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                case ANIMATION_END_DISAPPEAR:
763ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    clearAnimatedView();
764ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    break;
765ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                case ANIMATION_END_REMAIN_VISIBLE:
766ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    break;
7673e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                }
7683e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            }
7693e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        });
770716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mDropAnim.start();
771716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
772716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
773ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public void clearAnimatedView() {
7747bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        if (mDropAnim != null) {
7757bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            mDropAnim.cancel();
7767bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        }
7777bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        if (mDropView != null) {
7782d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen            mDragController.onDeferredEndDrag(mDropView);
7797bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        }
780ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        mDropView = null;
781ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        invalidate();
782ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
783ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
784ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public View getAnimatedView() {
785ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        return mDropView;
786ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
787ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
788716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    @Override
7898b805b17158886035b38261eb611d8641701ae43Michael Jurka    public void onChildViewAdded(View parent, View child) {
790a6d0492e5f0dd4e1b43d4034a770241dc65f8f8cAdam Cohen        super.onChildViewAdded(parent, child);
79121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        updateChildIndices();
79221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
79321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
79421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    @Override
7958b805b17158886035b38261eb611d8641701ae43Michael Jurka    public void onChildViewRemoved(View parent, View child) {
79621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        updateChildIndices();
79721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
79821b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
799432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen    @Override
800432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen    public void bringChildToFront(View child) {
801432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        super.bringChildToFront(child);
802432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        updateChildIndices();
803432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen    }
804432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen
80521b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    private void updateChildIndices() {
806432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        mTopViewIndex = -1;
80755bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi        int childCount = getChildCount();
80855bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi        for (int i = 0; i < childCount; i++) {
809b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen            if (getChildAt(i) instanceof DragView) {
810432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen                mTopViewIndex = i;
81155bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi            }
81221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        }
8132d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen        mChildCountOnLastUpdate = childCount;
81421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
81521b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
81621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    @Override
81721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    protected int getChildDrawingOrder(int childCount, int i) {
8182d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen        if (mChildCountOnLastUpdate != childCount) {
8192d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen            // between platform versions 17 and 18, behavior for onChildViewRemoved / Added changed.
8202d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen            // Pre-18, the child was not added / removed by the time of those callbacks. We need to
8212d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen            // force update our representation of things here to avoid crashing on pre-18 devices
8222d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen            // in certain instances.
8232d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen            updateChildIndices();
8242d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen        }
8252d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen
826432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        // i represents the current draw iteration
827432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        if (mTopViewIndex == -1) {
828432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen            // in general we do nothing
82921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            return i;
830432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        } else if (i == childCount - 1) {
831432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen            // if we have a top index, we return it when drawing last item (highest z-order)
832432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen            return mTopViewIndex;
833432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        } else if (i < mTopViewIndex) {
83421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            return i;
83555bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi        } else {
836432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen            // for indexes greater than the top index, we fetch one item above to shift for the
837432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen            // displacement of the top index
838432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen            return i + 1;
83921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        }
84021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
841360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
84295cdb3a0211650e76adb451588ce89fd585b178fTony Wickham    public void invalidateScrim() {
84395cdb3a0211650e76adb451588ce89fd585b178fTony Wickham        if (mBackgroundAlpha > 0.0f) {
84495cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            invalidate();
84595cdb3a0211650e76adb451588ce89fd585b178fTony Wickham        }
84695cdb3a0211650e76adb451588ce89fd585b178fTony Wickham    }
84795cdb3a0211650e76adb451588ce89fd585b178fTony Wickham
848360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    @Override
849360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    protected void dispatchDraw(Canvas canvas) {
8500fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyal        // Draw the background below children.
8510fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyal        if (mBackgroundAlpha > 0.0f) {
85295cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            // Update the scroll position first to ensure scrim cutout is in the right place.
85395cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            mLauncher.getWorkspace().computeScrollWithoutInvalidation();
85495cdb3a0211650e76adb451588ce89fd585b178fTony Wickham
8556c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen            int alpha = (int) (mBackgroundAlpha * 255);
85695cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            CellLayout currCellLayout = mLauncher.getWorkspace().getCurrentDragOverlappingLayout();
85795cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            canvas.save();
85895cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            if (currCellLayout != null && currCellLayout != mLauncher.getHotseat().getLayout()) {
85995cdb3a0211650e76adb451588ce89fd585b178fTony Wickham                // Cut a hole in the darkening scrim on the page that should be highlighted, if any.
8606178f13e2d1f0c1a89cea74538b51993ef3439e3Sunny Goyal                getDescendantRectRelativeToSelf(currCellLayout, mHighlightRect);
86195cdb3a0211650e76adb451588ce89fd585b178fTony Wickham                canvas.clipRect(mHighlightRect, Region.Op.DIFFERENCE);
86295cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            }
8630fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyal            canvas.drawColor((alpha << 24) | SCRIM_COLOR);
86495cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            canvas.restore();
8656c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen        }
8666c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen
8673333b0ced8e6743c41909f6f6b916f1f9ec5a004Sunny Goyal        mFocusIndicatorHelper.draw(canvas);
868360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        super.dispatchDraw(canvas);
8698cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen    }
870360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
8716c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen    public void setBackgroundAlpha(float alpha) {
8726c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen        if (alpha != mBackgroundAlpha) {
8736c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen            mBackgroundAlpha = alpha;
8746c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen            invalidate();
8756c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen        }
8766c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen    }
8776c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen
8786c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen    public float getBackgroundAlpha() {
8796c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen        return mBackgroundAlpha;
8806c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen    }
8816c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen
88252851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal    @Override
88352851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
884740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal        View topView = AbstractFloatingView.getTopOpenView(mLauncher);
88552851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal        if (topView != null) {
88652851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            return topView.requestFocus(direction, previouslyFocusedRect);
88752851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal        } else {
88852851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
88952851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal        }
89052851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal    }
89152851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal
89252851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal    @Override
89352851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
894740ac7f00e0b847b8e392800f7948d93493e11d6Sunny Goyal        View topView = AbstractFloatingView.getTopOpenView(mLauncher);
89552851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal        if (topView != null) {
89652851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            topView.addFocusables(views, direction);
89752851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal        } else {
89852851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal            super.addFocusables(views, direction, focusableMode);
89952851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal        }
90052851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal    }
90152851aa3fd2dd9957e190d779f904f6abaf53fedSunny Goyal
902b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    public void setTouchCompleteListener(TouchCompleteListener listener) {
903b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        mTouchCompleteListener = listener;
904b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    }
905b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen
906b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    public interface TouchCompleteListener {
907b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        public void onTouchComplete();
908b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    }
90931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
910