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

Commit 4b7b90e7 authored by Nikita Dubrovsky's avatar Nikita Dubrovsky
Browse files

Integrate OnReceiveContentListener in View.onDragEvent

OnReceiveContentListener was already integrated with drag-and-drop
in TextView. The change extends support to all subclasses of View.

If an OnReceiveContentListener is set on the view, the default
implementation of View.onDragEvent will now return true for an
ACTION_DRAG_STARTED event and will call
View.performReceiveContent for an ACTION_DROP event.

Bug: 182617122
Test: atest CtsWindowManagerDeviceTestCases:CrossAppDragAndDropTests
Test: atest CtsViewTestCases:ViewOnReceiveContentTest
Test: atest CtsWidgetTestCases:TextViewOnReceiveContentTest
Test: Manually using ReceiveContentDemo
Change-Id: I98fb703220ebd1953b20dcab60d22847cc5000d8
parent 910746fe
Loading
Loading
Loading
Loading
+34 −0
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package android.view;
package android.view;
import static android.content.res.Resources.ID_NULL;
import static android.content.res.Resources.ID_NULL;
import static android.view.ContentInfo.SOURCE_DRAG_AND_DROP;
import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_BOUNDS;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_BOUNDS;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW;
@@ -26747,6 +26748,21 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
     * in DragEvent. The method uses these to determine what is happening in the drag and drop
     * in DragEvent. The method uses these to determine what is happening in the drag and drop
     * operation.
     * operation.
     * </p>
     * <p>
     * The default implementation returns false, except if an {@link OnReceiveContentListener}
     * is {@link #setOnReceiveContentListener set} for this view. If an
     * {@link OnReceiveContentListener} is set, the default implementation...
     * <ul>
     * <li>returns true for an
     * {@link android.view.DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} event
     * <li>calls {@link #performReceiveContent} for an
     * {@link android.view.DragEvent#ACTION_DROP ACTION_DROP} event
     * <li>returns true for an {@link android.view.DragEvent#ACTION_DROP ACTION_DROP} event, if
     * the listener consumed some or all of the content
     * </ul>
     * </p>
     *
     * @param event The {@link android.view.DragEvent} sent by the system.
     * @param event The {@link android.view.DragEvent} sent by the system.
     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
     * in DragEvent, indicating the type of drag event represented by this object.
     * in DragEvent, indicating the type of drag event represented by this object.
@@ -26766,6 +26782,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * </p>
     * </p>
     */
     */
    public boolean onDragEvent(DragEvent event) {
    public boolean onDragEvent(DragEvent event) {
        if (mListenerInfo == null || mListenerInfo.mOnReceiveContentListener == null) {
            return false;
        }
        // Accept drag events by default if there's an OnReceiveContentListener set.
        if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
            return true;
        }
        if (event.getAction() == DragEvent.ACTION_DROP) {
            final DragAndDropPermissions permissions = DragAndDropPermissions.obtain(event);
            if (permissions != null) {
                permissions.takeTransient();
            }
            final ContentInfo payload = new ContentInfo.Builder(
                    event.getClipData(), SOURCE_DRAG_AND_DROP).build();
            ContentInfo remainingPayload = performReceiveContent(payload);
            // Return true unless none of the payload was consumed.
            return remainingPayload != payload;
        }
        return false;
        return false;
    }
    }
+27 −1
Original line number Original line Diff line number Diff line
@@ -13059,11 +13059,37 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        return getLayout().getOffsetForHorizontal(line, x);
        return getLayout().getOffsetForHorizontal(line, x);
    }
    }
    /**
     * Handles drag events sent by the system following a call to
     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
     * startDragAndDrop()}.
     *
     * <p>If this text view is not editable, delegates to the default {@link View#onDragEvent}
     * implementation.
     *
     * <p>If this text view is editable, accepts all drag actions (returns true for an
     * {@link android.view.DragEvent#ACTION_DRAG_STARTED ACTION_DRAG_STARTED} event and all
     * subsequent drag events). While the drag is in progress, updates the cursor position
     * to follow the touch location. Once a drop event is received, handles content insertion
     * via {@link #performReceiveContent}.
     *
     * @param event The {@link android.view.DragEvent} sent by the system.
     * The {@link android.view.DragEvent#getAction()} method returns an action type constant
     * defined in DragEvent, indicating the type of drag event represented by this object.
     * @return Returns true if this text view is editable and delegates to super otherwise.
     * See {@link View#onDragEvent}.
     */
    @Override
    @Override
    public boolean onDragEvent(DragEvent event) {
    public boolean onDragEvent(DragEvent event) {
        if (mEditor == null || !mEditor.hasInsertionController()) {
            // If this TextView is not editable, defer to the default View implementation. This
            // will check for the presence of an OnReceiveContentListener and accept/reject
            // drag events depending on whether the listener is/isn't set.
            return super.onDragEvent(event);
        }
        switch (event.getAction()) {
        switch (event.getAction()) {
            case DragEvent.ACTION_DRAG_STARTED:
            case DragEvent.ACTION_DRAG_STARTED:
                return mEditor != null && mEditor.hasInsertionController();
                return true;
            case DragEvent.ACTION_DRAG_ENTERED:
            case DragEvent.ACTION_DRAG_ENTERED:
                TextView.this.requestFocus();
                TextView.this.requestFocus();