From 380664aadeada69dbb957dd034c44354f9159789 Mon Sep 17 00:00:00 2001 From: "joshmoz%gmail.com" Date: Tue, 17 Jul 2007 02:24:05 +0000 Subject: [PATCH] support promised file dragging in cocoa drag service. patch by Stan Shebs. b=358093 r=josh sr=pav git-svn-id: svn://10.0.0.236/trunk@230087 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/widget/src/cocoa/nsChildView.h | 6 ++ mozilla/widget/src/cocoa/nsChildView.mm | 79 +++++++++++++++++++++++ mozilla/widget/src/cocoa/nsClipboard.h | 10 +++ mozilla/widget/src/cocoa/nsClipboard.mm | 2 +- mozilla/widget/src/cocoa/nsDragService.h | 10 +++ mozilla/widget/src/cocoa/nsDragService.mm | 19 +++++- 6 files changed, 123 insertions(+), 3 deletions(-) diff --git a/mozilla/widget/src/cocoa/nsChildView.h b/mozilla/widget/src/cocoa/nsChildView.h index d0e7856b42c..181518459d6 100644 --- a/mozilla/widget/src/cocoa/nsChildView.h +++ b/mozilla/widget/src/cocoa/nsChildView.h @@ -69,6 +69,12 @@ #import #import +#ifdef MOZ_LOGGING +// make sure that logging is enabled before including prlog.h +#define FORCE_PR_LOG +#include "prlog.h" +#endif + class gfxASurface; class nsChildView; union nsPluginPort; diff --git a/mozilla/widget/src/cocoa/nsChildView.mm b/mozilla/widget/src/cocoa/nsChildView.mm index 28bc7bc8a41..1356480ae34 100644 --- a/mozilla/widget/src/cocoa/nsChildView.mm +++ b/mozilla/widget/src/cocoa/nsChildView.mm @@ -58,6 +58,8 @@ #include "nsIViewManager.h" #include "nsIInterfaceRequestor.h" #include "nsIServiceManager.h" +#include "nsILocalFile.h" +#include "nsILocalFileMac.h" #include "nsGfxCIID.h" #include "nsDragService.h" @@ -72,6 +74,10 @@ #undef DEBUG_UPDATE #undef INVALIDATE_DEBUGGING // flash areas as they are invalidated +#ifdef PR_LOGGING +PRLogModuleInfo* sCocoaLog = nsnull; +#endif + extern "C" { CG_EXTERN void CGContextResetCTM(CGContextRef); CG_EXTERN void CGContextSetCTM(CGContextRef, CGAffineTransform); @@ -328,6 +334,12 @@ nsChildView::nsChildView() : nsBaseWidget() { SetBackgroundColor(NS_RGB(255, 255, 255)); SetForegroundColor(NS_RGB(0, 0, 0)); + +#ifdef PR_LOGGING + if (!sCocoaLog) + sCocoaLog = PR_NewLogModule("nsCocoaWidgets"); +#endif + } @@ -1854,9 +1866,11 @@ NSEvent* globalDragEvent = nil; } // register for things we'll take from other applications + PR_LOG(sCocoaLog, PR_LOG_ALWAYS, ("ChildView initWithFrame: registering drag types\n")); [self registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSStringPboardType, NSURLPboardType, + NSFilesPromisePboardType, kWildcardPboardType, nil]]; @@ -3879,6 +3893,8 @@ static PRBool IsSpecialGeckoKey(UInt32 macKeyCode) if (!mGeckoChild) return NO; + PR_LOG(sCocoaLog, PR_LOG_ALWAYS, ("ChildView doDragAction: entered\n")); + if (!mDragService) { CallGetService(kDragServiceContractID, &mDragService); NS_ASSERTION(mDragService, "Couldn't get a drag service - big problem!"); @@ -3945,6 +3961,8 @@ static PRBool IsSpecialGeckoKey(UInt32 macKeyCode) - (NSDragOperation)draggingEntered:(id )sender { + PR_LOG(sCocoaLog, PR_LOG_ALWAYS, ("ChildView draggingEntered: entered\n")); + // there should never be a globalDragPboard when "draggingEntered:" is // called, but just in case we'll take care of it here. [globalDragPboard release]; @@ -3962,6 +3980,8 @@ static PRBool IsSpecialGeckoKey(UInt32 macKeyCode) - (NSDragOperation)draggingUpdated:(id )sender { + PR_LOG(sCocoaLog, PR_LOG_ALWAYS, ("ChildView draggingUpdated: entered\n")); + BOOL handled = [self doDragAction:NS_DRAGDROP_OVER sender:sender]; return handled ? NSDragOperationGeneric : NSDragOperationNone; } @@ -3969,6 +3989,8 @@ static PRBool IsSpecialGeckoKey(UInt32 macKeyCode) - (void)draggingExited:(id )sender { + PR_LOG(sCocoaLog, PR_LOG_ALWAYS, ("ChildView draggingExited: entered\n")); + [self doDragAction:NS_DRAGDROP_EXIT sender:sender]; } @@ -4004,6 +4026,63 @@ static PRBool IsSpecialGeckoKey(UInt32 macKeyCode) return UINT_MAX; } +// This method is a callback typically invoked in response to a drag ending on the desktop +// or a Findow folder window; the argument passed is a path to the drop location, to be used +// in constructing a complete pathname for the file(s) we want to create as a result of +// the drag. +- (NSArray *)namesOfPromisedFilesDroppedAtDestination:(id )dropDestination +{ + nsresult rv; + + PR_LOG(sCocoaLog, PR_LOG_ALWAYS, ("ChildView namesOfPromisedFilesDroppedAtDestination: entering callback for promised files\n")); + + nsCOMPtr targFile; + NS_NewLocalFile(EmptyString(), PR_TRUE, getter_AddRefs(targFile)); + nsCOMPtr macLocalFile = do_QueryInterface(targFile); + if (!macLocalFile) { + NS_ERROR("No Mac local file"); + return nil; + } + + if (!NS_SUCCEEDED(macLocalFile->InitWithCFURL((CFURLRef)dropDestination))) { + NS_ERROR("failed InitWithCFURL"); + return nil; + } + + extern nsISupportsArray *draggedTransferables; + + PRUint32 transferableCount; + rv = draggedTransferables->Count(&transferableCount); + if (NS_FAILED(rv)) + return nil; + + for (PRUint32 i = 0; i < transferableCount; i++) { + nsCOMPtr genericItem; + draggedTransferables->GetElementAt(i, getter_AddRefs(genericItem)); + nsCOMPtr item(do_QueryInterface(genericItem)); + if (!item) { + NS_ERROR("no transferable"); + return nil; + } + + item->SetTransferData(kFilePromiseDirectoryMime, macLocalFile, sizeof(nsILocalFile*)); + + // now request the kFilePromiseMime data, which will invoke the data provider + // If successful, the returned data is a reference to the resulting file. + nsCOMPtr fileDataPrimitive; + PRUint32 dataSize = 0; + item->GetTransferData(kFilePromiseMime, getter_AddRefs(fileDataPrimitive), &dataSize); + } + + NSPasteboard* generalPboard = [NSPasteboard pasteboardWithName:NSDragPboard]; + NSData* data = [generalPboard dataForType:@"application/x-moz-file-promise-dest-filename"]; + NSString* name = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + NSArray* rslt = [NSArray arrayWithObject:name]; + + [name release]; + + return rslt; +} #pragma mark - diff --git a/mozilla/widget/src/cocoa/nsClipboard.h b/mozilla/widget/src/cocoa/nsClipboard.h index 356be844818..441fa2e6fa7 100644 --- a/mozilla/widget/src/cocoa/nsClipboard.h +++ b/mozilla/widget/src/cocoa/nsClipboard.h @@ -43,6 +43,16 @@ #import +#ifdef MOZ_LOGGING +// make sure that logging is enabled before including prlog.h +#define FORCE_PR_LOG +#include "prlog.h" +#endif + +#ifdef PR_LOGGING +extern PRLogModuleInfo* sCocoaLog; +#endif + class nsITransferable; diff --git a/mozilla/widget/src/cocoa/nsClipboard.mm b/mozilla/widget/src/cocoa/nsClipboard.mm index e7e652c0713..f1819269882 100644 --- a/mozilla/widget/src/cocoa/nsClipboard.mm +++ b/mozilla/widget/src/cocoa/nsClipboard.mm @@ -299,7 +299,7 @@ nsClipboard::PasteboardDictFromTransferable(nsITransferable* aTransferable) nsXPIDLCString flavorStr; currentFlavor->ToString(getter_Copies(flavorStr)); - // printf("writing out clipboard data of type %s\n", flavorStr.get()); + PR_LOG(sCocoaLog, PR_LOG_ALWAYS, ("writing out clipboard data of type %s (%d)\n", flavorStr.get(), i)); if (flavorStr.EqualsLiteral(kUnicodeMime)) { void* data = nsnull; diff --git a/mozilla/widget/src/cocoa/nsDragService.h b/mozilla/widget/src/cocoa/nsDragService.h index 36b32878412..a88fd66f6c1 100644 --- a/mozilla/widget/src/cocoa/nsDragService.h +++ b/mozilla/widget/src/cocoa/nsDragService.h @@ -43,6 +43,16 @@ #include +#ifdef MOZ_LOGGING +// make sure that logging is enabled before including prlog.h +#define FORCE_PR_LOG +#include "prlog.h" +#endif + +#ifdef PR_LOGGING +extern PRLogModuleInfo* sCocoaLog; +#endif + extern NSString* const kWildcardPboardType; class nsDragService : public nsBaseDragService diff --git a/mozilla/widget/src/cocoa/nsDragService.mm b/mozilla/widget/src/cocoa/nsDragService.mm index 8f3c377724f..34f8dd4d1a0 100644 --- a/mozilla/widget/src/cocoa/nsDragService.mm +++ b/mozilla/widget/src/cocoa/nsDragService.mm @@ -69,6 +69,10 @@ extern NSPasteboard* globalDragPboard; extern NSView* globalDragView; extern NSEvent* globalDragEvent; +// This global makes the transferable array available to Cocoa's promised +// file destination callback. +nsISupportsArray *draggedTransferables; + NSString* const kWildcardPboardType = @"MozillaWildcard"; NS_IMPL_ADDREF_INHERITED(nsDragService, nsBaseDragService) @@ -262,12 +266,23 @@ nsDragService::InvokeDragSession(nsIDOMNode* aDOMNode, nsISupportsArray* aTransf point = [[globalDragView window] convertScreenToBase: point]; NSPoint localPoint = [globalDragView convertPoint:point fromView:nil]; + // Save the transferables away in case a promised file callback is invoked. + draggedTransferables = aTransferableArray; + nsBaseDragService::StartDragSession(); + + // It is possible to specify what file types we will create, but the Finder doesn't + // care; it is happy to store any type of file it is handed. So use an empty string + // for type. + NSPasteboard* workingPBoard = [NSPasteboard pasteboardWithName:NSDragPboard]; + NSArray* fileTypeList = [NSArray arrayWithObject:@""]; + [workingPBoard setPropertyList:fileTypeList forType:NSFilesPromisePboardType]; + [globalDragView dragImage:image at:localPoint offset:NSMakeSize(0,0) event:globalDragEvent - pasteboard:[NSPasteboard pasteboardWithName:NSDragPboard] + pasteboard:workingPBoard source:globalDragView slideBack:YES]; @@ -331,7 +346,7 @@ nsDragService::GetData(nsITransferable* aTransferable, PRUint32 aItemIndex) nsXPIDLCString flavorStr; currentFlavor->ToString(getter_Copies(flavorStr)); - // printf("looking for clipboard data of type %s\n", flavorStr.get()); + PR_LOG(sCocoaLog, PR_LOG_ALWAYS, ("nsDragService::GetData: looking for clipboard data of type %s\n", flavorStr.get())); if (flavorStr.EqualsLiteral(kFileMime)) { NSArray* pFiles = [globalDragPboard propertyListForType:NSFilenamesPboardType];