Bug 563878. Part 12. Change the view observer interface and overhaul painting in view/. r=mats f=roc

This commit is contained in:
Timothy Nikkel 2010-07-18 21:23:47 -05:00
Родитель b3aff69b2d
Коммит afd4c534db
4 изменённых файлов: 84 добавлений и 65 удалений

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

@ -817,6 +817,7 @@ public:
nsIView* aViewToPaint, nsIView* aViewToPaint,
nsIWidget* aWidget, nsIWidget* aWidget,
const nsRegion& aDirtyRegion, const nsRegion& aDirtyRegion,
const nsIntRegion& aIntDirtyRegion,
PRBool aPaintDefaultBackground, PRBool aPaintDefaultBackground,
PRBool aWillSendDidPaint); PRBool aWillSendDidPaint);
NS_IMETHOD HandleEvent(nsIView* aView, NS_IMETHOD HandleEvent(nsIView* aView,
@ -5828,7 +5829,7 @@ static void DrawThebesLayer(ThebesLayer* aLayer,
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
rc->Init(devCtx, aContext); rc->Init(devCtx, aContext);
nsIRenderingContext::AutoPushTranslation nsIRenderingContext::AutoPushTranslation
push(rc, -params->mOffsetToWidget.x, -params->mOffsetToWidget.y); push(rc, params->mOffsetToWidget.x, params->mOffsetToWidget.y);
nsLayoutUtils::PaintFrame(rc, frame, *params->mDirtyRegion, nsLayoutUtils::PaintFrame(rc, frame, *params->mDirtyRegion,
params->mBackgroundColor, params->mBackgroundColor,
nsLayoutUtils::PAINT_WIDGET_LAYERS); nsLayoutUtils::PAINT_WIDGET_LAYERS);
@ -5844,12 +5845,13 @@ static void DrawThebesLayer(ThebesLayer* aLayer,
} }
NS_IMETHODIMP NS_IMETHODIMP
PresShell::Paint(nsIView* aDisplayRoot, PresShell::Paint(nsIView* aDisplayRoot,
nsIView* aViewToPaint, nsIView* aViewToPaint,
nsIWidget* aWidgetToPaint, nsIWidget* aWidgetToPaint,
const nsRegion& aDirtyRegion, const nsRegion& aDirtyRegion,
PRBool aPaintDefaultBackground, const nsIntRegion& aIntDirtyRegion,
PRBool aWillSendDidPaint) PRBool aPaintDefaultBackground,
PRBool aWillSendDidPaint)
{ {
#ifdef NS_FUNCTION_TIMER #ifdef NS_FUNCTION_TIMER
NS_TIME_FUNCTION_DECLARE_DOCURL; NS_TIME_FUNCTION_DECLARE_DOCURL;
@ -5893,14 +5895,10 @@ PresShell::Paint(nsIView* aDisplayRoot,
return NS_OK; return NS_OK;
} }
nsPoint offsetToRoot = aViewToPaint->GetOffsetTo(aDisplayRoot);
nsRegion dirtyRegion = aDirtyRegion;
dirtyRegion.MoveBy(offsetToRoot);
if (frame) { if (frame) {
// Defer invalidates that are triggered during painting, and discard // Defer invalidates that are triggered during painting, and discard
// invalidates of areas that are already being repainted. // invalidates of areas that are already being repainted.
frame->BeginDeferringInvalidatesForDisplayRoot(dirtyRegion); frame->BeginDeferringInvalidatesForDisplayRoot(aDirtyRegion);
} }
LayerManager* layerManager = aWidgetToPaint->GetLayerManager(); LayerManager* layerManager = aWidgetToPaint->GetLayerManager();
@ -5908,10 +5906,8 @@ PresShell::Paint(nsIView* aDisplayRoot,
layerManager->BeginTransaction(); layerManager->BeginTransaction();
nsRefPtr<ThebesLayer> root = layerManager->CreateThebesLayer(); nsRefPtr<ThebesLayer> root = layerManager->CreateThebesLayer();
nsIntRect dirtyRect = aDirtyRegion.GetBounds().
ToOutsidePixels(presContext->AppUnitsPerDevPixel());
if (root) { if (root) {
root->SetVisibleRegion(dirtyRect); root->SetVisibleRegion(aIntDirtyRegion);
layerManager->SetRoot(root); layerManager->SetRoot(root);
} }
if (!frame) { if (!frame) {
@ -5919,8 +5915,8 @@ PresShell::Paint(nsIView* aDisplayRoot,
} }
PaintParams params = PaintParams params =
{ frame, { frame,
offsetToRoot - aViewToPaint->ViewToWidgetOffset(), aDisplayRoot->GetOffsetToWidget(aWidgetToPaint),
&dirtyRegion, &aDirtyRegion,
bgcolor }; bgcolor };
layerManager->EndTransaction(DrawThebesLayer, &params); layerManager->EndTransaction(DrawThebesLayer, &params);

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

@ -47,8 +47,8 @@ class nsIRenderingContext;
class nsGUIEvent; class nsGUIEvent;
#define NS_IVIEWOBSERVER_IID \ #define NS_IVIEWOBSERVER_IID \
{ 0x8e69db48, 0x9d01, 0x4c0a, \ { 0xc5dfb460, 0x50fb, 0x483e, \
{ 0xb9, 0xea, 0xa4, 0x4b, 0xc5, 0x89, 0xc8, 0x63 } } { 0xb4, 0x22, 0x19, 0xb7, 0x20, 0x4f, 0xe2, 0xdc } }
class nsIViewObserver : public nsISupports class nsIViewObserver : public nsISupports
{ {
@ -57,11 +57,16 @@ public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IVIEWOBSERVER_IID) NS_DECLARE_STATIC_IID_ACCESSOR(NS_IVIEWOBSERVER_IID)
/* called when the observer needs to paint. This paints the entire /* called when the observer needs to paint. This paints the entire
* frame subtree rooted at the view, including frame subtrees from * frame subtree rooted at aViewToPaint, including frame subtrees from
* subdocuments. * subdocuments.
* @param aViewToPaint the view for the widget that is being painted * @param aViewToPaint the view for the widget that is being painted
* @param aDirtyRegion the region to be painted, in the coordinates of * @param aWidgetToPaint the widget that is being painted, the widget of
* aViewToPaint * aViewToPaint
* @param aDirtyRegion the region to be painted, in appunits of aDisplayRoot
* and relative to aDisplayRoot
* @param aIntDirtyRegion the region to be painted, in dev pixels, in the
* coordinates of aWidgetToPaint. This conveys the same information as
* aDirtyRegion but in a different format.
* @param aPaintDefaultBackground just paint the default background, * @param aPaintDefaultBackground just paint the default background,
* don't try to paint any content. This is set when the observer * don't try to paint any content. This is set when the observer
* needs to paint something, but the view tree is unstable, so it * needs to paint something, but the view tree is unstable, so it
@ -71,12 +76,13 @@ public:
* which is to paint some default background color over the dirty region. * which is to paint some default background color over the dirty region.
* @return error status * @return error status
*/ */
NS_IMETHOD Paint(nsIView* aDisplayRoot, NS_IMETHOD Paint(nsIView* aDisplayRoot,
nsIView* aViewToPaint, nsIView* aViewToPaint,
nsIWidget* aWidgetToPaint, nsIWidget* aWidgetToPaint,
const nsRegion& aDirtyRegion, const nsRegion& aDirtyRegion,
PRBool aPaintDefaultBackground, const nsIntRegion& aIntDirtyRegion,
PRBool aWillSendDidPaint) = 0; PRBool aPaintDefaultBackground,
PRBool aWillSendDidPaint) = 0;
/* called when the observer needs to handle an event /* called when the observer needs to handle an event
* @param aView - where to start processing the event; the root view, * @param aView - where to start processing the event; the root view,

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

@ -341,19 +341,17 @@ NS_IMETHODIMP nsViewManager::FlushDelayedResize()
return NS_OK; return NS_OK;
} }
static nsRegion ConvertDeviceRegionToAppRegion(const nsIntRegion& aIn, // Convert aIn from being relative to and in appunits of aFromView, to being
nsIDeviceContext* aContext) // relative to and in appunits of aToView.
static nsRegion ConvertRegionBetweenViews(const nsRegion& aIn,
nsView* aFromView,
nsView* aToView)
{ {
PRInt32 p2a = aContext->AppUnitsPerDevPixel(); nsRegion out = aIn;
out.MoveBy(aFromView->GetOffsetTo(aToView));
nsRegion out; out = out.ConvertAppUnitsRoundOut(
nsIntRegionRectIterator iter(aIn); aFromView->GetViewManager()->AppUnitsPerDevPixel(),
for (;;) { aToView->GetViewManager()->AppUnitsPerDevPixel());
const nsIntRect* r = iter.Next();
if (!r)
break;
out.Or(out, r->ToAppUnits(p2a));
}
return out; return out;
} }
@ -380,20 +378,21 @@ void nsViewManager::Refresh(nsView *aView, nsIWidget *aWidget,
const nsIntRegion& aRegion, const nsIntRegion& aRegion,
PRUint32 aUpdateFlags) PRUint32 aUpdateFlags)
{ {
NS_ASSERTION(aView == nsView::GetViewFor(aWidget), "view widget mismatch");
NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager");
if (! IsRefreshEnabled()) if (! IsRefreshEnabled())
return; return;
nsRect viewRect;
aView->GetDimensions(viewRect);
nsPoint vtowoffset = aView->ViewToWidgetOffset();
// damageRegion is the damaged area, in twips, relative to the view origin // damageRegion is the damaged area, in twips, relative to the view origin
nsRegion damageRegion = ConvertDeviceRegionToAppRegion(aRegion, mContext); nsRegion damageRegion = aRegion.ToAppUnits(AppUnitsPerDevPixel());
// move region from widget coordinates into view coordinates // move region from widget coordinates into view coordinates
damageRegion.MoveBy(viewRect.TopLeft() - vtowoffset); damageRegion.MoveBy(-aView->ViewToWidgetOffset());
if (damageRegion.IsEmpty()) { if (damageRegion.IsEmpty()) {
#ifdef DEBUG_roc #ifdef DEBUG_roc
nsRect viewRect;
aView->GetDimensions(viewRect);
nsRect damageRect = damageRegion.GetBounds(); nsRect damageRect = damageRegion.GetBounds();
printf("XXX Damage rectangle (%d,%d,%d,%d) does not intersect the widget's view (%d,%d,%d,%d)!\n", printf("XXX Damage rectangle (%d,%d,%d,%d) does not intersect the widget's view (%d,%d,%d,%d)!\n",
damageRect.x, damageRect.y, damageRect.width, damageRect.height, damageRect.x, damageRect.y, damageRect.width, damageRect.height,
@ -412,7 +411,7 @@ void nsViewManager::Refresh(nsView *aView, nsIWidget *aWidget,
nsAutoScriptBlocker scriptBlocker; nsAutoScriptBlocker scriptBlocker;
SetPainting(PR_TRUE); SetPainting(PR_TRUE);
RenderViews(aView, aWidget, damageRegion); RenderViews(aView, aWidget, damageRegion, aRegion, PR_FALSE, PR_FALSE);
SetPainting(PR_FALSE); SetPainting(PR_FALSE);
} }
@ -427,19 +426,26 @@ void nsViewManager::Refresh(nsView *aView, nsIWidget *aWidget,
// aRC and aRegion are in view coordinates // aRC and aRegion are in view coordinates
void nsViewManager::RenderViews(nsView *aView, nsIWidget *aWidget, void nsViewManager::RenderViews(nsView *aView, nsIWidget *aWidget,
const nsRegion& aRegion) const nsRegion& aRegion,
const nsIntRegion& aIntRegion,
PRBool aPaintDefaultBackground,
PRBool aWillSendDidPaint)
{ {
nsView* displayRoot = GetDisplayRootFor(aView); nsView* displayRoot = GetDisplayRootFor(aView);
// Make sure we call Paint from the view manager that owns displayRoot. // Make sure we call Paint from the view manager that owns displayRoot.
// (Bug 485275) // (Bug 485275)
nsViewManager* displayRootVM = displayRoot->GetViewManager(); nsViewManager* displayRootVM = displayRoot->GetViewManager();
if (displayRootVM && displayRootVM != this) { if (displayRootVM && displayRootVM != this) {
displayRootVM->RenderViews(aView, aWidget, aRegion); displayRootVM->
RenderViews(aView, aWidget, aRegion, aIntRegion, aPaintDefaultBackground,
aWillSendDidPaint);
return; return;
} }
if (mObserver) { if (mObserver) {
mObserver->Paint(displayRoot, aView, aWidget, aRegion, PR_FALSE, PR_FALSE); nsRegion region = ConvertRegionBetweenViews(aRegion, aView, displayRoot);
mObserver->Paint(displayRoot, aView, aWidget, region, aIntRegion,
aPaintDefaultBackground, aWillSendDidPaint);
} }
} }
@ -471,11 +477,10 @@ void nsViewManager::ProcessPendingUpdates(nsView* aView, PRBool aDoInvalidate)
nsView* nearestViewWithWidget = aView; nsView* nearestViewWithWidget = aView;
while (!nearestViewWithWidget->HasWidget() && while (!nearestViewWithWidget->HasWidget() &&
nearestViewWithWidget->GetParent()) { nearestViewWithWidget->GetParent()) {
nearestViewWithWidget = nearestViewWithWidget = nearestViewWithWidget->GetParent();
static_cast<nsView*>(nearestViewWithWidget->GetParent());
} }
nsRegion r = *dirtyRegion; nsRegion r =
r.MoveBy(aView->GetOffsetTo(nearestViewWithWidget)); ConvertRegionBetweenViews(*dirtyRegion, aView, nearestViewWithWidget);
nsViewManager* widgetVM = nearestViewWithWidget->GetViewManager(); nsViewManager* widgetVM = nearestViewWithWidget->GetViewManager();
widgetVM-> widgetVM->
UpdateWidgetArea(nearestViewWithWidget, UpdateWidgetArea(nearestViewWithWidget,
@ -538,6 +543,9 @@ nsViewManager::UpdateWidgetArea(nsView *aWidgetView, nsIWidget* aWidget,
const nsRegion &aDamagedRegion, const nsRegion &aDamagedRegion,
nsView* aIgnoreWidgetView) nsView* aIgnoreWidgetView)
{ {
NS_ASSERTION(aWidgetView->GetViewManager() == this,
"UpdateWidgetArea called on view we don't own");
#if 0 #if 0
nsRect dbgBounds = aDamagedRegion.GetBounds(); nsRect dbgBounds = aDamagedRegion.GetBounds();
printf("UpdateWidgetArea view:%X (%d) widget:%X region: %d, %d, %d, %d\n", printf("UpdateWidgetArea view:%X (%d) widget:%X region: %d, %d, %d, %d\n",
@ -607,11 +615,9 @@ nsViewManager::UpdateWidgetArea(nsView *aWidgetView, nsIWidget* aWidget,
// manager trees // manager trees
nsViewManager* viewManager = view->GetViewManager(); nsViewManager* viewManager = view->GetViewManager();
if (viewManager->RootViewManager() == RootViewManager()) { if (viewManager->RootViewManager() == RootViewManager()) {
// get the damage region into view's coordinate system // get the damage region into view's coordinate system and appunits
nsRegion damage = intersection; nsRegion damage =
ConvertRegionBetweenViews(intersection, aWidgetView, view);
nsPoint offset = view->GetOffsetTo(aWidgetView);
damage.MoveBy(-offset);
// Update the child and it's children // Update the child and it's children
viewManager-> viewManager->
@ -714,6 +720,9 @@ void nsViewManager::UpdateViews(nsView *aView, PRUint32 aUpdateFlags)
NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
nsIView* aView, nsEventStatus *aStatus) nsIView* aView, nsEventStatus *aStatus)
{ {
NS_ASSERTION(!aView || static_cast<nsView*>(aView)->GetViewManager() == this,
"wrong view manager");
*aStatus = nsEventStatus_eIgnore; *aStatus = nsEventStatus_eIgnore;
switch(aEvent->message) switch(aEvent->message)
@ -754,8 +763,12 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
if (aEvent->message == NS_PAINT && event->region.IsEmpty()) if (aEvent->message == NS_PAINT && event->region.IsEmpty())
break; break;
// The rect is in device units, and it's in the coordinate space of its NS_ASSERTION(static_cast<nsView*>(aView) ==
// associated window. nsView::GetViewFor(event->widget),
"view/widget mismatch");
// The region is in device units, and it's in the coordinate space of
// its associated widget.
// Refresh the view // Refresh the view
if (IsRefreshEnabled()) { if (IsRefreshEnabled()) {
@ -834,10 +847,10 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
// since we got an NS_PAINT event, we need to // 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. // unless there's no widget or it's transparent.
nsRegion rgn = ConvertDeviceRegionToAppRegion(event->region, mContext); nsRegion rgn = event->region.ToAppUnits(AppUnitsPerDevPixel());
mObserver->Paint(aView, aView, event->widget, rgn, PR_TRUE, rgn.MoveBy(-aView->ViewToWidgetOffset());
event->willSendDidPaint); RenderViews(static_cast<nsView*>(aView), event->widget, rgn,
event->region, PR_TRUE, event->willSendDidPaint);
// Clients like the editor can trigger multiple // Clients like the editor can trigger multiple
// reflows during what the user perceives as a single // reflows during what the user perceives as a single
// edit operation, so it disables view manager // edit operation, so it disables view manager

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

@ -184,10 +184,14 @@ private:
void TriggerRefresh(PRUint32 aUpdateFlags); void TriggerRefresh(PRUint32 aUpdateFlags);
// aView is the view for aWidget and aRegion is relative to aWidget.
void Refresh(nsView *aView, nsIWidget *aWidget, void Refresh(nsView *aView, nsIWidget *aWidget,
const nsIntRegion& aRegion, PRUint32 aUpdateFlags); const nsIntRegion& aRegion, PRUint32 aUpdateFlags);
// aRootView is the view for aWidget, aRegion is relative to aRootView, and
// aIntRegion is relative to aWidget.
void RenderViews(nsView *aRootView, nsIWidget *aWidget, void RenderViews(nsView *aRootView, nsIWidget *aWidget,
const nsRegion& aRegion); const nsRegion& aRegion, const nsIntRegion& aIntRegion,
PRBool aPaintDefaultBackground, PRBool aWillSendDidPaint);
void InvalidateRectDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut, PRUint32 aUpdateFlags); void InvalidateRectDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut, PRUint32 aUpdateFlags);
void InvalidateHorizontalBandDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut, void InvalidateHorizontalBandDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut,