Commit 1b3f569e authored by Robert O'Callahan's avatar Robert O'Callahan
Browse files

Bug 339548. Part 3: Introduce native widget clip region API.

parent 16f8bf9a
Loading
Loading
Loading
Loading
+23 −18
Original line number Diff line number Diff line
@@ -542,7 +542,8 @@ void nsViewManager::AddCoveringWidgetsToOpaqueRegion(nsRegion &aRgn, nsIDeviceCo
  // We may be required to paint behind them
  aRgn.SetEmpty();

  nsIWidget* widget = aRootView->GetNearestWidget(nsnull);
  nsPoint offsetToWidget;
  nsIWidget* widget = aRootView->GetNearestWidget(&offsetToWidget);
  if (!widget) {
    return;
  }
@@ -557,24 +558,19 @@ void nsViewManager::AddCoveringWidgetsToOpaqueRegion(nsRegion &aRgn, nsIDeviceCo
    PRBool widgetVisible;
    childWidget->IsVisible(widgetVisible);
    if (widgetVisible) {
      nsTArray<nsIntRect> clipRects;
      childWidget->GetWindowClipRegion(&clipRects);

      nsView* view = nsView::GetViewFor(childWidget);
      if (view && view->GetVisibility() == nsViewVisibility_kShow
          && !view->GetFloating()) {
        nsRect bounds = view->GetBounds();
        if (bounds.width > 0 && bounds.height > 0) {
          nsView* viewParent = view->GetParent();
            
          while (viewParent && viewParent != aRootView) {
            viewParent->ConvertToParentCoords(&bounds.x, &bounds.y);
            viewParent = viewParent->GetParent();
          }
            
          // maybe we couldn't get the view into the coordinate
          // system of aRootView (maybe it's not a descendant
          // view of aRootView?); if so, don't use it
          if (viewParent) {
            aRgn.Or(aRgn, bounds);
          }
        nsIntRect bounds;
        childWidget->GetBounds(bounds);
        for (PRUint32 i = 0; i < clipRects.Length(); ++i) {
          nsIntRect r = clipRects[i] + bounds.TopLeft();
          nsRect rr = r.ToAppUnits(mContext->AppUnitsPerDevPixel()) -
            offsetToWidget;
          aRgn.Or(aRgn, rr);
        }
      }
    }
@@ -831,12 +827,21 @@ nsViewManager::UpdateWidgetArea(nsView *aWidgetView, const nsRegion &aDamagedReg
          nsPoint offset = view->GetOffsetTo(aWidgetView);
          damage.MoveBy(-offset);
          UpdateWidgetArea(view, damage, aIgnoreWidgetView);
          children.Or(children, view->GetDimensions() + offset);

          nsIntRect bounds;
          childWidget->GetBounds(bounds);
          nsTArray<nsIntRect> clipRects;
          childWidget->GetWindowClipRegion(&clipRects);
          for (PRUint32 i = 0; i < clipRects.Length(); ++i) {
            nsRect rr = (clipRects[i] + bounds.TopLeft()).
              ToAppUnits(mContext->AppUnitsPerDevPixel());
            children.Or(children, rr - aWidgetView->ViewToWidgetOffset()); 
            children.SimplifyInward(20);
          }
        }
      }
    }
  }

  nsRegion leftOver;
  leftOver.Sub(intersection, children);
+34 −3
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@
#include "nsITheme.h"
#include "nsNativeWidget.h"
#include "nsWidgetInitData.h"
#include "nsTArray.h"

// forward declarations
class   nsIAppShell;
@@ -100,10 +101,9 @@ typedef nsEventStatus (* EVENT_CALLBACK)(nsGUIEvent *event);
#define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102
#endif

// {a395289d-b344-42c3-ae7e-34d64282b6e0}
#define NS_IWIDGET_IID \
{ 0xa395289d, 0xb344, 0x42c3, \
  { 0xae, 0x7e, 0x34, 0xd6, 0x42, 0x82, 0xb6, 0xe0 } }
  { 0x8f0869be, 0x6a53, 0x4f21, \
    { 0xa9, 0x64, 0x90, 0xd9, 0x26, 0x04, 0x05, 0xa3 } }

/*
 * Window shadow styles
@@ -608,6 +608,37 @@ class nsIWidget : public nsISupports {
     */
    virtual nsTransparencyMode GetTransparencyMode() = 0;

    /**
     * This represents a command to set the bounds and clip region of
     * a child widget.
     */
    struct Configuration {
        nsIWidget* mChild;
        nsIntRect mBounds;
        nsTArray<nsIntRect> mClipRegion;
    };

    /**
     * Sets the clip region of each mChild (which must actually be a child
     * of this widget) to the union of the pixel rects given in
     * mClipRegion, all relative to the top-left of the child
     * widget. Clip regions are not implemented on all platforms and only
     * need to actually work for children that are plugins.
     * 
     * Also sets the bounds of each child to mBounds.
     * 
     * This will invalidate areas of the children that have changed, but
     * does not need to invalidate any part of this widget.
     */
    virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations) = 0;

    /**
     * Appends to aRects the rectangles constituting this widget's clip
     * region. If this widget is not clipped, appends a single rectangle
     * (0, 0, bounds.width, bounds.height).
     */
    virtual void GetWindowClipRegion(nsTArray<nsIntRect>* aRects) = 0;

    /**
     * Set the shadow style of the window.
     */
