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 "java_awt_dnd_DnDConstants.h"
29
30 #import <Cocoa/Cocoa.h>
31 #import <JavaNativeFoundation/JavaNativeFoundation.h>
32
33 #import "AWTEvent.h"
34 #import "AWTView.h"
35 #import "CDataTransferer.h"
36 #import "CDropTarget.h"
37 #import "CDragSource.h"
38 #import "DnDUtilities.h"
39 #import "ThreadUtilities.h"
40
41
42 // When sIsJavaDragging is true Java drag gesture has been recognized and a drag is/has been initialized.
43 // We must stop posting MouseEvent.MOUSE_DRAGGED events for the duration of the drag or all hell will break
44 // loose in shared code - tracking state going haywire.
45 static BOOL sIsJavaDragging;
46
47
48 @interface NSEvent(AWTAdditions)
49
50 + (void)javaDraggingBegin;
51 + (void)javaDraggingEnd;
52
53 @end
54
55
56 @implementation NSEvent(AWTAdditions)
57
58
59 + (void)javaDraggingBegin
494 dragOrigin.x += fDragImageOffset.x;
495 dragOrigin.y -= fDragImageOffset.y + [dragImage size].height;
496
497 // Drag offset values don't seem to matter:
498 NSSize dragOffset = NSMakeSize(0, 0);
499
500 // These variables should be set based on the transferable:
501 BOOL isFileDrag = FALSE;
502 BOOL fileDragPromises = FALSE;
503
504 DLog(@"[CDragSource drag]: calling dragImage/File:");
505 DLog3(@" - drag origin: %f, %f", fDragPos.x, fDragPos.y);
506 DLog5(@" - drag image: %f, %f (%f x %f)", fDragImageOffset.x, fDragImageOffset.y, [dragImage size].width, [dragImage size].height);
507 DLog3(@" - event point (window) %f, %f", [dragEvent locationInWindow].x, [dragEvent locationInWindow].y);
508 DLog3(@" - drag point (view) %f, %f", dragOrigin.x, dragOrigin.y);
509 // Set up the fDragKeyModifier, so we know if the operation has changed
510 // Set up the fDragMouseModifier, so we can |= it later (since CoreDrag doesn't tell us mouse states during a drag)
511 fDragKeyModifiers = [DnDUtilities extractJavaExtKeyModifiersFromJavaExtModifiers:fModifiers];
512 fDragMouseModifiers = [DnDUtilities extractJavaExtMouseModifiersFromJavaExtModifiers:fModifiers];
513
514 sNeedsEnter = YES;
515
516 @try {
517 // Data dragging:
518 if (isFileDrag == FALSE) {
519 [view dragImage:dragImage at:dragOrigin offset:dragOffset event:dragEvent pasteboard:pb source:view slideBack:YES];
520 } else if (fileDragPromises == FALSE) {
521 // File dragging:
522 NSLog(@"[CDragSource drag]: file dragging is unsupported.");
523 NSString* fileName = nil; // This should be set based on the transferable.
524 NSRect fileLocationRect = NSMakeRect(0, 0, 0, 0); // This should be set based on the filename.
525
526 BOOL success = [view dragFile:fileName fromRect:fileLocationRect slideBack:YES event:dragEvent];
527 if (success == TRUE) { // One would erase dragged file if this was a move operation.
528 }
529 } else {
530 // Promised file dragging:
531 NSLog(@"[CDragSource drag]: file dragging promises are unsupported.");
532 NSArray* fileTypesArray = nil; // This should be set based on the transferable.
533 NSRect fileLocationRect = NSMakeRect(0, 0, 0, 0); // This should be set based on all filenames.
534
535 BOOL success = [view dragPromisedFilesOfTypes:fileTypesArray fromRect:fileLocationRect source:view slideBack:YES event:dragEvent];
536 if (success == TRUE) { // One would write out the promised files here.
544
545 // Drag success must acount for DragOperationNone:
546 jboolean success = (dragOp != java_awt_dnd_DnDConstants_ACTION_NONE);
547
548 // We have a problem here... we don't send DragSource dragEnter/Exit messages outside of our own process
549 // because we don't get anything from AppKit/CoreDrag
550 // This means that if you drag outside of the app and drop, even if it's valid, a dragDropFinished is posted without dragEnter
551 // I'm worried that this might confuse Java, so we're going to send a "bogus" dragEnter if necessary (only if the drag succeeded)
552 if (success && sNeedsEnter) {
553 [self postDragEnter];
554 }
555
556 // DragSourceContextPeer.dragDropFinished() should be called even if there was an error:
557 JNF_MEMBER_CACHE(dragDropFinishedMethod, CDragSourceContextPeerClass, "dragDropFinished", "(ZIII)V");
558 DLog3(@" -> posting dragDropFinished, point %f, %f", point.x, point.y);
559 JNFCallVoidMethod(env, fDragSourceContextPeer, dragDropFinishedMethod, success, dragOp, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event)
560 JNF_MEMBER_CACHE(resetHoveringMethod, CDragSourceContextPeerClass, "resetHovering", "()V");
561 JNFCallVoidMethod(env, fDragSourceContextPeer, resetHoveringMethod); // Hust reset static variable
562 } @finally {
563 sNeedsEnter = NO;
564 }
565
566 // We have to do this, otherwise AppKit doesn't know we're finished dragging. Yup, it's that bad.
567 if ([[[NSRunLoop currentRunLoop] currentMode] isEqualTo:NSEventTrackingRunLoopMode]) {
568 [NSApp postEvent:[self nsDragEvent:NO] atStart:YES];
569 }
570
571 DLog2(@"[CDragSource doDrag] end: %@\n", self);
572 }
573
574 - (void)drag
575 {
576 AWT_ASSERT_NOT_APPKIT_THREAD;
577
578 [self performSelectorOnMainThread:@selector(doDrag) withObject:nil waitUntilDone:YES]; // AWT_THREADING Safe (called from unique asynchronous thread)
579 }
580
581 /******************************** BEGIN NSDraggingSource Interface ********************************/
582
583 - (void)draggingOperationChanged:(NSDragOperation)dragOp {
590
591 NSPoint point = [self mapNSScreenPointToJavaWithOffset:sDraggingLocation];
592 DLog3(@" -> posting operationChanged, point %f, %f", point.x, point.y);
593 jint modifiedModifiers = fDragKeyModifiers | fDragMouseModifiers | [DnDUtilities javaKeyModifiersForNSDragOperation:dragOp];
594
595 JNF_MEMBER_CACHE(operationChangedMethod, CDragSourceContextPeerClass, "operationChanged", "(IIII)V");
596 JNFCallVoidMethod(env, fDragSourceContextPeer, operationChangedMethod, targetActions, modifiedModifiers, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event)
597 }
598
599 - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)localDrag {
600 //DLog2(@"[CDragSource draggingSourceOperationMaskForLocal]: %@\n", self);
601 return [DnDUtilities mapJavaDragOperationToNS:fSourceActions];
602 }
603
604 /* 9-16-02 Note: we don't support promises yet.
605 - (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination {
606 }*/
607
608 - (void)draggedImage:(NSImage *)image beganAt:(NSPoint)screenPoint {
609 DLog4(@"[CDragSource draggedImage beganAt]: (%f, %f) %@\n", screenPoint.x, screenPoint.y, self);
610
611 // Initialize static variables:
612 sDragOperation = NSDragOperationNone;
613 sDraggingLocation = screenPoint;
614 }
615
616 - (void)draggedImage:(NSImage *)image endedAt:(NSPoint)screenPoint operation:(NSDragOperation)operation {
617 DLog4(@"[CDragSource draggedImage endedAt:]: (%f, %f) %@\n", screenPoint.x, screenPoint.y, self);
618
619 sDraggingLocation = screenPoint;
620 sDragOperation = operation;
621 }
622
623 - (void)draggedImage:(NSImage *)image movedTo:(NSPoint)screenPoint {
624 //DLog4(@"[CDragSource draggedImage moved]: (%d, %d) %@\n", (int) screenPoint.x, (int) screenPoint.y, self);
625 JNIEnv* env = [ThreadUtilities getJNIEnv];
626
627 JNF_COCOA_ENTER(env);
628 // There are two things we would be interested in:
629 // a) mouse pointer has moved
630 // b) drag actions (key modifiers) have changed
631
632 BOOL notifyJava = FALSE;
633
634 // a) mouse pointer has moved:
635 if (NSEqualPoints(screenPoint, sDraggingLocation) == FALSE) {
636 //DLog2(@"[CDragSource draggedImage:movedTo]: mouse moved, %@\n", self);
637 notifyJava = TRUE;
638 }
639
640 // b) drag actions (key modifiers) have changed:
641 jint modifiers = NsKeyModifiersToJavaModifiers([NSEvent modifierFlags], YES);
642 if (fDragKeyModifiers != modifiers) {
643 NSDragOperation currentOp = [DnDUtilities nsDragOperationForModifiers:[NSEvent modifierFlags]];
644 NSDragOperation allowedOp = [DnDUtilities mapJavaDragOperationToNS:fSourceActions] & currentOp;
645
646 fDragKeyModifiers = modifiers;
647
|
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 "java_awt_dnd_DnDConstants.h"
29
30 #import <Cocoa/Cocoa.h>
31 #import <JavaNativeFoundation/JavaNativeFoundation.h>
32
33 #import "AWTEvent.h"
34 #import "AWTView.h"
35 #import "CDataTransferer.h"
36 #import "CDropTarget.h"
37 #import "CDragSource.h"
38 #import "DnDUtilities.h"
39 #import "ThreadUtilities.h"
40 #import "LWCToolkit.h"
41
42
43 // When sIsJavaDragging is true Java drag gesture has been recognized and a drag is/has been initialized.
44 // We must stop posting MouseEvent.MOUSE_DRAGGED events for the duration of the drag or all hell will break
45 // loose in shared code - tracking state going haywire.
46 static BOOL sIsJavaDragging;
47
48
49 @interface NSEvent(AWTAdditions)
50
51 + (void)javaDraggingBegin;
52 + (void)javaDraggingEnd;
53
54 @end
55
56
57 @implementation NSEvent(AWTAdditions)
58
59
60 + (void)javaDraggingBegin
495 dragOrigin.x += fDragImageOffset.x;
496 dragOrigin.y -= fDragImageOffset.y + [dragImage size].height;
497
498 // Drag offset values don't seem to matter:
499 NSSize dragOffset = NSMakeSize(0, 0);
500
501 // These variables should be set based on the transferable:
502 BOOL isFileDrag = FALSE;
503 BOOL fileDragPromises = FALSE;
504
505 DLog(@"[CDragSource drag]: calling dragImage/File:");
506 DLog3(@" - drag origin: %f, %f", fDragPos.x, fDragPos.y);
507 DLog5(@" - drag image: %f, %f (%f x %f)", fDragImageOffset.x, fDragImageOffset.y, [dragImage size].width, [dragImage size].height);
508 DLog3(@" - event point (window) %f, %f", [dragEvent locationInWindow].x, [dragEvent locationInWindow].y);
509 DLog3(@" - drag point (view) %f, %f", dragOrigin.x, dragOrigin.y);
510 // Set up the fDragKeyModifier, so we know if the operation has changed
511 // Set up the fDragMouseModifier, so we can |= it later (since CoreDrag doesn't tell us mouse states during a drag)
512 fDragKeyModifiers = [DnDUtilities extractJavaExtKeyModifiersFromJavaExtModifiers:fModifiers];
513 fDragMouseModifiers = [DnDUtilities extractJavaExtMouseModifiersFromJavaExtModifiers:fModifiers];
514
515 @try {
516 sNeedsEnter = YES;
517 AWTToolkit.inDoDragDropLoop = YES;
518 // Data dragging:
519 if (isFileDrag == FALSE) {
520 [view dragImage:dragImage at:dragOrigin offset:dragOffset event:dragEvent pasteboard:pb source:view slideBack:YES];
521 } else if (fileDragPromises == FALSE) {
522 // File dragging:
523 NSLog(@"[CDragSource drag]: file dragging is unsupported.");
524 NSString* fileName = nil; // This should be set based on the transferable.
525 NSRect fileLocationRect = NSMakeRect(0, 0, 0, 0); // This should be set based on the filename.
526
527 BOOL success = [view dragFile:fileName fromRect:fileLocationRect slideBack:YES event:dragEvent];
528 if (success == TRUE) { // One would erase dragged file if this was a move operation.
529 }
530 } else {
531 // Promised file dragging:
532 NSLog(@"[CDragSource drag]: file dragging promises are unsupported.");
533 NSArray* fileTypesArray = nil; // This should be set based on the transferable.
534 NSRect fileLocationRect = NSMakeRect(0, 0, 0, 0); // This should be set based on all filenames.
535
536 BOOL success = [view dragPromisedFilesOfTypes:fileTypesArray fromRect:fileLocationRect source:view slideBack:YES event:dragEvent];
537 if (success == TRUE) { // One would write out the promised files here.
545
546 // Drag success must acount for DragOperationNone:
547 jboolean success = (dragOp != java_awt_dnd_DnDConstants_ACTION_NONE);
548
549 // We have a problem here... we don't send DragSource dragEnter/Exit messages outside of our own process
550 // because we don't get anything from AppKit/CoreDrag
551 // This means that if you drag outside of the app and drop, even if it's valid, a dragDropFinished is posted without dragEnter
552 // I'm worried that this might confuse Java, so we're going to send a "bogus" dragEnter if necessary (only if the drag succeeded)
553 if (success && sNeedsEnter) {
554 [self postDragEnter];
555 }
556
557 // DragSourceContextPeer.dragDropFinished() should be called even if there was an error:
558 JNF_MEMBER_CACHE(dragDropFinishedMethod, CDragSourceContextPeerClass, "dragDropFinished", "(ZIII)V");
559 DLog3(@" -> posting dragDropFinished, point %f, %f", point.x, point.y);
560 JNFCallVoidMethod(env, fDragSourceContextPeer, dragDropFinishedMethod, success, dragOp, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event)
561 JNF_MEMBER_CACHE(resetHoveringMethod, CDragSourceContextPeerClass, "resetHovering", "()V");
562 JNFCallVoidMethod(env, fDragSourceContextPeer, resetHoveringMethod); // Hust reset static variable
563 } @finally {
564 sNeedsEnter = NO;
565 AWTToolkit.inDoDragDropLoop = NO;
566 }
567
568 // We have to do this, otherwise AppKit doesn't know we're finished dragging. Yup, it's that bad.
569 if ([[[NSRunLoop currentRunLoop] currentMode] isEqualTo:NSEventTrackingRunLoopMode]) {
570 [NSApp postEvent:[self nsDragEvent:NO] atStart:YES];
571 }
572
573 DLog2(@"[CDragSource doDrag] end: %@\n", self);
574 }
575
576 - (void)drag
577 {
578 AWT_ASSERT_NOT_APPKIT_THREAD;
579
580 [self performSelectorOnMainThread:@selector(doDrag) withObject:nil waitUntilDone:YES]; // AWT_THREADING Safe (called from unique asynchronous thread)
581 }
582
583 /******************************** BEGIN NSDraggingSource Interface ********************************/
584
585 - (void)draggingOperationChanged:(NSDragOperation)dragOp {
592
593 NSPoint point = [self mapNSScreenPointToJavaWithOffset:sDraggingLocation];
594 DLog3(@" -> posting operationChanged, point %f, %f", point.x, point.y);
595 jint modifiedModifiers = fDragKeyModifiers | fDragMouseModifiers | [DnDUtilities javaKeyModifiersForNSDragOperation:dragOp];
596
597 JNF_MEMBER_CACHE(operationChangedMethod, CDragSourceContextPeerClass, "operationChanged", "(IIII)V");
598 JNFCallVoidMethod(env, fDragSourceContextPeer, operationChangedMethod, targetActions, modifiedModifiers, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event)
599 }
600
601 - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)localDrag {
602 //DLog2(@"[CDragSource draggingSourceOperationMaskForLocal]: %@\n", self);
603 return [DnDUtilities mapJavaDragOperationToNS:fSourceActions];
604 }
605
606 /* 9-16-02 Note: we don't support promises yet.
607 - (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination {
608 }*/
609
610 - (void)draggedImage:(NSImage *)image beganAt:(NSPoint)screenPoint {
611 DLog4(@"[CDragSource draggedImage beganAt]: (%f, %f) %@\n", screenPoint.x, screenPoint.y, self);
612 [AWTToolkit eventCountPlusPlus];
613 // Initialize static variables:
614 sDragOperation = NSDragOperationNone;
615 sDraggingLocation = screenPoint;
616 }
617
618 - (void)draggedImage:(NSImage *)image endedAt:(NSPoint)screenPoint operation:(NSDragOperation)operation {
619 DLog4(@"[CDragSource draggedImage endedAt:]: (%f, %f) %@\n", screenPoint.x, screenPoint.y, self);
620 [AWTToolkit eventCountPlusPlus];
621 sDraggingLocation = screenPoint;
622 sDragOperation = operation;
623 }
624
625 - (void)draggedImage:(NSImage *)image movedTo:(NSPoint)screenPoint {
626 //DLog4(@"[CDragSource draggedImage moved]: (%d, %d) %@\n", (int) screenPoint.x, (int) screenPoint.y, self);
627 JNIEnv* env = [ThreadUtilities getJNIEnv];
628
629 JNF_COCOA_ENTER(env);
630 [AWTToolkit eventCountPlusPlus];
631 // There are two things we would be interested in:
632 // a) mouse pointer has moved
633 // b) drag actions (key modifiers) have changed
634
635 BOOL notifyJava = FALSE;
636
637 // a) mouse pointer has moved:
638 if (NSEqualPoints(screenPoint, sDraggingLocation) == FALSE) {
639 //DLog2(@"[CDragSource draggedImage:movedTo]: mouse moved, %@\n", self);
640 notifyJava = TRUE;
641 }
642
643 // b) drag actions (key modifiers) have changed:
644 jint modifiers = NsKeyModifiersToJavaModifiers([NSEvent modifierFlags], YES);
645 if (fDragKeyModifiers != modifiers) {
646 NSDragOperation currentOp = [DnDUtilities nsDragOperationForModifiers:[NSEvent modifierFlags]];
647 NSDragOperation allowedOp = [DnDUtilities mapJavaDragOperationToNS:fSourceActions] & currentOp;
648
649 fDragKeyModifiers = modifiers;
650
|