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 import sun.security.util.SecurityConstants; 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 JDK1.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.checkSystemClipboardAccess(); 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 } 243 244 if (dropStatus != STATUS_ACCEPT || dropComplete) { 245 throw new InvalidDnDOperationException("No drop current"); 246 } 247 248 Map flavorMap = DataTransferer.getInstance().getFlavorsForFormats 249 (currentT, DataTransferer.adaptFlavorMap 250 (currentDT.getFlavorMap())); 251 252 lFormat = (Long)flavorMap.get(df); 253 if (lFormat == null) { 254 throw new UnsupportedFlavorException(df); 255 } 256 257 if (df.isRepresentationClassRemote() && 258 currentDA != DnDConstants.ACTION_LINK) { 259 throw new InvalidDnDOperationException("only ACTION_LINK is permissable for transfer of java.rmi.Remote objects"); 260 } 261 262 final long format = lFormat.longValue(); 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 try { 274 return DataTransferer.getInstance(). 275 translateStream((InputStream)ret, df, format, this); 276 } catch (IOException e) { 277 throw new InvalidDnDOperationException(e.getMessage()); 278 } 279 } else { 280 throw new IOException("no native data was transfered"); 281 } 282 } 283 284 protected abstract Object getNativeData(long format) 285 throws IOException; 286 287 /** 288 * @return if the transfer is a local one 289 */ 290 public boolean isTransferableJVMLocal() { 291 return local != null || getJVMLocalSourceTransferable() != null; 292 } 293 294 private int handleEnterMessage(final Component component, 295 final int x, final int y, 296 final int dropAction, 297 final int actions, final long[] formats, 298 final long nativeCtxt) { 299 return postDropTargetEvent(component, x, y, dropAction, actions, 300 formats, nativeCtxt, 301 SunDropTargetEvent.MOUSE_ENTERED, 302 SunDropTargetContextPeer.DISPATCH_SYNC); 303 } 304 305 /** 306 * actual processing on EventQueue Thread 307 */ 308 309 protected void processEnterMessage(SunDropTargetEvent event) { 310 Component c = (Component)event.getSource(); 311 DropTarget dt = c.getDropTarget(); 312 Point hots = event.getPoint(); 313 314 local = getJVMLocalSourceTransferable(); 315 316 if (currentDTC != null) { // some wreckage from last time 317 currentDTC.removeNotify(); 318 currentDTC = null; 319 } 320 321 if (c.isShowing() && dt != null && dt.isActive()) { 322 currentDT = dt; 323 currentDTC = currentDT.getDropTargetContext(); 324 325 currentDTC.addNotify(this); 326 327 currentA = dt.getDefaultActions(); 328 329 try { 330 ((DropTargetListener)dt).dragEnter(new DropTargetDragEvent(currentDTC, 331 hots, 332 currentDA, 333 currentSA)); 334 } catch (Exception e) { 335 e.printStackTrace(); 336 currentDA = DnDConstants.ACTION_NONE; 337 } 338 } else { 339 currentDT = null; 340 currentDTC = null; 341 currentDA = DnDConstants.ACTION_NONE; 342 currentSA = DnDConstants.ACTION_NONE; 343 currentA = DnDConstants.ACTION_NONE; 344 } 345 346 } 347 348 /** 349 * upcall to handle exit messages 350 */ 351 352 private void handleExitMessage(final Component component, 353 final long nativeCtxt) { 354 /* 355 * Even though the return value is irrelevant for this event, it is 356 * dispatched synchronously to fix 4393148 properly. 357 */ 358 postDropTargetEvent(component, 0, 0, DnDConstants.ACTION_NONE, 359 DnDConstants.ACTION_NONE, null, nativeCtxt, 360 SunDropTargetEvent.MOUSE_EXITED, 361 SunDropTargetContextPeer.DISPATCH_SYNC); 362 } 363 364 /** 365 * 366 */ 367 368 protected void processExitMessage(SunDropTargetEvent event) { 369 Component c = (Component)event.getSource(); 370 DropTarget dt = c.getDropTarget(); 371 DropTargetContext dtc = null; 372 373 if (dt == null) { 374 currentDT = null; 375 currentT = null; 376 377 if (currentDTC != null) { 378 currentDTC.removeNotify(); 379 } 380 381 currentDTC = null; 382 383 return; 384 } 385 386 if (dt != currentDT) { 387 388 if (currentDTC != null) { 389 currentDTC.removeNotify(); 390 } 391 392 currentDT = dt; 393 currentDTC = dt.getDropTargetContext(); 394 395 currentDTC.addNotify(this); 396 } 397 398 dtc = currentDTC; 399 400 if (dt.isActive()) try { 401 ((DropTargetListener)dt).dragExit(new DropTargetEvent(dtc)); 402 } catch (Exception e) { 403 e.printStackTrace(); 404 } finally { 405 currentA = DnDConstants.ACTION_NONE; 406 currentSA = DnDConstants.ACTION_NONE; 407 currentDA = DnDConstants.ACTION_NONE; 408 currentDT = null; 409 currentT = null; 410 411 currentDTC.removeNotify(); 412 currentDTC = null; 413 414 local = null; 415 416 dragRejected = false; 417 } 418 } 419 420 private int handleMotionMessage(final Component component, 421 final int x, final int y, 422 final int dropAction, 423 final int actions, final long[] formats, 424 final long nativeCtxt) { 425 return postDropTargetEvent(component, x, y, dropAction, actions, 426 formats, nativeCtxt, 427 SunDropTargetEvent.MOUSE_DRAGGED, 428 SunDropTargetContextPeer.DISPATCH_SYNC); 429 } 430 431 /** 432 * 433 */ 434 435 protected void processMotionMessage(SunDropTargetEvent event, 436 boolean operationChanged) { 437 Component c = (Component)event.getSource(); 438 Point hots = event.getPoint(); 439 int id = event.getID(); 440 DropTarget dt = c.getDropTarget(); 441 DropTargetContext dtc = null; 442 443 if (c.isShowing() && (dt != null) && dt.isActive()) { 444 if (currentDT != dt) { 445 if (currentDTC != null) { 446 currentDTC.removeNotify(); 447 } 448 449 currentDT = dt; 450 currentDTC = null; 451 } 452 453 dtc = currentDT.getDropTargetContext(); 454 if (dtc != currentDTC) { 455 if (currentDTC != null) { 456 currentDTC.removeNotify(); 457 } 458 459 currentDTC = dtc; 460 currentDTC.addNotify(this); 461 } 462 463 currentA = currentDT.getDefaultActions(); 464 465 try { 466 DropTargetDragEvent dtde = new DropTargetDragEvent(dtc, 467 hots, 468 currentDA, 469 currentSA); 470 DropTargetListener dtl = (DropTargetListener)dt; 471 if (operationChanged) { 472 dtl.dropActionChanged(dtde); 473 } else { 474 dtl.dragOver(dtde); 475 } 476 477 if (dragRejected) { 478 currentDA = DnDConstants.ACTION_NONE; 479 } 480 } catch (Exception e) { 481 e.printStackTrace(); 482 currentDA = DnDConstants.ACTION_NONE; 483 } 484 } else { 485 currentDA = DnDConstants.ACTION_NONE; 486 } 487 } 488 489 /** 490 * upcall to handle the Drop message 491 */ 492 493 private void handleDropMessage(final Component component, 494 final int x, final int y, 495 final int dropAction, final int actions, 496 final long[] formats, 497 final long nativeCtxt) { 498 postDropTargetEvent(component, x, y, dropAction, actions, 499 formats, nativeCtxt, 500 SunDropTargetEvent.MOUSE_DROPPED, 501 !SunDropTargetContextPeer.DISPATCH_SYNC); 502 } 503 504 /** 505 * 506 */ 507 508 protected void processDropMessage(SunDropTargetEvent event) { 509 Component c = (Component)event.getSource(); 510 Point hots = event.getPoint(); 511 DropTarget dt = c.getDropTarget(); 512 513 dropStatus = STATUS_WAIT; // drop pending ACK 514 dropComplete = false; 515 516 if (c.isShowing() && dt != null && dt.isActive()) { 517 DropTargetContext dtc = dt.getDropTargetContext(); 518 519 currentDT = dt; 520 521 if (currentDTC != null) { 522 currentDTC.removeNotify(); 523 } 524 525 currentDTC = dtc; 526 currentDTC.addNotify(this); 527 currentA = dt.getDefaultActions(); 528 529 synchronized(_globalLock) { 530 if ((local = getJVMLocalSourceTransferable()) != null) 531 setCurrentJVMLocalSourceTransferable(null); 532 } 533 534 dropInProcess = true; 535 536 try { 537 ((DropTargetListener)dt).drop(new DropTargetDropEvent(dtc, 538 hots, 539 currentDA, 540 currentSA, 541 local != null)); 542 } finally { 543 if (dropStatus == STATUS_WAIT) { 544 rejectDrop(); 545 } else if (dropComplete == false) { 546 dropComplete(false); 547 } 548 dropInProcess = false; 549 } 550 } else { 551 rejectDrop(); 552 } 553 } 554 555 protected int postDropTargetEvent(final Component component, 556 final int x, final int y, 557 final int dropAction, 558 final int actions, 559 final long[] formats, 560 final long nativeCtxt, 561 final int eventID, 562 final boolean dispatchType) { 563 AppContext appContext = SunToolkit.targetToAppContext(component); 564 565 EventDispatcher dispatcher = 566 new EventDispatcher(this, dropAction, actions, formats, nativeCtxt, 567 dispatchType); 568 569 SunDropTargetEvent event = 570 new SunDropTargetEvent(component, eventID, x, y, dispatcher); 571 572 if (dispatchType == SunDropTargetContextPeer.DISPATCH_SYNC) { 573 DataTransferer.getInstance().getToolkitThreadBlockedHandler().lock(); 574 } 575 576 // schedule callback 577 SunToolkit.postEvent(appContext, event); 578 579 eventPosted(event); 580 581 if (dispatchType == SunDropTargetContextPeer.DISPATCH_SYNC) { 582 while (!dispatcher.isDone()) { 583 DataTransferer.getInstance().getToolkitThreadBlockedHandler().enter(); 584 } 585 586 DataTransferer.getInstance().getToolkitThreadBlockedHandler().unlock(); 587 588 // return target's response 589 return dispatcher.getReturnValue(); 590 } else { 591 return 0; 592 } 593 } 594 595 /** 596 * acceptDrag 597 */ 598 599 public synchronized void acceptDrag(int dragOperation) { 600 if (currentDT == null) { 601 throw new InvalidDnDOperationException("No Drag pending"); 602 } 603 currentDA = mapOperation(dragOperation); 604 if (currentDA != DnDConstants.ACTION_NONE) { 605 dragRejected = false; 606 } 607 } 608 609 /** 610 * rejectDrag 611 */ 612 613 public synchronized void rejectDrag() { 614 if (currentDT == null) { 615 throw new InvalidDnDOperationException("No Drag pending"); 616 } 617 currentDA = DnDConstants.ACTION_NONE; 618 dragRejected = true; 619 } 620 621 /** 622 * acceptDrop 623 */ 624 625 public synchronized void acceptDrop(int dropOperation) { 626 if (dropOperation == DnDConstants.ACTION_NONE) 627 throw new IllegalArgumentException("invalid acceptDrop() action"); 628 629 if (dropStatus != STATUS_WAIT) { 630 throw new InvalidDnDOperationException("invalid acceptDrop()"); 631 } 632 633 currentDA = currentA = mapOperation(dropOperation & currentSA); 634 635 dropStatus = STATUS_ACCEPT; 636 dropComplete = false; 637 } 638 639 /** 640 * reject Drop 641 */ 642 643 public synchronized void rejectDrop() { 644 if (dropStatus != STATUS_WAIT) { 645 throw new InvalidDnDOperationException("invalid rejectDrop()"); 646 } 647 dropStatus = STATUS_REJECT; 648 /* 649 * Fix for 4285634. 650 * The target rejected the drop means that it doesn't perform any 651 * drop action. This change is to make Solaris behavior consistent 652 * with Win32. 653 */ 654 currentDA = DnDConstants.ACTION_NONE; 655 dropComplete(false); 656 } 657 658 /** 659 * mapOperation 660 */ 661 662 private int mapOperation(int operation) { 663 int[] operations = { 664 DnDConstants.ACTION_MOVE, 665 DnDConstants.ACTION_COPY, 666 DnDConstants.ACTION_LINK, 667 }; 668 int ret = DnDConstants.ACTION_NONE; 669 670 for (int i = 0; i < operations.length; i++) { 671 if ((operation & operations[i]) == operations[i]) { 672 ret = operations[i]; 673 break; 674 } 675 } 676 677 return ret; 678 } 679 680 /** 681 * signal drop complete 682 */ 683 684 public synchronized void dropComplete(boolean success) { 685 if (dropStatus == STATUS_NONE) { 686 throw new InvalidDnDOperationException("No Drop pending"); 687 } 688 689 if (currentDTC != null) currentDTC.removeNotify(); 690 691 currentDT = null; 692 currentDTC = null; 693 currentT = null; 694 currentA = DnDConstants.ACTION_NONE; 695 696 synchronized(_globalLock) { 697 currentJVMLocalSourceTransferable = null; 698 } 699 700 dropStatus = STATUS_NONE; 701 dropComplete = true; 702 703 try { 704 doDropDone(success, currentDA, local != null); 705 } finally { 706 currentDA = DnDConstants.ACTION_NONE; 707 // The native context is invalid after the drop is done. 708 // Clear the reference to prohibit access. 709 nativeDragContext = 0; 710 } 711 } 712 713 protected abstract void doDropDone(boolean success, 714 int dropAction, boolean isLocal); 715 716 protected synchronized long getNativeDragContext() { 717 return nativeDragContext; 718 } 719 720 protected void eventPosted(SunDropTargetEvent e) {} 721 722 protected void eventProcessed(SunDropTargetEvent e, int returnValue, 723 boolean dispatcherDone) {} 724 725 protected static class EventDispatcher { 726 727 private final SunDropTargetContextPeer peer; 728 729 // context fields 730 private final int dropAction; 731 private final int actions; 732 private final long[] formats; 733 private long nativeCtxt; 734 private final boolean dispatchType; 735 private boolean dispatcherDone = false; 736 737 // dispatcher state fields 738 private int returnValue = 0; 739 // set of events to be dispatched by this dispatcher 740 private final HashSet eventSet = new HashSet(3); 741 742 static final ToolkitThreadBlockedHandler handler = 743 DataTransferer.getInstance().getToolkitThreadBlockedHandler(); 744 745 EventDispatcher(SunDropTargetContextPeer peer, 746 int dropAction, 747 int actions, 748 long[] formats, 749 long nativeCtxt, 750 boolean dispatchType) { 751 752 this.peer = peer; 753 this.nativeCtxt = nativeCtxt; 754 this.dropAction = dropAction; 755 this.actions = actions; 756 this.formats = 757 (null == formats) ? null : Arrays.copyOf(formats, formats.length); 758 this.dispatchType = dispatchType; 759 } 760 761 void dispatchEvent(SunDropTargetEvent e) { 762 int id = e.getID(); 763 764 switch (id) { 765 case SunDropTargetEvent.MOUSE_ENTERED: 766 dispatchEnterEvent(e); 767 break; 768 case SunDropTargetEvent.MOUSE_DRAGGED: 769 dispatchMotionEvent(e); 770 break; 771 case SunDropTargetEvent.MOUSE_EXITED: 772 dispatchExitEvent(e); 773 break; 774 case SunDropTargetEvent.MOUSE_DROPPED: 775 dispatchDropEvent(e); 776 break; 777 default: 778 throw new InvalidDnDOperationException(); 779 } 780 } 781 782 private void dispatchEnterEvent(SunDropTargetEvent e) { 783 synchronized (peer) { 784 785 // store the drop action here to track operation changes 786 peer.previousDA = dropAction; 787 788 // setup peer context 789 peer.nativeDragContext = nativeCtxt; 790 peer.currentT = formats; 791 peer.currentSA = actions; 792 peer.currentDA = dropAction; 793 // To allow data retrieval. 794 peer.dropStatus = STATUS_ACCEPT; 795 peer.dropComplete = false; 796 797 try { 798 peer.processEnterMessage(e); 799 } finally { 800 peer.dropStatus = STATUS_NONE; 801 } 802 803 setReturnValue(peer.currentDA); 804 } 805 } 806 807 private void dispatchMotionEvent(SunDropTargetEvent e) { 808 synchronized (peer) { 809 810 boolean operationChanged = peer.previousDA != dropAction; 811 peer.previousDA = dropAction; 812 813 // setup peer context 814 peer.nativeDragContext = nativeCtxt; 815 peer.currentT = formats; 816 peer.currentSA = actions; 817 peer.currentDA = dropAction; 818 // To allow data retrieval. 819 peer.dropStatus = STATUS_ACCEPT; 820 peer.dropComplete = false; 821 822 try { 823 peer.processMotionMessage(e, operationChanged); 824 } finally { 825 peer.dropStatus = STATUS_NONE; 826 } 827 828 setReturnValue(peer.currentDA); 829 } 830 } 831 832 private void dispatchExitEvent(SunDropTargetEvent e) { 833 synchronized (peer) { 834 835 // setup peer context 836 peer.nativeDragContext = nativeCtxt; 837 838 peer.processExitMessage(e); 839 } 840 } 841 842 private void dispatchDropEvent(SunDropTargetEvent e) { 843 synchronized (peer) { 844 845 // setup peer context 846 peer.nativeDragContext = nativeCtxt; 847 peer.currentT = formats; 848 peer.currentSA = actions; 849 peer.currentDA = dropAction; 850 851 peer.processDropMessage(e); 852 } 853 } 854 855 void setReturnValue(int ret) { 856 returnValue = ret; 857 } 858 859 int getReturnValue() { 860 return returnValue; 861 } 862 863 boolean isDone() { 864 return eventSet.isEmpty(); 865 } 866 867 void registerEvent(SunDropTargetEvent e) { 868 handler.lock(); 869 if (!eventSet.add(e) && dndLog.isLoggable(PlatformLogger.FINE)) { 870 dndLog.fine("Event is already registered: " + e); 871 } 872 handler.unlock(); 873 } 874 875 void unregisterEvent(SunDropTargetEvent e) { 876 handler.lock(); 877 try { 878 if (!eventSet.remove(e)) { 879 // This event has already been unregistered. 880 return; 881 } 882 if (eventSet.isEmpty()) { 883 if (!dispatcherDone && dispatchType == DISPATCH_SYNC) { 884 handler.exit(); 885 } 886 dispatcherDone = true; 887 } 888 } finally { 889 handler.unlock(); 890 } 891 892 try { 893 peer.eventProcessed(e, returnValue, dispatcherDone); 894 } finally { 895 /* 896 * Clear the reference to the native context if all copies of 897 * the original event are processed. 898 */ 899 if (dispatcherDone) { 900 nativeCtxt = 0; 901 // Fix for 6342381 902 peer.nativeDragContext = 0; 903 904 } 905 } 906 } 907 908 public void unregisterAllEvents() { 909 Object[] events = null; 910 handler.lock(); 911 try { 912 events = eventSet.toArray(); 913 } finally { 914 handler.unlock(); 915 } 916 917 if (events != null) { 918 for (int i = 0; i < events.length; i++) { 919 unregisterEvent((SunDropTargetEvent)events[i]); 920 } 921 } 922 } 923 } 924 }