diff --git a/content/base/src/nsContentSink.cpp b/content/base/src/nsContentSink.cpp index 58d6c840379..f6ac02ea29b 100644 --- a/content/base/src/nsContentSink.cpp +++ b/content/base/src/nsContentSink.cpp @@ -989,7 +989,8 @@ nsContentSink::StartLayout(PRBool aIsFrameset) if (vm) { nsIView* rootView = nsnull; vm->GetRootView(rootView); - nsCOMPtr sview(do_QueryInterface(rootView)); + nsIScrollableView* sview; + CallQueryInterface(rootView, &sview); if (sview) { sview->SetScrollPreference(nsScrollPreference_kNeverScroll); diff --git a/view/public/nsIScrollableView.h b/view/public/nsIScrollableView.h index 8ffc041fe95..383d51f1e72 100644 --- a/view/public/nsIScrollableView.h +++ b/view/public/nsIScrollableView.h @@ -38,7 +38,6 @@ #ifndef nsIScrollableView_h___ #define nsIScrollableView_h___ -#include "nsISupports.h" #include "nsCoord.h" #include "nsIViewManager.h" #include "nsIView.h" @@ -73,10 +72,12 @@ typedef enum { * child view created by the scrolling view). * */ -class nsIScrollableView : public nsISupports { +class nsIScrollableView { public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISCROLLABLEVIEW_IID) + NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) = 0; + /** * Create the controls used to allow scrolling. Call this method * before anything else is done with the scrollable view. diff --git a/view/public/nsIView.h b/view/public/nsIView.h index 416c2daa3a0..0278a6fbc9b 100644 --- a/view/public/nsIView.h +++ b/view/public/nsIView.h @@ -38,7 +38,6 @@ #ifndef nsIView_h___ #define nsIView_h___ -#include "nsISupports.h" #include "nsCoord.h" #include "nsRect.h" #include "nsPoint.h" @@ -141,10 +140,12 @@ struct nsViewZIndex { */ // hack to make egcs / gcc 2.95.2 happy -class nsIView_base : public nsISupports +class nsIView_base { public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_IVIEW_IID) + + NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) = 0; }; class nsIView : public nsIView_base @@ -375,10 +376,6 @@ public: virtual PRBool ExternalIsRoot() const; -private: - NS_IMETHOD_(nsrefcnt) AddRef(void) = 0; - NS_IMETHOD_(nsrefcnt) Release(void) = 0; - protected: nsViewManager *mViewManager; nsView *mParent; diff --git a/view/src/nsScrollPortView.cpp b/view/src/nsScrollPortView.cpp index 0ad7993d60c..85d81053dfd 100644 --- a/view/src/nsScrollPortView.cpp +++ b/view/src/nsScrollPortView.cpp @@ -123,17 +123,6 @@ nsresult nsScrollPortView::QueryInterface(const nsIID& aIID, void** aInstancePtr return nsView::QueryInterface(aIID, aInstancePtr); } -nsrefcnt nsScrollPortView::AddRef() -{ - return 1; -} - -nsrefcnt nsScrollPortView::Release() -{ - return 1; -} - - NS_IMETHODIMP nsScrollPortView::GetClipView(const nsIView** aClipView) const { *aClipView = this; diff --git a/view/src/nsScrollPortView.h b/view/src/nsScrollPortView.h index 6e2660b5356..70eba5606cb 100644 --- a/view/src/nsScrollPortView.h +++ b/view/src/nsScrollPortView.h @@ -94,8 +94,6 @@ public: nsView* GetScrolledView() const { return GetFirstChild(); } private: - NS_IMETHOD_(nsrefcnt) AddRef(void); - NS_IMETHOD_(nsrefcnt) Release(void); NS_IMETHOD ScrollToImpl(nscoord aX, nscoord aY, PRUint32 aUpdateFlags); // data members diff --git a/view/src/nsView.cpp b/view/src/nsView.cpp index b7fb37f0f39..1edec8de990 100644 --- a/view/src/nsView.cpp +++ b/view/src/nsView.cpp @@ -61,6 +61,50 @@ static nsEventStatus PR_CALLBACK HandleEvent(nsGUIEvent *aEvent); //#define SHOW_VIEW_BORDERS //#define HIDE_ALL_WIDGETS +// {34297A07-A8FD-d811-87C6-000244212BCB} +#define VIEW_WRAPPER_IID \ +{ 0x34297a07, 0xa8fd, 0xd811, { 0x87, 0xc6, 0x0, 0x2, 0x44, 0x21, 0x2b, 0xcb } }; + + +/** + * nsISupports-derived helper class that allows to store and get a view + */ +class ViewWrapper : public nsISupports +{ + public: + NS_DEFINE_STATIC_IID_ACCESSOR(VIEW_WRAPPER_IID) + NS_DECL_ISUPPORTS + + ViewWrapper(nsView* aView) : mView(aView) {} + + nsView* GetView() { return mView; } + private: + nsView* mView; +}; + +NS_IMPL_ISUPPORTS1(ViewWrapper, ViewWrapper); + +/** + * Given a widget, returns the stored ViewWrapper on it, or NULL if no + * ViewWrapper is there. + */ +static ViewWrapper* GetWrapperFor(nsIWidget* aWidget) +{ + // The widget's client data points back to the owning view + if (aWidget) { + void* clientData; + aWidget->GetClientData(clientData); + nsISupports* data = (nsISupports*)clientData; + + if (data) { + ViewWrapper* wrapper; + CallQueryInterface(data, &wrapper); + return wrapper; + } + } + return nsnull; +} + // // Main events handler // @@ -162,6 +206,10 @@ nsView::~nsView() // Destroy and release the widget if (mWindow) { + // Release memory for the view wrapper + ViewWrapper* wrapper = GetWrapperFor(mWindow); + NS_IF_RELEASE(wrapper); + mWindow->SetClientData(nsnull); mWindow->Destroy(); NS_RELEASE(mWindow); @@ -179,7 +227,7 @@ nsresult nsView::QueryInterface(const nsIID& aIID, void** aInstancePtr) *aInstancePtr = nsnull; - if (aIID.Equals(NS_GET_IID(nsIView)) || (aIID.Equals(NS_GET_IID(nsISupports)))) { + if (aIID.Equals(NS_GET_IID(nsIView))) { *aInstancePtr = (void*)(nsIView*)this; return NS_OK; } @@ -187,35 +235,13 @@ nsresult nsView::QueryInterface(const nsIID& aIID, void** aInstancePtr) return NS_NOINTERFACE; } -nsrefcnt nsView::AddRef() -{ - NS_WARNING("not supported for views"); - return 1; -} - -nsrefcnt nsView::Release() -{ - NS_WARNING("not supported for views"); - return 1; -} - nsView* nsView::GetViewFor(nsIWidget* aWidget) { NS_PRECONDITION(nsnull != aWidget, "null widget ptr"); - - // The widget's client data points back to the owning view - if (aWidget) { - void* clientData; - aWidget->GetClientData(clientData); - nsISupports* data = (nsISupports*)clientData; - - if (data) { - nsIView* view = nsnull; - if (NS_SUCCEEDED(data->QueryInterface(NS_GET_IID(nsIView), (void **)&view))) { - return NS_STATIC_CAST(nsView*, view); - } - } - } + + ViewWrapper* wrapper = GetWrapperFor(aWidget); + if (wrapper) + return wrapper->GetView(); return nsnull; } @@ -634,13 +660,23 @@ void nsView::SetZIndex(PRBool aAuto, PRInt32 aZIndex, PRBool aTopMost) NS_IMETHODIMP nsView::SetWidget(nsIWidget *aWidget) { + ViewWrapper* wrapper = new ViewWrapper(this); + if (!wrapper) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(wrapper); // Will be released in ~nsView or upon setting a new widget + + // Destroy any old wrappers if there are any + ViewWrapper* oldWrapper = GetWrapperFor(aWidget); + NS_IF_RELEASE(oldWrapper); + + NS_IF_RELEASE(mWindow); mWindow = aWidget; if (nsnull != mWindow) { NS_ADDREF(mWindow); - mWindow->SetClientData((void *)this); + mWindow->SetClientData(wrapper); } return NS_OK; @@ -651,11 +687,18 @@ NS_IMETHODIMP nsView::SetWidget(nsIWidget *aWidget) // nsresult nsView::LoadWidget(const nsCID &aClassIID) { - nsresult rv = nsComponentManager::CreateInstance(aClassIID, nsnull, NS_GET_IID(nsIWidget), (void**)&mWindow); + ViewWrapper* wrapper = new ViewWrapper(this); + if (!wrapper) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(wrapper); // Will be released in ~nsView - if (NS_OK == rv) { + nsresult rv = CallCreateInstance(aClassIID, &mWindow); + + if (NS_SUCCEEDED(rv)) { // Set the widget's client data - mWindow->SetClientData((void*)this); + mWindow->SetClientData(wrapper); + } else { + delete wrapper; } return rv; diff --git a/view/src/nsView.h b/view/src/nsView.h index 7656efd36cb..1f1f7228d58 100644 --- a/view/src/nsView.h +++ b/view/src/nsView.h @@ -62,7 +62,6 @@ public: NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW - // nsISupports NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); /** @@ -272,9 +271,6 @@ protected: nsIRegion* mDirtyRegion; PRPackedBool mChildRemoved; -private: - NS_IMETHOD_(nsrefcnt) AddRef(void); - NS_IMETHOD_(nsrefcnt) Release(void); }; #endif