Bug 318559 - MouseTrailer holds XPCOM references past shutdown, r=ere sr=roc

This commit is contained in:
benjamin%smedbergs.us 2006-02-22 21:08:40 +00:00
Родитель 1fccd9aa39
Коммит 18d946ce0e
3 изменённых файлов: 50 добавлений и 33 удалений

Просмотреть файл

@ -92,8 +92,6 @@ DEFINE_GUID(IID_IActiveIMMMessagePumpOwner,
IActiveIMMApp* nsToolkit::gAIMMApp = NULL;
PRInt32 nsToolkit::gAIMMCount = 0;
MouseTrailer MouseTrailer::mSingleton;
#if !defined(MOZ_STATIC_COMPONENT_LIBS) && !defined(MOZ_ENABLE_LIBXUL)
//
// Dll entry point. Keep the dll instance
@ -695,6 +693,8 @@ NS_CreateWindowEx nsToolkit::mCreateWindowEx = nsCreateWindowEx;
NS_RegisterClass nsToolkit::mRegisterClass = nsRegisterClass;
NS_UnregisterClass nsToolkit::mUnregisterClass = nsUnregisterClass;
MouseTrailer* nsToolkit::gMouseTrailer;
#ifndef WINCE
NS_SHGetPathFromIDList nsToolkit::mSHGetPathFromIDList = nsSHGetPathFromIDList;
NS_SHBrowseForFolder nsToolkit::mSHBrowseForFolder = nsSHBrowseForFolder;
@ -751,6 +751,8 @@ nsToolkit::nsToolkit()
#if defined(MOZ_STATIC_COMPONENT_LIBS) || defined (WINCE)
nsToolkit::Startup(GetModuleHandle(NULL));
#endif
gMouseTrailer = new MouseTrailer();
}
@ -784,6 +786,12 @@ nsToolkit::~nsToolkit()
// Remove reference to cached event queue
gEventQueueService = nsnull;
if (gMouseTrailer) {
gMouseTrailer->DestroyTimer();
delete gMouseTrailer;
gMouseTrailer = nsnull;
}
// Unhook the filter used to determine when
// the user is moving a top-level window.
#ifndef WINCE
@ -1212,46 +1220,48 @@ void MouseTrailer::DestroyTimer()
//-------------------------------------------------------------------------
void MouseTrailer::TimerProc(nsITimer* aTimer, void* aClosure)
{
MouseTrailer *mtrailer = nsToolkit::gMouseTrailer;
NS_ASSERTION(mtrailer, "MouseTrailer still firing after deletion!");
// Check to see if we are in mouse capture mode,
// Once capture ends we could still get back one more timer event.
// Capture could end outside our window.
// Also, for some reason when the mouse is on the frame it thinks that
// it is inside the window that is being captured.
if (mSingleton.mCaptureWindow) {
if (mSingleton.mCaptureWindow != mSingleton.mMouseTrailerWindow) {
if (mtrailer->mCaptureWindow) {
if (mtrailer->mCaptureWindow != mtrailer->mMouseTrailerWindow) {
return;
}
} else {
if (mSingleton.mIsInCaptureMode) {
if (mtrailer->mIsInCaptureMode) {
// mMouseTrailerWindow could be bad from rolling over the frame, so clear
// it if we were capturing and now this is the first timer callback
// since we canceled the capture
mSingleton.mMouseTrailerWindow = nsnull;
mSingleton.mIsInCaptureMode = PR_FALSE;
mtrailer->mMouseTrailerWindow = nsnull;
mtrailer->mIsInCaptureMode = PR_FALSE;
return;
}
}
if (mSingleton.mMouseTrailerWindow && ::IsWindow(mSingleton.mMouseTrailerWindow)) {
if (mtrailer->mMouseTrailerWindow && ::IsWindow(mtrailer->mMouseTrailerWindow)) {
POINT mp;
DWORD pos = ::GetMessagePos();
mp.x = GET_X_LPARAM(pos);
mp.y = GET_Y_LPARAM(pos);
HWND mouseWnd = ::WindowFromPoint(mp);
if (mSingleton.mMouseTrailerWindow != mouseWnd) {
if (mtrailer->mMouseTrailerWindow != mouseWnd) {
#ifndef WINCE
// Notify someone that a mouse exit happened.
PostMessage(mSingleton.mMouseTrailerWindow, WM_MOUSELEAVE, NULL, NULL);
PostMessage(mtrailer->mMouseTrailerWindow, WM_MOUSELEAVE, NULL, NULL);
#endif
// we are out of this window, destroy timer
mSingleton.DestroyTimer();
mSingleton.mMouseTrailerWindow = nsnull;
mtrailer->DestroyTimer();
mtrailer->mMouseTrailerWindow = nsnull;
}
} else {
mSingleton.DestroyTimer();
mSingleton.mMouseTrailerWindow = nsnull;
mtrailer->DestroyTimer();
mtrailer->mMouseTrailerWindow = nsnull;
}
}

Просмотреть файл

@ -50,6 +50,7 @@
struct MethodInfo;
class nsIEventQueue;
class MouseTrailer;
// we used to use MAX_PATH
// which works great for one file
@ -138,6 +139,8 @@ public:
#ifndef WINCE
static NS_SHBrowseForFolder mSHBrowseForFolder;
#endif
static MouseTrailer *gMouseTrailer;
};
#define WM_CALLMETHOD (WM_USER+1)
@ -160,8 +163,6 @@ class nsWindow;
class MouseTrailer
{
public:
static MouseTrailer &GetSingleton() { return mSingleton; }
HWND GetMouseTrailerWindow() { return mMouseTrailerWindow; }
HWND GetCaptureWindow() { return mCaptureWindow; }
@ -170,18 +171,15 @@ public:
void Disable() { mEnabled = PR_FALSE; DestroyTimer(); }
void Enable() { mEnabled = PR_TRUE; CreateTimer(); }
void DestroyTimer();
~MouseTrailer();
private:
MouseTrailer();
~MouseTrailer();
private:
nsresult CreateTimer();
static void TimerProc(nsITimer* aTimer, void* aClosure);
// Global nsToolkit Instance
static MouseTrailer mSingleton;
// Information for mouse enter/exit events
HWND mMouseTrailerWindow;
HWND mCaptureWindow;

Просмотреть файл

@ -789,11 +789,13 @@ nsWindow::~nsWindow()
gCurrentWindow = nsnull;
}
if (MouseTrailer::GetSingleton().GetMouseTrailerWindow() == mWnd) {
MouseTrailer::GetSingleton().DestroyTimer();
}
if (MouseTrailer::GetSingleton().GetCaptureWindow() == mWnd) {
MouseTrailer::GetSingleton().SetCaptureWindow(nsnull);
MouseTrailer* mtrailer = nsToolkit::gMouseTrailer;
if (mtrailer) {
if (mtrailer->GetMouseTrailerWindow() == mWnd)
mtrailer->DestroyTimer();
if (mtrailer->GetCaptureWindow() == mWnd)
mtrailer->SetCaptureWindow(nsnull);
}
// If the widget was released without calling Destroy() then the native
@ -834,11 +836,16 @@ nsWindow::~nsWindow()
NS_METHOD nsWindow::CaptureMouse(PRBool aCapture)
{
if (!nsToolkit::gMouseTrailer) {
NS_ERROR("nsWindow::CaptureMouse called after nsToolkit destroyed");
return NS_OK;
}
if (aCapture) {
MouseTrailer::GetSingleton().SetCaptureWindow(mWnd);
nsToolkit::gMouseTrailer->SetCaptureWindow(mWnd);
::SetCapture(mWnd);
} else {
MouseTrailer::GetSingleton().SetCaptureWindow(NULL);
nsToolkit::gMouseTrailer->SetCaptureWindow(NULL);
::ReleaseCapture();
}
mIsInMouseCapture = aCapture;
@ -5933,10 +5940,11 @@ PRBool nsWindow::DispatchMouseEvent(PRUint32 aEventType, WPARAM wParam, LPARAM l
// call the event callback
if (nsnull != mEventCallback) {
MouseTrailer::GetSingleton().Disable();
if (nsToolkit::gMouseTrailer)
nsToolkit::gMouseTrailer->Disable();
if (aEventType == NS_MOUSE_MOVE) {
if (!mIsInMouseCapture) {
MouseTrailer::GetSingleton().SetMouseTrailerWindow(mWnd);
if (nsToolkit::gMouseTrailer && !mIsInMouseCapture) {
nsToolkit::gMouseTrailer->SetMouseTrailerWindow(mWnd);
}
nsRect rect;
GetBounds(rect);
@ -5964,7 +5972,8 @@ PRBool nsWindow::DispatchMouseEvent(PRUint32 aEventType, WPARAM wParam, LPARAM l
result = DispatchWindowEvent(&event);
MouseTrailer::GetSingleton().Enable();
if (nsToolkit::gMouseTrailer)
nsToolkit::gMouseTrailer->Enable();
// Release the widget with NS_IF_RELEASE() just in case
// the context menu key code in nsEventListenerManager::HandleEvent()