< prev index next >

src/java.desktop/macosx/native/libawt_lwawt/awt/CDropTarget.m

Print this page
rev 54094 : 8257853: Remove dependencies on JNF's JNI utility functions in AWT and 2D code
rev 54096 : 8259651: [macOS] Replace JNF_COCOA_ENTER/EXIT macros
rev 54097 : 8259869: [macOS] Remove desktop module dependencies on JNF Reference APIs
rev 54098 : 8260616: Removing remaining JNF dependencies in the java.desktop module
8259729: Missed JNFInstanceOf -> IsInstanceOf conversion


  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 //#define DND_DEBUG TRUE
  27 
  28 #import "CDropTarget.h"
  29 #import "AWTView.h"
  30 
  31 #import "sun_lwawt_macosx_CDropTarget.h"
  32 #import "java_awt_dnd_DnDConstants.h"
  33 
  34 #import <JavaNativeFoundation/JavaNativeFoundation.h>
  35 #import <JavaRuntimeSupport/JavaRuntimeSupport.h>
  36 #include <objc/objc-runtime.h>
  37 
  38 
  39 #import "CDragSource.h"
  40 #import "CDataTransferer.h"
  41 #import "DnDUtilities.h"
  42 #import "ThreadUtilities.h"

  43 
  44 
  45 static NSInteger        sDraggingSequenceNumber = -1;
  46 static NSDragOperation    sDragOperation;
  47 static NSDragOperation    sUpdateOperation;
  48 static jint                sJavaDropOperation;
  49 static NSPoint            sDraggingLocation;
  50 static BOOL                sDraggingExited;
  51 static BOOL                sDraggingError;
  52 
  53 static NSUInteger        sPasteboardItemsCount = 0;
  54 static NSArray*            sPasteboardTypes = nil;
  55 static NSArray*            sPasteboardData = nil;
  56 static jlongArray        sDraggingFormats = nil;
  57 
  58 static CDropTarget*        sCurrentDropTarget;
  59 
  60 extern JNFClassInfo jc_CDropTargetContextPeer;





  61 
  62 @implementation CDropTarget
  63 
  64 + (CDropTarget *) currentDropTarget {
  65     return sCurrentDropTarget;
  66 }
  67 
  68 - (id)init:(jobject)jdropTarget component:(jobject)jcomponent control:(id)control
  69 {
  70     self = [super init];
  71     DLog2(@"[CDropTarget init]: %@\n", self);
  72 
  73     fView = nil;
  74     fComponent = nil;
  75     fDropTarget = nil;
  76     fDropTargetContextPeer = nil;
  77 
  78 
  79     if (control != nil) {
  80         JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
  81         fComponent = JNFNewGlobalRef(env, jcomponent);
  82         fDropTarget = JNFNewGlobalRef(env, jdropTarget);
  83 
  84         fView = [((AWTView *) control) retain];
  85         [fView setDropTarget:self];
  86 
  87 
  88     } else {
  89         // This would be an error.
  90         [self release];
  91         self = nil;
  92     }
  93     return self;
  94 }
  95 
  96 // When [CDropTarget init] is called the ControlModel's fView may not have been set up yet. ControlModel
  97 // (soon after) calls [CDropTarget controlModelControlValid] on the native event thread, once per CDropTarget,
  98 // to let it know it's been set up now.
  99 - (void)controlModelControlValid
 100 {
 101     // 9-30-02 Note: [Radar 3065621]
 102     // List all known pasteboard types here (see AppKit's NSPasteboard.h)


 125 
 126     // Enable dragging events over this object:
 127     [fView registerForDraggedTypes:dataTypes];
 128 
 129     [dataTypes release];
 130 }
 131 
 132 - (void)releaseDraggingData
 133 {
 134     DLog2(@"[CDropTarget releaseDraggingData]: %@\n", self);
 135 
 136     // Release any old pasteboard types, data and properties:
 137     [sPasteboardTypes release];
 138     sPasteboardTypes = nil;
 139 
 140     [sPasteboardData release];
 141     sPasteboardData = nil;
 142 
 143     if (sDraggingFormats != NULL) {
 144         JNIEnv *env = [ThreadUtilities getJNIEnv];
 145         JNFDeleteGlobalRef(env, sDraggingFormats);
 146         sDraggingFormats = NULL;
 147     }
 148 
 149     sPasteboardItemsCount = 0;
 150     sDraggingSequenceNumber = -1;
 151 }
 152 
 153 - (void)removeFromView:(JNIEnv *)env
 154 {
 155     DLog2(@"[CDropTarget removeFromView]: %@\n", self);
 156 
 157     // Remove this dragging destination from the view:
 158     [((AWTView *) fView) setDropTarget:nil];
 159 
 160     // Clean up JNI refs
 161     if (fComponent != NULL) {
 162         JNFDeleteGlobalRef(env, fComponent);
 163         fComponent = NULL;
 164     }
 165     if (fDropTarget != NULL) {
 166         JNFDeleteGlobalRef(env, fDropTarget);
 167         fDropTarget = NULL;
 168     }
 169     if (fDropTargetContextPeer != NULL) {
 170         JNFDeleteGlobalRef(env, fDropTargetContextPeer);
 171         fDropTargetContextPeer = NULL;
 172     }
 173 
 174     [self release];
 175 }
 176 
 177 - (void)dealloc
 178 {
 179     DLog2(@"[CDropTarget dealloc]: %@\n", self);
 180 
 181     if(sCurrentDropTarget == self) {
 182         sCurrentDropTarget = nil;
 183     }
 184 
 185     [fView release];
 186     fView = nil;
 187 
 188     [super dealloc];
 189 }
 190 


 216 }
 217 
 218 - (BOOL)copyDraggingTypes:(id<NSDraggingInfo>)sender
 219 {
 220     DLog2(@"[CDropTarget copyDraggingTypes]: %@\n", self);
 221     JNIEnv*    env = [ThreadUtilities getJNIEnv];
 222 
 223     // Release any old pasteboard data:
 224     [self releaseDraggingData];
 225 
 226     NSPasteboard* pb = [sender draggingPasteboard];
 227     sPasteboardTypes = [[pb types] retain];
 228     sPasteboardItemsCount = [sPasteboardTypes count];
 229     if (sPasteboardItemsCount == 0)
 230         return FALSE;
 231 
 232     jlongArray formats = (*env)->NewLongArray(env, sPasteboardItemsCount);
 233     if (formats == nil)
 234         return FALSE;
 235 
 236     sDraggingFormats = (jlongArray) JNFNewGlobalRef(env, formats);
 237     (*env)->DeleteLocalRef(env, formats);
 238     if (sDraggingFormats == nil)
 239         return FALSE;
 240 
 241     jboolean isCopy;
 242     jlong* jformats = (*env)->GetLongArrayElements(env, sDraggingFormats, &isCopy);
 243     if (jformats == nil) {
 244         return FALSE;
 245     }
 246 
 247     // Copy all data formats and properties. In case of properties, if they are nil, we need to use
 248     // a special NilProperty since [NSArray addObject] would crash on adding a nil object.
 249     DLog2(@"[CDropTarget copyDraggingTypes]: typesCount = %lu\n", (unsigned long) sPasteboardItemsCount);
 250     NSUInteger i;
 251     for (i = 0; i < sPasteboardItemsCount; i++) {
 252         NSString* pbType = [sPasteboardTypes objectAtIndex:i];
 253         DLog3(@"[CDropTarget copyDraggingTypes]: type[%lu] = %@\n", (unsigned long) i, pbType);
 254 
 255         // 01-10-03 Note: until we need data properties for doing something useful don't copy them.
 256         // They're often copies of their flavor's data and copying them for all available pasteboard flavors


 333     if ([sPasteboardTypes containsObject:pbType]) {
 334         NSUInteger dataIndex = [sPasteboardTypes indexOfObject:pbType];
 335         data = [sPasteboardData objectAtIndex:dataIndex];
 336 
 337         if ((id) data == [NSNull null])
 338             data = nil;
 339 
 340         // format == 8 (CF_URL in CDataTransferer): we need a URL-to-String conversion:
 341         else if ([pbType isEqualToString:@"Apple URL pasteboard type"])
 342             data = [self getDraggingDataForURL:data];
 343     }
 344 
 345     // Get NS data:
 346     char* dataBytes = (data != nil) ? (char*) [data bytes] : "Unsupported type";
 347     NSUInteger dataLength = (data != nil) ? [data length] : sizeof("Unsupported type");
 348 
 349     // Create a global byte array:
 350     jbyteArray lbyteArray = (*env)->NewByteArray(env, dataLength);
 351     if (lbyteArray == nil)
 352         return nil;
 353     jbyteArray gbyteArray = (jbyteArray) JNFNewGlobalRef(env, lbyteArray);
 354     (*env)->DeleteLocalRef(env, lbyteArray);
 355     if (gbyteArray == nil)
 356         return nil;
 357 
 358     // Get byte array elements:
 359     jboolean isCopy;
 360     jbyte* jbytes = (*env)->GetByteArrayElements(env, gbyteArray, &isCopy);
 361     if (jbytes == nil)
 362         return nil;
 363 
 364     // Copy data to byte array and release elements:
 365     memcpy(jbytes, dataBytes, dataLength);
 366     (*env)->ReleaseByteArrayElements(env, gbyteArray, jbytes, JNI_COMMIT);
 367 
 368     // In case of an error make sure to return nil:
 369     if ((*env)->ExceptionOccurred(env)) {
 370                 (*env)->ExceptionDescribe(env);
 371         gbyteArray = nil;
 372         }
 373 


 436     DLog2(@"[CDropTarget draggingEntered]: %@\n", self);
 437 
 438     sCurrentDropTarget = self;
 439 
 440     JNIEnv* env = [ThreadUtilities getJNIEnv];
 441     NSInteger draggingSequenceNumber = [sender draggingSequenceNumber];
 442 
 443     // Set the initial drag operation return value:
 444     NSDragOperation dragOp = NSDragOperationNone;
 445         sJavaDropOperation = java_awt_dnd_DnDConstants_ACTION_NONE;
 446 
 447     // We could probably special-case some stuff if drag and drop objects match:
 448     //if ([sender dragSource] == fView)
 449 
 450     if (draggingSequenceNumber != sDraggingSequenceNumber) {
 451         sDraggingSequenceNumber = draggingSequenceNumber;
 452         sDraggingError = FALSE;
 453 
 454         // Delete any drop target context peer left over from a previous drag:
 455         if (fDropTargetContextPeer != NULL) {
 456             JNFDeleteGlobalRef(env, fDropTargetContextPeer);
 457             fDropTargetContextPeer = NULL;
 458         }
 459 
 460         // Look up the CDropTargetContextPeer class:
 461         JNF_STATIC_MEMBER_CACHE(getDropTargetContextPeerMethod, jc_CDropTargetContextPeer, "getDropTargetContextPeer", "()Lsun/lwawt/macosx/CDropTargetContextPeer;");


 462         if (sDraggingError == FALSE) {
 463             // Create a new drop target context peer:
 464             jobject dropTargetContextPeer = JNFCallStaticObjectMethod(env, getDropTargetContextPeerMethod);

 465 
 466             if (dropTargetContextPeer != nil) {
 467                 fDropTargetContextPeer = JNFNewGlobalRef(env, dropTargetContextPeer);
 468                 (*env)->DeleteLocalRef(env, dropTargetContextPeer);
 469             }
 470         }
 471 
 472         // Get dragging types (dragging data is only copied if dropped):
 473         if (sDraggingError == FALSE && [self copyDraggingTypes:sender] == FALSE)
 474             sDraggingError = TRUE;
 475     }
 476 
 477     if (sDraggingError == FALSE) {
 478         sDraggingExited = FALSE;
 479         sDraggingLocation = [sender draggingLocation];
 480         NSPoint javaLocation = [fView convertPoint:sDraggingLocation fromView:nil];
 481         javaLocation.y = fView.window.frame.size.height - javaLocation.y;
 482 
 483         DLog5(@"+ dragEnter: loc native %f, %f, java %f, %f\n", sDraggingLocation.x, sDraggingLocation.y, javaLocation.x, javaLocation.y);
 484 
 485                 ////////// BEGIN Calculate the current drag actions //////////
 486                 jint actions = java_awt_dnd_DnDConstants_ACTION_NONE;
 487         jint dropAction = actions;
 488 
 489                 [self calculateCurrentSourceActions:&actions dropAction:&dropAction];
 490 
 491                 sJavaDropOperation = dropAction;
 492                 ////////// END Calculate the current drag actions //////////
 493 
 494         jlongArray formats = sDraggingFormats;
 495 
 496         JNF_MEMBER_CACHE(handleEnterMessageMethod, jc_CDropTargetContextPeer, "handleEnterMessage", "(Ljava/awt/Component;IIII[JJ)I");


 497         if (sDraggingError == FALSE) {
 498             // Double-casting self gets rid of 'different size' compiler warning:
 499             // AWT_THREADING Safe (CToolkitThreadBlockedHandler)
 500             actions = JNFCallIntMethod(env, fDropTargetContextPeer, handleEnterMessageMethod,
 501                                        fComponent, (jint) javaLocation.x, (jint) javaLocation.y,
 502                                        dropAction, actions, formats, ptr_to_jlong(self));

 503         }
 504 
 505         if (sDraggingError == FALSE) {
 506             // Initialize drag operation:
 507             sDragOperation = NSDragOperationNone;
 508 
 509             // Map Java actions back to NSDragOperation.
 510             // 1-6-03 Note: if the entry point of this CDropTarget isn't covered by a droppable component
 511             // (as can be the case with lightweight children) we must not return NSDragOperationNone
 512             // since that would prevent dropping into any of the contained drop targets.
 513             // Unfortunately there is no easy way to test this so we just test actions and override them
 514             // with GENERIC if necessary. Proper drag operations will be returned by draggingUpdated: which is
 515             // called right away, taking care of setting the right cursor and snap-back action.
 516             dragOp = ((actions != java_awt_dnd_DnDConstants_ACTION_NONE) ?
 517                 [DnDUtilities mapJavaDragOperationToNS:dropAction] : NSDragOperationGeneric);
 518 
 519             // Remember the dragOp for no-op'd update messages:
 520             sUpdateOperation = dragOp;
 521         }
 522     }


 561         jint dropAction = actions;
 562 
 563         [self calculateCurrentSourceActions:&actions dropAction:&dropAction];
 564 
 565         if (sJavaDropOperation != dropAction) {
 566             sJavaDropOperation = dropAction;
 567             notifyJava = TRUE;
 568         }
 569         ////////// END Calculate the current drag actions //////////
 570 
 571     jint userAction = dropAction;
 572 
 573     // Should we notify Java things have changed?
 574     if (sDraggingError == FALSE && notifyJava) {
 575         NSPoint javaLocation = [fView convertPoint:sDraggingLocation fromView:nil];
 576         javaLocation.y = fView.window.frame.size.height - javaLocation.y;
 577         //DLog5(@"  : dragMoved: loc native %f, %f, java %f, %f\n", sDraggingLocation.x, sDraggingLocation.y, javaLocation.x, javaLocation.y);
 578 
 579         jlongArray formats = sDraggingFormats;
 580 
 581         JNF_MEMBER_CACHE(handleMotionMessageMethod, jc_CDropTargetContextPeer, "handleMotionMessage", "(Ljava/awt/Component;IIII[JJ)I");

 582         if (sDraggingError == FALSE) {
 583             DLog3(@"  >> posting handleMotionMessage, point %f, %f", javaLocation.x, javaLocation.y);
 584             userAction = JNFCallIntMethod(env, fDropTargetContextPeer, handleMotionMessageMethod, fComponent, (jint) javaLocation.x, (jint) javaLocation.y, dropAction, actions, formats, ptr_to_jlong(self)); // AWT_THREADING Safe (CToolkitThreadBlockedHandler)


 585         }
 586 
 587         if (sDraggingError == FALSE) {
 588             dragOp = [DnDUtilities mapJavaDragOperationToNS:userAction];
 589 
 590             // Remember the dragOp for no-op'd update messages:
 591             sUpdateOperation = dragOp;
 592         } else {
 593             dragOp = NSDragOperationNone;
 594         }
 595     }
 596 
 597     DLog2(@"[CDropTarget draggingUpdated]: returning %lu\n", (unsigned long) dragOp);
 598 
 599     return dragOp;
 600 }
 601 
 602 - (void)draggingExited:(id<NSDraggingInfo>)sender
 603 {
 604     DLog2(@"[CDropTarget draggingExited]: %@\n", self);
 605 
 606     sCurrentDropTarget = nil;
 607 
 608     JNIEnv* env = [ThreadUtilities getJNIEnv];
 609 
 610     if (sDraggingExited == FALSE && sDraggingError == FALSE) {
 611         JNF_MEMBER_CACHE(handleExitMessageMethod, jc_CDropTargetContextPeer, "handleExitMessage", "(Ljava/awt/Component;J)V");

 612         if (sDraggingError == FALSE) {
 613             DLog3(@"  - dragExit: loc native %f, %f\n", sDraggingLocation.x, sDraggingLocation.y);
 614              // AWT_THREADING Safe (CToolkitThreadBlockedHandler)
 615             JNFCallVoidMethod(env, fDropTargetContextPeer,
 616                               handleExitMessageMethod, fComponent, ptr_to_jlong(self));

 617         }
 618 
 619         // 5-27-03 Note: [Radar 3270455]
 620         // -draggingExited: can be called both by the AppKit and by -performDragOperation: but shouldn't execute
 621         // twice per drop since cleanup code like that in swing/plaf/basic/BasicDropTargetListener would throw NPEs.
 622         sDraggingExited = TRUE;
 623     }
 624 
 625     DLog(@"[CDropTarget draggingExited]: returning.\n");
 626 }
 627 
 628 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
 629 {
 630     DLog2(@"[CDropTarget prepareForDragOperation]: %@\n", self);
 631     DLog2(@"[CDropTarget prepareForDragOperation]: returning %@\n", (sDraggingError ? @"NO" : @"YES"));
 632 
 633     return sDraggingError ? NO : YES;
 634 }
 635 
 636 - (BOOL)performDragOperation:(id<NSDraggingInfo>)sender


 641 
 642     JNIEnv* env = [ThreadUtilities getJNIEnv];
 643 
 644     // Now copy dragging data:
 645     if (sDraggingError == FALSE && [self copyDraggingData:sender] == FALSE)
 646         sDraggingError = TRUE;
 647 
 648     if (sDraggingError == FALSE) {
 649         sDraggingLocation = [sender draggingLocation];
 650         NSPoint javaLocation = [fView convertPoint:sDraggingLocation fromView:nil];
 651         // The y coordinate that comes in the NSDraggingInfo seems to be reversed - probably
 652         // has to do something with the type of view it comes to.
 653         // This is the earliest place where we can correct it.
 654         javaLocation.y = fView.window.frame.size.height - javaLocation.y;
 655 
 656         jint actions = [DnDUtilities mapNSDragOperationMaskToJava:[sender draggingSourceOperationMask]];
 657         jint dropAction = sJavaDropOperation;
 658 
 659         jlongArray formats = sDraggingFormats;
 660 
 661         JNF_MEMBER_CACHE(handleDropMessageMethod, jc_CDropTargetContextPeer, "handleDropMessage", "(Ljava/awt/Component;IIII[JJ)V");

 662 
 663         if (sDraggingError == FALSE) {
 664             JNFCallVoidMethod(env, fDropTargetContextPeer, handleDropMessageMethod, fComponent, (jint) javaLocation.x, (jint) javaLocation.y, dropAction, actions, formats, ptr_to_jlong(self)); // AWT_THREADING Safe (event)


 665         }
 666     } else {
 667         // 8-19-03 Note: [Radar 3368754]
 668         // draggingExited: is not called after a drop - we must do that here ... but only in case
 669         // of an error, instead of drop(). Otherwise we get twice the cleanup in shared code.
 670         [self draggingExited:sender];
 671     }
 672 
 673 // TODO:BG
 674 //   [(id)sender _setLastDragDestinationOperation:sDragOperation];
 675 
 676 
 677     DLog2(@"[CDropTarget performDragOperation]: returning %@\n", (sDraggingError ? @"NO" : @"YES"));
 678 
 679     return !sDraggingError;
 680 }
 681 
 682 - (void)concludeDragOperation:(id<NSDraggingInfo>)sender
 683 {
 684     sCurrentDropTarget = nil;


 694 
 695     DLog2(@"[CDropTarget draggingEnded]: %@\n", self);
 696     DLog(@"[CDropTarget draggingEnded]: returning.\n");
 697 }
 698 
 699 /********************************  END NSDraggingDestination Interface  ********************************/
 700 
 701 @end
 702 
 703 
 704 /*
 705  * Class:     sun_lwawt_macosx_CDropTarget
 706  * Method:    createNativeDropTarget
 707  * Signature: (Ljava/awt/dnd/DropTarget;Ljava/awt/Component;Ljava/awt/peer/ComponentPeer;J)J
 708  */
 709 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CDropTarget_createNativeDropTarget
 710   (JNIEnv *env, jobject jthis, jobject jdroptarget, jobject jcomponent, jlong jnativepeer)
 711 {
 712     CDropTarget* dropTarget = nil;
 713 
 714 JNF_COCOA_ENTER(env);
 715     id controlObj = (id) jlong_to_ptr(jnativepeer);
 716     dropTarget = [[CDropTarget alloc] init:jdroptarget component:jcomponent control:controlObj];
 717 JNF_COCOA_EXIT(env);
 718 
 719     return ptr_to_jlong(dropTarget);
 720 }
 721 
 722 /*
 723  * Class:     sun_lwawt_macosx_CDropTarget
 724  * Method:    releaseNativeDropTarget
 725  * Signature: (J)V
 726  */
 727 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CDropTarget_releaseNativeDropTarget
 728   (JNIEnv *env, jobject jthis, jlong nativeDropTargetVal)
 729 {
 730     id dropTarget = (id)jlong_to_ptr(nativeDropTargetVal);
 731 
 732 JNF_COCOA_ENTER(env);
 733     [dropTarget removeFromView:env];
 734 JNF_COCOA_EXIT(env);
 735 }


  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 //#define DND_DEBUG TRUE
  27 
  28 #import "CDropTarget.h"
  29 #import "AWTView.h"
  30 
  31 #import "sun_lwawt_macosx_CDropTarget.h"
  32 #import "java_awt_dnd_DnDConstants.h"
  33 

  34 #import <JavaRuntimeSupport/JavaRuntimeSupport.h>
  35 #include <objc/objc-runtime.h>
  36 
  37 
  38 #import "CDragSource.h"
  39 #import "CDataTransferer.h"
  40 #import "DnDUtilities.h"
  41 #import "ThreadUtilities.h"
  42 #import "JNIUtilities.h"
  43 
  44 
  45 static NSInteger        sDraggingSequenceNumber = -1;
  46 static NSDragOperation    sDragOperation;
  47 static NSDragOperation    sUpdateOperation;
  48 static jint                sJavaDropOperation;
  49 static NSPoint            sDraggingLocation;
  50 static BOOL                sDraggingExited;
  51 static BOOL                sDraggingError;
  52 
  53 static NSUInteger        sPasteboardItemsCount = 0;
  54 static NSArray*            sPasteboardTypes = nil;
  55 static NSArray*            sPasteboardData = nil;
  56 static jlongArray        sDraggingFormats = nil;
  57 
  58 static CDropTarget*        sCurrentDropTarget;
  59 
  60 extern jclass jc_CDropTargetContextPeer;
  61 #define GET_DTCP_CLASS() \
  62     GET_CLASS(jc_CDropTargetContextPeer, "sun/lwawt/macosx/CDropTargetContextPeer");
  63 
  64 #define GET_DTCP_CLASS_RETURN(ret) \
  65     GET_CLASS_RETURN(jc_CDropTargetContextPeer, "sun/lwawt/macosx/CDropTargetContextPeer", ret);
  66 
  67 @implementation CDropTarget
  68 
  69 + (CDropTarget *) currentDropTarget {
  70     return sCurrentDropTarget;
  71 }
  72 
  73 - (id)init:(jobject)jdropTarget component:(jobject)jcomponent control:(id)control
  74 {
  75     self = [super init];
  76     DLog2(@"[CDropTarget init]: %@\n", self);
  77 
  78     fView = nil;
  79     fComponent = nil;
  80     fDropTarget = nil;
  81     fDropTargetContextPeer = nil;
  82 
  83 
  84     if (control != nil) {
  85         JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
  86         fComponent = (*env)->NewGlobalRef(env, jcomponent);
  87         fDropTarget = (*env)->NewGlobalRef(env, jdropTarget);
  88 
  89         fView = [((AWTView *) control) retain];
  90         [fView setDropTarget:self];
  91 
  92 
  93     } else {
  94         // This would be an error.
  95         [self release];
  96         self = nil;
  97     }
  98     return self;
  99 }
 100 
 101 // When [CDropTarget init] is called the ControlModel's fView may not have been set up yet. ControlModel
 102 // (soon after) calls [CDropTarget controlModelControlValid] on the native event thread, once per CDropTarget,
 103 // to let it know it's been set up now.
 104 - (void)controlModelControlValid
 105 {
 106     // 9-30-02 Note: [Radar 3065621]
 107     // List all known pasteboard types here (see AppKit's NSPasteboard.h)


 130 
 131     // Enable dragging events over this object:
 132     [fView registerForDraggedTypes:dataTypes];
 133 
 134     [dataTypes release];
 135 }
 136 
 137 - (void)releaseDraggingData
 138 {
 139     DLog2(@"[CDropTarget releaseDraggingData]: %@\n", self);
 140 
 141     // Release any old pasteboard types, data and properties:
 142     [sPasteboardTypes release];
 143     sPasteboardTypes = nil;
 144 
 145     [sPasteboardData release];
 146     sPasteboardData = nil;
 147 
 148     if (sDraggingFormats != NULL) {
 149         JNIEnv *env = [ThreadUtilities getJNIEnv];
 150         (*env)->DeleteGlobalRef(env, sDraggingFormats);
 151         sDraggingFormats = NULL;
 152     }
 153 
 154     sPasteboardItemsCount = 0;
 155     sDraggingSequenceNumber = -1;
 156 }
 157 
 158 - (void)removeFromView:(JNIEnv *)env
 159 {
 160     DLog2(@"[CDropTarget removeFromView]: %@\n", self);
 161 
 162     // Remove this dragging destination from the view:
 163     [((AWTView *) fView) setDropTarget:nil];
 164 
 165     // Clean up JNI refs
 166     if (fComponent != NULL) {
 167         (*env)->DeleteGlobalRef(env, fComponent);
 168         fComponent = NULL;
 169     }
 170     if (fDropTarget != NULL) {
 171         (*env)->DeleteGlobalRef(env, fDropTarget);
 172         fDropTarget = NULL;
 173     }
 174     if (fDropTargetContextPeer != NULL) {
 175         (*env)->DeleteGlobalRef(env, fDropTargetContextPeer);
 176         fDropTargetContextPeer = NULL;
 177     }
 178 
 179     [self release];
 180 }
 181 
 182 - (void)dealloc
 183 {
 184     DLog2(@"[CDropTarget dealloc]: %@\n", self);
 185 
 186     if(sCurrentDropTarget == self) {
 187         sCurrentDropTarget = nil;
 188     }
 189 
 190     [fView release];
 191     fView = nil;
 192 
 193     [super dealloc];
 194 }
 195 


 221 }
 222 
 223 - (BOOL)copyDraggingTypes:(id<NSDraggingInfo>)sender
 224 {
 225     DLog2(@"[CDropTarget copyDraggingTypes]: %@\n", self);
 226     JNIEnv*    env = [ThreadUtilities getJNIEnv];
 227 
 228     // Release any old pasteboard data:
 229     [self releaseDraggingData];
 230 
 231     NSPasteboard* pb = [sender draggingPasteboard];
 232     sPasteboardTypes = [[pb types] retain];
 233     sPasteboardItemsCount = [sPasteboardTypes count];
 234     if (sPasteboardItemsCount == 0)
 235         return FALSE;
 236 
 237     jlongArray formats = (*env)->NewLongArray(env, sPasteboardItemsCount);
 238     if (formats == nil)
 239         return FALSE;
 240 
 241     sDraggingFormats = (jlongArray) (*env)->NewGlobalRef(env, formats);
 242     (*env)->DeleteLocalRef(env, formats);
 243     if (sDraggingFormats == nil)
 244         return FALSE;
 245 
 246     jboolean isCopy;
 247     jlong* jformats = (*env)->GetLongArrayElements(env, sDraggingFormats, &isCopy);
 248     if (jformats == nil) {
 249         return FALSE;
 250     }
 251 
 252     // Copy all data formats and properties. In case of properties, if they are nil, we need to use
 253     // a special NilProperty since [NSArray addObject] would crash on adding a nil object.
 254     DLog2(@"[CDropTarget copyDraggingTypes]: typesCount = %lu\n", (unsigned long) sPasteboardItemsCount);
 255     NSUInteger i;
 256     for (i = 0; i < sPasteboardItemsCount; i++) {
 257         NSString* pbType = [sPasteboardTypes objectAtIndex:i];
 258         DLog3(@"[CDropTarget copyDraggingTypes]: type[%lu] = %@\n", (unsigned long) i, pbType);
 259 
 260         // 01-10-03 Note: until we need data properties for doing something useful don't copy them.
 261         // They're often copies of their flavor's data and copying them for all available pasteboard flavors


 338     if ([sPasteboardTypes containsObject:pbType]) {
 339         NSUInteger dataIndex = [sPasteboardTypes indexOfObject:pbType];
 340         data = [sPasteboardData objectAtIndex:dataIndex];
 341 
 342         if ((id) data == [NSNull null])
 343             data = nil;
 344 
 345         // format == 8 (CF_URL in CDataTransferer): we need a URL-to-String conversion:
 346         else if ([pbType isEqualToString:@"Apple URL pasteboard type"])
 347             data = [self getDraggingDataForURL:data];
 348     }
 349 
 350     // Get NS data:
 351     char* dataBytes = (data != nil) ? (char*) [data bytes] : "Unsupported type";
 352     NSUInteger dataLength = (data != nil) ? [data length] : sizeof("Unsupported type");
 353 
 354     // Create a global byte array:
 355     jbyteArray lbyteArray = (*env)->NewByteArray(env, dataLength);
 356     if (lbyteArray == nil)
 357         return nil;
 358     jbyteArray gbyteArray = (jbyteArray) (*env)->NewGlobalRef(env, lbyteArray);
 359     (*env)->DeleteLocalRef(env, lbyteArray);
 360     if (gbyteArray == nil)
 361         return nil;
 362 
 363     // Get byte array elements:
 364     jboolean isCopy;
 365     jbyte* jbytes = (*env)->GetByteArrayElements(env, gbyteArray, &isCopy);
 366     if (jbytes == nil)
 367         return nil;
 368 
 369     // Copy data to byte array and release elements:
 370     memcpy(jbytes, dataBytes, dataLength);
 371     (*env)->ReleaseByteArrayElements(env, gbyteArray, jbytes, JNI_COMMIT);
 372 
 373     // In case of an error make sure to return nil:
 374     if ((*env)->ExceptionOccurred(env)) {
 375                 (*env)->ExceptionDescribe(env);
 376         gbyteArray = nil;
 377         }
 378 


 441     DLog2(@"[CDropTarget draggingEntered]: %@\n", self);
 442 
 443     sCurrentDropTarget = self;
 444 
 445     JNIEnv* env = [ThreadUtilities getJNIEnv];
 446     NSInteger draggingSequenceNumber = [sender draggingSequenceNumber];
 447 
 448     // Set the initial drag operation return value:
 449     NSDragOperation dragOp = NSDragOperationNone;
 450         sJavaDropOperation = java_awt_dnd_DnDConstants_ACTION_NONE;
 451 
 452     // We could probably special-case some stuff if drag and drop objects match:
 453     //if ([sender dragSource] == fView)
 454 
 455     if (draggingSequenceNumber != sDraggingSequenceNumber) {
 456         sDraggingSequenceNumber = draggingSequenceNumber;
 457         sDraggingError = FALSE;
 458 
 459         // Delete any drop target context peer left over from a previous drag:
 460         if (fDropTargetContextPeer != NULL) {
 461             (*env)->DeleteGlobalRef(env, fDropTargetContextPeer);
 462             fDropTargetContextPeer = NULL;
 463         }
 464 
 465         // Look up the CDropTargetContextPeer class:
 466         GET_DTCP_CLASS_RETURN(dragOp);
 467         DECLARE_STATIC_METHOD_RETURN(getDropTargetContextPeerMethod, jc_CDropTargetContextPeer,
 468                                      "getDropTargetContextPeer", "()Lsun/lwawt/macosx/CDropTargetContextPeer;", dragOp)
 469         if (sDraggingError == FALSE) {
 470             // Create a new drop target context peer:
 471             jobject dropTargetContextPeer = (*env)->CallStaticObjectMethod(env, jc_CDropTargetContextPeer, getDropTargetContextPeerMethod);
 472             CHECK_EXCEPTION();
 473 
 474             if (dropTargetContextPeer != nil) {
 475                 fDropTargetContextPeer = (*env)->NewGlobalRef(env, dropTargetContextPeer);
 476                 (*env)->DeleteLocalRef(env, dropTargetContextPeer);
 477             }
 478         }
 479 
 480         // Get dragging types (dragging data is only copied if dropped):
 481         if (sDraggingError == FALSE && [self copyDraggingTypes:sender] == FALSE)
 482             sDraggingError = TRUE;
 483     }
 484 
 485     if (sDraggingError == FALSE) {
 486         sDraggingExited = FALSE;
 487         sDraggingLocation = [sender draggingLocation];
 488         NSPoint javaLocation = [fView convertPoint:sDraggingLocation fromView:nil];
 489         javaLocation.y = fView.window.frame.size.height - javaLocation.y;
 490 
 491         DLog5(@"+ dragEnter: loc native %f, %f, java %f, %f\n", sDraggingLocation.x, sDraggingLocation.y, javaLocation.x, javaLocation.y);
 492 
 493                 ////////// BEGIN Calculate the current drag actions //////////
 494                 jint actions = java_awt_dnd_DnDConstants_ACTION_NONE;
 495         jint dropAction = actions;
 496 
 497                 [self calculateCurrentSourceActions:&actions dropAction:&dropAction];
 498 
 499                 sJavaDropOperation = dropAction;
 500                 ////////// END Calculate the current drag actions //////////
 501 
 502         jlongArray formats = sDraggingFormats;
 503 
 504         GET_DTCP_CLASS_RETURN(dragOp);
 505         DECLARE_METHOD_RETURN(handleEnterMessageMethod, jc_CDropTargetContextPeer,
 506                               "handleEnterMessage", "(Ljava/awt/Component;IIII[JJ)I", dragOp);
 507         if (sDraggingError == FALSE) {
 508             // Double-casting self gets rid of 'different size' compiler warning:
 509             // AWT_THREADING Safe (CToolkitThreadBlockedHandler)
 510             actions = (*env)->CallIntMethod(env, fDropTargetContextPeer, handleEnterMessageMethod,
 511                                        fComponent, (jint) javaLocation.x, (jint) javaLocation.y,
 512                                        dropAction, actions, formats, ptr_to_jlong(self));
 513             CHECK_EXCEPTION();
 514         }
 515 
 516         if (sDraggingError == FALSE) {
 517             // Initialize drag operation:
 518             sDragOperation = NSDragOperationNone;
 519 
 520             // Map Java actions back to NSDragOperation.
 521             // 1-6-03 Note: if the entry point of this CDropTarget isn't covered by a droppable component
 522             // (as can be the case with lightweight children) we must not return NSDragOperationNone
 523             // since that would prevent dropping into any of the contained drop targets.
 524             // Unfortunately there is no easy way to test this so we just test actions and override them
 525             // with GENERIC if necessary. Proper drag operations will be returned by draggingUpdated: which is
 526             // called right away, taking care of setting the right cursor and snap-back action.
 527             dragOp = ((actions != java_awt_dnd_DnDConstants_ACTION_NONE) ?
 528                 [DnDUtilities mapJavaDragOperationToNS:dropAction] : NSDragOperationGeneric);
 529 
 530             // Remember the dragOp for no-op'd update messages:
 531             sUpdateOperation = dragOp;
 532         }
 533     }


 572         jint dropAction = actions;
 573 
 574         [self calculateCurrentSourceActions:&actions dropAction:&dropAction];
 575 
 576         if (sJavaDropOperation != dropAction) {
 577             sJavaDropOperation = dropAction;
 578             notifyJava = TRUE;
 579         }
 580         ////////// END Calculate the current drag actions //////////
 581 
 582     jint userAction = dropAction;
 583 
 584     // Should we notify Java things have changed?
 585     if (sDraggingError == FALSE && notifyJava) {
 586         NSPoint javaLocation = [fView convertPoint:sDraggingLocation fromView:nil];
 587         javaLocation.y = fView.window.frame.size.height - javaLocation.y;
 588         //DLog5(@"  : dragMoved: loc native %f, %f, java %f, %f\n", sDraggingLocation.x, sDraggingLocation.y, javaLocation.x, javaLocation.y);
 589 
 590         jlongArray formats = sDraggingFormats;
 591 
 592         GET_DTCP_CLASS_RETURN(dragOp);
 593         DECLARE_METHOD_RETURN(handleMotionMessageMethod, jc_CDropTargetContextPeer, "handleMotionMessage", "(Ljava/awt/Component;IIII[JJ)I", dragOp);
 594         if (sDraggingError == FALSE) {
 595             DLog3(@"  >> posting handleMotionMessage, point %f, %f", javaLocation.x, javaLocation.y);
 596             userAction = (*env)->CallIntMethod(env, fDropTargetContextPeer, handleMotionMessageMethod, fComponent,
 597                          (jint) javaLocation.x, (jint) javaLocation.y, dropAction, actions, formats, ptr_to_jlong(self)); // AWT_THREADING Safe (CToolkitThreadBlockedHandler)
 598         CHECK_EXCEPTION();
 599         }
 600 
 601         if (sDraggingError == FALSE) {
 602             dragOp = [DnDUtilities mapJavaDragOperationToNS:userAction];
 603 
 604             // Remember the dragOp for no-op'd update messages:
 605             sUpdateOperation = dragOp;
 606         } else {
 607             dragOp = NSDragOperationNone;
 608         }
 609     }
 610 
 611     DLog2(@"[CDropTarget draggingUpdated]: returning %lu\n", (unsigned long) dragOp);
 612 
 613     return dragOp;
 614 }
 615 
 616 - (void)draggingExited:(id<NSDraggingInfo>)sender
 617 {
 618     DLog2(@"[CDropTarget draggingExited]: %@\n", self);
 619 
 620     sCurrentDropTarget = nil;
 621 
 622     JNIEnv* env = [ThreadUtilities getJNIEnv];
 623 
 624     if (sDraggingExited == FALSE && sDraggingError == FALSE) {
 625         GET_DTCP_CLASS();
 626         DECLARE_METHOD(handleExitMessageMethod, jc_CDropTargetContextPeer, "handleExitMessage", "(Ljava/awt/Component;J)V");
 627         if (sDraggingError == FALSE) {
 628             DLog3(@"  - dragExit: loc native %f, %f\n", sDraggingLocation.x, sDraggingLocation.y);
 629              // AWT_THREADING Safe (CToolkitThreadBlockedHandler)
 630             (*env)->CallVoidMethod(env, fDropTargetContextPeer,
 631                               handleExitMessageMethod, fComponent, ptr_to_jlong(self));
 632             CHECK_EXCEPTION();
 633         }
 634 
 635         // 5-27-03 Note: [Radar 3270455]
 636         // -draggingExited: can be called both by the AppKit and by -performDragOperation: but shouldn't execute
 637         // twice per drop since cleanup code like that in swing/plaf/basic/BasicDropTargetListener would throw NPEs.
 638         sDraggingExited = TRUE;
 639     }
 640 
 641     DLog(@"[CDropTarget draggingExited]: returning.\n");
 642 }
 643 
 644 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
 645 {
 646     DLog2(@"[CDropTarget prepareForDragOperation]: %@\n", self);
 647     DLog2(@"[CDropTarget prepareForDragOperation]: returning %@\n", (sDraggingError ? @"NO" : @"YES"));
 648 
 649     return sDraggingError ? NO : YES;
 650 }
 651 
 652 - (BOOL)performDragOperation:(id<NSDraggingInfo>)sender


 657 
 658     JNIEnv* env = [ThreadUtilities getJNIEnv];
 659 
 660     // Now copy dragging data:
 661     if (sDraggingError == FALSE && [self copyDraggingData:sender] == FALSE)
 662         sDraggingError = TRUE;
 663 
 664     if (sDraggingError == FALSE) {
 665         sDraggingLocation = [sender draggingLocation];
 666         NSPoint javaLocation = [fView convertPoint:sDraggingLocation fromView:nil];
 667         // The y coordinate that comes in the NSDraggingInfo seems to be reversed - probably
 668         // has to do something with the type of view it comes to.
 669         // This is the earliest place where we can correct it.
 670         javaLocation.y = fView.window.frame.size.height - javaLocation.y;
 671 
 672         jint actions = [DnDUtilities mapNSDragOperationMaskToJava:[sender draggingSourceOperationMask]];
 673         jint dropAction = sJavaDropOperation;
 674 
 675         jlongArray formats = sDraggingFormats;
 676 
 677         GET_DTCP_CLASS_RETURN(NO);
 678         DECLARE_METHOD_RETURN(handleDropMessageMethod, jc_CDropTargetContextPeer, "handleDropMessage", "(Ljava/awt/Component;IIII[JJ)V", NO);
 679 
 680         if (sDraggingError == FALSE) {
 681             (*env)->CallVoidMethod(env, fDropTargetContextPeer, handleDropMessageMethod, fComponent,
 682                      (jint) javaLocation.x, (jint) javaLocation.y, dropAction, actions, formats, ptr_to_jlong(self)); // AWT_THREADING Safe (event)
 683             CHECK_EXCEPTION();
 684         }
 685     } else {
 686         // 8-19-03 Note: [Radar 3368754]
 687         // draggingExited: is not called after a drop - we must do that here ... but only in case
 688         // of an error, instead of drop(). Otherwise we get twice the cleanup in shared code.
 689         [self draggingExited:sender];
 690     }
 691 
 692 // TODO:BG
 693 //   [(id)sender _setLastDragDestinationOperation:sDragOperation];
 694 
 695 
 696     DLog2(@"[CDropTarget performDragOperation]: returning %@\n", (sDraggingError ? @"NO" : @"YES"));
 697 
 698     return !sDraggingError;
 699 }
 700 
 701 - (void)concludeDragOperation:(id<NSDraggingInfo>)sender
 702 {
 703     sCurrentDropTarget = nil;


 713 
 714     DLog2(@"[CDropTarget draggingEnded]: %@\n", self);
 715     DLog(@"[CDropTarget draggingEnded]: returning.\n");
 716 }
 717 
 718 /********************************  END NSDraggingDestination Interface  ********************************/
 719 
 720 @end
 721 
 722 
 723 /*
 724  * Class:     sun_lwawt_macosx_CDropTarget
 725  * Method:    createNativeDropTarget
 726  * Signature: (Ljava/awt/dnd/DropTarget;Ljava/awt/Component;Ljava/awt/peer/ComponentPeer;J)J
 727  */
 728 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CDropTarget_createNativeDropTarget
 729   (JNIEnv *env, jobject jthis, jobject jdroptarget, jobject jcomponent, jlong jnativepeer)
 730 {
 731     CDropTarget* dropTarget = nil;
 732 
 733 JNI_COCOA_ENTER(env);
 734     id controlObj = (id) jlong_to_ptr(jnativepeer);
 735     dropTarget = [[CDropTarget alloc] init:jdroptarget component:jcomponent control:controlObj];
 736 JNI_COCOA_EXIT(env);
 737 
 738     return ptr_to_jlong(dropTarget);
 739 }
 740 
 741 /*
 742  * Class:     sun_lwawt_macosx_CDropTarget
 743  * Method:    releaseNativeDropTarget
 744  * Signature: (J)V
 745  */
 746 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CDropTarget_releaseNativeDropTarget
 747   (JNIEnv *env, jobject jthis, jlong nativeDropTargetVal)
 748 {
 749     id dropTarget = (id)jlong_to_ptr(nativeDropTargetVal);
 750 
 751 JNI_COCOA_ENTER(env);
 752     [dropTarget removeFromView:env];
 753 JNI_COCOA_EXIT(env);
 754 }
< prev index next >