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); newBounds.y, newBounds.width, newBounds.height);
#endif #endif
mContentViewer->SetBounds(newBounds); mContentViewer->SetBounds(newBounds);
} else {
nsIScrollableFrame *rootScrollFrame = do_QueryFrame(shell->GetRootScrollFrame());
if (rootScrollFrame) {
rootScrollFrame->PostScrolledAreaEventForCurrentArea();
}
} }
} }

View File

@ -157,7 +157,6 @@ void
nsHTMLScrollFrame::Destroy() nsHTMLScrollFrame::Destroy()
{ {
mInner.Destroy(); mInner.Destroy();
mScrolledAreaEventDispatcher.Revoke();
nsHTMLContainerFrame::Destroy(); nsHTMLContainerFrame::Destroy();
} }
@ -895,7 +894,7 @@ nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext,
} }
if (mInner.mIsRoot && oldScrolledAreaBounds != newScrolledAreaBounds) { if (mInner.mIsRoot && oldScrolledAreaBounds != newScrolledAreaBounds) {
PostScrolledAreaEvent(newScrolledAreaBounds); mInner.PostScrolledAreaEvent(newScrolledAreaBounds);
} }
aStatus = NS_FRAME_COMPLETE; 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 #ifdef NS_DEBUG
@ -991,6 +939,15 @@ nsHTMLScrollFrame::CurPosAttributeChanged(nsIContent* aChild,
mInner.CurPosAttributeChanged(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_HEAD(nsHTMLScrollFrame)
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator) NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_ENTRY(nsIScrollableFrame) NS_QUERYFRAME_ENTRY(nsIScrollableFrame)
@ -1333,6 +1290,15 @@ nsXULScrollFrame::DoLayout(nsBoxLayoutState& aState)
return rv; return rv;
} }
NS_IMETHODIMP
nsXULScrollFrame::PostScrolledAreaEventForCurrentArea()
{
nsRect currentScrolledArea = mInner.mScrolledFrame->GetView()->GetBounds();
mInner.PostScrolledAreaEvent(currentScrolledArea);
return NS_OK;
}
NS_QUERYFRAME_HEAD(nsXULScrollFrame) NS_QUERYFRAME_HEAD(nsXULScrollFrame)
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator) NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_ENTRY(nsIScrollableFrame) NS_QUERYFRAME_ENTRY(nsIScrollableFrame)
@ -1777,6 +1743,7 @@ nsGfxScrollFrameInner::Destroy()
mOuter->PresContext()->PresShell()->CancelReflowCallback(this); mOuter->PresContext()->PresShell()->CancelReflowCallback(this);
mPostedReflowCallback = PR_FALSE; mPostedReflowCallback = PR_FALSE;
} }
mScrolledAreaEventDispatcher.Revoke();
nsIScrollableView *view = GetScrollableView(); nsIScrollableView *view = GetScrollableView();
NS_ASSERTION(view, "unexpected null pointer"); NS_ASSERTION(view, "unexpected null pointer");
if (view) if (view)
@ -2880,3 +2847,56 @@ nsGfxScrollFrameInner::RestoreState(nsPresState* aState)
mLastPos = nsPoint(0, 0); 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 "nsIView.h"
#include "nsIReflowCallback.h" #include "nsIReflowCallback.h"
#include "nsBoxLayoutState.h" #include "nsBoxLayoutState.h"
#include "nsQueryFrame.h"
class nsPresContext; class nsPresContext;
class nsIPresShell; class nsIPresShell;
@ -105,6 +106,9 @@ public:
void CurPosAttributeChanged(nsIContent* aChild); void CurPosAttributeChanged(nsIContent* aChild);
void PostScrollEvent(); void PostScrollEvent();
void FireScrollEvent(); void FireScrollEvent();
void PostScrolledAreaEvent(nsRect &aScrolledArea);
void FireScrolledAreaEvent(nsRect &aScrolledArea);
class ScrollEvent : public nsRunnable { class ScrollEvent : public nsRunnable {
public: public:
@ -232,6 +236,25 @@ public:
// If true, need to actually update our scrollbar attributes in the // If true, need to actually update our scrollbar attributes in the
// reflow callback. // reflow callback.
PRPackedBool mUpdateScrollbarAttributes:1; 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. * scroll frame's scrolled content area.
*/ */
void PostScrolledAreaEvent(nsRect &aScrolledArea); NS_IMETHOD PostScrolledAreaEventForCurrentArea();
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;
};
protected: protected:
nsHTMLScrollFrame(nsIPresShell* aShell, nsStyleContext* aContext, PRBool aIsRoot); nsHTMLScrollFrame(nsIPresShell* aShell, nsStyleContext* aContext, PRBool aIsRoot);
@ -440,8 +446,6 @@ protected:
private: private:
friend class nsGfxScrollFrameInner; friend class nsGfxScrollFrameInner;
nsGfxScrollFrameInner mInner; nsGfxScrollFrameInner mInner;
nsRevocableEventPtr<ScrolledAreaEventDispatcher> mScrolledAreaEventDispatcher;
}; };
/** /**
@ -604,6 +608,10 @@ public:
return nsBoxFrame::IsFrameOfType(aFlags); return nsBoxFrame::IsFrameOfType(aFlags);
} }
void PostScrolledAreaEvent(nsRect &aScrolledArea);
NS_IMETHOD PostScrolledAreaEventForCurrentArea();
#ifdef NS_DEBUG #ifdef NS_DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const; NS_IMETHOD GetFrameName(nsAString& aResult) const;
#endif #endif

View File

@ -119,6 +119,13 @@ public:
* restored after reflows are done... * restored after reflows are done...
*/ */
virtual void ScrollToRestoredPosition() = 0; 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 #endif