зеркало из https://github.com/mozilla/gecko-dev.git
Bug 318559 - MouseTrailer holds XPCOM references past shutdown, r=ere sr=roc
This commit is contained in:
Родитель
1fccd9aa39
Коммит
18d946ce0e
|
@ -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()
|
||||
|
|
Загрузка…
Ссылка в новой задаче