Bug 478079 - Kill nsViewManager::DefaultRefresh, and move the cached canvas background to the pres shell; r+sr=roc

This commit is contained in:
Zack Weinberg 2009-02-23 02:10:23 +01:00
Родитель 4763c60ba6
Коммит 4b0289ba0b
8 изменённых файлов: 132 добавлений и 185 удалений

Просмотреть файл

@ -6493,8 +6493,6 @@ nsDocShell::SetupNewViewer(nsIContentViewer * aNewViewer)
}
nscolor bgcolor = NS_RGBA(0, 0, 0, 0);
PRBool bgSet = PR_FALSE;
// Ensure that the content viewer is destroyed *after* the GC - bug 71515
nsCOMPtr<nsIContentViewer> kungfuDeathGrip = mContentViewer;
if (mContentViewer) {
@ -6502,8 +6500,8 @@ nsDocShell::SetupNewViewer(nsIContentViewer * aNewViewer)
// releasing it...
mContentViewer->Stop();
// Try to extract the default background color from the old
// view manager, so we can use it for the next document.
// Try to extract the canvas background color from the old
// presentation shell, so we can use it for the next document.
nsCOMPtr<nsIDocumentViewer> docviewer =
do_QueryInterface(mContentViewer);
@ -6512,13 +6510,7 @@ nsDocShell::SetupNewViewer(nsIContentViewer * aNewViewer)
docviewer->GetPresShell(getter_AddRefs(shell));
if (shell) {
nsIViewManager* vm = shell->GetViewManager();
if (vm) {
vm->GetDefaultBackgroundColor(&bgcolor);
// If the background color is not known, don't propagate it.
bgSet = NS_GET_A(bgcolor) != 0;
}
bgcolor = shell->GetCanvasBackground();
}
}
@ -6579,23 +6571,18 @@ nsDocShell::SetupNewViewer(nsIContentViewer * aNewViewer)
focusController->SetSuppressFocus(PR_FALSE,
"Win32-Only Link Traversal Issue");
if (bgSet && widget) {
// Stuff the bgcolor from the last view manager into the new
// view manager. This improves page load continuity.
nsCOMPtr<nsIDocumentViewer> docviewer =
do_QueryInterface(mContentViewer);
if (docviewer) {
nsCOMPtr<nsIPresShell> shell;
docviewer->GetPresShell(getter_AddRefs(shell));
// Stuff the bgcolor from the old pres shell into the new
// pres shell. This improves page load continuity.
nsCOMPtr<nsIDocumentViewer> docviewer =
do_QueryInterface(mContentViewer);
if (shell) {
nsIViewManager* vm = shell->GetViewManager();
if (docviewer) {
nsCOMPtr<nsIPresShell> shell;
docviewer->GetPresShell(getter_AddRefs(shell));
if (vm) {
vm->SetDefaultBackgroundColor(bgcolor);
}
}
if (shell) {
shell->SetCanvasBackground(bgcolor);
}
}

Просмотреть файл

@ -722,12 +722,6 @@ DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow, PRBool aReena
mPresContext->SetTextZoom(mTextZoom);
mPresContext->SetFullZoom(mPageZoom);
// Setup default view manager background color
// This may be overridden by the docshell with the background color
// for the last document loaded into the docshell
mViewManager->SetDefaultBackgroundColor(mPresContext->DefaultBackgroundColor());
if (aDoInitialReflow) {
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
if (htmlDoc) {

Просмотреть файл

@ -101,10 +101,10 @@ class gfxContext;
typedef short SelectionType;
typedef PRUint32 nsFrameState;
// 780d34b0-00c3-4bbd-b57d-c600aaf53613
#define NS_IPRESSHELL_IID \
{ 0x780d34b0, 0xc3, 0x4bbd, \
{ 0xb5, 0x7d, 0xc6, 0x0, 0xaa, 0xf5, 0x36, 0x13 } }
// 445e6184-5e7e-4a9b-97f7-c9391e6773d2
#define NS_IPRESSHELL_IID \
{ 0x445e6184, 0x5e7e, 0x4a9b, \
{ 0x97, 0xf7, 0xc9, 0x39, 0x1e, 0x67, 0x73, 0xd2 } }
// Constants for ScrollContentIntoView() function
#define NS_PRESSHELL_SCROLL_TOP 0
@ -776,11 +776,20 @@ public:
* Stop or restart non synthetic test mouse event handling on *all*
* presShells.
*
* @param aDisable If true, disable all non synthetic test mouse events on all
* presShells. Otherwise, enable them.
* @param aDisable If true, disable all non synthetic test mouse
* events on all presShells. Otherwise, enable them.
*/
NS_IMETHOD DisableNonTestMouseEvents(PRBool aDisable) = 0;
/* Record the background color of the most recently loaded canvas.
* This color is composited on top of the user's default background
* color whenever we need to provide an "ultimate" background color.
* See PresShell::Paint, PresShell::PaintDefaultBackground, and
* nsDocShell::SetupNewViewer; bug 476557 and other bugs mentioned there.
*/
void SetCanvasBackground(nscolor aColor) { mCanvasBackgroundColor = aColor; }
nscolor GetCanvasBackground() { return mCanvasBackgroundColor; }
protected:
// IMPORTANT: The ownership implicit in the following member variables
// has been explicitly checked. If you add any members to this class,
@ -819,6 +828,9 @@ protected:
// A list of weak frames. This is a pointer to the last item in the list.
nsWeakFrame* mWeakFrames;
// Most recent canvas background color.
nscolor mCanvasBackgroundColor;
};
/**

Просмотреть файл

@ -901,6 +901,9 @@ public:
NS_IMETHOD Paint(nsIView *aView,
nsIRenderingContext* aRenderingContext,
const nsRegion& aDirtyRegion);
NS_IMETHOD PaintDefaultBackground(nsIView *aView,
nsIRenderingContext* aRenderingContext,
const nsRect& aDirtyRect);
NS_IMETHOD ComputeRepaintRegionForCopy(nsIView* aRootView,
nsIView* aMovingView,
nsPoint aDelta,
@ -5377,68 +5380,64 @@ PresShell::Paint(nsIView* aView,
NS_ASSERTION(!mIsDestroying, "painting a destroyed PresShell");
NS_ASSERTION(aView, "null view");
// Compute the backstop color for the view. This color must be
// totally transparent if the view is within a glass or transparent
// widget; otherwise it must be totally opaque. The user's default
// background color as recorded in the prescontext is guaranteed to
// be opaque.
PRBool needTransparency = PR_FALSE;
nscolor backgroundColor = mPresContext->DefaultBackgroundColor();
for (nsIView *view = aView; view; view = view->GetParent()) {
if (view->HasWidget() &&
view->GetWidget()->GetTransparencyMode() != eTransparencyOpaque) {
needTransparency = PR_TRUE;
break;
}
}
// Check whether the view manager knows the background color of the
// canvas. We set this below, and the docshell propagates it across
// page loads; using it in preference to the user's default color
// avoids screen flashing in between pages that use the same
// non-default background.
//
// If we're called at some weird moment when there is no view
// manager, default to transparent.
nscolor viewDefaultColor = NS_RGBA(0,0,0,0);
if (mViewManager)
mViewManager->GetDefaultBackgroundColor(&viewDefaultColor);
// If we don't have a frame tree yet, all we can do is paint the
// backstop colors.
nsIFrame* frame = static_cast<nsIFrame*>(aView->GetClientData());
if (!frame) {
if (!needTransparency) {
backgroundColor = NS_ComposeColors(backgroundColor, viewDefaultColor);
aRenderingContext->SetColor(backgroundColor);
aRenderingContext->FillRect(aDirtyRegion.GetBounds());
}
return NS_OK;
}
// If we do have a frame tree, check whether it specifies a canvas
// background color yet. If it does, use that instead of whatever
// color the view manager reported, and update the view manager
// accordingly.
// If we have a frame tree and it has style information that
// specifies the background color of the canvas, update our local
// cache of that color.
nsIFrame* rootFrame = FrameConstructor()->GetRootElementStyleFrame();
if (rootFrame) {
const nsStyleBackground* bgStyle =
nsCSSRendering::FindRootFrameBackground(rootFrame);
// XXX ideally we would set the view manager default to
// bgStyle->mBackgroundColor, and nsViewManager::DefaultRefresh would
// be able to cope with partial transparency. But it can't so we can't.
// -- zwol 2009-02-11
backgroundColor = NS_ComposeColors(backgroundColor,
bgStyle->mBackgroundColor);
mViewManager->SetDefaultBackgroundColor(backgroundColor);
} else {
backgroundColor = NS_ComposeColors(backgroundColor, viewDefaultColor);
mCanvasBackgroundColor = bgStyle->mBackgroundColor;
}
nsLayoutUtils::PaintFrame(aRenderingContext, frame, aDirtyRegion,
needTransparency ? NS_RGBA(0,0,0,0)
: backgroundColor);
// Compute the backstop color for the view.
nscolor bgcolor;
nsIWidget* widget = aView->GetNearestWidget(nsnull);
if (widget && widget->GetTransparencyMode() != eTransparencyOpaque) {
// Within a transparent widget, so the backstop color must be
// totally transparent.
bgcolor = NS_RGBA(0,0,0,0);
} else {
// Within an opaque widget (or no widget at all), so the backstop
// color must be totally opaque. The cached canvas background
// color is not guaranteed to be opaque, but the user's default
// background as reported by the prescontext is. Composing the
// former on top of the latter prevents window flashing in between
// pages that use the same non-default background.
bgcolor = NS_ComposeColors(mPresContext->DefaultBackgroundColor(),
mCanvasBackgroundColor);
}
nsIFrame* frame = static_cast<nsIFrame*>(aView->GetClientData());
if (frame) {
nsLayoutUtils::PaintFrame(aRenderingContext, frame, aDirtyRegion, bgcolor);
} else {
aRenderingContext->SetColor(bgcolor);
aRenderingContext->FillRect(aDirtyRegion.GetBounds());
}
return NS_OK;
}
NS_IMETHODIMP
PresShell::PaintDefaultBackground(nsIView* aView,
nsIRenderingContext* aRenderingContext,
const nsRect& aDirtyRect)
{
AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Paint);
NS_ASSERTION(!mIsDestroying, "painting a destroyed PresShell");
NS_ASSERTION(aView, "null view");
// The view manager does not call this function if there is no
// widget or it is transparent. We must not look at the frame tree,
// so all we have to use is the canvas default color as set above,
// or failing that, the user's default color.
nscolor bgcolor = NS_ComposeColors(mPresContext->DefaultBackgroundColor(),
mCanvasBackgroundColor);
aRenderingContext->SetColor(bgcolor);
aRenderingContext->FillRect(aDirtyRect);
return NS_OK;
}

Просмотреть файл

@ -40,7 +40,6 @@
#include "nscore.h"
#include "nsIView.h"
#include "nsColor.h"
#include "nsEvent.h"
#include "nsIRenderingContext.h"
@ -60,10 +59,10 @@ enum nsRectVisibility {
nsRectVisibility_kZeroAreaRect
};
// de2a2d24-9753-4488-9fdc-dd0accb484f7
// fa490965-ebd0-4203-836c-51c42d01fedb
#define NS_IVIEWMANAGER_IID \
{ 0xde2a2d24, 0x9753, 0x4488, \
{ 0x9f, 0xdc, 0xdd, 0x0a, 0xcc, 0xb4, 0x84, 0xf7 } }
{ 0xfa490965, 0xebd0, 0x4203, \
{ 0x83, 0x6c, 0x51, 0xc4, 0x2d, 0x01, 0xfe, 0xdb } }
class nsIViewManager : public nsISupports
{
@ -441,22 +440,6 @@ public:
*/
NS_IMETHOD IsPainting(PRBool& aIsPainting)=0;
/**
* Set the default background color that the view manager should use
* to paint otherwise unowned areas. If the color isn't known, just set
* it to zero (which means 'transparent' since the color is RGBA).
*
* @param aColor the default background color
*/
NS_IMETHOD SetDefaultBackgroundColor(nscolor aColor)=0;
/**
* Retrieve the default background color.
*
* @param aColor the default background color
*/
NS_IMETHOD GetDefaultBackgroundColor(nscolor* aColor)=0;
/**
* Retrieve the time of the last user event. User events
* include mouse and keyboard events. The viewmanager

Просмотреть файл

@ -46,10 +46,10 @@
class nsIRenderingContext;
class nsGUIEvent;
// cb03e6e3-9d14-4018-85f8-7d46af878c98
#define NS_IVIEWOBSERVER_IID \
{ 0xcb03e6e3, 0x9d14, 0x4018, \
{ 0x85, 0xf8, 0x7d, 0x46, 0xaf, 0x87, 0x8c, 0x98 } }
// 52b3b616-23a9-4516-a8d3-452b4126eb2b
#define NS_IVIEWOBSERVER_IID \
{ 0x52b3b616, 0x23a9, 0x4516, \
{ 0xa8, 0xd3, 0x45, 0x2b, 0x41, 0x26, 0xeb, 0x2b } }
class nsIViewObserver : public nsISupports
{
@ -64,13 +64,33 @@ public:
* of the view is painted at (0,0) in the rendering context's current
* transform. For best results this should transform to pixel-aligned
* coordinates.
* @param aDirtyRegion the region to be painted, in the coordinates of aRootView
* @param aDirtyRegion the region to be painted, in the coordinates of
* aRootView
* @return error status
*/
NS_IMETHOD Paint(nsIView* aRootView,
nsIRenderingContext* aRenderingContext,
const nsRegion& aDirtyRegion) = 0;
/* called when the observer needs to paint something, but the view
* tree is unstable, so it must *not* paint, or even examine, the
* frame subtree rooted at the view. (It is, however, safe to inspect
* the state of the view itself, and any associated widget.) The name
* illustrates the expected behavior, which is to paint some default
* background color over the dirty rect.
*
* @param aRenderingContext rendering context to paint to; the origin
* of the view is painted at (0,0) in the rendering context's current
* transform. For best results this should transform to pixel-aligned
* coordinates.
* @param aDirtyRect the rectangle to be painted, in the coordinates
* of aRootView
* @return error status
*/
NS_IMETHOD PaintDefaultBackground(nsIView* aRootView,
nsIRenderingContext* aRenderingContext,
const nsRect& aDirtyRect) = 0;
/**
* @see nsLayoutUtils::ComputeRepaintRegionForCopy
*/

Просмотреть файл

@ -180,7 +180,6 @@ nsViewManager::nsViewManager()
}
// NOTE: we use a zeroing operator new, so all data members are
// assumed to be cleared here.
mDefaultBackgroundColor = NS_RGBA(0, 0, 0, 0);
mHasPendingUpdates = PR_FALSE;
mRecursiveRefreshPending = PR_FALSE;
mUpdateBatchFlags = 0;
@ -532,44 +531,6 @@ void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext,
}
// aRect is in app units and relative to the top-left of the aView->GetWidget()
void nsViewManager::DefaultRefresh(nsView* aView,
nsIRenderingContext *aContext,
const nsRect* aRect)
{
NS_PRECONDITION(aView, "Must have a view to work with!");
// Don't draw anything if there's no widget or it's transparent.
nsIWidget* widget = aView->GetNearestWidget(nsnull);
if (!widget || widget->GetTransparencyMode() != eTransparencyOpaque)
return;
nsCOMPtr<nsIRenderingContext> context = aContext;
if (!context)
context = CreateRenderingContext(*aView);
// XXXzw I think this can only happen if we don't have a widget, in
// which case we bailed out above.
if (!context) {
NS_WARNING("nsViewManager: No rendering context for DefaultRefresh");
return;
}
nscolor bgcolor = mDefaultBackgroundColor;
// If we somehow get here before any default background color has
// been set, warn and use white.
if (bgcolor == NS_RGBA(0,0,0,0)) {
NS_WARNING("nsViewManager: DefaultRefresh called with no background set");
bgcolor = NS_RGB(255,255,255);
}
NS_ASSERTION(NS_GET_A(bgcolor) == 255,
"nsViewManager: non-opaque background color snuck in");
context->SetColor(bgcolor);
context->FillRect(*aRect);
}
void nsViewManager::AddCoveringWidgetsToOpaqueRegion(nsRegion &aRgn, nsIDeviceContext* aContext,
nsView* aRootView) {
NS_PRECONDITION(aRootView, "Must have root view");
@ -1134,11 +1095,25 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aS
}
} else {
// since we got an NS_PAINT event, we need to
// draw something so we don't get blank areas.
// draw something so we don't get blank areas,
// unless there's no widget or it's transparent.
nsIntRect damIntRect;
region->GetBoundingBox(&damIntRect.x, &damIntRect.y, &damIntRect.width, &damIntRect.height);
nsRect damRect = nsIntRect::ToAppUnits(damIntRect, mContext->AppUnitsPerDevPixel());
DefaultRefresh(view, event->renderingContext, &damRect);
region->GetBoundingBox(&damIntRect.x, &damIntRect.y,
&damIntRect.width, &damIntRect.height);
nsRect damRect =
nsIntRect::ToAppUnits(damIntRect, mContext->AppUnitsPerDevPixel());
nsIWidget* widget = view->GetNearestWidget(nsnull);
if (widget && widget->GetTransparencyMode() == eTransparencyOpaque) {
nsCOMPtr<nsIRenderingContext> context = event->renderingContext;
if (!context)
context = CreateRenderingContext(*view);
if (context)
mObserver->PaintDefaultBackground(view, context, damRect);
else
NS_WARNING("nsViewManager: no rc for default refresh");
}
// Clients like the editor can trigger multiple
// reflows during what the user perceives as a single
@ -1163,7 +1138,7 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aS
// async paint event for the *entire* ScrollPort or
// ScrollingView's viewable area. (See bug 97674 for this
// alternate patch.)
UpdateView(view, damRect, NS_VMREFRESH_NO_SYNC);
}
@ -2231,22 +2206,6 @@ nsViewManager::ProcessInvalidateEvent()
}
}
NS_IMETHODIMP
nsViewManager::SetDefaultBackgroundColor(nscolor aColor)
{
NS_ASSERTION(NS_GET_A(aColor) == 255, "default background must be opaque");
mDefaultBackgroundColor = aColor;
return NS_OK;
}
NS_IMETHODIMP
nsViewManager::GetDefaultBackgroundColor(nscolor* aColor)
{
*aColor = mDefaultBackgroundColor;
return NS_OK;
}
NS_IMETHODIMP
nsViewManager::GetLastUserEventTime(PRUint32& aTime)
{

Просмотреть файл

@ -176,8 +176,6 @@ public:
NS_IMETHOD ForceUpdate();
NS_IMETHOD IsPainting(PRBool& aIsPainting);
NS_IMETHOD SetDefaultBackgroundColor(nscolor aColor);
NS_IMETHOD GetDefaultBackgroundColor(nscolor* aColor);
NS_IMETHOD GetLastUserEventTime(PRUint32& aTime);
void ProcessInvalidateEvent();
static PRUint32 gLastUserEventTime;
@ -262,10 +260,6 @@ private:
void Refresh(nsView *aView, nsIRenderingContext *aContext,
nsIRegion *region, PRUint32 aUpdateFlags);
/**
* Refresh aView (which must be non-null) with our default background color
*/
void DefaultRefresh(nsView* aView, nsIRenderingContext *aContext, const nsRect* aRect);
void RenderViews(nsView *aRootView, nsIRenderingContext& aRC,
const nsRegion& aRegion);
@ -427,7 +421,6 @@ private:
nsIDeviceContext *mContext;
nsIViewObserver *mObserver;
nsIScrollableView *mRootScrollable;
nscolor mDefaultBackgroundColor;
nsIntPoint mMouseLocation; // device units, relative to mRootView
// The size for a resize that we delayed until the root view becomes