+6 −0
Original line number Diff line number Diff line
@@ -349,6 +349,7 @@ public:
  NS_IMETHOD              Validate();

  virtual void*           GetNativeData(PRUint32 aDataType);
  virtual nsresult        ConfigureChildren(const nsTArray<Configuration>& aConfigurations);
  NS_IMETHOD              Scroll(PRInt32 aDx, PRInt32 aDy, nsIntRect *aClipRect);
  virtual nsIntPoint      WidgetToScreenOffset();
  NS_IMETHOD              BeginResizingChildren(void);
@@ -416,6 +417,11 @@ public:
  static PRBool DoHasPendingInputEvent();
  static PRUint32 GetCurrentInputEventCount();
  static void UpdateCurrentInputEventCount();

  static void ApplyConfiguration(nsIWidget* aExpectedParent,
                                 const nsIWidget::Configuration& aConfiguration,
                                 PRBool aRepaint);

protected:

  PRBool            ReportDestroyEvent();
+46 −7
Original line number Diff line number Diff line
@@ -1259,12 +1259,26 @@ NS_IMETHODIMP nsChildView::GetPluginClipRect(nsIntRect& outClipRect, nsIntPoint&
  outClipRect.x = NSToIntRound(clipOrigin.x);
  outClipRect.y = NSToIntRound(clipOrigin.y);

  // need to convert view's origin to window coordinates.
  // then, encode as "SetOrigin" ready values.
  outOrigin.x = -NSToIntRound(viewOrigin.x);
  outOrigin.y = -NSToIntRound(viewOrigin.y);

  PRBool isVisible;
  IsVisible(isVisible);
  if (isVisible && [mView window] != nil) {
    outClipRect.width  = NSToIntRound(visibleBounds.origin.x + visibleBounds.size.width) - NSToIntRound(visibleBounds.origin.x);
    outClipRect.height = NSToIntRound(visibleBounds.origin.y + visibleBounds.size.height) - NSToIntRound(visibleBounds.origin.y);

    if (mClipRects) {
      nsIntRect clipBounds;
      for (PRUint32 i = 0; i < mClipRectCount; ++i) {
        clipBounds.UnionRect(clipBounds, mClipRects[i]);
      }
      outClipRect.IntersectRect(outClipRect, clipBounds - outOrigin);
    }

    // XXXroc should this be !outClipRect.IsEmpty()?
    outWidgetVisible = PR_TRUE;
  }
  else {
@@ -1273,11 +1287,6 @@ NS_IMETHODIMP nsChildView::GetPluginClipRect(nsIntRect& outClipRect, nsIntPoint&
    outWidgetVisible = PR_FALSE;
  }

  // need to convert view's origin to window coordinates.
  // then, encode as "SetOrigin" ready values.
  outOrigin.x = -NSToIntRound(viewOrigin.x);
  outOrigin.y = -NSToIntRound(viewOrigin.y);
  
  return NS_OK;

  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
@@ -1688,6 +1697,36 @@ NS_IMETHODIMP nsChildView::Update()

#pragma mark -

void nsChildView::ApplyConfiguration(nsIWidget* aExpectedParent,
                                     const nsIWidget::Configuration& aConfiguration,
                                     PRBool aRepaint)
{
#ifdef DEBUG
  nsWindowType kidType;
  aConfiguration.mChild->GetWindowType(kidType);
#endif
  NS_ASSERTION(kidType == eWindowType_child,
               "Configured widget is not a child type");
  NS_ASSERTION(aConfiguration.mChild->GetParent() == aExpectedParent,
               "Configured widget is not a child of the right widget");
  aConfiguration.mChild->Resize(
      aConfiguration.mBounds.x, aConfiguration.mBounds.y,
      aConfiguration.mBounds.width, aConfiguration.mBounds.height,
      aRepaint);
  // On Mac we don't use the clip region here, we just store it
  // in case GetPluginClipRect needs it.
  static_cast<nsChildView*>(aConfiguration.mChild)->
    StoreWindowClipRegion(aConfiguration.mClipRegion);
}

nsresult nsChildView::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
{
  for (PRUint32 i = 0; i < aConfigurations.Length(); ++i) {
    nsChildView::ApplyConfiguration(this, aConfigurations[i], PR_TRUE);
  }
  return NS_OK;
}  

// Scroll the bits of a view and its children
// FIXME: I'm sure the invalidating can be optimized, just no time now.
NS_IMETHODIMP nsChildView::Scroll(PRInt32 aDx, PRInt32 aDy, nsIntRect *aClipRect)
+1 −0
Original line number Diff line number Diff line
@@ -226,6 +226,7 @@ public:
    NS_IMETHOD Invalidate(const nsIntRect &aRect, PRBool aIsSynchronous);
    NS_IMETHOD Invalidate(PRBool aIsSynchronous);
    NS_IMETHOD Update();
    virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations);
    NS_IMETHOD Scroll(PRInt32 aDx, PRInt32 aDy, nsIntRect *alCipRect) { return NS_OK; }
    NS_IMETHOD BeginResizingChildren(void) { return NS_OK; }
    NS_IMETHOD EndResizingChildren(void) { return NS_OK; }
Loading