# Class NativeDragAndDrop

java.lang.Object
com.codename1.ui.NativeDragAndDrop

public final class NativeDragAndDrop extends Object

Drag and drop through the operating system rather than inside the application.

Codename One has always had a lightweight drag and drop -- `Component#setDraggable(boolean)` and `Component#setDropTarget(boolean)` -- which moves a rendered image around inside one form. That never leaves the application, so it cannot drop a file on the desktop, cannot carry text into another application's window, and cannot receive anything from one.

This class is the other half: it hands the drag to the operating system's own drag machinery, using the same `ClipboardContent` a copy publishes as the payload. That is the whole idea -- a drag is a copy that the user aims with the pointer, so anything the application can already put on the clipboard it can already drag out, and anything it can paste it can already accept as a drop.

##### Dragging out

    Label file = new Label("report.pdf");
    file.setNativeDragOperation(NativeDragOperation.createFileDrag(
            new String[] { FileSystemStorage.getInstance().getAppHomePath() + "report.pdf" }));

Dropping that on the desktop, on a mail composer or into a file manager copies the file, because the receiving application asked for `ClipboardContent#MIME_FILE` and the drag offered it. Offer several representations and every receiver takes the best one it understands.

##### Receiving a drop

    Container inbox = new Container();
    inbox.setNativeDropTarget(true);
    inbox.addNativeDropListener(e -> {
        NativeDropEvent drop = (NativeDropEvent)e;
        String[] files = drop.getFiles();
        ...
    });

##### Where it works

Native drag and drop needs the platform to have it. Check `#isSupported()` before offering the affordance, and `#isDragOutsideApplicationSupported()` before promising the user that a drag can leave the application: a desktop can drop onto any other window, a tablet can drop into another application beside it, and a phone in full screen has nowhere for a drag to go even though drags within the application still work. Where nothing is supported the calls here are harmless no-ops and the lightweight drag and drop is unaffected.

##### Threading

