mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
fix drag and drop for multiple items, fix a data corruption bug, fix dragging images out of gecko. b=385116 r=shebs sr=dbaron a=mconnor
This commit is contained in:
parent
d429b8c71d
commit
d6bb5dc808
@ -57,6 +57,7 @@ public:
|
||||
// nsIDragService
|
||||
NS_IMETHOD InvokeDragSession(nsIDOMNode *aDOMNode, nsISupportsArray * anArrayTransferables,
|
||||
nsIScriptableRegion * aRegion, PRUint32 aActionType);
|
||||
NS_IMETHOD EndDragSession(PRBool aDoneDrag);
|
||||
|
||||
// nsIDragSession
|
||||
NS_IMETHOD GetData(nsITransferable * aTransferable, PRUint32 aItemIndex);
|
||||
@ -68,6 +69,8 @@ private:
|
||||
NSImage* ConstructDragImage(nsIDOMNode* aDOMNode,
|
||||
nsRect* aDragRect,
|
||||
nsIScriptableRegion* aRegion);
|
||||
|
||||
nsCOMPtr<nsISupportsArray> mDataItems; // only valid for a drag started within gecko
|
||||
};
|
||||
|
||||
#endif // nsDragService_h_
|
||||
|
@ -75,6 +75,7 @@ NS_IMPL_ADDREF_INHERITED(nsDragService, nsBaseDragService)
|
||||
NS_IMPL_RELEASE_INHERITED(nsDragService, nsBaseDragService)
|
||||
NS_IMPL_QUERY_INTERFACE2(nsDragService, nsIDragService, nsIDragSession)
|
||||
|
||||
|
||||
nsDragService::nsDragService()
|
||||
{
|
||||
|
||||
@ -86,6 +87,7 @@ nsDragService::~nsDragService()
|
||||
|
||||
}
|
||||
|
||||
|
||||
static nsresult SetUpDragClipboard(nsISupportsArray* aTransferableArray)
|
||||
{
|
||||
if (!aTransferableArray)
|
||||
@ -117,17 +119,16 @@ static nsresult SetUpDragClipboard(nsISupportsArray* aTransferableArray)
|
||||
for (unsigned int i = 0; i < outputCount; i++) {
|
||||
NSString* currentKey = [outputKeys objectAtIndex:i];
|
||||
id currentValue = [pasteboardOutputDict valueForKey:currentKey];
|
||||
if (currentKey == NSStringPboardType)
|
||||
if (currentKey == NSStringPboardType) {
|
||||
[generalPBoard setString:currentValue forType:currentKey];
|
||||
else {
|
||||
}
|
||||
else if (currentKey == NSTIFFPboardType) {
|
||||
[generalPBoard setData:currentValue forType:currentKey];
|
||||
// Record miscellaneous types of data a second time, under a
|
||||
// generic type that is always registered with Cocoa as
|
||||
// draggable. This allows types dynamically synthesized from
|
||||
// JS to work; if in the future several different types of
|
||||
// drag data need to be distinguished, it will be the
|
||||
// responsibility of higher-level drag code to detect the
|
||||
// situation (which it would normally have to do anyway.)
|
||||
}
|
||||
else {
|
||||
// Record miscellaneous types of data under a generic type
|
||||
// that is always registered with Cocoa as draggable. This
|
||||
// allows types dynamically synthesized from JS to work.
|
||||
[generalPBoard setData:nil forType:kWildcardPboardType];
|
||||
}
|
||||
}
|
||||
@ -225,6 +226,8 @@ nsDragService::InvokeDragSession(nsIDOMNode* aDOMNode, nsISupportsArray* aTransf
|
||||
{
|
||||
nsBaseDragService::InvokeDragSession(aDOMNode, aTransferableArray, aDragRgn, aActionType);
|
||||
|
||||
mDataItems = aTransferableArray;
|
||||
|
||||
// put data on the clipboard
|
||||
if (NS_FAILED(SetUpDragClipboard(aTransferableArray)))
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -277,8 +280,135 @@ nsDragService::InvokeDragSession(nsIDOMNode* aDOMNode, nsISupportsArray* aTransf
|
||||
NS_IMETHODIMP
|
||||
nsDragService::GetData(nsITransferable* aTransferable, PRUint32 aItemIndex)
|
||||
{
|
||||
// Ask the clipboard to look this up for us
|
||||
return nsClipboard::CopyPasteboardDataToTransferable(globalDragPboard, aTransferable, aItemIndex);
|
||||
if (!aTransferable)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// get flavor list that includes all acceptable flavors (including ones obtained through conversion)
|
||||
nsCOMPtr<nsISupportsArray> flavorList;
|
||||
nsresult rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRUint32 acceptableFlavorCount;
|
||||
flavorList->Count(&acceptableFlavorCount);
|
||||
|
||||
// if this drag originated within Mozilla we should just use the cached data from
|
||||
// when the drag started if possible
|
||||
if (mDataItems) {
|
||||
nsCOMPtr<nsISupports> currentTransferableSupports;
|
||||
mDataItems->GetElementAt(aItemIndex, getter_AddRefs(currentTransferableSupports));
|
||||
if (currentTransferableSupports) {
|
||||
nsCOMPtr<nsITransferable> currentTransferable(do_QueryInterface(currentTransferableSupports));
|
||||
if (currentTransferable) {
|
||||
for (PRUint32 i = 0; i < acceptableFlavorCount; i++) {
|
||||
nsCOMPtr<nsISupports> genericFlavor;
|
||||
flavorList->GetElementAt(i, getter_AddRefs(genericFlavor));
|
||||
nsCOMPtr<nsISupportsCString> currentFlavor(do_QueryInterface(genericFlavor));
|
||||
if (!currentFlavor)
|
||||
continue;
|
||||
nsXPIDLCString flavorStr;
|
||||
currentFlavor->ToString(getter_Copies(flavorStr));
|
||||
|
||||
nsCOMPtr<nsISupports> dataSupports;
|
||||
PRUint32 dataSize = 0;
|
||||
rv = currentTransferable->GetTransferData(flavorStr, getter_AddRefs(dataSupports), &dataSize);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
aTransferable->SetTransferData(flavorStr, dataSupports, dataSize);
|
||||
return NS_OK; // maybe try to fill in more types? Is there a point?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now check the actual clipboard for data
|
||||
for (PRUint32 i = 0; i < acceptableFlavorCount; i++) {
|
||||
nsCOMPtr<nsISupports> genericFlavor;
|
||||
flavorList->GetElementAt(i, getter_AddRefs(genericFlavor));
|
||||
nsCOMPtr<nsISupportsCString> currentFlavor(do_QueryInterface(genericFlavor));
|
||||
|
||||
if (!currentFlavor)
|
||||
continue;
|
||||
|
||||
nsXPIDLCString flavorStr;
|
||||
currentFlavor->ToString(getter_Copies(flavorStr));
|
||||
|
||||
// printf("looking for clipboard data of type %s\n", flavorStr.get());
|
||||
|
||||
if (strcmp(flavorStr, kFileMime) == 0) {
|
||||
NSArray* pFiles = [globalDragPboard propertyListForType:NSFilenamesPboardType];
|
||||
if (!pFiles || [pFiles count] < (aItemIndex + 1))
|
||||
continue;
|
||||
|
||||
NSString* filePath = [pFiles objectAtIndex:aItemIndex];
|
||||
if (!filePath)
|
||||
continue;
|
||||
|
||||
unsigned int stringLength = [filePath length];
|
||||
unsigned int dataLength = (stringLength + 1) * sizeof(PRUnichar); // in bytes
|
||||
PRUnichar* clipboardDataPtr = (PRUnichar*)malloc(dataLength);
|
||||
if (!clipboardDataPtr)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
[filePath getCharacters:clipboardDataPtr];
|
||||
clipboardDataPtr[stringLength] = 0; // null terminate
|
||||
|
||||
nsCOMPtr<nsILocalFile> file;
|
||||
nsresult rv = NS_NewLocalFile(nsDependentString(clipboardDataPtr), PR_TRUE, getter_AddRefs(file));
|
||||
free(clipboardDataPtr);
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsISupports> genericDataWrapper;
|
||||
genericDataWrapper = do_QueryInterface(file);
|
||||
aTransferable->SetTransferData(flavorStr, genericDataWrapper, dataLength);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (strcmp(flavorStr, kUnicodeMime) == 0) {
|
||||
NSString* pString = [globalDragPboard stringForType:NSStringPboardType];
|
||||
if (!pString)
|
||||
continue;
|
||||
|
||||
NSData* stringData = [pString dataUsingEncoding:NSUnicodeStringEncoding];
|
||||
unsigned int dataLength = [stringData length];
|
||||
void* clipboardDataPtr = malloc(dataLength);
|
||||
if (!clipboardDataPtr)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
[stringData getBytes:clipboardDataPtr];
|
||||
|
||||
// The DOM only wants LF, so convert from MacOS line endings to DOM line endings.
|
||||
PRInt32 signedDataLength = dataLength;
|
||||
nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks(flavorStr, &clipboardDataPtr, (PRInt32*)&signedDataLength);
|
||||
dataLength = signedDataLength;
|
||||
|
||||
// skip BOM (Byte Order Mark to distinguish little or big endian)
|
||||
PRUnichar* clipboardDataPtrNoBOM = (PRUnichar*)clipboardDataPtr;
|
||||
if ((dataLength > 2) &&
|
||||
((clipboardDataPtrNoBOM[0] == 0xFEFF) ||
|
||||
(clipboardDataPtrNoBOM[0] == 0xFFFE))) {
|
||||
dataLength -= sizeof(PRUnichar);
|
||||
clipboardDataPtrNoBOM += 1;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> genericDataWrapper;
|
||||
nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, clipboardDataPtrNoBOM, dataLength,
|
||||
getter_AddRefs(genericDataWrapper));
|
||||
aTransferable->SetTransferData(flavorStr, genericDataWrapper, dataLength);
|
||||
free(clipboardDataPtr);
|
||||
break;
|
||||
}
|
||||
|
||||
// We have never supported this on Mac OS X, we should someday. Normally dragging images
|
||||
// in is accomplished with a file path drag instead of the image data itself.
|
||||
/*
|
||||
if (strcmp(flavorStr, kPNGImageMime) == 0 || strcmp(flavorStr, kJPEGImageMime) == 0 ||
|
||||
strcmp(flavorStr, kGIFImageMime) == 0) {
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -315,7 +445,13 @@ NS_IMETHODIMP
|
||||
nsDragService::GetNumDropItems(PRUint32* aNumItems)
|
||||
{
|
||||
*aNumItems = 0;
|
||||
|
||||
|
||||
// first check to see if we have a number of items cached
|
||||
if (mDataItems) {
|
||||
mDataItems->Count(aNumItems);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// if there is a clipboard and there is something on it, then there is at least 1 item
|
||||
NSArray* clipboardTypes = [globalDragPboard types];
|
||||
if (globalDragPboard && [clipboardTypes count] > 0)
|
||||
@ -330,3 +466,11 @@ nsDragService::GetNumDropItems(PRUint32* aNumItems)
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDragService::EndDragSession(PRBool aDoneDrag)
|
||||
{
|
||||
mDataItems = nsnull;
|
||||
return nsBaseDragService::EndDragSession(aDoneDrag);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user