Fire MozScrolledAreaChanged from nsDocShell::RestoreFromHistory() in case document root scroll frame isn't reflowed by the restore. r=roc

This commit is contained in:
Roy Frostig 2009-10-25 00:04:18 -07:00
parent 278c4c6e2e
commit fb0534737b
4 changed files with 113 additions and 73 deletions

View File

@ -6956,6 +6956,11 @@ nsDocShell::RestoreFromHistory()
newBounds.y, newBounds.width, newBounds.height);
#endif
mContentViewer->SetBounds(newBounds);
} else {
nsIScrollableFrame *rootScrollFrame = do_QueryFrame(shell->GetRootScrollFrame());
if (rootScrollFrame) {
rootScrollFrame->PostScrolledAreaEventForCurrentArea();
}
}
}

View File

@ -157,7 +157,6 @@ void
nsHTMLScrollFrame::Destroy()
{
mInner.Destroy();
mScrolledAreaEventDispatcher.Revoke();
nsHTMLContainerFrame::Destroy();
}
@ -895,7 +894,7 @@ nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext,
}
if (mInner.mIsRoot && oldScrolledAreaBounds != newScrolledAreaBounds) {
PostScrolledAreaEvent(newScrolledAreaBounds);
mInner.PostScrolledAreaEvent(newScrolledAreaBounds);
}
aStatus = NS_FRAME_COMPLETE;
@ -905,57 +904,6 @@ nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext,
}
////////////////////////////////////////////////////////////////////////////////
// ScrolledArea change event dispatch
NS_IMETHODIMP
nsHTMLScrollFrame::ScrolledAreaEventDispatcher::Run()
{
if (mScrollFrame)
mScrollFrame->FireScrolledAreaEvent(mScrolledArea);
return NS_OK;
}
void
nsHTMLScrollFrame::FireScrolledAreaEvent(nsRect &aScrolledArea)
{
mScrolledAreaEventDispatcher.Forget();
nsScrollAreaEvent event(PR_TRUE, NS_SCROLLEDAREACHANGED, nsnull);
nsPresContext *prescontext = PresContext();
nsIContent* content = GetContent();
event.mArea = aScrolledArea;
nsIDocument *doc = content->GetCurrentDoc();
if (doc) {
nsEventDispatcher::Dispatch(doc, prescontext, &event, nsnull);
}
}
void
nsHTMLScrollFrame::PostScrolledAreaEvent(nsRect &aScrolledArea)
{
if (mScrolledAreaEventDispatcher.IsPending()) {
mScrolledAreaEventDispatcher.get()->mScrolledArea = aScrolledArea;
return;
}
nsRefPtr<ScrolledAreaEventDispatcher> dp = new ScrolledAreaEventDispatcher(this);
if (!dp) {
NS_WARNING("OOM while posting NS_SCROLLEDAREACHANGED");
return;
}
dp->mScrolledArea = aScrolledArea;
if (NS_FAILED(NS_DispatchToCurrentThread(dp))) {
NS_WARNING("Failed to dispatch ScrolledAreaEventDispatcher");
} else {
mScrolledAreaEventDispatcher = dp;
}
}
////////////////////////////////////////////////////////////////////////////////
#ifdef NS_DEBUG
@ -991,6 +939,15 @@ nsHTMLScrollFrame::CurPosAttributeChanged(nsIContent* aChild,
mInner.CurPosAttributeChanged(aChild);
}
NS_IMETHODIMP
nsHTMLScrollFrame::PostScrolledAreaEventForCurrentArea()
{
nsRect currentScrolledArea = mInner.mScrolledFrame->GetView()->GetBounds();
mInner.PostScrolledAreaEvent(currentScrolledArea);
return NS_OK;
}
NS_QUERYFRAME_HEAD(nsHTMLScrollFrame)
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_ENTRY(nsIScrollableFrame)
@ -1333,6 +1290,15 @@ nsXULScrollFrame::DoLayout(nsBoxLayoutState& aState)
return rv;
}
NS_IMETHODIMP
nsXULScrollFrame::PostScrolledAreaEventForCurrentArea()
{
nsRect currentScrolledArea = mInner.mScrolledFrame->GetView()->GetBounds();
mInner.PostScrolledAreaEvent(currentScrolledArea);
return NS_OK;
}
NS_QUERYFRAME_HEAD(nsXULScrollFrame)
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_ENTRY(nsIScrollableFrame)
@ -1777,6 +1743,7 @@ nsGfxScrollFrameInner::Destroy()
mOuter->PresContext()->PresShell()->CancelReflowCallback(this);
mPostedReflowCallback = PR_FALSE;
}
mScrolledAreaEventDispatcher.Revoke();
nsIScrollableView *view = GetScrollableView();
NS_ASSERTION(view, "unexpected null pointer");
if (view)
@ -2880,3 +2847,56 @@ nsGfxScrollFrameInner::RestoreState(nsPresState* aState)
mLastPos = nsPoint(0, 0);
}
}
void
nsGfxScrollFrameInner::PostScrolledAreaEvent(nsRect &aScrolledArea)
{
if (mScrolledAreaEventDispatcher.IsPending()) {
mScrolledAreaEventDispatcher.get()->mScrolledArea = aScrolledArea;
return;
}
nsRefPtr<ScrolledAreaEventDispatcher> dp = new ScrolledAreaEventDispatcher(this);
if (!dp) {
NS_WARNING("OOM while posting NS_SCROLLEDAREACHANGED");
return;
}
dp->mScrolledArea = aScrolledArea;
if (NS_FAILED(NS_DispatchToCurrentThread(dp))) {
NS_WARNING("Failed to dispatch ScrolledAreaEventDispatcher");
} else {
mScrolledAreaEventDispatcher = dp;
}
}
////////////////////////////////////////////////////////////////////////////////
// ScrolledArea change event dispatch
NS_IMETHODIMP
nsGfxScrollFrameInner::ScrolledAreaEventDispatcher::Run()
{
if (mScrollFrameInner)
mScrollFrameInner->FireScrolledAreaEvent(mScrolledArea);
return NS_OK;
}
void
nsGfxScrollFrameInner::FireScrolledAreaEvent(nsRect &aScrolledArea)
{
mScrolledAreaEventDispatcher.Forget();
nsScrollAreaEvent event(PR_TRUE, NS_SCROLLEDAREACHANGED, nsnull);
nsPresContext *prescontext = mOuter->PresContext();
nsIContent* content = mOuter->GetContent();
event.mArea = aScrolledArea;
nsIDocument *doc = content->GetCurrentDoc();
if (doc) {
nsEventDispatcher::Dispatch(doc, prescontext, &event, nsnull);
}
}

