Backed out changeset 7da2469ac949 (bug 1824236) for causing assertion failures in layout/generic/crashtests/369038-1.xhtml CLOSED TREE

This commit is contained in:
Sandor Molnar
2023-03-27 23:20:35 +03:00
parent 2c2a8e69f9
commit 7944d7404c
36 changed files with 750 additions and 767 deletions

View File

@@ -12,7 +12,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1697769
<hbox height="300" align="center">
<vbox width="30" align="center">
<scrollbar id="scrollbar" orient="vertical" curpos="0" maxpos="500" style="height: 300px" />
<scrollbar id="scrollbar" orient="vertical" curpos="0" maxpos="500" height="300" />
</vbox>
</hbox>

View File

@@ -15,7 +15,7 @@
</head>
<body>
<div style="height: 20000px; background-color: green"></div>
<script>
<script type="application/javascript">
const utils = SpecialPowers.getDOMWindowUtils(window);
async function test() {

View File

@@ -222,8 +222,8 @@ nsIFrame* NS_NewSliderFrame(PresShell* aPresShell, ComputedStyle* aStyle);
nsIFrame* NS_NewScrollbarFrame(PresShell* aPresShell, ComputedStyle* aStyle);
nsIFrame* NS_NewScrollbarButtonFrame(PresShell*, ComputedStyle*);
nsIFrame* NS_NewSimpleXULLeafFrame(PresShell*, ComputedStyle*);
nsIFrame* NS_NewScrollbarButtonFrame(PresShell* aPresShell,
ComputedStyle* aStyle);
nsIFrame* NS_NewXULImageFrame(PresShell*, ComputedStyle*);
nsIFrame* NS_NewImageFrameForContentProperty(PresShell*, ComputedStyle*);
@@ -4145,11 +4145,8 @@ nsCSSFrameConstructor::FindXULTagData(const Element& aElement,
SIMPLE_XUL_CREATE(editor, NS_NewSubDocumentFrame),
SIMPLE_XUL_CREATE(browser, NS_NewSubDocumentFrame),
SIMPLE_XUL_CREATE(splitter, NS_NewSplitterFrame),
SIMPLE_XUL_CREATE(scrollbar, NS_NewScrollbarFrame),
SIMPLE_XUL_CREATE(slider, NS_NewSliderFrame),
SIMPLE_XUL_CREATE(thumb, NS_NewSimpleXULLeafFrame),
SIMPLE_XUL_CREATE(scrollcorner, NS_NewSimpleXULLeafFrame),
SIMPLE_XUL_CREATE(resizer, NS_NewSimpleXULLeafFrame),
SIMPLE_XUL_CREATE(scrollbar, NS_NewScrollbarFrame),
SIMPLE_XUL_CREATE(scrollbarbutton, NS_NewScrollbarButtonFrame),
{nsGkAtoms::panel, kPopupData},
{nsGkAtoms::menupopup, kPopupData},

View File

@@ -77,8 +77,7 @@ FRAME_CLASSES = [
Frame("nsRubyFrame", "Ruby", NOT_LEAF),
Frame("nsRubyTextContainerFrame", "RubyTextContainer", NOT_LEAF),
Frame("nsRubyTextFrame", "RubyText", NOT_LEAF),
Frame("SimpleXULLeafFrame", "SimpleXULLeaf", LEAF),
Frame("nsScrollbarButtonFrame", "SimpleXULLeaf", LEAF),
Frame("nsScrollbarButtonFrame", "Box", NOT_LEAF),
Frame("nsScrollbarFrame", "Scrollbar", NOT_LEAF),
Frame("nsSearchControlFrame", "SearchControl", LEAF),
Frame("nsSelectsAreaFrame", "Block", NOT_LEAF),

View File

@@ -15,7 +15,6 @@
#include "nsIScrollableFrame.h"
#include "PresShell.h"
#include "nsLayoutUtils.h"
#include "nsScrollbarFrame.h"
#include "nsRefreshDriver.h"
#include "nsComponentManagerUtils.h"
#include "nsStyledElement.h"

View File

@@ -397,6 +397,35 @@ void nsHTMLScrollFrame::RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) {
ReloadChildFrames();
}
static void GetScrollbarMetrics(nsBoxLayoutState& aState, nsIFrame* aBox,
nsSize* aMin, nsSize* aPref) {
NS_ASSERTION(aState.GetRenderingContext(),
"Must have rendering context in layout state for size "
"computations");
if (aMin) {
*aMin = aBox->GetXULMinSize(aState);
nsIFrame::AddXULMargin(aBox, *aMin);
if (aMin->width < 0) {
aMin->width = 0;
}
if (aMin->height < 0) {
aMin->height = 0;
}
}
if (aPref) {
*aPref = aBox->GetXULPrefSize(aState);
nsIFrame::AddXULMargin(aBox, *aPref);
if (aPref->width < 0) {
aPref->width = 0;
}
if (aPref->height < 0) {
aPref->height = 0;
}
}
}
/**
HTML scrolling implementation
@@ -431,6 +460,7 @@ struct MOZ_STACK_CLASS ScrollReflowInput {
// === Filled in by the constructor. Members in this section shouldn't change
// their values after the constructor. ===
const ReflowInput& mReflowInput;
nsBoxLayoutState mBoxState;
ShowScrollbar mHScrollbar;
// If the horizontal scrollbar is allowed (even if mHScrollbar ==
// ShowScrollbar::Never) provided that it is for scrolling the visual viewport
@@ -475,9 +505,9 @@ struct MOZ_STACK_CLASS ScrollReflowInput {
ScrollReflowInput(nsHTMLScrollFrame* aFrame, const ReflowInput& aReflowInput);
nscoord VScrollbarMinHeight() const { return mVScrollbarPrefSize.height; }
nscoord VScrollbarMinHeight() const { return mVScrollbarMinSize.height; }
nscoord VScrollbarPrefWidth() const { return mVScrollbarPrefSize.width; }
nscoord HScrollbarMinWidth() const { return mHScrollbarPrefSize.width; }
nscoord HScrollbarMinWidth() const { return mHScrollbarMinSize.width; }
nscoord HScrollbarPrefHeight() const { return mHScrollbarPrefSize.height; }
// Returns the sizes occupied by the scrollbar gutters. If aShowVScroll or
@@ -485,9 +515,6 @@ struct MOZ_STACK_CLASS ScrollReflowInput {
// included.
nsMargin ScrollbarGutter(bool aShowVScrollbar, bool aShowHScrollbar,
bool aScrollbarOnRight) const {
if (mOverlayScrollbars) {
return mScrollbarGutter;
}
nsMargin gutter = mScrollbarGutter;
if (aShowVScrollbar && gutter.right == 0 && gutter.left == 0) {
const nscoord w = VScrollbarPrefWidth();
@@ -504,14 +531,13 @@ struct MOZ_STACK_CLASS ScrollReflowInput {
return gutter;
}
bool OverlayScrollbars() const { return mOverlayScrollbars; }
private:
// Filled in by the constructor. Put variables here to keep them unchanged
// after initializing them in the constructor.
nsSize mVScrollbarMinSize;
nsSize mVScrollbarPrefSize;
nsSize mHScrollbarMinSize;
nsSize mHScrollbarPrefSize;
bool mOverlayScrollbars = false;
// The scrollbar gutter sizes resolved from the scrollbar-gutter and
// scrollbar-width property.
nsMargin mScrollbarGutter;
@@ -520,35 +546,55 @@ struct MOZ_STACK_CLASS ScrollReflowInput {
ScrollReflowInput::ScrollReflowInput(nsHTMLScrollFrame* aFrame,
const ReflowInput& aReflowInput)
: mReflowInput(aReflowInput),
// mBoxState is just used for scrollbars so we don't need to
// worry about the reflow depth here
mBoxState(aReflowInput.mFrame->PresContext(),
aReflowInput.mRenderingContext),
mComputedBorder(aReflowInput.ComputedPhysicalBorderPadding() -
aReflowInput.ComputedPhysicalPadding()),
mScrollbarGutterFromLastReflow(aFrame->GetWritingMode()) {
ScrollStyles styles = aFrame->GetScrollStyles();
mHScrollbar = ShouldShowScrollbar(styles.mHorizontal);
mVScrollbar = ShouldShowScrollbar(styles.mVertical);
mOverlayScrollbars = aFrame->UsesOverlayScrollbars();
if (nsScrollbarFrame* scrollbar = aFrame->GetScrollbarBox(false)) {
if (nsIFrame* hScrollbarBox = aFrame->GetScrollbarBox(false)) {
nsScrollbarFrame* scrollbar = do_QueryFrame(hScrollbarBox);
scrollbar->SetScrollbarMediatorContent(mReflowInput.mFrame->GetContent());
mHScrollbarPrefSize = scrollbar->ScrollbarMinSize();
// A zero minimum size is a bug with non-overlay scrollbars. That means
// we'll always try to place the scrollbar, even if it will ultimately not
// fit, see bug 1809630. XUL collapsing is the exception because the
GetScrollbarMetrics(mBoxState, hScrollbarBox, &mHScrollbarMinSize,
&mHScrollbarPrefSize);
// A zero minimum size is a bug with non-overlay scrollbars. That
// means we'll always try to place the scrollbar, even if it will ultimately
// not fit, see bug 1809630. XUL collapsing is the exception because the
// front-end uses it.
MOZ_ASSERT(scrollbar->IsXULCollapsed() ||
(mHScrollbarPrefSize.width && mHScrollbarPrefSize.height),
"Shouldn't have a zero horizontal scrollbar-size");
MOZ_ASSERT(aFrame->PresContext()->UseOverlayScrollbars() ||
hScrollbarBox->IsXULCollapsed() ||
(mHScrollbarMinSize.width && mHScrollbarMinSize.height),
"Shouldn't have a zero horizontal min-scrollbar-size");
MOZ_ASSERT(mHScrollbarPrefSize.width >= mHScrollbarMinSize.width &&
mHScrollbarPrefSize.height >= mHScrollbarMinSize.height,
"Scrollbar pref size should be >= min size");
} else {
mHScrollbar = ShowScrollbar::Never;
mHScrollbarAllowedForScrollingVVInsideLV = false;
}
if (nsScrollbarFrame* scrollbar = aFrame->GetScrollbarBox(true)) {
if (nsIFrame* vScrollbarBox = aFrame->GetScrollbarBox(true)) {
nsScrollbarFrame* scrollbar = do_QueryFrame(vScrollbarBox);
scrollbar->SetScrollbarMediatorContent(mReflowInput.mFrame->GetContent());
mVScrollbarPrefSize = scrollbar->ScrollbarMinSize();
GetScrollbarMetrics(mBoxState, vScrollbarBox, &mVScrollbarMinSize,
&mVScrollbarPrefSize);
// See above.
MOZ_ASSERT(scrollbar->IsXULCollapsed() ||
(mVScrollbarPrefSize.width && mVScrollbarPrefSize.height),
"Shouldn't have a zero vertical scrollbar-size");
MOZ_ASSERT(aFrame->PresContext()->UseOverlayScrollbars() ||
vScrollbarBox->IsXULCollapsed() ||
(mVScrollbarMinSize.width && mVScrollbarMinSize.height),
"Shouldn't have a zero vertical min-size");
MOZ_ASSERT(mVScrollbarPrefSize.width >= mVScrollbarMinSize.width &&
mVScrollbarPrefSize.height >= mVScrollbarMinSize.height,
"Scrollbar pref size should be >= min size");
} else {
mVScrollbar = ShowScrollbar::Never;
mVScrollbarAllowedForScrollingVVInsideLV = false;
@@ -569,8 +615,7 @@ ScrollReflowInput::ScrollReflowInput(nsHTMLScrollFrame* aFrame,
mVScrollbar = ShowScrollbar::Never;
mVScrollbarAllowedForScrollingVVInsideLV = false;
} else if (const auto& scrollbarGutterStyle =
scrollbarStyle->StyleDisplay()->mScrollbarGutter;
scrollbarGutterStyle && !mOverlayScrollbars) {
scrollbarStyle->StyleDisplay()->mScrollbarGutter) {
const auto stable =
bool(scrollbarGutterStyle & StyleScrollbarGutter::STABLE);
const auto bothEdges =
@@ -744,7 +789,7 @@ bool nsHTMLScrollFrame::TryLayout(ScrollReflowInput& aState,
"TryLayout scrolledRect:%s overflowRect:%s scrollportSize:%s\n",
ToString(scrolledRect).c_str(), ToString(overflowRect).c_str(),
ToString(scrollPortSize).c_str());
nscoord oneDevPixel = PresContext()->DevPixelsToAppUnits(1);
nscoord oneDevPixel = aState.mBoxState.PresContext()->DevPixelsToAppUnits(1);
bool showHScrollbar = aAssumeHScroll;
bool showVScrollbar = aAssumeVScroll;
@@ -808,7 +853,6 @@ bool nsHTMLScrollFrame::TryLayout(ScrollReflowInput& aState,
if (mIsRoot && gfxPlatform::UseDesktopZoomingScrollbars()) {
bool vvChanged = true;
const bool overlay = aState.OverlayScrollbars();
// This loop can run at most twice since we can only add a scrollbar once.
// At this point we've already decided that this layout is consistent so we
// will return true. Scrollbars added here never take up layout space even
@@ -819,12 +863,9 @@ bool nsHTMLScrollFrame::TryLayout(ScrollReflowInput& aState,
if (!aState.mShowHScrollbar &&
aState.mHScrollbarAllowedForScrollingVVInsideLV) {
if (ScrollPort().width >= visualViewportSize.width + oneDevPixel &&
(overlay ||
visualViewportSize.width >= aState.HScrollbarMinWidth())) {
visualViewportSize.width >= aState.HScrollbarMinWidth()) {
vvChanged = true;
if (!overlay) {
visualViewportSize.height -= aState.HScrollbarPrefHeight();
}
visualViewportSize.height -= aState.HScrollbarPrefHeight();
aState.mShowHScrollbar = true;
aState.mOnlyNeedHScrollbarToScrollVVInsideLV = true;
ROOT_SCROLLBAR_LOG("TryLayout added H scrollbar for VV, VV now %s\n",
@@ -835,12 +876,9 @@ bool nsHTMLScrollFrame::TryLayout(ScrollReflowInput& aState,
if (!aState.mShowVScrollbar &&
aState.mVScrollbarAllowedForScrollingVVInsideLV) {
if (ScrollPort().height >= visualViewportSize.height + oneDevPixel &&
(overlay ||
visualViewportSize.height >= aState.VScrollbarMinHeight())) {
visualViewportSize.height >= aState.VScrollbarMinHeight()) {
vvChanged = true;
if (!overlay) {
visualViewportSize.width -= aState.VScrollbarPrefWidth();
}
visualViewportSize.width -= aState.VScrollbarPrefWidth();
aState.mShowVScrollbar = true;
aState.mOnlyNeedVScrollbarToScrollVVInsideLV = true;
ROOT_SCROLLBAR_LOG("TryLayout added V scrollbar for VV, VV now %s\n",
@@ -1201,17 +1239,13 @@ void nsHTMLScrollFrame::PlaceScrollArea(ScrollReflowInput& aState,
nscoord nsHTMLScrollFrame::IntrinsicScrollbarGutterSizeAtInlineEdges(
gfxContext* aRenderingContext) {
const bool isVerticalWM = GetWritingMode().IsVertical();
nsScrollbarFrame* inlineEndScrollbarBox =
nsIFrame* inlineEndScrollbarBox =
isVerticalWM ? mHScrollbarBox : mVScrollbarBox;
if (!inlineEndScrollbarBox) {
// No scrollbar box frame means no intrinsic size.
return 0;
}
if (PresContext()->UseOverlayScrollbars()) {
return 0;
}
const auto* styleForScrollbar = nsLayoutUtils::StyleForScrollbar(this);
if (styleForScrollbar->StyleUIReset()->ScrollbarWidth() ==
StyleScrollbarWidth::None) {
@@ -1234,7 +1268,9 @@ nscoord nsHTMLScrollFrame::IntrinsicScrollbarGutterSizeAtInlineEdges(
}
// No need to worry about reflow depth here since it's just for scrollbars.
nsSize scrollbarPrefSize = inlineEndScrollbarBox->ScrollbarMinSize();
nsBoxLayoutState bls(PresContext(), aRenderingContext, 0);
nsSize scrollbarPrefSize;
GetScrollbarMetrics(bls, inlineEndScrollbarBox, nullptr, &scrollbarPrefSize);
const nscoord scrollbarSize =
isVerticalWM ? scrollbarPrefSize.height : scrollbarPrefSize.width;
const auto bothEdges =
@@ -1572,7 +1608,7 @@ void nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext,
const nsRect insideBorderArea(
nsPoint(state.mComputedBorder.left, state.mComputedBorder.top),
layoutSize);
LayoutScrollbars(state, insideBorderArea, oldScrollPort);
LayoutScrollbars(state.mBoxState, insideBorderArea, oldScrollPort);
} else {
mSkippedScrollbarLayout = true;
}
@@ -1602,7 +1638,7 @@ void nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext,
// Note that we need to do this after the
// UpdateVisualViewportSizeForPotentialScrollbarChange call above because that
// is what updates the visual viewport size and we need it to be up to date.
if (mIsRoot && !state.OverlayScrollbars() &&
if (mIsRoot && !UsesOverlayScrollbars() &&
(didHaveHScrollbar != state.mShowHScrollbar ||
didHaveVScrollbar != state.mShowVScrollbar ||
didOnlyHScrollbar != mOnlyNeedHScrollbarToScrollVVInsideLV ||
@@ -1842,7 +1878,7 @@ void nsHTMLScrollFrame::ScrollByWhole(nsScrollbarFrame* aScrollbar,
void nsHTMLScrollFrame::ScrollByLine(nsScrollbarFrame* aScrollbar,
int32_t aDirection,
ScrollSnapFlags aSnapFlags) {
bool isHorizontal = aScrollbar->IsHorizontal();
bool isHorizontal = aScrollbar->IsXULHorizontal();
nsIntPoint delta;
if (isHorizontal) {
const double kScrollMultiplier =
@@ -1880,7 +1916,7 @@ void nsHTMLScrollFrame::RepeatButtonScroll(nsScrollbarFrame* aScrollbar) {
void nsHTMLScrollFrame::ThumbMoved(nsScrollbarFrame* aScrollbar,
nscoord aOldPos, nscoord aNewPos) {
MOZ_ASSERT(aScrollbar != nullptr);
bool isHorizontal = aScrollbar->IsHorizontal();
bool isHorizontal = aScrollbar->IsXULHorizontal();
nsPoint current = GetScrollPosition();
nsPoint dest = current;
if (isHorizontal) {
@@ -1917,7 +1953,7 @@ void nsHTMLScrollFrame::ScrollByUnit(nsScrollbarFrame* aScrollbar,
ScrollUnit aUnit,
ScrollSnapFlags aSnapFlags) {
MOZ_ASSERT(aScrollbar != nullptr);
bool isHorizontal = aScrollbar->IsHorizontal();
bool isHorizontal = aScrollbar->IsXULHorizontal();
nsIntPoint delta;
if (isHorizontal) {
delta.x = aDirection;
@@ -5432,12 +5468,10 @@ void nsHTMLScrollFrame::ReloadChildFrames() {
if (value.LowerCaseEqualsLiteral("horizontal")) {
NS_ASSERTION(!mHScrollbarBox,
"Found multiple horizontal scrollbars?");
mHScrollbarBox = do_QueryFrame(frame);
MOZ_ASSERT(mHScrollbarBox, "Not a scrollbar?");
mHScrollbarBox = frame;
} else {
NS_ASSERTION(!mVScrollbarBox, "Found multiple vertical scrollbars?");
mVScrollbarBox = do_QueryFrame(frame);
MOZ_ASSERT(mVScrollbarBox, "Not a scrollbar?");
mVScrollbarBox = frame;
}
} else if (content->IsXULElement(nsGkAtoms::resizer)) {
NS_ASSERTION(!mResizerBox, "Found multiple resizers");
@@ -5783,9 +5817,7 @@ void nsHTMLScrollFrame::CurPosAttributeChangedInternal(nsIContent* aContent,
//
// In cases 2 and 3 we do not need to scroll because we're just
// updating our scrollbar.
if (mFrameIsUpdatingScrollbar) {
return;
}
if (mFrameIsUpdatingScrollbar) return;
nsRect scrollRange = GetVisualScrollRange();
@@ -6498,39 +6530,12 @@ static void AdjustOverlappingScrollbars(nsRect& aVRect, nsRect& aHRect) {
}
}
void nsHTMLScrollFrame::LayoutScrollbarPartAtRect(
const ScrollReflowInput& aState, ReflowInput& aKidReflowInput,
const nsRect& aRect) {
nsPresContext* pc = PresContext();
nsIFrame* kid = aKidReflowInput.mFrame;
const auto wm = kid->GetWritingMode();
ReflowOutput desiredSize(wm);
MOZ_ASSERT(!wm.IsVertical(),
"Scrollbar parts should have writing-mode: initial");
MOZ_ASSERT(!wm.IsInlineReversed(),
"Scrollbar parts should have writing-mode: initial");
// XXX Maybe get a meaningful container size or something. Shouldn't matter
// given our asserts above.
const nsSize containerSize;
aKidReflowInput.SetComputedISize(aRect.Width());
aKidReflowInput.SetComputedBSize(aRect.Height());
const LogicalPoint pos(wm, aRect.TopLeft(), containerSize);
const auto flags = ReflowChildFlags::Default;
nsReflowStatus status;
ReflowOutput kidDesiredSize(wm);
ReflowChild(kid, pc, kidDesiredSize, aKidReflowInput, wm, pos, containerSize,
flags, status);
FinishReflowChild(kid, pc, kidDesiredSize, &aKidReflowInput, wm, pos,
containerSize, flags);
}
void nsHTMLScrollFrame::LayoutScrollbars(ScrollReflowInput& aState,
void nsHTMLScrollFrame::LayoutScrollbars(nsBoxLayoutState& aState,
const nsRect& aInsideBorderArea,
const nsRect& aOldScrollPort) {
NS_ASSERTION(!mSuppressScrollbarUpdate, "This should have been suppressed");
const bool scrollbarOnLeft = !IsScrollbarOnRight();
bool scrollbarOnLeft = !IsScrollbarOnRight();
const bool overlayScrollbars = UsesOverlayScrollbars();
const bool overlayScrollBarsOnRoot = overlayScrollbars && mIsRoot;
const bool showVScrollbar = mVScrollbarBox && mHasVerticalScrollbar;
@@ -6545,6 +6550,7 @@ void nsHTMLScrollFrame::LayoutScrollbars(ScrollReflowInput& aState,
nsPresContext* presContext = mScrolledFrame->PresContext();
nsRect vRect;
if (showVScrollbar) {
MOZ_ASSERT(mVScrollbarBox->IsXULBoxFrame(), "Must be a box frame!");
vRect.height =
overlayScrollBarsOnRoot ? compositionSize.height : mScrollPort.height;
vRect.y = mScrollPort.y;
@@ -6555,46 +6561,67 @@ void nsHTMLScrollFrame::LayoutScrollbars(ScrollReflowInput& aState,
vRect.width = aInsideBorderArea.XMost() - mScrollPort.XMost();
vRect.x = mScrollPort.x + compositionSize.width;
}
if (overlayScrollbars || mOnlyNeedVScrollbarToScrollVVInsideLV) {
const nscoord width = aState.VScrollbarPrefWidth();
// For overlay scrollbars the margin returned from this GetXULMargin call
// is a negative margin that moves the scrollbar from just outside the
// scrollport (and hence not visible) to just inside the scrollport (and
// hence visible). For non-overlay scrollbars it is a 0 margin.
nsMargin margin;
mVScrollbarBox->GetXULMargin(margin);
if (!overlayScrollbars && mOnlyNeedVScrollbarToScrollVVInsideLV) {
// There is no space reserved for the layout scrollbar, it is currently
// not visible because it is positioned just outside the scrollport. But
// we know that it needs to be made visible so we shift it back in.
vRect.width += width;
nsSize vScrollbarPrefSize(0, 0);
GetScrollbarMetrics(aState, mVScrollbarBox, nullptr, &vScrollbarPrefSize);
if (scrollbarOnLeft) {
vRect.x += width;
margin.right -= vScrollbarPrefSize.width;
} else {
vRect.x -= width;
margin.left -= vScrollbarPrefSize.width;
}
}
vRect.Deflate(margin);
}
nsRect hRect;
if (showHScrollbar) {
MOZ_ASSERT(mHScrollbarBox->IsXULBoxFrame(), "Must be a box frame!");
hRect.width =
overlayScrollBarsOnRoot ? compositionSize.width : mScrollPort.width;
hRect.x = mScrollPort.x;
hRect.height = aInsideBorderArea.YMost() - mScrollPort.YMost();
hRect.y = mScrollPort.y + compositionSize.height;
if (overlayScrollbars || mOnlyNeedHScrollbarToScrollVVInsideLV) {
const nscoord height = aState.HScrollbarPrefHeight();
hRect.height += height;
// For overlay scrollbars the margin returned from this GetXULMargin call
// is a negative margin that moves the scrollbar from just outside the
// scrollport (and hence not visible) to just inside the scrollport (and
// hence visible). For non-overlay scrollbars it is a 0 margin.
nsMargin margin;
mHScrollbarBox->GetXULMargin(margin);
if (!overlayScrollbars && mOnlyNeedHScrollbarToScrollVVInsideLV) {
// There is no space reserved for the layout scrollbar, it is currently
// not visible because it is positioned just outside the scrollport. But
// we know that it needs to be made visible so we shift it back in.
hRect.y -= height;
nsSize hScrollbarPrefSize(0, 0);
GetScrollbarMetrics(aState, mHScrollbarBox, nullptr, &hScrollbarPrefSize);
margin.top -= hScrollbarPrefSize.height;
}
hRect.Deflate(margin);
}
const bool hasVisualOnlyScrollbarsOnBothDirections =
!overlayScrollbars && showHScrollbar &&
mOnlyNeedHScrollbarToScrollVVInsideLV && showVScrollbar &&
mOnlyNeedVScrollbarToScrollVVInsideLV;
nsPresContext* pc = PresContext();
// place the scrollcorner
if (mScrollCornerBox) {
MOZ_ASSERT(mScrollCornerBox->IsXULBoxFrame(), "Must be a box frame!");
nsRect r(0, 0, 0, 0);
if (scrollbarOnLeft) {
// scrollbar (if any) on left
@@ -6626,25 +6653,20 @@ void nsHTMLScrollFrame::LayoutScrollbars(ScrollReflowInput& aState,
r.y = mScrollPort.YMost() - r.height;
}
ReflowInput scrollCornerRI(
pc, aState.mReflowInput, mScrollCornerBox,
LogicalSize(mScrollCornerBox->GetWritingMode(), r.Size()));
LayoutScrollbarPartAtRect(aState, scrollCornerRI, r);
nsBoxFrame::LayoutChildAt(aState, mScrollCornerBox, r);
}
if (mResizerBox) {
// If a resizer is present, get its size.
//
// TODO(emilio): Should this really account for scrollbar-width?
nsPresContext* pc = aState.PresContext();
auto scrollbarWidth = nsLayoutUtils::StyleForScrollbar(this)
->StyleUIReset()
->ScrollbarWidth();
auto scrollbarSize = pc->Theme()->GetScrollbarSize(pc, scrollbarWidth,
nsITheme::Overlay::No);
ReflowInput resizerRI(pc, aState.mReflowInput, mResizerBox,
LogicalSize(mResizerBox->GetWritingMode()));
nsSize resizerMinSize = {resizerRI.ComputedMinWidth(),
resizerRI.ComputedMinHeight()};
nsSize resizerMinSize = mResizerBox->GetXULMinSize(aState);
nsRect r;
nscoord vScrollbarWidth = pc->DevPixelsToAppUnits(scrollbarSize);
@@ -6658,7 +6680,7 @@ void nsHTMLScrollFrame::LayoutScrollbars(ScrollReflowInput& aState,
std::max(std::max(r.height, hScrollbarHeight), resizerMinSize.height);
r.y = aInsideBorderArea.YMost() - r.height;
LayoutScrollbarPartAtRect(aState, resizerRI, r);
nsBoxFrame::LayoutChildAt(aState, mResizerBox, r);
}
// Note that AdjustScrollbarRectForResizer has to be called after the
@@ -6680,16 +6702,10 @@ void nsHTMLScrollFrame::LayoutScrollbars(ScrollReflowInput& aState,
AdjustOverlappingScrollbars(vRect, hRect);
}
if (mVScrollbarBox) {
ReflowInput vScrollbarRI(
pc, aState.mReflowInput, mVScrollbarBox,
LogicalSize(mVScrollbarBox->GetWritingMode(), vRect.Size()));
LayoutScrollbarPartAtRect(aState, vScrollbarRI, vRect);
nsBoxFrame::LayoutChildAt(aState, mVScrollbarBox, vRect);
}
if (mHScrollbarBox) {
ReflowInput hScrollbarRI(
pc, aState.mReflowInput, mHScrollbarBox,
LogicalSize(mHScrollbarBox->GetWritingMode(), hRect.Size()));
LayoutScrollbarPartAtRect(aState, hScrollbarRI, hRect);
nsBoxFrame::LayoutChildAt(aState, mHScrollbarBox, hRect);
}
// may need to update fixed position children of the viewport,
@@ -6704,7 +6720,7 @@ void nsHTMLScrollFrame::LayoutScrollbars(ScrollReflowInput& aState,
// post reflow callback to modify scrollbar attributes
mUpdateScrollbarAttributes = true;
if (!mPostedReflowCallback) {
PresShell()->PostReflowCallback(this);
aState.PresShell()->PostReflowCallback(this);
mPostedReflowCallback = true;
}
}

View File

@@ -385,7 +385,7 @@ class nsHTMLScrollFrame : public nsContainerFrame,
nscoord aNewPos) final;
void ScrollbarReleased(nsScrollbarFrame* aScrollbar) final;
void VisibilityChanged(bool aVisible) final {}
nsScrollbarFrame* GetScrollbarBox(bool aVertical) final {
nsIFrame* GetScrollbarBox(bool aVertical) final {
return aVertical ? mVScrollbarBox : mHScrollbarBox;
}
@@ -717,13 +717,10 @@ class nsHTMLScrollFrame : public nsContainerFrame,
void AdjustScrollbarRectForResizer(
nsIFrame* aFrame, nsPresContext* aPresContext, nsRect& aRect,
bool aHasResizer, mozilla::layers::ScrollDirection aDirection);
void LayoutScrollbars(ScrollReflowInput& aState,
void LayoutScrollbars(nsBoxLayoutState& aState,
const nsRect& aInsideBorderArea,
const nsRect& aOldScrollPort);
void LayoutScrollbarPartAtRect(const ScrollReflowInput&,
ReflowInput& aKidReflowInput, const nsRect&);
bool IsAlwaysActive() const;
void MarkRecentlyScrolled();
void MarkNotRecentlyScrolled();
@@ -786,8 +783,8 @@ class nsHTMLScrollFrame : public nsContainerFrame,
RefPtr<ScrollEndEvent> mScrollEndEvent;
nsRevocableEventPtr<AsyncScrollPortEvent> mAsyncScrollPortEvent;
nsRevocableEventPtr<ScrolledAreaEvent> mScrolledAreaEvent;
nsScrollbarFrame* mHScrollbarBox;
nsScrollbarFrame* mVScrollbarBox;
nsIFrame* mHScrollbarBox;
nsIFrame* mVScrollbarBox;
nsIFrame* mScrolledFrame;
nsIFrame* mScrollCornerBox;
nsIFrame* mResizerBox;

View File

@@ -275,7 +275,7 @@ void nsInlineFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics,
DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aStatus);
MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
if (!aReflowInput.mLineLayout) {
if (nullptr == aReflowInput.mLineLayout) {
NS_ERROR("must have non-null aReflowInput.mLineLayout");
return;
}

View File

@@ -21,15 +21,24 @@
-moz-font-smoothing-background-color: initial;
-moz-min-font-size-ratio: initial;
-moz-box-collapse: initial;
-moz-box-layout: initial;
/* -moz-box-layout: initial; is not included in 'all' but it's not needed,
* because we explicitly specify it below for the top level scrollbar parts
* (and it inherits through to the rest).
*/
math-depth: initial;
/* As long as inert implies pointer-events: none as it does now, we're
* good. */
-moz-inert: initial;
/* direction: initial is not sufficient, since its initial value can depend
* on the document's language. But we specify ltr explicitly below */
/* Using initial is not sufficient for direction, since its initial value can
* depend on the document's language.
*
* LTR is what we want for all scrollbar parts anyway, so that e.g. we don't
* reverse the rendering of a horizontal scrollbar.
*/
direction: ltr;
/* Similarly for font properties, whose initial values depend on the
* document's language. Scrollbar parts don't have any text or rely on
@@ -60,17 +69,16 @@
}
scrollbar, scrollbarbutton, scrollcorner, slider, thumb, resizer {
/* We need a display value that doesn't get blockified to preserve the
* scrollbar sizing asserts. In practice it doesn't matter since these get
* special frames */
display: block;
/* Force legacy XUL layout for now on scrollbars / resizers and descendants,
* as nsHTMLScrollFrame relies on that (and nsScrollbarFrame is a XUL frame
* anyways).
*
* TODO: Eventually we should rewrite scrollbars so that they don't use XUL
* layout.
*/
-moz-box-layout: legacy;
display: -moz-box;
box-sizing: border-box;
/* Our scrollbar layout uses physical coordinates, we wouldn't want an
* horizontal scrollbar to flip in rtl for example. */
direction: ltr;
writing-mode: initial;
-moz-user-focus: ignore;
/* Prevent -moz-user-modify declaration from designmode.css having an effect. */
-moz-user-modify: initial;
@@ -88,6 +96,11 @@ resizer {
appearance: auto;
-moz-default-appearance: resizer;
/* native resizer should never flip on its own;
we will flip it (or the SVG background) with CSS transform below. */
direction: ltr;
writing-mode: initial;
background: url("chrome://global/skin/icons/resizer.svg") no-repeat;
background-size: 100% 100%;
cursor: se-resize;
@@ -134,10 +147,14 @@ resizer[dir="topright"] {
thumb {
appearance: auto;
-moz-default-appearance: scrollbarthumb-horizontal;
-moz-box-flex: 1;
-moz-box-align: center;
-moz-box-pack: center;
}
thumb[orient="vertical"] {
-moz-default-appearance: scrollbarthumb-vertical;
-moz-box-orient: vertical;
}
scrollbar[disabled="true"] thumb {
@@ -158,6 +175,7 @@ scrollbar {
scrollbar[orient="vertical"] {
-moz-default-appearance: scrollbar-vertical;
-moz-box-orient: vertical;
}
scrollbar[root="true"] {
@@ -179,10 +197,12 @@ scrollbar[root="true"] {
slider {
appearance: auto;
-moz-default-appearance: scrollbartrack-horizontal;
-moz-box-flex: 1;
}
slider[orient="vertical"] {
-moz-default-appearance: scrollbartrack-vertical;
-moz-box-orient: vertical;
}
scrollbarbutton {

View File

@@ -13,21 +13,18 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1367568
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug 1367568</a>
<div id="content">
<!-- Some fixed-width divs that we shouldn't have to reflow when the viewport
changes. More than 5 so that our leeway for scrollbar parts doesn't
accidentally cause the test to pass -->
<div style="width: 100px">fixed-width <div>(child)</div></div>
<div style="width: 100px">fixed-width <div>(child)</div></div>
<div style="width: 100px">fixed-width <div>(child)</div></div>
<div style="width: 100px">fixed-width <div>(child)</div></div>
<div style="width: 100px">fixed-width <div>(child)</div></div>
<div style="width: 100px">fixed-width <div>(child)</div></div>
changes: -->
<div style="width: 100px">
fixed-width
<div>(child)</div>
</div>
<div style="position: absolute; width: 150px">
abs-fixed-width
<div>(child)</div>
</div>
</div>
<pre id="test">
<script>
<script type="application/javascript">
"use strict";
/** Test for Bug 1367568 **/
@@ -80,11 +77,9 @@ function main() {
ok(count > 0,
"Should reflow some frames when 'width' & 'height' change");
const scrollbarsHaveButtons = navigator.platform.includes("Win");
// This is to allow for reflowing scrollbar parts themselves.
const scrollbarReflows = scrollbarsHaveButtons ? 5 : 2;
// Expected maximum number of frames reflowed for "overflow" changes
const expectedMax = count + scrollbarReflows;
// (+2 is to allow for reflowing scrollbars themselves):
const expectedMax = count + 2;
// Shared ending for messages in all ok() checks below:
const messageSuffix =

View File

@@ -1,37 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SimpleXULLeafFrame.h"
#include "mozilla/PresShell.h"
nsIFrame* NS_NewSimpleXULLeafFrame(mozilla::PresShell* aPresShell,
mozilla::ComputedStyle* aStyle) {
return new (aPresShell)
mozilla::SimpleXULLeafFrame(aStyle, aPresShell->GetPresContext());
}
namespace mozilla {
NS_IMPL_FRAMEARENA_HELPERS(SimpleXULLeafFrame)
void SimpleXULLeafFrame::Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) {
MarkInReflow();
MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
const auto wm = GetWritingMode();
const auto& bp = aReflowInput.ComputedLogicalBorderPadding(wm);
aDesiredSize.ISize(wm) = bp.IStartEnd(wm) + aReflowInput.ComputedISize();
aDesiredSize.BSize(wm) =
bp.BStartEnd(wm) + (aReflowInput.ComputedBSize() == NS_UNCONSTRAINEDSIZE
? aReflowInput.ComputedMinBSize()
: aReflowInput.ComputedBSize());
aDesiredSize.SetOverflowAreasToDesiredBounds();
}
} // namespace mozilla

View File

@@ -1,46 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// A simple frame class for XUL frames that are leafs on the tree but need
// background / border painting, and for some reason or another need special
// code (like event handling code) which we haven't ported to the DOM.
//
// This should generally not be used for new frame classes.
#ifndef mozilla_SimpleXULLeafFrame_h
#define mozilla_SimpleXULLeafFrame_h
#include "nsLeafFrame.h"
namespace mozilla {
// Shared class for thumb and scrollbar buttons.
class SimpleXULLeafFrame : public nsLeafFrame {
public:
NS_DECL_FRAMEARENA_HELPERS(SimpleXULLeafFrame)
// TODO: Look at appearance instead maybe?
nscoord GetIntrinsicISize() override { return 0; }
nscoord GetIntrinsicBSize() override { return 0; }
void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
explicit SimpleXULLeafFrame(ComputedStyle* aStyle,
nsPresContext* aPresContext, ClassID aClassID)
: nsLeafFrame(aStyle, aPresContext, aClassID) {}
explicit SimpleXULLeafFrame(ComputedStyle* aStyle,
nsPresContext* aPresContext)
: SimpleXULLeafFrame(aStyle, aPresContext, kClassID) {}
friend nsIFrame* NS_NewSimpleXULLeafFrame(mozilla::PresShell* aPresShell,
ComputedStyle* aStyle);
};
} // namespace mozilla
#endif

View File

@@ -34,7 +34,6 @@ UNIFIED_SOURCES += [
"nsTextBoxFrame.cpp",
"nsXULPopupManager.cpp",
"nsXULTooltipListener.cpp",
"SimpleXULLeafFrame.cpp",
]
DIRS += ["tree"]

View File

@@ -884,3 +884,34 @@ nsresult nsBoxFrame::LayoutChildAt(nsBoxLayoutState& aState, nsIFrame* aBox,
return NS_OK;
}
bool nsBoxFrame::GetEventPoint(WidgetGUIEvent* aEvent, nsPoint& aPoint) {
LayoutDeviceIntPoint refPoint;
bool res = GetEventPoint(aEvent, refPoint);
aPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, refPoint,
RelativeTo{this});
return res;
}
bool nsBoxFrame::GetEventPoint(WidgetGUIEvent* aEvent,
LayoutDeviceIntPoint& aPoint) {
NS_ENSURE_TRUE(aEvent, false);
WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();
if (touchEvent) {
// return false if there is more than one touch on the page, or if
// we can't find a touch point
if (touchEvent->mTouches.Length() != 1) {
return false;
}
dom::Touch* touch = touchEvent->mTouches.SafeElementAt(0);
if (!touch) {
return false;
}
aPoint = touch->mRefPoint;
} else {
aPoint = aEvent->mRefPoint;
}
return true;
}

View File

@@ -154,6 +154,14 @@ class nsBoxFrame : public nsContainerFrame {
nsCOMPtr<nsBoxLayout> mLayoutManager;
// Get the point associated with this event. Returns true if a single valid
// point was found. Otherwise false.
bool GetEventPoint(mozilla::WidgetGUIEvent* aEvent, nsPoint& aPoint);
// Gets the event coordinates relative to the widget offset associated with
// this frame. Return true if a single valid point was found.
bool GetEventPoint(mozilla::WidgetGUIEvent* aEvent,
mozilla::LayoutDeviceIntPoint& aPoint);
private:
void CacheAttributes();

View File

@@ -81,7 +81,7 @@ class nsIScrollbarMediator : public nsQueryFrame {
* Obtain the frame for the horizontal or vertical scrollbar, or null
* if there is no such box.
*/
virtual nsScrollbarFrame* GetScrollbarBox(bool aVertical) = 0;
virtual nsIFrame* GetScrollbarBox(bool aVertical) = 0;
/**
* Show or hide scrollbars on 2 fingers touch.
* Subclasses should call their ScrollbarActivity's corresponding methods.

View File

@@ -39,6 +39,7 @@ nsIFrame* NS_NewScrollbarButtonFrame(PresShell* aPresShell,
return new (aPresShell)
nsScrollbarButtonFrame(aStyle, aPresShell->GetPresContext());
}
NS_IMPL_FRAMEARENA_HELPERS(nsScrollbarButtonFrame)
nsresult nsScrollbarButtonFrame::HandleEvent(nsPresContext* aPresContext,
@@ -78,7 +79,7 @@ nsresult nsScrollbarButtonFrame::HandleEvent(nsPresContext* aPresContext,
break;
}
return SimpleXULLeafFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
return nsBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
bool nsScrollbarButtonFrame::HandleButtonPress(nsPresContext* aPresContext,
@@ -269,5 +270,5 @@ void nsScrollbarButtonFrame::DestroyFrom(nsIFrame* aDestructRoot,
// Ensure our repeat service isn't going... it's possible that a scrollbar can
// disappear out from under you while you're in the process of scrolling.
StopRepeat();
SimpleXULLeafFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
nsBoxFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
}

View File

@@ -14,26 +14,25 @@
#ifndef nsScrollbarButtonFrame_h___
#define nsScrollbarButtonFrame_h___
#include "SimpleXULLeafFrame.h"
#include "mozilla/Attributes.h"
#include "nsLeafFrame.h"
#include "nsBoxFrame.h"
#include "nsRepeatService.h"
namespace mozilla {
class PresShell;
} // namespace mozilla
class nsScrollbarButtonFrame final : public mozilla::SimpleXULLeafFrame {
class nsScrollbarButtonFrame final : public nsBoxFrame {
public:
NS_DECL_FRAMEARENA_HELPERS(nsScrollbarButtonFrame)
explicit nsScrollbarButtonFrame(ComputedStyle* aStyle,
nsPresContext* aPresContext)
: mozilla::SimpleXULLeafFrame(aStyle, aPresContext, kClassID) {}
: nsBoxFrame(aStyle, aPresContext, kClassID), mCursorOnThis(false) {}
// Overrides
void DestroyFrom(nsIFrame* aDestructRoot,
PostDestroyData& aPostDestroyData) override;
virtual void DestroyFrom(nsIFrame* aDestructRoot,
PostDestroyData& aPostDestroyData) override;
friend nsIFrame* NS_NewScrollbarButtonFrame(mozilla::PresShell* aPresShell,
ComputedStyle* aStyle);
@@ -80,7 +79,7 @@ class nsScrollbarButtonFrame final : public mozilla::SimpleXULLeafFrame {
static_cast<nsScrollbarButtonFrame*>(aData)->Notify();
}
bool mCursorOnThis = false;
bool mCursorOnThis;
};
#endif

View File

@@ -20,7 +20,6 @@
#include "nsIScrollbarMediator.h"
#include "nsStyleConsts.h"
#include "nsIContent.h"
#include "nsLayoutUtils.h"
#include "mozilla/LookAndFeel.h"
#include "mozilla/PresShell.h"
#include "mozilla/dom/Element.h"
@@ -45,11 +44,11 @@ NS_IMPL_FRAMEARENA_HELPERS(nsScrollbarFrame)
NS_QUERYFRAME_HEAD(nsScrollbarFrame)
NS_QUERYFRAME_ENTRY(nsScrollbarFrame)
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
void nsScrollbarFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) {
nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
// We want to be a reflow root since we use reflows to move the
// slider. Any reflow inside the scrollbar frame will be a reflow to
@@ -65,112 +64,42 @@ void nsScrollbarFrame::DestroyFrom(nsIFrame* aDestructRoot,
aPostDestroyData.AddAnonymousContent(mSlider.forget());
aPostDestroyData.AddAnonymousContent(mUpBottomButton.forget());
aPostDestroyData.AddAnonymousContent(mDownBottomButton.forget());
nsContainerFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
nsBoxFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
}
void nsScrollbarFrame::Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) {
MarkInReflow();
MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
// We always take all the space we're given, and our track size in the other
// axis.
const bool horizontal = IsHorizontal();
const auto wm = GetWritingMode();
const auto minSize = aReflowInput.ComputedMinSize();
nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowInput, aStatus);
aDesiredSize.ISize(wm) = aReflowInput.ComputedISize();
aDesiredSize.BSize(wm) = [&] {
if (aReflowInput.ComputedBSize() != NS_UNCONSTRAINEDSIZE) {
return aReflowInput.ComputedBSize();
}
// We don't want to change our size during incremental reflow, see the
// reflow root comment in init.
if (!aReflowInput.mParentReflowInput) {
return GetLogicalSize(wm).BSize(wm);
}
return minSize.BSize(wm);
}();
const nsSize containerSize = aDesiredSize.PhysicalSize();
const LogicalSize totalAvailSize = aDesiredSize.Size(wm);
LogicalPoint nextKidPos(wm);
MOZ_ASSERT(!wm.IsVertical());
const bool movesInInlineDirection = horizontal;
// Layout our kids left to right / top to bottom.
for (nsIFrame* kid : mFrames) {
MOZ_ASSERT(!kid->GetWritingMode().IsOrthogonalTo(wm),
"We don't expect orthogonal scrollbar parts");
const bool isSlider = kid->GetContent() == mSlider;
LogicalSize availSize = totalAvailSize;
{
// Assume we'll consume the same size before and after the slider. This is
// not a technically correct assumption if we have weird scrollbar button
// setups, but those will be going away, see bug 1824254.
const int32_t factor = isSlider ? 2 : 1;
if (movesInInlineDirection) {
availSize.ISize(wm) =
std::max(0, totalAvailSize.ISize(wm) - nextKidPos.I(wm) * factor);
} else {
availSize.BSize(wm) =
std::max(0, totalAvailSize.BSize(wm) - nextKidPos.B(wm) * factor);
}
}
ReflowInput kidRI(aPresContext, aReflowInput, kid, availSize);
if (isSlider) {
// We want for the slider to take all the remaining available space.
kidRI.SetComputedISize(availSize.ISize(wm));
kidRI.SetComputedBSize(availSize.BSize(wm));
} else if (movesInInlineDirection) {
// Otherwise we want all the space in the axis we're not advancing in, and
// the default / minimum size on the other axis.
kidRI.SetComputedBSize(availSize.BSize(wm));
} else {
kidRI.SetComputedISize(availSize.ISize(wm));
}
ReflowOutput kidDesiredSize(wm);
nsReflowStatus status;
const auto flags = ReflowChildFlags::Default;
ReflowChild(kid, aPresContext, kidDesiredSize, kidRI, wm, nextKidPos,
containerSize, flags, status);
// We haven't seen the slider yet, we can advance
FinishReflowChild(kid, aPresContext, kidDesiredSize, &kidRI, wm, nextKidPos,
containerSize, flags);
if (movesInInlineDirection) {
nextKidPos.I(wm) += kidDesiredSize.ISize(wm);
} else {
nextKidPos.B(wm) += kidDesiredSize.BSize(wm);
}
// nsGfxScrollFrame may have told us to shrink to nothing. If so, make sure
// our desired size agrees.
if (aReflowInput.AvailableWidth() == 0) {
aDesiredSize.Width() = 0;
}
if (aReflowInput.AvailableHeight() == 0) {
aDesiredSize.Height() = 0;
}
aDesiredSize.SetOverflowAreasToDesiredBounds();
}
nsresult nsScrollbarFrame::AttributeChanged(int32_t aNameSpaceID,
nsAtom* aAttribute,
int32_t aModType) {
nsresult rv =
nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
// Update value in our children
UpdateChildrenAttributeValue(aAttribute, true);
// if the current position changes, notify any nsGfxScrollFrame
// parent we may have
if (aAttribute != nsGkAtoms::curpos) {
return rv;
}
if (aAttribute != nsGkAtoms::curpos) return rv;
nsIScrollableFrame* scrollable = do_QueryFrame(GetParent());
if (!scrollable) {
return rv;
}
if (!scrollable) return rv;
nsCOMPtr<nsIContent> content(mContent);
scrollable->CurPosAttributeChanged(content);
@@ -235,34 +164,47 @@ nsIScrollbarMediator* nsScrollbarFrame::GetScrollbarMediator() {
return sbm;
}
bool nsScrollbarFrame::IsHorizontal() const {
auto appearance = StyleDisplay()->EffectiveAppearance();
MOZ_ASSERT(appearance == StyleAppearance::ScrollbarHorizontal ||
appearance == StyleAppearance::ScrollbarVertical);
return appearance == StyleAppearance::ScrollbarHorizontal;
}
nsresult nsScrollbarFrame::GetXULMargin(nsMargin& aMargin) {
aMargin.SizeTo(0, 0, 0, 0);
nsSize nsScrollbarFrame::ScrollbarMinSize() const {
nsPresContext* pc = PresContext();
const LayoutDeviceIntSize widget =
pc->Theme()->GetMinimumWidgetSize(pc, const_cast<nsScrollbarFrame*>(this),
StyleDisplay()->EffectiveAppearance());
return LayoutDeviceIntSize::ToAppUnits(widget, pc->AppUnitsPerDevPixel());
}
const bool overlayScrollbars = PresContext()->UseOverlayScrollbars();
StyleScrollbarWidth nsScrollbarFrame::ScrollbarWidth() const {
return nsLayoutUtils::StyleForScrollbar(this)
->StyleUIReset()
->ScrollbarWidth();
}
const bool horizontal = IsXULHorizontal();
bool didSetMargin = false;
nscoord nsScrollbarFrame::ScrollbarTrackSize() const {
nsPresContext* pc = PresContext();
auto overlay = pc->UseOverlayScrollbars() ? nsITheme::Overlay::Yes
: nsITheme::Overlay::No;
return LayoutDevicePixel::ToAppUnits(
pc->Theme()->GetScrollbarSize(pc, ScrollbarWidth(), overlay),
pc->AppUnitsPerDevPixel());
if (overlayScrollbars) {
nsSize minSize;
bool widthSet = false;
bool heightSet = false;
AddXULMinSize(this, minSize, widthSet, heightSet);
if (horizontal) {
if (heightSet) {
aMargin.top = -minSize.height;
didSetMargin = true;
}
} else {
if (widthSet) {
aMargin.left = -minSize.width;
didSetMargin = true;
}
}
}
if (!didSetMargin) {
DebugOnly<nsresult> rv = nsIFrame::GetXULMargin(aMargin);
// TODO(emilio): Should probably not be fallible, it's not like anybody
// cares about the return value anyway.
MOZ_ASSERT(NS_SUCCEEDED(rv), "nsIFrame::GetXULMargin can't really fail");
}
if (!horizontal) {
nsIScrollbarMediator* scrollFrame = GetScrollbarMediator();
if (scrollFrame && !scrollFrame->IsScrollbarOnRight()) {
std::swap(aMargin.left, aMargin.right);
}
}
return NS_OK;
}
void nsScrollbarFrame::SetIncrementToLine(int32_t aDirection) {
@@ -416,7 +358,8 @@ static already_AddRefed<Element> MakeScrollbarButton(
nsresult nsScrollbarFrame::CreateAnonymousContent(
nsTArray<ContentInfo>& aElements) {
nsNodeInfoManager* nodeInfoManager = mContent->NodeInfo()->NodeInfoManager();
Element* el = GetContent()->AsElement();
Element* el(GetContent()->AsElement());
// If there are children already in the node, don't create any anonymous
// content (this only apply to crashtests/369038-1.xhtml)
@@ -425,7 +368,7 @@ nsresult nsScrollbarFrame::CreateAnonymousContent(
}
nsAutoString orient;
el->GetAttr(nsGkAtoms::orient, orient);
el->GetAttr(kNameSpaceID_None, nsGkAtoms::orient, orient);
bool vertical = orient.EqualsLiteral("vertical");
RefPtr<dom::NodeInfo> sbbNodeInfo =
@@ -508,12 +451,12 @@ nsresult nsScrollbarFrame::CreateAnonymousContent(
void nsScrollbarFrame::UpdateChildrenAttributeValue(nsAtom* aAttribute,
bool aNotify) {
Element* el = GetContent()->AsElement();
Element* el(GetContent()->AsElement());
nsAutoString value;
el->GetAttr(aAttribute, value);
el->GetAttr(kNameSpaceID_None, aAttribute, value);
if (!el->HasAttr(aAttribute)) {
if (!el->HasAttr(kNameSpaceID_None, aAttribute)) {
if (mUpTopButton) {
mUpTopButton->UnsetAttr(kNameSpaceID_None, aAttribute, aNotify);
}

View File

@@ -13,8 +13,8 @@
#include "mozilla/Attributes.h"
#include "mozilla/ScrollTypes.h"
#include "nsContainerFrame.h"
#include "nsIAnonymousContentCreator.h"
#include "nsBoxFrame.h"
class nsIScrollbarMediator;
@@ -28,13 +28,13 @@ class Element;
nsIFrame* NS_NewScrollbarFrame(mozilla::PresShell* aPresShell,
mozilla::ComputedStyle* aStyle);
class nsScrollbarFrame final : public nsContainerFrame,
class nsScrollbarFrame final : public nsBoxFrame,
public nsIAnonymousContentCreator {
using Element = mozilla::dom::Element;
public:
explicit nsScrollbarFrame(ComputedStyle* aStyle, nsPresContext* aPresContext)
: nsContainerFrame(aStyle, aPresContext, kClassID),
: nsBoxFrame(aStyle, aPresContext, kClassID),
mSmoothScroll(false),
mScrollUnit(mozilla::ScrollUnit::DEVICE_PIXELS),
mDirection(0),
@@ -51,14 +51,14 @@ class nsScrollbarFrame final : public nsContainerFrame,
NS_DECL_FRAMEARENA_HELPERS(nsScrollbarFrame)
#ifdef DEBUG_FRAME_DUMP
nsresult GetFrameName(nsAString& aResult) const override {
virtual nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(u"ScrollbarFrame"_ns, aResult);
}
#endif
// nsIFrame overrides
nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
int32_t aModType) override;
virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
int32_t aModType) override;
NS_IMETHOD HandlePress(nsPresContext* aPresContext,
mozilla::WidgetGUIEvent* aEvent,
@@ -78,24 +78,32 @@ class nsScrollbarFrame final : public nsContainerFrame,
mozilla::WidgetGUIEvent* aEvent,
nsEventStatus* aEventStatus) override;
mozilla::StyleScrollbarWidth ScrollbarWidth() const;
nscoord ScrollbarTrackSize() const;
nsSize ScrollbarMinSize() const;
bool IsHorizontal() const;
virtual void DestroyFrom(nsIFrame* aDestructRoot,
PostDestroyData& aPostDestroyData) override;
void DestroyFrom(nsIFrame* aDestructRoot,
PostDestroyData& aPostDestroyData) override;
virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
void Init(nsIContent* aContent, nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
void SetScrollbarMediatorContent(nsIContent* aMediator);
nsIScrollbarMediator* GetScrollbarMediator();
// nsBox methods
/**
* Treat scrollbars as clipping their children; overflowing children
* will not be allowed to set an overflow rect on this
* frame. This means that when the scroll code decides to hide a
* scrollframe by setting its height or width to zero, that will
* hide the children too.
*/
virtual bool DoesClipChildrenInBothAxes() override { return true; }
virtual nsresult GetXULMargin(nsMargin& aMargin) override;
/**
* The following three methods set the value of mIncrement when a
* scrollbar button is pressed.
@@ -103,7 +111,6 @@ class nsScrollbarFrame final : public nsContainerFrame,
void SetIncrementToLine(int32_t aDirection);
void SetIncrementToPage(int32_t aDirection);
void SetIncrementToWhole(int32_t aDirection);
/**
* If aImplementsScrollByUnit is Yes then this uses mSmoothScroll,
* mScrollUnit, and mDirection and calls ScrollByUnit on the
@@ -120,9 +127,10 @@ class nsScrollbarFrame final : public nsContainerFrame,
int32_t GetIncrement() { return mIncrement; }
// nsIAnonymousContentCreator
nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) override;
virtual nsresult CreateAnonymousContent(
nsTArray<ContentInfo>& aElements) override;
virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) override;
void UpdateChildrenAttributeValue(nsAtom* aAttribute, bool aNotify);

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,6 @@
#define nsSliderFrame_h__
#include "mozilla/Attributes.h"
#include "nsIFrame.h"
#include "nsRepeatService.h"
#include "nsBoxFrame.h"
#include "nsAtom.h"
@@ -17,7 +16,6 @@
#include "nsIDOMEventListener.h"
class nsITimer;
class nsScrollbarFrame;
class nsSliderFrame;
namespace mozilla {
@@ -36,7 +34,7 @@ class nsSliderMediator final : public nsIDOMEventListener {
explicit nsSliderMediator(nsSliderFrame* aSlider) { mSlider = aSlider; }
void SetSlider(nsSliderFrame* aSlider) { mSlider = aSlider; }
virtual void SetSlider(nsSliderFrame* aSlider) { mSlider = aSlider; }
NS_DECL_NSIDOMEVENTLISTENER
@@ -44,7 +42,7 @@ class nsSliderMediator final : public nsIDOMEventListener {
virtual ~nsSliderMediator() = default;
};
class nsSliderFrame final : public nsContainerFrame {
class nsSliderFrame final : public nsBoxFrame {
public:
NS_DECL_FRAMEARENA_HELPERS(nsSliderFrame)
NS_DECL_QUERYFRAME
@@ -55,44 +53,36 @@ class nsSliderFrame final : public nsContainerFrame {
explicit nsSliderFrame(ComputedStyle* aStyle, nsPresContext* aPresContext);
virtual ~nsSliderFrame();
// Get the point associated with this event. Returns true if a single valid
// point was found. Otherwise false.
bool GetEventPoint(mozilla::WidgetGUIEvent* aEvent, nsPoint& aPoint);
// Gets the event coordinates relative to the widget associated with this
// frame. Return true if a single valid point was found.
bool GetEventPoint(mozilla::WidgetGUIEvent* aEvent,
mozilla::LayoutDeviceIntPoint& aPoint);
#ifdef DEBUG_FRAME_DUMP
nsresult GetFrameName(nsAString& aResult) const override {
virtual nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(u"SliderFrame"_ns, aResult);
}
#endif
void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
virtual nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual nsSize GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState) override;
NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState) override;
// nsIFrame overrides
void DestroyFrom(nsIFrame* aDestructRoot,
PostDestroyData& aPostDestroyData) override;
virtual void DestroyFrom(nsIFrame* aDestructRoot,
PostDestroyData& aPostDestroyData) override;
void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) override;
virtual void BuildDisplayListForChildren(
nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists) override;
void BuildDisplayListForThumb(nsDisplayListBuilder* aBuilder,
nsIFrame* aThumb,
const nsDisplayListSet& aLists);
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) override;
nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
int32_t aModType) override;
virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
int32_t aModType) override;
void Init(nsIContent* aContent, nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
nsIFrame* asPrevInFlow) override;
nsresult HandleEvent(nsPresContext* aPresContext,
mozilla::WidgetGUIEvent* aEvent,
nsEventStatus* aEventStatus) override;
virtual nsresult HandleEvent(nsPresContext* aPresContext,
mozilla::WidgetGUIEvent* aEvent,
nsEventStatus* aEventStatus) override;
// nsContainerFrame overrides
void SetInitialChildList(ChildListID aListID,
@@ -101,7 +91,7 @@ class nsSliderFrame final : public nsContainerFrame {
void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
const nsLineList::iterator* aPrevFrameLine,
nsFrameList&& aFrameList) override;
void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override;
virtual void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override;
nsresult StartDrag(mozilla::dom::Event* aEvent);
nsresult StopDrag();
@@ -115,6 +105,7 @@ class nsSliderFrame final : public nsContainerFrame {
static int32_t GetPageIncrement(nsIContent* content);
static int32_t GetIntegerAttribute(nsIContent* content, nsAtom* atom,
int32_t defaultValue);
void EnsureOrient();
NS_IMETHOD HandlePress(nsPresContext* aPresContext,
mozilla::WidgetGUIEvent* aEvent,
@@ -159,7 +150,7 @@ class nsSliderFrame final : public nsContainerFrame {
private:
bool GetScrollToClick();
nsScrollbarFrame* Scrollbar();
nsIFrame* GetScrollbar();
bool ShouldScrollForEvent(mozilla::WidgetGUIEvent* aEvent);
bool ShouldScrollToClickForEvent(mozilla::WidgetGUIEvent* aEvent);
bool IsEventOverThumb(mozilla::WidgetGUIEvent* aEvent);

View File

@@ -1,4 +1,4 @@
<?xml-stylesheet href='chrome://global/skin' type='text/css'?>
<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' align='start' pack='start' style='-moz-appearance: none; margin: 0; padding: 0; border: 0;'>
<resizer dir='bottomright' flex='1' style="min-width: 150px; min-height: 150px; appearance: none; margin: 0; border: 0; padding: 0;"/>
<resizer dir='bottomright' flex='1' style="width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;"/>
</window>

View File

@@ -1,4 +1,4 @@
<?xml-stylesheet href='chrome://global/skin' type='text/css'?>
<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' align='start' pack='start' style='-moz-appearance: none; margin: 0; padding: 0; border: 0; min-width: 120px; max-width: 480px; min-height: 110px; max-height: 470px'>
<resizer dir='bottomright' flex='1' style='min-width: 150px; min-height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
<resizer dir='bottomright' flex='1' style='width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
</window>

View File

@@ -1,4 +1,4 @@
<?xml-stylesheet href='chrome://global/skin' type='text/css'?>
<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' align='start' pack='start' style='-moz-appearance: none; margin: 0; padding: 0; border: 0; min-width: 180px; min-height: 210px;'>
<resizer dir='bottomright' flex='1' style='min-width: 150px; min-height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
<resizer dir='bottomright' flex='1' style='width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
</window>

View File

@@ -1,4 +1,4 @@
<?xml-stylesheet href='chrome://global/skin' type='text/css'?>
<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' align='start' pack='start' style='-moz-appearance: none; margin: 0; padding: 0; border: 0; max-width: 125px; max-height: 140px'>
<resizer dir='bottomright' flex='1' style='min-width: 150px; min-height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
<resizer dir='bottomright' flex='1' style='width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
</window>

View File

@@ -1,4 +1,4 @@
<?xml-stylesheet href='chrome://global/skin' type='text/css'?>
<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' align='start' pack='start' style='-moz-appearance: none; margin: 0; padding: 0; border: 0; min-width: 240px; min-height: 220px'>
<resizer dir='bottomright' flex='1' style='min-width: 150px; min-height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
<resizer dir='bottomright' flex='1' style='width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
</window>

View File

@@ -1,4 +1,4 @@
<?xml-stylesheet href='chrome://global/skin' type='text/css'?>
<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' align='start' pack='start' style='-moz-appearance: none; margin: 0; padding: 0; border: 0; min-width: 215px; min-height: 235px' width='190' height='220'>
<resizer dir='bottomright' flex='1' style='min-width: 150px; min-height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
<resizer dir='bottomright' flex='1' style='width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
</window>

View File

@@ -1,4 +1,4 @@
<?xml-stylesheet href='chrome://global/skin' type='text/css'?>
<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' align='start' pack='start' style='-moz-appearance: none; margin: 0; padding: 0; border: 0; max-width: 125px; max-height: 95px'>
<resizer dir='bottomright' flex='1' style='min-width: 150px; min-height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
<resizer dir='bottomright' flex='1' style='width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
</window>

View File

@@ -1,4 +1,4 @@
<?xml-stylesheet href='chrome://global/skin' type='text/css'?>
<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' align='start' pack='start' style='-moz-appearance: none; margin: 0; padding: 0; border: 0; min-width: 210px'>
<resizer dir='bottomright' flex='1' style='min-width: 150px; min-height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
<resizer dir='bottomright' flex='1' style='width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
</window>

View File

@@ -1,4 +1,4 @@
<?xml-stylesheet href='chrome://global/skin' type='text/css'?>
<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' align='start' pack='start' style='-moz-appearance: none; margin: 0; padding: 0; border: 0; max-width: 128px'>
<resizer dir='bottomright' flex='1' style='min-width: 150px; min-height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
<resizer dir='bottomright' flex='1' style='width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
</window>

View File

@@ -1,4 +1,4 @@
<?xml-stylesheet href='chrome://global/skin' type='text/css'?>
<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' align='start' pack='start' style='-moz-appearance: none; margin: 0; padding: 0; border: 0; max-width: 195px; min-height: 180px' width='230' height='120'>
<resizer dir='bottomright' flex='1' style='min-width: 150px; min-height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
<resizer dir='bottomright' flex='1' style='width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
</window>

View File

@@ -644,8 +644,9 @@ static void FindScrollParts(nsIFrame* aCurrFrame,
}
}
if (nsScrollbarFrame* sf = do_QueryFrame(aCurrFrame)) {
if (!sf->IsHorizontal()) {
nsScrollbarFrame* sf = do_QueryFrame(aCurrFrame);
if (sf) {
if (!aCurrFrame->IsXULHorizontal()) {
if (!aResult->mVScrollbar) {
aResult->mVScrollbar = sf;
}
@@ -670,17 +671,20 @@ static void FindScrollParts(nsIFrame* aCurrFrame,
nsTreeBodyFrame::ScrollParts nsTreeBodyFrame::GetScrollParts() {
ScrollParts result = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
XULTreeElement* tree = GetBaseElement();
if (nsIFrame* treeFrame = tree ? tree->GetPrimaryFrame() : nullptr) {
nsIFrame* treeFrame = tree ? tree->GetPrimaryFrame() : nullptr;
if (treeFrame) {
// The way we do this, searching through the entire frame subtree, is pretty
// dumb! We should know where these frames are.
FindScrollParts(treeFrame, &result);
if (result.mHScrollbar) {
result.mHScrollbar->SetScrollbarMediatorContent(GetContent());
result.mHScrollbarContent = result.mHScrollbar->GetContent()->AsElement();
nsIFrame* f = do_QueryFrame(result.mHScrollbar);
result.mHScrollbarContent = f->GetContent()->AsElement();
}
if (result.mVScrollbar) {
result.mVScrollbar->SetScrollbarMediatorContent(GetContent());
result.mVScrollbarContent = result.mVScrollbar->GetContent()->AsElement();
nsIFrame* f = do_QueryFrame(result.mVScrollbar);
result.mVScrollbarContent = f->GetContent()->AsElement();
}
}
return result;
@@ -3816,7 +3820,7 @@ void nsTreeBodyFrame::RepeatButtonScroll(nsScrollbarFrame* aScrollbar) {
} else if (increment > 0) {
direction = 1;
}
bool isHorizontal = aScrollbar->IsHorizontal();
bool isHorizontal = aScrollbar->IsXULHorizontal();
AutoWeakFrame weakFrame(this);
if (isHorizontal) {

View File

@@ -145,7 +145,7 @@ class nsTreeBodyFrame final : public nsLeafBoxFrame,
nscoord aNewPos) override;
virtual void ScrollbarReleased(nsScrollbarFrame* aScrollbar) override {}
virtual void VisibilityChanged(bool aVisible) override { Invalidate(); }
nsScrollbarFrame* GetScrollbarBox(bool aVertical) override {
virtual nsIFrame* GetScrollbarBox(bool aVertical) override {
ScrollParts parts = GetScrollParts();
return aVertical ? parts.mVScrollbar : parts.mHScrollbar;
}

View File

@@ -15,12 +15,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1048178
target="_blank">Mozilla Bug 1048178</a>
<hbox>
<scrollbar id="scroller"
orient="horizontal"
curpos="0"
maxpos="500"
pageincrement="500"
style="width: 500px; margin:0"/>
<scrollbar id="scroller"
orient="horizontal"
curpos="0"
maxpos="500"
pageincrement="500"
width="500"
style="margin:0"/>
</hbox>
<!-- test code goes here -->
@@ -44,7 +45,7 @@ var scrollbarTester = {
this.mouseup(x, y, 2);
this.mouseup(x, y, 0);
var newPos = this.getPos(); // should be '500'
var newPos = this.getPos(); // sould be '500'
this.mousedown(x, y, 0);
this.mousemove(x-1, y, 0);

View File

@@ -13,12 +13,13 @@
<body xmlns="http://www.w3.org/1999/xhtml"/>
<hbox>
<scrollbar orient="horizontal"
id="scroller"
curpos="0"
maxpos="600"
pageincrement="400"
style="width: 500px; margin: 0"/>
<scrollbar orient="horizontal"
id="scroller"
curpos="0"
maxpos="600"
pageincrement="400"
width="500"
style="margin:0"/>
</hbox>
<!-- test code goes here -->