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