Bug 1824236 - Stop using XUL layout for scrollbars. r=jwatt
This rewrites scrollbar layout to work with regular reflow rather than box layout. Overall it's about the same amount of code (mostly because nsScrollbarFrame::Reflow is sorta hand-rolled), but it cleans up a bit and it is progress towards removing XUL layout altogether, without getting into much deeper refactoring. This also blocks some other performance improvements and refactorings I want to make in this code. We make some assumptions to simplify the code that to some extent were made already before, both explicitly and by virtue of using XUL layout. In particular, we assume that scrollbar / slider / thumb has no border or padding and that the writing-mode is horizontal ltr. Differential Revision: https://phabricator.services.mozilla.com/D173489
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" height="300" />
|
||||
<scrollbar id="scrollbar" orient="vertical" curpos="0" maxpos="500" style="height: 300px" />
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<div style="height: 20000px; background-color: green"></div>
|
||||
<script type="application/javascript">
|
||||
<script>
|
||||
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* aPresShell,
|
||||
ComputedStyle* aStyle);
|
||||
nsIFrame* NS_NewScrollbarButtonFrame(PresShell*, ComputedStyle*);
|
||||
nsIFrame* NS_NewSimpleXULLeafFrame(PresShell*, ComputedStyle*);
|
||||
|
||||
nsIFrame* NS_NewXULImageFrame(PresShell*, ComputedStyle*);
|
||||
nsIFrame* NS_NewImageFrameForContentProperty(PresShell*, ComputedStyle*);
|
||||
@@ -4145,8 +4145,11 @@ 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(slider, NS_NewSliderFrame),
|
||||
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(scrollbarbutton, NS_NewScrollbarButtonFrame),
|
||||
{nsGkAtoms::panel, kPopupData},
|
||||
{nsGkAtoms::menupopup, kPopupData},
|
||||
|
||||
@@ -77,7 +77,8 @@ FRAME_CLASSES = [
|
||||
Frame("nsRubyFrame", "Ruby", NOT_LEAF),
|
||||
Frame("nsRubyTextContainerFrame", "RubyTextContainer", NOT_LEAF),
|
||||
Frame("nsRubyTextFrame", "RubyText", NOT_LEAF),
|
||||
Frame("nsScrollbarButtonFrame", "Box", NOT_LEAF),
|
||||
Frame("SimpleXULLeafFrame", "SimpleXULLeaf", LEAF),
|
||||
Frame("nsScrollbarButtonFrame", "SimpleXULLeaf", LEAF),
|
||||
Frame("nsScrollbarFrame", "Scrollbar", NOT_LEAF),
|
||||
Frame("nsSearchControlFrame", "SearchControl", LEAF),
|
||||
Frame("nsSelectsAreaFrame", "Block", NOT_LEAF),
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "PresShell.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsScrollbarFrame.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsStyledElement.h"
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
class="reftest-wait">
|
||||
|
||||
<head>
|
||||
<script>
|
||||
|
||||
var XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
|
||||
function boom()
|
||||
{
|
||||
var hbox = document.getElementById("hbox");
|
||||
var checkbox = document.createElementNS(XUL_NS, "checkbox");
|
||||
|
||||
hbox.appendChild(checkbox);
|
||||
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="setTimeout(boom, 30)">
|
||||
|
||||
<xul:scrollbar><span><xul:hbox id="hbox"/></span></xul:scrollbar>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -75,7 +75,6 @@ load 368568.html
|
||||
load 368752.html
|
||||
load 368860-1.html
|
||||
load 368863-1.html
|
||||
load 369038-1.xhtml
|
||||
load 369150-1.html
|
||||
load 369150-2.html
|
||||
load 369227-1.xhtml
|
||||
|
||||
@@ -397,35 +397,6 @@ 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
|
||||
|
||||
@@ -460,7 +431,6 @@ 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
|
||||
@@ -505,9 +475,9 @@ struct MOZ_STACK_CLASS ScrollReflowInput {
|
||||
|
||||
ScrollReflowInput(nsHTMLScrollFrame* aFrame, const ReflowInput& aReflowInput);
|
||||
|
||||
nscoord VScrollbarMinHeight() const { return mVScrollbarMinSize.height; }
|
||||
nscoord VScrollbarMinHeight() const { return mVScrollbarPrefSize.height; }
|
||||
nscoord VScrollbarPrefWidth() const { return mVScrollbarPrefSize.width; }
|
||||
nscoord HScrollbarMinWidth() const { return mHScrollbarMinSize.width; }
|
||||
nscoord HScrollbarMinWidth() const { return mHScrollbarPrefSize.width; }
|
||||
nscoord HScrollbarPrefHeight() const { return mHScrollbarPrefSize.height; }
|
||||
|
||||
// Returns the sizes occupied by the scrollbar gutters. If aShowVScroll or
|
||||
@@ -515,6 +485,9 @@ 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();
|
||||
@@ -531,13 +504,14 @@ 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;
|
||||
@@ -546,55 +520,35 @@ 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 (nsIFrame* hScrollbarBox = aFrame->GetScrollbarBox(false)) {
|
||||
nsScrollbarFrame* scrollbar = do_QueryFrame(hScrollbarBox);
|
||||
if (nsScrollbarFrame* scrollbar = aFrame->GetScrollbarBox(false)) {
|
||||
scrollbar->SetScrollbarMediatorContent(mReflowInput.mFrame->GetContent());
|
||||
|
||||
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
|
||||
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
|
||||
// front-end uses it.
|
||||
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");
|
||||
|
||||
MOZ_ASSERT(scrollbar->IsXULCollapsed() ||
|
||||
(mHScrollbarPrefSize.width && mHScrollbarPrefSize.height),
|
||||
"Shouldn't have a zero horizontal scrollbar-size");
|
||||
} else {
|
||||
mHScrollbar = ShowScrollbar::Never;
|
||||
mHScrollbarAllowedForScrollingVVInsideLV = false;
|
||||
}
|
||||
if (nsIFrame* vScrollbarBox = aFrame->GetScrollbarBox(true)) {
|
||||
nsScrollbarFrame* scrollbar = do_QueryFrame(vScrollbarBox);
|
||||
if (nsScrollbarFrame* scrollbar = aFrame->GetScrollbarBox(true)) {
|
||||
scrollbar->SetScrollbarMediatorContent(mReflowInput.mFrame->GetContent());
|
||||
|
||||
GetScrollbarMetrics(mBoxState, vScrollbarBox, &mVScrollbarMinSize,
|
||||
&mVScrollbarPrefSize);
|
||||
|
||||
mVScrollbarPrefSize = scrollbar->ScrollbarMinSize();
|
||||
// See above.
|
||||
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");
|
||||
MOZ_ASSERT(scrollbar->IsXULCollapsed() ||
|
||||
(mVScrollbarPrefSize.width && mVScrollbarPrefSize.height),
|
||||
"Shouldn't have a zero vertical scrollbar-size");
|
||||
} else {
|
||||
mVScrollbar = ShowScrollbar::Never;
|
||||
mVScrollbarAllowedForScrollingVVInsideLV = false;
|
||||
@@ -615,7 +569,8 @@ ScrollReflowInput::ScrollReflowInput(nsHTMLScrollFrame* aFrame,
|
||||
mVScrollbar = ShowScrollbar::Never;
|
||||
mVScrollbarAllowedForScrollingVVInsideLV = false;
|
||||
} else if (const auto& scrollbarGutterStyle =
|
||||
scrollbarStyle->StyleDisplay()->mScrollbarGutter) {
|
||||
scrollbarStyle->StyleDisplay()->mScrollbarGutter;
|
||||
scrollbarGutterStyle && !mOverlayScrollbars) {
|
||||
const auto stable =
|
||||
bool(scrollbarGutterStyle & StyleScrollbarGutter::STABLE);
|
||||
const auto bothEdges =
|
||||
@@ -789,7 +744,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 = aState.mBoxState.PresContext()->DevPixelsToAppUnits(1);
|
||||
nscoord oneDevPixel = PresContext()->DevPixelsToAppUnits(1);
|
||||
|
||||
bool showHScrollbar = aAssumeHScroll;
|
||||
bool showVScrollbar = aAssumeVScroll;
|
||||
@@ -853,6 +808,7 @@ 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
|
||||
@@ -863,9 +819,12 @@ bool nsHTMLScrollFrame::TryLayout(ScrollReflowInput& aState,
|
||||
if (!aState.mShowHScrollbar &&
|
||||
aState.mHScrollbarAllowedForScrollingVVInsideLV) {
|
||||
if (ScrollPort().width >= visualViewportSize.width + oneDevPixel &&
|
||||
visualViewportSize.width >= aState.HScrollbarMinWidth()) {
|
||||
(overlay ||
|
||||
visualViewportSize.width >= aState.HScrollbarMinWidth())) {
|
||||
vvChanged = true;
|
||||
if (!overlay) {
|
||||
visualViewportSize.height -= aState.HScrollbarPrefHeight();
|
||||
}
|
||||
aState.mShowHScrollbar = true;
|
||||
aState.mOnlyNeedHScrollbarToScrollVVInsideLV = true;
|
||||
ROOT_SCROLLBAR_LOG("TryLayout added H scrollbar for VV, VV now %s\n",
|
||||
@@ -876,9 +835,12 @@ bool nsHTMLScrollFrame::TryLayout(ScrollReflowInput& aState,
|
||||
if (!aState.mShowVScrollbar &&
|
||||
aState.mVScrollbarAllowedForScrollingVVInsideLV) {
|
||||
if (ScrollPort().height >= visualViewportSize.height + oneDevPixel &&
|
||||
visualViewportSize.height >= aState.VScrollbarMinHeight()) {
|
||||
(overlay ||
|
||||
visualViewportSize.height >= aState.VScrollbarMinHeight())) {
|
||||
vvChanged = true;
|
||||
if (!overlay) {
|
||||
visualViewportSize.width -= aState.VScrollbarPrefWidth();
|
||||
}
|
||||
aState.mShowVScrollbar = true;
|
||||
aState.mOnlyNeedVScrollbarToScrollVVInsideLV = true;
|
||||
ROOT_SCROLLBAR_LOG("TryLayout added V scrollbar for VV, VV now %s\n",
|
||||
@@ -1239,13 +1201,17 @@ void nsHTMLScrollFrame::PlaceScrollArea(ScrollReflowInput& aState,
|
||||
nscoord nsHTMLScrollFrame::IntrinsicScrollbarGutterSizeAtInlineEdges(
|
||||
gfxContext* aRenderingContext) {
|
||||
const bool isVerticalWM = GetWritingMode().IsVertical();
|
||||
nsIFrame* inlineEndScrollbarBox =
|
||||
nsScrollbarFrame* 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) {
|
||||
@@ -1268,9 +1234,7 @@ nscoord nsHTMLScrollFrame::IntrinsicScrollbarGutterSizeAtInlineEdges(
|
||||
}
|
||||
|
||||
// No need to worry about reflow depth here since it's just for scrollbars.
|
||||
nsBoxLayoutState bls(PresContext(), aRenderingContext, 0);
|
||||
nsSize scrollbarPrefSize;
|
||||
GetScrollbarMetrics(bls, inlineEndScrollbarBox, nullptr, &scrollbarPrefSize);
|
||||
nsSize scrollbarPrefSize = inlineEndScrollbarBox->ScrollbarMinSize();
|
||||
const nscoord scrollbarSize =
|
||||
isVerticalWM ? scrollbarPrefSize.height : scrollbarPrefSize.width;
|
||||
const auto bothEdges =
|
||||
@@ -1608,7 +1572,7 @@ void nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext,
|
||||
const nsRect insideBorderArea(
|
||||
nsPoint(state.mComputedBorder.left, state.mComputedBorder.top),
|
||||
layoutSize);
|
||||
LayoutScrollbars(state.mBoxState, insideBorderArea, oldScrollPort);
|
||||
LayoutScrollbars(state, insideBorderArea, oldScrollPort);
|
||||
} else {
|
||||
mSkippedScrollbarLayout = true;
|
||||
}
|
||||
@@ -1638,7 +1602,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 && !UsesOverlayScrollbars() &&
|
||||
if (mIsRoot && !state.OverlayScrollbars() &&
|
||||
(didHaveHScrollbar != state.mShowHScrollbar ||
|
||||
didHaveVScrollbar != state.mShowVScrollbar ||
|
||||
didOnlyHScrollbar != mOnlyNeedHScrollbarToScrollVVInsideLV ||
|
||||
@@ -1878,7 +1842,7 @@ void nsHTMLScrollFrame::ScrollByWhole(nsScrollbarFrame* aScrollbar,
|
||||
void nsHTMLScrollFrame::ScrollByLine(nsScrollbarFrame* aScrollbar,
|
||||
int32_t aDirection,
|
||||
ScrollSnapFlags aSnapFlags) {
|
||||
bool isHorizontal = aScrollbar->IsXULHorizontal();
|
||||
bool isHorizontal = aScrollbar->IsHorizontal();
|
||||
nsIntPoint delta;
|
||||
if (isHorizontal) {
|
||||
const double kScrollMultiplier =
|
||||
@@ -1916,7 +1880,7 @@ void nsHTMLScrollFrame::RepeatButtonScroll(nsScrollbarFrame* aScrollbar) {
|
||||
void nsHTMLScrollFrame::ThumbMoved(nsScrollbarFrame* aScrollbar,
|
||||
nscoord aOldPos, nscoord aNewPos) {
|
||||
MOZ_ASSERT(aScrollbar != nullptr);
|
||||
bool isHorizontal = aScrollbar->IsXULHorizontal();
|
||||
bool isHorizontal = aScrollbar->IsHorizontal();
|
||||
nsPoint current = GetScrollPosition();
|
||||
nsPoint dest = current;
|
||||
if (isHorizontal) {
|
||||
@@ -1953,7 +1917,7 @@ void nsHTMLScrollFrame::ScrollByUnit(nsScrollbarFrame* aScrollbar,
|
||||
ScrollUnit aUnit,
|
||||
ScrollSnapFlags aSnapFlags) {
|
||||
MOZ_ASSERT(aScrollbar != nullptr);
|
||||
bool isHorizontal = aScrollbar->IsXULHorizontal();
|
||||
bool isHorizontal = aScrollbar->IsHorizontal();
|
||||
nsIntPoint delta;
|
||||
if (isHorizontal) {
|
||||
delta.x = aDirection;
|
||||
@@ -5468,10 +5432,12 @@ void nsHTMLScrollFrame::ReloadChildFrames() {
|
||||
if (value.LowerCaseEqualsLiteral("horizontal")) {
|
||||
NS_ASSERTION(!mHScrollbarBox,
|
||||
"Found multiple horizontal scrollbars?");
|
||||
mHScrollbarBox = frame;
|
||||
mHScrollbarBox = do_QueryFrame(frame);
|
||||
MOZ_ASSERT(mHScrollbarBox, "Not a scrollbar?");
|
||||
} else {
|
||||
NS_ASSERTION(!mVScrollbarBox, "Found multiple vertical scrollbars?");
|
||||
mVScrollbarBox = frame;
|
||||
mVScrollbarBox = do_QueryFrame(frame);
|
||||
MOZ_ASSERT(mVScrollbarBox, "Not a scrollbar?");
|
||||
}
|
||||
} else if (content->IsXULElement(nsGkAtoms::resizer)) {
|
||||
NS_ASSERTION(!mResizerBox, "Found multiple resizers");
|
||||
@@ -5817,7 +5783,9 @@ 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();
|
||||
|
||||
@@ -6530,12 +6498,39 @@ static void AdjustOverlappingScrollbars(nsRect& aVRect, nsRect& aHRect) {
|
||||
}
|
||||
}
|
||||
|
||||
void nsHTMLScrollFrame::LayoutScrollbars(nsBoxLayoutState& aState,
|
||||
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,
|
||||
const nsRect& aInsideBorderArea,
|
||||
const nsRect& aOldScrollPort) {
|
||||
NS_ASSERTION(!mSuppressScrollbarUpdate, "This should have been suppressed");
|
||||
|
||||
bool scrollbarOnLeft = !IsScrollbarOnRight();
|
||||
const bool scrollbarOnLeft = !IsScrollbarOnRight();
|
||||
const bool overlayScrollbars = UsesOverlayScrollbars();
|
||||
const bool overlayScrollBarsOnRoot = overlayScrollbars && mIsRoot;
|
||||
const bool showVScrollbar = mVScrollbarBox && mHasVerticalScrollbar;
|
||||
@@ -6550,7 +6545,6 @@ void nsHTMLScrollFrame::LayoutScrollbars(nsBoxLayoutState& 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;
|
||||
@@ -6561,67 +6555,46 @@ void nsHTMLScrollFrame::LayoutScrollbars(nsBoxLayoutState& aState,
|
||||
vRect.width = aInsideBorderArea.XMost() - mScrollPort.XMost();
|
||||
vRect.x = mScrollPort.x + compositionSize.width;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if (overlayScrollbars || mOnlyNeedVScrollbarToScrollVVInsideLV) {
|
||||
const nscoord width = aState.VScrollbarPrefWidth();
|
||||
// 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.
|
||||
nsSize vScrollbarPrefSize(0, 0);
|
||||
GetScrollbarMetrics(aState, mVScrollbarBox, nullptr, &vScrollbarPrefSize);
|
||||
vRect.width += width;
|
||||
if (scrollbarOnLeft) {
|
||||
margin.right -= vScrollbarPrefSize.width;
|
||||
vRect.x += width;
|
||||
} else {
|
||||
margin.left -= vScrollbarPrefSize.width;
|
||||
vRect.x -= 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;
|
||||
|
||||
// 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) {
|
||||
if (overlayScrollbars || mOnlyNeedHScrollbarToScrollVVInsideLV) {
|
||||
const nscoord height = aState.HScrollbarPrefHeight();
|
||||
hRect.height += height;
|
||||
// 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.
|
||||
nsSize hScrollbarPrefSize(0, 0);
|
||||
GetScrollbarMetrics(aState, mHScrollbarBox, nullptr, &hScrollbarPrefSize);
|
||||
margin.top -= hScrollbarPrefSize.height;
|
||||
hRect.y -= 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
|
||||
@@ -6653,20 +6626,25 @@ void nsHTMLScrollFrame::LayoutScrollbars(nsBoxLayoutState& aState,
|
||||
r.y = mScrollPort.YMost() - r.height;
|
||||
}
|
||||
|
||||
nsBoxFrame::LayoutChildAt(aState, mScrollCornerBox, r);
|
||||
ReflowInput scrollCornerRI(
|
||||
pc, aState.mReflowInput, mScrollCornerBox,
|
||||
LogicalSize(mScrollCornerBox->GetWritingMode(), r.Size()));
|
||||
LayoutScrollbarPartAtRect(aState, scrollCornerRI, 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);
|
||||
nsSize resizerMinSize = mResizerBox->GetXULMinSize(aState);
|
||||
ReflowInput resizerRI(pc, aState.mReflowInput, mResizerBox,
|
||||
LogicalSize(mResizerBox->GetWritingMode()));
|
||||
nsSize resizerMinSize = {resizerRI.ComputedMinWidth(),
|
||||
resizerRI.ComputedMinHeight()};
|
||||
|
||||
nsRect r;
|
||||
nscoord vScrollbarWidth = pc->DevPixelsToAppUnits(scrollbarSize);
|
||||
@@ -6680,7 +6658,7 @@ void nsHTMLScrollFrame::LayoutScrollbars(nsBoxLayoutState& aState,
|
||||
std::max(std::max(r.height, hScrollbarHeight), resizerMinSize.height);
|
||||
r.y = aInsideBorderArea.YMost() - r.height;
|
||||
|
||||
nsBoxFrame::LayoutChildAt(aState, mResizerBox, r);
|
||||
LayoutScrollbarPartAtRect(aState, resizerRI, r);
|
||||
}
|
||||
|
||||
// Note that AdjustScrollbarRectForResizer has to be called after the
|
||||
@@ -6702,10 +6680,16 @@ void nsHTMLScrollFrame::LayoutScrollbars(nsBoxLayoutState& aState,
|
||||
AdjustOverlappingScrollbars(vRect, hRect);
|
||||
}
|
||||
if (mVScrollbarBox) {
|
||||
nsBoxFrame::LayoutChildAt(aState, mVScrollbarBox, vRect);
|
||||
ReflowInput vScrollbarRI(
|
||||
pc, aState.mReflowInput, mVScrollbarBox,
|
||||
LogicalSize(mVScrollbarBox->GetWritingMode(), vRect.Size()));
|
||||
LayoutScrollbarPartAtRect(aState, vScrollbarRI, vRect);
|
||||
}
|
||||
if (mHScrollbarBox) {
|
||||
nsBoxFrame::LayoutChildAt(aState, mHScrollbarBox, hRect);
|
||||
ReflowInput hScrollbarRI(
|
||||
pc, aState.mReflowInput, mHScrollbarBox,
|
||||
LogicalSize(mHScrollbarBox->GetWritingMode(), hRect.Size()));
|
||||
LayoutScrollbarPartAtRect(aState, hScrollbarRI, hRect);
|
||||
}
|
||||
|
||||
// may need to update fixed position children of the viewport,
|
||||
@@ -6720,7 +6704,7 @@ void nsHTMLScrollFrame::LayoutScrollbars(nsBoxLayoutState& aState,
|
||||
// post reflow callback to modify scrollbar attributes
|
||||
mUpdateScrollbarAttributes = true;
|
||||
if (!mPostedReflowCallback) {
|
||||
aState.PresShell()->PostReflowCallback(this);
|
||||
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 {}
|
||||
nsIFrame* GetScrollbarBox(bool aVertical) final {
|
||||
nsScrollbarFrame* GetScrollbarBox(bool aVertical) final {
|
||||
return aVertical ? mVScrollbarBox : mHScrollbarBox;
|
||||
}
|
||||
|
||||
@@ -717,10 +717,13 @@ class nsHTMLScrollFrame : public nsContainerFrame,
|
||||
void AdjustScrollbarRectForResizer(
|
||||
nsIFrame* aFrame, nsPresContext* aPresContext, nsRect& aRect,
|
||||
bool aHasResizer, mozilla::layers::ScrollDirection aDirection);
|
||||
void LayoutScrollbars(nsBoxLayoutState& aState,
|
||||
void LayoutScrollbars(ScrollReflowInput& aState,
|
||||
const nsRect& aInsideBorderArea,
|
||||
const nsRect& aOldScrollPort);
|
||||
|
||||
void LayoutScrollbarPartAtRect(const ScrollReflowInput&,
|
||||
ReflowInput& aKidReflowInput, const nsRect&);
|
||||
|
||||
bool IsAlwaysActive() const;
|
||||
void MarkRecentlyScrolled();
|
||||
void MarkNotRecentlyScrolled();
|
||||
@@ -783,8 +786,8 @@ class nsHTMLScrollFrame : public nsContainerFrame,
|
||||
RefPtr<ScrollEndEvent> mScrollEndEvent;
|
||||
nsRevocableEventPtr<AsyncScrollPortEvent> mAsyncScrollPortEvent;
|
||||
nsRevocableEventPtr<ScrolledAreaEvent> mScrolledAreaEvent;
|
||||
nsIFrame* mHScrollbarBox;
|
||||
nsIFrame* mVScrollbarBox;
|
||||
nsScrollbarFrame* mHScrollbarBox;
|
||||
nsScrollbarFrame* 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 (nullptr == aReflowInput.mLineLayout) {
|
||||
if (!aReflowInput.mLineLayout) {
|
||||
NS_ERROR("must have non-null aReflowInput.mLineLayout");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -21,24 +21,15 @@
|
||||
-moz-font-smoothing-background-color: initial;
|
||||
-moz-min-font-size-ratio: initial;
|
||||
-moz-box-collapse: 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).
|
||||
*/
|
||||
-moz-box-layout: initial;
|
||||
|
||||
math-depth: initial;
|
||||
/* As long as inert implies pointer-events: none as it does now, we're
|
||||
* good. */
|
||||
-moz-inert: initial;
|
||||
|
||||
/* 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;
|
||||
/* direction: initial is not sufficient, since its initial value can depend
|
||||
* on the document's language. But we specify ltr explicitly below */
|
||||
|
||||
/* Similarly for font properties, whose initial values depend on the
|
||||
* document's language. Scrollbar parts don't have any text or rely on
|
||||
@@ -69,16 +60,17 @@
|
||||
}
|
||||
|
||||
scrollbar, scrollbarbutton, scrollcorner, slider, thumb, resizer {
|
||||
/* 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;
|
||||
/* 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;
|
||||
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;
|
||||
@@ -96,11 +88,6 @@ 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;
|
||||
@@ -147,14 +134,10 @@ 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 {
|
||||
@@ -175,7 +158,6 @@ scrollbar {
|
||||
|
||||
scrollbar[orient="vertical"] {
|
||||
-moz-default-appearance: scrollbar-vertical;
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
scrollbar[root="true"] {
|
||||
@@ -197,12 +179,10 @@ 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,18 +13,21 @@ 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: -->
|
||||
<div style="width: 100px">
|
||||
fixed-width
|
||||
<div>(child)</div>
|
||||
</div>
|
||||
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>
|
||||
<div style="position: absolute; width: 150px">
|
||||
abs-fixed-width
|
||||
<div>(child)</div>
|
||||
</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
/** Test for Bug 1367568 **/
|
||||
@@ -77,9 +80,11 @@ 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
|
||||
// (+2 is to allow for reflowing scrollbars themselves):
|
||||
const expectedMax = count + 2;
|
||||
const expectedMax = count + scrollbarReflows;
|
||||
|
||||
// Shared ending for messages in all ok() checks below:
|
||||
const messageSuffix =
|
||||
|
||||
37
layout/xul/SimpleXULLeafFrame.cpp
Normal file
37
layout/xul/SimpleXULLeafFrame.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
/* -*- 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
|
||||
46
layout/xul/SimpleXULLeafFrame.h
Normal file
46
layout/xul/SimpleXULLeafFrame.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* -*- 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,6 +34,7 @@ UNIFIED_SOURCES += [
|
||||
"nsTextBoxFrame.cpp",
|
||||
"nsXULPopupManager.cpp",
|
||||
"nsXULTooltipListener.cpp",
|
||||
"SimpleXULLeafFrame.cpp",
|
||||
]
|
||||
|
||||
DIRS += ["tree"]
|
||||
|
||||
@@ -884,34 +884,3 @@ 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,14 +154,6 @@ 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 nsIFrame* GetScrollbarBox(bool aVertical) = 0;
|
||||
virtual nsScrollbarFrame* GetScrollbarBox(bool aVertical) = 0;
|
||||
/**
|
||||
* Show or hide scrollbars on 2 fingers touch.
|
||||
* Subclasses should call their ScrollbarActivity's corresponding methods.
|
||||
|
||||
@@ -39,7 +39,6 @@ nsIFrame* NS_NewScrollbarButtonFrame(PresShell* aPresShell,
|
||||
return new (aPresShell)
|
||||
nsScrollbarButtonFrame(aStyle, aPresShell->GetPresContext());
|
||||
}
|
||||
|
||||
NS_IMPL_FRAMEARENA_HELPERS(nsScrollbarButtonFrame)
|
||||
|
||||
nsresult nsScrollbarButtonFrame::HandleEvent(nsPresContext* aPresContext,
|
||||
@@ -79,7 +78,7 @@ nsresult nsScrollbarButtonFrame::HandleEvent(nsPresContext* aPresContext,
|
||||
break;
|
||||
}
|
||||
|
||||
return nsBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
|
||||
return SimpleXULLeafFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
|
||||
}
|
||||
|
||||
bool nsScrollbarButtonFrame::HandleButtonPress(nsPresContext* aPresContext,
|
||||
@@ -270,5 +269,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();
|
||||
nsBoxFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
|
||||
SimpleXULLeafFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
|
||||
}
|
||||
|
||||
@@ -14,24 +14,25 @@
|
||||
#ifndef nsScrollbarButtonFrame_h___
|
||||
#define nsScrollbarButtonFrame_h___
|
||||
|
||||
#include "SimpleXULLeafFrame.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsBoxFrame.h"
|
||||
#include "nsLeafFrame.h"
|
||||
#include "nsRepeatService.h"
|
||||
|
||||
namespace mozilla {
|
||||
class PresShell;
|
||||
} // namespace mozilla
|
||||
|
||||
class nsScrollbarButtonFrame final : public nsBoxFrame {
|
||||
class nsScrollbarButtonFrame final : public mozilla::SimpleXULLeafFrame {
|
||||
public:
|
||||
NS_DECL_FRAMEARENA_HELPERS(nsScrollbarButtonFrame)
|
||||
|
||||
explicit nsScrollbarButtonFrame(ComputedStyle* aStyle,
|
||||
nsPresContext* aPresContext)
|
||||
: nsBoxFrame(aStyle, aPresContext, kClassID), mCursorOnThis(false) {}
|
||||
: mozilla::SimpleXULLeafFrame(aStyle, aPresContext, kClassID) {}
|
||||
|
||||
// Overrides
|
||||
virtual void DestroyFrom(nsIFrame* aDestructRoot,
|
||||
void DestroyFrom(nsIFrame* aDestructRoot,
|
||||
PostDestroyData& aPostDestroyData) override;
|
||||
|
||||
friend nsIFrame* NS_NewScrollbarButtonFrame(mozilla::PresShell* aPresShell,
|
||||
@@ -79,7 +80,7 @@ class nsScrollbarButtonFrame final : public nsBoxFrame {
|
||||
static_cast<nsScrollbarButtonFrame*>(aData)->Notify();
|
||||
}
|
||||
|
||||
bool mCursorOnThis;
|
||||
bool mCursorOnThis = false;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#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"
|
||||
@@ -44,11 +45,11 @@ NS_IMPL_FRAMEARENA_HELPERS(nsScrollbarFrame)
|
||||
NS_QUERYFRAME_HEAD(nsScrollbarFrame)
|
||||
NS_QUERYFRAME_ENTRY(nsScrollbarFrame)
|
||||
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
|
||||
NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
|
||||
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
|
||||
|
||||
void nsScrollbarFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
|
||||
nsIFrame* aPrevInFlow) {
|
||||
nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
|
||||
nsContainerFrame::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
|
||||
@@ -64,42 +65,112 @@ void nsScrollbarFrame::DestroyFrom(nsIFrame* aDestructRoot,
|
||||
aPostDestroyData.AddAnonymousContent(mSlider.forget());
|
||||
aPostDestroyData.AddAnonymousContent(mUpBottomButton.forget());
|
||||
aPostDestroyData.AddAnonymousContent(mDownBottomButton.forget());
|
||||
nsBoxFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
|
||||
nsContainerFrame::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!");
|
||||
|
||||
nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowInput, aStatus);
|
||||
// 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();
|
||||
|
||||
// nsGfxScrollFrame may have told us to shrink to nothing. If so, make sure
|
||||
// our desired size agrees.
|
||||
if (aReflowInput.AvailableWidth() == 0) {
|
||||
aDesiredSize.Width() = 0;
|
||||
aDesiredSize.ISize(wm) = aReflowInput.ComputedISize();
|
||||
aDesiredSize.BSize(wm) = [&] {
|
||||
if (aReflowInput.ComputedBSize() != NS_UNCONSTRAINEDSIZE) {
|
||||
return aReflowInput.ComputedBSize();
|
||||
}
|
||||
if (aReflowInput.AvailableHeight() == 0) {
|
||||
aDesiredSize.Height() = 0;
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
aDesiredSize.SetOverflowAreasToDesiredBounds();
|
||||
}
|
||||
|
||||
nsresult nsScrollbarFrame::AttributeChanged(int32_t aNameSpaceID,
|
||||
nsAtom* aAttribute,
|
||||
int32_t aModType) {
|
||||
nsresult rv =
|
||||
nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
|
||||
nsContainerFrame::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);
|
||||
@@ -164,47 +235,34 @@ nsIScrollbarMediator* nsScrollbarFrame::GetScrollbarMediator() {
|
||||
return sbm;
|
||||
}
|
||||
|
||||
nsresult nsScrollbarFrame::GetXULMargin(nsMargin& aMargin) {
|
||||
aMargin.SizeTo(0, 0, 0, 0);
|
||||
bool nsScrollbarFrame::IsHorizontal() const {
|
||||
auto appearance = StyleDisplay()->EffectiveAppearance();
|
||||
MOZ_ASSERT(appearance == StyleAppearance::ScrollbarHorizontal ||
|
||||
appearance == StyleAppearance::ScrollbarVertical);
|
||||
return appearance == StyleAppearance::ScrollbarHorizontal;
|
||||
}
|
||||
|
||||
const bool overlayScrollbars = PresContext()->UseOverlayScrollbars();
|
||||
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 horizontal = IsXULHorizontal();
|
||||
bool didSetMargin = false;
|
||||
StyleScrollbarWidth nsScrollbarFrame::ScrollbarWidth() const {
|
||||
return nsLayoutUtils::StyleForScrollbar(this)
|
||||
->StyleUIReset()
|
||||
->ScrollbarWidth();
|
||||
}
|
||||
|
||||
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;
|
||||
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());
|
||||
}
|
||||
|
||||
void nsScrollbarFrame::SetIncrementToLine(int32_t aDirection) {
|
||||
@@ -358,8 +416,7 @@ 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)
|
||||
@@ -368,7 +425,7 @@ nsresult nsScrollbarFrame::CreateAnonymousContent(
|
||||
}
|
||||
|
||||
nsAutoString orient;
|
||||
el->GetAttr(kNameSpaceID_None, nsGkAtoms::orient, orient);
|
||||
el->GetAttr(nsGkAtoms::orient, orient);
|
||||
bool vertical = orient.EqualsLiteral("vertical");
|
||||
|
||||
RefPtr<dom::NodeInfo> sbbNodeInfo =
|
||||
@@ -451,12 +508,12 @@ nsresult nsScrollbarFrame::CreateAnonymousContent(
|
||||
|
||||
void nsScrollbarFrame::UpdateChildrenAttributeValue(nsAtom* aAttribute,
|
||||
bool aNotify) {
|
||||
Element* el(GetContent()->AsElement());
|
||||
Element* el = GetContent()->AsElement();
|
||||
|
||||
nsAutoString value;
|
||||
el->GetAttr(kNameSpaceID_None, aAttribute, value);
|
||||
el->GetAttr(aAttribute, value);
|
||||
|
||||
if (!el->HasAttr(kNameSpaceID_None, aAttribute)) {
|
||||
if (!el->HasAttr(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 nsBoxFrame,
|
||||
class nsScrollbarFrame final : public nsContainerFrame,
|
||||
public nsIAnonymousContentCreator {
|
||||
using Element = mozilla::dom::Element;
|
||||
|
||||
public:
|
||||
explicit nsScrollbarFrame(ComputedStyle* aStyle, nsPresContext* aPresContext)
|
||||
: nsBoxFrame(aStyle, aPresContext, kClassID),
|
||||
: nsContainerFrame(aStyle, aPresContext, kClassID),
|
||||
mSmoothScroll(false),
|
||||
mScrollUnit(mozilla::ScrollUnit::DEVICE_PIXELS),
|
||||
mDirection(0),
|
||||
@@ -51,13 +51,13 @@ class nsScrollbarFrame final : public nsBoxFrame,
|
||||
NS_DECL_FRAMEARENA_HELPERS(nsScrollbarFrame)
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
virtual nsresult GetFrameName(nsAString& aResult) const override {
|
||||
nsresult GetFrameName(nsAString& aResult) const override {
|
||||
return MakeFrameName(u"ScrollbarFrame"_ns, aResult);
|
||||
}
|
||||
#endif
|
||||
|
||||
// nsIFrame overrides
|
||||
virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
|
||||
nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
|
||||
int32_t aModType) override;
|
||||
|
||||
NS_IMETHOD HandlePress(nsPresContext* aPresContext,
|
||||
@@ -78,32 +78,24 @@ class nsScrollbarFrame final : public nsBoxFrame,
|
||||
mozilla::WidgetGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus) override;
|
||||
|
||||
virtual void DestroyFrom(nsIFrame* aDestructRoot,
|
||||
mozilla::StyleScrollbarWidth ScrollbarWidth() const;
|
||||
nscoord ScrollbarTrackSize() const;
|
||||
nsSize ScrollbarMinSize() const;
|
||||
bool IsHorizontal() const;
|
||||
|
||||
void DestroyFrom(nsIFrame* aDestructRoot,
|
||||
PostDestroyData& aPostDestroyData) override;
|
||||
|
||||
virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
|
||||
void Init(nsIContent* aContent, nsContainerFrame* aParent,
|
||||
nsIFrame* aPrevInFlow) override;
|
||||
|
||||
virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
|
||||
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.
|
||||
@@ -111,6 +103,7 @@ class nsScrollbarFrame final : public nsBoxFrame,
|
||||
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
|
||||
@@ -127,9 +120,8 @@ class nsScrollbarFrame final : public nsBoxFrame,
|
||||
int32_t GetIncrement() { return mIncrement; }
|
||||
|
||||
// nsIAnonymousContentCreator
|
||||
virtual nsresult CreateAnonymousContent(
|
||||
nsTArray<ContentInfo>& aElements) override;
|
||||
virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
|
||||
nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
|
||||
void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
|
||||
uint32_t aFilter) override;
|
||||
|
||||
void UpdateChildrenAttributeValue(nsAtom* aAttribute, bool aNotify);
|
||||
|
||||
@@ -65,11 +65,6 @@ int32_t nsSliderFrame::gSnapMultiplier;
|
||||
// Turn this on if you want to debug slider frames.
|
||||
#undef DEBUG_SLIDER
|
||||
|
||||
static already_AddRefed<nsIContent> GetContentOfBox(nsIFrame* aBox) {
|
||||
nsCOMPtr<nsIContent> content = aBox->GetContent();
|
||||
return content.forget();
|
||||
}
|
||||
|
||||
nsIFrame* NS_NewSliderFrame(PresShell* aPresShell, ComputedStyle* aStyle) {
|
||||
return new (aPresShell) nsSliderFrame(aStyle, aPresShell->GetPresContext());
|
||||
}
|
||||
@@ -78,10 +73,10 @@ NS_IMPL_FRAMEARENA_HELPERS(nsSliderFrame)
|
||||
|
||||
NS_QUERYFRAME_HEAD(nsSliderFrame)
|
||||
NS_QUERYFRAME_ENTRY(nsSliderFrame)
|
||||
NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
|
||||
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
|
||||
|
||||
nsSliderFrame::nsSliderFrame(ComputedStyle* aStyle, nsPresContext* aPresContext)
|
||||
: nsBoxFrame(aStyle, aPresContext, kClassID),
|
||||
: nsContainerFrame(aStyle, aPresContext, kClassID),
|
||||
mRatio(0.0f),
|
||||
mDragStart(0),
|
||||
mThumbStart(0),
|
||||
@@ -96,7 +91,7 @@ nsSliderFrame::nsSliderFrame(ComputedStyle* aStyle, nsPresContext* aPresContext)
|
||||
// stop timer
|
||||
nsSliderFrame::~nsSliderFrame() {
|
||||
if (mSuppressionActive) {
|
||||
if (mozilla::PresShell* presShell = PresShell()) {
|
||||
if (auto* presShell = PresShell()) {
|
||||
presShell->SuppressDisplayport(false);
|
||||
}
|
||||
}
|
||||
@@ -104,7 +99,7 @@ nsSliderFrame::~nsSliderFrame() {
|
||||
|
||||
void nsSliderFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
|
||||
nsIFrame* aPrevInFlow) {
|
||||
nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
|
||||
nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
|
||||
|
||||
static bool gotPrefs = false;
|
||||
if (!gotPrefs) {
|
||||
@@ -118,26 +113,32 @@ void nsSliderFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
|
||||
}
|
||||
|
||||
void nsSliderFrame::RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) {
|
||||
nsBoxFrame::RemoveFrame(aListID, aOldFrame);
|
||||
if (mFrames.IsEmpty()) RemoveListener();
|
||||
nsContainerFrame::RemoveFrame(aListID, aOldFrame);
|
||||
if (mFrames.IsEmpty()) {
|
||||
RemoveListener();
|
||||
}
|
||||
}
|
||||
|
||||
void nsSliderFrame::InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
|
||||
const nsLineList::iterator* aPrevFrameLine,
|
||||
nsFrameList&& aFrameList) {
|
||||
bool wasEmpty = mFrames.IsEmpty();
|
||||
nsBoxFrame::InsertFrames(aListID, aPrevFrame, aPrevFrameLine,
|
||||
nsContainerFrame::InsertFrames(aListID, aPrevFrame, aPrevFrameLine,
|
||||
std::move(aFrameList));
|
||||
if (wasEmpty) AddListener();
|
||||
if (wasEmpty) {
|
||||
AddListener();
|
||||
}
|
||||
}
|
||||
|
||||
void nsSliderFrame::AppendFrames(ChildListID aListID,
|
||||
nsFrameList&& aFrameList) {
|
||||
// if we have no children and on was added then make sure we add the
|
||||
// If we have no children and on was added then make sure we add the
|
||||
// listener
|
||||
bool wasEmpty = mFrames.IsEmpty();
|
||||
nsBoxFrame::AppendFrames(aListID, std::move(aFrameList));
|
||||
if (wasEmpty) AddListener();
|
||||
nsContainerFrame::AppendFrames(aListID, std::move(aFrameList));
|
||||
if (wasEmpty) {
|
||||
AddListener();
|
||||
}
|
||||
}
|
||||
|
||||
int32_t nsSliderFrame::GetCurrentPosition(nsIContent* content) {
|
||||
@@ -179,7 +180,7 @@ int32_t nsSliderFrame::GetIntegerAttribute(nsIContent* content, nsAtom* atom,
|
||||
nsresult nsSliderFrame::AttributeChanged(int32_t aNameSpaceID,
|
||||
nsAtom* aAttribute, int32_t aModType) {
|
||||
nsresult rv =
|
||||
nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
|
||||
nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
|
||||
// if the current position changes
|
||||
if (aAttribute == nsGkAtoms::curpos) {
|
||||
CurrentPositionChanged();
|
||||
@@ -187,8 +188,8 @@ nsresult nsSliderFrame::AttributeChanged(int32_t aNameSpaceID,
|
||||
aAttribute == nsGkAtoms::maxpos) {
|
||||
// bounds check it.
|
||||
|
||||
nsIFrame* scrollbarBox = GetScrollbar();
|
||||
nsCOMPtr<nsIContent> scrollbar = GetContentOfBox(scrollbarBox);
|
||||
nsScrollbarFrame* scrollbarBox = Scrollbar();
|
||||
nsCOMPtr<nsIContent> scrollbar = scrollbarBox->GetContent();
|
||||
int32_t current = GetCurrentPosition(scrollbar);
|
||||
int32_t min = GetMinPosition(scrollbar);
|
||||
int32_t max = GetMaxPosition(scrollbar);
|
||||
@@ -204,15 +205,12 @@ nsresult nsSliderFrame::AttributeChanged(int32_t aNameSpaceID,
|
||||
}
|
||||
|
||||
// set the new position and notify observers
|
||||
nsScrollbarFrame* scrollbarFrame = do_QueryFrame(scrollbarBox);
|
||||
if (scrollbarFrame) {
|
||||
nsIScrollbarMediator* mediator = scrollbarFrame->GetScrollbarMediator();
|
||||
scrollbarFrame->SetIncrementToWhole(direction);
|
||||
nsIScrollbarMediator* mediator = scrollbarBox->GetScrollbarMediator();
|
||||
scrollbarBox->SetIncrementToWhole(direction);
|
||||
if (mediator) {
|
||||
mediator->ScrollByWhole(scrollbarFrame, direction,
|
||||
mediator->ScrollByWhole(scrollbarBox, direction,
|
||||
ScrollSnapFlags::IntendedEndPosition);
|
||||
}
|
||||
}
|
||||
// 'this' might be destroyed here
|
||||
|
||||
nsContentUtils::AddScriptRunner(new nsSetAttrRunnable(
|
||||
@@ -246,8 +244,7 @@ class nsDisplaySliderMarks final : public nsPaintedDisplayItem {
|
||||
void PaintMarks(nsDisplayListBuilder* aDisplayListBuilder,
|
||||
wr::DisplayListBuilder* aBuilder, gfxContext* aCtx);
|
||||
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap) const override {
|
||||
nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override {
|
||||
*aSnap = false;
|
||||
return mFrame->InkOverflowRectRelativeToSelf() + ToReferenceFrame();
|
||||
}
|
||||
@@ -255,7 +252,7 @@ class nsDisplaySliderMarks final : public nsPaintedDisplayItem {
|
||||
bool CreateWebRenderCommands(
|
||||
wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
|
||||
const StackingContextHelper& aSc,
|
||||
mozilla::layers::RenderRootStateManager* aManager,
|
||||
layers::RenderRootStateManager* aManager,
|
||||
nsDisplayListBuilder* aDisplayListBuilder) override;
|
||||
|
||||
void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
|
||||
@@ -287,8 +284,8 @@ void nsDisplaySliderMarks::PaintMarks(nsDisplayListBuilder* aDisplayListBuilder,
|
||||
|
||||
nsSliderFrame* sliderFrame = static_cast<nsSliderFrame*>(mFrame);
|
||||
|
||||
nsIFrame* scrollbarBox = sliderFrame->GetScrollbar();
|
||||
nsCOMPtr<nsIContent> scrollbar = GetContentOfBox(scrollbarBox);
|
||||
nsIFrame* scrollbarBox = sliderFrame->Scrollbar();
|
||||
nsCOMPtr<nsIContent> scrollbar = scrollbarBox->GetContent();
|
||||
|
||||
int32_t minPos = sliderFrame->GetMinPosition(scrollbar);
|
||||
int32_t maxPos = sliderFrame->GetMaxPosition(scrollbar);
|
||||
@@ -312,7 +309,7 @@ void nsDisplaySliderMarks::PaintMarks(nsDisplayListBuilder* aDisplayListBuilder,
|
||||
->DeviceContext()
|
||||
->GetDesktopToDeviceScale()
|
||||
.scale;
|
||||
bool isHorizontal = sliderFrame->IsXULHorizontal();
|
||||
const bool isHorizontal = sliderFrame->Scrollbar()->IsHorizontal();
|
||||
float increasePixelsX = isHorizontal ? increasePixels : 0;
|
||||
float increasePixelsY = isHorizontal ? 0 : increasePixels;
|
||||
nsSize initialSize =
|
||||
@@ -358,8 +355,7 @@ void nsDisplaySliderMarks::PaintMarks(nsDisplayListBuilder* aDisplayListBuilder,
|
||||
|
||||
bool nsDisplaySliderMarks::CreateWebRenderCommands(
|
||||
wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources,
|
||||
const StackingContextHelper& aSc,
|
||||
mozilla::layers::RenderRootStateManager* aManager,
|
||||
const StackingContextHelper& aSc, layers::RenderRootStateManager* aManager,
|
||||
nsDisplayListBuilder* aDisplayListBuilder) {
|
||||
PaintMarks(aDisplayListBuilder, &aBuilder, nullptr);
|
||||
return true;
|
||||
@@ -381,22 +377,24 @@ void nsSliderFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
return;
|
||||
}
|
||||
|
||||
nsBoxFrame::BuildDisplayList(aBuilder, aLists);
|
||||
DisplayBorderBackgroundOutline(aBuilder, aLists);
|
||||
|
||||
// If this is a vertical scrollbar for the root frame, draw any markers.
|
||||
if (nsIFrame* thumb = mFrames.FirstChild()) {
|
||||
BuildDisplayListForThumb(aBuilder, thumb, aLists);
|
||||
}
|
||||
|
||||
// If this is an scrollbar for the root frame, draw any markers.
|
||||
// Markers are not drawn for other scrollbars.
|
||||
// XXX seems like this should be done in nsScrollbarFrame instead perhaps?
|
||||
if (!aBuilder->IsForEventDelivery()) {
|
||||
nsIFrame* scrollbarBox = GetScrollbar();
|
||||
if (scrollbarBox) {
|
||||
nsScrollbarFrame* scrollbar = Scrollbar();
|
||||
if (nsIScrollableFrame* scrollFrame =
|
||||
do_QueryFrame(scrollbarBox->GetParent())) {
|
||||
do_QueryFrame(scrollbar->GetParent())) {
|
||||
if (scrollFrame->IsRootScrollFrameOfDocument()) {
|
||||
Document* doc = mContent->GetUncomposedDoc();
|
||||
if (doc) {
|
||||
nsGlobalWindowInner* window =
|
||||
nsGlobalWindowInner::Cast(doc->GetInnerWindow());
|
||||
nsGlobalWindowInner* window = nsGlobalWindowInner::Cast(
|
||||
PresContext()->Document()->GetInnerWindow());
|
||||
if (window &&
|
||||
window->GetScrollMarksOnHScrollbar() == IsXULHorizontal() &&
|
||||
window->GetScrollMarksOnHScrollbar() == scrollbar->IsHorizontal() &&
|
||||
window->GetScrollMarks().Length() > 0) {
|
||||
aLists.Content()->AppendNewToTop<nsDisplaySliderMarks>(aBuilder,
|
||||
this);
|
||||
@@ -404,8 +402,6 @@ void nsSliderFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool UsesCustomScrollbarMediator(nsIFrame* scrollbarBox) {
|
||||
@@ -423,23 +419,16 @@ static bool UsesCustomScrollbarMediator(nsIFrame* scrollbarBox) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void nsSliderFrame::BuildDisplayListForChildren(
|
||||
nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists) {
|
||||
// if we are too small to have a thumb don't paint it.
|
||||
nsIFrame* thumb = nsIFrame::GetChildXULBox(this);
|
||||
|
||||
if (thumb) {
|
||||
nsRect thumbRect(thumb->GetRect());
|
||||
nsMargin m;
|
||||
thumb->GetXULMargin(m);
|
||||
thumbRect.Inflate(m);
|
||||
|
||||
nsRect sliderTrack;
|
||||
GetXULClientRect(sliderTrack);
|
||||
void nsSliderFrame::BuildDisplayListForThumb(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aThumb,
|
||||
const nsDisplayListSet& aLists) {
|
||||
nsRect thumbRect(aThumb->GetRect());
|
||||
|
||||
nsRect sliderTrack = GetRect();
|
||||
if (sliderTrack.width < thumbRect.width ||
|
||||
sliderTrack.height < thumbRect.height)
|
||||
sliderTrack.height < thumbRect.height) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If this scrollbar is the scrollbar of an actively scrolled scroll frame,
|
||||
// layerize the scrollbar thumb, wrap it in its own ContainerLayer and
|
||||
@@ -448,23 +437,22 @@ void nsSliderFrame::BuildDisplayListForChildren(
|
||||
// that the event region that gets created for the thumb is included in
|
||||
// the nsDisplayOwnLayer contents.
|
||||
|
||||
const mozilla::layers::ScrollableLayerGuid::ViewID scrollTargetId =
|
||||
const layers::ScrollableLayerGuid::ViewID scrollTargetId =
|
||||
aBuilder->GetCurrentScrollbarTarget();
|
||||
const bool thumbGetsLayer =
|
||||
(scrollTargetId != layers::ScrollableLayerGuid::NULL_SCROLL_ID);
|
||||
scrollTargetId != layers::ScrollableLayerGuid::NULL_SCROLL_ID;
|
||||
|
||||
if (thumbGetsLayer) {
|
||||
const Maybe<ScrollDirection> scrollDirection =
|
||||
aBuilder->GetCurrentScrollbarDirection();
|
||||
MOZ_ASSERT(scrollDirection.isSome());
|
||||
const bool isHorizontal =
|
||||
*scrollDirection == ScrollDirection::eHorizontal;
|
||||
const bool isHorizontal = *scrollDirection == ScrollDirection::eHorizontal;
|
||||
const OuterCSSCoord thumbLength = OuterCSSPixel::FromAppUnits(
|
||||
isHorizontal ? thumbRect.width : thumbRect.height);
|
||||
const OuterCSSCoord minThumbLength =
|
||||
OuterCSSPixel::FromAppUnits(mThumbMinLength);
|
||||
|
||||
nsIFrame* scrollbarBox = GetScrollbar();
|
||||
nsIFrame* scrollbarBox = Scrollbar();
|
||||
bool isAsyncDraggable = !UsesCustomScrollbarMediator(scrollbarBox);
|
||||
|
||||
nsPoint scrollPortOrigin;
|
||||
@@ -476,8 +464,7 @@ void nsSliderFrame::BuildDisplayListForChildren(
|
||||
}
|
||||
|
||||
// This rect is the range in which the scroll thumb can slide in.
|
||||
sliderTrack = sliderTrack + GetRect().TopLeft() +
|
||||
scrollbarBox->GetPosition() - scrollPortOrigin;
|
||||
sliderTrack = sliderTrack + scrollbarBox->GetPosition() - scrollPortOrigin;
|
||||
const OuterCSSCoord sliderTrackStart = OuterCSSPixel::FromAppUnits(
|
||||
isHorizontal ? sliderTrack.x : sliderTrack.y);
|
||||
const OuterCSSCoord sliderTrackLength = OuterCSSPixel::FromAppUnits(
|
||||
@@ -485,11 +472,11 @@ void nsSliderFrame::BuildDisplayListForChildren(
|
||||
const OuterCSSCoord thumbStart =
|
||||
OuterCSSPixel::FromAppUnits(isHorizontal ? thumbRect.x : thumbRect.y);
|
||||
|
||||
const nsRect overflow = thumb->InkOverflowRectRelativeToParent();
|
||||
const nsRect overflow = aThumb->InkOverflowRectRelativeToParent();
|
||||
nsSize refSize = aBuilder->RootReferenceFrame()->GetSize();
|
||||
nsRect dirty = aBuilder->GetVisibleRect().Intersect(thumbRect);
|
||||
dirty = nsLayoutUtils::ComputePartialPrerenderArea(
|
||||
thumb, aBuilder->GetVisibleRect(), overflow, refSize);
|
||||
aThumb, aBuilder->GetVisibleRect(), overflow, refSize);
|
||||
|
||||
nsDisplayListBuilder::AutoBuildingDisplayList buildingDisplayList(
|
||||
aBuilder, this, dirty, dirty);
|
||||
@@ -511,7 +498,7 @@ void nsSliderFrame::BuildDisplayListForChildren(
|
||||
|
||||
nsDisplayListBuilder::AutoContainerASRTracker contASRTracker(aBuilder);
|
||||
nsDisplayListCollection tempLists(aBuilder);
|
||||
nsBoxFrame::BuildDisplayListForChildren(aBuilder, tempLists);
|
||||
BuildDisplayListForChild(aBuilder, aThumb, tempLists);
|
||||
|
||||
// This is a bit of a hack. Collect up all descendant display items
|
||||
// and merge them into a single Content() list.
|
||||
@@ -540,38 +527,47 @@ void nsSliderFrame::BuildDisplayListForChildren(
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nsBoxFrame::BuildDisplayListForChildren(aBuilder, aLists);
|
||||
BuildDisplayListForChild(aBuilder, aThumb, aLists);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSliderFrame::DoXULLayout(nsBoxLayoutState& aState) {
|
||||
// get the thumb should be our only child
|
||||
nsIFrame* thumbBox = nsIFrame::GetChildXULBox(this);
|
||||
void nsSliderFrame::Reflow(nsPresContext* aPresContext,
|
||||
ReflowOutput& aDesiredSize,
|
||||
const ReflowInput& aReflowInput,
|
||||
nsReflowStatus& aStatus) {
|
||||
MarkInReflow();
|
||||
MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
|
||||
NS_ASSERTION(aReflowInput.AvailableWidth() != NS_UNCONSTRAINEDSIZE,
|
||||
"Bogus avail width");
|
||||
NS_ASSERTION(aReflowInput.AvailableHeight() != NS_UNCONSTRAINEDSIZE,
|
||||
"Bogus avail height");
|
||||
|
||||
if (!thumbBox) {
|
||||
SyncXULLayout(aState);
|
||||
return NS_OK;
|
||||
// We always take all the space we're given.
|
||||
aDesiredSize.Width() = aReflowInput.ComputedWidth();
|
||||
aDesiredSize.Height() = aReflowInput.ComputedHeight();
|
||||
aDesiredSize.SetOverflowAreasToDesiredBounds();
|
||||
|
||||
// Get the thumb, should be our only child.
|
||||
nsIFrame* thumbBox = mFrames.FirstChild();
|
||||
if (NS_WARN_IF(!thumbBox)) {
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureOrient();
|
||||
nsScrollbarFrame* scrollbarBox = Scrollbar();
|
||||
nsIContent* scrollbar = scrollbarBox->GetContent();
|
||||
const bool horizontal = scrollbarBox->IsHorizontal();
|
||||
const auto wm = GetWritingMode();
|
||||
nsSize availSize = aDesiredSize.PhysicalSize();
|
||||
ReflowInput thumbRI(aPresContext, aReflowInput, thumbBox,
|
||||
aReflowInput.AvailableSize(wm));
|
||||
|
||||
// get the content area inside our borders
|
||||
nsRect clientRect;
|
||||
GetXULClientRect(clientRect);
|
||||
|
||||
// get the scrollbar
|
||||
nsIFrame* scrollbarBox = GetScrollbar();
|
||||
nsCOMPtr<nsIContent> scrollbar = GetContentOfBox(scrollbarBox);
|
||||
|
||||
// get the thumb's pref size
|
||||
nsSize thumbSize = thumbBox->GetXULPrefSize(aState);
|
||||
|
||||
if (IsXULHorizontal())
|
||||
thumbSize.height = clientRect.height;
|
||||
else
|
||||
thumbSize.width = clientRect.width;
|
||||
// Get the thumb's pref size.
|
||||
nsSize thumbSize = thumbRI.ComputedMinSize(wm).GetPhysicalSize(wm);
|
||||
if (horizontal) {
|
||||
thumbSize.height = availSize.height;
|
||||
} else {
|
||||
thumbSize.width = availSize.width;
|
||||
}
|
||||
|
||||
int32_t curPos = GetCurrentPosition(scrollbar);
|
||||
int32_t minPos = GetMinPosition(scrollbar);
|
||||
@@ -583,12 +579,11 @@ nsSliderFrame::DoXULLayout(nsBoxLayoutState& aState) {
|
||||
|
||||
// If modifying the logic here, be sure to modify the corresponding
|
||||
// compositor-side calculation in ScrollThumbUtils::ApplyTransformForAxis().
|
||||
nscoord& availableLength =
|
||||
IsXULHorizontal() ? clientRect.width : clientRect.height;
|
||||
nscoord& thumbLength = IsXULHorizontal() ? thumbSize.width : thumbSize.height;
|
||||
nscoord& availableLength = horizontal ? availSize.width : availSize.height;
|
||||
nscoord& thumbLength = horizontal ? thumbSize.width : thumbSize.height;
|
||||
mThumbMinLength = thumbLength;
|
||||
|
||||
if ((pageIncrement + maxPos - minPos) > 0 && thumbBox->GetXULFlex() > 0) {
|
||||
if ((pageIncrement + maxPos - minPos) > 0) {
|
||||
float ratio = float(pageIncrement) / float(maxPos - minPos + pageIncrement);
|
||||
thumbLength =
|
||||
std::max(thumbLength, NSToCoordRound(availableLength * ratio));
|
||||
@@ -612,20 +607,26 @@ nsSliderFrame::DoXULLayout(nsBoxLayoutState& aState) {
|
||||
nscoord pos = reverse ? (maxPos - curPos) : (curPos - minPos);
|
||||
|
||||
// set the thumb's coord to be the current pos * the ratio.
|
||||
nsRect thumbRect(clientRect.x, clientRect.y, thumbSize.width,
|
||||
thumbSize.height);
|
||||
int32_t& thumbPos = (IsXULHorizontal() ? thumbRect.x : thumbRect.y);
|
||||
thumbPos += NSToCoordRound(pos * mRatio);
|
||||
nsPoint thumbPos;
|
||||
if (horizontal) {
|
||||
thumbPos.x = NSToCoordRound(pos * mRatio);
|
||||
} else {
|
||||
thumbPos.y = NSToCoordRound(pos * mRatio);
|
||||
}
|
||||
|
||||
nsRect oldThumbRect(thumbBox->GetRect());
|
||||
LayoutChildAt(aState, thumbBox, thumbRect);
|
||||
|
||||
SyncXULLayout(aState);
|
||||
|
||||
// Redraw only if thumb changed size.
|
||||
if (!oldThumbRect.IsEqualInterior(thumbRect)) XULRedraw(aState);
|
||||
|
||||
return NS_OK;
|
||||
const LogicalPoint logicalPos(wm, thumbPos, availSize);
|
||||
// TODO: It seems like a lot of this stuff should really belong in the thumb's
|
||||
// reflow code rather than here, but since we rely on the frame tree structure
|
||||
// heavily this matches the previous code more closely for now.
|
||||
ReflowOutput thumbDesiredSize(wm);
|
||||
const auto flags = ReflowChildFlags::Default;
|
||||
nsReflowStatus status;
|
||||
thumbRI.SetComputedISize(thumbSize.width);
|
||||
thumbRI.SetComputedBSize(thumbSize.height);
|
||||
ReflowChild(thumbBox, aPresContext, thumbDesiredSize, thumbRI, wm, logicalPos,
|
||||
availSize, flags, status);
|
||||
FinishReflowChild(thumbBox, aPresContext, thumbDesiredSize, &thumbRI, wm,
|
||||
logicalPos, availSize, flags);
|
||||
}
|
||||
|
||||
nsresult nsSliderFrame::HandleEvent(nsPresContext* aPresContext,
|
||||
@@ -661,10 +662,9 @@ nsresult nsSliderFrame::HandleEvent(nsPresContext* aPresContext,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIFrame* scrollbarBox = GetScrollbar();
|
||||
nsCOMPtr<nsIContent> scrollbar;
|
||||
scrollbar = GetContentOfBox(scrollbarBox);
|
||||
bool isHorizontal = IsXULHorizontal();
|
||||
nsScrollbarFrame* scrollbarBox = Scrollbar();
|
||||
nsCOMPtr<nsIContent> scrollbar = scrollbarBox->GetContent();
|
||||
bool isHorizontal = scrollbarBox->IsHorizontal();
|
||||
|
||||
if (isDraggingThumb()) {
|
||||
switch (aEvent->mMessage) {
|
||||
@@ -819,38 +819,14 @@ nsresult nsSliderFrame::HandleEvent(nsPresContext* aPresContext,
|
||||
// caching this, users expect to be able to change the system preference
|
||||
// and see the browser change its behavior immediately.
|
||||
bool nsSliderFrame::GetScrollToClick() {
|
||||
if (GetScrollbar() != this) {
|
||||
return LookAndFeel::GetInt(LookAndFeel::IntID::ScrollToClick, false);
|
||||
}
|
||||
|
||||
if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None,
|
||||
nsGkAtoms::movetoclick,
|
||||
nsGkAtoms::_true, eCaseMatters)) {
|
||||
return true;
|
||||
}
|
||||
if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None,
|
||||
nsGkAtoms::movetoclick,
|
||||
nsGkAtoms::_false, eCaseMatters)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsIFrame* nsSliderFrame::GetScrollbar() {
|
||||
// if we are in a scrollbar then return the scrollbar's content node
|
||||
// if we are not then return ours.
|
||||
nsIFrame* scrollbar;
|
||||
nsScrollbarButtonFrame::GetParentWithTag(nsGkAtoms::scrollbar, this,
|
||||
scrollbar);
|
||||
|
||||
if (scrollbar == nullptr) return this;
|
||||
|
||||
return scrollbar->IsXULBoxFrame() ? scrollbar : this;
|
||||
nsScrollbarFrame* nsSliderFrame::Scrollbar() {
|
||||
MOZ_ASSERT(GetParent());
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
static_cast<nsScrollbarFrame*>(do_QueryFrame(GetParent())));
|
||||
return static_cast<nsScrollbarFrame*>(GetParent());
|
||||
}
|
||||
|
||||
void nsSliderFrame::PageUpDown(nscoord change) {
|
||||
@@ -858,9 +834,8 @@ void nsSliderFrame::PageUpDown(nscoord change) {
|
||||
// scrollbar we are in and asking it for the current position and the page
|
||||
// increment. If we are not in a scrollbar we will get the values from our own
|
||||
// node.
|
||||
nsIFrame* scrollbarBox = GetScrollbar();
|
||||
nsCOMPtr<nsIContent> scrollbar;
|
||||
scrollbar = GetContentOfBox(scrollbarBox);
|
||||
nsIFrame* scrollbarBox = Scrollbar();
|
||||
nsCOMPtr<nsIContent> scrollbar = scrollbarBox->GetContent();
|
||||
|
||||
nscoord pageIncrement = GetPageIncrement(scrollbar);
|
||||
int32_t curpos = GetCurrentPosition(scrollbar);
|
||||
@@ -880,14 +855,16 @@ void nsSliderFrame::PageUpDown(nscoord change) {
|
||||
// called when the current position changed and we need to update the thumb's
|
||||
// location
|
||||
void nsSliderFrame::CurrentPositionChanged() {
|
||||
nsIFrame* scrollbarBox = GetScrollbar();
|
||||
nsCOMPtr<nsIContent> scrollbar = GetContentOfBox(scrollbarBox);
|
||||
nsScrollbarFrame* scrollbarBox = Scrollbar();
|
||||
nsCOMPtr<nsIContent> scrollbar = scrollbarBox->GetContent();
|
||||
|
||||
// get the current position
|
||||
int32_t curPos = GetCurrentPosition(scrollbar);
|
||||
|
||||
// do nothing if the position did not change
|
||||
if (mCurPos == curPos) return;
|
||||
if (mCurPos == curPos) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get our current min and max position from our content node
|
||||
int32_t minPos = GetMinPosition(scrollbar);
|
||||
@@ -898,24 +875,23 @@ void nsSliderFrame::CurrentPositionChanged() {
|
||||
|
||||
// get the thumb's rect
|
||||
nsIFrame* thumbFrame = mFrames.FirstChild();
|
||||
if (!thumbFrame) return; // The thumb may stream in asynchronously via XBL.
|
||||
|
||||
nsRect thumbRect = thumbFrame->GetRect();
|
||||
|
||||
nsRect clientRect;
|
||||
GetXULClientRect(clientRect);
|
||||
|
||||
// figure out the new rect
|
||||
nsRect newThumbRect(thumbRect);
|
||||
if (!thumbFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool reverse = mContent->AsElement()->AttrValueIs(
|
||||
kNameSpaceID_None, nsGkAtoms::dir, nsGkAtoms::reverse, eCaseMatters);
|
||||
nscoord pos = reverse ? (maxPos - curPos) : (curPos - minPos);
|
||||
const bool horizontal = Scrollbar()->IsHorizontal();
|
||||
|
||||
if (IsXULHorizontal())
|
||||
newThumbRect.x = clientRect.x + NSToCoordRound(pos * mRatio);
|
||||
else
|
||||
newThumbRect.y = clientRect.y + NSToCoordRound(pos * mRatio);
|
||||
// figure out the new rect
|
||||
nsRect thumbRect = thumbFrame->GetRect();
|
||||
nsRect newThumbRect(thumbRect);
|
||||
if (horizontal) {
|
||||
newThumbRect.x = NSToCoordRound(pos * mRatio);
|
||||
} else {
|
||||
newThumbRect.y = NSToCoordRound(pos * mRatio);
|
||||
}
|
||||
|
||||
// avoid putting the scroll thumb at subpixel positions which cause needless
|
||||
// invalidations
|
||||
@@ -923,19 +899,18 @@ void nsSliderFrame::CurrentPositionChanged() {
|
||||
nsPoint snappedThumbLocation =
|
||||
ToAppUnits(newThumbRect.TopLeft().ToNearestPixels(appUnitsPerPixel),
|
||||
appUnitsPerPixel);
|
||||
if (IsXULHorizontal()) {
|
||||
if (horizontal) {
|
||||
newThumbRect.x = snappedThumbLocation.x;
|
||||
} else {
|
||||
newThumbRect.y = snappedThumbLocation.y;
|
||||
}
|
||||
|
||||
// set the rect
|
||||
// XXX This out-of-band update of the frame tree is rather fishy!
|
||||
thumbFrame->SetRect(newThumbRect);
|
||||
|
||||
// Request a repaint of the scrollbar
|
||||
nsScrollbarFrame* scrollbarFrame = do_QueryFrame(scrollbarBox);
|
||||
nsIScrollbarMediator* mediator =
|
||||
scrollbarFrame ? scrollbarFrame->GetScrollbarMediator() : nullptr;
|
||||
nsIScrollbarMediator* mediator = scrollbarBox->GetScrollbarMediator();
|
||||
if (!mediator || !mediator->ShouldSuppressScrollbarRepaints()) {
|
||||
SchedulePaint();
|
||||
}
|
||||
@@ -964,11 +939,7 @@ static void UpdateAttribute(dom::Element* aScrollbar, nscoord aNewPos,
|
||||
void nsSliderFrame::SetCurrentThumbPosition(nsIContent* aScrollbar,
|
||||
nscoord aNewThumbPos,
|
||||
bool aIsSmooth, bool aMaySnap) {
|
||||
nsRect crect;
|
||||
GetXULClientRect(crect);
|
||||
nscoord offset = IsXULHorizontal() ? crect.x : crect.y;
|
||||
int32_t newPos = NSToIntRound((aNewThumbPos - offset) / mRatio);
|
||||
|
||||
int32_t newPos = NSToIntRound(aNewThumbPos / mRatio);
|
||||
if (aMaySnap &&
|
||||
mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::snap,
|
||||
nsGkAtoms::_true, eCaseMatters)) {
|
||||
@@ -995,16 +966,18 @@ void nsSliderFrame::SetCurrentPosition(nsIContent* aScrollbar, int32_t aNewPos,
|
||||
// in reverse direction sliders, flip the value so that it goes from
|
||||
// right to left, or bottom to top.
|
||||
if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::dir,
|
||||
nsGkAtoms::reverse, eCaseMatters))
|
||||
nsGkAtoms::reverse, eCaseMatters)) {
|
||||
aNewPos = maxpos - aNewPos;
|
||||
else
|
||||
} else {
|
||||
aNewPos += minpos;
|
||||
}
|
||||
|
||||
// get the new position and make sure it is in bounds
|
||||
if (aNewPos < minpos || maxpos < minpos)
|
||||
if (aNewPos < minpos || maxpos < minpos) {
|
||||
aNewPos = minpos;
|
||||
else if (aNewPos > maxpos)
|
||||
} else if (aNewPos > maxpos) {
|
||||
aNewPos = maxpos;
|
||||
}
|
||||
|
||||
SetCurrentPositionInternal(aScrollbar, aNewPos, aIsSmooth);
|
||||
}
|
||||
@@ -1013,20 +986,17 @@ void nsSliderFrame::SetCurrentPositionInternal(nsIContent* aScrollbar,
|
||||
int32_t aNewPos,
|
||||
bool aIsSmooth) {
|
||||
nsCOMPtr<nsIContent> scrollbar = aScrollbar;
|
||||
nsIFrame* scrollbarBox = GetScrollbar();
|
||||
nsScrollbarFrame* scrollbarBox = Scrollbar();
|
||||
AutoWeakFrame weakFrame(this);
|
||||
|
||||
mUserChanged = true;
|
||||
|
||||
nsScrollbarFrame* scrollbarFrame = do_QueryFrame(scrollbarBox);
|
||||
if (scrollbarFrame) {
|
||||
// See if we have a mediator.
|
||||
nsIScrollbarMediator* mediator = scrollbarFrame->GetScrollbarMediator();
|
||||
if (mediator) {
|
||||
if (nsIScrollbarMediator* mediator = scrollbarBox->GetScrollbarMediator()) {
|
||||
nscoord oldPos =
|
||||
nsPresContext::CSSPixelsToAppUnits(GetCurrentPosition(scrollbar));
|
||||
nscoord newPos = nsPresContext::CSSPixelsToAppUnits(aNewPos);
|
||||
mediator->ThumbMoved(scrollbarFrame, oldPos, newPos);
|
||||
mediator->ThumbMoved(scrollbarBox, oldPos, newPos);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
@@ -1036,7 +1006,6 @@ void nsSliderFrame::SetCurrentPositionInternal(nsIContent* aScrollbar,
|
||||
mUserChanged = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateAttribute(scrollbar->AsElement(), aNewPos, true, aIsSmooth);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
@@ -1051,7 +1020,7 @@ void nsSliderFrame::SetCurrentPositionInternal(nsIContent* aScrollbar,
|
||||
|
||||
void nsSliderFrame::SetInitialChildList(ChildListID aListID,
|
||||
nsFrameList&& aChildList) {
|
||||
nsBoxFrame::SetInitialChildList(aListID, std::move(aChildList));
|
||||
nsContainerFrame::SetInitialChildList(aListID, std::move(aChildList));
|
||||
if (aListID == FrameChildListID::Principal) {
|
||||
AddListener();
|
||||
}
|
||||
@@ -1081,18 +1050,7 @@ static bool ScrollFrameWillBuildScrollInfoLayer(nsIFrame* aScrollFrame) {
|
||||
}
|
||||
|
||||
nsIScrollableFrame* nsSliderFrame::GetScrollFrame() {
|
||||
nsIFrame* scrollbarBox = GetScrollbar();
|
||||
if (!scrollbarBox) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsContainerFrame* scrollFrame = scrollbarBox->GetParent();
|
||||
if (!scrollFrame) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIScrollableFrame* scrollFrameAsScrollable = do_QueryFrame(scrollFrame);
|
||||
return scrollFrameAsScrollable;
|
||||
return do_QueryFrame(Scrollbar()->GetParent());
|
||||
}
|
||||
|
||||
void nsSliderFrame::StartAPZDrag(WidgetGUIEvent* aEvent) {
|
||||
@@ -1104,7 +1062,7 @@ void nsSliderFrame::StartAPZDrag(WidgetGUIEvent* aEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIFrame* scrollbarBox = GetScrollbar();
|
||||
nsIFrame* scrollbarBox = Scrollbar();
|
||||
nsContainerFrame* scrollFrame = scrollbarBox->GetParent();
|
||||
if (!scrollFrame) {
|
||||
return;
|
||||
@@ -1126,12 +1084,12 @@ void nsSliderFrame::StartAPZDrag(WidgetGUIEvent* aEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool isHorizontal = IsXULHorizontal();
|
||||
bool isHorizontal = Scrollbar()->IsHorizontal();
|
||||
|
||||
mozilla::layers::ScrollableLayerGuid::ViewID scrollTargetId;
|
||||
layers::ScrollableLayerGuid::ViewID scrollTargetId;
|
||||
bool hasID = nsLayoutUtils::FindIDFor(scrollableContent, &scrollTargetId);
|
||||
bool hasAPZView =
|
||||
hasID && (scrollTargetId != layers::ScrollableLayerGuid::NULL_SCROLL_ID);
|
||||
hasID && scrollTargetId != layers::ScrollableLayerGuid::NULL_SCROLL_ID;
|
||||
|
||||
if (!hasAPZView) {
|
||||
return;
|
||||
@@ -1141,7 +1099,7 @@ void nsSliderFrame::StartAPZDrag(WidgetGUIEvent* aEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
mozilla::PresShell* presShell = PresShell();
|
||||
auto* presShell = PresShell();
|
||||
uint64_t inputblockId = InputAPZContext::GetInputBlockId();
|
||||
uint32_t presShellId = presShell->GetPresShellId();
|
||||
AsyncDragMetrics dragMetrics(
|
||||
@@ -1197,7 +1155,7 @@ nsresult nsSliderFrame::StartDrag(Event* aEvent) {
|
||||
if (!GetEventPoint(event, pt)) {
|
||||
return NS_OK;
|
||||
}
|
||||
bool isHorizontal = IsXULHorizontal();
|
||||
bool isHorizontal = Scrollbar()->IsHorizontal();
|
||||
nscoord pos = isHorizontal ? pt.x : pt.y;
|
||||
|
||||
// If we should scroll-to-click, first place the middle of the slider thumb
|
||||
@@ -1216,8 +1174,7 @@ nsresult nsSliderFrame::StartDrag(Event* aEvent) {
|
||||
|
||||
newpos -= (thumbLength / 2);
|
||||
|
||||
nsIFrame* scrollbarBox = GetScrollbar();
|
||||
scrollbar = GetContentOfBox(scrollbarBox);
|
||||
scrollbar = Scrollbar()->GetContent();
|
||||
}
|
||||
|
||||
DragThumb(true);
|
||||
@@ -1398,21 +1355,12 @@ bool nsSliderFrame::IsEventOverThumb(WidgetGUIEvent* aEvent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsRect thumbRect = thumbFrame->GetRect();
|
||||
#if defined(MOZ_WIDGET_GTK)
|
||||
/* Scrollbar track can have padding, so it's better to check that eventPoint
|
||||
* is inside of actual thumb, not just its one axis. The part of the scrollbar
|
||||
* track adjacent to thumb can actually receive events in GTK3 */
|
||||
return eventPoint.x >= thumbRect.x && eventPoint.x < thumbRect.XMost() &&
|
||||
eventPoint.y >= thumbRect.y && eventPoint.y < thumbRect.YMost();
|
||||
#else
|
||||
bool isHorizontal = IsXULHorizontal();
|
||||
const nsRect thumbRect = thumbFrame->GetRect();
|
||||
const bool isHorizontal = Scrollbar()->IsHorizontal();
|
||||
nscoord eventPos = isHorizontal ? eventPoint.x : eventPoint.y;
|
||||
nscoord thumbStart = isHorizontal ? thumbRect.x : thumbRect.y;
|
||||
nscoord thumbEnd = isHorizontal ? thumbRect.XMost() : thumbRect.YMost();
|
||||
|
||||
return eventPos >= thumbStart && eventPos < thumbEnd;
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@@ -1442,9 +1390,10 @@ nsSliderFrame::HandlePress(nsPresContext* aPresContext, WidgetGUIEvent* aEvent,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (IsXULHorizontal() ? eventPoint.x < thumbRect.x
|
||||
: eventPoint.y < thumbRect.y)
|
||||
if (Scrollbar()->IsHorizontal() ? eventPoint.x < thumbRect.x
|
||||
: eventPoint.y < thumbRect.y) {
|
||||
change = -1;
|
||||
}
|
||||
|
||||
mChange = change;
|
||||
DragThumb(true);
|
||||
@@ -1453,13 +1402,10 @@ nsSliderFrame::HandlePress(nsPresContext* aPresContext, WidgetGUIEvent* aEvent,
|
||||
// scrolling as soon as the scrollbar thumb has reached the current mouse
|
||||
// position.
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
nsRect clientRect;
|
||||
GetXULClientRect(clientRect);
|
||||
|
||||
// Set the destination point to the very end of the scrollbar so that
|
||||
// scrolling doesn't stop halfway through.
|
||||
if (change > 0) {
|
||||
mDestinationPoint = nsPoint(clientRect.width, clientRect.height);
|
||||
mDestinationPoint = nsPoint(GetRect().width, GetRect().height);
|
||||
} else {
|
||||
mDestinationPoint = nsPoint(0, 0);
|
||||
}
|
||||
@@ -1478,14 +1424,10 @@ nsSliderFrame::HandleRelease(nsPresContext* aPresContext,
|
||||
nsEventStatus* aEventStatus) {
|
||||
StopRepeat();
|
||||
|
||||
nsIFrame* scrollbar = GetScrollbar();
|
||||
nsScrollbarFrame* sb = do_QueryFrame(scrollbar);
|
||||
if (sb) {
|
||||
nsIScrollbarMediator* m = sb->GetScrollbarMediator();
|
||||
if (m) {
|
||||
nsScrollbarFrame* sb = Scrollbar();
|
||||
if (nsIScrollbarMediator* m = sb->GetScrollbarMediator()) {
|
||||
m->ScrollbarReleased(sb);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -1499,37 +1441,10 @@ void nsSliderFrame::DestroyFrom(nsIFrame* aDestructRoot,
|
||||
StopRepeat();
|
||||
|
||||
// call base class Destroy()
|
||||
nsBoxFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
|
||||
nsContainerFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
|
||||
}
|
||||
|
||||
nsSize nsSliderFrame::GetXULPrefSize(nsBoxLayoutState& aState) {
|
||||
EnsureOrient();
|
||||
return nsBoxFrame::GetXULPrefSize(aState);
|
||||
}
|
||||
|
||||
nsSize nsSliderFrame::GetXULMinSize(nsBoxLayoutState& aState) {
|
||||
EnsureOrient();
|
||||
|
||||
// our min size is just our borders and padding
|
||||
return nsIFrame::GetUncachedXULMinSize(aState);
|
||||
}
|
||||
|
||||
nsSize nsSliderFrame::GetXULMaxSize(nsBoxLayoutState& aState) {
|
||||
EnsureOrient();
|
||||
return nsBoxFrame::GetXULMaxSize(aState);
|
||||
}
|
||||
|
||||
void nsSliderFrame::EnsureOrient() {
|
||||
nsIFrame* scrollbarBox = GetScrollbar();
|
||||
|
||||
bool isHorizontal = scrollbarBox->HasAnyStateBits(NS_STATE_IS_HORIZONTAL);
|
||||
if (isHorizontal)
|
||||
AddStateBits(NS_STATE_IS_HORIZONTAL);
|
||||
else
|
||||
RemoveStateBits(NS_STATE_IS_HORIZONTAL);
|
||||
}
|
||||
|
||||
void nsSliderFrame::Notify(void) {
|
||||
void nsSliderFrame::Notify() {
|
||||
bool stop = false;
|
||||
|
||||
nsIFrame* thumbFrame = mFrames.FirstChild();
|
||||
@@ -1539,7 +1454,7 @@ void nsSliderFrame::Notify(void) {
|
||||
}
|
||||
nsRect thumbRect = thumbFrame->GetRect();
|
||||
|
||||
bool isHorizontal = IsXULHorizontal();
|
||||
const bool isHorizontal = Scrollbar()->IsHorizontal();
|
||||
|
||||
// See if the thumb has moved past our destination point.
|
||||
// if it has we want to stop.
|
||||
@@ -1569,18 +1484,14 @@ void nsSliderFrame::PageScroll(nscoord aChange) {
|
||||
nsGkAtoms::reverse, eCaseMatters)) {
|
||||
aChange = -aChange;
|
||||
}
|
||||
nsIFrame* scrollbar = GetScrollbar();
|
||||
nsScrollbarFrame* sb = do_QueryFrame(scrollbar);
|
||||
if (sb) {
|
||||
nsIScrollbarMediator* m = sb->GetScrollbarMediator();
|
||||
nsScrollbarFrame* sb = Scrollbar();
|
||||
sb->SetIncrementToPage(aChange);
|
||||
if (m) {
|
||||
if (nsIScrollbarMediator* m = sb->GetScrollbarMediator()) {
|
||||
m->ScrollByPage(sb, aChange,
|
||||
ScrollSnapFlags::IntendedDirection |
|
||||
ScrollSnapFlags::IntendedEndPosition);
|
||||
return;
|
||||
}
|
||||
}
|
||||
PageUpDown(aChange);
|
||||
}
|
||||
|
||||
@@ -1589,7 +1500,7 @@ float nsSliderFrame::GetThumbRatio() const {
|
||||
// ratio of the thumb's CSS pixels per scrolled CSS pixels. (Note the thumb
|
||||
// is in the scrollframe's parent's space whereas the scrolled CSS pixels
|
||||
// are in the scrollframe's space).
|
||||
return mRatio / mozilla::AppUnitsPerCSSPixel();
|
||||
return mRatio / AppUnitsPerCSSPixel();
|
||||
}
|
||||
|
||||
void nsSliderFrame::AsyncScrollbarDragInitiated(uint64_t aDragBlockId) {
|
||||
@@ -1627,4 +1538,36 @@ bool nsSliderFrame::OnlySystemGroupDispatch(EventMessage aMessage) const {
|
||||
isDraggingThumb() && GetContent()->IsInNativeAnonymousSubtree();
|
||||
}
|
||||
|
||||
bool nsSliderFrame::GetEventPoint(WidgetGUIEvent* aEvent, nsPoint& aPoint) {
|
||||
LayoutDeviceIntPoint refPoint;
|
||||
if (!GetEventPoint(aEvent, refPoint)) {
|
||||
return false;
|
||||
}
|
||||
aPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, refPoint,
|
||||
RelativeTo{this});
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nsSliderFrame::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;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsSliderMediator, nsIDOMEventListener)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define nsSliderFrame_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsRepeatService.h"
|
||||
#include "nsBoxFrame.h"
|
||||
#include "nsAtom.h"
|
||||
@@ -16,6 +17,7 @@
|
||||
#include "nsIDOMEventListener.h"
|
||||
|
||||
class nsITimer;
|
||||
class nsScrollbarFrame;
|
||||
class nsSliderFrame;
|
||||
|
||||
namespace mozilla {
|
||||
@@ -34,7 +36,7 @@ class nsSliderMediator final : public nsIDOMEventListener {
|
||||
|
||||
explicit nsSliderMediator(nsSliderFrame* aSlider) { mSlider = aSlider; }
|
||||
|
||||
virtual void SetSlider(nsSliderFrame* aSlider) { mSlider = aSlider; }
|
||||
void SetSlider(nsSliderFrame* aSlider) { mSlider = aSlider; }
|
||||
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
@@ -42,7 +44,7 @@ class nsSliderMediator final : public nsIDOMEventListener {
|
||||
virtual ~nsSliderMediator() = default;
|
||||
};
|
||||
|
||||
class nsSliderFrame final : public nsBoxFrame {
|
||||
class nsSliderFrame final : public nsContainerFrame {
|
||||
public:
|
||||
NS_DECL_FRAMEARENA_HELPERS(nsSliderFrame)
|
||||
NS_DECL_QUERYFRAME
|
||||
@@ -53,34 +55,42 @@ class nsSliderFrame final : public nsBoxFrame {
|
||||
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
|
||||
virtual nsresult GetFrameName(nsAString& aResult) const override {
|
||||
nsresult GetFrameName(nsAString& aResult) const override {
|
||||
return MakeFrameName(u"SliderFrame"_ns, aResult);
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) override;
|
||||
virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
|
||||
virtual nsSize GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState) override;
|
||||
NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState) override;
|
||||
void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
|
||||
const ReflowInput& aReflowInput,
|
||||
nsReflowStatus& aStatus) override;
|
||||
|
||||
// nsIFrame overrides
|
||||
virtual void DestroyFrom(nsIFrame* aDestructRoot,
|
||||
void DestroyFrom(nsIFrame* aDestructRoot,
|
||||
PostDestroyData& aPostDestroyData) override;
|
||||
|
||||
virtual void BuildDisplayListForChildren(
|
||||
nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists) override;
|
||||
|
||||
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
void BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aLists) override;
|
||||
|
||||
virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
|
||||
void BuildDisplayListForThumb(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aThumb,
|
||||
const nsDisplayListSet& aLists);
|
||||
|
||||
nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
|
||||
int32_t aModType) override;
|
||||
|
||||
virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
|
||||
nsIFrame* asPrevInFlow) override;
|
||||
void Init(nsIContent* aContent, nsContainerFrame* aParent,
|
||||
nsIFrame* aPrevInFlow) override;
|
||||
|
||||
virtual nsresult HandleEvent(nsPresContext* aPresContext,
|
||||
nsresult HandleEvent(nsPresContext* aPresContext,
|
||||
mozilla::WidgetGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus) override;
|
||||
|
||||
@@ -91,7 +101,7 @@ class nsSliderFrame final : public nsBoxFrame {
|
||||
void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
|
||||
const nsLineList::iterator* aPrevFrameLine,
|
||||
nsFrameList&& aFrameList) override;
|
||||
virtual void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override;
|
||||
void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override;
|
||||
|
||||
nsresult StartDrag(mozilla::dom::Event* aEvent);
|
||||
nsresult StopDrag();
|
||||
@@ -105,7 +115,6 @@ class nsSliderFrame final : public nsBoxFrame {
|
||||
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,
|
||||
@@ -150,7 +159,7 @@ class nsSliderFrame final : public nsBoxFrame {
|
||||
|
||||
private:
|
||||
bool GetScrollToClick();
|
||||
nsIFrame* GetScrollbar();
|
||||
nsScrollbarFrame* Scrollbar();
|
||||
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="width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;"/>
|
||||
<resizer dir='bottomright' flex='1' style="min-width: 150px; min-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='width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
|
||||
<resizer dir='bottomright' flex='1' style='min-width: 150px; min-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='width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
|
||||
<resizer dir='bottomright' flex='1' style='min-width: 150px; min-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='width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
|
||||
<resizer dir='bottomright' flex='1' style='min-width: 150px; min-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='width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
|
||||
<resizer dir='bottomright' flex='1' style='min-width: 150px; min-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='width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
|
||||
<resizer dir='bottomright' flex='1' style='min-width: 150px; min-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='width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
|
||||
<resizer dir='bottomright' flex='1' style='min-width: 150px; min-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='width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
|
||||
<resizer dir='bottomright' flex='1' style='min-width: 150px; min-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='width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
|
||||
<resizer dir='bottomright' flex='1' style='min-width: 150px; min-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='width: 150px; height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
|
||||
<resizer dir='bottomright' flex='1' style='min-width: 150px; min-height: 150px; appearance: none; margin: 0; border: 0; padding: 0;'/>
|
||||
</window>
|
||||
|
||||
@@ -644,9 +644,8 @@ static void FindScrollParts(nsIFrame* aCurrFrame,
|
||||
}
|
||||
}
|
||||
|
||||
nsScrollbarFrame* sf = do_QueryFrame(aCurrFrame);
|
||||
if (sf) {
|
||||
if (!aCurrFrame->IsXULHorizontal()) {
|
||||
if (nsScrollbarFrame* sf = do_QueryFrame(aCurrFrame)) {
|
||||
if (!sf->IsHorizontal()) {
|
||||
if (!aResult->mVScrollbar) {
|
||||
aResult->mVScrollbar = sf;
|
||||
}
|
||||
@@ -671,20 +670,17 @@ static void FindScrollParts(nsIFrame* aCurrFrame,
|
||||
nsTreeBodyFrame::ScrollParts nsTreeBodyFrame::GetScrollParts() {
|
||||
ScrollParts result = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
|
||||
XULTreeElement* tree = GetBaseElement();
|
||||
nsIFrame* treeFrame = tree ? tree->GetPrimaryFrame() : nullptr;
|
||||
if (treeFrame) {
|
||||
if (nsIFrame* treeFrame = tree ? tree->GetPrimaryFrame() : nullptr) {
|
||||
// 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());
|
||||
nsIFrame* f = do_QueryFrame(result.mHScrollbar);
|
||||
result.mHScrollbarContent = f->GetContent()->AsElement();
|
||||
result.mHScrollbarContent = result.mHScrollbar->GetContent()->AsElement();
|
||||
}
|
||||
if (result.mVScrollbar) {
|
||||
result.mVScrollbar->SetScrollbarMediatorContent(GetContent());
|
||||
nsIFrame* f = do_QueryFrame(result.mVScrollbar);
|
||||
result.mVScrollbarContent = f->GetContent()->AsElement();
|
||||
result.mVScrollbarContent = result.mVScrollbar->GetContent()->AsElement();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -3820,7 +3816,7 @@ void nsTreeBodyFrame::RepeatButtonScroll(nsScrollbarFrame* aScrollbar) {
|
||||
} else if (increment > 0) {
|
||||
direction = 1;
|
||||
}
|
||||
bool isHorizontal = aScrollbar->IsXULHorizontal();
|
||||
bool isHorizontal = aScrollbar->IsHorizontal();
|
||||
|
||||
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(); }
|
||||
virtual nsIFrame* GetScrollbarBox(bool aVertical) override {
|
||||
nsScrollbarFrame* GetScrollbarBox(bool aVertical) override {
|
||||
ScrollParts parts = GetScrollParts();
|
||||
return aVertical ? parts.mVScrollbar : parts.mHScrollbar;
|
||||
}
|
||||
|
||||
@@ -20,8 +20,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1048178
|
||||
curpos="0"
|
||||
maxpos="500"
|
||||
pageincrement="500"
|
||||
width="500"
|
||||
style="margin:0"/>
|
||||
style="width: 500px; margin:0"/>
|
||||
</hbox>
|
||||
|
||||
<!-- test code goes here -->
|
||||
@@ -45,7 +44,7 @@ var scrollbarTester = {
|
||||
this.mouseup(x, y, 2);
|
||||
this.mouseup(x, y, 0);
|
||||
|
||||
var newPos = this.getPos(); // sould be '500'
|
||||
var newPos = this.getPos(); // should be '500'
|
||||
|
||||
this.mousedown(x, y, 0);
|
||||
this.mousemove(x-1, y, 0);
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
curpos="0"
|
||||
maxpos="600"
|
||||
pageincrement="400"
|
||||
width="500"
|
||||
style="margin:0"/>
|
||||
style="width: 500px; margin: 0"/>
|
||||
</hbox>
|
||||
|
||||
<!-- test code goes here -->
|
||||
|
||||
Reference in New Issue
Block a user