Bug 598482 part 18 - Separate NS_WILL_PAINT and NS_PAINT handling; only flush again if no NS_WILL_PAINT event has been sent by the platform. r=roc

This commit is contained in:
Markus Stange 2011-12-23 22:52:24 -05:00
Родитель 2eef95f959
Коммит 7e9c8ecff4
4 изменённых файлов: 46 добавлений и 52 удалений

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

@ -753,34 +753,20 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
break;
case NS_WILL_PAINT:
case NS_PAINT:
{
nsPaintEvent *event = static_cast<nsPaintEvent*>(aEvent);
if (!aView || !mContext)
break;
*aStatus = nsEventStatus_eConsumeNoDefault;
if (aEvent->message == NS_PAINT && event->region.IsEmpty())
break;
nsPaintEvent *event = static_cast<nsPaintEvent*>(aEvent);
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
NS_ASSERTION(IsPaintingAllowed(),
"shouldn't be receiving paint events while painting is "
"disallowed!");
nsRefPtr<nsViewManager> rootVM = RootViewManager();
// If an ancestor widget was hidden and then shown, we could
// have a delayed resize to handle.
bool didResize = false;
for (nsViewManager *vm = this; vm;
vm = vm->mRootView->GetParent()
? vm->mRootView->GetParent()->GetViewManager()
@ -789,47 +775,51 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
vm->mRootView->IsEffectivelyVisible() &&
mPresShell && mPresShell->IsVisible()) {
vm->FlushDelayedResize(true);
// Paint later.
vm->UpdateView(vm->mRootView);
didResize = true;
// not sure if it's valid for us to claim that we
// ignored this, but we're going to do so anyway, since
// we didn't actually paint anything
*aStatus = nsEventStatus_eIgnore;
}
}
if (!didResize) {
// Notify view observers that we're about to paint.
// Make sure to not send WillPaint notifications while scrolling.
nsCOMPtr<nsIWidget> widget;
rootVM->GetRootWidget(getter_AddRefs(widget));
bool transparentWindow = false;
if (widget)
transparentWindow = widget->GetTransparencyMode() == eTransparencyTransparent;
nsView* view = static_cast<nsView*>(aView);
if (!transparentWindow) {
if (mPresShell) {
rootVM->CallWillPaintOnObservers(event->willSendDidPaint);
// Get the view pointer again since the code above might have
// destroyed it (bug 378273).
view = nsView::GetViewFor(aEvent->widget);
}
}
// Make sure to sync up any widget geometry changes we
// have pending before we paint.
if (rootVM->mHasPendingUpdates) {
rootVM->ProcessPendingUpdatesForView(mRootView);
}
if (view && aEvent->message == NS_PAINT) {
Refresh(view, event->widget, event->region);
}
// Flush things like reflows and plugin widget geometry updates by
// calling WillPaint on observer presShells.
nsRefPtr<nsViewManager> rootVM = RootViewManager();
if (mPresShell) {
rootVM->CallWillPaintOnObservers(event->willSendDidPaint);
}
// Flush view widget geometry updates and invalidations.
rootVM->ProcessPendingUpdates();
}
break;
case NS_PAINT:
{
if (!aView || !mContext)
break;
*aStatus = nsEventStatus_eConsumeNoDefault;
nsPaintEvent *event = static_cast<nsPaintEvent*>(aEvent);
nsView* view = static_cast<nsView*>(aView);
NS_ASSERTION(view == nsView::GetViewFor(event->widget),
"view/widget mismatch");
NS_ASSERTION(IsPaintingAllowed(),
"shouldn't be receiving paint events while painting is "
"disallowed!");
if (!event->didSendWillPaint) {
// Send NS_WILL_PAINT event ourselves.
nsPaintEvent willPaintEvent(true, NS_WILL_PAINT, event->widget);
willPaintEvent.willSendDidPaint = event->willSendDidPaint;
DispatchEvent(&willPaintEvent, view, aStatus);
// Get the view pointer again since NS_WILL_PAINT might have
// destroyed it during CallWillPaintOnObservers (bug 378273).
view = nsView::GetViewFor(event->widget);
}
if (!view || event->region.IsEmpty())
break;
// Paint.
Refresh(view, event->widget, event->region);
break;
}

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

@ -2508,6 +2508,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
#endif
// Create the event so we can fill in its region
nsPaintEvent paintEvent(true, NS_PAINT, mGeckoChild);
paintEvent.didSendWillPaint = true;
nsIntRect boundingRect =
nsIntRect(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height);

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

@ -737,13 +737,15 @@ class nsPaintEvent : public nsGUIEvent
public:
nsPaintEvent(bool isTrusted, PRUint32 msg, nsIWidget *w)
: nsGUIEvent(isTrusted, msg, w, NS_PAINT_EVENT),
willSendDidPaint(false)
willSendDidPaint(false),
didSendWillPaint(false)
{
}
// area that needs repainting
nsIntRegion region;
bool willSendDidPaint;
bool didSendWillPaint;
};
/**

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

@ -312,6 +312,7 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32 aNestingLevel)
#endif
event.region = GetRegionToPaint(forceRepaint, ps, hDC);
event.willSendDidPaint = true;
event.didSendWillPaint = true;
if (!event.region.IsEmpty() && mEventCallback)
{