1 /* 2 * Copyright (c) 2011, 2013, 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 //#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 peer:(jobject)jpeer 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) 103 // How to register for non-standard data types remains to be determined. 104 NSArray* dataTypes = [[NSArray alloc] initWithObjects: 105 NSStringPboardType, 106 NSFilenamesPboardType, 107 NSPostScriptPboardType, 108 NSTIFFPboardType, 109 NSRTFPboardType, 110 NSTabularTextPboardType, 111 NSFontPboardType, 112 NSRulerPboardType, 113 NSFileContentsPboardType, 114 NSColorPboardType, 115 NSRTFDPboardType, 116 NSHTMLPboardType, 117 NSURLPboardType, 118 NSPDFPboardType, 119 NSVCardPboardType, 120 NSFilesPromisePboardType, 121 [DnDUtilities javaPboardType], 122 nil]; 123 124 // Enable dragging events over this object: 125 [fView registerForDraggedTypes:dataTypes]; 126 127 [dataTypes release]; 128 } 129 130 - (void)releaseDraggingData 131 { 132 DLog2(@"[CDropTarget releaseDraggingData]: %@\n", self); 133 134 // Release any old pasteboard types, data and properties: 135 [sPasteboardTypes release]; 136 sPasteboardTypes = nil; 137 138 [sPasteboardData release]; 139 sPasteboardData = nil; 140 141 if (sDraggingFormats != NULL) { 142 JNIEnv *env = [ThreadUtilities getJNIEnv]; 143 JNFDeleteGlobalRef(env, sDraggingFormats); 144 sDraggingFormats = NULL; 145 } 146 147 sPasteboardItemsCount = 0; 148 sDraggingSequenceNumber = -1; 149 } 150 151 - (void)removeFromView:(JNIEnv *)env 152 { 153 DLog2(@"[CDropTarget removeFromView]: %@\n", self); 154 155 // Remove this dragging destination from the view: 156 [((AWTView *) fView) setDropTarget:nil]; 157 158 // Clean up JNI refs 159 if (fComponent != NULL) { 160 JNFDeleteGlobalRef(env, fComponent); 161 fComponent = NULL; 162 } 163 if (fDropTarget != NULL) { 164 JNFDeleteGlobalRef(env, fDropTarget); 165 fDropTarget = NULL; 166 } 167 if (fDropTargetContextPeer != NULL) { 168 JNFDeleteGlobalRef(env, fDropTargetContextPeer); 169 fDropTargetContextPeer = NULL; 170 } 171 172 CFRelease(self); 173 } 174 175 - (void)dealloc 176 { 177 DLog2(@"[CDropTarget dealloc]: %@\n", self); 178 179 if(sCurrentDropTarget == self) { 180 sCurrentDropTarget = nil; 181 } 182 183 [fView release]; 184 fView = nil; 185 186 [super dealloc]; 187 } 188 //- (void)finalize { [super finalize]; } 189 190 - (NSInteger) getDraggingSequenceNumber 191 { 192 return sDraggingSequenceNumber; 193 } 194 195 // Debugging help: 196 - (void)dumpPasteboard:(NSPasteboard*)pasteboard 197 { 198 NSArray* pasteboardTypes = [pasteboard types]; 199 NSUInteger pasteboardItemsCount = [pasteboardTypes count]; 200 NSUInteger i; 201 202 // For each flavor on the pasteboard show the type, its data, and its property if there is one: 203 for (i = 0; i < pasteboardItemsCount; i++) { 204 NSString* pbType = [pasteboardTypes objectAtIndex:i]; 205 CFShow(pbType); 206 207 NSData* pbData = [pasteboard dataForType:pbType]; 208 CFShow(pbData); 209 210 if ([pbType hasPrefix:@"CorePasteboardFlavorType"] == NO) { 211 id pbDataProperty = [pasteboard propertyListForType:pbType]; 212 CFShow(pbDataProperty); 213 } 214 } 215 } 216 217 - (BOOL)copyDraggingTypes:(id<NSDraggingInfo>)sender 218 { 219 DLog2(@"[CDropTarget copyDraggingTypes]: %@\n", self); 220 JNIEnv* env = [ThreadUtilities getJNIEnv]; 221 222 // Release any old pasteboard data: 223 [self releaseDraggingData]; 224 225 NSPasteboard* pb = [sender draggingPasteboard]; 226 sPasteboardTypes = [[pb types] retain]; 227 sPasteboardItemsCount = [sPasteboardTypes count]; 228 if (sPasteboardItemsCount == 0) 229 return FALSE; 230 231 jlongArray formats = (*env)->NewLongArray(env, sPasteboardItemsCount); 232 if (formats == nil) 233 return FALSE; 234 235 sDraggingFormats = (jlongArray) JNFNewGlobalRef(env, formats); 236 (*env)->DeleteLocalRef(env, formats); 237 if (sDraggingFormats == nil) 238 return FALSE; 239 240 jboolean isCopy; 241 jlong* jformats = (*env)->GetLongArrayElements(env, sDraggingFormats, &isCopy); 242 if (jformats == nil) { 243 return FALSE; 244 } 245 246 // Copy all data formats and properties. In case of properties, if they are nil, we need to use 247 // a special NilProperty since [NSArray addObject] would crash on adding a nil object. 248 DLog2(@"[CDropTarget copyDraggingTypes]: typesCount = %lu\n", (unsigned long) sPasteboardItemsCount); 249 NSUInteger i; 250 for (i = 0; i < sPasteboardItemsCount; i++) { 251 NSString* pbType = [sPasteboardTypes objectAtIndex:i]; 252 DLog3(@"[CDropTarget copyDraggingTypes]: type[%lu] = %@\n", (unsigned long) i, pbType); 253 254 // 01-10-03 Note: until we need data properties for doing something useful don't copy them. 255 // They're often copies of their flavor's data and copying them for all available pasteboard flavors 256 // (which are often auto-translation of one another) can be a significant time/space hit. 257 258 // If this is a remote object type (not a pre-defined format) register it with the pasteboard: 259 jformats[i] = indexForFormat(pbType); 260 if (jformats[i] == -1 && [pbType hasPrefix:@"JAVA_DATAFLAVOR:application/x-java-remote-object;"]) 261 jformats[i] = registerFormatWithPasteboard(pbType); 262 } 263 264 (*env)->ReleaseLongArrayElements(env, sDraggingFormats, jformats, JNI_COMMIT); 265 266 return TRUE; 267 } 268 269 - (BOOL)copyDraggingData:(id<NSDraggingInfo>)sender 270 { 271 DLog2(@"[CDropTarget copyDraggingData]: %@\n", self); 272 273 sPasteboardData = [[NSMutableArray alloc] init]; 274 if (sPasteboardData == nil) 275 return FALSE; 276 277 // Copy all data items to a safe place since the pasteboard may go away before we'll need them: 278 NSPasteboard* pb = [sender draggingPasteboard]; 279 NSUInteger i; 280 for (i = 0; i < sPasteboardItemsCount; i++) { 281 // Get a type and its data and save the data: 282 NSString* pbType = [sPasteboardTypes objectAtIndex:i]; 283 // 01-10-03 Note: copying only NS-type data (until Java-specified types can make it through the AppKit) 284 // would be a good idea since we can't do anything with those CoreFoundation unknown types anyway. 285 // But I'm worried that it would break something in Fuller so I'm leaving this here as a reminder, 286 // to be evaluated later. 287 //id pbData = [pbType hasPrefix:@"NS"] ? [pb dataForType:pbType] : nil; // Copy only NS-type data! 288 id pbData = [pb dataForType:pbType]; 289 290 // If the data is null we can't store it in the array - an exception would be thrown. 291 // We use the special object NSNull instead which is kosher. 292 if (pbData == nil) 293 pbData = [NSNull null]; 294 295 [((NSMutableArray*) sPasteboardData) addObject:pbData]; 296 } 297 298 return TRUE; 299 } 300 301 - (NSData*) getDraggingDataForURL:(NSData*)data 302 { 303 NSData* result = nil; 304 305 // Convert data into a property list if possible: 306 NSPropertyListFormat propertyListFormat; 307 NSString* errorString = nil; 308 id propertyList = [NSPropertyListSerialization propertyListFromData:data mutabilityOption:NSPropertyListImmutable 309 format:&propertyListFormat errorDescription:&errorString]; 310 311 // URL types have only a single URL string in an array: 312 if (propertyList != nil && errorString == nil && [propertyList isKindOfClass:[NSArray class]]) { 313 NSArray* array = (NSArray*) propertyList; 314 if ([array count] > 0) { 315 NSString* url = (NSString*) [array objectAtIndex:0]; 316 if (url != nil && [url length] > 0) 317 result = [url dataUsingEncoding:[url fastestEncoding]]; 318 } 319 } 320 321 return result; 322 } 323 324 - (jobject) copyDraggingDataForFormat:(jlong)format 325 { 326 JNIEnv* env = [ThreadUtilities getJNIEnvUncached]; // Join the main thread by requesting uncached environment 327 328 NSData* data = nil; 329 330 // Convert the Java format (datatransferer int index) to a pasteboard format (NSString): 331 NSString* pbType = formatForIndex(format); 332 if ([sPasteboardTypes containsObject:pbType]) { 333 NSUInteger dataIndex = [sPasteboardTypes indexOfObject:pbType]; 334 data = [sPasteboardData objectAtIndex:dataIndex]; 335 336 if ((id) data == [NSNull null]) 337 data = nil; 338 339 // format == 8 (CF_URL in CDataTransferer): we need a URL-to-String conversion: 340 else if ([pbType isEqualToString:@"Apple URL pasteboard type"]) 341 data = [self getDraggingDataForURL:data]; 342 } 343 344 // Get NS data: 345 char* dataBytes = (data != nil) ? (char*) [data bytes] : "Unsupported type"; 346 NSUInteger dataLength = (data != nil) ? [data length] : sizeof("Unsupported type"); 347 348 // Create a global byte array: 349 jbyteArray lbyteArray = (*env)->NewByteArray(env, dataLength); 350 if (lbyteArray == nil) 351 return nil; 352 jbyteArray gbyteArray = (jbyteArray) JNFNewGlobalRef(env, lbyteArray); 353 (*env)->DeleteLocalRef(env, lbyteArray); 354 if (gbyteArray == nil) 355 return nil; 356 357 // Get byte array elements: 358 jboolean isCopy; 359 jbyte* jbytes = (*env)->GetByteArrayElements(env, gbyteArray, &isCopy); 360 if (jbytes == nil) 361 return nil; 362 363 // Copy data to byte array and release elements: 364 memcpy(jbytes, dataBytes, dataLength); 365 (*env)->ReleaseByteArrayElements(env, gbyteArray, jbytes, JNI_COMMIT); 366 367 // In case of an error make sure to return nil: 368 if ((*env)->ExceptionOccurred(env)) { 369 (*env)->ExceptionDescribe(env); 370 gbyteArray = nil; 371 } 372 373 return gbyteArray; 374 } 375 376 - (void)safeReleaseDraggingData:(NSNumber *)arg 377 { 378 jlong draggingSequenceNumber = [arg longLongValue]; 379 380 // Make sure dragging data is released only if no new drag is under way. If a new drag 381 // has been initiated it has released the old dragging data already. This has to be called 382 // on the native event thread - otherwise we'd need to start synchronizing. 383 if (draggingSequenceNumber == sDraggingSequenceNumber) 384 [self releaseDraggingData]; 385 } 386 387 - (void)javaDraggingEnded:(jlong)draggingSequenceNumber success:(BOOL)jsuccess action:(jint)jdropaction 388 { 389 NSNumber *draggingSequenceNumberID = [NSNumber numberWithLongLong:draggingSequenceNumber]; 390 // Report back actual Swing success, not what AppKit thinks 391 sDraggingError = !jsuccess; 392 sDragOperation = [DnDUtilities mapJavaDragOperationToNS:jdropaction]; 393 394 // Release dragging data if any when Java's AWT event thread is all finished. 395 // Make sure dragging data is released on the native event thread. 396 [ThreadUtilities performOnMainThread:@selector(safeReleaseDraggingData:) on:self withObject:draggingSequenceNumberID waitUntilDone:NO]; 397 } 398 399 - (jint)currentJavaActions { 400 return [DnDUtilities mapNSDragOperationToJava:sUpdateOperation]; 401 } 402 403 /******************************** BEGIN NSDraggingDestination Interface ********************************/ 404 405 406 // Private API to calculate the current Java actions 407 - (void) calculateCurrentSourceActions:(jint *)actions dropAction:(jint *)dropAction 408 { 409 // Get the raw (unmodified by keys) source actions 410 id jrsDrag = objc_lookUpClass("JRSDrag"); 411 if (jrsDrag != nil) { 412 NSDragOperation rawDragActions = (NSDragOperation) [jrsDrag performSelector:@selector(currentAllowableActions)]; 413 if (rawDragActions != NSDragOperationNone) { 414 // Both actions and dropAction default to the rawActions 415 *actions = [DnDUtilities mapNSDragOperationMaskToJava:rawDragActions]; 416 *dropAction = *actions; 417 418 // Get the current key modifiers. 419 NSUInteger dragModifiers = (NSUInteger) [jrsDrag performSelector:@selector(currentModifiers)]; 420 // Either the drop action is narrowed as per Java rules (MOVE, COPY, LINK, NONE) or by the drag modifiers 421 if (dragModifiers) { 422 // Get the user selected operation based on the drag modifiers, then return the intersection 423 NSDragOperation currentOp = [DnDUtilities nsDragOperationForModifiers:dragModifiers]; 424 NSDragOperation allowedOp = rawDragActions & currentOp; 425 426 *dropAction = [DnDUtilities mapNSDragOperationToJava:allowedOp]; 427 } 428 } 429 } 430 *dropAction = [DnDUtilities narrowJavaDropActions:*dropAction]; 431 } 432 433 - (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender 434 { 435 DLog2(@"[CDropTarget draggingEntered]: %@\n", self); 436 437 sCurrentDropTarget = self; 438 439 JNIEnv* env = [ThreadUtilities getJNIEnv]; 440 NSInteger draggingSequenceNumber = [sender draggingSequenceNumber]; 441 442 // Set the initial drag operation return value: 443 NSDragOperation dragOp = NSDragOperationNone; 444 sJavaDropOperation = java_awt_dnd_DnDConstants_ACTION_NONE; 445 446 // We could probably special-case some stuff if drag and drop objects match: 447 //if ([sender dragSource] == fView) 448 449 if (draggingSequenceNumber != sDraggingSequenceNumber) { 450 sDraggingSequenceNumber = draggingSequenceNumber; 451 sDraggingError = FALSE; 452 453 // Delete any drop target context peer left over from a previous drag: 454 if (fDropTargetContextPeer != NULL) { 455 JNFDeleteGlobalRef(env, fDropTargetContextPeer); 456 fDropTargetContextPeer = NULL; 457 } 458 459 // Look up the CDropTargetContextPeer class: 460 JNF_STATIC_MEMBER_CACHE(getDropTargetContextPeerMethod, jc_CDropTargetContextPeer, "getDropTargetContextPeer", "()Lsun/lwawt/macosx/CDropTargetContextPeer;"); 461 if (sDraggingError == FALSE) { 462 // Create a new drop target context peer: 463 jobject dropTargetContextPeer = JNFCallStaticObjectMethod(env, getDropTargetContextPeerMethod); 464 465 if (dropTargetContextPeer != nil) { 466 fDropTargetContextPeer = JNFNewGlobalRef(env, dropTargetContextPeer); 467 (*env)->DeleteLocalRef(env, dropTargetContextPeer); 468 } 469 } 470 471 // Get dragging types (dragging data is only copied if dropped): 472 if (sDraggingError == FALSE && [self copyDraggingTypes:sender] == FALSE) 473 sDraggingError = TRUE; 474 } 475 476 if (sDraggingError == FALSE) { 477 sDraggingExited = FALSE; 478 sDraggingLocation = [sender draggingLocation]; 479 NSPoint javaLocation = [fView convertPoint:sDraggingLocation fromView:nil]; 480 javaLocation.y = fView.window.frame.size.height - javaLocation.y; 481 482 DLog5(@"+ dragEnter: loc native %f, %f, java %f, %f\n", sDraggingLocation.x, sDraggingLocation.y, javaLocation.x, javaLocation.y); 483 484 ////////// BEGIN Calculate the current drag actions ////////// 485 jint actions = java_awt_dnd_DnDConstants_ACTION_NONE; 486 jint dropAction = actions; 487 488 [self calculateCurrentSourceActions:&actions dropAction:&dropAction]; 489 490 sJavaDropOperation = dropAction; 491 ////////// END Calculate the current drag actions ////////// 492 493 jlongArray formats = sDraggingFormats; 494 495 JNF_MEMBER_CACHE(handleEnterMessageMethod, jc_CDropTargetContextPeer, "handleEnterMessage", "(Ljava/awt/Component;IIII[JJ)I"); 496 if (sDraggingError == FALSE) { 497 // Double-casting self gets rid of 'different size' compiler warning: 498 // AWT_THREADING Safe (CToolkitThreadBlockedHandler) 499 actions = JNFCallIntMethod(env, fDropTargetContextPeer, handleEnterMessageMethod, 500 fComponent, (jint) javaLocation.x, (jint) javaLocation.y, 501 dropAction, actions, formats, ptr_to_jlong(self)); 502 } 503 504 if (sDraggingError == FALSE) { 505 // Initialize drag operation: 506 sDragOperation = NSDragOperationNone; 507 508 // Map Java actions back to NSDragOperation. 509 // 1-6-03 Note: if the entry point of this CDropTarget isn't covered by a droppable component 510 // (as can be the case with lightweight children) we must not return NSDragOperationNone 511 // since that would prevent dropping into any of the contained drop targets. 512 // Unfortunately there is no easy way to test this so we just test actions and override them 513 // with GENERIC if necessary. Proper drag operations will be returned by draggingUpdated: which is 514 // called right away, taking care of setting the right cursor and snap-back action. 515 dragOp = ((actions != java_awt_dnd_DnDConstants_ACTION_NONE) ? 516 [DnDUtilities mapJavaDragOperationToNS:dropAction] : NSDragOperationGeneric); 517 518 // Remember the dragOp for no-op'd update messages: 519 sUpdateOperation = dragOp; 520 } 521 } 522 523 // 9-11-02 Note: the native event thread would not handle an exception gracefully: 524 //if (sDraggingError == TRUE) 525 // [NSException raise:NSGenericException format:@"[CDropTarget draggingEntered] failed."]; 526 527 DLog2(@"[CDropTarget draggingEntered]: returning %lu\n", (unsigned long) dragOp); 528 529 return dragOp; 530 } 531 532 - (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender 533 { 534 //DLog2(@"[CDropTarget draggingUpdated]: %@\n", self); 535 536 sCurrentDropTarget = self; 537 538 // Set the initial drag operation return value: 539 NSDragOperation dragOp = (sDraggingError == FALSE ? sUpdateOperation : NSDragOperationNone); 540 541 // There are two things we would be interested in: 542 // a) mouse pointer has moved 543 // b) drag actions (key modifiers) have changed 544 545 NSPoint draggingLocation = [sender draggingLocation]; 546 JNIEnv* env = [ThreadUtilities getJNIEnv]; 547 548 BOOL notifyJava = FALSE; 549 550 // a) mouse pointer has moved: 551 if (NSEqualPoints(draggingLocation, sDraggingLocation) == FALSE) { 552 //DLog2(@"[CDropTarget draggingUpdated]: mouse moved, %@\n", self); 553 sDraggingLocation = draggingLocation; 554 notifyJava = TRUE; 555 } 556 557 // b) drag actions (key modifiers) have changed (handleMotionMessage() will do proper notifications): 558 ////////// BEGIN Calculate the current drag actions ////////// 559 jint actions = java_awt_dnd_DnDConstants_ACTION_NONE; 560 jint dropAction = actions; 561 562 [self calculateCurrentSourceActions:&actions dropAction:&dropAction]; 563 564 if (sJavaDropOperation != dropAction) { 565 sJavaDropOperation = dropAction; 566 notifyJava = TRUE; 567 } 568 ////////// END Calculate the current drag actions ////////// 569 570 jint userAction = dropAction; 571 572 // Should we notify Java things have changed? 573 if (sDraggingError == FALSE && notifyJava) { 574 NSPoint javaLocation = [fView convertPoint:sDraggingLocation fromView:nil]; 575 javaLocation.y = fView.window.frame.size.height - javaLocation.y; 576 //DLog5(@" : dragMoved: loc native %f, %f, java %f, %f\n", sDraggingLocation.x, sDraggingLocation.y, javaLocation.x, javaLocation.y); 577 578 jlongArray formats = sDraggingFormats; 579 580 JNF_MEMBER_CACHE(handleMotionMessageMethod, jc_CDropTargetContextPeer, "handleMotionMessage", "(Ljava/awt/Component;IIII[JJ)I"); 581 if (sDraggingError == FALSE) { 582 DLog3(@" >> posting handleMotionMessage, point %f, %f", javaLocation.x, javaLocation.y); 583 userAction = JNFCallIntMethod(env, fDropTargetContextPeer, handleMotionMessageMethod, fComponent, (jint) javaLocation.x, (jint) javaLocation.y, dropAction, actions, formats, ptr_to_jlong(self)); // AWT_THREADING Safe (CToolkitThreadBlockedHandler) 584 } 585 586 if (sDraggingError == FALSE) { 587 dragOp = [DnDUtilities mapJavaDragOperationToNS:userAction]; 588 589 // Remember the dragOp for no-op'd update messages: 590 sUpdateOperation = dragOp; 591 } else { 592 dragOp = NSDragOperationNone; 593 } 594 } 595 596 DLog2(@"[CDropTarget draggingUpdated]: returning %lu\n", (unsigned long) dragOp); 597 598 return dragOp; 599 } 600 601 - (void)draggingExited:(id<NSDraggingInfo>)sender 602 { 603 DLog2(@"[CDropTarget draggingExited]: %@\n", self); 604 605 sCurrentDropTarget = nil; 606 607 JNIEnv* env = [ThreadUtilities getJNIEnv]; 608 609 if (sDraggingExited == FALSE && sDraggingError == FALSE) { 610 JNF_MEMBER_CACHE(handleExitMessageMethod, jc_CDropTargetContextPeer, "handleExitMessage", "(Ljava/awt/Component;J)V"); 611 if (sDraggingError == FALSE) { 612 DLog3(@" - dragExit: loc native %f, %f\n", sDraggingLocation.x, sDraggingLocation.y); 613 // AWT_THREADING Safe (CToolkitThreadBlockedHandler) 614 JNFCallVoidMethod(env, fDropTargetContextPeer, 615 handleExitMessageMethod, fComponent, ptr_to_jlong(self)); 616 } 617 618 // 5-27-03 Note: [Radar 3270455] 619 // -draggingExited: can be called both by the AppKit and by -performDragOperation: but shouldn't execute 620 // twice per drop since cleanup code like that in swing/plaf/basic/BasicDropTargetListener would throw NPEs. 621 sDraggingExited = TRUE; 622 } 623 624 DLog(@"[CDropTarget draggingExited]: returning.\n"); 625 } 626 627 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender 628 { 629 DLog2(@"[CDropTarget prepareForDragOperation]: %@\n", self); 630 DLog2(@"[CDropTarget prepareForDragOperation]: returning %@\n", (sDraggingError ? @"NO" : @"YES")); 631 632 return sDraggingError ? NO : YES; 633 } 634 635 - (BOOL)performDragOperation:(id<NSDraggingInfo>)sender 636 { 637 DLog2(@"[CDropTarget performDragOperation]: %@\n", self); 638 639 sCurrentDropTarget = nil; 640 641 JNIEnv* env = [ThreadUtilities getJNIEnv]; 642 643 // Now copy dragging data: 644 if (sDraggingError == FALSE && [self copyDraggingData:sender] == FALSE) 645 sDraggingError = TRUE; 646 647 if (sDraggingError == FALSE) { 648 sDraggingLocation = [sender draggingLocation]; 649 NSPoint javaLocation = [fView convertPoint:sDraggingLocation fromView:nil]; 650 // The y coordinate that comes in the NSDraggingInfo seems to be reversed - probably 651 // has to do something with the type of view it comes to. 652 // This is the earliest place where we can correct it. 653 javaLocation.y = fView.window.frame.size.height - javaLocation.y; 654 655 jint actions = [DnDUtilities mapNSDragOperationMaskToJava:[sender draggingSourceOperationMask]]; 656 jint dropAction = sJavaDropOperation; 657 658 jlongArray formats = sDraggingFormats; 659 660 JNF_MEMBER_CACHE(handleDropMessageMethod, jc_CDropTargetContextPeer, "handleDropMessage", "(Ljava/awt/Component;IIII[JJ)V"); 661 662 if (sDraggingError == FALSE) { 663 JNFCallVoidMethod(env, fDropTargetContextPeer, handleDropMessageMethod, fComponent, (jint) javaLocation.x, (jint) javaLocation.y, dropAction, actions, formats, ptr_to_jlong(self)); // AWT_THREADING Safe (event) 664 } 665 666 if (sDraggingError == FALSE) { 667 JNF_MEMBER_CACHE(flushEventsMethod, jc_CDropTargetContextPeer, "flushEvents", "(Ljava/awt/Component;)V"); 668 if (sDraggingError == FALSE) { 669 JNFCallVoidMethod(env, fDropTargetContextPeer, flushEventsMethod, fComponent); // AWT_THREADING Safe (AWTRunLoopMode) 670 } 671 } 672 } else { 673 // 8-19-03 Note: [Radar 3368754] 674 // draggingExited: is not called after a drop - we must do that here ... but only in case 675 // of an error, instead of drop(). Otherwise we get twice the cleanup in shared code. 676 [self draggingExited:sender]; 677 } 678 679 // TODO:BG 680 // [(id)sender _setLastDragDestinationOperation:sDragOperation]; 681 682 683 DLog2(@"[CDropTarget performDragOperation]: returning %@\n", (sDraggingError ? @"NO" : @"YES")); 684 685 return !sDraggingError; 686 } 687 688 - (void)concludeDragOperation:(id<NSDraggingInfo>)sender 689 { 690 sCurrentDropTarget = nil; 691 692 DLog2(@"[CDropTarget concludeDragOperation]: %@\n", self); 693 DLog(@"[CDropTarget concludeDragOperation]: returning.\n"); 694 } 695 696 // 9-11-02 Note: draggingEnded is not yet implemented by the AppKit. 697 - (void)draggingEnded:(id<NSDraggingInfo>)sender 698 { 699 sCurrentDropTarget = nil; 700 701 DLog2(@"[CDropTarget draggingEnded]: %@\n", self); 702 DLog(@"[CDropTarget draggingEnded]: returning.\n"); 703 } 704 705 /******************************** END NSDraggingDestination Interface ********************************/ 706 707 @end 708 709 710 /* 711 * Class: sun_lwawt_macosx_CDropTarget 712 * Method: createNativeDropTarget 713 * Signature: (Ljava/awt/dnd/DropTarget;Ljava/awt/Component;Ljava/awt/peer/ComponentPeer;J)J 714 */ 715 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CDropTarget_createNativeDropTarget 716 (JNIEnv *env, jobject jthis, jobject jdroptarget, jobject jcomponent, jobject jpeer, jlong jnativepeer) 717 { 718 CDropTarget* dropTarget = nil; 719 720 JNF_COCOA_ENTER(env); 721 id controlObj = (id) jlong_to_ptr(jnativepeer); 722 dropTarget = [[CDropTarget alloc] init:jdroptarget component:jcomponent peer:jpeer control:controlObj]; 723 JNF_COCOA_EXIT(env); 724 725 if (dropTarget) { 726 CFRetain(dropTarget); // GC 727 [dropTarget release]; 728 } 729 return ptr_to_jlong(dropTarget); 730 } 731 732 /* 733 * Class: sun_lwawt_macosx_CDropTarget 734 * Method: releaseNativeDropTarget 735 * Signature: (J)V 736 */ 737 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CDropTarget_releaseNativeDropTarget 738 (JNIEnv *env, jobject jthis, jlong nativeDropTargetVal) 739 { 740 id dropTarget = (id)jlong_to_ptr(nativeDropTargetVal); 741 742 JNF_COCOA_ENTER(env); 743 [dropTarget removeFromView:env]; 744 JNF_COCOA_EXIT(env); 745 }