Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8b6f38c7 authored by Vladislav Kaznacheev's avatar Vladislav Kaznacheev
Browse files

'Drag and drop failed' animation

If the drop has not been consumed (DragState.mDragResult is false)
the drag shadow surface is not immediately destroyed, but animated
back into the position where the drag started.

The current animation is an OK placeholder, still waiting for the
final word from UX.

Bug: 24415573

Change-Id: Ia30135ce1e85655c8ba16e28dc69f0ebf9b36239
parent 140913c7
Loading
Loading
Loading
Loading
+72 −3
Original line number Diff line number Diff line
@@ -16,6 +16,14 @@

package com.android.server.wm;

import android.graphics.Matrix;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.Transformation;
import android.view.animation.TranslateAnimation;
import com.android.server.input.InputApplicationHandle;
import com.android.server.input.InputWindowHandle;
import com.android.server.wm.WindowManagerService.DragInputEventReceiver;
@@ -45,6 +53,8 @@ import java.util.ArrayList;
 * Drag/drop state
 */
class DragState {
    private static final long ANIMATION_DURATION_MS = 500;

    final WindowManagerService mService;
    IBinder mToken;
    SurfaceControl mSurfaceControl;
@@ -55,6 +65,8 @@ class DragState {
    ClipData mData;
    ClipDescription mDataDescription;
    boolean mDragResult;
    float mOriginalAlpha;
    float mOriginalX, mOriginalY;
    float mCurrentX, mCurrentY;
    float mThumbOffsetX, mThumbOffsetY;
    InputChannel mServerChannel, mClientChannel;
@@ -69,6 +81,10 @@ class DragState {
    private final Region mTmpRegion = new Region();
    private final Rect mTmpRect = new Rect();

    private Animation mAnimation;
    final Transformation mTransformation = new Transformation();
    private final Interpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);

    DragState(WindowManagerService service, IBinder token, SurfaceControl surface,
            int flags, IBinder localWin) {
        mService = service;
@@ -184,6 +200,9 @@ class DragState {
    /* call out to each visible window/session informing it about the drag
     */
    void broadcastDragStartedLw(final float touchX, final float touchY) {
        mOriginalX = mCurrentX = touchX;
        mOriginalY = mCurrentY = touchY;

        // Cache a base-class instance of the clip metadata so that parceling
        // works correctly in calling out to the apps.
        mDataDescription = (mData != null) ? mData.getDescription() : null;
@@ -294,19 +313,32 @@ class DragState {
    }

    void endDragLw() {
        mService.mDragState.broadcastDragEndedLw();
        if (!mDragResult) {
            mAnimation = createReturnAnimationLocked();
            mService.scheduleAnimationLocked();
            return;  // Will call cleanUpDragLw when the animation is done.
        }
        cleanUpDragLw();
    }


    void cleanUpDragLw() {
        broadcastDragEndedLw();

        // stop intercepting input
        mService.mDragState.unregister();
        unregister();

        // free our resources and drop all the object references
        mService.mDragState.reset();
        reset();
        mService.mDragState = null;

        mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
    }

    void notifyMoveLw(float x, float y) {
        mCurrentX = x;
        mCurrentY = y;

        final int myPid = Process.myPid();

        // Move the surface to the given touch
@@ -378,6 +410,9 @@ class DragState {
    // result from the recipient.
    boolean notifyDropLw(WindowState touchedWin, DropPermissionHolder dropPermissionHolder,
            float x, float y) {
        mCurrentX = x;
        mCurrentY = y;

        if (touchedWin == null) {
            // "drop" outside a valid window -- no recipient to apply a
            // timeout to, and we can send the drag-ended message immediately.
@@ -469,4 +504,38 @@ class DragState {
        return DragEvent.obtain(action, winX, winY, localState, description, data,
                dropPermissionHolder, result);
    }

    boolean stepAnimationLocked(long currentTimeMs) {
        if (mAnimation == null) {
            return false;
        }

        mTransformation.clear();
        if (!mAnimation.getTransformation(currentTimeMs, mTransformation)) {
            cleanUpDragLw();
            return false;
        }

        final float tmpFloats[] = mService.mTmpFloats;
        mTransformation.getMatrix().getValues(tmpFloats);
        mSurfaceControl.setPosition(
                tmpFloats[Matrix.MTRANS_X] - mThumbOffsetX,
                tmpFloats[Matrix.MTRANS_Y] - mThumbOffsetY);
        mSurfaceControl.setAlpha(mTransformation.getAlpha());
        mSurfaceControl.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y],
                tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]);
        return true;
    }

    private Animation createReturnAnimationLocked() {
        final AnimationSet set = new AnimationSet(false);
        set.addAnimation(new TranslateAnimation(
                mCurrentX, mOriginalX, mCurrentY, mOriginalY));
        set.addAnimation(new AlphaAnimation(mOriginalAlpha, mOriginalAlpha / 2));
        set.setDuration(ANIMATION_DURATION_MS);
        set.setInterpolator(mCubicEaseOutInterpolator);
        set.initialize(0, 0, 0, 0);
        set.start();  // Will start on the first call to getTransformation.
        return set;
    }
}
 No newline at end of file
+0 −2
Original line number Diff line number Diff line
@@ -325,8 +325,6 @@ final class Session extends IWindowSession.Stub
            }

            mService.mDragState.mData = data;
            mService.mDragState.mCurrentX = touchX;
            mService.mDragState.mCurrentY = touchY;
            mService.mDragState.broadcastDragStartedLw(touchX, touchY);

            // remember the thumb offsets for later
+4 −0
Original line number Diff line number Diff line
@@ -708,6 +708,10 @@ public class WindowAnimator {
                }
            }

            if (mService.mDragState != null) {
                mAnimating |= mService.mDragState.stepAnimationLocked(mCurrentTime);
            }

            if (mAnimating) {
                mService.scheduleAnimationLocked();
            }
+6 −4
Original line number Diff line number Diff line
@@ -309,6 +309,8 @@ public class WindowManagerService extends IWindowManager.Stub
    // trying to apply a new one.
    private static final boolean ALWAYS_KEEP_CURRENT = true;

    private static final float DRAG_SHADOW_ALPHA_TRANSPARENT = .7071f;

    final private KeyguardDisableHandler mKeyguardDisableHandler;

    final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -753,9 +755,6 @@ public class WindowManagerService extends IWindowManager.Stub
    private boolean completeDropLw(float x, float y) {
        WindowState dropTargetWin = mDragState.getDropTargetWinLw(x, y);

        mDragState.mCurrentX = x;
        mDragState.mCurrentY = y;

        DropPermissionHolder dropPermissionHolder = null;
        if (dropTargetWin != null &&
                (mDragState.mFlags & View.DRAG_FLAG_GLOBAL) != 0 &&
@@ -7175,9 +7174,11 @@ public class WindowManagerService extends IWindowManager.Stub
                        SurfaceControl surface = new SurfaceControl(session, "drag surface",
                                width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
                        surface.setLayerStack(display.getLayerStack());
                        float alpha = 1;
                        if ((flags & View.DRAG_FLAG_OPAQUE) == 0) {
                            surface.setAlpha(.7071f);
                            alpha = DRAG_SHADOW_ALPHA_TRANSPARENT;
                        }
                        surface.setAlpha(alpha);

                        if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DRAG "
                                + surface + ": CREATE");
@@ -7187,6 +7188,7 @@ public class WindowManagerService extends IWindowManager.Stub
                        mDragState = new DragState(this, token, surface, flags, winBinder);
                        mDragState.mPid = callerPid;
                        mDragState.mUid = callerUid;
                        mDragState.mOriginalAlpha = alpha;
                        token = mDragState.mToken = new Binder();

                        // 5 second timeout for this window to actually begin the drag