Eliminate old nsCWeakReference implementation (bug 230480). This rewrites nsListControlFrame's event listener to be a little more sane. r+sr=dbaron.

git-svn-id: svn://10.0.0.236/trunk@151106 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
bryner%brianryner.com
2004-01-09 22:18:26 +00:00
parent d508bb9c57
commit ac18b979bc
10 changed files with 248 additions and 1006 deletions

View File

@@ -63,8 +63,8 @@
#include "nsITextContent.h"
#include "nsIScrollableViewProvider.h"
#include "nsIStatefulFrame.h"
#include "nsIDOMMouseListener.h"
class nsIDOMMouseListener;
class nsIView;
class nsStyleContext;
class nsIHTMLContent;

View File

@@ -88,6 +88,9 @@
#include "nsILookAndFeel.h"
#include "nsReflowPath.h"
#include "nsITheme.h"
#include "nsIDOMMouseListener.h"
#include "nsIDOMMouseMotionListener.h"
#include "nsIDOMKeyListener.h"
// Timer Includes
#include "nsITimer.h"
@@ -111,6 +114,48 @@ nsListControlFrame * nsListControlFrame::mFocused = nsnull;
DOMTimeStamp nsListControlFrame::gLastKeyTime = 0;
/******************************************************************************
* nsListEventListener
* This class is responsible for propagating events to the nsListControlFrame.
* Frames are not refcounted so they can't be used as event listeners.
*****************************************************************************/
class nsListEventListener : public nsIDOMKeyListener,
public nsIDOMMouseListener,
public nsIDOMMouseMotionListener
{
public:
nsListEventListener(nsListControlFrame *aFrame)
: mFrame(aFrame) { }
void SetFrame(nsListControlFrame *aFrame) { mFrame = aFrame; }
NS_DECL_ISUPPORTS
// nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
// nsIDOMKeyListener
NS_IMETHOD KeyDown(nsIDOMEvent* aKeyEvent);
NS_IMETHOD KeyUp(nsIDOMEvent* aKeyEvent);
NS_IMETHOD KeyPress(nsIDOMEvent* aKeyEvent);
// nsIDOMMouseListener
NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseUp(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseClick(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseDblClick(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseOver(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseOut(nsIDOMEvent* aMouseEvent);
// nsIDOMMouseMotionListener
NS_IMETHOD MouseMove(nsIDOMEvent* aMouseEvent);
NS_IMETHOD DragMove(nsIDOMEvent* aMouseEvent);
private:
nsListControlFrame *mFrame;
};
//---------------------------------------------------------
nsresult
NS_NewListControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
@@ -391,7 +436,7 @@ nsSelectUpdateTimer::~nsSelectUpdateTimer()
//---------------------------------------------------------
nsListControlFrame::nsListControlFrame(nsIPresShell* aShell,
nsIDocument* aDocument)
: nsGfxScrollFrame(aShell, aDocument, PR_FALSE), mWeakReferent(this)
: nsGfxScrollFrame(aShell, aDocument, PR_FALSE)
{
mComboboxFrame = nsnull;
mButtonDown = PR_FALSE;
@@ -441,17 +486,22 @@ nsListControlFrame::Destroy(nsIPresContext *aPresContext)
// get the receiver interface from the browser button's content node
nsCOMPtr<nsIDOMEventReceiver> receiver(do_QueryInterface(mContent));
nsCOMPtr<nsIDOMMouseListener> mouseListener = do_QueryInterface(mEventListener);
if (!mouseListener) { return NS_ERROR_NO_INTERFACE; }
receiver->RemoveEventListenerByIID(mouseListener, NS_GET_IID(nsIDOMMouseListener));
// Clear the frame pointer on our event listener, just in case the
// event listener can outlive the frame.
nsCOMPtr<nsIDOMMouseMotionListener> mouseMotionListener = do_QueryInterface(mEventListener);
if (!mouseMotionListener) { return NS_ERROR_NO_INTERFACE; }
receiver->RemoveEventListenerByIID(mouseMotionListener, NS_GET_IID(nsIDOMMouseMotionListener));
mEventListener->SetFrame(nsnull);
nsCOMPtr<nsIDOMKeyListener> keyListener = do_QueryInterface(mEventListener);
if (!keyListener) { return NS_ERROR_NO_INTERFACE; }
receiver->RemoveEventListenerByIID(keyListener, NS_GET_IID(nsIDOMKeyListener));
receiver->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMMouseListener*,
mEventListener),
NS_GET_IID(nsIDOMMouseListener));
receiver->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMMouseMotionListener*,
mEventListener),
NS_GET_IID(nsIDOMMouseMotionListener));
receiver->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMKeyListener*,
mEventListener),
NS_GET_IID(nsIDOMKeyListener));
if (IsInDropDownMode() == PR_FALSE) {
nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE);
@@ -687,18 +737,6 @@ nsListControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
NS_STATIC_CAST(void*,NS_STATIC_CAST(nsIStatefulFrame*,this));
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIDOMMouseListener))) {
*aInstancePtr = (void*)(nsIDOMMouseListener*) this;
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIDOMMouseMotionListener))) {
*aInstancePtr = (void*)(nsIDOMMouseMotionListener*) this;
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIDOMKeyListener))) {
*aInstancePtr = (void*)(nsIDOMKeyListener*) this;
return NS_OK;
}
return nsGfxScrollFrame::QueryInterface(aIID, aInstancePtr);
}
@@ -1796,23 +1834,21 @@ nsListControlFrame::Init(nsIPresContext* aPresContext,
// our frame goes away all these content node go away as well
// because our frame is the only one who references them.
// we need to hook up our listeners before the editor is initialized
result = NS_NewListEventListener(getter_AddRefs(mEventListener));
if (NS_FAILED(result)) { return result ; }
if (!mEventListener) { return NS_ERROR_NULL_POINTER; }
mEventListener = new nsListEventListener(this);
if (!mEventListener)
return NS_ERROR_OUT_OF_MEMORY;
mEventListener->SetFrame(this);
receiver->AddEventListenerByIID(NS_STATIC_CAST(nsIDOMMouseListener*,
mEventListener),
NS_GET_IID(nsIDOMMouseListener));
nsCOMPtr<nsIDOMMouseListener> mouseListener = do_QueryInterface(mEventListener);
if (!mouseListener) { return NS_ERROR_NO_INTERFACE; }
receiver->AddEventListenerByIID(mouseListener, NS_GET_IID(nsIDOMMouseListener));
receiver->AddEventListenerByIID(NS_STATIC_CAST(nsIDOMMouseMotionListener*,
mEventListener),
NS_GET_IID(nsIDOMMouseMotionListener));
nsCOMPtr<nsIDOMMouseMotionListener> mouseMotionListener = do_QueryInterface(mEventListener);
if (!mouseMotionListener) { return NS_ERROR_NO_INTERFACE; }
receiver->AddEventListenerByIID(mouseMotionListener, NS_GET_IID(nsIDOMMouseMotionListener));
nsCOMPtr<nsIDOMKeyListener> keyListener = do_QueryInterface(mEventListener);
if (!keyListener) { return NS_ERROR_NO_INTERFACE; }
receiver->AddEventListenerByIID(keyListener, NS_GET_IID(nsIDOMKeyListener));
receiver->AddEventListenerByIID(NS_STATIC_CAST(nsIDOMKeyListener*,
mEventListener),
NS_GET_IID(nsIDOMKeyListener));
mStartSelectionIndex = kNothingSelected;
mEndSelectionIndex = kNothingSelected;
@@ -2036,8 +2072,8 @@ nsListControlFrame::GetFormControlType() const
//---------------------------------------------------------
void
nsListControlFrame::MouseClicked(nsIPresContext* aPresContext)
void
nsListControlFrame::MouseClicked(nsIPresContext* aPresContext)
{
}
@@ -3014,15 +3050,6 @@ nsListControlFrame::DragMove(nsIDOMEvent* aMouseEvent)
return NS_OK;
}
//----------------------------------------------------------------------
// nsIDOMKeyListener
//----------------------------------------------------------------------
nsresult
nsListControlFrame::KeyDown(nsIDOMEvent* aKeyEvent)
{
return NS_OK;
}
nsresult
nsListControlFrame::ScrollToIndex(PRInt32 aIndex)
{
@@ -3501,225 +3528,59 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent)
}
/*******************************************************************************
/******************************************************************************
* nsListEventListener
******************************************************************************/
nsresult
NS_NewListEventListener(nsIListEventListener ** aInstancePtr)
{
nsListEventListener* it = new nsListEventListener();
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
return it->QueryInterface(NS_GET_IID(nsIListEventListener), (void **) aInstancePtr);
}
*****************************************************************************/
NS_IMPL_ADDREF(nsListEventListener)
NS_IMPL_RELEASE(nsListEventListener)
NS_INTERFACE_MAP_BEGIN(nsListEventListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseMotionListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMMouseListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMouseListener)
NS_INTERFACE_MAP_END
nsListEventListener::nsListEventListener()
{
#define FORWARD_EVENT(_event) \
NS_IMETHODIMP \
nsListEventListener::_event(nsIDOMEvent* aEvent) \
{ \
if (mFrame) \
return mFrame->nsListControlFrame::_event(aEvent); \
return NS_OK; \
}
nsListEventListener::~nsListEventListener()
{
// all refcounted objects are held as nsCOMPtrs, clear themselves
}
#define IGNORE_EVENT(_event) \
NS_IMETHODIMP \
nsListEventListener::_event(nsIDOMEvent* aEvent) \
{ return NS_OK; }
NS_IMETHODIMP
nsListEventListener::SetFrame(nsListControlFrame *aFrame)
{
mFrame.SetReference(aFrame->WeakReferent());
if (aFrame)
{
mContent = aFrame->GetContent();
}
return NS_OK;
}
IGNORE_EVENT(HandleEvent)
nsresult
nsListEventListener::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (nsnull == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(NS_GET_IID(nsISupports))) {
nsIDOMKeyListener *tmp = this;
nsISupports *tmp2 = tmp;
*aInstancePtr = (void*) tmp2;
NS_ADDREF_THIS();
return NS_OK;
}
/*================== nsIDOMKeyListener =========================*/
if (aIID.Equals(NS_GET_IID(nsIDOMEventListener))) {
nsIDOMKeyListener *kl = (nsIDOMKeyListener*)this;
nsIDOMEventListener *temp = kl;
*aInstancePtr = (void*)temp;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIDOMMouseMotionListener))) {
*aInstancePtr = (void*)(nsIDOMMouseMotionListener*) this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIDOMKeyListener))) {
*aInstancePtr = (void*)(nsIDOMKeyListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIDOMMouseListener))) {
*aInstancePtr = (void*)(nsIDOMMouseListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIListEventListener))) {
*aInstancePtr = (void*)(nsIListEventListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
IGNORE_EVENT(KeyDown)
IGNORE_EVENT(KeyUp)
FORWARD_EVENT(KeyPress)
return NS_NOINTERFACE;
}
/*=============== nsIDOMMouseListener ======================*/
nsresult
nsListEventListener::HandleEvent(nsIDOMEvent* aEvent)
{
return NS_OK;
}
/*================== nsIKeyListener =========================*/
nsresult
nsListEventListener::KeyDown(nsIDOMEvent* aKeyEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->KeyDown(aKeyEvent);
}
return NS_OK;
}
nsresult
nsListEventListener::KeyUp(nsIDOMEvent* aKeyEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->KeyUp(aKeyEvent);
}
return NS_OK;
}
nsresult
nsListEventListener::KeyPress(nsIDOMEvent* aKeyEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->KeyPress(aKeyEvent);
}
return NS_OK;
}
/*=============== nsIMouseListener ======================*/
nsresult
nsListEventListener::MouseDown(nsIDOMEvent* aMouseEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->MouseDown(aMouseEvent);
}
return NS_OK;
}
nsresult
nsListEventListener::MouseUp(nsIDOMEvent* aMouseEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->MouseUp(aMouseEvent);
}
return NS_OK;
}
nsresult
nsListEventListener::MouseClick(nsIDOMEvent* aMouseEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->MouseClick(aMouseEvent);
}
return NS_OK;
}
nsresult
nsListEventListener::MouseDblClick(nsIDOMEvent* aMouseEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->MouseDblClick(aMouseEvent);
}
return NS_OK;
}
nsresult
nsListEventListener::MouseOver(nsIDOMEvent* aMouseEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->MouseOver(aMouseEvent);
}
return NS_OK;
}
nsresult
nsListEventListener::MouseOut(nsIDOMEvent* aMouseEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->MouseOut(aMouseEvent);
}
return NS_OK;
}
FORWARD_EVENT(MouseDown)
FORWARD_EVENT(MouseUp)
IGNORE_EVENT(MouseClick)
IGNORE_EVENT(MouseDblClick)
IGNORE_EVENT(MouseOver)
IGNORE_EVENT(MouseOut)
/*=============== nsIDOMMouseMotionListener ======================*/
nsresult
nsListEventListener::MouseMove(nsIDOMEvent* aMouseEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->MouseMove(aMouseEvent);
}
return NS_OK;
}
FORWARD_EVENT(MouseMove)
// XXXbryner does anyone call this, ever?
IGNORE_EVENT(DragMove)
nsresult
nsListEventListener::DragMove(nsIDOMEvent* aMouseEvent)
{
/*
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->DragMove(aMouseEvent);
}
*/
return NS_OK;
}
#undef FORWARD_EVENT
#undef IGNORE_EVENT
/*=============== Timer Related Code ======================*/
nsresult

