1 /*
2 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.awt.dnd;
27
28 import java.awt.Component;
29 import java.awt.Point;
30
31 import java.awt.datatransfer.DataFlavor;
32 import java.awt.datatransfer.Transferable;
33 import java.awt.datatransfer.UnsupportedFlavorException;
34
35 import java.awt.dnd.DnDConstants;
36
37 import java.awt.dnd.DropTarget;
38 import java.awt.dnd.DropTargetContext;
39 import java.awt.dnd.DropTargetListener;
40 import java.awt.dnd.DropTargetEvent;
41 import java.awt.dnd.DropTargetDragEvent;
42 import java.awt.dnd.DropTargetDropEvent;
43 import java.awt.dnd.InvalidDnDOperationException;
44
45 import java.awt.dnd.peer.DropTargetContextPeer;
46
47 import java.util.HashSet;
48 import java.util.Map;
49 import java.util.Arrays;
50
51 import sun.util.logging.PlatformLogger;
52
53 import java.io.IOException;
54 import java.io.InputStream;
55
56 import sun.awt.AppContext;
57 import sun.awt.SunToolkit;
58 import sun.awt.datatransfer.DataTransferer;
59 import sun.awt.datatransfer.ToolkitThreadBlockedHandler;
60
61 /**
62 * <p>
63 * The SunDropTargetContextPeer class is the generic class responsible for handling
64 * the interaction between a windowing systems DnD system and Java.
65 * </p>
66 *
67 * @since JDK1.3.1
68 *
69 */
70
71 public abstract class SunDropTargetContextPeer implements DropTargetContextPeer, Transferable {
72
73 /*
74 * A boolean constant that requires the peer to wait until the
75 * SunDropTargetEvent is processed and return the status back
76 * to the native code.
77 */
78 public static final boolean DISPATCH_SYNC = true;
79 private DropTarget currentDT;
80 private DropTargetContext currentDTC;
81 private long[] currentT;
82 private int currentA; // target actions
83 private int currentSA; // source actions
84 private int currentDA; // current drop action
85 private int previousDA;
86
87 private long nativeDragContext;
88
89 private Transferable local;
90
91 private boolean dragRejected = false;
92
93 protected int dropStatus = STATUS_NONE;
94 protected boolean dropComplete = false;
95
96 // The flag is used to monitor whether the drop action is
97 // handled by a user. That allows to distinct during
98 // which operation getTransferData() method is invoked.
99 boolean dropInProcess = false;
100
101 /*
102 * global lock
103 */
104
105 protected static final Object _globalLock = new Object();
106
107 private static final PlatformLogger dndLog = PlatformLogger.getLogger("sun.awt.dnd.SunDropTargetContextPeer");
108
109 /*
110 * a primitive mechanism for advertising intra-JVM Transferables
111 */
112
113 protected static Transferable currentJVMLocalSourceTransferable = null;
114
115 public static void setCurrentJVMLocalSourceTransferable(Transferable t) throws InvalidDnDOperationException {
116 synchronized(_globalLock) {
117 if (t != null && currentJVMLocalSourceTransferable != null) {
118 throw new InvalidDnDOperationException();
119 } else {
120 currentJVMLocalSourceTransferable = t;
121 }
122 }
123 }
124
125 /**
126 * obtain the transferable iff the operation is in the same VM
127 */
128
129 private static Transferable getJVMLocalSourceTransferable() {
130 return currentJVMLocalSourceTransferable;
131 }
132
133 /*
134 * constants used by dropAccept() or dropReject()
135 */
136
137 protected final static int STATUS_NONE = 0; // none pending
138 protected final static int STATUS_WAIT = 1; // drop pending
139 protected final static int STATUS_ACCEPT = 2;
140 protected final static int STATUS_REJECT = -1;
141
142 /**
143 * create the peer
144 */
145
146 public SunDropTargetContextPeer() {
147 super();
148 }
149
150 /**
151 * @return the DropTarget associated with this peer
152 */
153
154 public DropTarget getDropTarget() { return currentDT; }
155
156 /**
157 * @param actions set the current actions
158 */
159
160 public synchronized void setTargetActions(int actions) {
161 currentA = actions &
162 (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK);
163 }
164
165 /**
166 * @return the current target actions
167 */
168
169 public int getTargetActions() {
170 return currentA;
171 }
172
173 /**
174 * get the Transferable associated with the drop
175 */
176
177 public Transferable getTransferable() {
178 return this;
179 }
180
181 /**
182 * @return current DataFlavors available
183 */
184 // NOTE: This method may be called by privileged threads.
185 // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
186
187 public DataFlavor[] getTransferDataFlavors() {
188 final Transferable localTransferable = local;
189
190 if (localTransferable != null) {
191 return localTransferable.getTransferDataFlavors();
192 } else {
193 return DataTransferer.getInstance().getFlavorsForFormatsAsArray
194 (currentT, DataTransferer.adaptFlavorMap
195 (currentDT.getFlavorMap()));
196 }
197 }
198
199 /**
200 * @return if the flavor is supported
201 */
202
203 public boolean isDataFlavorSupported(DataFlavor df) {
204 Transferable localTransferable = local;
205
206 if (localTransferable != null) {
207 return localTransferable.isDataFlavorSupported(df);
208 } else {
209 return DataTransferer.getInstance().getFlavorsForFormats
210 (currentT, DataTransferer.adaptFlavorMap
211 (currentDT.getFlavorMap())).
212 containsKey(df);
213 }
214 }
215
216 /**
217 * @return the data
218 */
219
220 public Object getTransferData(DataFlavor df)
221 throws UnsupportedFlavorException, IOException,
222 InvalidDnDOperationException
223 {
224
225 SecurityManager sm = System.getSecurityManager();
226 try {
227 if (!dropInProcess && sm != null) {
228 sm.checkSystemClipboardAccess();
229 }
230 } catch (Exception e) {
231 Thread currentThread = Thread.currentThread();
232 currentThread.getUncaughtExceptionHandler().uncaughtException(currentThread, e);
233 return null;
234 }
235
236 Long lFormat = null;
237 Transferable localTransferable = local;
238
239 if (localTransferable != null) {
240 return localTransferable.getTransferData(df);
241 }
242
243 if (dropStatus != STATUS_ACCEPT || dropComplete) {
244 throw new InvalidDnDOperationException("No drop current");
245 }
246
247 Map flavorMap = DataTransferer.getInstance().getFlavorsForFormats
248 (currentT, DataTransferer.adaptFlavorMap
249 (currentDT.getFlavorMap()));
250
251 lFormat = (Long)flavorMap.get(df);
252 if (lFormat == null) {
253 throw new UnsupportedFlavorException(df);
254 }
255
256 if (df.isRepresentationClassRemote() &&
257 currentDA != DnDConstants.ACTION_LINK) {
258 throw new InvalidDnDOperationException("only ACTION_LINK is permissable for transfer of java.rmi.Remote objects");
259 }
260
261 final long format = lFormat.longValue();
262
263 Object ret = getNativeData(format);
264
265 if (ret instanceof byte[]) {
266 try {
267 return DataTransferer.getInstance().
268 translateBytes((byte[])ret, df, format, this);
269 } catch (IOException e) {
270 throw new InvalidDnDOperationException(e.getMessage());
271 }
272 } else if (ret instanceof InputStream) {
273 InputStream inputStream = (InputStream)ret;
274 try {
275 return DataTransferer.getInstance().
276 translateStream(inputStream, df, format, this);
277 } catch (IOException e) {
278 throw new InvalidDnDOperationException(e.getMessage());
279 } finally {
280 inputStream.close();
281 }
282 } else {
283 throw new IOException("no native data was transfered");
284 }
285 }
286
287 protected abstract Object getNativeData(long format)
288 throws IOException;
289
290 /**
291 * @return if the transfer is a local one
292 */
293 public boolean isTransferableJVMLocal() {
294 return local != null || getJVMLocalSourceTransferable() != null;
295 }
296
297 private int handleEnterMessage(final Component component,
298 final int x, final int y,
299 final int dropAction,
300 final int actions, final long[] formats,
301 final long nativeCtxt) {
302 return postDropTargetEvent(component, x, y, dropAction, actions,
303 formats, nativeCtxt,
304 SunDropTargetEvent.MOUSE_ENTERED,
305 SunDropTargetContextPeer.DISPATCH_SYNC);
306 }
307
308 /**
309 * actual processing on EventQueue Thread
310 */
311
312 protected void processEnterMessage(SunDropTargetEvent event) {
313 Component c = (Component)event.getSource();
314 DropTarget dt = c.getDropTarget();
315 Point hots = event.getPoint();
316
317 local = getJVMLocalSourceTransferable();
318
319 if (currentDTC != null) { // some wreckage from last time
320 currentDTC.removeNotify();
321 currentDTC = null;
322 }
323
324 if (c.isShowing() && dt != null && dt.isActive()) {
325 currentDT = dt;
326 currentDTC = currentDT.getDropTargetContext();
327
328 currentDTC.addNotify(this);
329
330 currentA = dt.getDefaultActions();
331
332 try {
333 ((DropTargetListener)dt).dragEnter(new DropTargetDragEvent(currentDTC,
334 hots,
335 currentDA,
336 currentSA));
337 } catch (Exception e) {
338 e.printStackTrace();
339 currentDA = DnDConstants.ACTION_NONE;
340 }
341 } else {
342 currentDT = null;
343 currentDTC = null;
344 currentDA = DnDConstants.ACTION_NONE;
345 currentSA = DnDConstants.ACTION_NONE;
346 currentA = DnDConstants.ACTION_NONE;
347 }
348
349 }
350
351 /**
352 * upcall to handle exit messages
353 */
354
355 private void handleExitMessage(final Component component,
356 final long nativeCtxt) {
357 /*
358 * Even though the return value is irrelevant for this event, it is
359 * dispatched synchronously to fix 4393148 properly.
360 */
361 postDropTargetEvent(component, 0, 0, DnDConstants.ACTION_NONE,
362 DnDConstants.ACTION_NONE, null, nativeCtxt,
363 SunDropTargetEvent.MOUSE_EXITED,
364 SunDropTargetContextPeer.DISPATCH_SYNC);
365 }
366
367 /**
368 *
369 */
370
371 protected void processExitMessage(SunDropTargetEvent event) {
372 Component c = (Component)event.getSource();
373 DropTarget dt = c.getDropTarget();
374 DropTargetContext dtc = null;
375
376 if (dt == null) {
377 currentDT = null;
378 currentT = null;
379
380 if (currentDTC != null) {
381 currentDTC.removeNotify();
382 }
383
384 currentDTC = null;
385
386 return;
387 }
388
389 if (dt != currentDT) {
390
391 if (currentDTC != null) {
392 currentDTC.removeNotify();
393 }
394
395 currentDT = dt;
396 currentDTC = dt.getDropTargetContext();
397
398 currentDTC.addNotify(this);
399 }
400
401 dtc = currentDTC;
402
403 if (dt.isActive()) try {
404 ((DropTargetListener)dt).dragExit(new DropTargetEvent(dtc));
405 } catch (Exception e) {
406 e.printStackTrace();
407 } finally {
408 currentA = DnDConstants.ACTION_NONE;
409 currentSA = DnDConstants.ACTION_NONE;
410 currentDA = DnDConstants.ACTION_NONE;
411 currentDT = null;
412 currentT = null;
413
414 currentDTC.removeNotify();
415 currentDTC = null;
416
417 local = null;
418
419 dragRejected = false;
420 }
421 }
422
423 private int handleMotionMessage(final Component component,
424 final int x, final int y,
425 final int dropAction,
426 final int actions, final long[] formats,
427 final long nativeCtxt) {
428 return postDropTargetEvent(component, x, y, dropAction, actions,
429 formats, nativeCtxt,
430 SunDropTargetEvent.MOUSE_DRAGGED,
431 SunDropTargetContextPeer.DISPATCH_SYNC);
432 }
433
434 /**
435 *
436 */
437
438 protected void processMotionMessage(SunDropTargetEvent event,
439 boolean operationChanged) {
440 Component c = (Component)event.getSource();
441 Point hots = event.getPoint();
442 int id = event.getID();
443 DropTarget dt = c.getDropTarget();
444 DropTargetContext dtc = null;
445
446 if (c.isShowing() && (dt != null) && dt.isActive()) {
447 if (currentDT != dt) {
448 if (currentDTC != null) {
449 currentDTC.removeNotify();
450 }
451
452 currentDT = dt;
453 currentDTC = null;
454 }
455
456 dtc = currentDT.getDropTargetContext();
457 if (dtc != currentDTC) {
458 if (currentDTC != null) {
459 currentDTC.removeNotify();
460 }
461
462 currentDTC = dtc;
463 currentDTC.addNotify(this);
464 }
465
466 currentA = currentDT.getDefaultActions();
467
468 try {
469 DropTargetDragEvent dtde = new DropTargetDragEvent(dtc,
470 hots,
471 currentDA,
472 currentSA);
473 DropTargetListener dtl = (DropTargetListener)dt;
474 if (operationChanged) {
475 dtl.dropActionChanged(dtde);
476 } else {
477 dtl.dragOver(dtde);
478 }
479
480 if (dragRejected) {
481 currentDA = DnDConstants.ACTION_NONE;
482 }
483 } catch (Exception e) {
484 e.printStackTrace();
485 currentDA = DnDConstants.ACTION_NONE;
486 }
487 } else {
488 currentDA = DnDConstants.ACTION_NONE;
489 }
490 }
491
492 /**
493 * upcall to handle the Drop message
494 */
495
496 private void handleDropMessage(final Component component,
497 final int x, final int y,
498 final int dropAction, final int actions,
499 final long[] formats,
500 final long nativeCtxt) {
501 postDropTargetEvent(component, x, y, dropAction, actions,
502 formats, nativeCtxt,
503 SunDropTargetEvent.MOUSE_DROPPED,
504 !SunDropTargetContextPeer.DISPATCH_SYNC);
505 }
506
507 /**
508 *
509 */
510
511 protected void processDropMessage(SunDropTargetEvent event) {
512 Component c = (Component)event.getSource();
513 Point hots = event.getPoint();
514 DropTarget dt = c.getDropTarget();
515
516 dropStatus = STATUS_WAIT; // drop pending ACK
517 dropComplete = false;
518
519 if (c.isShowing() && dt != null && dt.isActive()) {
520 DropTargetContext dtc = dt.getDropTargetContext();
521
522 currentDT = dt;
523
524 if (currentDTC != null) {
525 currentDTC.removeNotify();
526 }
527
528 currentDTC = dtc;
529 currentDTC.addNotify(this);
530 currentA = dt.getDefaultActions();
531
532 synchronized(_globalLock) {
533 if ((local = getJVMLocalSourceTransferable()) != null)
534 setCurrentJVMLocalSourceTransferable(null);
535 }
536
537 dropInProcess = true;
538
539 try {
540 ((DropTargetListener)dt).drop(new DropTargetDropEvent(dtc,
541 hots,
542 currentDA,
543 currentSA,
544 local != null));
545 } finally {
546 if (dropStatus == STATUS_WAIT) {
547 rejectDrop();
548 } else if (dropComplete == false) {
549 dropComplete(false);
550 }
551 dropInProcess = false;
552 }
553 } else {
554 rejectDrop();
555 }
556 }
557
558 protected int postDropTargetEvent(final Component component,
559 final int x, final int y,
560 final int dropAction,
561 final int actions,
562 final long[] formats,
563 final long nativeCtxt,
564 final int eventID,
565 final boolean dispatchType) {
566 AppContext appContext = SunToolkit.targetToAppContext(component);
567
568 EventDispatcher dispatcher =
569 new EventDispatcher(this, dropAction, actions, formats, nativeCtxt,
570 dispatchType);
571
572 SunDropTargetEvent event =
573 new SunDropTargetEvent(component, eventID, x, y, dispatcher);
574
575 if (dispatchType == SunDropTargetContextPeer.DISPATCH_SYNC) {
576 DataTransferer.getInstance().getToolkitThreadBlockedHandler().lock();
577 }
578
579 // schedule callback
580 SunToolkit.postEvent(appContext, event);
581
582 eventPosted(event);
583
584 if (dispatchType == SunDropTargetContextPeer.DISPATCH_SYNC) {
585 while (!dispatcher.isDone()) {
586 DataTransferer.getInstance().getToolkitThreadBlockedHandler().enter();
587 }
588
589 DataTransferer.getInstance().getToolkitThreadBlockedHandler().unlock();
590
591 // return target's response
592 return dispatcher.getReturnValue();
593 } else {
594 return 0;
595 }
596 }
597
598 /**
599 * acceptDrag
600 */
601
602 public synchronized void acceptDrag(int dragOperation) {
603 if (currentDT == null) {
604 throw new InvalidDnDOperationException("No Drag pending");
605 }
606 currentDA = mapOperation(dragOperation);
607 if (currentDA != DnDConstants.ACTION_NONE) {
608 dragRejected = false;
609 }
610 }
611
612 /**
613 * rejectDrag
614 */
615
616 public synchronized void rejectDrag() {
617 if (currentDT == null) {
618 throw new InvalidDnDOperationException("No Drag pending");
619 }
620 currentDA = DnDConstants.ACTION_NONE;
621 dragRejected = true;
622 }
623
624 /**
625 * acceptDrop
626 */
627
628 public synchronized void acceptDrop(int dropOperation) {
629 if (dropOperation == DnDConstants.ACTION_NONE)
630 throw new IllegalArgumentException("invalid acceptDrop() action");
631
632 if (dropStatus != STATUS_WAIT) {
633 throw new InvalidDnDOperationException("invalid acceptDrop()");
634 }
635
636 currentDA = currentA = mapOperation(dropOperation & currentSA);
637
638 dropStatus = STATUS_ACCEPT;
639 dropComplete = false;
640 }
641
642 /**
643 * reject Drop
644 */
645
646 public synchronized void rejectDrop() {
647 if (dropStatus != STATUS_WAIT) {
648 throw new InvalidDnDOperationException("invalid rejectDrop()");
649 }
650 dropStatus = STATUS_REJECT;
651 /*
652 * Fix for 4285634.
653 * The target rejected the drop means that it doesn't perform any
654 * drop action. This change is to make Solaris behavior consistent
655 * with Win32.
656 */
657 currentDA = DnDConstants.ACTION_NONE;
658 dropComplete(false);
659 }
660
661 /**
662 * mapOperation
663 */
664
665 private int mapOperation(int operation) {
666 int[] operations = {
667 DnDConstants.ACTION_MOVE,
668 DnDConstants.ACTION_COPY,
669 DnDConstants.ACTION_LINK,
670 };
671 int ret = DnDConstants.ACTION_NONE;
672
673 for (int i = 0; i < operations.length; i++) {
674 if ((operation & operations[i]) == operations[i]) {
675 ret = operations[i];
676 break;
677 }
678 }
679
680 return ret;
681 }
682
683 /**
684 * signal drop complete
685 */
686
687 public synchronized void dropComplete(boolean success) {
688 if (dropStatus == STATUS_NONE) {
689 throw new InvalidDnDOperationException("No Drop pending");
690 }
691
692 if (currentDTC != null) currentDTC.removeNotify();
693
694 currentDT = null;
695 currentDTC = null;
696 currentT = null;
697 currentA = DnDConstants.ACTION_NONE;
698
699 synchronized(_globalLock) {
700 currentJVMLocalSourceTransferable = null;
701 }
702
703 dropStatus = STATUS_NONE;
704 dropComplete = true;
705
706 try {
707 doDropDone(success, currentDA, local != null);
708 } finally {
709 currentDA = DnDConstants.ACTION_NONE;
710 // The native context is invalid after the drop is done.
711 // Clear the reference to prohibit access.
712 nativeDragContext = 0;
713 }
714 }
715
716 protected abstract void doDropDone(boolean success,
717 int dropAction, boolean isLocal);
718
719 protected synchronized long getNativeDragContext() {
720 return nativeDragContext;
721 }
722
723 protected void eventPosted(SunDropTargetEvent e) {}
724
725 protected void eventProcessed(SunDropTargetEvent e, int returnValue,
726 boolean dispatcherDone) {}
727
728 protected static class EventDispatcher {
729
730 private final SunDropTargetContextPeer peer;
731
732 // context fields
733 private final int dropAction;
734 private final int actions;
735 private final long[] formats;
736 private long nativeCtxt;
737 private final boolean dispatchType;
738 private boolean dispatcherDone = false;
739
740 // dispatcher state fields
741 private int returnValue = 0;
742 // set of events to be dispatched by this dispatcher
743 private final HashSet eventSet = new HashSet(3);
744
745 static final ToolkitThreadBlockedHandler handler =
746 DataTransferer.getInstance().getToolkitThreadBlockedHandler();
747
748 EventDispatcher(SunDropTargetContextPeer peer,
749 int dropAction,
750 int actions,
751 long[] formats,
752 long nativeCtxt,
753 boolean dispatchType) {
754
755 this.peer = peer;
756 this.nativeCtxt = nativeCtxt;
757 this.dropAction = dropAction;
758 this.actions = actions;
759 this.formats =
760 (null == formats) ? null : Arrays.copyOf(formats, formats.length);
761 this.dispatchType = dispatchType;
762 }
763
764 void dispatchEvent(SunDropTargetEvent e) {
765 int id = e.getID();
766
767 switch (id) {
768 case SunDropTargetEvent.MOUSE_ENTERED:
769 dispatchEnterEvent(e);
770 break;
771 case SunDropTargetEvent.MOUSE_DRAGGED:
772 dispatchMotionEvent(e);
773 break;
774 case SunDropTargetEvent.MOUSE_EXITED:
775 dispatchExitEvent(e);
776 break;
777 case SunDropTargetEvent.MOUSE_DROPPED:
778 dispatchDropEvent(e);
779 break;
780 default:
781 throw new InvalidDnDOperationException();
782 }
783 }
784
785 private void dispatchEnterEvent(SunDropTargetEvent e) {
786 synchronized (peer) {
787
788 // store the drop action here to track operation changes
789 peer.previousDA = dropAction;
790
791 // setup peer context
792 peer.nativeDragContext = nativeCtxt;
793 peer.currentT = formats;
794 peer.currentSA = actions;
795 peer.currentDA = dropAction;
796 // To allow data retrieval.
797 peer.dropStatus = STATUS_ACCEPT;
798 peer.dropComplete = false;
799
800 try {
801 peer.processEnterMessage(e);
802 } finally {
803 peer.dropStatus = STATUS_NONE;
804 }
805
806 setReturnValue(peer.currentDA);
807 }
808 }
809
810 private void dispatchMotionEvent(SunDropTargetEvent e) {
811 synchronized (peer) {
812
813 boolean operationChanged = peer.previousDA != dropAction;
814 peer.previousDA = dropAction;
815
816 // setup peer context
817 peer.nativeDragContext = nativeCtxt;
818 peer.currentT = formats;
819 peer.currentSA = actions;
820 peer.currentDA = dropAction;
821 // To allow data retrieval.
822 peer.dropStatus = STATUS_ACCEPT;
823 peer.dropComplete = false;
824
825 try {
826 peer.processMotionMessage(e, operationChanged);
827 } finally {
828 peer.dropStatus = STATUS_NONE;
829 }
830
831 setReturnValue(peer.currentDA);
832 }
833 }
834
835 private void dispatchExitEvent(SunDropTargetEvent e) {
836 synchronized (peer) {
837
838 // setup peer context
839 peer.nativeDragContext = nativeCtxt;
840
841 peer.processExitMessage(e);
842 }
843 }
844
845 private void dispatchDropEvent(SunDropTargetEvent e) {
846 synchronized (peer) {
847
848 // setup peer context
849 peer.nativeDragContext = nativeCtxt;
850 peer.currentT = formats;
851 peer.currentSA = actions;
852 peer.currentDA = dropAction;
853
854 peer.processDropMessage(e);
855 }
856 }
857
858 void setReturnValue(int ret) {
859 returnValue = ret;
860 }
861
862 int getReturnValue() {
863 return returnValue;
864 }
865
866 boolean isDone() {
867 return eventSet.isEmpty();
868 }
869
870 void registerEvent(SunDropTargetEvent e) {
871 handler.lock();
872 if (!eventSet.add(e) && dndLog.isLoggable(PlatformLogger.FINE)) {
873 dndLog.fine("Event is already registered: " + e);
874 }
875 handler.unlock();
876 }
877
878 void unregisterEvent(SunDropTargetEvent e) {
879 handler.lock();
880 try {
881 if (!eventSet.remove(e)) {
882 // This event has already been unregistered.
883 return;
884 }
885 if (eventSet.isEmpty()) {
886 if (!dispatcherDone && dispatchType == DISPATCH_SYNC) {
887 handler.exit();
888 }
889 dispatcherDone = true;
890 }
891 } finally {
892 handler.unlock();
893 }
894
895 try {
896 peer.eventProcessed(e, returnValue, dispatcherDone);
897 } finally {
898 /*
899 * Clear the reference to the native context if all copies of
900 * the original event are processed.
901 */
902 if (dispatcherDone) {
903 nativeCtxt = 0;
904 // Fix for 6342381
905 peer.nativeDragContext = 0;
906
907 }
908 }
909 }
910
911 public void unregisterAllEvents() {
912 Object[] events = null;
913 handler.lock();
914 try {
915 events = eventSet.toArray();
916 } finally {
917 handler.unlock();
918 }
919
920 if (events != null) {
921 for (int i = 0; i < events.length; i++) {
922 unregisterEvent((SunDropTargetEvent)events[i]);
923 }
924 }
925 }
926 }
927 }
--- EOF ---