CDragSource.m revision 4639
1879N/A#import <Cocoa/Cocoa.h>
1703N/A// When sIsJavaDragging is true Java drag gesture has been recognized and a drag is/has been initialized.
1703N/A// We must stop posting MouseEvent.MOUSE_DRAGGED events for the duration of the drag or all hell will break
1703N/A+ (void)javaDraggingBegin;
1703N/A+ (void)javaDraggingEnd;
1703N/A+ (void)javaDraggingBegin
1703N/A+ (void)javaDraggingEnd
1703N/A return sCurrentDragSource;
1703N/A- (id)init:(jobject)jdragsourcecontextpeer component:(jobject)jcomponent peer:(jobject)jpeer control:(id)control
1703N/A dragPosX:(jint)dragPosX dragPosY:(jint)dragPosY modifiers:(jint)extModifiers clickCount:(jint)clickCount
1703N/A dragImage:(jlong)jnsdragimage dragImageOffsetX:(jint)jdragimageoffsetx dragImageOffsetY:(jint)jdragimageoffsety
3108N/A sourceActions:(jint)jsourceactions formats:(jlongArray)jformats formatMap:(jobject)jformatmap
1703N/A fDragImage = (NSImage*) jlong_to_ptr(jnsdragimage); // Double-casting prevents compiler 'different size' warning.
return self;
- (void)dealloc
[super dealloc];
// * NOTE: This returns a JNI Local Ref. Any code that calls must call DeleteLocalRef with the return value.
JNF_STATIC_MEMBER_CACHE(getInstanceMethod, DataTransfererClass, "getInstance", "()Lsun/awt/datatransfer/DataTransferer;");
// * NOTE: This returns a JNI Local Ref. Any code that calls must call DeleteLocalRef with the return value.
JNF_MEMBER_CACHE(convertDataMethod, DataTransfererClass, "convertData", "(Ljava/lang/Object;Ljava/awt/datatransfer/Transferable;JLjava/util/Map;Z)[B");
data = JNFCallObjectMethod(env, transferer, convertDataMethod, fComponent, fTransferable, format, fFormatMap, (jboolean) TRUE);
return data;
// Encodes a byte array of zero-terminated filenames into an NSArray of NSStrings representing them.
jsize i;
strings++;
return FALSE;
// "JAVA_DATAFLAVOR:application/x-java-serialized-object; class=java.awt.Label".
jsize i;
hasNSTypeData = true;
// When TransferHandler is used with Swing components it puts only a type like this on the pasteboard:
// "JAVA_DATAFLAVOR:application/x-java-jvm-local-objectref; class=java.lang.String"
// Since our drop targets aren't trained for arbitrary data types yet we need to fake an empty string
// Also, use a custom format rather than NSString, since that will prevent random views from accepting the drag
// If I provide the filenames _right now_, NSFilenamesPboardType is properly converted to CoreDrag flavors
// This is an NSPasteboard callback. In declareTypesToPasteboard:withEnv:, we only declared the types
// Note that if the transfer is handled entirely from Swing (as in a local-vm drag), this method may never be called.
- (void)validateDragImage
// Convert fTriggerEventTimeStamp to NS - AWTEvent.h defines UTC(nsEvent) as ((jlong)[event timestamp] * 1000):
if (isDrag) {
return dragEvent;
- (void)doDrag
DLog5(@" - drag image: %f, %f (%f x %f)", fDragImageOffset.x, fDragImageOffset.y, [dragImage size].width, [dragImage size].height);
DLog3(@" - event point (window) %f, %f", [dragEvent locationInWindow].x, [dragEvent locationInWindow].y);
// Set up the fDragMouseModifier, so we can |= it later (since CoreDrag doesn't tell us mouse states during a drag)
[view dragImage:dragImage at:dragOrigin offset:dragOffset event:dragEvent pasteboard:pb source:view slideBack:YES];
BOOL success = [view dragPromisedFilesOfTypes:fileTypesArray fromRect:fileLocationRect source:view slideBack:YES event:dragEvent];
// We have a problem here... we don't send DragSource dragEnter/Exit messages outside of our own process
// This means that if you drag outside of the app and drop, even if it's valid, a dragDropFinished is posted without dragEnter
// I'm worried that this might confuse Java, so we're going to send a "bogus" dragEnter if necessary (only if the drag succeeded)
JNF_MEMBER_CACHE(dragDropFinishedMethod, CDragSourceContextPeerClass, "dragDropFinished", "(ZIII)V");
JNFCallVoidMethod(env, fDragSourceContextPeer, dragDropFinishedMethod, success, dragOp, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event)
- (void)drag
[self performSelectorOnMainThread:@selector(doDrag) withObject:nil waitUntilDone:YES]; // AWT_THREADING Safe (called from unique asynchronous thread)
/******************************** BEGIN NSDraggingSource Interface ********************************/
if ([CDropTarget currentDropTarget]) targetActions = [[CDropTarget currentDropTarget] currentJavaActions];
jint modifiedModifiers = fDragKeyModifiers | fDragMouseModifiers | [DnDUtilities javaKeyModifiersForNSDragOperation:dragOp];
JNF_MEMBER_CACHE(operationChangedMethod, CDragSourceContextPeerClass, "operationChanged", "(IIII)V");
JNFCallVoidMethod(env, fDragSourceContextPeer, operationChangedMethod, targetActions, modifiedModifiers, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event)
- (void)draggedImage:(NSImage *)image endedAt:(NSPoint)screenPoint operation:(NSDragOperation)operation {
//DLog4(@"[CDragSource draggedImage moved]: (%d, %d) %@\n", (int) screenPoint.x, (int) screenPoint.y, self);
if (notifyJava) {
if ([CDropTarget currentDropTarget]) targetActions = [[CDropTarget currentDropTarget] currentJavaActions];
JNFCallVoidMethod(env, fDragSourceContextPeer, dragMotionMethod, targetActions, (jint) fModifiers, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event)
JNFCallVoidMethod(env, fDragSourceContextPeer, dragMouseMovedMethod, targetActions, (jint) fModifiers, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event)
return NO;
- (void) postDragEnter {
if ([CDropTarget currentDropTarget]) targetActions = [[CDropTarget currentDropTarget] currentJavaActions];
JNFCallVoidMethod(env, fDragSourceContextPeer, dragEnterMethod, targetActions, (jint) fModifiers, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event)
- (void) postDragExit {
JNFCallVoidMethod(env, fDragSourceContextPeer, dragExitMethod, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event)
// The point should remain in screen coordinates (as per DragSourceEvent.getLocation() documentation)
return point;
@end