View File

@@ -53,12 +53,10 @@
#include "nsIListControlFrame.h"
#include "nsISelectControlFrame.h"
#include "nsIStatefulFrame.h"
#include "nsIDOMMouseListener.h"
#include "nsIDOMMouseMotionListener.h"
#include "nsIDOMKeyListener.h"
#include "nsIDOMEventListener.h"
#include "nsIPresState.h"
#include "nsCWeakReference.h"
#include "nsIContent.h"
#include "nsAutoPtr.h"
class nsIDOMHTMLSelectElement;
class nsIDOMHTMLOptionsCollection;
@@ -69,102 +67,9 @@ class nsIPresContext;
class nsVoidArray;
class nsIScrollableView;
class nsListControlFrame;
class nsSelectUpdateTimer;
class nsVoidArray;
#define NS_ILIST_EVENT_LISTENER_IID \
{/* 45BC6821-6EFB-11d4-B1EE-000064657374*/ \
0x45bc6821, 0x6efb, 0x11d4, \
{0xb1, 0xee, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
/******************************************************************************
* nsIListEventListener
* Standard interface for event listeners that are attached to nsListControls
******************************************************************************/
class nsIListEventListener : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ILIST_EVENT_LISTENER_IID)
/** SetFrame sets the frame we send event messages to, when necessary
* @param aFrame -- the frame, can be null, not ref counted (guaranteed to outlive us!)
*/
NS_IMETHOD SetFrame(nsListControlFrame *aFrame)=0;
};
/******************************************************************************
* nsListEventListener
* This class is responsible for propagating events to the nsListControlFrame
* becuase it isn't ref-counted
******************************************************************************/
class nsListEventListener; // forward declaration for factory
/* factory for ender key listener */
nsresult NS_NewListEventListener(nsIListEventListener ** aInstancePtrResult);
class nsListEventListener : public nsIListEventListener,
public nsIDOMKeyListener,
public nsIDOMMouseListener,
public nsIDOMMouseMotionListener
{
public:
/** the default destructor */
virtual ~nsListEventListener();
/** interfaces for addref and release and queryinterface*/
NS_DECL_ISUPPORTS
/** nsIDOMKeyListener interfaces
* @see nsIDOMKeyListener
*/
NS_IMETHOD SetFrame(nsListControlFrame *aFrame);
/** nsIDOMKeyListener interfaces
* @see nsIDOMKeyListener
*/
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
NS_IMETHOD KeyDown(nsIDOMEvent* aKeyEvent);
NS_IMETHOD KeyUp(nsIDOMEvent* aKeyEvent);
NS_IMETHOD KeyPress(nsIDOMEvent* aKeyEvent);
/* END interfaces from nsIDOMKeyListener*/
/** nsIDOMMouseListener interfaces
* @see nsIDOMMouseListener
*/
NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseUp(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseClick(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseDblClick(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseOver(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseOut(nsIDOMEvent* aMouseEvent);
/* END interfaces from nsIDOMMouseListener*/
//nsIDOMEventMotionListener
/** nsIDOMEventMotionListener interfaces
* @see nsIDOMEventMotionListener
*/
NS_IMETHOD MouseMove(nsIDOMEvent* aMouseEvent);
NS_IMETHOD DragMove(nsIDOMEvent* aMouseEvent);
/* END interfaces from nsIDOMMouseListener*/
friend nsresult NS_NewListEventListener(nsIListEventListener ** aInstancePtrResult);
protected:
/** the default constructor. Protected, use the factory to create an instance.
* @see NS_NewEnderEventListener
*/
nsListEventListener();
protected:
nsCWeakReference<nsListControlFrame> mFrame;
nsCOMPtr<nsIContent> mContent; // ref counted
};
class nsListEventListener;
/**
* Frame-based listbox.
@@ -174,9 +79,6 @@ class nsListControlFrame : public nsGfxScrollFrame,
public nsIFormControlFrame,
public nsIListControlFrame,
public nsIStatefulFrame,
public nsIDOMMouseListener,
public nsIDOMMouseMotionListener,
public nsIDOMKeyListener,
public nsISelectControlFrame
{
public:
@@ -295,23 +197,16 @@ public:
NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState);
NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState);
//nsIDOMEventListener
NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseUp(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseClick(nsIDOMEvent* aMouseEvent) { return NS_OK; }
NS_IMETHOD MouseDblClick(nsIDOMEvent* aMouseEvent) { return NS_OK; }
NS_IMETHOD MouseOver(nsIDOMEvent* aMouseEvent) { return NS_OK; }
NS_IMETHOD MouseOut(nsIDOMEvent* aMouseEvent) { return NS_OK; }
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) { return NS_OK; }
// mouse event listeners
nsresult MouseDown(nsIDOMEvent* aMouseEvent);
nsresult MouseUp(nsIDOMEvent* aMouseEvent);
//nsIDOMEventMotionListener
NS_IMETHOD MouseMove(nsIDOMEvent* aMouseEvent);
NS_IMETHOD DragMove(nsIDOMEvent* aMouseEvent);
// mouse motion listeners
nsresult MouseMove(nsIDOMEvent* aMouseEvent);
nsresult DragMove(nsIDOMEvent* aMouseEvent);
//nsIDOMKeyListener
NS_IMETHOD KeyDown(nsIDOMEvent* aKeyEvent);
NS_IMETHOD KeyUp(nsIDOMEvent* aKeyEvent) { return NS_OK; }
NS_IMETHOD KeyPress(nsIDOMEvent* aKeyEvent);
// key listeners
nsresult KeyPress(nsIDOMEvent* aKeyEvent);
// Static Methods
static nsIDOMHTMLSelectElement* GetSelect(nsIContent * aContent);
@@ -321,10 +216,6 @@ public:
static void ComboboxFocusSet();
// Weak Reference
nsCWeakReferent *WeakReferent()
{ return &mWeakReferent; }
// Helper
void SetPassId(PRInt16 aId) { mPassId = aId; }
@@ -405,8 +296,7 @@ protected:
nsIPresContext* mPresContext; // XXX: Remove the need to cache the pres context.
nsCOMPtr<nsIListEventListener> mEventListener; // ref counted
nsCWeakReferent mWeakReferent; // so this obj can be used as a weak ptr
nsRefPtr<nsListEventListener> mEventListener;
// XXX temprary only until full system mouse capture works
PRPackedBool mIsScrollbarVisible;

View File

@@ -63,8 +63,8 @@
#include "nsITextContent.h"
#include "nsIScrollableViewProvider.h"
#include "nsIStatefulFrame.h"
#include "nsIDOMMouseListener.h"
class nsIDOMMouseListener;
class nsIView;
class nsStyleContext;
class nsIHTMLContent;

View File

@@ -88,6 +88,9 @@
#include "nsILookAndFeel.h"
#include "nsReflowPath.h"
#include "nsITheme.h"
#include "nsIDOMMouseListener.h"
#include "nsIDOMMouseMotionListener.h"
#include "nsIDOMKeyListener.h"
// Timer Includes
#include "nsITimer.h"
@@ -111,6 +114,48 @@ nsListControlFrame * nsListControlFrame::mFocused = nsnull;
DOMTimeStamp nsListControlFrame::gLastKeyTime = 0;
/******************************************************************************
* nsListEventListener
* This class is responsible for propagating events to the nsListControlFrame.
* Frames are not refcounted so they can't be used as event listeners.
*****************************************************************************/
class nsListEventListener : public nsIDOMKeyListener,
public nsIDOMMouseListener,
public nsIDOMMouseMotionListener
{
public:
nsListEventListener(nsListControlFrame *aFrame)
: mFrame(aFrame) { }
void SetFrame(nsListControlFrame *aFrame) { mFrame = aFrame; }
NS_DECL_ISUPPORTS
// nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
// nsIDOMKeyListener
NS_IMETHOD KeyDown(nsIDOMEvent* aKeyEvent);
NS_IMETHOD KeyUp(nsIDOMEvent* aKeyEvent);
NS_IMETHOD KeyPress(nsIDOMEvent* aKeyEvent);
// nsIDOMMouseListener
NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseUp(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseClick(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseDblClick(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseOver(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseOut(nsIDOMEvent* aMouseEvent);
// nsIDOMMouseMotionListener
NS_IMETHOD MouseMove(nsIDOMEvent* aMouseEvent);
NS_IMETHOD DragMove(nsIDOMEvent* aMouseEvent);
private:
nsListControlFrame *mFrame;
};
//---------------------------------------------------------
nsresult
NS_NewListControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
@@ -391,7 +436,7 @@ nsSelectUpdateTimer::~nsSelectUpdateTimer()
//---------------------------------------------------------
nsListControlFrame::nsListControlFrame(nsIPresShell* aShell,
nsIDocument* aDocument)
: nsGfxScrollFrame(aShell, aDocument, PR_FALSE), mWeakReferent(this)
: nsGfxScrollFrame(aShell, aDocument, PR_FALSE)
{
mComboboxFrame = nsnull;
mButtonDown = PR_FALSE;
@@ -441,17 +486,22 @@ nsListControlFrame::Destroy(nsIPresContext *aPresContext)
// get the receiver interface from the browser button's content node
nsCOMPtr<nsIDOMEventReceiver> receiver(do_QueryInterface(mContent));
nsCOMPtr<nsIDOMMouseListener> mouseListener = do_QueryInterface(mEventListener);
if (!mouseListener) { return NS_ERROR_NO_INTERFACE; }
receiver->RemoveEventListenerByIID(mouseListener, NS_GET_IID(nsIDOMMouseListener));
// Clear the frame pointer on our event listener, just in case the
// event listener can outlive the frame.
nsCOMPtr<nsIDOMMouseMotionListener> mouseMotionListener = do_QueryInterface(mEventListener);
if (!mouseMotionListener) { return NS_ERROR_NO_INTERFACE; }
receiver->RemoveEventListenerByIID(mouseMotionListener, NS_GET_IID(nsIDOMMouseMotionListener));
mEventListener->SetFrame(nsnull);
nsCOMPtr<nsIDOMKeyListener> keyListener = do_QueryInterface(mEventListener);
if (!keyListener) { return NS_ERROR_NO_INTERFACE; }
receiver->RemoveEventListenerByIID(keyListener, NS_GET_IID(nsIDOMKeyListener));
receiver->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMMouseListener*,
mEventListener),
NS_GET_IID(nsIDOMMouseListener));
receiver->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMMouseMotionListener*,
mEventListener),
NS_GET_IID(nsIDOMMouseMotionListener));
receiver->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMKeyListener*,
mEventListener),
NS_GET_IID(nsIDOMKeyListener));
if (IsInDropDownMode() == PR_FALSE) {
nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE);
@@ -687,18 +737,6 @@ nsListControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
NS_STATIC_CAST(void*,NS_STATIC_CAST(nsIStatefulFrame*,this));
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIDOMMouseListener))) {
*aInstancePtr = (void*)(nsIDOMMouseListener*) this;
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIDOMMouseMotionListener))) {
*aInstancePtr = (void*)(nsIDOMMouseMotionListener*) this;
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIDOMKeyListener))) {
*aInstancePtr = (void*)(nsIDOMKeyListener*) this;
return NS_OK;
}
return nsGfxScrollFrame::QueryInterface(aIID, aInstancePtr);
}
@@ -1796,23 +1834,21 @@ nsListControlFrame::Init(nsIPresContext* aPresContext,
// our frame goes away all these content node go away as well
// because our frame is the only one who references them.
// we need to hook up our listeners before the editor is initialized
result = NS_NewListEventListener(getter_AddRefs(mEventListener));
if (NS_FAILED(result)) { return result ; }
if (!mEventListener) { return NS_ERROR_NULL_POINTER; }
mEventListener = new nsListEventListener(this);
if (!mEventListener)
return NS_ERROR_OUT_OF_MEMORY;
mEventListener->SetFrame(this);
receiver->AddEventListenerByIID(NS_STATIC_CAST(nsIDOMMouseListener*,
mEventListener),
NS_GET_IID(nsIDOMMouseListener));
nsCOMPtr<nsIDOMMouseListener> mouseListener = do_QueryInterface(mEventListener);
if (!mouseListener) { return NS_ERROR_NO_INTERFACE; }
receiver->AddEventListenerByIID(mouseListener, NS_GET_IID(nsIDOMMouseListener));
receiver->AddEventListenerByIID(NS_STATIC_CAST(nsIDOMMouseMotionListener*,
mEventListener),
NS_GET_IID(nsIDOMMouseMotionListener));
nsCOMPtr<nsIDOMMouseMotionListener> mouseMotionListener = do_QueryInterface(mEventListener);
if (!mouseMotionListener) { return NS_ERROR_NO_INTERFACE; }
receiver->AddEventListenerByIID(mouseMotionListener, NS_GET_IID(nsIDOMMouseMotionListener));
nsCOMPtr<nsIDOMKeyListener> keyListener = do_QueryInterface(mEventListener);
if (!keyListener) { return NS_ERROR_NO_INTERFACE; }
receiver->AddEventListenerByIID(keyListener, NS_GET_IID(nsIDOMKeyListener));
receiver->AddEventListenerByIID(NS_STATIC_CAST(nsIDOMKeyListener*,
mEventListener),
NS_GET_IID(nsIDOMKeyListener));
mStartSelectionIndex = kNothingSelected;
mEndSelectionIndex = kNothingSelected;
@@ -2036,8 +2072,8 @@ nsListControlFrame::GetFormControlType() const
//---------------------------------------------------------
void
nsListControlFrame::MouseClicked(nsIPresContext* aPresContext)
void
nsListControlFrame::MouseClicked(nsIPresContext* aPresContext)
{
}
@@ -3014,15 +3050,6 @@ nsListControlFrame::DragMove(nsIDOMEvent* aMouseEvent)
return NS_OK;
}
//----------------------------------------------------------------------
// nsIDOMKeyListener
//----------------------------------------------------------------------
nsresult
nsListControlFrame::KeyDown(nsIDOMEvent* aKeyEvent)
{
return NS_OK;
}
nsresult
nsListControlFrame::ScrollToIndex(PRInt32 aIndex)
{
@@ -3501,225 +3528,59 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent)
}
/*******************************************************************************
/******************************************************************************
* nsListEventListener
******************************************************************************/
nsresult
NS_NewListEventListener(nsIListEventListener ** aInstancePtr)
{
nsListEventListener* it = new nsListEventListener();
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
return it->QueryInterface(NS_GET_IID(nsIListEventListener), (void **) aInstancePtr);
}
*****************************************************************************/
NS_IMPL_ADDREF(nsListEventListener)
NS_IMPL_RELEASE(nsListEventListener)
NS_INTERFACE_MAP_BEGIN(nsListEventListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseMotionListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMMouseListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMouseListener)
NS_INTERFACE_MAP_END
nsListEventListener::nsListEventListener()
{
#define FORWARD_EVENT(_event) \
NS_IMETHODIMP \
nsListEventListener::_event(nsIDOMEvent* aEvent) \
{ \
if (mFrame) \
return mFrame->nsListControlFrame::_event(aEvent); \
return NS_OK; \
}
nsListEventListener::~nsListEventListener()
{
// all refcounted objects are held as nsCOMPtrs, clear themselves
}
#define IGNORE_EVENT(_event) \
NS_IMETHODIMP \
nsListEventListener::_event(nsIDOMEvent* aEvent) \
{ return NS_OK; }
NS_IMETHODIMP
nsListEventListener::SetFrame(nsListControlFrame *aFrame)
{
mFrame.SetReference(aFrame->WeakReferent());
if (aFrame)
{
mContent = aFrame->GetContent();
}
return NS_OK;
}
IGNORE_EVENT(HandleEvent)
nsresult
nsListEventListener::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (nsnull == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(NS_GET_IID(nsISupports))) {
nsIDOMKeyListener *tmp = this;
nsISupports *tmp2 = tmp;
*aInstancePtr = (void*) tmp2;
NS_ADDREF_THIS();
return NS_OK;
}
/*================== nsIDOMKeyListener =========================*/
if (aIID.Equals(NS_GET_IID(nsIDOMEventListener))) {
nsIDOMKeyListener *kl = (nsIDOMKeyListener*)this;
nsIDOMEventListener *temp = kl;
*aInstancePtr = (void*)temp;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIDOMMouseMotionListener))) {
*aInstancePtr = (void*)(nsIDOMMouseMotionListener*) this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIDOMKeyListener))) {
*aInstancePtr = (void*)(nsIDOMKeyListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIDOMMouseListener))) {
*aInstancePtr = (void*)(nsIDOMMouseListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIListEventListener))) {
*aInstancePtr = (void*)(nsIListEventListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
IGNORE_EVENT(KeyDown)
IGNORE_EVENT(KeyUp)
FORWARD_EVENT(KeyPress)
return NS_NOINTERFACE;
}
/*=============== nsIDOMMouseListener ======================*/
nsresult
nsListEventListener::HandleEvent(nsIDOMEvent* aEvent)
{
return NS_OK;
}
/*================== nsIKeyListener =========================*/
nsresult
nsListEventListener::KeyDown(nsIDOMEvent* aKeyEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->KeyDown(aKeyEvent);
}
return NS_OK;
}
nsresult
nsListEventListener::KeyUp(nsIDOMEvent* aKeyEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->KeyUp(aKeyEvent);
}
return NS_OK;
}
nsresult
nsListEventListener::KeyPress(nsIDOMEvent* aKeyEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->KeyPress(aKeyEvent);
}
return NS_OK;
}
/*=============== nsIMouseListener ======================*/
nsresult
nsListEventListener::MouseDown(nsIDOMEvent* aMouseEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->MouseDown(aMouseEvent);
}
return NS_OK;
}
nsresult
nsListEventListener::MouseUp(nsIDOMEvent* aMouseEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->MouseUp(aMouseEvent);
}
return NS_OK;
}
nsresult
nsListEventListener::MouseClick(nsIDOMEvent* aMouseEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->MouseClick(aMouseEvent);
}
return NS_OK;
}
nsresult
nsListEventListener::MouseDblClick(nsIDOMEvent* aMouseEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->MouseDblClick(aMouseEvent);
}
return NS_OK;
}
nsresult
nsListEventListener::MouseOver(nsIDOMEvent* aMouseEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->MouseOver(aMouseEvent);
}
return NS_OK;
}
nsresult
nsListEventListener::MouseOut(nsIDOMEvent* aMouseEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->MouseOut(aMouseEvent);
}
return NS_OK;
}
FORWARD_EVENT(MouseDown)
FORWARD_EVENT(MouseUp)
IGNORE_EVENT(MouseClick)
IGNORE_EVENT(MouseDblClick)
IGNORE_EVENT(MouseOver)
IGNORE_EVENT(MouseOut)
/*=============== nsIDOMMouseMotionListener ======================*/
nsresult
nsListEventListener::MouseMove(nsIDOMEvent* aMouseEvent)
{
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->MouseMove(aMouseEvent);
}
return NS_OK;
}
FORWARD_EVENT(MouseMove)
// XXXbryner does anyone call this, ever?
IGNORE_EVENT(DragMove)
nsresult
nsListEventListener::DragMove(nsIDOMEvent* aMouseEvent)
{
/*
nsListControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame && mContent)
{
return gfxFrame->DragMove(aMouseEvent);
}
*/
return NS_OK;
}
#undef FORWARD_EVENT
#undef IGNORE_EVENT
/*=============== Timer Related Code ======================*/
nsresult

