27
28 import com.sun.javafx.tk.Toolkit;
29 import java.awt.Component;
30 import java.awt.Cursor;
31 import java.awt.Point;
32 import java.awt.SecondaryLoop;
33 import java.awt.datatransfer.DataFlavor;
34 import java.awt.datatransfer.Transferable;
35 import java.awt.dnd.DnDConstants;
36 import java.awt.dnd.DragGestureEvent;
37 import java.awt.dnd.DragGestureListener;
38 import java.awt.dnd.DragGestureRecognizer;
39 import java.awt.dnd.DragSource;
40 import java.awt.dnd.DropTarget;
41 import java.awt.dnd.DropTargetContext;
42 import java.awt.dnd.DropTargetDragEvent;
43 import java.awt.dnd.DropTargetDropEvent;
44 import java.awt.dnd.DropTargetListener;
45 import java.awt.dnd.InvalidDnDOperationException;
46 import java.awt.dnd.MouseDragGestureRecognizer;
47 import java.awt.dnd.peer.DragSourceContextPeer;
48 import java.awt.dnd.peer.DropTargetContextPeer;
49 import java.security.AccessController;
50 import java.security.PrivilegedAction;
51 import java.util.HashMap;
52 import java.util.Map;
53 import javafx.application.Platform;
54 import javafx.event.EventHandler;
55 import javafx.event.EventType;
56 import javafx.scene.input.DataFormat;
57 import javafx.scene.input.DragEvent;
58 import javafx.scene.input.Dragboard;
59 import javafx.scene.input.MouseEvent;
60 import javafx.scene.input.TransferMode;
61 import sun.awt.AWTAccessor;
62 import sun.awt.dnd.SunDragSourceContextPeer;
63 import sun.swing.JLightweightFrame;
64
65
66 /**
67 * A utility class to connect DnD mechanism of Swing and FX.
68 * It allows Swing content to use the FX machinery for performing DnD.
69 */
70 final class FXDnD {
71 private final SwingNode node;
72 private static boolean fxAppThreadIsDispatchThread;
73 private SwingNode getNode() { return node; }
74
75 static {
76 AccessController.doPrivileged(new PrivilegedAction<Object>() {
77 public Object run() {
78 fxAppThreadIsDispatchThread =
79 "true".equals(System.getProperty("javafx.embed.singleThread"));
80 return null;
81 }
82 });
83 }
84
85 FXDnD(SwingNode node) {
86 this.node = node;
87 }
88
89 /**
90 * Utility class that operates on Maps with Components as keys.
91 * Useful when processing mouse events to choose an object from the map
92 * based on the component located at the given coordinates.
93 */
94 private class ComponentMapper<T> {
95 private int x, y;
96 private T object = null;
97
98 private ComponentMapper(Map<Component, T> map, int xArg, int yArg) {
99 this.x = xArg;
100 this.y = yArg;
101
102 final JLightweightFrame lwFrame = node.getLightweightFrame();
103 Component c = AWTAccessor.getContainerAccessor().findComponentAt(
104 lwFrame, x, y, false);
105 if (c == null) return;
106
107 synchronized (c.getTreeLock()) {
108 do {
109 object = map.get(c);
110 } while (object == null && (c = c.getParent()) != null);
111
112 if (object != null) {
113 // The object is either a DropTarget or a DragSource, so:
114 //assert c == object.getComponent();
115
116 // Translate x, y from lwFrame to component coordinates
117 while (c != lwFrame && c != null) {
118 x -= c.getX();
119 y -= c.getY();
120 c = c.getParent();
121 }
122 }
123 }
124 }
125 }
126 public <T> ComponentMapper<T> mapComponent(Map<Component, T> map, int x, int y) {
127 return new ComponentMapper<T>(map, x, y);
128 }
129
130
131
132
133
134 ///////////////////////////////////////////////////////////////////////////
135 // DRAG SOURCE IMPLEMENTATION
136 ///////////////////////////////////////////////////////////////////////////
137
180 protected void unregisterListeners() {
181 SwingFXUtils.runOnFxThread(() -> {
182 if (isDragSourceListenerInstalled) {
183 node.removeEventHandler(MouseEvent.MOUSE_PRESSED, onMousePressHandler);
184 node.removeEventHandler(MouseEvent.DRAG_DETECTED, onDragStartHandler);
185 node.removeEventHandler(DragEvent.DRAG_DONE, onDragDoneHandler);
186
187 isDragSourceListenerInstalled = false;
188 }
189 });
190 }
191
192 private void fireEvent(int x, int y, long evTime, int modifiers) {
193 // In theory we should register all the events that trigger the gesture (like PRESS, DRAG, DRAG, BINGO!)
194 // But we can live with this hack for now.
195 appendEvent(new java.awt.event.MouseEvent(getComponent(), java.awt.event.MouseEvent.MOUSE_PRESSED,
196 evTime, modifiers, x, y, 0, false));
197
198 // Also, the modifiers here should've actually come from the last known mouse event (last MOVE or DRAG).
199 // But we're OK with using the initial PRESS modifiers for now
200 int initialAction = SunDragSourceContextPeer.convertModifiersToDropAction(
201 modifiers, getSourceActions());
202
203 fireDragGestureRecognized(initialAction, new java.awt.Point(x, y));
204 }
205 }
206
207 // Invoked on EDT
208 private void fireEvent(int x, int y, long evTime, int modifiers) {
209 ComponentMapper<FXDragGestureRecognizer> mapper = mapComponent(recognizers, x, y);
210
211 final FXDragGestureRecognizer r = mapper.object;
212 if (r != null) {
213 r.fireEvent(mapper.x, mapper.y, evTime, modifiers);
214 } else {
215 // No recognizer, no DnD, no startDrag, so release the FX loop now
216 SwingFXUtils.leaveFXNestedLoop(FXDnD.this);
217 }
218 }
219
220 private MouseEvent getInitialGestureEvent() {
264 }
265 };
266
267 private final EventHandler<DragEvent> onDragDoneHandler = (event) -> {
268 event.consume();
269
270 // Release FXDragSourceContextPeer.startDrag()
271 if (!fxAppThreadIsDispatchThread) {
272 loop.exit();
273 }
274
275 if (activeDSContextPeer != null) {
276 final TransferMode mode = event.getTransferMode();
277 activeDSContextPeer.dragDone(
278 mode == null ? 0 : SwingDnD.transferModeToDropAction(mode),
279 (int)event.getX(), (int)event.getY());
280 }
281 };
282
283
284 private final class FXDragSourceContextPeer extends SunDragSourceContextPeer {
285 private volatile int sourceActions = 0;
286
287 private final CachingTransferable transferable = new CachingTransferable();
288
289 @Override public void startSecondaryEventLoop(){
290 Toolkit.getToolkit().enterNestedEventLoop(this);
291 }
292 @Override public void quitSecondaryEventLoop(){
293 assert !Platform.isFxApplicationThread();
294 Platform.runLater(() -> Toolkit.getToolkit().exitNestedEventLoop(FXDragSourceContextPeer.this, null));
295 }
296
297 @Override protected void setNativeCursor(long nativeCtxt, Cursor c, int cType) {
298 //TODO
299 }
300
301
302 private void dragDone(int operation, int x, int y) {
303 dragDropFinished(operation != 0, operation, x, y);
304 }
320 // StringReader as data, etc.) So instead we perform our internal
321 // translation.
322 // Note that fetchData == true. FX doesn't support delayed data
323 // callbacks yet anyway, so we have to fetch all the data from AWT upfront.
324 transferable.updateData(trans, true);
325
326 sourceActions = getDragSourceContext().getSourceActions();
327
328 // Release the FX nested loop to allow onDragDetected to start the actual DnD operation,
329 // and then start an AWT nested loop to wait until DnD finishes.
330 if (!fxAppThreadIsDispatchThread) {
331 loop = java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue().createSecondaryLoop();
332 SwingFXUtils.leaveFXNestedLoop(FXDnD.this);
333 if (!loop.enter()) {
334 // An error occured, but there's little we can do here...
335 }
336 }
337 }
338 };
339
340 public <T extends DragGestureRecognizer> T createDragGestureRecognizer(
341 Class<T> abstractRecognizerClass,
342 DragSource ds, Component c, int srcActions,
343 DragGestureListener dgl)
344 {
345 return (T) new FXDragGestureRecognizer(ds, c, srcActions, dgl);
346 }
347
348 public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException
349 {
350 return new FXDragSourceContextPeer(dge);
351 }
352
353
354
355
356
357 ///////////////////////////////////////////////////////////////////////////
358 // DROP TARGET IMPLEMENTATION
359 ///////////////////////////////////////////////////////////////////////////
360
361
362 private boolean isDropTargetListenerInstalled = false;
363 private volatile FXDropTargetContextPeer activeDTContextPeer = null;
364 private final Map<Component, DropTarget> dropTargets = new HashMap<>();
365
366 private final EventHandler<DragEvent> onDragEnteredHandler = (event) -> {
367 if (activeDTContextPeer == null) activeDTContextPeer = new FXDropTargetContextPeer();
368
401
402 int action = activeDTContextPeer.postDropTargetEvent(event);
403
404 if (action != 0) {
405 // NOTE: the dropAction is ignored since we use the action last
406 // reported from the DRAG_OVER handler.
407 //
408 // We might want to:
409 //
410 // assert activeDTContextPeer.dropAction == onDragDroppedHandler.currentAction;
411 //
412 // and maybe print a diagnostic message if they differ.
413 event.setDropCompleted(activeDTContextPeer.success);
414
415 event.consume();
416 }
417
418 activeDTContextPeer = null;
419 };
420
421 private final class FXDropTargetContextPeer implements DropTargetContextPeer {
422
423 private int targetActions = DnDConstants.ACTION_NONE;
424 private int currentAction = DnDConstants.ACTION_NONE;
425 private DropTarget dt = null;
426 private DropTargetContext ctx = null;
427
428 private final CachingTransferable transferable = new CachingTransferable();
429
430 // Drop result
431 private boolean success = false;
432 private int dropAction = 0;
433
434 @Override public synchronized void setTargetActions(int actions) { targetActions = actions; }
435 @Override public synchronized int getTargetActions() { return targetActions; }
436
437 @Override public synchronized DropTarget getDropTarget() { return dt; }
438
439 @Override public synchronized boolean isTransferableJVMLocal() { return false; }
440
441 @Override public synchronized DataFlavor[] getTransferDataFlavors() { return transferable.getTransferDataFlavors(); }
452
453 private int postDropTargetEvent(DragEvent event)
454 {
455 ComponentMapper<DropTarget> mapper = mapComponent(dropTargets, (int)event.getX(), (int)event.getY());
456
457 final EventType<?> fxEvType = event.getEventType();
458
459 Dragboard db = event.getDragboard();
460 transferable.updateData(db, DragEvent.DRAG_DROPPED.equals(fxEvType));
461
462 final int sourceActions = SwingDnD.transferModesToDropActions(db.getTransferModes());
463 final int userAction = event.getTransferMode() == null ? DnDConstants.ACTION_NONE
464 : SwingDnD.transferModeToDropAction(event.getTransferMode());
465
466 // A target for the AWT DnD event
467 DropTarget target = mapper.object != null ? mapper.object : dt;
468
469 SwingFXUtils.runOnEDTAndWait(FXDnD.this, () -> {
470 if (target != dt) {
471 if (ctx != null) {
472 AWTAccessor.getDropTargetContextAccessor().reset(ctx);
473 }
474 ctx = null;
475
476 currentAction = dropAction = DnDConstants.ACTION_NONE;
477 }
478
479 if (target != null) {
480 if (ctx == null) {
481 ctx = target.getDropTargetContext();
482 AWTAccessor.getDropTargetContextAccessor()
483 .setDropTargetContextPeer(ctx, FXDropTargetContextPeer.this);
484 }
485
486 DropTargetListener dtl = (DropTargetListener)target;
487
488 if (DragEvent.DRAG_DROPPED.equals(fxEvType)) {
489 DropTargetDropEvent awtEvent = new DropTargetDropEvent(
490 ctx, new Point(mapper.x, mapper.y), userAction, sourceActions);
491
492 dtl.drop(awtEvent);
493 } else {
494 DropTargetDragEvent awtEvent = new DropTargetDragEvent(
495 ctx, new Point(mapper.x, mapper.y), userAction, sourceActions);
496
497 if (DragEvent.DRAG_OVER.equals(fxEvType)) dtl.dragOver(awtEvent);
498 else if (DragEvent.DRAG_ENTERED.equals(fxEvType)) dtl.dragEnter(awtEvent);
499 else if (DragEvent.DRAG_EXITED.equals(fxEvType)) dtl.dragExit(awtEvent);
500 }
501 }
502
503 dt = mapper.object;
|
27
28 import com.sun.javafx.tk.Toolkit;
29 import java.awt.Component;
30 import java.awt.Cursor;
31 import java.awt.Point;
32 import java.awt.SecondaryLoop;
33 import java.awt.datatransfer.DataFlavor;
34 import java.awt.datatransfer.Transferable;
35 import java.awt.dnd.DnDConstants;
36 import java.awt.dnd.DragGestureEvent;
37 import java.awt.dnd.DragGestureListener;
38 import java.awt.dnd.DragGestureRecognizer;
39 import java.awt.dnd.DragSource;
40 import java.awt.dnd.DropTarget;
41 import java.awt.dnd.DropTargetContext;
42 import java.awt.dnd.DropTargetDragEvent;
43 import java.awt.dnd.DropTargetDropEvent;
44 import java.awt.dnd.DropTargetListener;
45 import java.awt.dnd.InvalidDnDOperationException;
46 import java.awt.dnd.MouseDragGestureRecognizer;
47 import java.security.AccessController;
48 import java.security.PrivilegedAction;
49 import java.util.HashMap;
50 import java.util.Map;
51 import javafx.application.Platform;
52 import javafx.event.EventHandler;
53 import javafx.event.EventType;
54 import javafx.scene.input.DataFormat;
55 import javafx.scene.input.DragEvent;
56 import javafx.scene.input.Dragboard;
57 import javafx.scene.input.MouseEvent;
58 import javafx.scene.input.TransferMode;
59
60 import jdk.swing.interop.LightweightFrameWrapper;
61 import jdk.swing.interop.SwingInterOpUtils;
62 import jdk.swing.interop.DragSourceContextWrapper;
63 import jdk.swing.interop.DropTargetContextWrapper;
64
65 /**
66 * A utility class to connect DnD mechanism of Swing and FX.
67 * It allows Swing content to use the FX machinery for performing DnD.
68 */
69 final class FXDnD {
70 private final SwingNode node;
71 private static boolean fxAppThreadIsDispatchThread;
72 private SwingNode getNode() { return node; }
73
74 static {
75 AccessController.doPrivileged(new PrivilegedAction<Object>() {
76 public Object run() {
77 fxAppThreadIsDispatchThread =
78 "true".equals(System.getProperty("javafx.embed.singleThread"));
79 return null;
80 }
81 });
82 }
83
84 FXDnD(SwingNode node) {
85 this.node = node;
86 }
87
88 /**
89 * Utility class that operates on Maps with Components as keys.
90 * Useful when processing mouse events to choose an object from the map
91 * based on the component located at the given coordinates.
92 */
93 private class ComponentMapper<T> {
94 private int x, y;
95 private T object = null;
96
97 private ComponentMapper(Map<Component, T> map, int xArg, int yArg) {
98 this.x = xArg;
99 this.y = yArg;
100
101 final LightweightFrameWrapper lwFrame = node.getLightweightFrame();
102 Component c = lwFrame.findComponentAt(lwFrame, x, y, false);
103 if (c == null) return;
104
105 synchronized (c.getTreeLock()) {
106 do {
107 object = map.get(c);
108 } while (object == null && (c = c.getParent()) != null);
109
110 if (object != null) {
111 // The object is either a DropTarget or a DragSource, so:
112 //assert c == object.getComponent();
113
114 // Translate x, y from lwFrame to component coordinates
115 while ((lwFrame.isCompEqual(c,lwFrame)) && c != null) {
116 x -= c.getX();
117 y -= c.getY();
118 c = c.getParent();
119 }
120 }
121 }
122 }
123 }
124 public <T> ComponentMapper<T> mapComponent(Map<Component, T> map, int x, int y) {
125 return new ComponentMapper<T>(map, x, y);
126 }
127
128
129
130
131
132 ///////////////////////////////////////////////////////////////////////////
133 // DRAG SOURCE IMPLEMENTATION
134 ///////////////////////////////////////////////////////////////////////////
135
178 protected void unregisterListeners() {
179 SwingFXUtils.runOnFxThread(() -> {
180 if (isDragSourceListenerInstalled) {
181 node.removeEventHandler(MouseEvent.MOUSE_PRESSED, onMousePressHandler);
182 node.removeEventHandler(MouseEvent.DRAG_DETECTED, onDragStartHandler);
183 node.removeEventHandler(DragEvent.DRAG_DONE, onDragDoneHandler);
184
185 isDragSourceListenerInstalled = false;
186 }
187 });
188 }
189
190 private void fireEvent(int x, int y, long evTime, int modifiers) {
191 // In theory we should register all the events that trigger the gesture (like PRESS, DRAG, DRAG, BINGO!)
192 // But we can live with this hack for now.
193 appendEvent(new java.awt.event.MouseEvent(getComponent(), java.awt.event.MouseEvent.MOUSE_PRESSED,
194 evTime, modifiers, x, y, 0, false));
195
196 // Also, the modifiers here should've actually come from the last known mouse event (last MOVE or DRAG).
197 // But we're OK with using the initial PRESS modifiers for now
198 int initialAction = DragSourceContextWrapper.convertModifiersToDropAction(
199 modifiers, getSourceActions());
200
201 fireDragGestureRecognized(initialAction, new java.awt.Point(x, y));
202 }
203 }
204
205 // Invoked on EDT
206 private void fireEvent(int x, int y, long evTime, int modifiers) {
207 ComponentMapper<FXDragGestureRecognizer> mapper = mapComponent(recognizers, x, y);
208
209 final FXDragGestureRecognizer r = mapper.object;
210 if (r != null) {
211 r.fireEvent(mapper.x, mapper.y, evTime, modifiers);
212 } else {
213 // No recognizer, no DnD, no startDrag, so release the FX loop now
214 SwingFXUtils.leaveFXNestedLoop(FXDnD.this);
215 }
216 }
217
218 private MouseEvent getInitialGestureEvent() {
262 }
263 };
264
265 private final EventHandler<DragEvent> onDragDoneHandler = (event) -> {
266 event.consume();
267
268 // Release FXDragSourceContextPeer.startDrag()
269 if (!fxAppThreadIsDispatchThread) {
270 loop.exit();
271 }
272
273 if (activeDSContextPeer != null) {
274 final TransferMode mode = event.getTransferMode();
275 activeDSContextPeer.dragDone(
276 mode == null ? 0 : SwingDnD.transferModeToDropAction(mode),
277 (int)event.getX(), (int)event.getY());
278 }
279 };
280
281
282 private final class FXDragSourceContextPeer extends DragSourceContextWrapper {
283 private volatile int sourceActions = 0;
284
285 private final CachingTransferable transferable = new CachingTransferable();
286
287 @Override public void startSecondaryEventLoop(){
288 Toolkit.getToolkit().enterNestedEventLoop(this);
289 }
290 @Override public void quitSecondaryEventLoop(){
291 assert !Platform.isFxApplicationThread();
292 Platform.runLater(() -> Toolkit.getToolkit().exitNestedEventLoop(FXDragSourceContextPeer.this, null));
293 }
294
295 @Override protected void setNativeCursor(long nativeCtxt, Cursor c, int cType) {
296 //TODO
297 }
298
299
300 private void dragDone(int operation, int x, int y) {
301 dragDropFinished(operation != 0, operation, x, y);
302 }
318 // StringReader as data, etc.) So instead we perform our internal
319 // translation.
320 // Note that fetchData == true. FX doesn't support delayed data
321 // callbacks yet anyway, so we have to fetch all the data from AWT upfront.
322 transferable.updateData(trans, true);
323
324 sourceActions = getDragSourceContext().getSourceActions();
325
326 // Release the FX nested loop to allow onDragDetected to start the actual DnD operation,
327 // and then start an AWT nested loop to wait until DnD finishes.
328 if (!fxAppThreadIsDispatchThread) {
329 loop = java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue().createSecondaryLoop();
330 SwingFXUtils.leaveFXNestedLoop(FXDnD.this);
331 if (!loop.enter()) {
332 // An error occured, but there's little we can do here...
333 }
334 }
335 }
336 };
337
338 //@Override
339 public <T extends DragGestureRecognizer> T createDragGestureRecognizer(
340 Class<T> abstractRecognizerClass,
341 DragSource ds, Component c, int srcActions,
342 DragGestureListener dgl)
343 {
344 return (T) new FXDragGestureRecognizer(ds, c, srcActions, dgl);
345 }
346
347 //@Override
348 public DragSourceContextWrapper createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException
349 {
350 return new FXDragSourceContextPeer(dge);
351 }
352
353
354
355
356
357 ///////////////////////////////////////////////////////////////////////////
358 // DROP TARGET IMPLEMENTATION
359 ///////////////////////////////////////////////////////////////////////////
360
361
362 private boolean isDropTargetListenerInstalled = false;
363 private volatile FXDropTargetContextPeer activeDTContextPeer = null;
364 private final Map<Component, DropTarget> dropTargets = new HashMap<>();
365
366 private final EventHandler<DragEvent> onDragEnteredHandler = (event) -> {
367 if (activeDTContextPeer == null) activeDTContextPeer = new FXDropTargetContextPeer();
368
401
402 int action = activeDTContextPeer.postDropTargetEvent(event);
403
404 if (action != 0) {
405 // NOTE: the dropAction is ignored since we use the action last
406 // reported from the DRAG_OVER handler.
407 //
408 // We might want to:
409 //
410 // assert activeDTContextPeer.dropAction == onDragDroppedHandler.currentAction;
411 //
412 // and maybe print a diagnostic message if they differ.
413 event.setDropCompleted(activeDTContextPeer.success);
414
415 event.consume();
416 }
417
418 activeDTContextPeer = null;
419 };
420
421 private final class FXDropTargetContextPeer extends DropTargetContextWrapper {
422
423 private int targetActions = DnDConstants.ACTION_NONE;
424 private int currentAction = DnDConstants.ACTION_NONE;
425 private DropTarget dt = null;
426 private DropTargetContext ctx = null;
427
428 private final CachingTransferable transferable = new CachingTransferable();
429
430 // Drop result
431 private boolean success = false;
432 private int dropAction = 0;
433
434 @Override public synchronized void setTargetActions(int actions) { targetActions = actions; }
435 @Override public synchronized int getTargetActions() { return targetActions; }
436
437 @Override public synchronized DropTarget getDropTarget() { return dt; }
438
439 @Override public synchronized boolean isTransferableJVMLocal() { return false; }
440
441 @Override public synchronized DataFlavor[] getTransferDataFlavors() { return transferable.getTransferDataFlavors(); }
452
453 private int postDropTargetEvent(DragEvent event)
454 {
455 ComponentMapper<DropTarget> mapper = mapComponent(dropTargets, (int)event.getX(), (int)event.getY());
456
457 final EventType<?> fxEvType = event.getEventType();
458
459 Dragboard db = event.getDragboard();
460 transferable.updateData(db, DragEvent.DRAG_DROPPED.equals(fxEvType));
461
462 final int sourceActions = SwingDnD.transferModesToDropActions(db.getTransferModes());
463 final int userAction = event.getTransferMode() == null ? DnDConstants.ACTION_NONE
464 : SwingDnD.transferModeToDropAction(event.getTransferMode());
465
466 // A target for the AWT DnD event
467 DropTarget target = mapper.object != null ? mapper.object : dt;
468
469 SwingFXUtils.runOnEDTAndWait(FXDnD.this, () -> {
470 if (target != dt) {
471 if (ctx != null) {
472 DropTargetContextWrapper.reset(ctx);
473 }
474 ctx = null;
475
476 currentAction = dropAction = DnDConstants.ACTION_NONE;
477 }
478
479 if (target != null) {
480 if (ctx == null) {
481 ctx = target.getDropTargetContext();
482 DropTargetContextWrapper.setDropTargetContextPeer(ctx,
483 new FXDropTargetContextPeer());
484 }
485
486 DropTargetListener dtl = (DropTargetListener)target;
487
488 if (DragEvent.DRAG_DROPPED.equals(fxEvType)) {
489 DropTargetDropEvent awtEvent = new DropTargetDropEvent(
490 ctx, new Point(mapper.x, mapper.y), userAction, sourceActions);
491
492 dtl.drop(awtEvent);
493 } else {
494 DropTargetDragEvent awtEvent = new DropTargetDragEvent(
495 ctx, new Point(mapper.x, mapper.y), userAction, sourceActions);
496
497 if (DragEvent.DRAG_OVER.equals(fxEvType)) dtl.dragOver(awtEvent);
498 else if (DragEvent.DRAG_ENTERED.equals(fxEvType)) dtl.dragEnter(awtEvent);
499 else if (DragEvent.DRAG_EXITED.equals(fxEvType)) dtl.dragExit(awtEvent);
500 }
501 }
502
503 dt = mapper.object;
|