The gesture half runs on the event dispatch thread; the receiving half is called from whatever thread the platform hands the port. All of the shared state below is therefore guarded by one lock, and no callback into component or port code is ever made while holding it -- the framework's own event dispatch thread blocks on the platform's UI thread to paint on some ports, so a lock held across a callback is a deadlock waiting for the first drag.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `static void`
  `dragCompleted(int performedAction)`
  Reports that the session started by `#startDrag(com.codename1.ui.Component, com.codename1.ui.NativeDragOperation)` has finished, whatever the outcome, so that a source offering `NativeDragOperation#ACTION_MOVE` learns whether to delete its copy.
  `static int`
  `dragEnter(int windowId, int x, int y, ClipboardContent content, int allowedActions)`
  Reports that a native drag has entered one of the application's surfaces.
  `static void`
  `dragExit(int windowId)`
  Reports that a native drag has left the application's surfaces without dropping.
  `static int`
  `dragOver(int windowId, int x, int y, ClipboardContent content, int allowedActions)`
  Reports that a native drag has moved over one of the application's surfaces, and answers whether it would be accepted here.
  `static NativeDragOperation`
  `dragSessionStarted()`
  Reports that the platform started a drag session on its own, for the operation the press prepared.
  `static int`
  `drop(int windowId, int x, int y, ClipboardContent content, int action)`
  Delivers a native drop.
  `static NativeDragOperation`
  `getActiveDrag()`
  Returns the drag this application is currently running through the operating system, or null when it is not dragging.
  `static boolean`
  `isDragOutsideApplicationSupported()`
  Returns true when a drag started here can be dropped outside the application: on the desktop, in a file manager or in another application's window.
  `static boolean`
  `isSupported()`
  Returns true when this platform can drag and drop through the operating system at all.
  `static int`
  `plannedDropAction(int windowId, int x, int y, ClipboardContent content, int action)`
  The action a drop at this position would perform, without dispatching anything or disturbing the drag in progress.
  `static boolean`
  `startDrag(Component source, NativeDragOperation op)`
  Starts a native drag immediately, for an application that decides on its own that a drag has begun -- from a long press, or a menu item -- rather than letting a component do it through `Component#setNativeDragSource(boolean)`.

  ### Methods inherited from class Object

  `clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Method Details

  - ### isSupported

    public static boolean isSupported()
    Returns true when this platform can drag and drop through the operating system at all. Where this is false every method here does nothing and reports failure, so no call site needs to be conditional -- but an application that shows a "drag me" affordance should hide it.

  - ### isDragOutsideApplicationSupported

    public static boolean isDragOutsideApplicationSupported()

    Returns true when a drag started here can be dropped outside the application: on the desktop, in a file manager or in another application's window.

    This is narrower than `#isSupported()`. A platform can route drags between components, and between this application's own windows, while still refusing to let one leave -- which is the normal state of affairs on a phone.

  - ### startDrag

    public static boolean startDrag(Component source, NativeDragOperation op)

    Starts a native drag immediately, for an application that decides on its own that a drag has begun -- from a long press, or a menu item -- rather than letting a component do it through `Component#setNativeDragSource(boolean)`.

    Call this on the event dispatch thread while the pointer is still down; a drag the user is not currently holding cannot be aimed and platforms reject it.

    ###### Parameters

    - `source`: the component the drag comes from, used for the default drag image and reported by `NativeDragOperation#getSource()`. May be null.

    - `op`: what is being dragged

    ###### Returns

    true when the operating system took the drag; false when the platform has no native drag and drop, refused to start a session, or is already running one

  - ### dragSessionStarted

    public static NativeDragOperation dragSessionStarted()

    Reports that the platform started a drag session on its own, for the operation the press prepared. Ports whose operating system owns the drag gesture -- where a long press, not the framework's own threshold, is what begins a drag -- call this instead of returning true from `com.codename1.impl.CodenameOneImplementation#startNativeDrag(com.codename1.ui.NativeDragOperation)`.

    ###### Returns

    the operation the session is carrying, or null when nothing was prepared -- in which case the port should refuse to start a session

  - ### getActiveDrag

    public static NativeDragOperation getActiveDrag()
    Returns the drag this application is currently running through the operating system, or null when it is not dragging. A drop target uses this to tell a drag it started itself from one that arrived from elsewhere, which `NativeDropEvent#isLocal()` reports.

  - ### dragEnter

    public static int dragEnter(int windowId, int x, int y, ClipboardContent content, int allowedActions)

    Reports that a native drag has entered one of the application's surfaces.

    ###### Parameters

    - `windowId`: the id of the window the drag is over, or zero for the main surface

    - `x`: the pointer position within that surface

    - `y`: the pointer position within that surface

    - `content`: the representations the drag is offering

    - `allowedActions`: the actions the source permits

    ###### Returns

    the action a drop would perform right now, or `NativeDragOperation#ACTION_NONE` when nothing under the pointer will take it

  - ### dragOver

    public static int dragOver(int windowId, int x, int y, ClipboardContent content, int allowedActions)

    Reports that a native drag has moved over one of the application's surfaces, and answers whether it would be accepted here.

    ###### Threading

    The operating system needs the answer synchronously, while the framework's callbacks have to run on the event dispatch thread -- and blocking a native drag thread on the event dispatch thread deadlocks, because on some ports the event dispatch thread is itself waiting on that native thread to paint. So the target is resolved here, on the calling thread, from state that does not change under it, while `Component#nativeDragOver(com.codename1.ui.NativeDropEvent)` and the listeners are dispatched asynchronously; the value returned is the one they produced for the previous event on this same target. A target that changes its mind therefore shows the user the new cursor one drag event late, which is a frame, and never blocks.

    A target that refuses a drop outright should say so through `Component#canAcceptNativeDrop(com.codename1.ui.ClipboardContent)` or the accepted MIME list instead, both of which are consulted here and are therefore exact from the first event.

    ###### Parameters

    - `windowId`: the id of the window the drag is over, or zero for the main surface

    - `x`: the pointer position within that surface

    - `y`: the pointer position within that surface

    - `content`: the representations the drag is offering

    - `allowedActions`: the actions the source permits

    ###### Returns

    the action a drop would perform right now, or `NativeDragOperation#ACTION_NONE`

  - ### dragExit

    public static void dragExit(int windowId)

    Reports that a native drag has left the application's surfaces without dropping.

    ###### Parameters

    - `windowId`: the id of the window the drag left, or zero for the main surface

  - ### drop

    public static int drop(int windowId, int x, int y, ClipboardContent content, int action)

    Delivers a native drop.

    The content must be fully materialized before this is called: on most platforms the native transfer object is only readable inside the drop callback, so a port that hands over a lazy view of it delivers empty data by the time the event dispatch thread reads it.

    ###### Parameters

    - `windowId`: the id of the window dropped on, or zero for the main surface

    - `x`: the pointer position within that surface

    - `y`: the pointer position within that surface

    - `content`: the dropped representations

    - `action`: the action the operating system settled on

    ###### Returns

    the action actually accepted, or `NativeDragOperation#ACTION_NONE` when nothing under the pointer took the drop and the port should report the transfer as failed

  - ### plannedDropAction

    public static int plannedDropAction(int windowId, int x, int y, ClipboardContent content, int action)

    The action a drop at this position would perform, without dispatching anything or disturbing the drag in progress.

    A port whose platform commits to an action before it can read the transferred data -- AWT does, because a drop has to be accepted before it becomes readable -- asks here first, so that what it commits to is what `#drop(int, int, int, com.codename1.ui.ClipboardContent, int)` will go on to report. Committing the platform's own stale action instead told the source a copy had happened while the target was handed a move.

    ###### Parameters

    - `windowId`: the id of the window the drag is over, or zero for the main surface

    - `x`: the pointer position within that surface

    - `y`: the pointer position within that surface

    - `content`: the representations the drag is offering, which may still be a description rather than the materialized payload

    - `action`: the action the platform is proposing

    ###### Returns

    the action the drop would perform, or `NativeDragOperation#ACTION_NONE`

  - ### dragCompleted

    public static void dragCompleted(int performedAction)

    Reports that the session started by `#startDrag(com.codename1.ui.Component, com.codename1.ui.NativeDragOperation)` has finished, whatever the outcome, so that a source offering `NativeDragOperation#ACTION_MOVE` learns whether to delete its copy.

    ###### Parameters

    - `performedAction`: the action the receiver performed, or `NativeDragOperation#ACTION_NONE` when the drag was cancelled or refused