зеркало из https://github.com/mozilla/gecko-dev.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:
Родитель
0fa72586e5
Коммит
acc3123915
|
@ -3624,9 +3624,11 @@ nsDocShell::SetPositionAndSize(PRInt32 x, PRInt32 y, PRInt32 cx,
|
||||||
mBounds.width = cx;
|
mBounds.width = cx;
|
||||||
mBounds.height = cy;
|
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?
|
//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;
|
return NS_OK;
|
||||||
|
|
|
@ -2480,8 +2480,15 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
NS_ASSERTION(mViewManager, "Must have view manager");
|
NS_ASSERTION(mViewManager, "Must have view manager");
|
||||||
mViewManager->BeginUpdateViewBatch();
|
nsCOMPtr<nsIViewManager> viewManager = mViewManager;
|
||||||
|
viewManager->BeginUpdateViewBatch();
|
||||||
|
|
||||||
|
// Take this ref after viewManager so it'll make sure to go away first
|
||||||
|
nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
|
||||||
|
|
||||||
|
// Make sure style is up to date
|
||||||
|
mFrameConstructor->ProcessPendingRestyles();
|
||||||
|
if (!mIsDestroying) {
|
||||||
// XXX Do a full invalidate at the beginning so that invalidates along
|
// XXX Do a full invalidate at the beginning so that invalidates along
|
||||||
// the way don't have region accumulation issues?
|
// the way don't have region accumulation issues?
|
||||||
|
|
||||||
|
@ -2500,9 +2507,13 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
|
||||||
|
|
||||||
DidCauseReflow();
|
DidCauseReflow();
|
||||||
DidDoReflow();
|
DidDoReflow();
|
||||||
mViewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
|
}
|
||||||
|
|
||||||
|
viewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
|
||||||
|
|
||||||
|
if (!mIsDestroying) {
|
||||||
CreateResizeEventTimer();
|
CreateResizeEventTimer();
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK; //XXX this needs to be real. MMP
|
return NS_OK; //XXX this needs to be real. MMP
|
||||||
}
|
}
|
||||||
|
@ -6223,9 +6234,12 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible)
|
||||||
|
|
||||||
DidDoReflow();
|
DidDoReflow();
|
||||||
|
|
||||||
|
// DidDoReflow might have killed us
|
||||||
|
if (!mIsDestroying) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (VERIFY_REFLOW_DUMP_COMMANDS & gVerifyReflowFlags) {
|
if (VERIFY_REFLOW_DUMP_COMMANDS & gVerifyReflowFlags) {
|
||||||
printf("\nPresShell::ProcessReflowCommands() finished: this=%p\n", (void*)this);
|
printf("\nPresShell::ProcessReflowCommands() finished: this=%p\n",
|
||||||
|
(void*)this);
|
||||||
}
|
}
|
||||||
DoVerifyReflow();
|
DoVerifyReflow();
|
||||||
#endif
|
#endif
|
||||||
|
@ -6233,16 +6247,18 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible)
|
||||||
// If any new reflow commands were enqueued during the reflow, schedule
|
// If any new reflow commands were enqueued during the reflow, schedule
|
||||||
// another reflow event to process them. Note that we want to do this
|
// another reflow event to process them. Note that we want to do this
|
||||||
// after DidDoReflow(), since that method can change whether there are
|
// after DidDoReflow(), since that method can change whether there are
|
||||||
// dirty roots around by flushing, and there's no point in posting a reflow
|
// dirty roots around by flushing, and there's no point in posting a
|
||||||
// event just to have the flush revoke it.
|
// reflow event just to have the flush revoke it.
|
||||||
if (mDirtyRoots.Count())
|
if (mDirtyRoots.Count())
|
||||||
PostReflowEvent();
|
PostReflowEvent();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MOZ_TIMER_DEBUGLOG(("Stop: Reflow: PresShell::ProcessReflowCommands(), this=%p\n", this));
|
MOZ_TIMER_DEBUGLOG(("Stop: Reflow: PresShell::ProcessReflowCommands(), this=%p\n", this));
|
||||||
MOZ_TIMER_STOP(mReflowWatch);
|
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
|
// We only unlock if we're out of reflows. It's pointless
|
||||||
// to unlock if reflows are still pending, since reflows
|
// to unlock if reflows are still pending, since reflows
|
||||||
// are just going to thrash the frames around some more. By
|
// are just going to thrash the frames around some more. By
|
||||||
|
|
|
@ -89,6 +89,7 @@
|
||||||
#include "nsIDOMNSHTMLDocument.h"
|
#include "nsIDOMNSHTMLDocument.h"
|
||||||
#include "nsDisplayList.h"
|
#include "nsDisplayList.h"
|
||||||
#include "nsUnicharUtils.h"
|
#include "nsUnicharUtils.h"
|
||||||
|
#include "nsIReflowCallback.h"
|
||||||
|
|
||||||
// For Accessibility
|
// For Accessibility
|
||||||
#ifdef ACCESSIBILITY
|
#ifdef ACCESSIBILITY
|
||||||
|
@ -102,7 +103,8 @@ static NS_DEFINE_CID(kCChildCID, NS_CHILD_CID);
|
||||||
* nsSubDocumentFrame
|
* nsSubDocumentFrame
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
class nsSubDocumentFrame : public nsLeafFrame,
|
class nsSubDocumentFrame : public nsLeafFrame,
|
||||||
public nsIFrameFrame
|
public nsIFrameFrame,
|
||||||
|
public nsIReflowCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
nsSubDocumentFrame(nsStyleContext* aContext);
|
nsSubDocumentFrame(nsStyleContext* aContext);
|
||||||
|
@ -159,6 +161,9 @@ public:
|
||||||
|
|
||||||
NS_IMETHOD VerifyTree() const;
|
NS_IMETHOD VerifyTree() const;
|
||||||
|
|
||||||
|
// nsIReflowCallback
|
||||||
|
virtual PRBool ReflowFinished();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nsSize GetMargin();
|
nsSize GetMargin();
|
||||||
PRBool IsInline() { return mIsInline; }
|
PRBool IsInline() { return mIsInline; }
|
||||||
|
@ -175,11 +180,12 @@ protected:
|
||||||
PRPackedBool mDidCreateDoc;
|
PRPackedBool mDidCreateDoc;
|
||||||
PRPackedBool mOwnsFrameLoader;
|
PRPackedBool mOwnsFrameLoader;
|
||||||
PRPackedBool mIsInline;
|
PRPackedBool mIsInline;
|
||||||
|
PRPackedBool mPostedReflowCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
nsSubDocumentFrame::nsSubDocumentFrame(nsStyleContext* aContext)
|
nsSubDocumentFrame::nsSubDocumentFrame(nsStyleContext* aContext)
|
||||||
: nsLeafFrame(aContext), mDidCreateDoc(PR_FALSE), mOwnsFrameLoader(PR_FALSE),
|
: 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;
|
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
|
// "offset" is the offset of our content area from our frame's
|
||||||
// top-left corner.
|
// top-left corner.
|
||||||
nsPoint offset(0, 0);
|
nsPoint offset(0, 0);
|
||||||
|
@ -409,22 +418,9 @@ nsSubDocumentFrame::Reflow(nsPresContext* aPresContext,
|
||||||
nsRect rect(nsPoint(0, 0), GetSize());
|
nsRect rect(nsPoint(0, 0), GetSize());
|
||||||
Invalidate(rect, PR_FALSE);
|
Invalidate(rect, PR_FALSE);
|
||||||
|
|
||||||
if (!aPresContext->IsPaginated()) {
|
if (!aPresContext->IsPaginated() && !mPostedReflowCallback) {
|
||||||
nsCOMPtr<nsIDocShell> docShell;
|
PresContext()->PresShell()->PostReflowCallback(this);
|
||||||
GetDocShell(getter_AddRefs(docShell));
|
mPostedReflowCallback = PR_TRUE;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// printf("OuterFrame::Reflow DONE %X (%d,%d)\n", this,
|
// printf("OuterFrame::Reflow DONE %X (%d,%d)\n", this,
|
||||||
|
@ -438,6 +434,39 @@ nsSubDocumentFrame::Reflow(nsPresContext* aPresContext,
|
||||||
return NS_OK;
|
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
|
NS_IMETHODIMP
|
||||||
nsSubDocumentFrame::VerifyTree() const
|
nsSubDocumentFrame::VerifyTree() const
|
||||||
{
|
{
|
||||||
|
@ -556,6 +585,11 @@ NS_NewSubDocumentFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
||||||
void
|
void
|
||||||
nsSubDocumentFrame::Destroy()
|
nsSubDocumentFrame::Destroy()
|
||||||
{
|
{
|
||||||
|
if (mPostedReflowCallback) {
|
||||||
|
PresContext()->PresShell()->CancelReflowCallback(this);
|
||||||
|
mPostedReflowCallback = PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (mFrameLoader && mDidCreateDoc) {
|
if (mFrameLoader && mDidCreateDoc) {
|
||||||
// Get the content viewer through the docshell, but don't call
|
// Get the content viewer through the docshell, but don't call
|
||||||
// GetDocShell() since we don't want to create one if we don't
|
// GetDocShell() since we don't want to create one if we don't
|
||||||
|
@ -684,7 +718,7 @@ nsSubDocumentFrame::ShowDocShell()
|
||||||
|
|
||||||
if (presShell) {
|
if (presShell) {
|
||||||
// The docshell is already showing, nothing left to do...
|
// The docshell is already showing, nothing left to do...
|
||||||
|
NS_ASSERTION(mInnerView, "What's going on?");
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче