From 019b4a5782aacb139f6897aed87f37dffc1ec9ae Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Fri, 20 Aug 2010 14:29:02 -0500 Subject: [PATCH] Bug 582057, part g: Split nsIView::CreateWidget into CreateWidget, CreateWidgetForParent, and CreateWidgetForPopup in preparation of eliminating IIDs here. sr=roc --- layout/base/nsCSSFrameConstructor.cpp | 4 +- layout/base/nsDocumentViewer.cpp | 19 ++- layout/base/nsPresShell.cpp | 4 +- layout/generic/nsFrameFrame.cpp | 2 +- layout/printing/nsPrintEngine.cpp | 13 +- layout/xul/base/src/nsMenuPopupFrame.cpp | 8 +- view/public/nsIView.h | 50 +++++-- view/src/nsView.cpp | 169 +++++++++++++++++------ view/src/nsView.h | 22 ++- 9 files changed, 205 insertions(+), 86 deletions(-) diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index bf43335cb26..1a454b3a4a6 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -3264,10 +3264,10 @@ nsCSSFrameConstructor::InitializeSelectFrame(nsFrameConstructorState& aState, #if defined(XP_MACOSX) || defined(XP_BEOS) static NS_DEFINE_IID(kCPopUpCID, NS_POPUP_CID); - view->CreateWidget(kCPopUpCID, &widgetData, nsnull); + view->CreateWidgetForPopup(kCPopUpCID, &widgetData); #else static NS_DEFINE_IID(kCChildCID, NS_CHILD_CID); - view->CreateWidget(kCChildCID, &widgetData, nsnull); + view->CreateWidgetForPopup(kCChildCID, &widgetData); #endif } } diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index 2feec7fd61a..ed0e57c9b23 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -2320,9 +2320,13 @@ DocumentViewerImpl::MakeWindow(const nsSize& aSize, nsIView* aContainerView) if (!view) return NS_ERROR_OUT_OF_MEMORY; - // Don't create a widget if we weren't given a parent widget but we - // have a container view we can hook up to without a widget - if (mParentWidget || !aContainerView) { + PRBool isExternalResource = !!mDocument->GetDisplayDocument(); + + // Create a widget if we were given a parent widget or don't have a + // container view that we can hook up to without a widget. Don't + // create widgets for external resource documents, since they're not + // displayed. + if (!isExternalResource && (mParentWidget || !aContainerView)) { // pass in a native widget to be the parent widget ONLY if the view hierarchy will stand alone. // otherwise the view will find its own parent widget and "do the right thing" to // establish a parent/child widget relationship @@ -2343,11 +2347,12 @@ DocumentViewerImpl::MakeWindow(const nsSize& aSize, nsIView* aContainerView) // Reuse the top level parent widget. rv = view->AttachToTopLevelWidget(mParentWidget); } + else if (!aContainerView && mParentWidget) { + rv = view->CreateWidgetForParent(kWidgetCID, mParentWidget, initDataPtr, + PR_TRUE, PR_FALSE); + } else { - nsNativeWidget nw = (aContainerView != nsnull || !mParentWidget) ? - nsnull : mParentWidget->GetNativeData(NS_NATIVE_WIDGET); - rv = view->CreateWidget(kWidgetCID, initDataPtr, - nw, PR_TRUE, PR_FALSE); + rv = view->CreateWidget(kWidgetCID, initDataPtr, PR_TRUE, PR_FALSE); } if (NS_FAILED(rv)) return rv; diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 8e33d81b6bf..9814eeb4a64 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -8268,7 +8268,7 @@ PresShell::VerifyIncrementalReflow() nsIView* rootView; mViewManager->GetRootView(rootView); NS_ENSURE_TRUE(rootView->HasWidget(), PR_FALSE); - void* nativeParentWidget = rootView->GetWidget()->GetNativeData(NS_NATIVE_WIDGET); + nsIWidget* parentWidget = rootView->GetWidget(); // Create a new view manager. nsCOMPtr vm = do_CreateInstance(kViewManagerCID); @@ -8283,7 +8283,7 @@ PresShell::VerifyIncrementalReflow() NS_ENSURE_TRUE(view, PR_FALSE); //now create the widget for the view - rv = view->CreateWidget(kWidgetCID, nsnull, nativeParentWidget, PR_TRUE); + rv = view->CreateWidgetForParent(kWidgetCID, parentWidget, nsnull, PR_TRUE); NS_ENSURE_SUCCESS(rv, PR_FALSE); // Setup hierarchical relationship in view manager diff --git a/layout/generic/nsFrameFrame.cpp b/layout/generic/nsFrameFrame.cpp index cc57195388c..3cf991a8390 100644 --- a/layout/generic/nsFrameFrame.cpp +++ b/layout/generic/nsFrameFrame.cpp @@ -967,7 +967,7 @@ nsSubDocumentFrame::CreateViewAndWidget(nsContentType aContentType) if (aContentType == eContentTypeContent) { // widget needed. - nsresult rv = innerView->CreateWidget(kCChildCID, nsnull, nsnull, + nsresult rv = innerView->CreateWidget(kCChildCID, nsnull, PR_TRUE, PR_TRUE, aContentType); if (NS_FAILED(rv)) { NS_WARNING("Couldn't create widget for frame."); diff --git a/layout/printing/nsPrintEngine.cpp b/layout/printing/nsPrintEngine.cpp index 0bbc9a66f8c..bb42c0a3306 100644 --- a/layout/printing/nsPrintEngine.cpp +++ b/layout/printing/nsPrintEngine.cpp @@ -1996,12 +1996,15 @@ nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO) // unnecessary and unexpected // Also, no widget should be needed except for the top-level document if (mIsCreatingPrintPreview && documentIsTopLevel) { - nsNativeWidget widget = nsnull; + nsIWidget* widget = nsnull; if (!frame) - widget = mParentWidget->GetNativeData(NS_NATIVE_WIDGET); - rv = rootView->CreateWidget(kWidgetCID, nsnull, - widget, PR_TRUE, PR_TRUE, - eContentTypeContent); + widget = mParentWidget; + rv = widget ? rootView->CreateWidgetForParent(kWidgetCID, widget, nsnull, + PR_TRUE, PR_TRUE, + eContentTypeContent) + : rootView->CreateWidget(kWidgetCID, nsnull, + PR_TRUE, PR_TRUE, + eContentTypeContent); NS_ENSURE_SUCCESS(rv, rv); aPO->mWindow = rootView->GetWidget(); aPO->mPresContext->SetPaginatedScrolling(canCreateScrollbars); diff --git a/layout/xul/base/src/nsMenuPopupFrame.cpp b/layout/xul/base/src/nsMenuPopupFrame.cpp index b28b2869a0e..45914bee965 100644 --- a/layout/xul/base/src/nsMenuPopupFrame.cpp +++ b/layout/xul/base/src/nsMenuPopupFrame.cpp @@ -322,12 +322,12 @@ nsMenuPopupFrame::CreateWidgetForView(nsIView* aView) #if defined(XP_MACOSX) || defined(XP_BEOS) static NS_DEFINE_IID(kCPopupCID, NS_POPUP_CID); - aView->CreateWidget(kCPopupCID, &widgetData, nsnull, PR_TRUE, PR_TRUE, - eContentTypeUI, parentWidget); + aView->CreateWidgetForPopup(kCPopupCID, &widgetData, parentWidget, + PR_TRUE, PR_TRUE, eContentTypeUI); #else static NS_DEFINE_IID(kCChildCID, NS_CHILD_CID); - aView->CreateWidget(kCChildCID, &widgetData, nsnull, PR_TRUE, PR_TRUE, - eContentTypeInherit, parentWidget); + aView->CreateWidgetForPopup(kCChildCID, &widgetData, parentWidget, + PR_TRUE, PR_TRUE, eContentTypeInherit); #endif nsIWidget* widget = aView->GetWidget(); widget->SetTransparencyMode(mode); diff --git a/view/public/nsIView.h b/view/public/nsIView.h index 5dc34c6b6ec..4a79a254549 100644 --- a/view/public/nsIView.h +++ b/view/public/nsIView.h @@ -61,10 +61,9 @@ enum nsViewVisibility { nsViewVisibility_kShow = 1 }; -// IID for the nsIView interface #define NS_IVIEW_IID \ - { 0xfb9900df, 0x5956, 0x4175, \ - { 0x83, 0xba, 0x05, 0x74, 0x31, 0x96, 0x61, 0xee } } + { 0x01258624, 0xca90, 0x47a4, \ + { 0xb1, 0xfd, 0x52, 0x11, 0x26, 0xe6, 0xc8, 0xdc } } // Public view flags are defined in this file #define NS_VIEW_FLAGS_PUBLIC 0x00FF @@ -276,29 +275,50 @@ public: virtual nsIWidget* GetNearestWidget(nsPoint* aOffset) const; /** - * Create a widget to associate with this view. + * Create a widget to associate with this view. This variant of + * CreateWidget*() will look around in the view hierarchy for an + * appropriate parent widget for the view. + * * @param aWindowIID IID for Widget type that this view - * should have associated with it. if nsull, then no - * width will be created for this view + * should have associated with it. * @param aWidgetInitData data used to initialize this view's widget before * its create is called. - * @param aNative native window that will be used as parent of - * aWindowIID. if nsnull, then parent will be derived from - * parent view and it's ancestors - * @param aWindowType is either content, UI or inherit from parent window. + * @param aContentType is either content, UI or inherit from parent window. * This is used to expose what type of window this is to * assistive technology like screen readers. - * @param aParentWidget alternative parent to aNative used for popups. Must - * be null for non-popups. * @return error status */ nsresult CreateWidget(const nsIID &aWindowIID, nsWidgetInitData *aWidgetInitData = nsnull, - nsNativeWidget aNative = nsnull, PRBool aEnableDragDrop = PR_TRUE, PRBool aResetVisibility = PR_TRUE, - nsContentType aWindowType = eContentTypeInherit, - nsIWidget* aParentWidget = nsnull); + nsContentType aContentType = eContentTypeInherit); + + /** + * Create a widget for this view with an explicit parent widget. + * |aParentWidget| must be nonnull. The other params are the same + * as for |CreateWidget()|. + */ + nsresult CreateWidgetForParent(const nsIID &aWindowIID, + nsIWidget* aParentWidget, + nsWidgetInitData *aWidgetInitData = nsnull, + PRBool aEnableDragDrop = PR_TRUE, + PRBool aResetVisibility = PR_TRUE, + nsContentType aContentType = eContentTypeInherit); + + /** + * Create a popup widget for this view. Pass |aParentWidget| to + * explicitly set the popup's parent. If it's not passed, the view + * hierarchy will be searched for an appropriate parent widget. The + * other params are the same as for |CreateWidget()|, except that + * |aWidgetInitData| must be nonnull. + */ + nsresult CreateWidgetForPopup(const nsIID &aWindowIID, + nsWidgetInitData *aWidgetInitData, + nsIWidget* aParentWidget = nsnull, + PRBool aEnableDragDrop = PR_TRUE, + PRBool aResetVisibility = PR_TRUE, + nsContentType aContentType = eContentTypeInherit); /** * Attach/detach a top level widget from this view. When attached, the view diff --git a/view/src/nsView.cpp b/view/src/nsView.cpp index 828e679f068..6840bb3315a 100644 --- a/view/src/nsView.cpp +++ b/view/src/nsView.cpp @@ -660,33 +660,50 @@ static PRInt32 FindNonAutoZIndex(nsView* aView) nsresult nsIView::CreateWidget(const nsIID &aWindowIID, nsWidgetInitData *aWidgetInitData, - nsNativeWidget aNative, PRBool aEnableDragDrop, PRBool aResetVisibility, - nsContentType aContentType, - nsIWidget* aParentWidget) + nsContentType aContentType) { - return Impl()->CreateWidget(aWindowIID, aWidgetInitData, aNative, + return Impl()->CreateWidget(aWindowIID, aWidgetInitData, aEnableDragDrop, aResetVisibility, - aContentType, aParentWidget); + aContentType); +} + +nsresult nsIView::CreateWidgetForParent(const nsIID &aWindowIID, + nsIWidget* aParentWidget, + nsWidgetInitData *aWidgetInitData, + PRBool aEnableDragDrop, + PRBool aResetVisibility, + nsContentType aContentType) +{ + return Impl()->CreateWidgetForParent(aWindowIID, aParentWidget, + aWidgetInitData, + aEnableDragDrop, aResetVisibility, + aContentType); +} + +nsresult nsIView::CreateWidgetForPopup(const nsIID &aWindowIID, + nsWidgetInitData *aWidgetInitData, + nsIWidget* aParentWidget, + PRBool aEnableDragDrop, + PRBool aResetVisibility, + nsContentType aContentType) +{ + return Impl()->CreateWidgetForPopup(aWindowIID, aWidgetInitData, + aParentWidget, + aEnableDragDrop, aResetVisibility, + aContentType); } nsresult nsView::CreateWidget(const nsIID &aWindowIID, nsWidgetInitData *aWidgetInitData, - nsNativeWidget aNative, PRBool aEnableDragDrop, PRBool aResetVisibility, - nsContentType aContentType, - nsIWidget* aParentWidget) + nsContentType aContentType) { - if (NS_UNLIKELY(mWindow)) { - NS_ERROR("We already have a window for this view? BAD"); - ViewWrapper* wrapper = GetWrapperFor(mWindow); - NS_IF_RELEASE(wrapper); - mWindow->SetClientData(nsnull); - mWindow->Destroy(); - NS_RELEASE(mWindow); - } + NS_ABORT_IF_FALSE(!aWidgetInitData || + aWidgetInitData->mWindowType != eWindowType_popup, + "Use CreateWidgetForPopup"); nsresult rv = LoadWidget(aWindowIID); if (NS_FAILED(rv)) { @@ -710,38 +727,91 @@ nsresult nsView::CreateWidget(const nsIID &aWindowIID, nsCOMPtr dx; mViewManager->GetDeviceContext(*getter_AddRefs(dx)); - if (aWidgetInitData->mWindowType == eWindowType_popup) { - if (aParentWidget) { - mWindow->Create(aParentWidget, nsnull, trect, - ::HandleEvent, dx, nsnull, nsnull, aWidgetInitData); - } - else { - // XXX/cjones: having these two separate creation cases seems - // ... um ... unnecessary, but it's the way the old code did it. - // Please unify them by first finding a suitable parent nsIWidget, - // then passing only either the non-null parentWidget or the - // native ID to Create(). - nsIWidget* nearestParent = GetParent() ? GetParent()->GetNearestWidget(nsnull) - : nsnull; - if (!nearestParent) { - // Without a parent, we can't make a popup. This can happen - // when printing - return NS_ERROR_FAILURE; - } + initData.mListenForResizes = (!initDataPassedIn && GetParent() && + GetParent()->GetViewManager() != mViewManager); - mWindow->Create(nsnull, nearestParent->GetNativeData(NS_NATIVE_WIDGET), trect, - ::HandleEvent, dx, nsnull, nsnull, aWidgetInitData); - } + nsIWidget* parentWidget = + GetParent() ? GetParent()->GetNearestWidget(nsnull) : nsnull; + + mWindow->Create(parentWidget, nsnull, + trect, ::HandleEvent, dx, nsnull, nsnull, aWidgetInitData); + + InitializeWindow(aEnableDragDrop, aResetVisibility); + + return NS_OK; +} + +nsresult nsView::CreateWidgetForParent(const nsIID &aWindowIID, + nsIWidget* aParentWidget, + nsWidgetInitData *aWidgetInitData, + PRBool aEnableDragDrop, + PRBool aResetVisibility, + nsContentType aWindowType) +{ + NS_ABORT_IF_FALSE(!aWidgetInitData || + aWidgetInitData->mWindowType != eWindowType_popup, + "Use CreateWidgetForPopup"); + NS_ABORT_IF_FALSE(aParentWidget, "Parent widget required"); + + nsresult rv = LoadWidget(aWindowIID); + if (NS_FAILED(rv)) { + return rv; } - else if (aNative) { - mWindow->Create(nsnull, aNative, trect, ::HandleEvent, dx, nsnull, nsnull, aWidgetInitData); + + nsIntRect trect = CalcWidgetBounds( + aWidgetInitData ? aWidgetInitData->mWindowType : eWindowType_child); + + nsCOMPtr dx; + mViewManager->GetDeviceContext(*getter_AddRefs(dx)); + + mWindow->Create(nsnull, aParentWidget->GetNativeData(NS_NATIVE_WIDGET), + trect, ::HandleEvent, dx, nsnull, nsnull, aWidgetInitData); + + InitializeWindow(aEnableDragDrop, aResetVisibility); + + return NS_OK; +} + +nsresult nsView::CreateWidgetForPopup(const nsIID &aWindowIID, + nsWidgetInitData *aWidgetInitData, + nsIWidget* aParentWidget, + PRBool aEnableDragDrop, + PRBool aResetVisibility, + nsContentType aWindowType) +{ + NS_ABORT_IF_FALSE(aWidgetInitData, "Widget init data required"); + NS_ABORT_IF_FALSE(aWidgetInitData->mWindowType == eWindowType_popup, + "Use one of the other CreateWidget methods"); + + nsresult rv = LoadWidget(aWindowIID); + if (NS_FAILED(rv)) { + return rv; + } + + nsIntRect trect = CalcWidgetBounds(aWidgetInitData->mWindowType); + + nsCOMPtr dx; + mViewManager->GetDeviceContext(*getter_AddRefs(dx)); + + // XXX/cjones: having these two separate creation cases seems ... um + // ... unnecessary, but it's the way the old code did it. Please + // unify them by first finding a suitable parent nsIWidget, then + // passing only either the non-null parentWidget or the native ID to + // Create(). + if (aParentWidget) { + mWindow->Create(aParentWidget, nsnull, trect, + ::HandleEvent, dx, nsnull, nsnull, aWidgetInitData); } else { - initData.mListenForResizes = (!initDataPassedIn && GetParent() && - GetParent()->GetViewManager() != mViewManager); - nsIWidget* parentWidget = GetParent() ? GetParent()->GetNearestWidget(nsnull) - : nsnull; - mWindow->Create(parentWidget, nsnull, trect, + nsIWidget* nearestParent = GetParent() ? GetParent()->GetNearestWidget(nsnull) + : nsnull; + if (!nearestParent) { + // Without a parent, we can't make a popup. This can happen + // when printing + return NS_ERROR_FAILURE; + } + + mWindow->Create(nsnull, nearestParent->GetNativeData(NS_NATIVE_WIDGET), trect, ::HandleEvent, dx, nsnull, nsnull, aWidgetInitData); } @@ -751,7 +821,7 @@ nsresult nsView::CreateWidget(const nsIID &aWindowIID, } void -nsView::InitializeWindow(bool aEnableDragDrop, bool aResetVisibility) +nsView::InitializeWindow(PRBool aEnableDragDrop, PRBool aResetVisibility) { NS_ABORT_IF_FALSE(mWindow, "Must have a window to initialize"); @@ -841,7 +911,14 @@ void nsView::SetZIndex(PRBool aAuto, PRInt32 aZIndex, PRBool aTopMost) // nsresult nsView::LoadWidget(const nsCID &aClassIID) { - NS_ABORT_IF_FALSE(!mWindow, "Already have a widget?"); + if (NS_UNLIKELY(mWindow)) { + NS_ERROR("We already have a window for this view? BAD"); + ViewWrapper* wrapper = GetWrapperFor(mWindow); + NS_IF_RELEASE(wrapper); + mWindow->SetClientData(nsnull); + mWindow->Destroy(); + NS_RELEASE(mWindow); + } nsresult rv = CallCreateInstance(aClassIID, &mWindow); if (NS_FAILED(rv)) { diff --git a/view/src/nsView.h b/view/src/nsView.h index 76caeced888..15260c95000 100644 --- a/view/src/nsView.h +++ b/view/src/nsView.h @@ -120,11 +120,25 @@ public: // See nsIView::CreateWidget. nsresult CreateWidget(const nsIID &aWindowIID, nsWidgetInitData *aWidgetInitData, - nsNativeWidget aNative, PRBool aEnableDragDrop, PRBool aResetVisibility, - nsContentType aContentType, - nsIWidget* aParentWidget); + nsContentType aContentType); + + // See nsIView::CreateWidgetForParent. + nsresult CreateWidgetForParent(const nsIID &aWindowIID, + nsIWidget* aParentWidget, + nsWidgetInitData *aWidgetInitData, + PRBool aEnableDragDrop, + PRBool aResetVisibility, + nsContentType aContentType); + + // See nsIView::CreateWidgetForPopup. + nsresult CreateWidgetForPopup(const nsIID &aWindowIID, + nsWidgetInitData *aWidgetInitData, + nsIWidget* aParentWidget, + PRBool aEnableDragDrop, + PRBool aResetVisibility, + nsContentType aContentType); // NOT in nsIView, so only available in view module // These are also present in nsIView, but these versions return nsView and nsViewManager @@ -196,7 +210,7 @@ protected: nsRegion* mDirtyRegion; private: - void InitializeWindow(bool aEnableDragDrop, bool aResetVisibility); + void InitializeWindow(PRBool aEnableDragDrop, PRBool aResetVisibility); }; #endif