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

Commit 2c095f36 authored by Christopher Tate's avatar Christopher Tate
Browse files

Refinements to drag/drop

Thumbnail measurement & drawing has been moved out into a delegate
class called View.DragThumbnailBuilder.  This consolidates the
thumbnail-related code as well as ensuring that the drag initiator
does not have to know a priori where to place the thumbnail relative
to the touch point *before* the thumbnail measurement step, as was
previously the case.

startDrag() no longer needs to be told where the current touch point
is at the time the drag is launched.

Drag events are now dispatched only to VISIBLE views.

Dispatch shouldn't double-recycle events any more when the target
window is local to the system process.

Change-Id: I49419103765a0cad2e18ddfcdd6dacb94daf1ff1
parent b6b19301
Loading
Loading
Loading
Loading
+58 −9
Original line number Diff line number Diff line
@@ -189909,6 +189909,16 @@
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="action" type="int">
</parameter>
<parameter name="x" type="float">
</parameter>
<parameter name="y" type="float">
</parameter>
<parameter name="description" type="android.content.ClipDescription">
</parameter>
<parameter name="data" type="android.content.ClipData">
</parameter>
</method>
<method name="obtain"
 return="android.view.DragEvent"
@@ -189920,15 +189930,7 @@
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="action" type="int">
</parameter>
<parameter name="x" type="float">
</parameter>
<parameter name="y" type="float">
</parameter>
<parameter name="description" type="android.content.ClipDescription">
</parameter>
<parameter name="data" type="android.content.ClipData">
<parameter name="source" type="android.view.DragEvent">
</parameter>
</method>
<method name="recycle"
@@ -203415,6 +203417,53 @@
>
</field>
</class>
<class name="View.DragThumbnailBuilder"
 extends="java.lang.Object"
 abstract="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<constructor name="View.DragThumbnailBuilder"
 type="android.view.View.DragThumbnailBuilder"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="view" type="android.view.View">
</parameter>
</constructor>
<method name="onDrawThumbnail"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="canvas" type="android.graphics.Canvas">
</parameter>
</method>
<method name="onProvideThumbnailMetrics"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="thumbnailSize" type="android.graphics.Point">
</parameter>
<parameter name="thumbnailTouchPoint" type="android.graphics.Point">
</parameter>
</method>
</class>
<class name="View.MeasureSpec"
 extends="java.lang.Object"
 abstract="false"
