зеркало из https://github.com/mozilla/pjs.git
Bug 563878. Part 12. Change the view observer interface and overhaul painting in view/. r=mats f=roc
This commit is contained in:
Родитель
b3aff69b2d
Коммит
afd4c534db
|
@ -817,6 +817,7 @@ public:
|
|||
nsIView* aViewToPaint,
|
||||
nsIWidget* aWidget,
|
||||
const nsRegion& aDirtyRegion,
|
||||
const nsIntRegion& aIntDirtyRegion,
|
||||
PRBool aPaintDefaultBackground,
|
||||
PRBool aWillSendDidPaint);
|
||||
NS_IMETHOD HandleEvent(nsIView* aView,
|
||||
|
@ -5828,7 +5829,7 @@ static void DrawThebesLayer(ThebesLayer* aLayer,
|
|||
if (NS_SUCCEEDED(rv)) {
|
||||
rc->Init(devCtx, aContext);
|
||||
nsIRenderingContext::AutoPushTranslation
|
||||
push(rc, -params->mOffsetToWidget.x, -params->mOffsetToWidget.y);
|
||||
push(rc, params->mOffsetToWidget.x, params->mOffsetToWidget.y);
|
||||
nsLayoutUtils::PaintFrame(rc, frame, *params->mDirtyRegion,
|
||||
params->mBackgroundColor,
|
||||
nsLayoutUtils::PAINT_WIDGET_LAYERS);
|
||||
|
@ -5848,6 +5849,7 @@ PresShell::Paint(nsIView* aDisplayRoot,
|
|||
nsIView* aViewToPaint,
|
||||
nsIWidget* aWidgetToPaint,
|
||||
const nsRegion& aDirtyRegion,
|
||||
const nsIntRegion& aIntDirtyRegion,
|
||||
PRBool aPaintDefaultBackground,
|
||||
PRBool aWillSendDidPaint)
|
||||
{
|
||||
|
@ -5893,14 +5895,10 @@ PresShell::Paint(nsIView* aDisplayRoot,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsPoint offsetToRoot = aViewToPaint->GetOffsetTo(aDisplayRoot);
|
||||
nsRegion dirtyRegion = aDirtyRegion;
|
||||
dirtyRegion.MoveBy(offsetToRoot);
|
||||
|
||||
if (frame) {
|
||||
// Defer invalidates that are triggered during painting, and discard
|
||||
// invalidates of areas that are already being repainted.
|
||||
frame->BeginDeferringInvalidatesForDisplayRoot(dirtyRegion);
|
||||
frame->BeginDeferringInvalidatesForDisplayRoot(aDirtyRegion);
|
||||
}
|
||||
|
||||
LayerManager* layerManager = aWidgetToPaint->GetLayerManager();
|
||||
|
@ -5908,10 +5906,8 @@ PresShell::Paint(nsIView* aDisplayRoot,
|
|||
|
||||
layerManager->BeginTransaction();
|
||||
nsRefPtr<ThebesLayer> root = layerManager->CreateThebesLayer();
|
||||
nsIntRect dirtyRect = aDirtyRegion.GetBounds().
|
||||
ToOutsidePixels(presContext->AppUnitsPerDevPixel());
|
||||
if (root) {
|
||||
root->SetVisibleRegion(dirtyRect);
|
||||
root->SetVisibleRegion(aIntDirtyRegion);
|
||||
layerManager->SetRoot(root);
|
||||
}
|
||||
if (!frame) {
|
||||
|
@ -5919,8 +5915,8 @@ PresShell::Paint(nsIView* aDisplayRoot,
|
|||
}
|
||||
PaintParams params =
|
||||
{ frame,
|
||||
offsetToRoot - aViewToPaint->ViewToWidgetOffset(),
|
||||
&dirtyRegion,
|
||||
aDisplayRoot->GetOffsetToWidget(aWidgetToPaint),
|
||||
&aDirtyRegion,
|
||||
bgcolor };
|
||||
layerManager->EndTransaction(DrawThebesLayer, ¶ms);
|
||||
|
||||
|
|
|
@ -47,8 +47,8 @@ class nsIRenderingContext;
|
|||
class nsGUIEvent;
|
||||
|
||||
#define NS_IVIEWOBSERVER_IID \
|
||||
{ 0x8e69db48, 0x9d01, 0x4c0a, \
|
||||
{ 0xb9, 0xea, 0xa4, 0x4b, 0xc5, 0x89, 0xc8, 0x63 } }
|
||||
{ 0xc5dfb460, 0x50fb, 0x483e, \
|
||||
{ 0xb4, 0x22, 0x19, 0xb7, 0x20, 0x4f, 0xe2, 0xdc } }
|
||||
|
||||
class nsIViewObserver : public nsISupports
|
||||
{
|
||||
|
@ -57,11 +57,16 @@ public:
|
|||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IVIEWOBSERVER_IID)
|
||||
|
||||
/* 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.
|
||||
* @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
|
||||
* @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,
|
||||
* 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
|
||||
|
@ -75,6 +80,7 @@ public:
|
|||
nsIView* aViewToPaint,
|
||||
nsIWidget* aWidgetToPaint,
|
||||
const nsRegion& aDirtyRegion,
|
||||
const nsIntRegion& aIntDirtyRegion,
|
||||
PRBool aPaintDefaultBackground,
|
||||
PRBool aWillSendDidPaint) = 0;
|
||||
|
||||
|
|
|
@ -341,19 +341,17 @@ NS_IMETHODIMP nsViewManager::FlushDelayedResize()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsRegion ConvertDeviceRegionToAppRegion(const nsIntRegion& aIn,
|
||||
nsIDeviceContext* aContext)
|
||||
// Convert aIn from being relative to and in appunits of aFromView, to being
|
||||
// relative to and in appunits of aToView.
|
||||
static nsRegion ConvertRegionBetweenViews(const nsRegion& aIn,
|
||||
nsView* aFromView,
|
||||
nsView* aToView)
|
||||
{
|
||||
PRInt32 p2a = aContext->AppUnitsPerDevPixel();
|
||||
|
||||
nsRegion out;
|
||||
nsIntRegionRectIterator iter(aIn);
|
||||
for (;;) {
|
||||
const nsIntRect* r = iter.Next();
|
||||
if (!r)
|
||||
break;
|
||||
out.Or(out, r->ToAppUnits(p2a));
|
||||
}
|
||||
nsRegion out = aIn;
|
||||
out.MoveBy(aFromView->GetOffsetTo(aToView));
|
||||
out = out.ConvertAppUnitsRoundOut(
|
||||
aFromView->GetViewManager()->AppUnitsPerDevPixel(),
|
||||
aToView->GetViewManager()->AppUnitsPerDevPixel());
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -380,20 +378,21 @@ void nsViewManager::Refresh(nsView *aView, nsIWidget *aWidget,
|
|||
const nsIntRegion& aRegion,
|
||||
PRUint32 aUpdateFlags)
|
||||
{
|
||||
NS_ASSERTION(aView == nsView::GetViewFor(aWidget), "view widget mismatch");
|
||||
NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager");
|
||||
|
||||
if (! IsRefreshEnabled())
|
||||
return;
|
||||
|
||||
nsRect viewRect;
|
||||
aView->GetDimensions(viewRect);
|
||||
nsPoint vtowoffset = aView->ViewToWidgetOffset();
|
||||
|
||||
// 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
|
||||
damageRegion.MoveBy(viewRect.TopLeft() - vtowoffset);
|
||||
damageRegion.MoveBy(-aView->ViewToWidgetOffset());
|
||||
|
||||
if (damageRegion.IsEmpty()) {
|
||||
#ifdef DEBUG_roc
|
||||
nsRect viewRect;
|
||||
aView->GetDimensions(viewRect);
|
||||
nsRect damageRect = damageRegion.GetBounds();
|
||||
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,
|
||||
|
@ -412,7 +411,7 @@ void nsViewManager::Refresh(nsView *aView, nsIWidget *aWidget,
|
|||
nsAutoScriptBlocker scriptBlocker;
|
||||
SetPainting(PR_TRUE);
|
||||
|
||||
RenderViews(aView, aWidget, damageRegion);
|
||||
RenderViews(aView, aWidget, damageRegion, aRegion, PR_FALSE, PR_FALSE);
|
||||
|
||||
SetPainting(PR_FALSE);
|
||||
}
|
||||
|
@ -427,19 +426,26 @@ void nsViewManager::Refresh(nsView *aView, nsIWidget *aWidget,
|
|||
|
||||
// aRC and aRegion are in view coordinates
|
||||
void nsViewManager::RenderViews(nsView *aView, nsIWidget *aWidget,
|
||||
const nsRegion& aRegion)
|
||||
const nsRegion& aRegion,
|
||||
const nsIntRegion& aIntRegion,
|
||||
PRBool aPaintDefaultBackground,
|
||||
PRBool aWillSendDidPaint)
|
||||
{
|
||||
nsView* displayRoot = GetDisplayRootFor(aView);
|
||||
// Make sure we call Paint from the view manager that owns displayRoot.
|
||||
// (Bug 485275)
|
||||
nsViewManager* displayRootVM = displayRoot->GetViewManager();
|
||||
if (displayRootVM && displayRootVM != this) {
|
||||
displayRootVM->RenderViews(aView, aWidget, aRegion);
|
||||
displayRootVM->
|
||||
RenderViews(aView, aWidget, aRegion, aIntRegion, aPaintDefaultBackground,
|
||||
aWillSendDidPaint);
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
while (!nearestViewWithWidget->HasWidget() &&
|
||||
nearestViewWithWidget->GetParent()) {
|
||||
nearestViewWithWidget =
|
||||
static_cast<nsView*>(nearestViewWithWidget->GetParent());
|
||||
nearestViewWithWidget = nearestViewWithWidget->GetParent();
|
||||
}
|
||||
nsRegion r = *dirtyRegion;
|
||||
r.MoveBy(aView->GetOffsetTo(nearestViewWithWidget));
|
||||
nsRegion r =
|
||||
ConvertRegionBetweenViews(*dirtyRegion, aView, nearestViewWithWidget);
|
||||
nsViewManager* widgetVM = nearestViewWithWidget->GetViewManager();
|
||||
widgetVM->
|
||||
UpdateWidgetArea(nearestViewWithWidget,
|
||||
|
@ -538,6 +543,9 @@ nsViewManager::UpdateWidgetArea(nsView *aWidgetView, nsIWidget* aWidget,
|
|||
const nsRegion &aDamagedRegion,
|
||||
nsView* aIgnoreWidgetView)
|
||||
{
|
||||
NS_ASSERTION(aWidgetView->GetViewManager() == this,
|
||||
"UpdateWidgetArea called on view we don't own");
|
||||
|
||||
#if 0
|
||||
nsRect dbgBounds = aDamagedRegion.GetBounds();
|
||||
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
|
||||
nsViewManager* viewManager = view->GetViewManager();
|
||||
if (viewManager->RootViewManager() == RootViewManager()) {
|
||||
// get the damage region into view's coordinate system
|
||||
nsRegion damage = intersection;
|
||||
|
||||
nsPoint offset = view->GetOffsetTo(aWidgetView);
|
||||
damage.MoveBy(-offset);
|
||||
// get the damage region into view's coordinate system and appunits
|
||||
nsRegion damage =
|
||||
ConvertRegionBetweenViews(intersection, aWidgetView, view);
|
||||
|
||||
// Update the child and it's children
|
||||
viewManager->
|
||||
|
@ -714,6 +720,9 @@ void nsViewManager::UpdateViews(nsView *aView, PRUint32 aUpdateFlags)
|
|||
NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
|
||||
nsIView* aView, nsEventStatus *aStatus)
|
||||
{
|
||||
NS_ASSERTION(!aView || static_cast<nsView*>(aView)->GetViewManager() == this,
|
||||
"wrong view manager");
|
||||
|
||||
*aStatus = nsEventStatus_eIgnore;
|
||||
|
||||
switch(aEvent->message)
|
||||
|
@ -754,8 +763,12 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
|
|||
if (aEvent->message == NS_PAINT && event->region.IsEmpty())
|
||||
break;
|
||||
|
||||
// The rect is in device units, and it's in the coordinate space of its
|
||||
// associated window.
|
||||
NS_ASSERTION(static_cast<nsView*>(aView) ==
|
||||
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
|
||||
if (IsRefreshEnabled()) {
|
||||
|
@ -834,10 +847,10 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
|
|||
// since we got an NS_PAINT event, we need to
|
||||
// draw something so we don't get blank areas,
|
||||
// unless there's no widget or it's transparent.
|
||||
nsRegion rgn = ConvertDeviceRegionToAppRegion(event->region, mContext);
|
||||
mObserver->Paint(aView, aView, event->widget, rgn, PR_TRUE,
|
||||
event->willSendDidPaint);
|
||||
|
||||
nsRegion rgn = event->region.ToAppUnits(AppUnitsPerDevPixel());
|
||||
rgn.MoveBy(-aView->ViewToWidgetOffset());
|
||||
RenderViews(static_cast<nsView*>(aView), event->widget, rgn,
|
||||
event->region, PR_TRUE, event->willSendDidPaint);
|
||||
// Clients like the editor can trigger multiple
|
||||
// reflows during what the user perceives as a single
|
||||
// edit operation, so it disables view manager
|
||||
|
|
|
@ -184,10 +184,14 @@ private:
|
|||
|
||||
void TriggerRefresh(PRUint32 aUpdateFlags);
|
||||
|
||||
// aView is the view for aWidget and aRegion is relative to aWidget.
|
||||
void Refresh(nsView *aView, nsIWidget *aWidget,
|
||||
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,
|
||||
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 InvalidateHorizontalBandDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut,
|
||||
|
|
Загрузка…
Ссылка в новой задаче