зеркало из https://github.com/mozilla/pjs.git
Dragging links to desktop creates internet shortcut files. bug#37410, r=pavlov
This commit is contained in:
Родитель
905f0087f8
Коммит
30b99ea6b0
|
@ -407,7 +407,15 @@ nsDataObj :: GetFileDescriptorInternetShortcut ( FORMATETC& aFE, STGMEDIUM& aSTG
|
|||
if ( fileGroupDescHand ) {
|
||||
LPFILEGROUPDESCRIPTOR fileGroupDesc = NS_REINTERPRET_CAST(LPFILEGROUPDESCRIPTOR, ::GlobalLock(fileGroupDescHand));
|
||||
|
||||
char* url = "http://www.dvdresource.com"; // TEMP!
|
||||
#if 0
|
||||
nsAutoString url;
|
||||
if ( NS_FAILED(ExtractURL(url)) )
|
||||
return E_OUTOFMEMORY;
|
||||
char* urlStr = url.ToNewCString(); // XXX what about unicode urls?!?!
|
||||
if ( !urlStr )
|
||||
return E_OUTOFMEMORY;
|
||||
#endif
|
||||
char* urlStr = strdup("TEMP URL FILENAME");
|
||||
|
||||
// one file in the file descriptor block
|
||||
fileGroupDesc->cItems = 1;
|
||||
|
@ -416,12 +424,15 @@ nsDataObj :: GetFileDescriptorInternetShortcut ( FORMATETC& aFE, STGMEDIUM& aSTG
|
|||
// create the filename string -- |.URL| extensions imply an internet shortcut file. Make
|
||||
// sure the filename isn't too long as to blow out the array, and still have enough room
|
||||
// for the |.URL| suffix.
|
||||
int urlLength = strlen(url) > MAX_PATH - 5 ? MAX_PATH - 5 : strlen(url);
|
||||
url[urlLength] = nsnull;
|
||||
sprintf(fileGroupDesc->fgd[0].cFileName, "%s.URL", url);
|
||||
int urlLength = strlen(urlStr);
|
||||
int trimmedLen = urlLength > MAX_PATH - 5 ? MAX_PATH - 5 : urlLength;
|
||||
urlStr[trimmedLen] = nsnull;
|
||||
sprintf(fileGroupDesc->fgd[0].cFileName, "%s.URL", urlStr);
|
||||
|
||||
nsMemory::Free(urlStr);
|
||||
::GlobalUnlock ( fileGroupDescHand );
|
||||
aSTG.hGlobal = fileGroupDescHand;
|
||||
aSTG.tymed = TYMED_HGLOBAL;
|
||||
}
|
||||
else
|
||||
result = E_OUTOFMEMORY;
|
||||
|
@ -442,20 +453,27 @@ nsDataObj :: GetFileContentsInternetShortcut ( FORMATETC& aFE, STGMEDIUM& aSTG )
|
|||
{
|
||||
HRESULT result = S_OK;
|
||||
|
||||
char* url = "foopy"; // TEMP!
|
||||
|
||||
nsAutoString url;
|
||||
if ( NS_FAILED(ExtractURL(url)) )
|
||||
return E_OUTOFMEMORY;
|
||||
char* urlStr = url.ToNewCString(); // XXX what about unicode urls?!?!
|
||||
if ( !urlStr )
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
// setup format structure
|
||||
FORMATETC fmetc = { 0, NULL, DVASPECT_CONTENT, 0, TYMED_HGLOBAL };
|
||||
fmetc.cfFormat = RegisterClipboardFormat ( CFSTR_FILECONTENTS );
|
||||
|
||||
// create a global memory area and build up the file contents w/in it
|
||||
static const char* shortcutPrefix = "[InternetShortcut]\nURL=";
|
||||
HGLOBAL hGlobalMemory = ::GlobalAlloc(GMEM_SHARE, strlen(shortcutPrefix) + strlen(url) + 1);
|
||||
static int prefixLen = strlen(shortcutPrefix);
|
||||
HGLOBAL hGlobalMemory = ::GlobalAlloc(GMEM_SHARE, prefixLen + strlen(urlStr) + 1);
|
||||
if ( hGlobalMemory ) {
|
||||
char* contents = NS_REINTERPRET_CAST(char*, ::GlobalLock(hGlobalMemory));
|
||||
sprintf( contents, "%s%s", shortcutPrefix, url );
|
||||
sprintf( contents, "%s%s", shortcutPrefix, urlStr );
|
||||
::GlobalUnlock(hGlobalMemory);
|
||||
aSTG.hGlobal = hGlobalMemory;
|
||||
aSTG.tymed = TYMED_HGLOBAL;
|
||||
}
|
||||
else
|
||||
result = E_OUTOFMEMORY;
|
||||
|
@ -663,3 +681,31 @@ void nsDataObj::SetTransferable(nsITransferable * aTransferable)
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ExtractURL
|
||||
//
|
||||
// Roots around in the transferable for the appropriate flavor that indicates
|
||||
// a url and pulls it out. Used mostly for creating internet shortcuts on the desktop.
|
||||
//
|
||||
nsresult
|
||||
nsDataObj :: ExtractURL ( nsString & outURL )
|
||||
{
|
||||
NS_ASSERTION ( mTransferable, "We'd don't have a good transferable" );
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
PRUint32 len = 0;
|
||||
nsCOMPtr<nsISupports> genericURL;
|
||||
if ( NS_SUCCEEDED(mTransferable->GetTransferData(kURLMime, getter_AddRefs(genericURL), &len)) ) {
|
||||
nsCOMPtr<nsISupportsWString> urlObject ( do_QueryInterface(genericURL) );
|
||||
if ( urlObject ) {
|
||||
nsXPIDLString url;
|
||||
urlObject->GetData ( getter_Copies(url) );
|
||||
outURL = url;
|
||||
rv = NS_OK;
|
||||
}
|
||||
} // if found flavor
|
||||
|
||||
return rv;
|
||||
|
||||
} // ExtractURL
|
|
@ -138,6 +138,8 @@ class nsDataObj : public IDataObject
|
|||
virtual HRESULT GetFileDescriptorInternetShortcut ( FORMATETC& aFE, STGMEDIUM& aSTG ) ;
|
||||
virtual HRESULT GetFileContentsInternetShortcut ( FORMATETC& aFE, STGMEDIUM& aSTG ) ;
|
||||
|
||||
nsresult ExtractURL ( nsString & outURL ) ;
|
||||
|
||||
nsString mStringData;
|
||||
|
||||
BOOL FormatsMatch(const FORMATETC& source, const FORMATETC& target) const;
|
||||
|
|
|
@ -65,33 +65,47 @@ nsDragService::~nsDragService()
|
|||
NS_IMETHODIMP nsDragService::InvokeDragSession (nsIDOMNode *aDOMNode, nsISupportsArray * anArrayTransferables, nsIScriptableRegion * aRegion, PRUint32 aActionType)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 cnt;
|
||||
rv = anArrayTransferables->Count(&cnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (cnt == 0) {
|
||||
PRUint32 numItemsToDrag = 0;
|
||||
rv = anArrayTransferables->Count(&numItemsToDrag);
|
||||
if ( !numItemsToDrag )
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// The clipboard class contains some static utility methods
|
||||
// that we can use to create an IDataObject from the transferable
|
||||
|
||||
nsDataObjCollection * dataObjCollection = new nsDataObjCollection();
|
||||
IDataObject * dataObj = nsnull;
|
||||
PRUint32 i;
|
||||
for (i=0;i<cnt;i++) {
|
||||
// if we're dragging more than one item, we need to create a "collection" object to fake out
|
||||
// the OS. This collection contains one |IDataObject| for each transerable. If there is just
|
||||
// the one (most cases), only pass around the native |IDataObject|.
|
||||
IDataObject* itemToDrag = nsnull;
|
||||
if ( numItemsToDrag > 1 ) {
|
||||
nsDataObjCollection * dataObjCollection = new nsDataObjCollection();
|
||||
IDataObject* dataObj = nsnull;
|
||||
for ( PRUint32 i=0; i<numItemsToDrag; ++i ) {
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
anArrayTransferables->GetElementAt(i, getter_AddRefs(supports));
|
||||
nsCOMPtr<nsITransferable> trans(do_QueryInterface(supports));
|
||||
if ( trans ) {
|
||||
if ( NS_SUCCEEDED(nsClipboard::CreateNativeDataObject(trans, &dataObj)) ) {
|
||||
dataObjCollection->AddDataObject(dataObj);
|
||||
NS_IF_RELEASE(dataObj);
|
||||
}
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
itemToDrag = NS_STATIC_CAST ( IDataObject*, dataObjCollection );
|
||||
} // if dragging multiple items
|
||||
else {
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
anArrayTransferables->GetElementAt(i, getter_AddRefs(supports));
|
||||
anArrayTransferables->GetElementAt(0, getter_AddRefs(supports));
|
||||
nsCOMPtr<nsITransferable> trans(do_QueryInterface(supports));
|
||||
if ( trans ) {
|
||||
nsClipboard::CreateNativeDataObject(trans, &dataObj);
|
||||
dataObjCollection->AddDataObject(dataObj);
|
||||
NS_IF_RELEASE(dataObj);
|
||||
if ( NS_FAILED(nsClipboard::CreateNativeDataObject(trans, &itemToDrag)) )
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
StartInvokingDragSession((IDataObject *)dataObjCollection, aActionType);
|
||||
|
||||
return NS_OK;
|
||||
} // else dragging a single object
|
||||
|
||||
return StartInvokingDragSession ( itemToDrag, aActionType );
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
@ -101,9 +115,10 @@ NS_IMETHODIMP nsDragService::StartInvokingDragSession(IDataObject * aDataObj, PR
|
|||
// implements the IDataObject interface (for OLE)
|
||||
NS_IF_RELEASE(mNativeDragSrc);
|
||||
mNativeDragSrc = (IDropSource *)new nsNativeDragSource();
|
||||
if (nsnull != mNativeDragSrc) {
|
||||
mNativeDragSrc->AddRef();
|
||||
}
|
||||
if ( !mNativeDragSrc )
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mNativeDragSrc->AddRef();
|
||||
|
||||
// Now figure out what the native drag effect should be
|
||||
DWORD dropRes;
|
||||
|
@ -118,7 +133,7 @@ NS_IMETHODIMP nsDragService::StartInvokingDragSession(IDataObject * aDataObj, PR
|
|||
effects |= DROPEFFECT_LINK;
|
||||
}
|
||||
|
||||
mDragAction = aActionType;
|
||||
mDragAction = aActionType; //XXX not sure why we bother to cache this, it can change during the drag
|
||||
mDoingDrag = PR_TRUE;
|
||||
|
||||
// Call the native D&D method
|
||||
|
@ -132,12 +147,7 @@ NS_IMETHODIMP nsDragService::StartInvokingDragSession(IDataObject * aDataObj, PR
|
|||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsDragService::GetNumDropItems (PRUint32 * aNumItems)
|
||||
{
|
||||
// First check to see if the mDataObject is is Collection of IDataObjects
|
||||
UINT format = nsClipboard::GetFormat(MULTI_MIME);
|
||||
FORMATETC fe;
|
||||
SET_FORMATETC(fe, format, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL);
|
||||
if ( mDataObject->QueryGetData(&fe) == S_OK ) {
|
||||
// If it is the get the number of items in the collection
|
||||
if ( IsCollectionObject(mDataObject) ) {
|
||||
nsDataObjCollection * dataObjCol = NS_STATIC_CAST(nsDataObjCollection*, mDataObject);
|
||||
if ( dataObjCol )
|
||||
*aNumItems = dataObjCol->GetNumDataObjects();
|
||||
|
@ -170,34 +180,25 @@ NS_IMETHODIMP nsDragService::GetData (nsITransferable * aTransferable, PRUint32
|
|||
// This typcially happens on a drop, the target would be asking
|
||||
// for it's transferable to be filled in
|
||||
// Use a static clipboard utility method for this
|
||||
if ( nsnull == mDataObject ) {
|
||||
if ( !mDataObject )
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// First check to see if the mDataObject is is Collection of IDataObjects
|
||||
UINT format = nsClipboard::GetFormat(MULTI_MIME);
|
||||
FORMATETC fe;
|
||||
SET_FORMATETC(fe, format, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL);
|
||||
|
||||
// if it is a single object then get the data for it
|
||||
if (S_OK != mDataObject->QueryGetData(&fe)) {
|
||||
// Since there is only one object, they better be asking for item "0"
|
||||
if (anItem == 0) {
|
||||
return nsClipboard::GetDataFromDataObject(mDataObject, anItem, nsnull, aTransferable);
|
||||
} else {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
nsDataObjCollection * dataObjCol = NS_STATIC_CAST(nsDataObjCollection*, mDataObject);
|
||||
if ( dataObjCol ) {
|
||||
if ( IsCollectionObject(mDataObject) ) {
|
||||
// multiple items, use |anItem| as an index into our collection
|
||||
nsDataObjCollection * dataObjCol = NS_STATIC_CAST(nsDataObjCollection*, mDataObject);
|
||||
PRUint32 cnt = dataObjCol->GetNumDataObjects();
|
||||
if (anItem >= 0 && anItem < cnt) {
|
||||
IDataObject * dataObj = dataObjCol->GetDataObjectAt(anItem);
|
||||
return nsClipboard::GetDataFromDataObject(dataObj, 0, nsnull, aTransferable);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
// Since there is only one object, they better be asking for item "0"
|
||||
if (anItem == 0)
|
||||
return nsClipboard::GetDataFromDataObject(mDataObject, anItem, nsnull, aTransferable);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -226,13 +227,10 @@ NS_IMETHODIMP nsDragService::IsDataFlavorSupported(const char *aDataFlavor, PRBo
|
|||
|
||||
*_retval = PR_FALSE;
|
||||
|
||||
// Check to see if the mDataObject is a collection of IDataObjects or just a
|
||||
// single (which would be the case if something came from an external app).
|
||||
FORMATETC fe;
|
||||
UINT format = nsClipboard::GetFormat(MULTI_MIME);
|
||||
SET_FORMATETC(fe, format, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL);
|
||||
|
||||
if ( mDataObject->QueryGetData(&fe) == S_OK ) {
|
||||
UINT format = 0;
|
||||
|
||||
if ( IsCollectionObject(mDataObject) ) {
|
||||
// We know we have one of our special collection objects.
|
||||
format = nsClipboard::GetFormat(aDataFlavor);
|
||||
SET_FORMATETC(fe, format, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL | TYMED_FILE | TYMED_GDI);
|
||||
|
@ -278,3 +276,32 @@ NS_IMETHODIMP nsDragService::GetCurrentSession (nsIDragSession ** aSession)
|
|||
NS_ADDREF(*aSession);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// IsCollectionObject
|
||||
//
|
||||
// Determine if this is a single |IDataObject| or one of our private collection
|
||||
// objects. We know the difference because our collection object will respond to supporting
|
||||
// the private |MULTI_MIME| format.
|
||||
//
|
||||
PRBool
|
||||
nsDragService :: IsCollectionObject ( IDataObject* inDataObj )
|
||||
{
|
||||
PRBool isCollection = PR_FALSE;
|
||||
|
||||
// setup the format object to ask for the MULTI_MIME format. We only need to do this once
|
||||
static UINT sFormat = 0;
|
||||
static FORMATETC sFE;
|
||||
if ( !sFormat ) {
|
||||
sFormat = nsClipboard::GetFormat(MULTI_MIME);
|
||||
SET_FORMATETC(sFE, sFormat, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL);
|
||||
}
|
||||
|
||||
// ask the object if it supports it. If yes, we have a collection object
|
||||
if ( inDataObj->QueryGetData(&sFE) == S_OK )
|
||||
isCollection = PR_TRUE;
|
||||
|
||||
return isCollection;
|
||||
|
||||
} // IsCollectionObject
|
|
@ -54,6 +54,10 @@ public:
|
|||
NS_IMETHOD StartInvokingDragSession(IDataObject * aDataObj, PRUint32 aActionType);
|
||||
|
||||
protected:
|
||||
|
||||
// determine if we have a single data object or one of our private collections
|
||||
PRBool IsCollectionObject ( IDataObject* inDataObj ) ;
|
||||
|
||||
IDropSource * mNativeDragSrc;
|
||||
nsNativeDragTarget * mNativeDragTarget;
|
||||
IDataObject * mDataObject;
|
||||
|
|
Загрузка…
Ссылка в новой задаче