added nsDeleteObserver (#3147: crashes on mouseMoved or closeWindow)
git-svn-id: svn://10.0.0.236/trunk@21426 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
Binary file not shown.
@@ -17,8 +17,9 @@
|
||||
*/
|
||||
|
||||
#include <LowMem.h>
|
||||
|
||||
#include "nsMacEventHandler.h"
|
||||
#include "nsWindow.h"
|
||||
#include "nsToolkit.h"
|
||||
#include "prinrval.h"
|
||||
|
||||
// from MacHeaders.c
|
||||
@@ -45,6 +46,21 @@ nsMacEventHandler::nsMacEventHandler(nsWindow* aTopLevelWidget)
|
||||
|
||||
nsMacEventHandler::~nsMacEventHandler()
|
||||
{
|
||||
if (mLastWidgetPointed)
|
||||
mLastWidgetPointed->RemoveDeleteObserver(this);
|
||||
|
||||
if (mLastWidgetHit)
|
||||
mLastWidgetHit->RemoveDeleteObserver(this);
|
||||
}
|
||||
|
||||
|
||||
void nsMacEventHandler::NotifyDelete(void* aDeletedObject)
|
||||
{
|
||||
if (mLastWidgetPointed == aDeletedObject)
|
||||
mLastWidgetPointed = nsnull;
|
||||
|
||||
if (mLastWidgetHit == aDeletedObject)
|
||||
mLastWidgetHit = nsnull;
|
||||
}
|
||||
|
||||
|
||||
@@ -367,7 +383,14 @@ PRBool nsMacEventHandler::HandleMouseDownEvent(
|
||||
// dispatch the event
|
||||
retVal = widgetHit->DispatchMouseEvent(mouseEvent);
|
||||
}
|
||||
|
||||
if (mLastWidgetHit)
|
||||
mLastWidgetHit->RemoveDeleteObserver(this);
|
||||
|
||||
mLastWidgetHit = widgetHit;
|
||||
|
||||
if (mLastWidgetHit)
|
||||
mLastWidgetHit->AddDeleteObserver(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -392,8 +415,10 @@ PRBool nsMacEventHandler::HandleMouseUpEvent(
|
||||
if ((widgetReleased != nsnull) && (widgetReleased != mLastWidgetHit))
|
||||
retVal |= widgetReleased->DispatchMouseEvent(mouseEvent);
|
||||
|
||||
if (mLastWidgetHit != nsnull)
|
||||
if (mLastWidgetHit)
|
||||
{
|
||||
mLastWidgetHit->RemoveDeleteObserver(this);
|
||||
|
||||
retVal |= mLastWidgetHit->DispatchMouseEvent(mouseEvent);
|
||||
mLastWidgetHit = nsnull;
|
||||
}
|
||||
@@ -420,17 +445,22 @@ PRBool nsMacEventHandler::HandleMouseMoveEvent(
|
||||
{
|
||||
if (mLastWidgetPointed != nsnull)
|
||||
{
|
||||
mLastWidgetPointed->RemoveDeleteObserver(this);
|
||||
|
||||
mouseEvent.widget = mLastWidgetPointed;
|
||||
mouseEvent.message = NS_MOUSE_EXIT;
|
||||
retVal |= mLastWidgetPointed->DispatchMouseEvent(mouseEvent);
|
||||
mLastWidgetPointed = nsnull;
|
||||
mouseEvent.widget = widgetPointed;
|
||||
}
|
||||
|
||||
if (widgetPointed != nsnull)
|
||||
{
|
||||
widgetPointed->AddDeleteObserver(this);
|
||||
|
||||
mLastWidgetPointed = widgetPointed;
|
||||
mouseEvent.message = NS_MOUSE_ENTER;
|
||||
retVal |= widgetPointed->DispatchMouseEvent(mouseEvent);
|
||||
mLastWidgetPointed = widgetPointed;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -20,11 +20,13 @@
|
||||
|
||||
#include <Events.h>
|
||||
#include <MacWindows.h>
|
||||
#include "nsWindow.h"
|
||||
#include "nsDeleteObserver.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsGUIEvent.h"
|
||||
|
||||
class nsWindow;
|
||||
|
||||
class nsMacEventHandler
|
||||
class nsMacEventHandler : public nsDeleteObserver
|
||||
{
|
||||
public:
|
||||
nsMacEventHandler(nsWindow* aTopLevelWidget);
|
||||
@@ -46,6 +48,9 @@ protected:
|
||||
nsMouseEvent& aMouseEvent,
|
||||
PRUint32 aMessage);
|
||||
|
||||
public:
|
||||
virtual void NotifyDelete(void* aDeletedObject);
|
||||
|
||||
protected:
|
||||
nsWindow* mTopLevelWidget;
|
||||
nsWindow* mLastWidgetHit;
|
||||
|
||||
@@ -28,7 +28,7 @@ PLEventQueue* nsToolkit::sPLEventQueue = nsnull;
|
||||
extern "C" NS_EXPORT PLEventQueue* GetMacPLEventQueue()
|
||||
{
|
||||
return nsToolkit::GetEventQueue();
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
/* Constructor
|
||||
@@ -50,6 +50,12 @@ nsToolkit::nsToolkit(): Repeater()
|
||||
*/
|
||||
nsToolkit::~nsToolkit()
|
||||
{
|
||||
if (mFocusedWidget)
|
||||
{
|
||||
mFocusedWidget->RemoveDeleteObserver(this);
|
||||
mFocusedWidget = nsnull;
|
||||
}
|
||||
|
||||
StopRepeating();
|
||||
}
|
||||
|
||||
@@ -71,16 +77,20 @@ void nsToolkit::SetFocus(nsWindow *aFocusWidget)
|
||||
// tell the old widget, it is not focused
|
||||
if (mFocusedWidget)
|
||||
{
|
||||
mFocusedWidget->RemoveDeleteObserver(this);
|
||||
|
||||
guiEvent.message = NS_LOSTFOCUS;
|
||||
guiEvent.widget = mFocusedWidget;
|
||||
mFocusedWidget->DispatchWindowEvent(guiEvent);
|
||||
mFocusedWidget = nil;
|
||||
mFocusedWidget = nsnull;
|
||||
}
|
||||
|
||||
// let the new one know
|
||||
if (aFocusWidget)
|
||||
{
|
||||
mFocusedWidget = aFocusWidget;
|
||||
mFocusedWidget = aFocusWidget;
|
||||
mFocusedWidget->AddDeleteObserver(this);
|
||||
|
||||
guiEvent.message = NS_GOTFOCUS;
|
||||
guiEvent.widget = mFocusedWidget;
|
||||
mFocusedWidget->DispatchWindowEvent(guiEvent);
|
||||
@@ -124,3 +134,13 @@ void nsToolkit::RepeatAction(const EventRecord& /*inMacEvent*/)
|
||||
// Handle pending NSPR events
|
||||
PL_ProcessPendingEvents( sPLEventQueue );
|
||||
}
|
||||
|
||||
|
||||
//=================================================================
|
||||
/*
|
||||
*/
|
||||
void nsToolkit::NotifyDelete(void* aDeletedObject)
|
||||
{
|
||||
if (mFocusedWidget == aDeletedObject)
|
||||
mFocusedWidget = nsnull;
|
||||
}
|
||||
|
||||
@@ -21,10 +21,11 @@
|
||||
|
||||
#include "nsIToolkit.h"
|
||||
#include "nsRepeater.h"
|
||||
struct PLEventQueue;
|
||||
class nsWindow;
|
||||
#include "nsDeleteObserver.h"
|
||||
|
||||
struct PLEventQueue;
|
||||
struct MethodInfo;
|
||||
class nsWindow;
|
||||
|
||||
/**
|
||||
* Wrapper around the thread running the message pump.
|
||||
@@ -32,7 +33,7 @@ struct MethodInfo;
|
||||
* execute within the same thread that created the widget under Win32.
|
||||
*/
|
||||
|
||||
class nsToolkit : public nsIToolkit, public Repeater
|
||||
class nsToolkit : public nsIToolkit, public Repeater, public nsDeleteObserver
|
||||
{
|
||||
|
||||
public:
|
||||
@@ -49,9 +50,10 @@ public:
|
||||
|
||||
// Event Queue
|
||||
static PLEventQueue* GetEventQueue(){ return sPLEventQueue; }
|
||||
// LPeriodical interface
|
||||
// Repeater interface
|
||||
virtual void RepeatAction(const EventRecord& inMacEvent);
|
||||
|
||||
// DeleteObserver
|
||||
virtual void NotifyDelete(void* aDeletedObject);
|
||||
private:
|
||||
static nsWindow* mFocusedWidget;
|
||||
static PLEventQueue* sPLEventQueue;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "nsIFontMetrics.h"
|
||||
#include "nsIDeviceContext.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsToolkit.h"
|
||||
|
||||
|
||||
NS_IMPL_ADDREF(ChildWindow)
|
||||
@@ -37,7 +38,7 @@ ChildWindow::ChildWindow() : nsWindow()
|
||||
// nsWindow constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsWindow::nsWindow() : nsBaseWidget()
|
||||
nsWindow::nsWindow() : nsBaseWidget() , nsDeleteObserved(this)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
strcpy(gInstanceClassName, "nsWindow");
|
||||
@@ -56,6 +57,7 @@ nsWindow::nsWindow() : nsBaseWidget()
|
||||
mWindowPtr = nsnull;
|
||||
mDrawing = PR_FALSE;
|
||||
mDestroyCalled = PR_FALSE;
|
||||
mDestructorCalled = PR_FALSE;
|
||||
|
||||
SetBackgroundColor(NS_RGB(255, 255, 255));
|
||||
SetForegroundColor(NS_RGB(0, 0, 0));
|
||||
@@ -69,9 +71,12 @@ nsWindow::nsWindow() : nsBaseWidget()
|
||||
//-------------------------------------------------------------------------
|
||||
nsWindow::~nsWindow()
|
||||
{
|
||||
//Destroy();
|
||||
mDestructorCalled = PR_TRUE;
|
||||
|
||||
mEventCallback = nsnull; // prevent the widget from causing additional events
|
||||
//¥¥¥ if (mToolkit && ((nsToolkit*)mToolkit)->GetFocus() == this )
|
||||
//¥¥¥ ((nsToolkit*)mToolkit)->SetFocus(nsnull);
|
||||
|
||||
//Destroy();
|
||||
|
||||
if (mWindowRegion != nsnull)
|
||||
{
|
||||
@@ -80,7 +85,7 @@ nsWindow::~nsWindow()
|
||||
}
|
||||
|
||||
NS_IF_RELEASE(mTempRenderingContext);
|
||||
NS_IF_RELEASE(mMenuListener);
|
||||
NS_IF_RELEASE(mMenuListener);
|
||||
}
|
||||
|
||||
|
||||
@@ -174,20 +179,12 @@ NS_IMETHODIMP nsWindow::Destroy()
|
||||
if (mDestroyCalled)
|
||||
return NS_OK;
|
||||
mDestroyCalled = PR_TRUE;
|
||||
|
||||
#if 0
|
||||
// if the window being destroyed has the focus, lose it so that there isn't a dangling reference
|
||||
if (mToolkit && ((nsToolkit*)mToolkit)->GetFocus() == this )
|
||||
#else
|
||||
//¥¥¥TEMPORARY¥¥¥
|
||||
// We clear the focus when destroying a top level window. If we check whether
|
||||
// this window has the focus (as we should - see above), the focus isn't cleared
|
||||
// and we crash in the following case: open window A, open window B, select A, close A => crash
|
||||
if (mToolkit && (mParent == nsnull))
|
||||
#endif
|
||||
{
|
||||
((nsToolkit*)mToolkit)->SetFocus(nsnull);
|
||||
}
|
||||
|
||||
//¥¥¥ // if the window being destroyed has the focus, lose it so that there isn't a dangling reference
|
||||
//¥¥¥ if (mToolkit && ((nsToolkit*)mToolkit)->GetFocus() == this )
|
||||
//¥¥¥ {
|
||||
//¥¥¥ ((nsToolkit*)mToolkit)->SetFocus(nsnull);
|
||||
//¥¥¥ }
|
||||
|
||||
nsBaseWidget::OnDestroy();
|
||||
nsBaseWidget::Destroy();
|
||||
@@ -888,24 +885,25 @@ PRBool nsWindow::ConvertStatus(nsEventStatus aStatus)
|
||||
//-------------------------------------------------------------------------
|
||||
NS_IMETHODIMP nsWindow::DispatchEvent(nsGUIEvent* event, nsEventStatus& aStatus)
|
||||
{
|
||||
nsIWidget* aWidget = event->widget;
|
||||
NS_IF_ADDREF(aWidget);
|
||||
|
||||
aStatus = nsEventStatus_eIgnore;
|
||||
|
||||
if (nsnull != mMenuListener){
|
||||
if(NS_MENU_EVENT == event->eventStructType)
|
||||
aStatus = mMenuListener->MenuSelected( static_cast<nsMenuEvent&>(*event) );
|
||||
}
|
||||
if (mEventCallback)
|
||||
aStatus = (*mEventCallback)(event);
|
||||
if (! mDestructorCalled)
|
||||
{
|
||||
nsIWidget* aWidget = event->widget;
|
||||
NS_IF_ADDREF(aWidget);
|
||||
|
||||
if (nsnull != mMenuListener){
|
||||
if(NS_MENU_EVENT == event->eventStructType)
|
||||
aStatus = mMenuListener->MenuSelected( static_cast<nsMenuEvent&>(*event) );
|
||||
}
|
||||
if (mEventCallback)
|
||||
aStatus = (*mEventCallback)(event);
|
||||
|
||||
// Dispatch to event listener if event was not consumed
|
||||
if ((aStatus != nsEventStatus_eIgnore) && (mEventListener != nsnull))
|
||||
aStatus = mEventListener->ProcessEvent(*event);
|
||||
|
||||
NS_IF_RELEASE(aWidget);
|
||||
// Dispatch to event listener if event was not consumed
|
||||
if ((aStatus != nsEventStatus_eIgnore) && (mEventListener != nsnull))
|
||||
aStatus = mEventListener->ProcessEvent(*event);
|
||||
|
||||
NS_IF_RELEASE(aWidget);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsBaseWidget.h"
|
||||
|
||||
#include "nsToolkit.h"
|
||||
#include "nsDeleteObserver.h"
|
||||
|
||||
#include "nsIWidget.h"
|
||||
#include "nsIEnumerator.h"
|
||||
@@ -45,7 +44,7 @@
|
||||
//-------------------------------------------------------------------------
|
||||
// Generic object
|
||||
|
||||
class nsWindow : public nsBaseWidget
|
||||
class nsWindow : public nsBaseWidget, public nsDeleteObserved
|
||||
{
|
||||
|
||||
public:
|
||||
@@ -170,6 +169,7 @@ protected:
|
||||
RgnHandle mWindowRegion; // the region defining this window
|
||||
WindowPtr mWindowPtr;
|
||||
PRBool mDestroyCalled;
|
||||
PRBool mDestructorCalled;
|
||||
|
||||
PRBool mDrawing;
|
||||
nsIRenderingContext* mTempRenderingContext;
|
||||
|
||||
Reference in New Issue
Block a user