From cc9e6f290f6f50b8c9f9451d5754bbc84bd537fb Mon Sep 17 00:00:00 2001 From: "kipp%netscape.com" Date: Tue, 21 Jul 1998 16:44:45 +0000 Subject: [PATCH] Support aggregation (sort of) --- docshell/base/nsWebShell.cpp | 27 +++++++-- webshell/src/nsThrobber.cpp | 112 ++++++++++++++++++++++++++++++----- webshell/src/nsWebShell.cpp | 27 +++++++-- 3 files changed, 142 insertions(+), 24 deletions(-) diff --git a/docshell/base/nsWebShell.cpp b/docshell/base/nsWebShell.cpp index e30665804fa9..39bbe1f01bff 100644 --- a/docshell/base/nsWebShell.cpp +++ b/docshell/base/nsWebShell.cpp @@ -155,6 +155,7 @@ protected: nsIContentViewer* mContentViewer; nsIDeviceContext* mDeviceContext; nsIWidget* mWindow; + nsISupports* mInnerWindow; nsIDocumentLoader* mDocLoader; nsIWebShell* mParent; @@ -206,6 +207,8 @@ nsWebShell::nsWebShell() nsWebShell::~nsWebShell() { + NS_IF_RELEASE(mInnerWindow); + NS_IF_RELEASE(mContentViewer); NS_IF_RELEASE(mContainer); @@ -262,6 +265,9 @@ nsWebShell::QueryInterface(REFNSIID aIID, void** aInstancePtr) AddRef(); return NS_OK; } + if (nsnull != mInnerWindow) { + return mInnerWindow->QueryInterface(aIID, aInstancePtr); + } return NS_NOINTERFACE; } @@ -324,7 +330,8 @@ nsWebShell::Init(nsNativeWidget aNativeParent, WEB_TRACE(WEB_TRACE_CALLS, ("nsWebShell::Init: this=%p", this)); - nsresult rv = NSRepository::CreateInstance(kDocumentLoaderCID, nsnull, + nsresult rv = NSRepository::CreateInstance(kDocumentLoaderCID, + nsnull, kIDocumentLoaderIID, (void**)&mDocLoader); @@ -347,13 +354,23 @@ nsWebShell::Init(nsNativeWidget aNativeParent, mDeviceContext->SetGamma(1.7f); // Create a Native window for the shell container... - rv = NSRepository::CreateInstance(kChildCID, nsnull, kIWidgetIID, - (void**)&mWindow); + rv = NSRepository::CreateInstance(kChildCID, + (nsISupports*)((nsIWebShell*)this), + kISupportsIID, + (void**)&mInnerWindow); if (NS_OK != rv) { goto done; } - mWindow->Create(aNativeParent, aBounds, nsWebShell::HandleEvent, - mDeviceContext, nsnull); + mInnerWindow->QueryInterface(kIWidgetIID, (void**) &mWindow); + if (NS_OK != rv) { + NS_RELEASE(mInnerWindow); + } + else { + // Get rid of extra reference count + mWindow->Release(); + mWindow->Create(aNativeParent, aBounds, nsWebShell::HandleEvent, + mDeviceContext, nsnull); + } done: return rv; diff --git a/webshell/src/nsThrobber.cpp b/webshell/src/nsThrobber.cpp index 73706fbdd153..3f27d8556901 100644 --- a/webshell/src/nsThrobber.cpp +++ b/webshell/src/nsThrobber.cpp @@ -35,7 +35,7 @@ static NS_DEFINE_IID(kChildCID, NS_CHILD_CID); static NS_DEFINE_IID(kThrobberCID, NS_THROBBER_CID); -static NS_DEFINE_IID(kIChildWidgetIID, NS_IWIDGET_IID); +static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID); static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID); static NS_DEFINE_IID(kIImageObserverIID, NS_IIMAGEREQUESTOBSERVER_IID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); @@ -46,9 +46,12 @@ static NS_DEFINE_IID(kIThrobberIID, NS_ITHROBBER_IID); static nsVoidArray gThrobbers; +#define INNER_OUTER \ + ((nsThrobber*)((char*)this - offsetof(nsThrobber, mInner))) + class nsThrobber : public nsIThrobber { public: - nsThrobber(); + nsThrobber(nsISupports* aOuter); void* operator new(size_t sz) { void* rv = new char[sz]; @@ -78,11 +81,65 @@ public: PRInt32 mWidth; PRInt32 mHeight; nsIWidget* mWidget; + nsISupports* mInnerWidget; nsVoidArray* mImages; PRInt32 mIndex; nsIImageGroup* mImageGroup; nsITimer* mTimer; PRBool mRunning; + + nsISupports *mOuter; + + nsrefcnt AddRefObject() { + return ++mRefCnt; + } + + nsrefcnt ReleaseObject() { + NS_PRECONDITION(0 != mRefCnt, "dup release"); + if (--mRefCnt == 0) { + delete this; + return 0; + } + return mRefCnt; + } + + nsresult QueryObject(const nsIID& aIID, void** aInstancePtr) { + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(kIThrobberIID)) { + *aInstancePtr = (void*)(nsIThrobber*)this; + AddRef(); + return NS_OK; + } + if (aIID.Equals(kISupportsIID)) { + *aInstancePtr = (void*)(nsISupports*)this; + AddRef(); + return NS_OK; + } + if (nsnull != mInnerWidget) { + return mInnerWidget->QueryInterface(aIID, aInstancePtr); + } + return NS_NOINTERFACE; + } + + // This is used when we are not aggregated in + class InnerSupport : public nsISupports { + public: + InnerSupport() {} + + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr) { + return INNER_OUTER->QueryObject(aIID, aInstancePtr); + } + + NS_IMETHOD_(nsrefcnt) AddRef() { + return INNER_OUTER->AddRefObject(); + } + + NS_IMETHOD_(nsrefcnt) Release() { + return INNER_OUTER->ReleaseObject(); + } + } mInner; }; class ThrobObserver : public nsIImageRequestObserver { @@ -212,17 +269,40 @@ HandleThrobberEvent(nsGUIEvent *aEvent) //---------------------------------------------------------------------- // Note: operator new zeros our memory -nsThrobber::nsThrobber() +nsThrobber::nsThrobber(nsISupports* aOuter) { + // assign outer + if (aOuter) + mOuter = aOuter; + else + mOuter = &mInner; + AddThrobber(this); } nsThrobber::~nsThrobber() { + NS_IF_RELEASE(mInnerWidget); RemoveThrobber(this); } -NS_IMPL_ISUPPORTS(nsThrobber, kIThrobberIID); +nsrefcnt +nsThrobber::AddRef() +{ + return mOuter->AddRef(); +} + +nsrefcnt +nsThrobber::Release() +{ + return mOuter->Release(); +} + +nsresult +nsThrobber::QueryInterface(REFNSIID aIID, void** aInstancePtr) +{ + return mOuter->QueryInterface(aIID, aInstancePtr); +} NS_IMETHODIMP nsThrobber::Init(nsIWidget* aParent, const nsRect& aBounds) @@ -231,14 +311,22 @@ nsThrobber::Init(nsIWidget* aParent, const nsRect& aBounds) mHeight = aBounds.height; // Create widget - nsresult rv = NSRepository::CreateInstance(kChildCID, nsnull, - kIChildWidgetIID, - (void**)&mWidget); + nsresult rv = NSRepository::CreateInstance(kChildCID, + this, + kISupportsIID, + (void**)&mInnerWidget); if (NS_OK != rv) { return rv; } - - mWidget->Create(aParent, aBounds, HandleThrobberEvent, NULL); + mInnerWidget->QueryInterface(kIWidgetIID, (void**) &mWidget); + if (NS_OK != rv) { + NS_RELEASE(mInnerWidget); + } + else { + // Get rid of extra reference count + mWidget->Release(); + mWidget->Create(aParent, aBounds, HandleThrobberEvent, NULL); + } return LoadThrobberImages(); } @@ -492,12 +580,8 @@ nsThrobberFactory::CreateInstance(nsISupports *aOuter, return NS_ERROR_NULL_POINTER; } *aResult = NULL; - if (nsnull != aOuter) { - rv = NS_ERROR_NO_AGGREGATION; - goto done; - } - inst = new nsThrobber(); + inst = new nsThrobber(aOuter); if (inst == NULL) { rv = NS_ERROR_OUT_OF_MEMORY; goto done; diff --git a/webshell/src/nsWebShell.cpp b/webshell/src/nsWebShell.cpp index e30665804fa9..39bbe1f01bff 100644 --- a/webshell/src/nsWebShell.cpp +++ b/webshell/src/nsWebShell.cpp @@ -155,6 +155,7 @@ protected: nsIContentViewer* mContentViewer; nsIDeviceContext* mDeviceContext; nsIWidget* mWindow; + nsISupports* mInnerWindow; nsIDocumentLoader* mDocLoader; nsIWebShell* mParent; @@ -206,6 +207,8 @@ nsWebShell::nsWebShell() nsWebShell::~nsWebShell() { + NS_IF_RELEASE(mInnerWindow); + NS_IF_RELEASE(mContentViewer); NS_IF_RELEASE(mContainer); @@ -262,6 +265,9 @@ nsWebShell::QueryInterface(REFNSIID aIID, void** aInstancePtr) AddRef(); return NS_OK; } + if (nsnull != mInnerWindow) { + return mInnerWindow->QueryInterface(aIID, aInstancePtr); + } return NS_NOINTERFACE; } @@ -324,7 +330,8 @@ nsWebShell::Init(nsNativeWidget aNativeParent, WEB_TRACE(WEB_TRACE_CALLS, ("nsWebShell::Init: this=%p", this)); - nsresult rv = NSRepository::CreateInstance(kDocumentLoaderCID, nsnull, + nsresult rv = NSRepository::CreateInstance(kDocumentLoaderCID, + nsnull, kIDocumentLoaderIID, (void**)&mDocLoader); @@ -347,13 +354,23 @@ nsWebShell::Init(nsNativeWidget aNativeParent, mDeviceContext->SetGamma(1.7f); // Create a Native window for the shell container... - rv = NSRepository::CreateInstance(kChildCID, nsnull, kIWidgetIID, - (void**)&mWindow); + rv = NSRepository::CreateInstance(kChildCID, + (nsISupports*)((nsIWebShell*)this), + kISupportsIID, + (void**)&mInnerWindow); if (NS_OK != rv) { goto done; } - mWindow->Create(aNativeParent, aBounds, nsWebShell::HandleEvent, - mDeviceContext, nsnull); + mInnerWindow->QueryInterface(kIWidgetIID, (void**) &mWindow); + if (NS_OK != rv) { + NS_RELEASE(mInnerWindow); + } + else { + // Get rid of extra reference count + mWindow->Release(); + mWindow->Create(aNativeParent, aBounds, nsWebShell::HandleEvent, + mDeviceContext, nsnull); + } done: return rv;