Commit 51d24514 authored by Markus Stange's avatar Markus Stange
Browse files

Bug 598482 part 18 - Separate NS_WILL_PAINT and NS_PAINT handling; only flush...

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
parent 8928064b
Loading
Loading
Loading
Loading
+41 −51
Original line number Diff line number Diff line
@@ -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) {
        // 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);
              // Get the view pointer again since the code above might have
              // destroyed it (bug 378273).
              view = nsView::GetViewFor(aEvent->widget);
        }
        // Flush view widget geometry updates and invalidations.
        rootVM->ProcessPendingUpdates();
      }
          // Make sure to sync up any widget geometry changes we
          // have pending before we paint.
          if (rootVM->mHasPendingUpdates) {
            rootVM->ProcessPendingUpdatesForView(mRootView);
      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 && aEvent->message == NS_PAINT) {
        if (!view || event->region.IsEmpty())
          break;

        // Paint.
        Refresh(view, event->widget, event->region);
          }
        }

        break;
      }
+3 −1
Original line number Diff line number Diff line
@@ -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;
};

/**
+1 −0
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -310,6 +310,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)
  {