Fixing COM refcounting problems by removing |mDataObject| from the drag target. Also removing the
cached drag session. r=pchen/a=hyatt. bug# 54803 git-svn-id: svn://10.0.0.236/trunk@80624 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -211,7 +211,7 @@ NS_IMETHODIMP nsDragService::SetIDataObject (IDataObject * aDataObj)
|
||||
// the IDataObject that is being dragged
|
||||
NS_IF_RELEASE(mDataObject);
|
||||
mDataObject = aDataObj;
|
||||
NS_ADDREF(mDataObject);
|
||||
NS_IF_ADDREF(mDataObject);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -281,7 +281,6 @@ NS_IMETHODIMP nsDragService::IsDataFlavorSupported(const char *aDataFlavor, PRBo
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// IsCollectionObject
|
||||
@@ -310,3 +309,20 @@ nsDragService :: IsCollectionObject ( IDataObject* inDataObj )
|
||||
return isCollection;
|
||||
|
||||
} // IsCollectionObject
|
||||
|
||||
|
||||
//
|
||||
// EndDragSession
|
||||
//
|
||||
// Override the default to make sure that we release the data object when the drag ends. It
|
||||
// seems that OLE doesn't like to let apps quit w/out crashing when we're still holding onto
|
||||
// their data
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsDragService::EndDragSession ()
|
||||
{
|
||||
nsBaseDragService::EndDragSession();
|
||||
NS_IF_RELEASE(mDataObject);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ public:
|
||||
NS_IMETHOD GetData (nsITransferable * aTransferable, PRUint32 anItem);
|
||||
NS_IMETHOD GetNumDropItems (PRUint32 * aNumItems);
|
||||
NS_IMETHOD IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval);
|
||||
NS_IMETHOD EndDragSession ( ) ;
|
||||
|
||||
// native impl.
|
||||
NS_IMETHOD SetIDataObject (IDataObject * aDataObj);
|
||||
|
||||
@@ -59,12 +59,9 @@ static POINTL gDragLastPoint;
|
||||
// construction
|
||||
//-----------------------------------------------------
|
||||
nsNativeDragTarget::nsNativeDragTarget(nsIWidget * aWnd)
|
||||
: m_cRef(0), mWindow(aWnd)
|
||||
{
|
||||
m_cRef = 0;
|
||||
|
||||
mWindow = aWnd; // don't ref count this
|
||||
mHWnd = (HWND)mWindow->GetNativeData(NS_NATIVE_WINDOW);
|
||||
mDataObj = NULL;
|
||||
|
||||
/*
|
||||
* Create/Get the DragService that we have implemented
|
||||
@@ -72,11 +69,6 @@ nsNativeDragTarget::nsNativeDragTarget(nsIWidget * aWnd)
|
||||
nsresult rv = nsServiceManager::GetService(kCDragServiceCID,
|
||||
kIDragServiceIID,
|
||||
(nsISupports**)&mDragService);
|
||||
if (NS_OK == rv) {
|
||||
mDragSession = do_QueryInterface(mDragService);
|
||||
} else {
|
||||
mDragSession = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -85,9 +77,7 @@ nsNativeDragTarget::nsNativeDragTarget(nsIWidget * aWnd)
|
||||
//-----------------------------------------------------
|
||||
nsNativeDragTarget::~nsNativeDragTarget()
|
||||
{
|
||||
mDragSession = do_QueryInterface(0);
|
||||
nsServiceManager::ReleaseService(kCDragServiceCID, mDragService);
|
||||
NS_IF_RELEASE(mDataObj);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
@@ -125,15 +115,14 @@ STDMETHODIMP_(ULONG) nsNativeDragTarget::Release(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
void nsNativeDragTarget::GetGeckoDragAction(DWORD grfKeyState, LPDWORD pdwEffect, PRUint32 * aGeckoAction)
|
||||
{
|
||||
|
||||
//Check if we can link from this data object as well.
|
||||
//-----------------------------------------------------
|
||||
void nsNativeDragTarget::GetGeckoDragAction(LPDATAOBJECT pData, DWORD grfKeyState, LPDWORD pdwEffect, PRUint32 * aGeckoAction)
|
||||
{
|
||||
// Check if we can link from this data object as well.
|
||||
PRBool canLink = PR_FALSE;
|
||||
if (NULL != mDataObj) {
|
||||
canLink = (S_OK == ::OleQueryLinkFromData(mDataObj)?PR_TRUE:PR_FALSE);
|
||||
}
|
||||
if ( pData )
|
||||
canLink = (S_OK == ::OleQueryLinkFromData(pData) ? PR_TRUE : PR_FALSE);
|
||||
|
||||
// Default is move if we can, in fact drop here.
|
||||
*pdwEffect = DROPEFFECT_MOVE;
|
||||
@@ -195,17 +184,20 @@ void nsNativeDragTarget::DispatchDragDropEvent(PRUint32 aEventType,
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
void nsNativeDragTarget::ProcessDrag(PRUint32 aEventType,
|
||||
void nsNativeDragTarget::ProcessDrag(LPDATAOBJECT pData,
|
||||
PRUint32 aEventType,
|
||||
DWORD grfKeyState,
|
||||
POINTL pt,
|
||||
DWORD* pdwEffect)
|
||||
{
|
||||
// Before dispatching the event make sure we have the correct drop action set
|
||||
PRUint32 geckoAction;
|
||||
GetGeckoDragAction(grfKeyState, pdwEffect, &geckoAction);
|
||||
GetGeckoDragAction(pData, grfKeyState, pdwEffect, &geckoAction);
|
||||
|
||||
// Set the current action into the Gecko specific type
|
||||
mDragSession->SetDragAction(geckoAction);
|
||||
nsCOMPtr<nsIDragSession> currSession;
|
||||
mDragService->GetCurrentSession ( getter_AddRefs(currSession) );
|
||||
currSession->SetDragAction(geckoAction);
|
||||
|
||||
// Dispatch the event into Gecko
|
||||
DispatchDragDropEvent(aEventType, pt);
|
||||
@@ -214,18 +206,20 @@ void nsNativeDragTarget::ProcessDrag(PRUint32 aEventType,
|
||||
// the data memeber should have been set by who ever handled the
|
||||
// nsGUIEvent or nsIDOMEvent
|
||||
PRBool canDrop;
|
||||
mDragSession->GetCanDrop(&canDrop);
|
||||
if (!canDrop) {
|
||||
currSession->GetCanDrop(&canDrop);
|
||||
if (!canDrop)
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
}
|
||||
|
||||
// Clear the cached value
|
||||
mDragSession->SetCanDrop(PR_FALSE);
|
||||
currSession->SetCanDrop(PR_FALSE);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------
|
||||
// IDropTarget methods
|
||||
//-----------------------------------------------------
|
||||
|
||||
|
||||
STDMETHODIMP nsNativeDragTarget::DragEnter(LPDATAOBJECT pIDataSource,
|
||||
DWORD grfKeyState,
|
||||
POINTL pt,
|
||||
@@ -239,27 +233,21 @@ STDMETHODIMP nsNativeDragTarget::DragEnter(LPDATAOBJECT pIDataSource,
|
||||
// outside app).
|
||||
mDragService->StartDragSession();
|
||||
|
||||
// We have a new IDataObject, release the old one, if necessary and
|
||||
// keep a pointer to the new on
|
||||
NS_IF_RELEASE(mDataObj);
|
||||
mDataObj = pIDataSource;
|
||||
NS_ADDREF(mDataObj);
|
||||
|
||||
// Set the native data object into drag service
|
||||
//
|
||||
// This cast is ok because in the constructor we created a
|
||||
// the actual implementation we wanted, so we know this is
|
||||
// a nsDragService
|
||||
// a nsDragService. It should be a private interface, though.
|
||||
nsDragService * winDragService = NS_STATIC_CAST(nsDragService *, mDragService);
|
||||
|
||||
// Set the native data object into drag service
|
||||
winDragService->SetIDataObject(pIDataSource);
|
||||
|
||||
// Now process the native drag state and then dispatch the event
|
||||
ProcessDrag(NS_DRAGDROP_ENTER, grfKeyState, pt, pdwEffect);
|
||||
ProcessDrag(pIDataSource, NS_DRAGDROP_ENTER, grfKeyState, pt, pdwEffect);
|
||||
|
||||
return S_OK;
|
||||
} else {
|
||||
return ResultFromScode(E_FAIL);
|
||||
}
|
||||
else
|
||||
return ResultFromScode(E_FAIL);
|
||||
}
|
||||
|
||||
|
||||
@@ -271,77 +259,58 @@ STDMETHODIMP nsNativeDragTarget::DragOver(DWORD grfKeyState,
|
||||
if (DRAG_DEBUG) printf("DragOver\n");
|
||||
if (mDragService) {
|
||||
// Now process the native drag state and then dispatch the event
|
||||
ProcessDrag(NS_DRAGDROP_OVER, grfKeyState, pt, pdwEffect);
|
||||
ProcessDrag(nsnull, NS_DRAGDROP_OVER, grfKeyState, pt, pdwEffect);
|
||||
return S_OK;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
return ResultFromScode(E_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------
|
||||
STDMETHODIMP nsNativeDragTarget::DragLeave() {
|
||||
|
||||
if (DRAG_DEBUG) printf("DragLeave\n");
|
||||
if (mDragService) {
|
||||
|
||||
// tell the drag service that we're done with it
|
||||
mDragService->EndDragSession();
|
||||
|
||||
// dispatch the event into Gecko
|
||||
DispatchDragDropEvent(NS_DRAGDROP_EXIT, gDragLastPoint);
|
||||
|
||||
// tell the drag service that we're done with it
|
||||
mDragService->EndDragSession();
|
||||
return S_OK;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
return ResultFromScode(E_FAIL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------
|
||||
STDMETHODIMP nsNativeDragTarget::Drop(LPDATAOBJECT pIDataSource,
|
||||
STDMETHODIMP nsNativeDragTarget::Drop(LPDATAOBJECT pData,
|
||||
DWORD grfKeyState,
|
||||
POINTL aPT,
|
||||
LPDWORD pdwEffect)
|
||||
{
|
||||
if (DRAG_DEBUG) printf("Drop mDataObj: %p pIDataSource: %p\n", mDataObj, pIDataSource);
|
||||
|
||||
if (mDragService) {
|
||||
if (mDataObj != NULL) {
|
||||
// Make sure we have a valid IDataObject and
|
||||
// that it matches the one we got on the drag enter
|
||||
if (pIDataSource == mDataObj) {
|
||||
// We have already add ref'ed it
|
||||
//mDataObj = pIDataSource;
|
||||
//NS_ADDREF(mDataObj);
|
||||
} else {
|
||||
// Boy this is weird, they should be the same
|
||||
// XXX should assert here,
|
||||
// but instead we will just recover....
|
||||
NS_IF_RELEASE(mDataObj);
|
||||
mDataObj = pIDataSource;
|
||||
NS_ADDREF(mDataObj);
|
||||
}
|
||||
} else {
|
||||
// Boy this is weird, it shouldn't be null
|
||||
// XXX should assert here
|
||||
}
|
||||
|
||||
// Set the native data object into the drag service
|
||||
//
|
||||
// This cast is ok because in the constructor we created a
|
||||
// the actual implementation we wanted, so we know this is
|
||||
// a nsDragService
|
||||
// a nsDragService (but it should still be a private interface)
|
||||
nsDragService * winDragService = NS_STATIC_CAST(nsDragService *, mDragService);
|
||||
winDragService->SetIDataObject(pData);
|
||||
|
||||
// Set the native data object into drage service
|
||||
winDragService->SetIDataObject(pIDataSource);
|
||||
|
||||
// Now process the native drag state and then dispatch the event
|
||||
ProcessDrag(NS_DRAGDROP_DROP, grfKeyState, aPT, pdwEffect);
|
||||
// Now process the native drag state and then dispatch the event
|
||||
ProcessDrag(pData, NS_DRAGDROP_DROP, grfKeyState, aPT, pdwEffect);
|
||||
|
||||
// tell the drag service we're done with the session
|
||||
mDragService->EndDragSession();
|
||||
return S_OK;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
return ResultFromScode(E_FAIL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -77,23 +77,19 @@ class nsNativeDragTarget : public IDropTarget
|
||||
POINTL point, DWORD* pEffect);
|
||||
|
||||
protected:
|
||||
// methods
|
||||
void GetGeckoDragAction(DWORD grfKeyState, LPDWORD pdwEffect, PRUint32 * aGeckoAction);
|
||||
void ProcessDrag(PRUint32 aEventType,
|
||||
DWORD grfKeyState,
|
||||
POINTL pt,
|
||||
DWORD* pdwEffect);
|
||||
|
||||
void GetGeckoDragAction ( LPDATAOBJECT pData, DWORD grfKeyState, LPDWORD pdwEffect, PRUint32 * aGeckoAction );
|
||||
void ProcessDrag ( LPDATAOBJECT pData, PRUint32 aEventType, DWORD grfKeyState,
|
||||
POINTL pt, DWORD* pdwEffect );
|
||||
void DispatchDragDropEvent(PRUint32 aType, POINTL pt);
|
||||
|
||||
// Native Stuff
|
||||
ULONG m_cRef; // reference count
|
||||
HWND mHWnd;
|
||||
IDataObject * mDataObj;
|
||||
|
||||
// Gecko Stuff
|
||||
nsIWidget * mWindow;
|
||||
nsIDragService * mDragService;
|
||||
nsCOMPtr<nsIDragSession> mDragSession;
|
||||
};
|
||||
|
||||
#endif // _nsNativeDragTarget_h_
|
||||
|
||||
Reference in New Issue
Block a user