From 6c670f11899de9896df99379636ef75a936067af Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 30 Jul 2009 22:06:02 +1200 Subject: [PATCH] Backed out changeset c353fe809be0 --- layout/generic/nsContainerFrame.cpp | 9 ++++--- layout/generic/nsFrame.cpp | 9 +++++++ layout/generic/nsIFrame.h | 8 ++++-- layout/xul/base/src/nsBoxFrame.cpp | 12 +++++++++ layout/xul/base/src/nsDeckFrame.h | 4 +++ layout/xul/base/src/nsLeafBoxFrame.cpp | 12 +++++++++ view/public/nsIViewManager.h | 7 +---- view/src/nsView.cpp | 37 +++++++------------------- view/src/nsView.h | 4 --- view/src/nsViewManager.cpp | 25 ++++++++++++++--- 10 files changed, 80 insertions(+), 47 deletions(-) diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index 58f7a791ad9..f6f1423077b 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -617,10 +617,11 @@ nsContainerFrame::SyncFrameViewProperties(nsPresContext* aPresContext, if (!aStyleContext->GetStyleVisibility()->IsVisible() && !aFrame->SupportsVisibilityHidden()) { - // If it's a subdocument frame or a plugin, hide the view and - // any associated widget. - // These are leaf elements so this is OK, no descendant can be - // visibility:visible. + // If it's a scrollable frame that can't hide its scrollbars, + // hide the view. This means that child elements can't override + // their parent's visibility, but it's not practical to leave it + // visible in all cases because the scrollbars will be showing + // XXXldb Does the view system really enforce this correctly? viewIsVisible = PR_FALSE; } else if (IsMenuPopup(aFrame)) { // if the view is for a popup, don't show the view if the popup is closed diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 6168c7ed0ad..0d69168a530 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -6717,6 +6717,15 @@ nsFrame::SetParent(const nsIFrame* aParent) else if (wasBoxWrapped && !IsBoxWrapped()) DeleteProperty(nsGkAtoms::boxMetricsProperty); + if (aParent && aParent->IsBoxFrame()) { + if (aParent->ChildrenMustHaveWidgets()) { + nsHTMLContainerFrame::CreateViewForFrame(this, PR_TRUE); + nsIView* view = GetView(); + if (!view->HasWidget()) + CreateWidgetForView(view); + } + } + return NS_OK; } diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 6bea51a15af..def82baab31 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -107,9 +107,10 @@ struct nsMargin; typedef class nsIFrame nsIBox; // IID for the nsIFrame interface +// 7b437d20-a34e-11dd-ad8b-0800200c9a66 #define NS_IFRAME_IID \ - { 0x7e9018b5, 0x5405, 0x4e2b, \ - { 0x87, 0x67, 0xe2, 0xb4, 0xb1, 0x3e, 0xc1, 0x69 } } + { 0x7b437d20, 0xa34e, 0x11dd, \ + { 0xad, 0x8b, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } } /** * Indication of how the frame can be split. This is used when doing runaround @@ -2285,6 +2286,9 @@ NS_PTR_TO_INT32(frame->GetProperty(nsGkAtoms::embeddingLevel)) NS_IMETHOD DumpBox(FILE* out)=0; #endif + // Only nsDeckFrame requires that all its children have widgets + virtual PRBool ChildrenMustHaveWidgets() const { return PR_FALSE; } + /** * @return PR_TRUE if this text frame ends with a newline character. It * should return PR_FALSE if this is not a text frame. diff --git a/layout/xul/base/src/nsBoxFrame.cpp b/layout/xul/base/src/nsBoxFrame.cpp index fe6bd386ca0..5b2e4cefb11 100644 --- a/layout/xul/base/src/nsBoxFrame.cpp +++ b/layout/xul/base/src/nsBoxFrame.cpp @@ -205,6 +205,18 @@ nsBoxFrame::Init(nsIContent* aContent, MarkIntrinsicWidthsDirty(); + // see if we need a widget + if (aParent && aParent->IsBoxFrame()) { + if (aParent->ChildrenMustHaveWidgets()) { + rv = nsHTMLContainerFrame::CreateViewForFrame(this, PR_TRUE); + NS_ENSURE_SUCCESS(rv, rv); + + nsIView* view = GetView(); + if (!view->HasWidget()) + view->CreateWidget(kWidgetCID); + } + } + CacheAttributes(); #ifdef DEBUG_LAYOUT diff --git a/layout/xul/base/src/nsDeckFrame.h b/layout/xul/base/src/nsDeckFrame.h index 6fe832a83a0..741ba5315c1 100644 --- a/layout/xul/base/src/nsDeckFrame.h +++ b/layout/xul/base/src/nsDeckFrame.h @@ -75,6 +75,10 @@ public: virtual nsIAtom* GetType() const; +#ifndef MOZ_GFX_OPTIMIZE_MOBILE + virtual PRBool ChildrenMustHaveWidgets() const { return PR_TRUE; } +#endif + #ifdef NS_DEBUG NS_IMETHOD GetFrameName(nsAString& aResult) const { diff --git a/layout/xul/base/src/nsLeafBoxFrame.cpp b/layout/xul/base/src/nsLeafBoxFrame.cpp index 07448fe5743..dec1019d00c 100644 --- a/layout/xul/base/src/nsLeafBoxFrame.cpp +++ b/layout/xul/base/src/nsLeafBoxFrame.cpp @@ -98,6 +98,18 @@ nsLeafBoxFrame::Init( nsresult rv = nsLeafFrame::Init(aContent, aParent, aPrevInFlow); NS_ENSURE_SUCCESS(rv, rv); + // see if we need a widget + if (aParent && aParent->IsBoxFrame()) { + if (aParent->ChildrenMustHaveWidgets()) { + rv = nsHTMLContainerFrame::CreateViewForFrame(this, PR_TRUE); + NS_ENSURE_SUCCESS(rv, rv); + + nsIView* view = GetView(); + if (!view->HasWidget()) + view->CreateWidget(kWidgetCID); + } + } + mMouseThrough = unset; UpdateMouseThrough(); diff --git a/view/public/nsIViewManager.h b/view/public/nsIViewManager.h index ec4825e4c1b..840421b5e4f 100644 --- a/view/public/nsIViewManager.h +++ b/view/public/nsIViewManager.h @@ -256,12 +256,7 @@ public: PRBool aRepaintExposedAreaOnly = PR_FALSE) = 0; /** - * Set the visibility of a view. Hidden views have the effect of hiding - * their descendants as well. This does not affect painting, so layout - * is responsible for ensuring that content in hidden views is not - * painted nor handling events. It does affect the visibility of widgets; - * if a view is hidden, descendant views with widgets have their widgets - * hidden. + * Set the visibility of a view. * The view manager generates the appropriate dirty regions. * @param aView view to change visibility state of * @param visible new visibility state diff --git a/view/src/nsView.cpp b/view/src/nsView.cpp index 1fff95629f5..228e74597f2 100644 --- a/view/src/nsView.cpp +++ b/view/src/nsView.cpp @@ -52,6 +52,7 @@ static nsEventStatus HandleEvent(nsGUIEvent *aEvent); //#define SHOW_VIEW_BORDERS +//#define HIDE_ALL_WIDGETS // {34297A07-A8FD-d811-87C6-000244212BCB} #define VIEW_WRAPPER_IID \ @@ -337,15 +338,6 @@ void nsView::ResetWidgetBounds(PRBool aRecurse, PRBool aMoveOnly, } } -PRBool nsView::IsEffectivelyVisible() -{ - for (nsView* v = this; v; v = v->mParent) { - if (v->GetVisibility() == nsViewVisibility_kHide) - return PR_FALSE; - } - return PR_TRUE; -} - nsIntRect nsView::CalcWidgetBounds(nsWindowType aType) { nsCOMPtr dx; @@ -362,7 +354,7 @@ nsIntRect nsView::CalcWidgetBounds(nsWindowType aType) viewBounds += offset; if (parentWidget && aType == eWindowType_popup && - IsEffectivelyVisible()) { + mVis == nsViewVisibility_kShow) { nsIntPoint screenPoint = parentWidget->WidgetToScreenOffset(); viewBounds += nsPoint(NSIntPixelsToAppUnits(screenPoint.x, p2a), NSIntPixelsToAppUnits(screenPoint.y, p2a)); @@ -441,38 +433,29 @@ void nsView::SetDimensions(const nsRect& aRect, PRBool aPaint, PRBool aResizeWid } } -void nsView::NotifyEffectiveVisibilityChanged(PRBool aEffectivelyVisible) +NS_IMETHODIMP nsView::SetVisibility(nsViewVisibility aVisibility) { - if (!aEffectivelyVisible) + + mVis = aVisibility; + + if (aVisibility == nsViewVisibility_kHide) { DropMouseGrabbing(); } if (nsnull != mWindow) { - if (aEffectivelyVisible) +#ifndef HIDE_ALL_WIDGETS + if (mVis == nsViewVisibility_kShow) { DoResetWidgetBounds(PR_FALSE, PR_TRUE); mWindow->Show(PR_TRUE); } else +#endif mWindow->Show(PR_FALSE); } - for (nsView* child = mFirstChild; child; child = child->mNextSibling) { - if (child->mVis == nsViewVisibility_kHide) { - // It was effectively hidden and still is - continue; - } - // Our child is visible if we are - child->NotifyEffectiveVisibilityChanged(aEffectivelyVisible); - } -} - -NS_IMETHODIMP nsView::SetVisibility(nsViewVisibility aVisibility) -{ - mVis = aVisibility; - NotifyEffectiveVisibilityChanged(IsEffectivelyVisible()); return NS_OK; } diff --git a/view/src/nsView.h b/view/src/nsView.h index ad12aa1dade..8baf66500c5 100644 --- a/view/src/nsView.h +++ b/view/src/nsView.h @@ -166,8 +166,6 @@ public: void SetPositionIgnoringChildWidgets(nscoord aX, nscoord aY); nsresult LoadWidget(const nsCID &aClassIID); - void NotifyEffectiveVisibilityChanged(PRBool aEffectivelyVisible); - // Update the cached RootViewManager for all view manager descendents, // If the hierarchy is being removed, aViewManagerParent points to the view // manager for the hierarchy's old parent, and will have its mouse grab @@ -195,8 +193,6 @@ public: nsIntRect CalcWidgetBounds(nsWindowType aType); - PRBool IsEffectivelyVisible(); - protected: // Do the actual work of ResetWidgetBounds, unconditionally. Don't // call this method if we have no widget. diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp index eebb505cf6b..440ddfd1b3f 100644 --- a/view/src/nsViewManager.cpp +++ b/view/src/nsViewManager.cpp @@ -110,8 +110,14 @@ public: static PRBool IsViewVisible(nsView *aView) { - if (!aView->IsEffectivelyVisible()) - return PR_FALSE; + for (nsIView *view = aView; view; view = view->GetParent()) { + // We don't check widget visibility here because in the future (with + // the better approach to this that's in attachment 160801 on bug + // 227361), callers of the equivalent to this function should be able + // to rely on being notified when the result of this function changes. + if (view->GetVisibility() == nsViewVisibility_kHide) + return PR_FALSE; + } // Find out if the root view is visible by asking the view observer // (this won't be needed anymore if we link view trees across chrome / @@ -1225,7 +1231,8 @@ NS_IMETHODIMP nsViewManager::GrabMouseEvents(nsIView *aView, PRBool &aResult) // Along with nsView::SetVisibility, we enforce that the mouse grabber // can never be a hidden view. - if (aView && static_cast(aView)->IsEffectivelyVisible()) { + if (aView && static_cast(aView)->GetVisibility() + == nsViewVisibility_kHide) { aView = nsnull; } @@ -1580,6 +1587,16 @@ NS_IMETHODIMP nsViewManager::SetViewVisibility(nsIView *aView, nsViewVisibility } } } + + // Any child views not associated with frames might not get their visibility + // updated, so propagate our visibility to them. This is important because + // hidden views should have all hidden children. + for (nsView* childView = view->GetFirstChild(); childView; + childView = childView->GetNextSibling()) { + if (!childView->GetClientData()) { + childView->SetVisibility(aVisible); + } + } } return NS_OK; } @@ -1950,7 +1967,7 @@ NS_IMETHODIMP nsViewManager::GetRectVisibility(nsIView *aView, } // is this view even visible? - if (!view->IsEffectivelyVisible()) { + if (view->GetVisibility() == nsViewVisibility_kHide) { return NS_OK; }