зеркало из https://github.com/mozilla/gecko-dev.git
r=rpotts. Fix for nsbeta3+ bug 39368.
This commit is contained in:
Родитель
a15f6f0ddd
Коммит
1a24a39b49
|
@ -126,9 +126,12 @@
|
||||||
#include "nsIScrollableFrame.h"
|
#include "nsIScrollableFrame.h"
|
||||||
#include "prtime.h"
|
#include "prtime.h"
|
||||||
#include "prlong.h"
|
#include "prlong.h"
|
||||||
|
|
||||||
#include "nsIDragService.h"
|
#include "nsIDragService.h"
|
||||||
|
|
||||||
|
// Dummy layout request
|
||||||
|
#include "nsIChannel.h"
|
||||||
|
#include "nsILoadGroup.h"
|
||||||
|
#include "nsNetUtil.h"
|
||||||
|
|
||||||
// SubShell map
|
// SubShell map
|
||||||
#include "nsDST.h"
|
#include "nsDST.h"
|
||||||
|
@ -159,6 +162,9 @@ static NS_DEFINE_CID(kCXIFConverterCID, NS_XIFFORMATCONVERTER_CID);
|
||||||
|
|
||||||
#undef NOISY
|
#undef NOISY
|
||||||
|
|
||||||
|
// Uncomment the following define if you want asynchronous reflow to be enabled during document load
|
||||||
|
// #define ASYNC_REFLOW_DURING_DOC_LOAD 1
|
||||||
|
|
||||||
//========================================================================
|
//========================================================================
|
||||||
#ifdef MOZ_REFLOW_PERF
|
#ifdef MOZ_REFLOW_PERF
|
||||||
class ReflowCountMgr;
|
class ReflowCountMgr;
|
||||||
|
@ -580,6 +586,127 @@ struct nsCallbackEventRequest
|
||||||
nsCallbackEventRequest* next;
|
nsCallbackEventRequest* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// DummyLayoutRequest
|
||||||
|
//
|
||||||
|
// This is a dummy request implementation that we add to the document's load
|
||||||
|
// group. It ensures that EndDocumentLoad() in the docshell doesn't fire
|
||||||
|
// before we've finished all of layout.
|
||||||
|
//
|
||||||
|
|
||||||
|
class DummyLayoutRequest : public nsIChannel
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
DummyLayoutRequest();
|
||||||
|
virtual ~DummyLayoutRequest();
|
||||||
|
|
||||||
|
static PRInt32 gRefCnt;
|
||||||
|
static nsIURI* gURI;
|
||||||
|
|
||||||
|
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static nsresult
|
||||||
|
Create(nsIChannel** aResult);
|
||||||
|
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
|
// nsIRequest
|
||||||
|
NS_IMETHOD GetName(PRUnichar* *result) {
|
||||||
|
NS_NOTREACHED("DummyLayoutRequest::GetName");
|
||||||
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
NS_IMETHOD IsPending(PRBool *_retval) { *_retval = PR_TRUE; return NS_OK; }
|
||||||
|
NS_IMETHOD GetStatus(nsresult *status) { *status = NS_OK; return NS_OK; }
|
||||||
|
NS_IMETHOD Cancel(nsresult status);
|
||||||
|
NS_IMETHOD Suspend(void) { return NS_OK; }
|
||||||
|
NS_IMETHOD Resume(void) { return NS_OK; }
|
||||||
|
|
||||||
|
// nsIChannel
|
||||||
|
NS_IMETHOD GetOriginalURI(nsIURI* *aOriginalURI) { *aOriginalURI = gURI; NS_ADDREF(*aOriginalURI); return NS_OK; }
|
||||||
|
NS_IMETHOD SetOriginalURI(nsIURI* aOriginalURI) { gURI = aOriginalURI; NS_ADDREF(gURI); return NS_OK; }
|
||||||
|
NS_IMETHOD GetURI(nsIURI* *aURI) { *aURI = gURI; NS_ADDREF(*aURI); return NS_OK; }
|
||||||
|
NS_IMETHOD SetURI(nsIURI* aURI) { gURI = aURI; NS_ADDREF(gURI); return NS_OK; }
|
||||||
|
NS_IMETHOD OpenInputStream(nsIInputStream **_retval) { *_retval = nsnull; return NS_OK; }
|
||||||
|
NS_IMETHOD OpenOutputStream(nsIOutputStream **_retval) { *_retval = nsnull; return NS_OK; }
|
||||||
|
NS_IMETHOD AsyncOpen(nsIStreamObserver *observer, nsISupports *ctxt) { return NS_OK; }
|
||||||
|
NS_IMETHOD AsyncRead(nsIStreamListener *listener, nsISupports *ctxt) { return NS_OK; }
|
||||||
|
NS_IMETHOD AsyncWrite(nsIInputStream *fromStream, nsIStreamObserver *observer, nsISupports *ctxt) { return NS_OK; }
|
||||||
|
NS_IMETHOD GetLoadAttributes(nsLoadFlags *aLoadAttributes) { *aLoadAttributes = nsIChannel::LOAD_NORMAL; return NS_OK; }
|
||||||
|
NS_IMETHOD SetLoadAttributes(nsLoadFlags aLoadAttributes) { return NS_OK; }
|
||||||
|
NS_IMETHOD GetContentType(char * *aContentType) { *aContentType = nsnull; return NS_OK; }
|
||||||
|
NS_IMETHOD SetContentType(const char *aContentType) { return NS_OK; }
|
||||||
|
NS_IMETHOD GetContentLength(PRInt32 *aContentLength) { *aContentLength = 0; return NS_OK; }
|
||||||
|
NS_IMETHOD SetContentLength(PRInt32 aContentLength) { NS_NOTREACHED("SetContentLength"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD GetTransferOffset(PRUint32 *aTransferOffset) { NS_NOTREACHED("GetTransferOffset"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD SetTransferOffset(PRUint32 aTransferOffset) { NS_NOTREACHED("SetTransferOffset"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD GetTransferCount(PRInt32 *aTransferCount) { NS_NOTREACHED("GetTransferCount"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD SetTransferCount(PRInt32 aTransferCount) { NS_NOTREACHED("SetTransferCount"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD GetBufferSegmentSize(PRUint32 *aBufferSegmentSize) { NS_NOTREACHED("GetBufferSegmentSize"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD SetBufferSegmentSize(PRUint32 aBufferSegmentSize) { NS_NOTREACHED("SetBufferSegmentSize"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD GetBufferMaxSize(PRUint32 *aBufferMaxSize) { NS_NOTREACHED("GetBufferMaxSize"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD SetBufferMaxSize(PRUint32 aBufferMaxSize) { NS_NOTREACHED("SetBufferMaxSize"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD GetLocalFile(nsIFile* *result) { NS_NOTREACHED("GetLocalFile"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD GetPipeliningAllowed(PRBool *aPipeliningAllowed) { *aPipeliningAllowed = PR_FALSE; return NS_OK; }
|
||||||
|
NS_IMETHOD SetPipeliningAllowed(PRBool aPipeliningAllowed) { NS_NOTREACHED("SetPipeliningAllowed"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD GetOwner(nsISupports * *aOwner) { *aOwner = nsnull; return NS_OK; }
|
||||||
|
NS_IMETHOD SetOwner(nsISupports * aOwner) { return NS_OK; }
|
||||||
|
NS_IMETHOD GetLoadGroup(nsILoadGroup * *aLoadGroup) { *aLoadGroup = mLoadGroup; NS_IF_ADDREF(*aLoadGroup); return NS_OK; }
|
||||||
|
NS_IMETHOD SetLoadGroup(nsILoadGroup * aLoadGroup) { mLoadGroup = aLoadGroup; return NS_OK; }
|
||||||
|
NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor * *aNotificationCallbacks) { *aNotificationCallbacks = nsnull; return NS_OK; }
|
||||||
|
NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor * aNotificationCallbacks) { return NS_OK; }
|
||||||
|
NS_IMETHOD GetSecurityInfo(nsISupports **info) {*info = nsnull; return NS_OK;}
|
||||||
|
};
|
||||||
|
|
||||||
|
PRInt32 DummyLayoutRequest::gRefCnt;
|
||||||
|
nsIURI* DummyLayoutRequest::gURI;
|
||||||
|
|
||||||
|
NS_IMPL_ADDREF(DummyLayoutRequest);
|
||||||
|
NS_IMPL_RELEASE(DummyLayoutRequest);
|
||||||
|
NS_IMPL_QUERY_INTERFACE2(DummyLayoutRequest, nsIRequest, nsIChannel);
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
DummyLayoutRequest::Create(nsIChannel** aResult)
|
||||||
|
{
|
||||||
|
DummyLayoutRequest* request = new DummyLayoutRequest();
|
||||||
|
if (!request)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
*aResult = request;
|
||||||
|
NS_ADDREF(*aResult);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DummyLayoutRequest::DummyLayoutRequest()
|
||||||
|
{
|
||||||
|
NS_INIT_REFCNT();
|
||||||
|
|
||||||
|
if (gRefCnt++ == 0) {
|
||||||
|
nsresult rv;
|
||||||
|
rv = NS_NewURI(&gURI, "about:layout-dummy-request", nsnull);
|
||||||
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create about:layout-dummy-request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DummyLayoutRequest::~DummyLayoutRequest()
|
||||||
|
{
|
||||||
|
if (--gRefCnt == 0) {
|
||||||
|
NS_IF_RELEASE(gURI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
DummyLayoutRequest::Cancel(nsresult status)
|
||||||
|
{
|
||||||
|
// XXX Cancel layout - Implement this if we decide to enable the ASYNC_REFLOW_DURING_DOC_LOAD compile switch.
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
class PresShell : public nsIPresShell, public nsIViewObserver,
|
class PresShell : public nsIPresShell, public nsIViewObserver,
|
||||||
private nsIDocumentObserver, public nsIFocusTracker,
|
private nsIDocumentObserver, public nsIFocusTracker,
|
||||||
public nsISelectionController,
|
public nsISelectionController,
|
||||||
|
@ -816,6 +943,11 @@ protected:
|
||||||
*/
|
*/
|
||||||
nsresult NotifyReflowObservers(const char *aData);
|
nsresult NotifyReflowObservers(const char *aData);
|
||||||
|
|
||||||
|
nsresult ReflowCommandAdded(nsIReflowCommand* aRC);
|
||||||
|
nsresult ReflowCommandRemoved(nsIReflowCommand* aRC);
|
||||||
|
nsresult AddDummyLayoutRequest(void);
|
||||||
|
nsresult RemoveDummyLayoutRequest(void);
|
||||||
|
|
||||||
nsresult ReconstructFrames(void);
|
nsresult ReconstructFrames(void);
|
||||||
nsresult CloneStyleSet(nsIStyleSet* aSet, nsIStyleSet** aResult);
|
nsresult CloneStyleSet(nsIStyleSet* aSet, nsIStyleSet** aResult);
|
||||||
nsresult WillCauseReflow();
|
nsresult WillCauseReflow();
|
||||||
|
@ -877,6 +1009,8 @@ protected:
|
||||||
PRPackedBool mBatchReflows; // When set to true, the pres shell batches reflow commands.
|
PRPackedBool mBatchReflows; // When set to true, the pres shell batches reflow commands.
|
||||||
nsCOMPtr<nsIObserverService> mObserverService; // Observer service for reflow events
|
nsCOMPtr<nsIObserverService> mObserverService; // Observer service for reflow events
|
||||||
nsCOMPtr<nsIDragService> mDragService;
|
nsCOMPtr<nsIDragService> mDragService;
|
||||||
|
PRInt32 mRCCreatedDuringLoad; // Counter to keep track of reflow commands created during doc
|
||||||
|
nsCOMPtr<nsIChannel> mDummyLayoutRequest;
|
||||||
|
|
||||||
// used for list of posted events and attribute changes. To be done
|
// used for list of posted events and attribute changes. To be done
|
||||||
// after reflow.
|
// after reflow.
|
||||||
|
@ -911,7 +1045,6 @@ private:
|
||||||
void PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent);
|
void PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent);
|
||||||
void PopCurrentEventInfo();
|
void PopCurrentEventInfo();
|
||||||
nsresult HandleEventInternal(nsEvent* aEvent, nsIView* aView, nsEventStatus *aStatus);
|
nsresult HandleEventInternal(nsEvent* aEvent, nsIView* aView, nsEventStatus *aStatus);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
|
@ -1031,6 +1164,8 @@ PresShell::PresShell():mStackArena(nsnull),
|
||||||
mBatchReflows = PR_FALSE;
|
mBatchReflows = PR_FALSE;
|
||||||
mDocumentLoading = PR_FALSE;
|
mDocumentLoading = PR_FALSE;
|
||||||
mSubShellMap = nsnull;
|
mSubShellMap = nsnull;
|
||||||
|
mRCCreatedDuringLoad = 0;
|
||||||
|
mDummyLayoutRequest = nsnull;
|
||||||
|
|
||||||
#ifdef MOZ_REFLOW_PERF
|
#ifdef MOZ_REFLOW_PERF
|
||||||
mReflowCountMgr = new ReflowCountMgr();
|
mReflowCountMgr = new ReflowCountMgr();
|
||||||
|
@ -2491,11 +2626,13 @@ PresShell::AppendReflowCommand(nsIReflowCommand* aReflowCommand)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Add the reflow command to the queue
|
// Add the reflow command to the queue
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
if (!AlreadyInQueue(aReflowCommand)) {
|
if (!AlreadyInQueue(aReflowCommand)) {
|
||||||
NS_ADDREF(aReflowCommand);
|
NS_ADDREF(aReflowCommand);
|
||||||
rv = (mReflowCommands.AppendElement(aReflowCommand) ? NS_OK : NS_ERROR_OUT_OF_MEMORY);
|
rv = (mReflowCommands.AppendElement(aReflowCommand) ? NS_OK : NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
ReflowCommandAdded(aReflowCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kick off a reflow event if we aren't batching reflows
|
// Kick off a reflow event if we aren't batching reflows
|
||||||
|
@ -2503,7 +2640,11 @@ PresShell::AppendReflowCommand(nsIReflowCommand* aReflowCommand)
|
||||||
//
|
//
|
||||||
// If we're in the middle of a drag, process it right away (needed for mac,
|
// If we're in the middle of a drag, process it right away (needed for mac,
|
||||||
// might as well do it on all platforms just to keep the code paths the same).
|
// might as well do it on all platforms just to keep the code paths the same).
|
||||||
if (!mBatchReflows && !mDocumentLoading) {
|
#ifdef ASYNC_REFLOW_DURING_DOC_LOAD
|
||||||
|
if (!mBatchReflows) {
|
||||||
|
#else
|
||||||
|
if (!mBatchReflows && !mDocumentLoading) {
|
||||||
|
#endif
|
||||||
if ( IsDragInProgress() )
|
if ( IsDragInProgress() )
|
||||||
FlushPendingNotifications();
|
FlushPendingNotifications();
|
||||||
else
|
else
|
||||||
|
@ -2561,6 +2702,7 @@ PresShell::CancelReflowCommand(nsIFrame* aTargetFrame, nsIReflowCommand::ReflowT
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
mReflowCommands.RemoveElementAt(i);
|
mReflowCommands.RemoveElementAt(i);
|
||||||
|
ReflowCommandRemoved(rc);
|
||||||
NS_RELEASE(rc);
|
NS_RELEASE(rc);
|
||||||
n--;
|
n--;
|
||||||
i--;
|
i--;
|
||||||
|
@ -2573,8 +2715,6 @@ PresShell::CancelReflowCommand(nsIFrame* aTargetFrame, nsIReflowCommand::ReflowT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
PresShell::ClearFrameRefs(nsIFrame* aFrame)
|
PresShell::ClearFrameRefs(nsIFrame* aFrame)
|
||||||
{
|
{
|
||||||
|
@ -4204,9 +4344,13 @@ nsresult
|
||||||
PresShell::DidCauseReflow()
|
PresShell::DidCauseReflow()
|
||||||
{
|
{
|
||||||
mViewManager->CacheWidgetChanges(PR_FALSE);
|
mViewManager->CacheWidgetChanges(PR_FALSE);
|
||||||
|
|
||||||
|
#ifndef ASYNC_REFLOW_DURING_DOC_LOAD
|
||||||
if (mDocumentLoading) {
|
if (mDocumentLoading) {
|
||||||
FlushPendingNotifications();
|
FlushPendingNotifications();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4251,6 +4395,7 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible)
|
||||||
// new one during its execution.
|
// new one during its execution.
|
||||||
nsIReflowCommand* rc = (nsIReflowCommand*) mReflowCommands.ElementAt(0);
|
nsIReflowCommand* rc = (nsIReflowCommand*) mReflowCommands.ElementAt(0);
|
||||||
mReflowCommands.RemoveElementAt(0);
|
mReflowCommands.RemoveElementAt(0);
|
||||||
|
ReflowCommandRemoved(rc);
|
||||||
|
|
||||||
// Dispatch the reflow command
|
// Dispatch the reflow command
|
||||||
nsSize maxSize;
|
nsSize maxSize;
|
||||||
|
@ -4396,6 +4541,105 @@ PresShell::CloneStyleSet(nsIStyleSet* aSet, nsIStyleSet** aResult)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PresShell::ReflowCommandAdded(nsIReflowCommand* aRC)
|
||||||
|
{
|
||||||
|
#ifdef ASYNC_REFLOW_DURING_DOC_LOAD
|
||||||
|
NS_PRECONDITION(mRCCreatedDuringLoad >= 0, "PresShell's reflow command queue is in a bad state.");
|
||||||
|
if (mDocumentLoading) {
|
||||||
|
PRInt32 flags;
|
||||||
|
aRC->GetFlags(&flags);
|
||||||
|
flags |= NS_RC_CREATED_DURING_DOCUMENT_LOAD;
|
||||||
|
aRC->SetFlags(flags);
|
||||||
|
mRCCreatedDuringLoad++;
|
||||||
|
|
||||||
|
if (!mDummyLayoutRequest) {
|
||||||
|
AddDummyLayoutRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_nisheeth
|
||||||
|
printf("presshell=%p, mRCCreatedDuringLoad=%d\n", this, mRCCreatedDuringLoad);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PresShell::ReflowCommandRemoved(nsIReflowCommand* aRC)
|
||||||
|
{
|
||||||
|
#ifdef ASYNC_REFLOW_DURING_DOC_LOAD
|
||||||
|
NS_PRECONDITION(mRCCreatedDuringLoad >= 0, "PresShell's reflow command queue is in a bad state.");
|
||||||
|
PRInt32 flags;
|
||||||
|
aRC->GetFlags(&flags);
|
||||||
|
if (flags & NS_RC_CREATED_DURING_DOCUMENT_LOAD) {
|
||||||
|
mRCCreatedDuringLoad--;
|
||||||
|
#ifdef DEBUG_nisheeth
|
||||||
|
printf("presshell=%p, mRCCreatedDuringLoad=%d\n", this, mRCCreatedDuringLoad);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mRCCreatedDuringLoad == 0 && !mDocumentLoading && mDummyLayoutRequest)
|
||||||
|
RemoveDummyLayoutRequest();
|
||||||
|
#endif
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PresShell::AddDummyLayoutRequest(void)
|
||||||
|
{
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
#ifdef ASYNC_REFLOW_DURING_DOC_LOAD
|
||||||
|
rv = DummyLayoutRequest::Create(getter_AddRefs(mDummyLayoutRequest));
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||||
|
if (mDocument) {
|
||||||
|
rv = mDocument->GetDocumentLoadGroup(getter_AddRefs(loadGroup));
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loadGroup) {
|
||||||
|
rv = mDummyLayoutRequest->SetLoadGroup(loadGroup);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
rv = loadGroup->AddChannel(mDummyLayoutRequest, nsnull);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_nisheeth
|
||||||
|
printf("presshell=%p, Added dummy layout request.\n", this);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PresShell::RemoveDummyLayoutRequest(void)
|
||||||
|
{
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
#ifdef ASYNC_REFLOW_DURING_DOC_LOAD
|
||||||
|
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||||
|
if (mDocument) {
|
||||||
|
rv = mDocument->GetDocumentLoadGroup(getter_AddRefs(loadGroup));
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loadGroup && mDummyLayoutRequest) {
|
||||||
|
rv = loadGroup->RemoveChannel(mDummyLayoutRequest, nsnull, NS_OK, nsnull);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
mDummyLayoutRequest = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_nisheeth
|
||||||
|
printf("presshell=%p, Removed dummy layout request.\n", this);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
// End of protected and private methods on the PresShell
|
// End of protected and private methods on the PresShell
|
||||||
|
|
|
@ -37,6 +37,9 @@ struct nsSize;
|
||||||
{ 0xc3658e40, 0xff20, 0x11d1, \
|
{ 0xc3658e40, 0xff20, 0x11d1, \
|
||||||
{0x85, 0xbc, 0x0, 0xa0, 0x24, 0x68, 0xfa, 0xb6}}
|
{0x85, 0xbc, 0x0, 0xa0, 0x24, 0x68, 0xfa, 0xb6}}
|
||||||
|
|
||||||
|
// Reflow command flags
|
||||||
|
#define NS_RC_CREATED_DURING_DOCUMENT_LOAD 0x0001
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A reflow command is an object that is generated in response to a content
|
* A reflow command is an object that is generated in response to a content
|
||||||
* model change notification. The reflow command is given to a presentation
|
* model change notification. The reflow command is given to a presentation
|
||||||
|
@ -162,6 +165,12 @@ public:
|
||||||
* Dump out the reflow-command to out
|
* Dump out the reflow-command to out
|
||||||
*/
|
*/
|
||||||
NS_IMETHOD List(FILE* out) const = 0;
|
NS_IMETHOD List(FILE* out) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get/set reflow command flags
|
||||||
|
*/
|
||||||
|
NS_IMETHOD GetFlags(PRInt32* aFlags) = 0;
|
||||||
|
NS_IMETHOD SetFlags(PRInt32 aFlags) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* nsIReflowCommand_h___ */
|
#endif /* nsIReflowCommand_h___ */
|
||||||
|
|
|
@ -62,7 +62,8 @@ nsHTMLReflowCommand::nsHTMLReflowCommand(nsIFrame* aTargetFrame,
|
||||||
: mType(aReflowType), mTargetFrame(aTargetFrame), mChildFrame(aChildFrame),
|
: mType(aReflowType), mTargetFrame(aTargetFrame), mChildFrame(aChildFrame),
|
||||||
mPrevSiblingFrame(nsnull),
|
mPrevSiblingFrame(nsnull),
|
||||||
mAttribute(aAttribute),
|
mAttribute(aAttribute),
|
||||||
mListName(nsnull)
|
mListName(nsnull),
|
||||||
|
mFlags(0)
|
||||||
{
|
{
|
||||||
NS_PRECONDITION(mTargetFrame != nsnull, "null target frame");
|
NS_PRECONDITION(mTargetFrame != nsnull, "null target frame");
|
||||||
if (nsnull!=mAttribute)
|
if (nsnull!=mAttribute)
|
||||||
|
@ -287,3 +288,17 @@ NS_IMETHODIMP nsHTMLReflowCommand::List(FILE* out) const
|
||||||
#endif
|
#endif
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsHTMLReflowCommand::GetFlags(PRInt32* aFlags)
|
||||||
|
{
|
||||||
|
*aFlags = mFlags;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsHTMLReflowCommand::SetFlags(PRInt32 aFlags)
|
||||||
|
{
|
||||||
|
mFlags = aFlags;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -66,6 +66,9 @@ public:
|
||||||
NS_IMETHOD GetPrevSiblingFrame(nsIFrame*& aSiblingFrame) const;
|
NS_IMETHOD GetPrevSiblingFrame(nsIFrame*& aSiblingFrame) const;
|
||||||
NS_IMETHOD List(FILE* out) const;
|
NS_IMETHOD List(FILE* out) const;
|
||||||
|
|
||||||
|
NS_IMETHOD GetFlags(PRInt32* aFlags);
|
||||||
|
NS_IMETHOD SetFlags(PRInt32 aFlags);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void BuildPath();
|
void BuildPath();
|
||||||
nsIFrame* GetContainingBlock(nsIFrame* aFloater) const;
|
nsIFrame* GetContainingBlock(nsIFrame* aFloater) const;
|
||||||
|
@ -78,6 +81,7 @@ private:
|
||||||
nsIAtom* mAttribute;
|
nsIAtom* mAttribute;
|
||||||
nsIAtom* mListName;
|
nsIAtom* mListName;
|
||||||
nsVoidArray mPath;
|
nsVoidArray mPath;
|
||||||
|
PRInt32 mFlags;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* nsHTMLReflowCommand_h___ */
|
#endif /* nsHTMLReflowCommand_h___ */
|
||||||
|
|
|
@ -62,7 +62,8 @@ nsHTMLReflowCommand::nsHTMLReflowCommand(nsIFrame* aTargetFrame,
|
||||||
: mType(aReflowType), mTargetFrame(aTargetFrame), mChildFrame(aChildFrame),
|
: mType(aReflowType), mTargetFrame(aTargetFrame), mChildFrame(aChildFrame),
|
||||||
mPrevSiblingFrame(nsnull),
|
mPrevSiblingFrame(nsnull),
|
||||||
mAttribute(aAttribute),
|
mAttribute(aAttribute),
|
||||||
mListName(nsnull)
|
mListName(nsnull),
|
||||||
|
mFlags(0)
|
||||||
{
|
{
|
||||||
NS_PRECONDITION(mTargetFrame != nsnull, "null target frame");
|
NS_PRECONDITION(mTargetFrame != nsnull, "null target frame");
|
||||||
if (nsnull!=mAttribute)
|
if (nsnull!=mAttribute)
|
||||||
|
@ -287,3 +288,17 @@ NS_IMETHODIMP nsHTMLReflowCommand::List(FILE* out) const
|
||||||
#endif
|
#endif
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsHTMLReflowCommand::GetFlags(PRInt32* aFlags)
|
||||||
|
{
|
||||||
|
*aFlags = mFlags;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsHTMLReflowCommand::SetFlags(PRInt32 aFlags)
|
||||||
|
{
|
||||||
|
mFlags = aFlags;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -66,6 +66,9 @@ public:
|
||||||
NS_IMETHOD GetPrevSiblingFrame(nsIFrame*& aSiblingFrame) const;
|
NS_IMETHOD GetPrevSiblingFrame(nsIFrame*& aSiblingFrame) const;
|
||||||
NS_IMETHOD List(FILE* out) const;
|
NS_IMETHOD List(FILE* out) const;
|
||||||
|
|
||||||
|
NS_IMETHOD GetFlags(PRInt32* aFlags);
|
||||||
|
NS_IMETHOD SetFlags(PRInt32 aFlags);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void BuildPath();
|
void BuildPath();
|
||||||
nsIFrame* GetContainingBlock(nsIFrame* aFloater) const;
|
nsIFrame* GetContainingBlock(nsIFrame* aFloater) const;
|
||||||
|
@ -78,6 +81,7 @@ private:
|
||||||
nsIAtom* mAttribute;
|
nsIAtom* mAttribute;
|
||||||
nsIAtom* mListName;
|
nsIAtom* mListName;
|
||||||
nsVoidArray mPath;
|
nsVoidArray mPath;
|
||||||
|
PRInt32 mFlags;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* nsHTMLReflowCommand_h___ */
|
#endif /* nsHTMLReflowCommand_h___ */
|
||||||
|
|
|
@ -126,9 +126,12 @@
|
||||||
#include "nsIScrollableFrame.h"
|
#include "nsIScrollableFrame.h"
|
||||||
#include "prtime.h"
|
#include "prtime.h"
|
||||||
#include "prlong.h"
|
#include "prlong.h"
|
||||||
|
|
||||||
#include "nsIDragService.h"
|
#include "nsIDragService.h"
|
||||||
|
|
||||||
|
// Dummy layout request
|
||||||
|
#include "nsIChannel.h"
|
||||||
|
#include "nsILoadGroup.h"
|
||||||
|
#include "nsNetUtil.h"
|
||||||
|
|
||||||
// SubShell map
|
// SubShell map
|
||||||
#include "nsDST.h"
|
#include "nsDST.h"
|
||||||
|
@ -159,6 +162,9 @@ static NS_DEFINE_CID(kCXIFConverterCID, NS_XIFFORMATCONVERTER_CID);
|
||||||
|
|
||||||
#undef NOISY
|
#undef NOISY
|
||||||
|
|
||||||
|
// Uncomment the following define if you want asynchronous reflow to be enabled during document load
|
||||||
|
// #define ASYNC_REFLOW_DURING_DOC_LOAD 1
|
||||||
|
|
||||||
//========================================================================
|
//========================================================================
|
||||||
#ifdef MOZ_REFLOW_PERF
|
#ifdef MOZ_REFLOW_PERF
|
||||||
class ReflowCountMgr;
|
class ReflowCountMgr;
|
||||||
|
@ -580,6 +586,127 @@ struct nsCallbackEventRequest
|
||||||
nsCallbackEventRequest* next;
|
nsCallbackEventRequest* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// DummyLayoutRequest
|
||||||
|
//
|
||||||
|
// This is a dummy request implementation that we add to the document's load
|
||||||
|
// group. It ensures that EndDocumentLoad() in the docshell doesn't fire
|
||||||
|
// before we've finished all of layout.
|
||||||
|
//
|
||||||
|
|
||||||
|
class DummyLayoutRequest : public nsIChannel
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
DummyLayoutRequest();
|
||||||
|
virtual ~DummyLayoutRequest();
|
||||||
|
|
||||||
|
static PRInt32 gRefCnt;
|
||||||
|
static nsIURI* gURI;
|
||||||
|
|
||||||
|
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static nsresult
|
||||||
|
Create(nsIChannel** aResult);
|
||||||
|
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
|
// nsIRequest
|
||||||
|
NS_IMETHOD GetName(PRUnichar* *result) {
|
||||||
|
NS_NOTREACHED("DummyLayoutRequest::GetName");
|
||||||
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
NS_IMETHOD IsPending(PRBool *_retval) { *_retval = PR_TRUE; return NS_OK; }
|
||||||
|
NS_IMETHOD GetStatus(nsresult *status) { *status = NS_OK; return NS_OK; }
|
||||||
|
NS_IMETHOD Cancel(nsresult status);
|
||||||
|
NS_IMETHOD Suspend(void) { return NS_OK; }
|
||||||
|
NS_IMETHOD Resume(void) { return NS_OK; }
|
||||||
|
|
||||||
|
// nsIChannel
|
||||||
|
NS_IMETHOD GetOriginalURI(nsIURI* *aOriginalURI) { *aOriginalURI = gURI; NS_ADDREF(*aOriginalURI); return NS_OK; }
|
||||||
|
NS_IMETHOD SetOriginalURI(nsIURI* aOriginalURI) { gURI = aOriginalURI; NS_ADDREF(gURI); return NS_OK; }
|
||||||
|
NS_IMETHOD GetURI(nsIURI* *aURI) { *aURI = gURI; NS_ADDREF(*aURI); return NS_OK; }
|
||||||
|
NS_IMETHOD SetURI(nsIURI* aURI) { gURI = aURI; NS_ADDREF(gURI); return NS_OK; }
|
||||||
|
NS_IMETHOD OpenInputStream(nsIInputStream **_retval) { *_retval = nsnull; return NS_OK; }
|
||||||
|
NS_IMETHOD OpenOutputStream(nsIOutputStream **_retval) { *_retval = nsnull; return NS_OK; }
|
||||||
|
NS_IMETHOD AsyncOpen(nsIStreamObserver *observer, nsISupports *ctxt) { return NS_OK; }
|
||||||
|
NS_IMETHOD AsyncRead(nsIStreamListener *listener, nsISupports *ctxt) { return NS_OK; }
|
||||||
|
NS_IMETHOD AsyncWrite(nsIInputStream *fromStream, nsIStreamObserver *observer, nsISupports *ctxt) { return NS_OK; }
|
||||||
|
NS_IMETHOD GetLoadAttributes(nsLoadFlags *aLoadAttributes) { *aLoadAttributes = nsIChannel::LOAD_NORMAL; return NS_OK; }
|
||||||
|
NS_IMETHOD SetLoadAttributes(nsLoadFlags aLoadAttributes) { return NS_OK; }
|
||||||
|
NS_IMETHOD GetContentType(char * *aContentType) { *aContentType = nsnull; return NS_OK; }
|
||||||
|
NS_IMETHOD SetContentType(const char *aContentType) { return NS_OK; }
|
||||||
|
NS_IMETHOD GetContentLength(PRInt32 *aContentLength) { *aContentLength = 0; return NS_OK; }
|
||||||
|
NS_IMETHOD SetContentLength(PRInt32 aContentLength) { NS_NOTREACHED("SetContentLength"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD GetTransferOffset(PRUint32 *aTransferOffset) { NS_NOTREACHED("GetTransferOffset"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD SetTransferOffset(PRUint32 aTransferOffset) { NS_NOTREACHED("SetTransferOffset"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD GetTransferCount(PRInt32 *aTransferCount) { NS_NOTREACHED("GetTransferCount"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD SetTransferCount(PRInt32 aTransferCount) { NS_NOTREACHED("SetTransferCount"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD GetBufferSegmentSize(PRUint32 *aBufferSegmentSize) { NS_NOTREACHED("GetBufferSegmentSize"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD SetBufferSegmentSize(PRUint32 aBufferSegmentSize) { NS_NOTREACHED("SetBufferSegmentSize"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD GetBufferMaxSize(PRUint32 *aBufferMaxSize) { NS_NOTREACHED("GetBufferMaxSize"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD SetBufferMaxSize(PRUint32 aBufferMaxSize) { NS_NOTREACHED("SetBufferMaxSize"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD GetLocalFile(nsIFile* *result) { NS_NOTREACHED("GetLocalFile"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD GetPipeliningAllowed(PRBool *aPipeliningAllowed) { *aPipeliningAllowed = PR_FALSE; return NS_OK; }
|
||||||
|
NS_IMETHOD SetPipeliningAllowed(PRBool aPipeliningAllowed) { NS_NOTREACHED("SetPipeliningAllowed"); return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
NS_IMETHOD GetOwner(nsISupports * *aOwner) { *aOwner = nsnull; return NS_OK; }
|
||||||
|
NS_IMETHOD SetOwner(nsISupports * aOwner) { return NS_OK; }
|
||||||
|
NS_IMETHOD GetLoadGroup(nsILoadGroup * *aLoadGroup) { *aLoadGroup = mLoadGroup; NS_IF_ADDREF(*aLoadGroup); return NS_OK; }
|
||||||
|
NS_IMETHOD SetLoadGroup(nsILoadGroup * aLoadGroup) { mLoadGroup = aLoadGroup; return NS_OK; }
|
||||||
|
NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor * *aNotificationCallbacks) { *aNotificationCallbacks = nsnull; return NS_OK; }
|
||||||
|
NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor * aNotificationCallbacks) { return NS_OK; }
|
||||||
|
NS_IMETHOD GetSecurityInfo(nsISupports **info) {*info = nsnull; return NS_OK;}
|
||||||
|
};
|
||||||
|
|
||||||
|
PRInt32 DummyLayoutRequest::gRefCnt;
|
||||||
|
nsIURI* DummyLayoutRequest::gURI;
|
||||||
|
|
||||||
|
NS_IMPL_ADDREF(DummyLayoutRequest);
|
||||||
|
NS_IMPL_RELEASE(DummyLayoutRequest);
|
||||||
|
NS_IMPL_QUERY_INTERFACE2(DummyLayoutRequest, nsIRequest, nsIChannel);
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
DummyLayoutRequest::Create(nsIChannel** aResult)
|
||||||
|
{
|
||||||
|
DummyLayoutRequest* request = new DummyLayoutRequest();
|
||||||
|
if (!request)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
*aResult = request;
|
||||||
|
NS_ADDREF(*aResult);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DummyLayoutRequest::DummyLayoutRequest()
|
||||||
|
{
|
||||||
|
NS_INIT_REFCNT();
|
||||||
|
|
||||||
|
if (gRefCnt++ == 0) {
|
||||||
|
nsresult rv;
|
||||||
|
rv = NS_NewURI(&gURI, "about:layout-dummy-request", nsnull);
|
||||||
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create about:layout-dummy-request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DummyLayoutRequest::~DummyLayoutRequest()
|
||||||
|
{
|
||||||
|
if (--gRefCnt == 0) {
|
||||||
|
NS_IF_RELEASE(gURI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
DummyLayoutRequest::Cancel(nsresult status)
|
||||||
|
{
|
||||||
|
// XXX Cancel layout - Implement this if we decide to enable the ASYNC_REFLOW_DURING_DOC_LOAD compile switch.
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
class PresShell : public nsIPresShell, public nsIViewObserver,
|
class PresShell : public nsIPresShell, public nsIViewObserver,
|
||||||
private nsIDocumentObserver, public nsIFocusTracker,
|
private nsIDocumentObserver, public nsIFocusTracker,
|
||||||
public nsISelectionController,
|
public nsISelectionController,
|
||||||
|
@ -816,6 +943,11 @@ protected:
|
||||||
*/
|
*/
|
||||||
nsresult NotifyReflowObservers(const char *aData);
|
nsresult NotifyReflowObservers(const char *aData);
|
||||||
|
|
||||||
|
nsresult ReflowCommandAdded(nsIReflowCommand* aRC);
|
||||||
|
nsresult ReflowCommandRemoved(nsIReflowCommand* aRC);
|
||||||
|
nsresult AddDummyLayoutRequest(void);
|
||||||
|
nsresult RemoveDummyLayoutRequest(void);
|
||||||
|
|
||||||
nsresult ReconstructFrames(void);
|
nsresult ReconstructFrames(void);
|
||||||
nsresult CloneStyleSet(nsIStyleSet* aSet, nsIStyleSet** aResult);
|
nsresult CloneStyleSet(nsIStyleSet* aSet, nsIStyleSet** aResult);
|
||||||
nsresult WillCauseReflow();
|
nsresult WillCauseReflow();
|
||||||
|
@ -877,6 +1009,8 @@ protected:
|
||||||
PRPackedBool mBatchReflows; // When set to true, the pres shell batches reflow commands.
|
PRPackedBool mBatchReflows; // When set to true, the pres shell batches reflow commands.
|
||||||
nsCOMPtr<nsIObserverService> mObserverService; // Observer service for reflow events
|
nsCOMPtr<nsIObserverService> mObserverService; // Observer service for reflow events
|
||||||
nsCOMPtr<nsIDragService> mDragService;
|
nsCOMPtr<nsIDragService> mDragService;
|
||||||
|
PRInt32 mRCCreatedDuringLoad; // Counter to keep track of reflow commands created during doc
|
||||||
|
nsCOMPtr<nsIChannel> mDummyLayoutRequest;
|
||||||
|
|
||||||
// used for list of posted events and attribute changes. To be done
|
// used for list of posted events and attribute changes. To be done
|
||||||
// after reflow.
|
// after reflow.
|
||||||
|
@ -911,7 +1045,6 @@ private:
|
||||||
void PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent);
|
void PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent);
|
||||||
void PopCurrentEventInfo();
|
void PopCurrentEventInfo();
|
||||||
nsresult HandleEventInternal(nsEvent* aEvent, nsIView* aView, nsEventStatus *aStatus);
|
nsresult HandleEventInternal(nsEvent* aEvent, nsIView* aView, nsEventStatus *aStatus);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
|
@ -1031,6 +1164,8 @@ PresShell::PresShell():mStackArena(nsnull),
|
||||||
mBatchReflows = PR_FALSE;
|
mBatchReflows = PR_FALSE;
|
||||||
mDocumentLoading = PR_FALSE;
|
mDocumentLoading = PR_FALSE;
|
||||||
mSubShellMap = nsnull;
|
mSubShellMap = nsnull;
|
||||||
|
mRCCreatedDuringLoad = 0;
|
||||||
|
mDummyLayoutRequest = nsnull;
|
||||||
|
|
||||||
#ifdef MOZ_REFLOW_PERF
|
#ifdef MOZ_REFLOW_PERF
|
||||||
mReflowCountMgr = new ReflowCountMgr();
|
mReflowCountMgr = new ReflowCountMgr();
|
||||||
|
@ -2491,11 +2626,13 @@ PresShell::AppendReflowCommand(nsIReflowCommand* aReflowCommand)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Add the reflow command to the queue
|
// Add the reflow command to the queue
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
if (!AlreadyInQueue(aReflowCommand)) {
|
if (!AlreadyInQueue(aReflowCommand)) {
|
||||||
NS_ADDREF(aReflowCommand);
|
NS_ADDREF(aReflowCommand);
|
||||||
rv = (mReflowCommands.AppendElement(aReflowCommand) ? NS_OK : NS_ERROR_OUT_OF_MEMORY);
|
rv = (mReflowCommands.AppendElement(aReflowCommand) ? NS_OK : NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
ReflowCommandAdded(aReflowCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kick off a reflow event if we aren't batching reflows
|
// Kick off a reflow event if we aren't batching reflows
|
||||||
|
@ -2503,7 +2640,11 @@ PresShell::AppendReflowCommand(nsIReflowCommand* aReflowCommand)
|
||||||
//
|
//
|
||||||
// If we're in the middle of a drag, process it right away (needed for mac,
|
// If we're in the middle of a drag, process it right away (needed for mac,
|
||||||
// might as well do it on all platforms just to keep the code paths the same).
|
// might as well do it on all platforms just to keep the code paths the same).
|
||||||
if (!mBatchReflows && !mDocumentLoading) {
|
#ifdef ASYNC_REFLOW_DURING_DOC_LOAD
|
||||||
|
if (!mBatchReflows) {
|
||||||
|
#else
|
||||||
|
if (!mBatchReflows && !mDocumentLoading) {
|
||||||
|
#endif
|
||||||
if ( IsDragInProgress() )
|
if ( IsDragInProgress() )
|
||||||
FlushPendingNotifications();
|
FlushPendingNotifications();
|
||||||
else
|
else
|
||||||
|
@ -2561,6 +2702,7 @@ PresShell::CancelReflowCommand(nsIFrame* aTargetFrame, nsIReflowCommand::ReflowT
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
mReflowCommands.RemoveElementAt(i);
|
mReflowCommands.RemoveElementAt(i);
|
||||||
|
ReflowCommandRemoved(rc);
|
||||||
NS_RELEASE(rc);
|
NS_RELEASE(rc);
|
||||||
n--;
|
n--;
|
||||||
i--;
|
i--;
|
||||||
|
@ -2573,8 +2715,6 @@ PresShell::CancelReflowCommand(nsIFrame* aTargetFrame, nsIReflowCommand::ReflowT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
PresShell::ClearFrameRefs(nsIFrame* aFrame)
|
PresShell::ClearFrameRefs(nsIFrame* aFrame)
|
||||||
{
|
{
|
||||||
|
@ -4204,9 +4344,13 @@ nsresult
|
||||||
PresShell::DidCauseReflow()
|
PresShell::DidCauseReflow()
|
||||||
{
|
{
|
||||||
mViewManager->CacheWidgetChanges(PR_FALSE);
|
mViewManager->CacheWidgetChanges(PR_FALSE);
|
||||||
|
|
||||||
|
#ifndef ASYNC_REFLOW_DURING_DOC_LOAD
|
||||||
if (mDocumentLoading) {
|
if (mDocumentLoading) {
|
||||||
FlushPendingNotifications();
|
FlushPendingNotifications();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4251,6 +4395,7 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible)
|
||||||
// new one during its execution.
|
// new one during its execution.
|
||||||
nsIReflowCommand* rc = (nsIReflowCommand*) mReflowCommands.ElementAt(0);
|
nsIReflowCommand* rc = (nsIReflowCommand*) mReflowCommands.ElementAt(0);
|
||||||
mReflowCommands.RemoveElementAt(0);
|
mReflowCommands.RemoveElementAt(0);
|
||||||
|
ReflowCommandRemoved(rc);
|
||||||
|
|
||||||
// Dispatch the reflow command
|
// Dispatch the reflow command
|
||||||
nsSize maxSize;
|
nsSize maxSize;
|
||||||
|
@ -4396,6 +4541,105 @@ PresShell::CloneStyleSet(nsIStyleSet* aSet, nsIStyleSet** aResult)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PresShell::ReflowCommandAdded(nsIReflowCommand* aRC)
|
||||||
|
{
|
||||||
|
#ifdef ASYNC_REFLOW_DURING_DOC_LOAD
|
||||||
|
NS_PRECONDITION(mRCCreatedDuringLoad >= 0, "PresShell's reflow command queue is in a bad state.");
|
||||||
|
if (mDocumentLoading) {
|
||||||
|
PRInt32 flags;
|
||||||
|
aRC->GetFlags(&flags);
|
||||||
|
flags |= NS_RC_CREATED_DURING_DOCUMENT_LOAD;
|
||||||
|
aRC->SetFlags(flags);
|
||||||
|
mRCCreatedDuringLoad++;
|
||||||
|
|
||||||
|
if (!mDummyLayoutRequest) {
|
||||||
|
AddDummyLayoutRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_nisheeth
|
||||||
|
printf("presshell=%p, mRCCreatedDuringLoad=%d\n", this, mRCCreatedDuringLoad);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PresShell::ReflowCommandRemoved(nsIReflowCommand* aRC)
|
||||||
|
{
|
||||||
|
#ifdef ASYNC_REFLOW_DURING_DOC_LOAD
|
||||||
|
NS_PRECONDITION(mRCCreatedDuringLoad >= 0, "PresShell's reflow command queue is in a bad state.");
|
||||||
|
PRInt32 flags;
|
||||||
|
aRC->GetFlags(&flags);
|
||||||
|
if (flags & NS_RC_CREATED_DURING_DOCUMENT_LOAD) {
|
||||||
|
mRCCreatedDuringLoad--;
|
||||||
|
#ifdef DEBUG_nisheeth
|
||||||
|
printf("presshell=%p, mRCCreatedDuringLoad=%d\n", this, mRCCreatedDuringLoad);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mRCCreatedDuringLoad == 0 && !mDocumentLoading && mDummyLayoutRequest)
|
||||||
|
RemoveDummyLayoutRequest();
|
||||||
|
#endif
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PresShell::AddDummyLayoutRequest(void)
|
||||||
|
{
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
#ifdef ASYNC_REFLOW_DURING_DOC_LOAD
|
||||||
|
rv = DummyLayoutRequest::Create(getter_AddRefs(mDummyLayoutRequest));
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||||
|
if (mDocument) {
|
||||||
|
rv = mDocument->GetDocumentLoadGroup(getter_AddRefs(loadGroup));
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loadGroup) {
|
||||||
|
rv = mDummyLayoutRequest->SetLoadGroup(loadGroup);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
rv = loadGroup->AddChannel(mDummyLayoutRequest, nsnull);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_nisheeth
|
||||||
|
printf("presshell=%p, Added dummy layout request.\n", this);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PresShell::RemoveDummyLayoutRequest(void)
|
||||||
|
{
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
#ifdef ASYNC_REFLOW_DURING_DOC_LOAD
|
||||||
|
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||||
|
if (mDocument) {
|
||||||
|
rv = mDocument->GetDocumentLoadGroup(getter_AddRefs(loadGroup));
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loadGroup && mDummyLayoutRequest) {
|
||||||
|
rv = loadGroup->RemoveChannel(mDummyLayoutRequest, nsnull, NS_OK, nsnull);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
mDummyLayoutRequest = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_nisheeth
|
||||||
|
printf("presshell=%p, Removed dummy layout request.\n", this);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
// End of protected and private methods on the PresShell
|
// End of protected and private methods on the PresShell
|
||||||
|
|
Загрузка…
Ссылка в новой задаче