Merge back out of changeset 93c7b23284b8 (Bug 545593) for causing Md oth failures on linux.

This commit is contained in:
Timothy Nikkel 2010-02-12 16:46:46 -06:00
commit cefd1df784
14 changed files with 226 additions and 33 deletions

View File

@ -1266,6 +1266,29 @@ nsContentSink::ScrollToRef()
}
}
nsresult
nsContentSink::RefreshIfEnabled(nsIViewManager* vm)
{
if (!vm) {
// vm might be null if the shell got Destroy() called already
return NS_OK;
}
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
nsCOMPtr<nsIContentViewer> contentViewer;
mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
if (contentViewer) {
PRBool enabled;
contentViewer->GetEnableRendering(&enabled);
if (enabled) {
vm->EnableRefresh(NS_VMREFRESH_IMMEDIATE);
}
}
return NS_OK;
}
void
nsContentSink::StartLayout(PRBool aIgnorePendingSheets)
{
@ -1308,6 +1331,9 @@ nsContentSink::StartLayout(PRBool aIgnorePendingSheets)
if (NS_FAILED(rv)) {
return;
}
// Now trigger a refresh
RefreshIfEnabled(shell->GetViewManager());
}
// If the document we are loading has a reference or it is a

View File

@ -257,6 +257,7 @@ protected:
// Tries to scroll to the URI's named anchor. Once we've successfully
// done that, further calls to this method will be ignored.
void ScrollToRef();
nsresult RefreshIfEnabled(nsIViewManager* vm);
// Start layout. If aIgnorePendingSheets is true, this will happen even if
// we still have stylesheet loads pending. Otherwise, we'll wait until the

View File

@ -283,6 +283,13 @@ nsMediaDocument::StartLayout()
nsRect visibleArea = shell->GetPresContext()->GetVisibleArea();
nsresult rv = shell->InitialReflow(visibleArea.width, visibleArea.height);
NS_ENSURE_SUCCESS(rv, rv);
// Now trigger a refresh. vm might be null if the presshell got
// Destroy() called already.
nsIViewManager* vm = shell->GetViewManager();
if (vm) {
vm->EnableRefresh(NS_VMREFRESH_IMMEDIATE);
}
}
return NS_OK;

View File

