Bug 754480 - Remove PresShell members associated with mContentToScrollTo, put that data in a temporary content property instead. part=3/3 r=bz

This commit is contained in:
Mats Palmgren 2012-05-16 19:32:40 +02:00
parent 7268272a07
commit eef4cdb2e4
2 changed files with 58 additions and 30 deletions

View File

@ -914,7 +914,10 @@ PresShell::Destroy()
NS_RELEASE(gKeyDownTarget);
}
mContentToScrollTo = nsnull;
if (mContentToScrollTo) {
mContentToScrollTo->DeleteProperty(nsGkAtoms::scrolling);
mContentToScrollTo = nsnull;
}
if (mPresContext) {
// We need to notify the destroying the nsPresContext to ESM for
@ -3149,23 +3152,39 @@ static void ScrollToShowRect(nsIScrollableFrame* aScrollFrame,
}
}
static void
DeleteScrollIntoViewData(void* aObject, nsIAtom* aPropertyName,
void* aPropertyValue, void* aData)
{
PresShell::ScrollIntoViewData* data =
static_cast<PresShell::ScrollIntoViewData*>(aPropertyValue);
delete data;
}
nsresult
PresShell::ScrollContentIntoView(nsIContent* aContent,
nsIPresShell::ScrollAxis aVertical,
nsIPresShell::ScrollAxis aHorizontal,
PRUint32 aFlags)
{
nsCOMPtr<nsIContent> content = aContent; // Keep content alive while flushing.
NS_ENSURE_TRUE(content, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIDocument> currentDoc = content->GetCurrentDoc();
NS_ENSURE_TRUE(aContent, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIDocument> currentDoc = aContent->GetCurrentDoc();
NS_ENSURE_STATE(currentDoc);
NS_ASSERTION(mDidInitialReflow, "should have done initial reflow by now");
if (mContentToScrollTo) {
mContentToScrollTo->DeleteProperty(nsGkAtoms::scrolling);
}
mContentToScrollTo = aContent;
mContentScrollVAxis = aVertical;
mContentScrollHAxis = aHorizontal;
mContentToScrollToFlags = aFlags;
ScrollIntoViewData* data = new ScrollIntoViewData();
data->mContentScrollVAxis = aVertical;
data->mContentScrollHAxis = aHorizontal;
data->mContentToScrollToFlags = aFlags;
if (NS_FAILED(mContentToScrollTo->SetProperty(nsGkAtoms::scrolling, data,
::DeleteScrollIntoViewData))) {
mContentToScrollTo = nsnull;
}
// Flush layout and attempt to scroll in the process.
currentDoc->SetNeedLayoutFlush();
@ -3180,21 +3199,19 @@ PresShell::ScrollContentIntoView(nsIContent* aContent,
// than a single best-effort scroll followed by one final scroll on the first
// completed reflow.
if (mContentToScrollTo) {
DoScrollContentIntoView(content, aVertical, aHorizontal, aFlags);
DoScrollContentIntoView();
}
return NS_OK;
}
void
PresShell::DoScrollContentIntoView(nsIContent* aContent,
nsIPresShell::ScrollAxis aVertical,
nsIPresShell::ScrollAxis aHorizontal,
PRUint32 aFlags)
PresShell::DoScrollContentIntoView()
{
NS_ASSERTION(mDidInitialReflow, "should have done initial reflow by now");
nsIFrame* frame = aContent->GetPrimaryFrame();
nsIFrame* frame = mContentToScrollTo->GetPrimaryFrame();
if (!frame) {
mContentToScrollTo->DeleteProperty(nsGkAtoms::scrolling);
mContentToScrollTo = nsnull;
return;
}
@ -3213,6 +3230,13 @@ PresShell::DoScrollContentIntoView(nsIContent* aContent,
return;
}
ScrollIntoViewData* data = static_cast<ScrollIntoViewData*>(
mContentToScrollTo->GetProperty(nsGkAtoms::scrolling));
if (NS_UNLIKELY(!data)) {
mContentToScrollTo = nsnull;
return;
}
// This is a two-step process.
// Step 1: Find the bounds of the rect we want to scroll into view. For
// example, for an inline frame we may want to scroll in the whole
@ -3225,7 +3249,8 @@ PresShell::DoScrollContentIntoView(nsIContent* aContent,
// even if that assumption was false.)
nsRect frameBounds;
bool haveRect = false;
bool useWholeLineHeightForInlines = aVertical.mWhenToScroll != nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
bool useWholeLineHeightForInlines =
data->mContentScrollVAxis.mWhenToScroll != nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
// Reuse the same line iterator across calls to AccumulateFrameBounds. We set
// it every time we detect a new block (stored in prevBlock).
nsIFrame* prevBlock = nsnull;
@ -3238,8 +3263,9 @@ PresShell::DoScrollContentIntoView(nsIContent* aContent,
frameBounds, haveRect, prevBlock, lines, curLine);
} while ((frame = frame->GetNextContinuation()));
ScrollFrameRectIntoView(container, frameBounds, aVertical, aHorizontal,
aFlags);
ScrollFrameRectIntoView(container, frameBounds, data->mContentScrollVAxis,
data->mContentScrollHAxis,
data->mContentToScrollToFlags);
}
bool
@ -3836,11 +3862,11 @@ PresShell::FlushPendingNotifications(mozFlushType aType)
mViewManager->FlushDelayedResize(true);
if (ProcessReflowCommands(aType < Flush_Layout) && mContentToScrollTo) {
// We didn't get interrupted. Go ahead and scroll to our content
DoScrollContentIntoView(mContentToScrollTo,
mContentScrollVAxis,
mContentScrollHAxis,
mContentToScrollToFlags);
mContentToScrollTo = nsnull;
DoScrollContentIntoView();
if (mContentToScrollTo) {
mContentToScrollTo->DeleteProperty(nsGkAtoms::scrolling);
mContentToScrollTo = nsnull;
}
}
} else if (!mIsDestroying && mSuppressInterruptibleReflows &&
aType == Flush_InterruptibleLayout) {

View File

@ -362,6 +362,14 @@ public:
size_t *aPresContextSize) const;
size_t SizeOfTextRuns(nsMallocSizeOfFun aMallocSizeOf) const;
// This data is stored as a content property (nsGkAtoms::scrolling) on
// mContentToScrollTo when we have a pending ScrollIntoView.
struct ScrollIntoViewData {
ScrollAxis mContentScrollVAxis;
ScrollAxis mContentScrollHAxis;
PRUint32 mContentToScrollToFlags;
};
protected:
virtual ~PresShell();
@ -408,10 +416,7 @@ protected:
#endif
// Helper for ScrollContentIntoView
void DoScrollContentIntoView(nsIContent* aContent,
ScrollAxis aVertical,
ScrollAxis aHorizontal,
PRUint32 aFlags);
void DoScrollContentIntoView();
friend struct AutoRenderingStateSaveRestore;
friend struct RenderingState;
@ -774,12 +779,9 @@ protected:
// Information needed to properly handle scrolling content into view if the
// pre-scroll reflow flush can be interrupted. mContentToScrollTo is
// non-null between the initial scroll attempt and the first time we finish
// processing all our dirty roots. mContentScrollVPosition and
// mContentScrollHPosition are only used when it's non-null.
// processing all our dirty roots. mContentToScrollTo has a content property
// storing the details for the scroll operation, see ScrollIntoViewData above.
nsCOMPtr<nsIContent> mContentToScrollTo;
ScrollAxis mContentScrollVAxis;
ScrollAxis mContentScrollHAxis;
PRUint32 mContentToScrollToFlags;
nscoord mLastAnchorScrollPositionY;