Commit befa15f5 authored by Markus Stange's avatar Markus Stange Committed by Georg Koppen
Browse files

Bug 1070710 - Use ViewRegion for vibrant areas in VibrancyManager. r=spohl

MozReview-Commit-ID: 5qVo59SV7QG

--HG--
extra : histedit_source : 12980052172b2a858a52978fdd98dea28a9ea854
parent 41141273
Loading
Loading
Loading
Loading
+4 −10
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include "nsClassHashtable.h"
#include "nsRegion.h"
#include "nsTArray.h"
#include "ViewRegion.h"

#import <Foundation/NSGeometry.h>

@@ -100,20 +101,13 @@ public:
   */
  static bool SystemSupportsVibrancy();

  // The following are only public because otherwise ClearVibrantRegionFunc
  // can't see them.
  struct VibrantRegion {
    LayoutDeviceIntRegion region;
    nsTArray<NSView*> effectViews;
  };
  void ClearVibrantRegion(const VibrantRegion& aVibrantRegion) const;

protected:
  NSView* CreateEffectView(VibrancyType aType, NSRect aRect);
  void ClearVibrantRegion(const LayoutDeviceIntRegion& aVibrantRegion) const;
  NSView* CreateEffectView(VibrancyType aType);

  const nsChildView& mCoordinateConverter;
  NSView* mContainerView;
  nsClassHashtable<nsUint32HashKey, VibrantRegion> mVibrantRegions;
  nsClassHashtable<nsUint32HashKey, ViewRegion> mVibrantRegions;
};

} // namespace mozilla
+14 −56
Original line number Diff line number Diff line
@@ -15,63 +15,25 @@ VibrancyManager::UpdateVibrantRegion(VibrancyType aType,
                                     const LayoutDeviceIntRegion& aRegion)
{
  auto& vr = *mVibrantRegions.LookupOrAdd(uint32_t(aType));
  if (vr.region == aRegion) {
    return;
  }

  // We need to construct the required region using as many EffectViews
  // as necessary. We try to update the geometry of existing views if
  // possible, or create new ones or remove old ones if the number of
  // rects in the region has changed.

  nsTArray<NSView*> viewsToRecycle;
  vr.effectViews.SwapElements(viewsToRecycle);
  // vr.effectViews is now empty.

  LayoutDeviceIntRegion::RectIterator iter(aRegion);
  const LayoutDeviceIntRect* iterRect = nullptr;
  for (size_t i = 0; (iterRect = iter.Next()) || i < viewsToRecycle.Length(); ++i) {
    if (iterRect) {
      NSView* view = nil;
      NSRect rect = mCoordinateConverter.DevPixelsToCocoaPoints(*iterRect);
      if (i < viewsToRecycle.Length()) {
        view = viewsToRecycle[i];
        [view setFrame:rect];
        [view setNeedsDisplay:YES];
      } else {
        view = CreateEffectView(aType, rect);
        [mContainerView addSubview:view];

        // Now that the view is in the view hierarchy, it'll be kept alive by
        // its superview, so we can drop our reference.
        [view release];
      }
      vr.effectViews.AppendElement(view);
    } else {
      // Our new region is made of less rects than the old region, so we can
      // remove this view. We only have a weak reference to it, so removing it
      // from the view hierarchy will release it.
      [viewsToRecycle[i] removeFromSuperview];
    }
  }

  vr.region = aRegion;
  vr.UpdateRegion(aRegion, mCoordinateConverter, mContainerView, ^() {
    return this->CreateEffectView(aType);
  });
}

void
VibrancyManager::ClearVibrantAreas() const
{
  for (auto iter = mVibrantRegions.ConstIter(); !iter.Done(); iter.Next()) {
    ClearVibrantRegion(*iter.UserData());
    ClearVibrantRegion(iter.UserData()->Region());
  }
}

void
VibrancyManager::ClearVibrantRegion(const VibrantRegion& aVibrantRegion) const
VibrancyManager::ClearVibrantRegion(const LayoutDeviceIntRegion& aVibrantRegion) const
{
  [[NSColor clearColor] set];

  LayoutDeviceIntRegion::RectIterator iter(aVibrantRegion.region);
  LayoutDeviceIntRegion::RectIterator iter(aVibrantRegion);
  while (const LayoutDeviceIntRect* rect = iter.Next()) {
    NSRectFill(mCoordinateConverter.DevPixelsToCocoaPoints(*rect));
  }
@@ -97,15 +59,13 @@ AdjustedColor(NSColor* aFillColor, VibrancyType aType)
NSColor*
VibrancyManager::VibrancyFillColorForType(VibrancyType aType)
{
  const nsTArray<NSView*>& views =
    mVibrantRegions.LookupOrAdd(uint32_t(aType))->effectViews;
  NSView* view = mVibrantRegions.LookupOrAdd(uint32_t(aType))->GetAnyView();

  if (!views.IsEmpty() &&
      [views[0] respondsToSelector:@selector(_currentFillColor)]) {
  if (view && [view respondsToSelector:@selector(_currentFillColor)]) {
    // -[NSVisualEffectView _currentFillColor] is the color that our view
    // would draw during its drawRect implementation, if we hadn't
    // disabled that.
    return AdjustedColor([views[0] _currentFillColor], aType);
    return AdjustedColor([view _currentFillColor], aType);
  }
  return [NSColor whiteColor];
}
@@ -117,12 +77,10 @@ VibrancyManager::VibrancyFillColorForType(VibrancyType aType)
NSColor*
VibrancyManager::VibrancyFontSmoothingBackgroundColorForType(VibrancyType aType)
{
  const nsTArray<NSView*>& views =
    mVibrantRegions.LookupOrAdd(uint32_t(aType))->effectViews;
  NSView* view = mVibrantRegions.LookupOrAdd(uint32_t(aType))->GetAnyView();

  if (!views.IsEmpty() &&
      [views[0] respondsToSelector:@selector(fontSmoothingBackgroundColor)]) {
    return [views[0] fontSmoothingBackgroundColor];
  if (view && [view respondsToSelector:@selector(fontSmoothingBackgroundColor)]) {
    return [view fontSmoothingBackgroundColor];
  }
  return [NSColor clearColor];
}
@@ -250,14 +208,14 @@ enum {
@end

NSView*
VibrancyManager::CreateEffectView(VibrancyType aType, NSRect aRect)
VibrancyManager::CreateEffectView(VibrancyType aType)
{
  static Class EffectViewClassWithoutForegroundVibrancy = CreateEffectViewClass(NO);
  static Class EffectViewClassWithForegroundVibrancy = CreateEffectViewClass(YES);

  Class EffectViewClass = HasVibrantForeground(aType)
    ? EffectViewClassWithForegroundVibrancy : EffectViewClassWithoutForegroundVibrancy;
  NSView* effectView = [[EffectViewClass alloc] initWithFrame:aRect];
  NSView* effectView = [[EffectViewClass alloc] initWithFrame:NSZeroRect];
  [effectView performSelector:@selector(setAppearance:)
                   withObject:AppearanceForVibrancyType(aType)];
  [effectView setState:VisualEffectStateForVibrancyType(aType)];