@ -2034,7 +2034,29 @@ nsXULDocument::StartLayout(void)
if (! docShell)
return NS_ERROR_UNEXPECTED;
// Trigger a refresh before the call to InitialReflow(),
// because the view manager's UpdateView() function is
// dropping dirty rects if refresh is disabled rather than
// accumulating them until refresh is enabled and then
// triggering a repaint...
// XXXbz Is that still the case?
nsresult rv = NS_OK;
nsIViewManager* vm = shell->GetViewManager();
if (vm) {
nsCOMPtr<nsIContentViewer> contentViewer;
rv = docShell->GetContentViewer(getter_AddRefs(contentViewer));
if (NS_SUCCEEDED(rv) && (contentViewer != nsnull)) {
PRBool enabled;
contentViewer->GetEnableRendering(&enabled);
if (enabled) {
vm->EnableRefresh(NS_VMREFRESH_IMMEDIATE);
}
}
}
// Don't try to call GetVisibleArea earlier than this --- the EnableRefresh call
// above can flush reflows, which can cause a parent document to be flushed,
// calling ResizeReflow on our document which does SetVisibleArea.
nsRect r = cx->GetVisibleArea();
rv = shell->InitialReflow(r.width, r.height);
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -11420,6 +11420,20 @@ nsDocShell::StopDocumentLoad(void)
return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
}
NS_IMETHODIMP
nsDocShell::SetRendering(PRBool aRender)
{
if(eCharsetReloadRequested != mCharsetReloadState)
{
if (mContentViewer) {
mContentViewer->SetEnableRendering(aRender);
return NS_OK;
}
}
//return failer if this request is not accepted due to mCharsetReloadState
return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
}
NS_IMETHODIMP
nsDocShell::GetPrintPreview(nsIWebBrowserPrint** aPrintPreview)
{

View File

@ -15,7 +15,7 @@ struct nsIntRect;
[ptr] native nsIDocumentPtr(nsIDocument);
[ref] native nsIntRectRef(nsIntRect);
[scriptable, uuid(e2e5dd7d-8140-4fc5-b2c3-3a3b4f946fc7)]
[scriptable, uuid(c824ac5e-3d86-4ae5-9ccc-9433bdc43004)]
interface nsIContentViewer : nsISupports
{
@ -96,6 +96,8 @@ interface nsIContentViewer : nsISupports
void show();
void hide();
attribute boolean enableRendering;
attribute boolean sticky;
/*

View File

@ -62,6 +62,7 @@ NS_IMETHODIMP nsMyObserver::Notify(
if(!mCharset.Equals(aCharset)) {
if(mNotifyByReload) {
rv = mWebShellSvc->SetRendering( PR_FALSE);
rv = mWebShellSvc->StopDocumentLoad();
rv = mWebShellSvc->ReloadDocument(aCharset, kCharsetFromAutoDetection);
} else {

View File

@ -35,6 +35,8 @@
*
* ***** END LICENSE BLOCK ***** */
//#define DONT_INFORM_DOCSHELL
#include "nsIServiceManager.h"
#include "nsIWebShellServices.h"
#include "nsObserverBase.h"
@ -65,16 +67,24 @@ NS_IMETHODIMP nsObserverBase::NotifyDocShell(nsISupports* aDocShell,
nsCOMPtr<nsIWebShellServices> wss;
wss = do_QueryInterface(aDocShell,&res);
if (NS_SUCCEEDED(res)) {
#ifndef DONT_INFORM_DOCSHELL
// ask the webshellservice to load the URL
if (NS_FAILED(wss->StopDocumentLoad())){
// do nothing and fall through
if (NS_FAILED( res = wss->SetRendering(PR_FALSE) ))
rv = res;
// XXX nisheeth, uncomment the following two line to see the reent problem
else if (NS_FAILED(res = wss->StopDocumentLoad())){
rv = wss->SetRendering(PR_TRUE); // turn on the rendering so at least we will see something.
}
else if (NS_FAILED(wss->ReloadDocument(charset, source))) {
// do nothing and fall through
else if (NS_FAILED(res = wss->ReloadDocument(charset, source))) {
rv = wss->SetRendering(PR_TRUE); // turn on the rendering so at least we will see something.
}
else {
rv = NS_ERROR_HTMLPARSER_STOPPARSING; // We're reloading a new document...stop loading the current.
}
#endif
}
//if our reload request is not accepted, we should tell parser to go on

View File

@ -385,8 +385,11 @@ private:
/**
* @param aDoInitialReflow set to true if you want to kick off the initial
* reflow
* @param aReenableRefresh set to true if you want this to reenable refresh
* before returning; otherwise this will return with refresh disabled
* in the view manager
*/
nsresult InitPresentationStuff(PRBool aDoInitialReflow);
nsresult InitPresentationStuff(PRBool aDoInitialReflow, PRBool aReenableRefresh);
nsresult GetPopupNode(nsIDOMNode** aNode);
nsresult GetPopupLinkNode(nsIDOMNode** aNode);
@ -452,6 +455,7 @@ protected:
PRInt16 mNumURLStarts;
PRInt16 mDestroyRefCount; // a second "refcount" for the document viewer's "destroy"
unsigned mEnableRendering : 1;
unsigned mStopped : 1;
unsigned mLoaded : 1;
unsigned mDeferredWindowClose : 1;
@ -493,7 +497,6 @@ protected:
PRPackedBool mIsPageMode;
PRPackedBool mCallerIsClosingWindow;
PRPackedBool mInitializedForPrintPreview;
PRPackedBool mHidden;
};
//------------------------------------------------------------------
@ -520,6 +523,7 @@ NS_NewDocumentViewer(nsIDocumentViewer** aResult)
void DocumentViewerImpl::PrepareToStartLoad()
{
mEnableRendering = PR_TRUE;
mStopped = PR_FALSE;
mLoaded = PR_FALSE;
mDeferredWindowClose = PR_FALSE;
@ -554,8 +558,7 @@ DocumentViewerImpl::DocumentViewerImpl()
mPrintPreviewZoom(1.0),
#endif
mHintCharsetSource(kCharsetUninitialized),
mInitializedForPrintPreview(PR_FALSE),
mHidden(PR_FALSE)
mInitializedForPrintPreview(PR_FALSE)
{
PrepareToStartLoad();
}
@ -693,7 +696,7 @@ DocumentViewerImpl::Init(nsIWidget* aParentWidget,
}
nsresult
DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow)
DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow, PRBool aReenableRefresh)
{
if (GetIsPrintPreview())
return NS_OK;
@ -736,6 +739,7 @@ DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow)
nscoord width = mPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel() * mBounds.width;
nscoord height = mPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel() * mBounds.height;
mViewManager->DisableRefresh();
mViewManager->SetWindowDimensions(width, height);
mPresContext->SetTextZoom(mTextZoom);
mPresContext->SetFullZoom(mPageZoom);
@ -757,6 +761,11 @@ DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow)
mPresContext->SetVisibleArea(nsRect(0, 0, width, height));
}
// Now trigger a refresh
if (aReenableRefresh && mEnableRendering && mViewManager) {
mViewManager->EnableRefresh(NS_VMREFRESH_IMMEDIATE);
}
// now register ourselves as a selection listener, so that we get
// called when the selection changes in the window
if (!mSelectionListener) {
@ -957,7 +966,7 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget,
// The ViewManager and Root View was created above (in
// MakeWindow())...
rv = InitPresentationStuff(!makeCX);
rv = InitPresentationStuff(!makeCX, !makeCX);
}
return rv;
@ -1251,7 +1260,7 @@ DocumentViewerImpl::ResetCloseWindow()
NS_IMETHODIMP
DocumentViewerImpl::PageHide(PRBool aIsUnload)
{
mHidden = PR_TRUE;
mEnableRendering = PR_FALSE;
if (!mDocument) {
return NS_ERROR_NULL_POINTER;
@ -1631,7 +1640,7 @@ DocumentViewerImpl::Stop(void)
mDocument->StopDocumentLoad();
}
if (!mHidden && (mLoaded || mStopped) && mPresContext && !mSHEntry)
if (mEnableRendering && (mLoaded || mStopped) && mPresContext && !mSHEntry)
mPresContext->SetImageAnimationMode(imgIContainer::kDontAnimMode);
mStopped = PR_TRUE;
@ -1746,7 +1755,10 @@ DocumentViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument)
mPresContext->SetLinkHandler(linkHandler);
}
rv = InitPresentationStuff(PR_FALSE);
rv = InitPresentationStuff(PR_FALSE, PR_FALSE);
if (NS_SUCCEEDED(rv) && mEnableRendering && mViewManager) {
mViewManager->EnableRefresh(NS_VMREFRESH_IMMEDIATE);
}
}
return rv;
@ -1973,7 +1985,8 @@ DocumentViewerImpl::Show(void)
if (mPresContext) {
Hide();
rv = InitPresentationStuff(mDocument->MayStartLayout());
rv = InitPresentationStuff(mDocument->MayStartLayout(),
mDocument->MayStartLayout());
}
// If we get here the document load has already started and the
@ -2041,6 +2054,26 @@ DocumentViewerImpl::Hide(void)
return NS_OK;
}
NS_IMETHODIMP
DocumentViewerImpl::SetEnableRendering(PRBool aOn)
{
NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
mEnableRendering = aOn;
if (mViewManager) {
if (aOn) {
mViewManager->EnableRefresh(NS_VMREFRESH_IMMEDIATE);
nsIView* view;
mViewManager->GetRootView(view); // views are not refCounted
if (view) {
mViewManager->UpdateView(view, NS_VMREFRESH_IMMEDIATE);
}
}
else {
mViewManager->DisableRefresh();
}
}
return NS_OK;
}
NS_IMETHODIMP
DocumentViewerImpl::GetSticky(PRBool *aSticky)
@ -2058,6 +2091,17 @@ DocumentViewerImpl::SetSticky(PRBool aSticky)
return NS_OK;
}
NS_IMETHODIMP
DocumentViewerImpl::GetEnableRendering(PRBool* aResult)
{
NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
NS_PRECONDITION(nsnull != aResult, "null OUT ptr");
if (aResult) {
*aResult = mEnableRendering;
}
return NS_OK;
}
NS_IMETHODIMP
DocumentViewerImpl::RequestWindowClose(PRBool* aCanClose)
{
@ -4202,6 +4246,10 @@ DocumentViewerImpl::ReturnToGalleyPresentation()
mPrintEngine->Destroy();
mPrintEngine = nsnull;
if (mViewManager) {
mViewManager->EnableRefresh(NS_VMREFRESH_DEFERRED);
}
nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
ResetFocusState(docShell);
@ -4312,6 +4360,7 @@ NS_IMETHODIMP DocumentViewerImpl::SetPageMode(PRBool aPageMode, nsIPrintSettings
NS_ENSURE_SUCCESS(rv, rv);
}
InitInternal(mParentWidget, nsnull, mBounds, PR_TRUE, PR_FALSE, PR_FALSE);
mViewManager->EnableRefresh(NS_VMREFRESH_NO_SYNC);
Show();
return NS_OK;

View File

@ -600,17 +600,23 @@ nsHtml5TreeOpExecutor::NeedsCharsetSwitchTo(const char* aEncoding)
return;
}
nsresult rv = NS_OK;
nsCOMPtr<nsIWebShellServices> wss = do_QueryInterface(mDocShell);
if (!wss) {
return;
}
#ifndef DONT_INFORM_WEBSHELL
// ask the webshellservice to load the URL
if (NS_SUCCEEDED(wss->StopDocumentLoad())) {
wss->ReloadDocument(aEncoding, kCharsetFromMetaTag);
if (NS_FAILED(rv = wss->SetRendering(PR_FALSE))) {
// do nothing and fall thru
} else if (NS_FAILED(rv = wss->StopDocumentLoad())) {
rv = wss->SetRendering(PR_TRUE); // turn on the rendering so at least we will see something.
} else if (NS_FAILED(rv = wss->ReloadDocument(aEncoding, kCharsetFromMetaTag))) {
rv = wss->SetRendering(PR_TRUE); // turn on the rendering so at least we will see something.
}
// if the charset switch was accepted, wss has called Terminate() on the
// parser by now
#endif
if (!mParser) {
// success

View File

@ -50,8 +50,8 @@ class nsIDeviceContext;
class nsIViewObserver;
#define NS_IVIEWMANAGER_IID \
{ 0xbbdd429c, 0x6542, 0x477a, \
{ 0xab, 0x48, 0x6c, 0xd6, 0xcb, 0xb8, 0xdf, 0x98 } }
{ 0x6ca2fd1c, 0xa57e, 0x4802, \
{ 0xad, 0x55, 0x85, 0xf6, 0x6f, 0x4a, 0x2c, 0x04 } }
class nsIViewManager : public nsISupports
{
@ -277,6 +277,23 @@ public:
*/
NS_IMETHOD GetDeviceContext(nsIDeviceContext *&aContext) = 0;
/**
* prevent the view manager from refreshing.
* @return error status
*/
// XXXbz callers of this function don't seem to realize that it disables
// refresh for the entire view manager hierarchy.... Maybe it shouldn't do
// that?
NS_IMETHOD DisableRefresh(void) = 0;
/**
* allow the view manager to refresh. this may cause a synchronous
* paint to occur inside the call.
* @param aUpdateFlags see bottom of nsIViewManager.h for description
* @return error status
*/
NS_IMETHOD EnableRefresh(PRUint32 aUpdateFlags) = 0;
class NS_STACK_CLASS UpdateViewBatch {
public:
UpdateViewBatch() {}

View File

@ -256,6 +256,8 @@ NS_IMETHODIMP nsViewManager::Init(nsIDeviceContext* aContext)
}
mContext = aContext;
mRefreshEnabled = PR_TRUE;
return NS_OK;
}
@ -519,7 +521,7 @@ void nsViewManager::ProcessPendingUpdates(nsView* aView, PRBool aDoInvalidate)
if (aDoInvalidate && aView->HasNonEmptyDirtyRegion()) {
// Push out updates after we've processed the children; ensures that
// damage is applied based on the final widget geometry
NS_ASSERTION(IsRefreshEnabled(), "Cannot process pending updates with refresh disabled");
NS_ASSERTION(mRefreshEnabled, "Cannot process pending updates with refresh disabled");
nsRegion* dirtyRegion = aView->GetDirtyRegion();
if (dirtyRegion) {
nsView* nearestViewWithWidget = aView;
@ -1597,15 +1599,29 @@ nsViewManager::CreateRenderingContext(nsView &aView)
return cx;
}
void nsViewManager::TriggerRefresh(PRUint32 aUpdateFlags)
NS_IMETHODIMP nsViewManager::DisableRefresh(void)
{
if (!IsRootVM()) {
RootViewManager()->TriggerRefresh(aUpdateFlags);
return;
return RootViewManager()->DisableRefresh();
}
if (mUpdateBatchCnt > 0)
return;
return NS_OK;
mRefreshEnabled = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP nsViewManager::EnableRefresh(PRUint32 aUpdateFlags)
{
if (!IsRootVM()) {
return RootViewManager()->EnableRefresh(aUpdateFlags);
}
if (mUpdateBatchCnt > 0)
return NS_OK;
mRefreshEnabled = PR_TRUE;
// nested batching can combine IMMEDIATE with DEFERRED. Favour
// IMMEDIATE over DEFERRED and DEFERRED over NO_SYNC. We need to
@ -1622,6 +1638,8 @@ void nsViewManager::TriggerRefresh(PRUint32 aUpdateFlags)
} else { // NO_SYNC
FlushPendingInvalidates();
}
return NS_OK;
}
nsIViewManager* nsViewManager::BeginUpdateViewBatch(void)
@ -1630,11 +1648,15 @@ nsIViewManager* nsViewManager::BeginUpdateViewBatch(void)
return RootViewManager()->BeginUpdateViewBatch();
}
nsresult result = NS_OK;
if (mUpdateBatchCnt == 0) {
mUpdateBatchFlags = 0;
result = DisableRefresh();
}
++mUpdateBatchCnt;
if (NS_SUCCEEDED(result))
++mUpdateBatchCnt;
return this;
}
@ -1643,6 +1665,8 @@ NS_IMETHODIMP nsViewManager::EndUpdateViewBatch(PRUint32 aUpdateFlags)
{
NS_ASSERTION(IsRootVM(), "Should only be called on root");
nsresult result = NS_OK;
--mUpdateBatchCnt;
NS_ASSERTION(mUpdateBatchCnt >= 0, "Invalid batch count!");
@ -1655,10 +1679,10 @@ NS_IMETHODIMP nsViewManager::EndUpdateViewBatch(PRUint32 aUpdateFlags)
mUpdateBatchFlags |= aUpdateFlags;
if (mUpdateBatchCnt == 0) {
TriggerRefresh(mUpdateBatchFlags);
result = EnableRefresh(mUpdateBatchFlags);
}
return NS_OK;
return result;
}
NS_IMETHODIMP nsViewManager::GetRootWidget(nsIWidget **aWidget)
@ -1742,9 +1766,17 @@ nsViewManager::FlushPendingInvalidates()
// all of them together. We don't use
// BeginUpdateViewBatch/EndUpdateViewBatch, since that would reenter this
// exact code, but we want the effect of a single big update batch.
PRBool refreshEnabled = mRefreshEnabled;
mRefreshEnabled = PR_FALSE;
++mUpdateBatchCnt;
CallWillPaintOnObservers();
--mUpdateBatchCnt;
// Someone could have called EnableRefresh on us from inside WillPaint().
// Only reset the old mRefreshEnabled value if the current value is false.
if (!mRefreshEnabled) {
mRefreshEnabled = refreshEnabled;
}
}
if (mHasPendingUpdates) {

View File

@ -149,6 +149,9 @@ public:
NS_IMETHOD GetDeviceContext(nsIDeviceContext *&aContext);
NS_IMETHOD DisableRefresh(void);
NS_IMETHOD EnableRefresh(PRUint32 aUpdateFlags);
virtual nsIViewManager* BeginUpdateViewBatch(void);
NS_IMETHOD EndUpdateViewBatch(PRUint32 aUpdateFlags);
@ -186,8 +189,6 @@ private:
void UpdateViews(nsView *aView, PRUint32 aUpdateFlags);
void TriggerRefresh(PRUint32 aUpdateFlags);
void Refresh(nsView *aView, nsIRenderingContext *aContext,
nsIRegion *region, PRUint32 aUpdateFlags);
void RenderViews(nsView *aRootView, nsIRenderingContext& aRC,
@ -275,7 +276,7 @@ public: // NOT in nsIViewManager, so private to the view module
nsresult CreateRegion(nsIRegion* *result);
PRBool IsRefreshEnabled() { return RootViewManager()->mUpdateBatchCnt == 0; }
PRBool IsRefreshEnabled() { return RootViewManager()->mRefreshEnabled; }
nsIViewObserver* GetViewObserver() { return mObserver; }
@ -310,6 +311,8 @@ private:
PRInt32 mUpdateBatchCnt;
PRUint32 mUpdateBatchFlags;
PRInt32 mScrollCnt;
// Use IsRefreshEnabled() to check the value of mRefreshEnabled.
PRPackedBool mRefreshEnabled;
// Use IsPainting() and SetPainting() to access mPainting.
PRPackedBool mPainting;
PRPackedBool mRecursiveRefreshPending;

View File

@ -42,9 +42,10 @@
// Interface ID for nsIWebShellServices
/* 0c628af0-5638-4703-8f99-ed6134c9de18 */
/* 8b26a346-031e-11d3-aeea-00108300ff91 */
#define NS_IWEB_SHELL_SERVICES_IID \
{ 0x0c628af0, 0x5638, 0x4703, {0x8f, 0x99, 0xed, 0x61, 0x34, 0xc9, 0xde, 0x18} }
{ 0x8b26a346, 0x031e, 0x11d3, {0xae, 0xea, 0x00, 0x10, 0x83, 0x00, 0xff, 0x91} }
//----------------------------------------------------------------------
@ -55,6 +56,7 @@ public:
NS_IMETHOD ReloadDocument(const char* aCharset = nsnull ,
PRInt32 aSource = kCharsetUninitialized) = 0;
NS_IMETHOD StopDocumentLoad(void) = 0;
NS_IMETHOD SetRendering(PRBool aRender) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIWebShellServices, NS_IWEB_SHELL_SERVICES_IID)
@ -63,5 +65,6 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIWebShellServices, NS_IWEB_SHELL_SERVICES_IID)
#define NS_DECL_NSIWEBSHELLSERVICES \
NS_IMETHOD ReloadDocument(const char *aCharset=nsnull, PRInt32 aSource=kCharsetUninitialized); \
NS_IMETHOD StopDocumentLoad(void); \
NS_IMETHOD SetRendering(PRBool aRender);
#endif /* nsIWebShellServices_h___ */