diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 34a72d1c4f6..00307187545 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -3836,8 +3836,6 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, // 2) nsIScrollable::Scrollbar_Auto = scrollbars appear if needed // 3) nsIScrollable::Scrollbar_Always = scrollbars always // Only need to create a scroll frame/view for cases 2 and 3. - // Currently Scrollbar_Always isn't honored, as - // scrollportview::SetScrollPref is not implemented. PRBool isHTML = aDocElement->IsContentOfType(nsIContent::eHTML); PRBool isXUL = PR_FALSE; @@ -3856,6 +3854,11 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, isScrollable = PR_FALSE; } + // Don't create a scrollframe when we're inside a frame or iframe with + // scrolling="no". This makes the frame hierarchy inconsistent and is + // unnecessary for correctness (since + // nsGfxScrollFrameInner::GetScrollbarStyles handles all the necessary + // cases), but it seems to be needed for performance. if (isScrollable) { nsresult rv; if (aPresContext) { @@ -3864,12 +3867,13 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, nsCOMPtr scrollableContainer = do_QueryInterface(container, &rv); if (NS_SUCCEEDED(rv) && scrollableContainer) { PRInt32 scrolling = -1; - // XXX We should get prefs for X and Y and deal with these independently! scrollableContainer->GetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y,&scrolling); if (nsIScrollable::Scrollbar_Never == scrolling) { - isScrollable = PR_FALSE; + scrollableContainer->GetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X,&scrolling); + if (nsIScrollable::Scrollbar_Never == scrolling) { + isScrollable = PR_FALSE; + } } - // XXX NS_STYLE_OVERFLOW_SCROLL should create 'always on' scrollbars } } } diff --git a/mozilla/layout/base/public/nsIScrollableFrame.h b/mozilla/layout/base/public/nsIScrollableFrame.h index 6907cae2854..feb798e9210 100644 --- a/mozilla/layout/base/public/nsIScrollableFrame.h +++ b/mozilla/layout/base/public/nsIScrollableFrame.h @@ -67,10 +67,10 @@ public: struct ScrollbarStyles { // one of NS_STYLE_OVERFLOW_SCROLL, NS_STYLE_OVERFLOW_HIDDEN, - // NS_STYLE_OVERFLOW_VISIBLE, NS_STYLE_OVERFLOW_AUTO - PRInt32 mHorizontal; - PRInt32 mVertical; - ScrollbarStyles(PRInt32 h, PRInt32 v) : mHorizontal(h), mVertical(v) {} + // NS_STYLE_OVERFLOW_AUTO + PRUint8 mHorizontal, mVertical; + ScrollbarStyles(PRUint8 h, PRUint8 v) : mHorizontal(h), mVertical(v) {} + ScrollbarStyles() {} }; virtual ScrollbarStyles GetScrollbarStyles() const = 0; diff --git a/mozilla/layout/generic/nsGfxScrollFrame.cpp b/mozilla/layout/generic/nsGfxScrollFrame.cpp index 4608c28c76c..00c7d8dc942 100644 --- a/mozilla/layout/generic/nsGfxScrollFrame.cpp +++ b/mozilla/layout/generic/nsGfxScrollFrame.cpp @@ -45,6 +45,7 @@ #include "nsIServiceManager.h" #include "nsIView.h" #include "nsIScrollableView.h" +#include "nsIScrollable.h" #include "nsIViewManager.h" #include "nsHTMLContainerFrame.h" #include "nsWidgetsCID.h" @@ -1181,40 +1182,72 @@ NS_IMETHODIMP_(nsrefcnt) nsGfxScrollFrameInner::Release(void) NS_IMPL_QUERY_INTERFACE1(nsGfxScrollFrameInner, nsIScrollPositionListener) +static void HandleScrollPref(nsIScrollable *aScrollable, PRInt32 aOrientation, + PRUint8& aValue) +{ + PRInt32 pref; + aScrollable->GetDefaultScrollbarPreferences(aOrientation, &pref); + switch (pref) { + case nsIScrollable::Scrollbar_Auto: + // leave |aValue| untouched + break; + case nsIScrollable::Scrollbar_Never: + aValue = NS_STYLE_OVERFLOW_HIDDEN; + break; + case nsIScrollable::Scrollbar_Always: + aValue = NS_STYLE_OVERFLOW_SCROLL; + break; + } +} + +static nsGfxScrollFrameInner::ScrollbarStyles +ConvertOverflow(PRUint8 aOverflow) +{ + nsGfxScrollFrameInner::ScrollbarStyles result; + switch (aOverflow) { + case NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL: + result.mHorizontal = NS_STYLE_OVERFLOW_HIDDEN; + result.mVertical = NS_STYLE_OVERFLOW_SCROLL; + break; + case NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL: + result.mHorizontal = NS_STYLE_OVERFLOW_SCROLL; + result.mVertical = NS_STYLE_OVERFLOW_HIDDEN; + break; + default: + result.mHorizontal = aOverflow; + result.mVertical = aOverflow; + } + return result; +} + nsGfxScrollFrameInner::ScrollbarStyles nsGfxScrollFrameInner::GetScrollbarStylesFromFrame() const { - PRUint8 overflow; + ScrollbarStyles result; nsIFrame* parent = mOuter->GetParent(); if (parent && parent->GetType() == nsLayoutAtoms::viewportFrame && // Make sure we're actually the root scrollframe parent->GetFirstChild(nsnull) == NS_STATIC_CAST(const nsIFrame*, mOuter)) { - overflow = mOuter->GetPresContext()->GetViewportOverflowOverride(); + nsPresContext *presContext = mOuter->GetPresContext(); + result = ConvertOverflow(presContext->GetViewportOverflowOverride()); + + nsCOMPtr container = presContext->GetContainer(); + nsCOMPtr scrollable = do_QueryInterface(container); + HandleScrollPref(scrollable, nsIScrollable::ScrollOrientation_X, + result.mHorizontal); + HandleScrollPref(scrollable, nsIScrollable::ScrollOrientation_Y, + result.mVertical); } else { - overflow = mOuter->GetStyleDisplay()->mOverflow; + result = ConvertOverflow(mOuter->GetStyleDisplay()->mOverflow); } - switch (overflow) { - case NS_STYLE_OVERFLOW_SCROLL: - case NS_STYLE_OVERFLOW_HIDDEN: - case NS_STYLE_OVERFLOW_VISIBLE: // should never happen - case NS_STYLE_OVERFLOW_AUTO: - return ScrollbarStyles(overflow, overflow); - case NS_STYLE_OVERFLOW_CLIP: - // This isn't quite right (although the value is deprecated and not - // very important). The scrollframe will still be scrollable using - // keys. This can happen when HTML or BODY has propagated the style - // to the viewport. (In other cases, there will be no scrollframe.) - return ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, NS_STYLE_OVERFLOW_HIDDEN); - case NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL: - return ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, NS_STYLE_OVERFLOW_SCROLL); - case NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL: - return ScrollbarStyles(NS_STYLE_OVERFLOW_SCROLL, NS_STYLE_OVERFLOW_HIDDEN); - default: - NS_NOTREACHED("invalid overflow value"); - return ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, NS_STYLE_OVERFLOW_HIDDEN); - } + NS_ASSERTION(result.mHorizontal != NS_STYLE_OVERFLOW_VISIBLE && + result.mHorizontal != NS_STYLE_OVERFLOW_CLIP && + result.mVertical != NS_STYLE_OVERFLOW_VISIBLE && + result.mVertical != NS_STYLE_OVERFLOW_CLIP, + "scrollbars should not have been created"); + return result; } void diff --git a/mozilla/layout/generic/nsIScrollableFrame.h b/mozilla/layout/generic/nsIScrollableFrame.h index 6907cae2854..feb798e9210 100644 --- a/mozilla/layout/generic/nsIScrollableFrame.h +++ b/mozilla/layout/generic/nsIScrollableFrame.h @@ -67,10 +67,10 @@ public: struct ScrollbarStyles { // one of NS_STYLE_OVERFLOW_SCROLL, NS_STYLE_OVERFLOW_HIDDEN, - // NS_STYLE_OVERFLOW_VISIBLE, NS_STYLE_OVERFLOW_AUTO - PRInt32 mHorizontal; - PRInt32 mVertical; - ScrollbarStyles(PRInt32 h, PRInt32 v) : mHorizontal(h), mVertical(v) {} + // NS_STYLE_OVERFLOW_AUTO + PRUint8 mHorizontal, mVertical; + ScrollbarStyles(PRUint8 h, PRUint8 v) : mHorizontal(h), mVertical(v) {} + ScrollbarStyles() {} }; virtual ScrollbarStyles GetScrollbarStyles() const = 0; diff --git a/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp b/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp index 4608c28c76c..00c7d8dc942 100644 --- a/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp +++ b/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp @@ -45,6 +45,7 @@ #include "nsIServiceManager.h" #include "nsIView.h" #include "nsIScrollableView.h" +#include "nsIScrollable.h" #include "nsIViewManager.h" #include "nsHTMLContainerFrame.h" #include "nsWidgetsCID.h" @@ -1181,40 +1182,72 @@ NS_IMETHODIMP_(nsrefcnt) nsGfxScrollFrameInner::Release(void) NS_IMPL_QUERY_INTERFACE1(nsGfxScrollFrameInner, nsIScrollPositionListener) +static void HandleScrollPref(nsIScrollable *aScrollable, PRInt32 aOrientation, + PRUint8& aValue) +{ + PRInt32 pref; + aScrollable->GetDefaultScrollbarPreferences(aOrientation, &pref); + switch (pref) { + case nsIScrollable::Scrollbar_Auto: + // leave |aValue| untouched + break; + case nsIScrollable::Scrollbar_Never: + aValue = NS_STYLE_OVERFLOW_HIDDEN; + break; + case nsIScrollable::Scrollbar_Always: + aValue = NS_STYLE_OVERFLOW_SCROLL; + break; + } +} + +static nsGfxScrollFrameInner::ScrollbarStyles +ConvertOverflow(PRUint8 aOverflow) +{ + nsGfxScrollFrameInner::ScrollbarStyles result; + switch (aOverflow) { + case NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL: + result.mHorizontal = NS_STYLE_OVERFLOW_HIDDEN; + result.mVertical = NS_STYLE_OVERFLOW_SCROLL; + break; + case NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL: + result.mHorizontal = NS_STYLE_OVERFLOW_SCROLL; + result.mVertical = NS_STYLE_OVERFLOW_HIDDEN; + break; + default: + result.mHorizontal = aOverflow; + result.mVertical = aOverflow; + } + return result; +} + nsGfxScrollFrameInner::ScrollbarStyles nsGfxScrollFrameInner::GetScrollbarStylesFromFrame() const { - PRUint8 overflow; + ScrollbarStyles result; nsIFrame* parent = mOuter->GetParent(); if (parent && parent->GetType() == nsLayoutAtoms::viewportFrame && // Make sure we're actually the root scrollframe parent->GetFirstChild(nsnull) == NS_STATIC_CAST(const nsIFrame*, mOuter)) { - overflow = mOuter->GetPresContext()->GetViewportOverflowOverride(); + nsPresContext *presContext = mOuter->GetPresContext(); + result = ConvertOverflow(presContext->GetViewportOverflowOverride()); + + nsCOMPtr container = presContext->GetContainer(); + nsCOMPtr scrollable = do_QueryInterface(container); + HandleScrollPref(scrollable, nsIScrollable::ScrollOrientation_X, + result.mHorizontal); + HandleScrollPref(scrollable, nsIScrollable::ScrollOrientation_Y, + result.mVertical); } else { - overflow = mOuter->GetStyleDisplay()->mOverflow; + result = ConvertOverflow(mOuter->GetStyleDisplay()->mOverflow); } - switch (overflow) { - case NS_STYLE_OVERFLOW_SCROLL: - case NS_STYLE_OVERFLOW_HIDDEN: - case NS_STYLE_OVERFLOW_VISIBLE: // should never happen - case NS_STYLE_OVERFLOW_AUTO: - return ScrollbarStyles(overflow, overflow); - case NS_STYLE_OVERFLOW_CLIP: - // This isn't quite right (although the value is deprecated and not - // very important). The scrollframe will still be scrollable using - // keys. This can happen when HTML or BODY has propagated the style - // to the viewport. (In other cases, there will be no scrollframe.) - return ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, NS_STYLE_OVERFLOW_HIDDEN); - case NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL: - return ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, NS_STYLE_OVERFLOW_SCROLL); - case NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL: - return ScrollbarStyles(NS_STYLE_OVERFLOW_SCROLL, NS_STYLE_OVERFLOW_HIDDEN); - default: - NS_NOTREACHED("invalid overflow value"); - return ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, NS_STYLE_OVERFLOW_HIDDEN); - } + NS_ASSERTION(result.mHorizontal != NS_STYLE_OVERFLOW_VISIBLE && + result.mHorizontal != NS_STYLE_OVERFLOW_CLIP && + result.mVertical != NS_STYLE_OVERFLOW_VISIBLE && + result.mVertical != NS_STYLE_OVERFLOW_CLIP, + "scrollbars should not have been created"); + return result; } void diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp index 34a72d1c4f6..00307187545 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -3836,8 +3836,6 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, // 2) nsIScrollable::Scrollbar_Auto = scrollbars appear if needed // 3) nsIScrollable::Scrollbar_Always = scrollbars always // Only need to create a scroll frame/view for cases 2 and 3. - // Currently Scrollbar_Always isn't honored, as - // scrollportview::SetScrollPref is not implemented. PRBool isHTML = aDocElement->IsContentOfType(nsIContent::eHTML); PRBool isXUL = PR_FALSE; @@ -3856,6 +3854,11 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, isScrollable = PR_FALSE; } + // Don't create a scrollframe when we're inside a frame or iframe with + // scrolling="no". This makes the frame hierarchy inconsistent and is + // unnecessary for correctness (since + // nsGfxScrollFrameInner::GetScrollbarStyles handles all the necessary + // cases), but it seems to be needed for performance. if (isScrollable) { nsresult rv; if (aPresContext) { @@ -3864,12 +3867,13 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, nsCOMPtr scrollableContainer = do_QueryInterface(container, &rv); if (NS_SUCCEEDED(rv) && scrollableContainer) { PRInt32 scrolling = -1; - // XXX We should get prefs for X and Y and deal with these independently! scrollableContainer->GetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y,&scrolling); if (nsIScrollable::Scrollbar_Never == scrolling) { - isScrollable = PR_FALSE; + scrollableContainer->GetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X,&scrolling); + if (nsIScrollable::Scrollbar_Never == scrolling) { + isScrollable = PR_FALSE; + } } - // XXX NS_STYLE_OVERFLOW_SCROLL should create 'always on' scrollbars } } }