Path: blob/master/src/java.desktop/macosx/native/libawt_lwawt/awt/CDropTarget.m
41152 views
/*1* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425//#define DND_DEBUG TRUE2627#import "CDropTarget.h"28#import "AWTView.h"2930#import "sun_lwawt_macosx_CDropTarget.h"31#import "java_awt_dnd_DnDConstants.h"3233#import <JavaRuntimeSupport/JavaRuntimeSupport.h>34#include <objc/objc-runtime.h>353637#import "CDragSource.h"38#import "CDataTransferer.h"39#import "DnDUtilities.h"40#import "ThreadUtilities.h"41#import "JNIUtilities.h"424344static NSInteger sDraggingSequenceNumber = -1;45static NSDragOperation sDragOperation;46static NSDragOperation sUpdateOperation;47static jint sJavaDropOperation;48static NSPoint sDraggingLocation;49static BOOL sDraggingExited;50static BOOL sDraggingError;5152static NSUInteger sPasteboardItemsCount = 0;53static NSArray* sPasteboardTypes = nil;54static NSArray* sPasteboardData = nil;55static jlongArray sDraggingFormats = nil;5657static CDropTarget* sCurrentDropTarget;5859extern jclass jc_CDropTargetContextPeer;60#define GET_DTCP_CLASS() \61GET_CLASS(jc_CDropTargetContextPeer, "sun/lwawt/macosx/CDropTargetContextPeer");6263#define GET_DTCP_CLASS_RETURN(ret) \64GET_CLASS_RETURN(jc_CDropTargetContextPeer, "sun/lwawt/macosx/CDropTargetContextPeer", ret);6566@implementation CDropTarget6768+ (CDropTarget *) currentDropTarget {69return sCurrentDropTarget;70}7172- (id)init:(jobject)jdropTarget component:(jobject)jcomponent control:(id)control73{74self = [super init];75DLog2(@"[CDropTarget init]: %@\n", self);7677fView = nil;78fComponent = nil;79fDropTarget = nil;80fDropTargetContextPeer = nil;818283if (control != nil) {84JNIEnv *env = [ThreadUtilities getJNIEnvUncached];85fComponent = (*env)->NewGlobalRef(env, jcomponent);86fDropTarget = (*env)->NewGlobalRef(env, jdropTarget);8788fView = [((AWTView *) control) retain];89[fView setDropTarget:self];909192} else {93// This would be an error.94[self release];95self = nil;96}97return self;98}99100// When [CDropTarget init] is called the ControlModel's fView may not have been set up yet. ControlModel101// (soon after) calls [CDropTarget controlModelControlValid] on the native event thread, once per CDropTarget,102// to let it know it's been set up now.103- (void)controlModelControlValid104{105// 9-30-02 Note: [Radar 3065621]106// List all known pasteboard types here (see AppKit's NSPasteboard.h)107// How to register for non-standard data types remains to be determined.108NSArray* dataTypes = [[NSArray alloc] initWithObjects:109NSStringPboardType,110NSFilenamesPboardType,111NSPostScriptPboardType,112NSTIFFPboardType,113NSPasteboardTypePNG,114NSRTFPboardType,115NSTabularTextPboardType,116NSFontPboardType,117NSRulerPboardType,118NSFileContentsPboardType,119NSColorPboardType,120NSRTFDPboardType,121NSHTMLPboardType,122NSURLPboardType,123NSPDFPboardType,124NSVCardPboardType,125NSFilesPromisePboardType,126[DnDUtilities javaPboardType],127(NSString*)kUTTypeJPEG,128nil];129130// Enable dragging events over this object:131[fView registerForDraggedTypes:dataTypes];132133[dataTypes release];134}135136- (void)releaseDraggingData137{138DLog2(@"[CDropTarget releaseDraggingData]: %@\n", self);139140// Release any old pasteboard types, data and properties:141[sPasteboardTypes release];142sPasteboardTypes = nil;143144[sPasteboardData release];145sPasteboardData = nil;146147if (sDraggingFormats != NULL) {148JNIEnv *env = [ThreadUtilities getJNIEnv];149(*env)->DeleteGlobalRef(env, sDraggingFormats);150sDraggingFormats = NULL;151}152153sPasteboardItemsCount = 0;154sDraggingSequenceNumber = -1;155}156157- (void)removeFromView:(JNIEnv *)env158{159DLog2(@"[CDropTarget removeFromView]: %@\n", self);160161// Remove this dragging destination from the view:162[((AWTView *) fView) setDropTarget:nil];163164// Clean up JNI refs165if (fComponent != NULL) {166(*env)->DeleteGlobalRef(env, fComponent);167fComponent = NULL;168}169if (fDropTarget != NULL) {170(*env)->DeleteGlobalRef(env, fDropTarget);171fDropTarget = NULL;172}173if (fDropTargetContextPeer != NULL) {174(*env)->DeleteGlobalRef(env, fDropTargetContextPeer);175fDropTargetContextPeer = NULL;176}177178[self release];179}180181- (void)dealloc182{183DLog2(@"[CDropTarget dealloc]: %@\n", self);184185if(sCurrentDropTarget == self) {186sCurrentDropTarget = nil;187}188189[fView release];190fView = nil;191192[super dealloc];193}194195- (NSInteger) getDraggingSequenceNumber196{197return sDraggingSequenceNumber;198}199200// Debugging help:201- (void)dumpPasteboard:(NSPasteboard*)pasteboard202{203NSArray* pasteboardTypes = [pasteboard types];204NSUInteger pasteboardItemsCount = [pasteboardTypes count];205NSUInteger i;206207// For each flavor on the pasteboard show the type, its data, and its property if there is one:208for (i = 0; i < pasteboardItemsCount; i++) {209NSString* pbType = [pasteboardTypes objectAtIndex:i];210CFShow(pbType);211212NSData* pbData = [pasteboard dataForType:pbType];213CFShow(pbData);214215if ([pbType hasPrefix:@"CorePasteboardFlavorType"] == NO) {216id pbDataProperty = [pasteboard propertyListForType:pbType];217CFShow(pbDataProperty);218}219}220}221222- (BOOL)copyDraggingTypes:(id<NSDraggingInfo>)sender223{224DLog2(@"[CDropTarget copyDraggingTypes]: %@\n", self);225JNIEnv* env = [ThreadUtilities getJNIEnv];226227// Release any old pasteboard data:228[self releaseDraggingData];229230NSPasteboard* pb = [sender draggingPasteboard];231sPasteboardTypes = [[pb types] retain];232sPasteboardItemsCount = [sPasteboardTypes count];233if (sPasteboardItemsCount == 0)234return FALSE;235236jlongArray formats = (*env)->NewLongArray(env, sPasteboardItemsCount);237if (formats == nil)238return FALSE;239240sDraggingFormats = (jlongArray) (*env)->NewGlobalRef(env, formats);241(*env)->DeleteLocalRef(env, formats);242if (sDraggingFormats == nil)243return FALSE;244245jboolean isCopy;246jlong* jformats = (*env)->GetLongArrayElements(env, sDraggingFormats, &isCopy);247if (jformats == nil) {248return FALSE;249}250251// Copy all data formats and properties. In case of properties, if they are nil, we need to use252// a special NilProperty since [NSArray addObject] would crash on adding a nil object.253DLog2(@"[CDropTarget copyDraggingTypes]: typesCount = %lu\n", (unsigned long) sPasteboardItemsCount);254NSUInteger i;255for (i = 0; i < sPasteboardItemsCount; i++) {256NSString* pbType = [sPasteboardTypes objectAtIndex:i];257DLog3(@"[CDropTarget copyDraggingTypes]: type[%lu] = %@\n", (unsigned long) i, pbType);258259// 01-10-03 Note: until we need data properties for doing something useful don't copy them.260// They're often copies of their flavor's data and copying them for all available pasteboard flavors261// (which are often auto-translation of one another) can be a significant time/space hit.262263// If this is a remote object type (not a pre-defined format) register it with the pasteboard:264jformats[i] = indexForFormat(pbType);265if (jformats[i] == -1 && [pbType hasPrefix:@"JAVA_DATAFLAVOR:application/x-java-remote-object;"])266jformats[i] = registerFormatWithPasteboard(pbType);267}268269(*env)->ReleaseLongArrayElements(env, sDraggingFormats, jformats, JNI_COMMIT);270271return TRUE;272}273274- (BOOL)copyDraggingData:(id<NSDraggingInfo>)sender275{276DLog2(@"[CDropTarget copyDraggingData]: %@\n", self);277278sPasteboardData = [[NSMutableArray alloc] init];279if (sPasteboardData == nil)280return FALSE;281282// Copy all data items to a safe place since the pasteboard may go away before we'll need them:283NSPasteboard* pb = [sender draggingPasteboard];284NSUInteger i;285for (i = 0; i < sPasteboardItemsCount; i++) {286// Get a type and its data and save the data:287NSString* pbType = [sPasteboardTypes objectAtIndex:i];288// 01-10-03 Note: copying only NS-type data (until Java-specified types can make it through the AppKit)289// would be a good idea since we can't do anything with those CoreFoundation unknown types anyway.290// But I'm worried that it would break something in Fuller so I'm leaving this here as a reminder,291// to be evaluated later.292//id pbData = [pbType hasPrefix:@"NS"] ? [pb dataForType:pbType] : nil; // Copy only NS-type data!293id pbData = [pb dataForType:pbType];294295// If the data is null we can't store it in the array - an exception would be thrown.296// We use the special object NSNull instead which is kosher.297if (pbData == nil)298pbData = [NSNull null];299300[((NSMutableArray*) sPasteboardData) addObject:pbData];301}302303return TRUE;304}305306- (NSData*) getDraggingDataForURL:(NSData*)data307{308NSData* result = nil;309310// Convert data into a property list if possible:311NSPropertyListFormat propertyListFormat;312NSString* errorString = nil;313id propertyList = [NSPropertyListSerialization propertyListFromData:data mutabilityOption:NSPropertyListImmutable314format:&propertyListFormat errorDescription:&errorString];315316// URL types have only a single URL string in an array:317if (propertyList != nil && errorString == nil && [propertyList isKindOfClass:[NSArray class]]) {318NSArray* array = (NSArray*) propertyList;319if ([array count] > 0) {320NSString* url = (NSString*) [array objectAtIndex:0];321if (url != nil && [url length] > 0)322result = [url dataUsingEncoding:[url fastestEncoding]];323}324}325326return result;327}328329- (jobject) copyDraggingDataForFormat:(jlong)format330{331JNIEnv* env = [ThreadUtilities getJNIEnvUncached]; // Join the main thread by requesting uncached environment332333NSData* data = nil;334335// Convert the Java format (datatransferer int index) to a pasteboard format (NSString):336NSString* pbType = formatForIndex(format);337if ([sPasteboardTypes containsObject:pbType]) {338NSUInteger dataIndex = [sPasteboardTypes indexOfObject:pbType];339data = [sPasteboardData objectAtIndex:dataIndex];340341if ((id) data == [NSNull null])342data = nil;343344// format == 8 (CF_URL in CDataTransferer): we need a URL-to-String conversion:345else if ([pbType isEqualToString:@"Apple URL pasteboard type"])346data = [self getDraggingDataForURL:data];347}348349// Get NS data:350char* dataBytes = (data != nil) ? (char*) [data bytes] : "Unsupported type";351NSUInteger dataLength = (data != nil) ? [data length] : sizeof("Unsupported type");352353// Create a global byte array:354jbyteArray lbyteArray = (*env)->NewByteArray(env, dataLength);355if (lbyteArray == nil)356return nil;357jbyteArray gbyteArray = (jbyteArray) (*env)->NewGlobalRef(env, lbyteArray);358(*env)->DeleteLocalRef(env, lbyteArray);359if (gbyteArray == nil)360return nil;361362// Get byte array elements:363jboolean isCopy;364jbyte* jbytes = (*env)->GetByteArrayElements(env, gbyteArray, &isCopy);365if (jbytes == nil)366return nil;367368// Copy data to byte array and release elements:369memcpy(jbytes, dataBytes, dataLength);370(*env)->ReleaseByteArrayElements(env, gbyteArray, jbytes, JNI_COMMIT);371372// In case of an error make sure to return nil:373if ((*env)->ExceptionOccurred(env)) {374(*env)->ExceptionDescribe(env);375gbyteArray = nil;376}377378return gbyteArray;379}380381- (void)safeReleaseDraggingData:(NSNumber *)arg382{383jlong draggingSequenceNumber = [arg longLongValue];384385// Make sure dragging data is released only if no new drag is under way. If a new drag386// has been initiated it has released the old dragging data already. This has to be called387// on the native event thread - otherwise we'd need to start synchronizing.388if (draggingSequenceNumber == sDraggingSequenceNumber)389[self releaseDraggingData];390}391392- (void)javaDraggingEnded:(jlong)draggingSequenceNumber success:(BOOL)jsuccess action:(jint)jdropaction393{394NSNumber *draggingSequenceNumberID = [NSNumber numberWithLongLong:draggingSequenceNumber];395// Report back actual Swing success, not what AppKit thinks396sDraggingError = !jsuccess;397sDragOperation = [DnDUtilities mapJavaDragOperationToNS:jdropaction];398399// Release dragging data if any when Java's AWT event thread is all finished.400// Make sure dragging data is released on the native event thread.401[ThreadUtilities performOnMainThread:@selector(safeReleaseDraggingData:) on:self withObject:draggingSequenceNumberID waitUntilDone:NO];402}403404- (jint)currentJavaActions {405return [DnDUtilities mapNSDragOperationToJava:sUpdateOperation];406}407408/******************************** BEGIN NSDraggingDestination Interface ********************************/409410411// Private API to calculate the current Java actions412- (void) calculateCurrentSourceActions:(jint *)actions dropAction:(jint *)dropAction413{414// Get the raw (unmodified by keys) source actions415id jrsDrag = objc_lookUpClass("JRSDrag");416if (jrsDrag != nil) {417NSDragOperation rawDragActions = (NSDragOperation) [jrsDrag performSelector:@selector(currentAllowableActions)];418if (rawDragActions != NSDragOperationNone) {419// Both actions and dropAction default to the rawActions420*actions = [DnDUtilities mapNSDragOperationMaskToJava:rawDragActions];421*dropAction = *actions;422423// Get the current key modifiers.424NSUInteger dragModifiers = (NSUInteger) [jrsDrag performSelector:@selector(currentModifiers)];425// Either the drop action is narrowed as per Java rules (MOVE, COPY, LINK, NONE) or by the drag modifiers426if (dragModifiers) {427// Get the user selected operation based on the drag modifiers, then return the intersection428NSDragOperation currentOp = [DnDUtilities nsDragOperationForModifiers:dragModifiers];429NSDragOperation allowedOp = rawDragActions & currentOp;430431*dropAction = [DnDUtilities mapNSDragOperationToJava:allowedOp];432}433}434}435*dropAction = [DnDUtilities narrowJavaDropActions:*dropAction];436}437438- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender439{440DLog2(@"[CDropTarget draggingEntered]: %@\n", self);441442sCurrentDropTarget = self;443444JNIEnv* env = [ThreadUtilities getJNIEnv];445NSInteger draggingSequenceNumber = [sender draggingSequenceNumber];446447// Set the initial drag operation return value:448NSDragOperation dragOp = NSDragOperationNone;449sJavaDropOperation = java_awt_dnd_DnDConstants_ACTION_NONE;450451// We could probably special-case some stuff if drag and drop objects match:452//if ([sender dragSource] == fView)453454if (draggingSequenceNumber != sDraggingSequenceNumber) {455sDraggingSequenceNumber = draggingSequenceNumber;456sDraggingError = FALSE;457458// Delete any drop target context peer left over from a previous drag:459if (fDropTargetContextPeer != NULL) {460(*env)->DeleteGlobalRef(env, fDropTargetContextPeer);461fDropTargetContextPeer = NULL;462}463464// Look up the CDropTargetContextPeer class:465GET_DTCP_CLASS_RETURN(dragOp);466DECLARE_STATIC_METHOD_RETURN(getDropTargetContextPeerMethod, jc_CDropTargetContextPeer,467"getDropTargetContextPeer", "()Lsun/lwawt/macosx/CDropTargetContextPeer;", dragOp)468if (sDraggingError == FALSE) {469// Create a new drop target context peer:470jobject dropTargetContextPeer = (*env)->CallStaticObjectMethod(env, jc_CDropTargetContextPeer, getDropTargetContextPeerMethod);471CHECK_EXCEPTION();472473if (dropTargetContextPeer != nil) {474fDropTargetContextPeer = (*env)->NewGlobalRef(env, dropTargetContextPeer);475(*env)->DeleteLocalRef(env, dropTargetContextPeer);476}477}478479// Get dragging types (dragging data is only copied if dropped):480if (sDraggingError == FALSE && [self copyDraggingTypes:sender] == FALSE)481sDraggingError = TRUE;482}483484if (sDraggingError == FALSE) {485sDraggingExited = FALSE;486sDraggingLocation = [sender draggingLocation];487NSPoint javaLocation = [fView convertPoint:sDraggingLocation fromView:nil];488javaLocation.y = fView.window.frame.size.height - javaLocation.y;489490DLog5(@"+ dragEnter: loc native %f, %f, java %f, %f\n", sDraggingLocation.x, sDraggingLocation.y, javaLocation.x, javaLocation.y);491492////////// BEGIN Calculate the current drag actions //////////493jint actions = java_awt_dnd_DnDConstants_ACTION_NONE;494jint dropAction = actions;495496[self calculateCurrentSourceActions:&actions dropAction:&dropAction];497498sJavaDropOperation = dropAction;499////////// END Calculate the current drag actions //////////500501jlongArray formats = sDraggingFormats;502503GET_DTCP_CLASS_RETURN(dragOp);504DECLARE_METHOD_RETURN(handleEnterMessageMethod, jc_CDropTargetContextPeer,505"handleEnterMessage", "(Ljava/awt/Component;IIII[JJ)I", dragOp);506if (sDraggingError == FALSE) {507// Double-casting self gets rid of 'different size' compiler warning:508// AWT_THREADING Safe (CToolkitThreadBlockedHandler)509actions = (*env)->CallIntMethod(env, fDropTargetContextPeer, handleEnterMessageMethod,510fComponent, (jint) javaLocation.x, (jint) javaLocation.y,511dropAction, actions, formats, ptr_to_jlong(self));512CHECK_EXCEPTION();513}514515if (sDraggingError == FALSE) {516// Initialize drag operation:517sDragOperation = NSDragOperationNone;518519// Map Java actions back to NSDragOperation.520// 1-6-03 Note: if the entry point of this CDropTarget isn't covered by a droppable component521// (as can be the case with lightweight children) we must not return NSDragOperationNone522// since that would prevent dropping into any of the contained drop targets.523// Unfortunately there is no easy way to test this so we just test actions and override them524// with GENERIC if necessary. Proper drag operations will be returned by draggingUpdated: which is525// called right away, taking care of setting the right cursor and snap-back action.526dragOp = ((actions != java_awt_dnd_DnDConstants_ACTION_NONE) ?527[DnDUtilities mapJavaDragOperationToNS:dropAction] : NSDragOperationGeneric);528529// Remember the dragOp for no-op'd update messages:530sUpdateOperation = dragOp;531}532}533534// 9-11-02 Note: the native event thread would not handle an exception gracefully:535//if (sDraggingError == TRUE)536// [NSException raise:NSGenericException format:@"[CDropTarget draggingEntered] failed."];537538DLog2(@"[CDropTarget draggingEntered]: returning %lu\n", (unsigned long) dragOp);539540return dragOp;541}542543- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender544{545//DLog2(@"[CDropTarget draggingUpdated]: %@\n", self);546547sCurrentDropTarget = self;548549// Set the initial drag operation return value:550NSDragOperation dragOp = (sDraggingError == FALSE ? sUpdateOperation : NSDragOperationNone);551552// There are two things we would be interested in:553// a) mouse pointer has moved554// b) drag actions (key modifiers) have changed555556NSPoint draggingLocation = [sender draggingLocation];557JNIEnv* env = [ThreadUtilities getJNIEnv];558559BOOL notifyJava = FALSE;560561// a) mouse pointer has moved:562if (NSEqualPoints(draggingLocation, sDraggingLocation) == FALSE) {563//DLog2(@"[CDropTarget draggingUpdated]: mouse moved, %@\n", self);564sDraggingLocation = draggingLocation;565notifyJava = TRUE;566}567568// b) drag actions (key modifiers) have changed (handleMotionMessage() will do proper notifications):569////////// BEGIN Calculate the current drag actions //////////570jint actions = java_awt_dnd_DnDConstants_ACTION_NONE;571jint dropAction = actions;572573[self calculateCurrentSourceActions:&actions dropAction:&dropAction];574575if (sJavaDropOperation != dropAction) {576sJavaDropOperation = dropAction;577notifyJava = TRUE;578}579////////// END Calculate the current drag actions //////////580581jint userAction = dropAction;582583// Should we notify Java things have changed?584if (sDraggingError == FALSE && notifyJava) {585NSPoint javaLocation = [fView convertPoint:sDraggingLocation fromView:nil];586javaLocation.y = fView.window.frame.size.height - javaLocation.y;587//DLog5(@" : dragMoved: loc native %f, %f, java %f, %f\n", sDraggingLocation.x, sDraggingLocation.y, javaLocation.x, javaLocation.y);588589jlongArray formats = sDraggingFormats;590591GET_DTCP_CLASS_RETURN(dragOp);592DECLARE_METHOD_RETURN(handleMotionMessageMethod, jc_CDropTargetContextPeer, "handleMotionMessage", "(Ljava/awt/Component;IIII[JJ)I", dragOp);593if (sDraggingError == FALSE) {594DLog3(@" >> posting handleMotionMessage, point %f, %f", javaLocation.x, javaLocation.y);595userAction = (*env)->CallIntMethod(env, fDropTargetContextPeer, handleMotionMessageMethod, fComponent,596(jint) javaLocation.x, (jint) javaLocation.y, dropAction, actions, formats, ptr_to_jlong(self)); // AWT_THREADING Safe (CToolkitThreadBlockedHandler)597CHECK_EXCEPTION();598}599600if (sDraggingError == FALSE) {601dragOp = [DnDUtilities mapJavaDragOperationToNS:userAction];602603// Remember the dragOp for no-op'd update messages:604sUpdateOperation = dragOp;605} else {606dragOp = NSDragOperationNone;607}608}609610DLog2(@"[CDropTarget draggingUpdated]: returning %lu\n", (unsigned long) dragOp);611612return dragOp;613}614615- (void)draggingExited:(id<NSDraggingInfo>)sender616{617DLog2(@"[CDropTarget draggingExited]: %@\n", self);618619sCurrentDropTarget = nil;620621JNIEnv* env = [ThreadUtilities getJNIEnv];622623if (sDraggingExited == FALSE && sDraggingError == FALSE) {624GET_DTCP_CLASS();625DECLARE_METHOD(handleExitMessageMethod, jc_CDropTargetContextPeer, "handleExitMessage", "(Ljava/awt/Component;J)V");626if (sDraggingError == FALSE) {627DLog3(@" - dragExit: loc native %f, %f\n", sDraggingLocation.x, sDraggingLocation.y);628// AWT_THREADING Safe (CToolkitThreadBlockedHandler)629(*env)->CallVoidMethod(env, fDropTargetContextPeer,630handleExitMessageMethod, fComponent, ptr_to_jlong(self));631CHECK_EXCEPTION();632}633634// 5-27-03 Note: [Radar 3270455]635// -draggingExited: can be called both by the AppKit and by -performDragOperation: but shouldn't execute636// twice per drop since cleanup code like that in swing/plaf/basic/BasicDropTargetListener would throw NPEs.637sDraggingExited = TRUE;638}639640DLog(@"[CDropTarget draggingExited]: returning.\n");641}642643- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender644{645DLog2(@"[CDropTarget prepareForDragOperation]: %@\n", self);646DLog2(@"[CDropTarget prepareForDragOperation]: returning %@\n", (sDraggingError ? @"NO" : @"YES"));647648return sDraggingError ? NO : YES;649}650651- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender652{653DLog2(@"[CDropTarget performDragOperation]: %@\n", self);654655sCurrentDropTarget = nil;656657JNIEnv* env = [ThreadUtilities getJNIEnv];658659// Now copy dragging data:660if (sDraggingError == FALSE && [self copyDraggingData:sender] == FALSE)661sDraggingError = TRUE;662663if (sDraggingError == FALSE) {664sDraggingLocation = [sender draggingLocation];665NSPoint javaLocation = [fView convertPoint:sDraggingLocation fromView:nil];666// The y coordinate that comes in the NSDraggingInfo seems to be reversed - probably667// has to do something with the type of view it comes to.668// This is the earliest place where we can correct it.669javaLocation.y = fView.window.frame.size.height - javaLocation.y;670671jint actions = [DnDUtilities mapNSDragOperationMaskToJava:[sender draggingSourceOperationMask]];672jint dropAction = sJavaDropOperation;673674jlongArray formats = sDraggingFormats;675676GET_DTCP_CLASS_RETURN(NO);677DECLARE_METHOD_RETURN(handleDropMessageMethod, jc_CDropTargetContextPeer, "handleDropMessage", "(Ljava/awt/Component;IIII[JJ)V", NO);678679if (sDraggingError == FALSE) {680(*env)->CallVoidMethod(env, fDropTargetContextPeer, handleDropMessageMethod, fComponent,681(jint) javaLocation.x, (jint) javaLocation.y, dropAction, actions, formats, ptr_to_jlong(self)); // AWT_THREADING Safe (event)682CHECK_EXCEPTION();683}684} else {685// 8-19-03 Note: [Radar 3368754]686// draggingExited: is not called after a drop - we must do that here ... but only in case687// of an error, instead of drop(). Otherwise we get twice the cleanup in shared code.688[self draggingExited:sender];689}690691// TODO:BG692// [(id)sender _setLastDragDestinationOperation:sDragOperation];693694695DLog2(@"[CDropTarget performDragOperation]: returning %@\n", (sDraggingError ? @"NO" : @"YES"));696697return !sDraggingError;698}699700- (void)concludeDragOperation:(id<NSDraggingInfo>)sender701{702sCurrentDropTarget = nil;703704DLog2(@"[CDropTarget concludeDragOperation]: %@\n", self);705DLog(@"[CDropTarget concludeDragOperation]: returning.\n");706}707708// 9-11-02 Note: draggingEnded is not yet implemented by the AppKit.709- (void)draggingEnded:(id<NSDraggingInfo>)sender710{711sCurrentDropTarget = nil;712713DLog2(@"[CDropTarget draggingEnded]: %@\n", self);714DLog(@"[CDropTarget draggingEnded]: returning.\n");715}716717/******************************** END NSDraggingDestination Interface ********************************/718719@end720721722/*723* Class: sun_lwawt_macosx_CDropTarget724* Method: createNativeDropTarget725* Signature: (Ljava/awt/dnd/DropTarget;Ljava/awt/Component;Ljava/awt/peer/ComponentPeer;J)J726*/727JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CDropTarget_createNativeDropTarget728(JNIEnv *env, jobject jthis, jobject jdroptarget, jobject jcomponent, jlong jnativepeer)729{730CDropTarget* dropTarget = nil;731732JNI_COCOA_ENTER(env);733id controlObj = (id) jlong_to_ptr(jnativepeer);734dropTarget = [[CDropTarget alloc] init:jdroptarget component:jcomponent control:controlObj];735JNI_COCOA_EXIT(env);736737return ptr_to_jlong(dropTarget);738}739740/*741* Class: sun_lwawt_macosx_CDropTarget742* Method: releaseNativeDropTarget743* Signature: (J)V744*/745JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CDropTarget_releaseNativeDropTarget746(JNIEnv *env, jobject jthis, jlong nativeDropTargetVal)747{748id dropTarget = (id)jlong_to_ptr(nativeDropTargetVal);749750JNI_COCOA_ENTER(env);751[dropTarget removeFromView:env];752JNI_COCOA_EXIT(env);753}754755756