View File

@@ -53,12 +53,10 @@
#include "nsIListControlFrame.h"
#include "nsISelectControlFrame.h"
#include "nsIStatefulFrame.h"
#include "nsIDOMMouseListener.h"
#include "nsIDOMMouseMotionListener.h"
#include "nsIDOMKeyListener.h"
#include "nsIDOMEventListener.h"
#include "nsIPresState.h"
#include "nsCWeakReference.h"
#include "nsIContent.h"
#include "nsAutoPtr.h"
class nsIDOMHTMLSelectElement;
class nsIDOMHTMLOptionsCollection;
@@ -69,102 +67,9 @@ class nsIPresContext;
class nsVoidArray;
class nsIScrollableView;
class nsListControlFrame;
class nsSelectUpdateTimer;
class nsVoidArray;
#define NS_ILIST_EVENT_LISTENER_IID \
{/* 45BC6821-6EFB-11d4-B1EE-000064657374*/ \
0x45bc6821, 0x6efb, 0x11d4, \
{0xb1, 0xee, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
/******************************************************************************
* nsIListEventListener
* Standard interface for event listeners that are attached to nsListControls
******************************************************************************/
class nsIListEventListener : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ILIST_EVENT_LISTENER_IID)
/** SetFrame sets the frame we send event messages to, when necessary
* @param aFrame -- the frame, can be null, not ref counted (guaranteed to outlive us!)
*/
NS_IMETHOD SetFrame(nsListControlFrame *aFrame)=0;
};
/******************************************************************************
* nsListEventListener
* This class is responsible for propagating events to the nsListControlFrame
* becuase it isn't ref-counted
******************************************************************************/
class nsListEventListener; // forward declaration for factory
/* factory for ender key listener */
nsresult NS_NewListEventListener(nsIListEventListener ** aInstancePtrResult);
class nsListEventListener : public nsIListEventListener,
public nsIDOMKeyListener,
public nsIDOMMouseListener,
public nsIDOMMouseMotionListener
{
public:
/** the default destructor */
virtual ~nsListEventListener();
/** interfaces for addref and release and queryinterface*/
NS_DECL_ISUPPORTS
/** nsIDOMKeyListener interfaces
* @see nsIDOMKeyListener
*/
NS_IMETHOD SetFrame(nsListControlFrame *aFrame);
/** nsIDOMKeyListener interfaces
* @see nsIDOMKeyListener
*/
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
NS_IMETHOD KeyDown(nsIDOMEvent* aKeyEvent);
NS_IMETHOD KeyUp(nsIDOMEvent* aKeyEvent);
NS_IMETHOD KeyPress(nsIDOMEvent* aKeyEvent);
/* END interfaces from nsIDOMKeyListener*/
/** nsIDOMMouseListener interfaces
* @see nsIDOMMouseListener
*/
NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseUp(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseClick(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseDblClick(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseOver(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseOut(nsIDOMEvent* aMouseEvent);
/* END interfaces from nsIDOMMouseListener*/
//nsIDOMEventMotionListener
/** nsIDOMEventMotionListener interfaces
* @see nsIDOMEventMotionListener
*/
NS_IMETHOD MouseMove(nsIDOMEvent* aMouseEvent);
NS_IMETHOD DragMove(nsIDOMEvent* aMouseEvent);
/* END interfaces from nsIDOMMouseListener*/
friend nsresult NS_NewListEventListener(nsIListEventListener ** aInstancePtrResult);
protected:
/** the default constructor. Protected, use the factory to create an instance.
* @see NS_NewEnderEventListener
*/
nsListEventListener();
protected:
nsCWeakReference<nsListControlFrame> mFrame;
nsCOMPtr<nsIContent> mContent; // ref counted
};
class nsListEventListener;
/**
* Frame-based listbox.
@@ -174,9 +79,6 @@ class nsListControlFrame : public nsGfxScrollFrame,
public nsIFormControlFrame,
public nsIListControlFrame,
public nsIStatefulFrame,
public nsIDOMMouseListener,
public nsIDOMMouseMotionListener,
public nsIDOMKeyListener,
public nsISelectControlFrame
{
public:
@@ -295,23 +197,16 @@ public:
NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState);
NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState);
//nsIDOMEventListener
NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseUp(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseClick(nsIDOMEvent* aMouseEvent) { return NS_OK; }
NS_IMETHOD MouseDblClick(nsIDOMEvent* aMouseEvent) { return NS_OK; }
NS_IMETHOD MouseOver(nsIDOMEvent* aMouseEvent) { return NS_OK; }
NS_IMETHOD MouseOut(nsIDOMEvent* aMouseEvent) { return NS_OK; }
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) { return NS_OK; }
// mouse event listeners
nsresult MouseDown(nsIDOMEvent* aMouseEvent);
nsresult MouseUp(nsIDOMEvent* aMouseEvent);
//nsIDOMEventMotionListener
NS_IMETHOD MouseMove(nsIDOMEvent* aMouseEvent);
NS_IMETHOD DragMove(nsIDOMEvent* aMouseEvent);
// mouse motion listeners
nsresult MouseMove(nsIDOMEvent* aMouseEvent);
nsresult DragMove(nsIDOMEvent* aMouseEvent);
//nsIDOMKeyListener
NS_IMETHOD KeyDown(nsIDOMEvent* aKeyEvent);
NS_IMETHOD KeyUp(nsIDOMEvent* aKeyEvent) { return NS_OK; }
NS_IMETHOD KeyPress(nsIDOMEvent* aKeyEvent);
// key listeners
nsresult KeyPress(nsIDOMEvent* aKeyEvent);
// Static Methods
static nsIDOMHTMLSelectElement* GetSelect(nsIContent * aContent);
@@ -321,10 +216,6 @@ public:
static void ComboboxFocusSet();
// Weak Reference
nsCWeakReferent *WeakReferent()
{ return &mWeakReferent; }
// Helper
void SetPassId(PRInt16 aId) { mPassId = aId; }
@@ -405,8 +296,7 @@ protected:
nsIPresContext* mPresContext; // XXX: Remove the need to cache the pres context.
nsCOMPtr<nsIListEventListener> mEventListener; // ref counted
nsCWeakReferent mWeakReferent; // so this obj can be used as a weak ptr
nsRefPtr<nsListEventListener> mEventListener;
// XXX temprary only until full system mouse capture works
PRPackedBool mIsScrollbarVisible;

View File

@@ -36,7 +36,6 @@ REQUIRES = string \
CPPSRCS = \
nsAllocator.cpp \
nsCWeakReference.cpp \
nsConsoleMessage.cpp \
nsConsoleService.cpp \
nsDebugImpl.cpp \
@@ -56,7 +55,6 @@ endif
EXPORTS = \
nsAgg.h \
nsAutoPtr.h \
nsCWeakReference.h \
nsCom.h \
nsComObsolete.h \
nsDebugImpl.h \

View File

@@ -1,84 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code,
* released March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* A set of support classes for defining weak references, rather like
nsIWeakReference, but for use with non-COM objects
*/
#include "nsCWeakReference.h"
/************ a thing supporting weak references to itself ***********/
nsCWeakReferent::nsCWeakReferent(void *aRealThing) :
mRealThing(aRealThing),
mProxy(0) {
}
nsCWeakReferent::~nsCWeakReferent() {
if (mProxy)
mProxy->RealThingDeleted();
}
void nsCWeakReferent::SetReferent(void *aRealThing) {
NS_ASSERTION(!mRealThing && !mProxy, "weak referent set twice");
mRealThing = aRealThing;
mProxy = 0;
}
nsCWeakProxy *nsCWeakReferent::GetProxy() {
if (!mProxy)
mProxy = new nsCWeakProxy(mRealThing, this);
return mProxy;
}
/************ a reference proxy whose lifetime we control ***********/
/* the nsCWeakProxy object is an object whose creation and lifetime is
under our control, unlike the nsCWeakReferent and its family of
nsCWeakReferences. An nsCWeakProxy is created by the nsCWeakReferent
when the first weak reference is necessary, and refcounted for each
additional reference. It knows about the lifetime of the nsCWeakReferent,
and deletes itself once all weak references have been broken.
*/
nsCWeakProxy::nsCWeakProxy(void *aRealThing, nsCWeakReferent *aReferent) :
mRealPointer(aRealThing),
mReferent(aReferent),
mRefCount(0) {
NS_ASSERTION(aRealThing && aReferent, "weak proxy constructed with null ptr");
}
nsCWeakProxy::~nsCWeakProxy() {
if (mReferent)
mReferent->ProxyDeleted();
}
void nsCWeakProxy::ReleaseReference() {
if (--mRefCount == 0) {
delete this;
}
}

View File

@@ -1,171 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code,
* released March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsCWeakReference_h___
#define nsCWeakReference_h___
#include "nsDebug.h"
/* A set of support classes for defining weak references, rather like
nsIWeakReference, but for use with non-COM objects.
Expected use is when an object, call it A, holds a reference to an object B,
and B may be unexpectedly deleted from underneath A. To use these classes
to solve that problem, add an nsCWeakReferent member variable to B and
construct that member in B's constructor. (B::B():mWeakRef(this)).
Hold an nsCWeakReference<B> variable in A, rather than a B directly, and
dereference B from that variable afresh each time that B may have been
deleted.
*/
class nsCWeakProxy;
/* An object wishing to support weak references to itself has an nsCWeakReferent
member variable and provides an accessor for getting to it. Notice that
nsCWeakReferent has no default constructor, so must be initialized with
a pointer to the object.
*/
class NS_COM nsCWeakReferent {
public:
nsCWeakReferent(void *aRealThing);
virtual ~nsCWeakReferent();
void SetReferent(void *aRealThing);
nsCWeakProxy *GetProxy();
void ProxyDeleted()
{ mProxy = 0; }
private:
// copy and assignment constructors can't be implemented without help
// from the containing class, so they're made inaccessible, forcing
// the container to address this issue explicitly.
nsCWeakReferent(const nsCWeakReferent &aOriginal);
nsCWeakReferent& operator= (const nsCWeakReferent &aOriginal);
void *mRealThing;
nsCWeakProxy *mProxy;
};
/* The nsCWeakProxy object is an object whose creation and lifetime is
under our control, unlike the nsCWeakReferent and its family of
nsCWeakReferences. An nsCWeakProxy is created by the nsCWeakReferent
when the first weak reference is necessary, and refcounted for each
additional reference. It knows about the lifetime of the nsCWeakReferent,
and deletes itself once all weak references have been broken.
This is an internal-use class; clients need not use it or ever see it.
*/
class NS_COM nsCWeakProxy {
public:
nsCWeakProxy(void *aRealThing, nsCWeakReferent *aReferent);
virtual ~nsCWeakProxy();
void *Reference()
{ return mRealPointer; }
void AddReference()
{ ++mRefCount; }
void ReleaseReference();
void RealThingDeleted()
{ mRealPointer = 0; mReferent = 0; }
private:
void *mRealPointer;
nsCWeakReferent *mReferent;
PRUint32 mRefCount;
};
/* internal use only: there's no need for clients to use this class */
class nsCWeakReferenceBase {
public:
nsCWeakReferenceBase() {};
virtual ~nsCWeakReferenceBase() {};
};
/* This class is the actual weak reference. Clients hold one of these
and access the actual object by dereferencing this weak reference
using operator*, operator-> or Reference().
*/
template<class T> class nsCWeakReference : public nsCWeakReferenceBase {
public:
nsCWeakReference()
{ mProxy = 0; }
nsCWeakReference(nsCWeakReferent *aReferent) {
mProxy = 0;
SetReference(aReferent);
}
nsCWeakReference(const nsCWeakReference<T> &aOriginal) {
mProxy = aOriginal.mProxy;
if (mProxy)
mProxy->AddReference();
}
nsCWeakReference<T>& operator= (const nsCWeakReference<T> &aOriginal) {
nsCWeakProxy *temp = mProxy;
mProxy = aOriginal.mProxy;
if (mProxy)
mProxy->AddReference();
if (temp)
temp->ReleaseReference();
return *this;
}
T& operator*() const {
NS_ASSERTION(mProxy, "weak reference used without being set");
return (T&) *(T*)mProxy->Reference();
}
T* operator->() const {
NS_ASSERTION(mProxy, "weak reference used without being set");
return (T*) mProxy->Reference();
}
virtual ~nsCWeakReference() {
mProxy->ReleaseReference();
}
T* Reference() {
NS_ASSERTION(mProxy, "weak reference used without being set");
return (T*) mProxy->Reference();
}
void SetReference(nsCWeakReferent *aReferent) {
NS_ASSERTION(aReferent, "weak reference set with null referent");
if (mProxy)
mProxy->ReleaseReference();
mProxy = aReferent->GetProxy();
NS_ASSERTION(mProxy, "weak reference proxy allocation failed");
mProxy->AddReference();
}
private:
nsCWeakProxy *mProxy;
};
#endif

View File

@@ -66,7 +66,6 @@
#include "nsIGenericFactory.h"
#include "nsIPipe.h"
#include "nsStreamUtils.h"
#include "nsCWeakReference.h"
#include "nsWeakReference.h"
#include "nsTextFormatter.h"
#include "nsIStorageStream.h"
@@ -139,8 +138,6 @@ void XXXNeverCalled()
XPTI_GetInterfaceInfoManager();
NS_NewGenericFactory(nsnull, nsnull);
NS_NewGenericModule2(nsnull, nsnull);
nsCWeakProxy(0, 0);
nsCWeakReferent(0);
NS_GetWeakReference(nsnull);
nsCOMPtr<nsISupports> dummyFoo(do_GetInterface(nsnull));
NS_NewByteArrayInputStream(nsnull, nsnull, 0);