+7 −2
Original line number Diff line number Diff line
@@ -50,10 +50,10 @@ public class DragEvent implements Parcelable {
    public static final int ACTION_DRAG_EXITED = 6;

    /* hide the constructor behind package scope */
    DragEvent() {
    private DragEvent() {
    }

    public static DragEvent obtain() {
    static DragEvent obtain() {
        return DragEvent.obtain(0, 0f, 0f, null, null);
    }

@@ -81,6 +81,11 @@ public class DragEvent implements Parcelable {
        return ev;
    }

    public static DragEvent obtain(DragEvent source) {
        return obtain(source.mAction, source.mX, source.mY,
                source.mClipDescription, source.mClipData);
    }

    public int getAction() {
        return mAction;
    }
+0 −2
Original line number Diff line number Diff line
@@ -17,8 +17,6 @@

package android.view;

import android.content.ClipData;
import android.content.ClipDescription;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
+80 −19
Original line number Diff line number Diff line
@@ -615,7 +615,6 @@ import java.util.WeakHashMap;
 */
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
    private static final boolean DBG = false;
    static final boolean DEBUG_DRAG = true;

    /**
     * The logging tag used by this class with android.util.Log.
@@ -3957,6 +3956,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
        return true;
    }

    /** Gets the ViewRoot, or null if not attached. */
    /*package*/ ViewRoot getViewRoot() {
        View root = getRootView();
        return root != null ? (ViewRoot)root.getParent() : null;
    }

    /**
     * Call this to try to give focus to a specific view or to one of its descendants. This is a
     * special variant of {@link #requestFocus() } that will allow views that are not focuable in
@@ -3970,14 +3975,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
    public final boolean requestFocusFromTouch() {
        // Leave touch mode if we need to
        if (isInTouchMode()) {
            View root = getRootView();
            if (root != null) {
               ViewRoot viewRoot = (ViewRoot)root.getParent();
            ViewRoot viewRoot = getViewRoot();
            if (viewRoot != null) {
                viewRoot.ensureTouchMode(false);
            }
        }
        }
        return requestFocus(View.FOCUS_DOWN);
    }

@@ -9832,6 +9834,56 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
    }

    /**
     * !!! TODO: real docs
     *
     * The base class implementation makes the thumbnail the same size and appearance
     * as the view itself, and positions it with its center at the touch point.
     */
    public class DragThumbnailBuilder {
        private View mView;

        /**
         * Construct a thumbnail builder object for use with the given view.
         * @param view
         */
        public DragThumbnailBuilder(View view) {
            mView = view;
        }

        /**
         * Provide the draggable-thumbnail metrics for the operation: the dimensions of
         * the thumbnail image itself, and the point within that thumbnail that should
         * be centered under the touch location while dragging.
         * <p>
         * The default implementation sets the dimensions of the thumbnail to be the
         * same as the dimensions of the View itself and centers the thumbnail under
         * the touch point.
         *
         * @param thumbnailSize The application should set the {@code x} member of this
         *        parameter to the desired thumbnail width, and the {@code y} member to
         *        the desired height.
         * @param thumbnailTouchPoint The application should set this point to be the
         *        location within the thumbnail that should track directly underneath
         *        the touch point on the screen during a drag.
         */
        public void onProvideThumbnailMetrics(Point thumbnailSize, Point thumbnailTouchPoint) {
            thumbnailSize.set(mView.getWidth(), mView.getHeight());
            thumbnailTouchPoint.set(thumbnailSize.x / 2, thumbnailSize.y / 2);
        }

        /**
         * Draw the thumbnail image for the upcoming drag.  The thumbnail canvas was
         * created with the dimensions supplied by the onProvideThumbnailMetrics()
         * callback.
         *
         * @param canvas
         */
        public void onDrawThumbnail(Canvas canvas) {
            mView.draw(canvas);
        }
    }

    /**
     * Drag and drop.  App calls startDrag(), then callbacks to onMeasureDragThumbnail()
     * and onDrawDragThumbnail() happen, then the drag operation is handed over to the
@@ -9839,34 +9891,43 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
     * !!! TODO: real docs
     * @hide
     */
    public final boolean startDrag(ClipData data, float touchX, float touchY,
            float thumbnailTouchX, float thumbnailTouchY, boolean myWindowOnly) {
        if (DEBUG_DRAG) {
            Log.d(VIEW_LOG_TAG, "startDrag: touch=(" + touchX + "," + touchY
                    + ") thumb=(" + thumbnailTouchX + "," + thumbnailTouchY
                    + ") data=" + data + " local=" + myWindowOnly);
    public final boolean startDrag(ClipData data, DragThumbnailBuilder thumbBuilder,
            boolean myWindowOnly) {
        if (ViewDebug.DEBUG_DRAG) {
            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " local=" + myWindowOnly);
        }
        boolean okay = false;

        measureThumbnail();     // throws if the view fails to specify dimensions
        Point thumbSize = new Point();
        Point thumbTouchPoint = new Point();
        thumbBuilder.onProvideThumbnailMetrics(thumbSize, thumbTouchPoint);

        if ((thumbSize.x < 0) || (thumbSize.y < 0) ||
                (thumbTouchPoint.x < 0) || (thumbTouchPoint.y < 0)) {
            throw new IllegalStateException("Drag thumb dimensions must not be negative");
        }

        Surface surface = new Surface();
        try {
            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
                    myWindowOnly, mThumbnailWidth, mThumbnailHeight, surface);
            if (DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
                    + " surface=" + surface);
            if (token != null) {
                Canvas canvas = surface.lockCanvas(null);
                try {
                    onDrawDragThumbnail(canvas);
                    thumbBuilder.onDrawThumbnail(canvas);
                } finally {
                    surface.unlockCanvasAndPost(canvas);
                }

                // repurpose 'thumbSize' for the last touch point
                getViewRoot().getLastTouchPoint(thumbSize);

                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
                        touchX, touchY, thumbnailTouchX, thumbnailTouchY, data);
                if (DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
                        (float) thumbSize.x, (float) thumbSize.y,
                        (float) thumbTouchPoint.x, (float) thumbTouchPoint.y, data);
                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
            }
        } catch (Exception e) {
            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
@@ -9888,7 +9949,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
                    + " measured dimension by calling setDragThumbnailDimension()");
        }

        if (DEBUG_DRAG) {
        if (ViewDebug.DEBUG_DRAG) {
            Log.d(VIEW_LOG_TAG, "Drag thumb measured: w=" + mThumbnailWidth
                    + " h=" + mThumbnailHeight);
        }
+6 −0
Original line number Diff line number Diff line
@@ -135,6 +135,12 @@ public class ViewDebug {
     */
    public static final boolean DEBUG_SHOW_FPS = false;

    /**
     * Enables detailed logging of drag/drop operations.
     * @hide
     */
    public static final boolean DEBUG_DRAG = true;

    /**
     * <p>Enables or disables views consistency check. Even when this property is enabled,
     * view consistency checks happen only if {@link android.util.Config#DEBUG} is set
Loading