Skip to content

Commit

Permalink
Bug 946658. r=tn
Browse files Browse the repository at this point in the history
  • Loading branch information
MatsPalmgren committed Mar 7, 2014
1 parent 1ffbeef commit 266bc9e
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 47 deletions.
5 changes: 5 additions & 0 deletions view/public/nsViewManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "nsCRT.h"
#include "nsVoidArray.h"
#include "nsDeviceContext.h"
#include "nsTArray.h"
#include "mozilla/EventForwards.h"

class nsIWidget;
Expand Down Expand Up @@ -327,6 +328,10 @@ class nsViewManager MOZ_FINAL

void ProcessPendingUpdatesForView(nsView *aView,
bool aFlushDirtyRegion = true);
void ProcessPendingUpdatesRecurse(nsView* aView,
nsTArray<nsCOMPtr<nsIWidget> >& aWidgets);
void ProcessPendingUpdatesPaint(nsIWidget* aWidget);

void FlushDirtyRegionToWidget(nsView* aView);
/**
* Call WillPaint() on all view observers under this vm root.
Expand Down
124 changes: 77 additions & 47 deletions view/src/nsViewManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,74 +366,104 @@ void nsViewManager::Refresh(nsView *aView, const nsIntRegion& aRegion)
}
}

void nsViewManager::ProcessPendingUpdatesForView(nsView* aView,
bool aFlushDirtyRegion)
void
nsViewManager::ProcessPendingUpdatesForView(nsView* aView,
bool aFlushDirtyRegion)
{
NS_ASSERTION(IsRootVM(), "Updates will be missed");

// Protect against a null-view.
nsViewManager* viewManager = aView ? aView->GetViewManager() : nullptr;
if (!aView || !viewManager) {
if (!aView) {
return;
}

nsIPresShell* presShell = viewManager->mPresShell;
if (presShell && presShell->IsNeverPainting()) {
return;
nsCOMPtr<nsIPresShell> rootShell(mPresShell);
nsTArray<nsCOMPtr<nsIWidget> > widgets;
aView->GetViewManager()->ProcessPendingUpdatesRecurse(aView, widgets);
for (uint32_t i = 0; i < widgets.Length(); ++i) {
nsView* view = nsView::GetViewFor(widgets[i]);
if (view) {
view->ResetWidgetBounds(false, true);
}
}
if (rootShell->GetViewManager() != this) {
return; // 'this' might have been destroyed
}
if (aFlushDirtyRegion) {
nsAutoScriptBlocker scriptBlocker;
SetPainting(true);
for (uint32_t i = 0; i < widgets.Length(); ++i) {
nsIWidget* widget = widgets[i];
nsView* view = nsView::GetViewFor(widget);
if (view) {
view->GetViewManager()->ProcessPendingUpdatesPaint(widget);
}
}
SetPainting(false);
}
}

if (aView->HasWidget()) {
aView->ResetWidgetBounds(false, true);
void
nsViewManager::ProcessPendingUpdatesRecurse(nsView* aView,
nsTArray<nsCOMPtr<nsIWidget> >& aWidgets)
{
if (mPresShell && mPresShell->IsNeverPainting()) {
return;
}

// process pending updates in child view.
for (nsView* childView = aView->GetFirstChild(); childView;
childView = childView->GetNextSibling()) {
ProcessPendingUpdatesForView(childView, aFlushDirtyRegion);
childView->GetViewManager()->
ProcessPendingUpdatesRecurse(childView, aWidgets);
}

// Push out updates after we've processed the children; ensures that
// damage is applied based on the final widget geometry
if (aFlushDirtyRegion) {
nsIWidget *widget = aView->GetWidget();
if (widget && widget->NeedsPaint()) {
// If an ancestor widget was hidden and then shown, we could
// have a delayed resize to handle.
for (nsViewManager *vm = viewManager; vm;
vm = vm->mRootView->GetParent()
? vm->mRootView->GetParent()->GetViewManager()
: nullptr) {
if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
vm->mRootView->IsEffectivelyVisible() &&
vm->mPresShell && vm->mPresShell->IsVisible()) {
vm->FlushDelayedResize(true);
}
nsIWidget* widget = aView->GetWidget();
if (widget) {
aWidgets.AppendElement(widget);
} else {
FlushDirtyRegionToWidget(aView);
}
}

void
nsViewManager::ProcessPendingUpdatesPaint(nsIWidget* aWidget)
{
if (aWidget->NeedsPaint()) {
// If an ancestor widget was hidden and then shown, we could
// have a delayed resize to handle.
for (nsViewManager *vm = this; vm;
vm = vm->mRootView->GetParent()
? vm->mRootView->GetParent()->GetViewManager()
: nullptr) {
if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
vm->mRootView->IsEffectivelyVisible() &&
vm->mPresShell && vm->mPresShell->IsVisible()) {
vm->FlushDelayedResize(true);
}
NS_ASSERTION(aView->HasWidget(), "FlushDelayedResize removed our widget!");
}
nsView* view = nsView::GetViewFor(aWidget);
if (!view) {
NS_ERROR("FlushDelayedResize destroyed the nsView?");
return;
}

if (presShell) {
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
printf_stderr("---- PAINT START ----PresShell(%p), nsView(%p), nsIWidget(%p)\n", presShell, aView, widget);
}
#endif
nsAutoScriptBlocker scriptBlocker;
SetPainting(true);
presShell->Paint(aView, nsRegion(), nsIPresShell::PAINT_LAYERS);
if (mPresShell) {
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
printf_stderr("---- PAINT END ----\n");
}
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
printf_stderr("---- PAINT START ----PresShell(%p), nsView(%p), nsIWidget(%p)\n",
mPresShell, view, aWidget);
}
#endif

aView->SetForcedRepaint(false);
SetPainting(false);
mPresShell->Paint(view, nsRegion(), nsIPresShell::PAINT_LAYERS);
view->SetForcedRepaint(false);

#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
printf_stderr("---- PAINT END ----\n");
}
viewManager->FlushDirtyRegionToWidget(aView);
} else {
viewManager->FlushDirtyRegionToWidget(aView);
#endif
}
}
FlushDirtyRegionToWidget(nsView::GetViewFor(aWidget));
}

void nsViewManager::FlushDirtyRegionToWidget(nsView* aView)
Expand Down

0 comments on commit 266bc9e

Please sign in to comment.