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:
pierre%netscape.com
1999-02-21 02:10:36 +00:00
parent e6d0867a28
commit 3e39d64a45
7 changed files with 104 additions and 49 deletions

Binary file not shown.

View File

@@ -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

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;