зеркало из https://github.com/mozilla/pjs.git
Resize the subdocument off a post-reflow callback so that we don't run script
during reflow, and a few related checks to make sure we can deal with script in reflow callbacks better. Bug 396587, r+sr+a=roc.
This commit is contained in:
Родитель
95a79b473c
Коммит
3a1ec82b89
|
@ -3624,9 +3624,11 @@ nsDocShell::SetPositionAndSize(PRInt32 x, PRInt32 y, PRInt32 cx,
|
|||
mBounds.width = cx;
|
||||
mBounds.height = cy;
|
||||
|
||||
if (mContentViewer) {
|
||||
// Hold strong ref, since SetBounds can make us null out mContentViewer
|
||||
nsCOMPtr<nsIContentViewer> viewer = mContentViewer;
|
||||
if (viewer) {
|
||||
//XXX Border figured in here or is that handled elsewhere?
|
||||
NS_ENSURE_SUCCESS(mContentViewer->SetBounds(mBounds), NS_ERROR_FAILURE);
|
||||
NS_ENSURE_SUCCESS(viewer->SetBounds(mBounds), NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -2480,29 +2480,40 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
|
|||
return NS_OK;
|
||||
|
||||
NS_ASSERTION(mViewManager, "Must have view manager");
|
||||
mViewManager->BeginUpdateViewBatch();
|
||||
nsCOMPtr<nsIViewManager> viewManager = mViewManager;
|
||||
viewManager->BeginUpdateViewBatch();
|
||||
|
||||
// XXX Do a full invalidate at the beginning so that invalidates along
|
||||
// the way don't have region accumulation issues?
|
||||
// Take this ref after viewManager so it'll make sure to go away first
|
||||
nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
|
||||
|
||||
WillCauseReflow();
|
||||
WillDoReflow();
|
||||
// Make sure style is up to date
|
||||
mFrameConstructor->ProcessPendingRestyles();
|
||||
if (!mIsDestroying) {
|
||||
// XXX Do a full invalidate at the beginning so that invalidates along
|
||||
// the way don't have region accumulation issues?
|
||||
|
||||
{
|
||||
// Kick off a top-down reflow
|
||||
AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow);
|
||||
mIsReflowing = PR_TRUE;
|
||||
WillCauseReflow();
|
||||
WillDoReflow();
|
||||
|
||||
mDirtyRoots.RemoveElement(rootFrame);
|
||||
DoReflow(rootFrame);
|
||||
mIsReflowing = PR_FALSE;
|
||||
{
|
||||
// Kick off a top-down reflow
|
||||
AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow);
|
||||
mIsReflowing = PR_TRUE;
|
||||
|
||||
mDirtyRoots.RemoveElement(rootFrame);
|
||||
DoReflow(rootFrame);
|
||||
mIsReflowing = PR_FALSE;
|
||||
}
|
||||
|
||||
DidCauseReflow();
|
||||
DidDoReflow();
|
||||
}
|
||||
|
||||
DidCauseReflow();
|
||||
DidDoReflow();
|
||||
mViewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
|
||||
viewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
|
||||
|
||||
CreateResizeEventTimer();
|
||||
if (!mIsDestroying) {
|
||||
CreateResizeEventTimer();
|
||||
}
|
||||
|
||||
return NS_OK; //XXX this needs to be real. MMP
|
||||
}
|
||||
|
@ -6223,26 +6234,31 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible)
|
|||
|
||||
DidDoReflow();
|
||||
|
||||
// DidDoReflow might have killed us
|
||||
if (!mIsDestroying) {
|
||||
#ifdef DEBUG
|
||||
if (VERIFY_REFLOW_DUMP_COMMANDS & gVerifyReflowFlags) {
|
||||
printf("\nPresShell::ProcessReflowCommands() finished: this=%p\n", (void*)this);
|
||||
}
|
||||
DoVerifyReflow();
|
||||
if (VERIFY_REFLOW_DUMP_COMMANDS & gVerifyReflowFlags) {
|
||||
printf("\nPresShell::ProcessReflowCommands() finished: this=%p\n",
|
||||
(void*)this);
|
||||
}
|
||||
DoVerifyReflow();
|
||||
#endif
|
||||
|
||||
// If any new reflow commands were enqueued during the reflow, schedule
|
||||
// another reflow event to process them. Note that we want to do this
|
||||
// after DidDoReflow(), since that method can change whether there are
|
||||
// dirty roots around by flushing, and there's no point in posting a reflow
|
||||
// event just to have the flush revoke it.
|
||||
if (mDirtyRoots.Count())
|
||||
PostReflowEvent();
|
||||
// If any new reflow commands were enqueued during the reflow, schedule
|
||||
// another reflow event to process them. Note that we want to do this
|
||||
// after DidDoReflow(), since that method can change whether there are
|
||||
// dirty roots around by flushing, and there's no point in posting a
|
||||
// reflow event just to have the flush revoke it.
|
||||
if (mDirtyRoots.Count())
|
||||
PostReflowEvent();
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_TIMER_DEBUGLOG(("Stop: Reflow: PresShell::ProcessReflowCommands(), this=%p\n", this));
|
||||
MOZ_TIMER_STOP(mReflowWatch);
|
||||
|
||||
if (mShouldUnsuppressPainting && mDirtyRoots.Count() == 0) {
|
||||
if (!mIsDestroying && mShouldUnsuppressPainting &&
|
||||
mDirtyRoots.Count() == 0) {
|
||||
// We only unlock if we're out of reflows. It's pointless
|
||||
// to unlock if reflows are still pending, since reflows
|
||||
// are just going to thrash the frames around some more. By
|
||||
|
|
|
@ -89,6 +89,7 @@
|
|||
#include "nsIDOMNSHTMLDocument.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsIReflowCallback.h"
|
||||
|
||||
// For Accessibility
|
||||
#ifdef ACCESSIBILITY
|
||||
|
@ -102,7 +103,8 @@ static NS_DEFINE_CID(kCChildCID, NS_CHILD_CID);
|
|||
* nsSubDocumentFrame
|
||||
*****************************************************************************/
|
||||
class nsSubDocumentFrame : public nsLeafFrame,
|
||||
public nsIFrameFrame
|
||||
public nsIFrameFrame,
|
||||
public nsIReflowCallback
|
||||
{
|
||||
public:
|
||||
nsSubDocumentFrame(nsStyleContext* aContext);
|
||||
|
@ -159,6 +161,9 @@ public:
|
|||
|
||||
NS_IMETHOD VerifyTree() const;
|
||||
|
||||
// nsIReflowCallback
|
||||
virtual PRBool ReflowFinished();
|
||||
|
||||
protected:
|
||||
nsSize GetMargin();
|
||||
PRBool IsInline() { return mIsInline; }
|
||||
|
@ -175,11 +180,12 @@ protected:
|
|||
PRPackedBool mDidCreateDoc;
|
||||
PRPackedBool mOwnsFrameLoader;
|
||||
PRPackedBool mIsInline;
|
||||
PRPackedBool mPostedReflowCallback;
|
||||
};
|
||||
|
||||
nsSubDocumentFrame::nsSubDocumentFrame(nsStyleContext* aContext)
|
||||
: nsLeafFrame(aContext), mDidCreateDoc(PR_FALSE), mOwnsFrameLoader(PR_FALSE),
|
||||
mIsInline(PR_FALSE)
|
||||
mIsInline(PR_FALSE), mPostedReflowCallback(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -372,6 +378,9 @@ nsSubDocumentFrame::Reflow(nsPresContext* aPresContext,
|
|||
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
|
||||
NS_ASSERTION(aPresContext->GetPresShell()->GetPrimaryFrameFor(mContent) == this,
|
||||
"Shouldn't happen");
|
||||
|
||||
// "offset" is the offset of our content area from our frame's
|
||||
// top-left corner.
|
||||
nsPoint offset(0, 0);
|
||||
|
@ -409,22 +418,9 @@ nsSubDocumentFrame::Reflow(nsPresContext* aPresContext,
|
|||
nsRect rect(nsPoint(0, 0), GetSize());
|
||||
Invalidate(rect, PR_FALSE);
|
||||
|
||||
if (!aPresContext->IsPaginated()) {
|
||||
nsCOMPtr<nsIDocShell> docShell;
|
||||
GetDocShell(getter_AddRefs(docShell));
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(docShell));
|
||||
|
||||
// resize the sub document
|
||||
if (baseWindow) {
|
||||
PRInt32 x = 0;
|
||||
PRInt32 y = 0;
|
||||
|
||||
baseWindow->GetPositionAndSize(&x, &y, nsnull, nsnull);
|
||||
PRInt32 cx = aPresContext->AppUnitsToDevPixels(innerSize.width);
|
||||
PRInt32 cy = aPresContext->AppUnitsToDevPixels(innerSize.height);
|
||||
baseWindow->SetPositionAndSize(x, y, cx, cy, PR_FALSE);
|
||||
}
|
||||
if (!aPresContext->IsPaginated() && !mPostedReflowCallback) {
|
||||
PresContext()->PresShell()->PostReflowCallback(this);
|
||||
mPostedReflowCallback = PR_TRUE;
|
||||
}
|
||||
|
||||
// printf("OuterFrame::Reflow DONE %X (%d,%d)\n", this,
|
||||
|
@ -438,6 +434,39 @@ nsSubDocumentFrame::Reflow(nsPresContext* aPresContext,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSubDocumentFrame::ReflowFinished()
|
||||
{
|
||||
mPostedReflowCallback = PR_FALSE;
|
||||
|
||||
nsSize innerSize(GetSize());
|
||||
if (IsInline()) {
|
||||
nsMargin usedBorderPadding = GetUsedBorderAndPadding();
|
||||
innerSize.width -= usedBorderPadding.LeftRight();
|
||||
innerSize.height -= usedBorderPadding.TopBottom();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell;
|
||||
GetDocShell(getter_AddRefs(docShell));
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(docShell));
|
||||
|
||||
// resize the sub document
|
||||
if (baseWindow) {
|
||||
PRInt32 x = 0;
|
||||
PRInt32 y = 0;
|
||||
|
||||
nsPresContext* presContext = PresContext();
|
||||
baseWindow->GetPositionAndSize(&x, &y, nsnull, nsnull);
|
||||
PRInt32 cx = presContext->AppUnitsToDevPixels(innerSize.width);
|
||||
PRInt32 cy = presContext->AppUnitsToDevPixels(innerSize.height);
|
||||
baseWindow->SetPositionAndSize(x, y, cx, cy, PR_FALSE);
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSubDocumentFrame::VerifyTree() const
|
||||
{
|
||||
|
@ -556,6 +585,11 @@ NS_NewSubDocumentFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
|||
void
|
||||
nsSubDocumentFrame::Destroy()
|
||||
{
|
||||
if (mPostedReflowCallback) {
|
||||
PresContext()->PresShell()->CancelReflowCallback(this);
|
||||
mPostedReflowCallback = PR_FALSE;
|
||||
}
|
||||
|
||||
if (mFrameLoader && mDidCreateDoc) {
|
||||
// Get the content viewer through the docshell, but don't call
|
||||
// GetDocShell() since we don't want to create one if we don't
|
||||
|
@ -684,7 +718,7 @@ nsSubDocumentFrame::ShowDocShell()
|
|||
|
||||
if (presShell) {
|
||||
// The docshell is already showing, nothing left to do...
|
||||
|
||||
NS_ASSERTION(mInnerView, "What's going on?");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче