Backed out changeset 7da2469ac949 (bug 1824236) for causing assertion failures in layout/generic/crashtests/369038-1.xhtml CLOSED TREE
This commit is contained in:
@@ -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>
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -34,7 +34,6 @@ UNIFIED_SOURCES += [
|
||||
"nsTextBoxFrame.cpp",
|
||||
"nsXULPopupManager.cpp",
|
||||
"nsXULTooltipListener.cpp",
|
||||
"SimpleXULLeafFrame.cpp",
|
||||
]
|
||||
|
||||
DIRS += ["tree"]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
Reference in New Issue
Block a user