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