View File

@ -51,6 +51,7 @@
#include "nsIView.h"
#include "nsIReflowCallback.h"
#include "nsBoxLayoutState.h"
#include "nsQueryFrame.h"
class nsPresContext;
class nsIPresShell;
@ -105,6 +106,9 @@ public:
void CurPosAttributeChanged(nsIContent* aChild);
void PostScrollEvent();
void FireScrollEvent();
void PostScrolledAreaEvent(nsRect &aScrolledArea);
void FireScrolledAreaEvent(nsRect &aScrolledArea);
class ScrollEvent : public nsRunnable {
public:
@ -232,6 +236,25 @@ public:
// If true, need to actually update our scrollbar attributes in the
// reflow callback.
PRPackedBool mUpdateScrollbarAttributes:1;
private:
class ScrolledAreaEventDispatcher : public nsRunnable {
public:
NS_DECL_NSIRUNNABLE
ScrolledAreaEventDispatcher(nsGfxScrollFrameInner *aScrollFrameInner)
: mScrollFrameInner(aScrollFrameInner),
mScrolledArea(0, 0, 0, 0)
{
}
void Revoke() { mScrollFrameInner = nsnull; }
nsGfxScrollFrameInner *mScrollFrameInner;
nsRect mScrolledArea;
};
nsRevocableEventPtr<ScrolledAreaEventDispatcher> mScrolledAreaEventDispatcher;
};
/**
@ -389,24 +412,7 @@ public:
* scroll frame's scrolled content area.
*/
void PostScrolledAreaEvent(nsRect &aScrolledArea);
void FireScrolledAreaEvent(nsRect &aScrolledArea);
class ScrolledAreaEventDispatcher : public nsRunnable {
public:
NS_DECL_NSIRUNNABLE
ScrolledAreaEventDispatcher(nsHTMLScrollFrame *aScrollFrame)
: mScrollFrame(aScrollFrame),
mScrolledArea(0, 0, 0, 0)
{
}
void Revoke() { mScrollFrame = nsnull; }
nsHTMLScrollFrame *mScrollFrame;
nsRect mScrolledArea;
};
NS_IMETHOD PostScrolledAreaEventForCurrentArea();
protected:
nsHTMLScrollFrame(nsIPresShell* aShell, nsStyleContext* aContext, PRBool aIsRoot);
@ -440,8 +446,6 @@ protected:
private:
friend class nsGfxScrollFrameInner;
nsGfxScrollFrameInner mInner;
nsRevocableEventPtr<ScrolledAreaEventDispatcher> mScrolledAreaEventDispatcher;
};
/**
@ -604,6 +608,10 @@ public:
return nsBoxFrame::IsFrameOfType(aFlags);
}
void PostScrolledAreaEvent(nsRect &aScrolledArea);
NS_IMETHOD PostScrolledAreaEventForCurrentArea();
#ifdef NS_DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const;
#endif

View File

@ -119,6 +119,13 @@ public:
* restored after reflows are done...
*/
virtual void ScrollToRestoredPosition() = 0;
/**
* Allows the docshell to request that the scroll frame post an event
* after being restored from history.
*/
NS_IMETHOD PostScrolledAreaEventForCurrentArea() = 0;
};
#endif