Back out bug 1592739 due to multiple regressions (bug 1599366, bug 1601183, bug 1602193). a=backout
authorMarkus Stange <mstange@themasta.com>
Thu, 13 Feb 2020 14:26:51 +0000
changeset 575698 fee92a1f6d6ec6ea10f6c431439dfaea26e54baa
parent 575697 b844a7db6c64ad6d577d86a19b464fa5dc1f9367
child 575699 30f86efe77d8b6807d331a62cf8189b5a2dc7503
push id12693
push useraiakab@mozilla.com
push dateThu, 13 Feb 2020 15:14:04 +0000
treeherdermozilla-beta@30f86efe77d8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1592739, 1599366, 1601183, 1602193
milestone74.0
Back out bug 1592739 due to multiple regressions (bug 1599366, bug 1601183, bug 1602193). a=backout Differential Revision: https://phabricator.services.mozilla.com/D62753
browser/themes/osx/browser.css
gfx/layers/composite/LayerManagerComposite.cpp
gfx/src/nsITheme.h
layout/base/PresShell.cpp
layout/painting/nsDisplayItemTypesList.h
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
widget/CompositorWidget.h
widget/InProcessCompositorWidget.cpp
widget/InProcessCompositorWidget.h
widget/cocoa/VibrancyManager.h
widget/cocoa/VibrancyManager.mm
widget/cocoa/nsChildView.h
widget/cocoa/nsChildView.mm
widget/cocoa/nsNativeThemeCocoa.h
widget/cocoa/nsNativeThemeCocoa.mm
widget/nsBaseWidget.h
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -69,16 +69,21 @@
   --tab-line-color: #0a84ff;
 }
 
 #navigator-toolbox toolbarbutton:-moz-lwtheme {
   color: inherit;
   text-shadow: inherit;
 }
 
+:root {
+  -moz-appearance: none;
+  background-color: #eeeeee;
+}
+
 /** Begin titlebar **/
 
 #titlebar {
   /* Centrally align content items vertically */
   -moz-box-pack: center;
 }
 
 .titlebar-button {
@@ -487,26 +492,19 @@
 
 #browser {
   --sidebar-border-color: hsla(240, 5%, 5%, .1);
 }
 
 #sidebar-box {
   /* Default font size is 11px on mac, so this is 12px */
   font-size: 1.0909rem;
-  --sidebar-background-color: -moz-mac-source-list;
 }
 
-/* Give the sidebar a vibrant -moz-appearance. Only do this when no lwtheme is
- * in use, because vibrant -moz-appearance values only work if there is no
- * background-color rendered behind the element, and we have :root:-moz-lwtheme
- * rules which set -moz-appearance: none and an opaque background color on the
- * root element. That background color would interfere with the vibrancy.
- * See bug 1594132 for fixing this. */
-#sidebar-box:not(:-moz-lwtheme) {
+#sidebar-box:not([lwt-sidebar]) {
   -moz-appearance: -moz-mac-source-list;
   -moz-font-smoothing-background-color: -moz-mac-source-list;
 }
 
 /* ----- CONTENT ----- */
 
 .browserContainer > findbar {
   background: @scopeBarBackground@;
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -1210,17 +1210,21 @@ bool LayerManagerComposite::Render(const
   {
     Diagnostics::Record record;
 
     if (usingNativeLayers) {
       // Update the placement of our native layers, so that transparent and
       // opaque parts of the window are covered by different layers and we can
       // update those parts separately.
       IntRegion opaqueRegion;
-      opaqueRegion.And(aOpaqueRegion, mRenderBounds);
+#ifdef XP_MACOSX
+      opaqueRegion =
+          mCompositor->GetWidget()->GetOpaqueWidgetRegion().ToUnknownRegion();
+#endif
+      opaqueRegion.AndWith(mRenderBounds);
 
       // Limit the complexity of these regions. Usually, opaqueRegion should be
       // only one or two rects, so this SimplifyInward call will not change the
       // region if everything looks as expected.
       opaqueRegion.SimplifyInward(4);
 
       IntRegion transparentRegion;
       transparentRegion.Sub(mRenderBounds, opaqueRegion);
--- a/gfx/src/nsITheme.h
+++ b/gfx/src/nsITheme.h
@@ -163,16 +163,21 @@ class nsITheme : public nsISupports {
 
   NS_IMETHOD ThemeChanged() = 0;
 
   virtual bool WidgetAppearanceDependsOnWindowFocus(
       StyleAppearance aWidgetType) {
     return false;
   }
 
+  virtual bool NeedToClearBackgroundBehindWidget(nsIFrame* aFrame,
+                                                 StyleAppearance aWidgetType) {
+    return false;
+  }
+
   /**
    * ThemeGeometryType values are used for describing themed nsIFrames in
    * calls to nsIWidget::UpdateThemeGeometries. We don't simply pass the
    * -moz-appearance value ("widget type") of the frame because the widget may
    * want to treat different frames with the same -moz-appearance differently
    * based on other properties of the frame. So we give the theme a first look
    * at the frame in nsITheme::ThemeGeometryTypeForWidget and pass the
    * returned ThemeGeometryType along to the widget.
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -5071,26 +5071,21 @@ void PresShell::UpdateCanvasBackground()
   nsIFrame* rootStyleFrame = FrameConstructor()->GetRootElementStyleFrame();
   if (rootStyleFrame) {
     ComputedStyle* bgStyle =
         nsCSSRendering::FindRootFrameBackground(rootStyleFrame);
     // XXX We should really be passing the canvasframe, not the root element
     // style frame but we don't have access to the canvasframe here. It isn't
     // a problem because only a few frames can return something other than true
     // and none of them would be a canvas frame or root element style frame.
-    bool drawBackgroundImage = false;
-    bool drawBackgroundColor = false;
-    if (rootStyleFrame->IsThemed()) {
-      // Ignore the CSS background-color if -moz-appearance is used.
-      mCanvasBackgroundColor = NS_RGBA(0, 0, 0, 0);
-    } else {
-      mCanvasBackgroundColor = nsCSSRendering::DetermineBackgroundColor(
-          mPresContext, bgStyle, rootStyleFrame, drawBackgroundImage,
-          drawBackgroundColor);
-    }
+    bool drawBackgroundImage;
+    bool drawBackgroundColor;
+    mCanvasBackgroundColor = nsCSSRendering::DetermineBackgroundColor(
+        mPresContext, bgStyle, rootStyleFrame, drawBackgroundImage,
+        drawBackgroundColor);
     mHasCSSBackgroundColor = drawBackgroundColor;
     if (mPresContext->IsRootContentDocumentCrossProcess() &&
         !IsTransparentContainerElement(mPresContext)) {
       mCanvasBackgroundColor = NS_ComposeColors(
           GetDefaultBackgroundColorToDraw(), mCanvasBackgroundColor);
     }
   }
 
--- a/layout/painting/nsDisplayItemTypesList.h
+++ b/layout/painting/nsDisplayItemTypesList.h
@@ -29,16 +29,17 @@ DECLARE_DISPLAY_ITEM_TYPE(CANVAS_BACKGRO
 DECLARE_DISPLAY_ITEM_TYPE(CANVAS_FOCUS, TYPE_RENDERS_NO_IMAGES)
 DECLARE_DISPLAY_ITEM_TYPE(CANVAS_THEMED_BACKGROUND,
                           TYPE_RENDERS_NO_IMAGES | TYPE_IS_CONTENTFUL)
 DECLARE_DISPLAY_ITEM_TYPE(CARET, TYPE_RENDERS_NO_IMAGES | TYPE_IS_CONTENTFUL)
 DECLARE_DISPLAY_ITEM_TYPE(CHECKED_CHECKBOX,
                           TYPE_RENDERS_NO_IMAGES | TYPE_IS_CONTENTFUL)
 DECLARE_DISPLAY_ITEM_TYPE(CHECKED_RADIOBUTTON,
                           TYPE_RENDERS_NO_IMAGES | TYPE_IS_CONTENTFUL)
+DECLARE_DISPLAY_ITEM_TYPE(CLEAR_BACKGROUND, TYPE_RENDERS_NO_IMAGES)
 DECLARE_DISPLAY_ITEM_TYPE(COLUMN_RULE, TYPE_RENDERS_NO_IMAGES)
 DECLARE_DISPLAY_ITEM_TYPE(COMBOBOX_FOCUS, TYPE_RENDERS_NO_IMAGES)
 DECLARE_DISPLAY_ITEM_TYPE(COMPOSITOR_HITTEST_INFO, TYPE_RENDERS_NO_IMAGES)
 DECLARE_DISPLAY_ITEM_TYPE(CONTAINER, TYPE_RENDERS_NO_IMAGES | TYPE_IS_CONTAINER)
 DECLARE_DISPLAY_ITEM_TYPE(EVENT_RECEIVER, TYPE_RENDERS_NO_IMAGES)
 DECLARE_DISPLAY_ITEM_TYPE(FIELDSET_BORDER_BACKGROUND, 0)
 DECLARE_DISPLAY_ITEM_TYPE(FILTER, TYPE_RENDERS_NO_IMAGES | TYPE_IS_CONTAINER)
 DECLARE_DISPLAY_ITEM_TYPE(FIXED_POSITION,
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -1366,17 +1366,17 @@ void nsDisplayListBuilder::SetGlassDispl
       mGlassDisplayItem = aItem;
       mGlassDisplayItem->SetIsGlassItem();
     }
   }
 }
 
 bool nsDisplayListBuilder::NeedToForceTransparentSurfaceForItem(
     nsDisplayItem* aItem) {
-  return aItem == mGlassDisplayItem;
+  return aItem == mGlassDisplayItem || aItem->ClearsBackground();
 }
 
 AnimatedGeometryRoot* nsDisplayListBuilder::WrapAGRForFrame(
     nsIFrame* aAnimatedGeometryRoot, bool aIsAsync,
     AnimatedGeometryRoot* aParent /* = nullptr */) {
   DebugOnly<bool> dummy;
   MOZ_ASSERT(IsAnimatedGeometryRoot(aAnimatedGeometryRoot, dummy) == AGR_YES);
 
@@ -4167,16 +4167,22 @@ bool nsDisplayBackgroundImage::AppendBac
     }
     if (bgItem) {
       bgItem->SetDependentFrame(aBuilder, dependentFrame);
       bgItemList.AppendToTop(bgItem);
     }
   }
 
   if (isThemed) {
+    nsITheme* theme = presContext->GetTheme();
+    if (theme->NeedToClearBackgroundBehindWidget(
+            aFrame, aFrame->StyleDisplay()->mAppearance) &&
+        aBuilder->IsInChromeDocumentOrPopup() && !aBuilder->IsInTransform()) {
+      bgItemList.AppendNewToTop<nsDisplayClearBackground>(aBuilder, aFrame);
+    }
     if (aSecondaryReferenceFrame) {
       nsDisplayTableThemedBackground* bgItem =
           MakeDisplayItem<nsDisplayTableThemedBackground>(
               aBuilder, aSecondaryReferenceFrame, bgRect, aFrame);
       if (bgItem) {
         bgItem->Init(aBuilder);
         bgItemList.AppendToTop(bgItem);
       }
@@ -5282,16 +5288,58 @@ void nsDisplayBackgroundColor::HitTest(n
 }
 
 void nsDisplayBackgroundColor::WriteDebugInfo(std::stringstream& aStream) {
   aStream << " (rgba " << mColor.r << "," << mColor.g << "," << mColor.b << ","
           << mColor.a << ")";
   aStream << " backgroundRect" << mBackgroundRect;
 }
 
+already_AddRefed<Layer> nsDisplayClearBackground::BuildLayer(
+    nsDisplayListBuilder* aBuilder, LayerManager* aManager,
+    const ContainerLayerParameters& aParameters) {
+  RefPtr<ColorLayer> layer = static_cast<ColorLayer*>(
+      aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this));
+  if (!layer) {
+    layer = aManager->CreateColorLayer();
+    if (!layer) {
+      return nullptr;
+    }
+  }
+  layer->SetColor(Color());
+  layer->SetMixBlendMode(gfx::CompositionOp::OP_SOURCE);
+
+  bool snap;
+  nsRect bounds = GetBounds(aBuilder, &snap);
+  int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
+  layer->SetBounds(bounds.ToNearestPixels(appUnitsPerDevPixel));  // XXX Do we
+                                                                  // need to
+                                                                  // respect the
+                                                                  // parent
+                                                                  // layer's
+                                                                  // scale here?
+
+  return layer.forget();
+}
+
+bool nsDisplayClearBackground::CreateWebRenderCommands(
+    mozilla::wr::DisplayListBuilder& aBuilder,
+    mozilla::wr::IpcResourceUpdateQueue& aResources,
+    const StackingContextHelper& aSc,
+    mozilla::layers::RenderRootStateManager* aManager,
+    nsDisplayListBuilder* aDisplayListBuilder) {
+  LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
+      nsRect(ToReferenceFrame(), mFrame->GetSize()),
+      mFrame->PresContext()->AppUnitsPerDevPixel());
+
+  aBuilder.PushClearRect(wr::ToLayoutRect(bounds));
+
+  return true;
+}
+
 nsRect nsDisplayOutline::GetBounds(nsDisplayListBuilder* aBuilder,
                                    bool* aSnap) const {
   *aSnap = false;
   return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
 }
 
 void nsDisplayOutline::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) {
   // TODO join outlines together
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -2744,16 +2744,18 @@ class nsDisplayItem : public nsDisplayIt
   /**
    * @return true if the contents of this item are rendered fixed relative
    * to the nearest viewport.
    */
   virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) const {
     return false;
   }
 
+  virtual bool ClearsBackground() const { return false; }
+
   /**
    * Returns true if all layers that can be active should be forced to be
    * active. Requires setting the pref layers.force-active=true.
    */
   static bool ForceActiveLayers();
 
   /**
    * @return LAYER_NONE if BuildLayer will return null. In this case
@@ -5077,16 +5079,59 @@ class nsDisplayTableBackgroundColor : pu
     return false;
   }
 
  protected:
   nsIFrame* mAncestorFrame;
   TableType mTableType;
 };
 
+class nsDisplayClearBackground : public nsPaintedDisplayItem {
+ public:
+  nsDisplayClearBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
+      : nsPaintedDisplayItem(aBuilder, aFrame) {}
+
+  NS_DISPLAY_DECL_NAME("ClearBackground", TYPE_CLEAR_BACKGROUND)
+
+  nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override {
+    *aSnap = true;
+    return nsRect(ToReferenceFrame(), Frame()->GetSize());
+  }
+
+  nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
+                           bool* aSnap) const override {
+    *aSnap = false;
+    return GetBounds(aBuilder, aSnap);
+  }
+
+  mozilla::Maybe<nscolor> IsUniform(
+      nsDisplayListBuilder* aBuilder) const override {
+    return mozilla::Some(NS_RGBA(0, 0, 0, 0));
+  }
+
+  bool ClearsBackground() const override { return true; }
+
+  LayerState GetLayerState(
+      nsDisplayListBuilder* aBuilder, LayerManager* aManager,
+      const ContainerLayerParameters& aParameters) override {
+    return mozilla::LayerState::LAYER_ACTIVE_FORCE;
+  }
+
+  already_AddRefed<Layer> BuildLayer(
+      nsDisplayListBuilder* aBuilder, LayerManager* aManager,
+      const ContainerLayerParameters& aContainerParameters) override;
+
+  bool CreateWebRenderCommands(
+      mozilla::wr::DisplayListBuilder& aBuilder,
+      mozilla::wr::IpcResourceUpdateQueue& aResources,
+      const StackingContextHelper& aSc,
+      mozilla::layers::RenderRootStateManager* aManager,
+      nsDisplayListBuilder* aDisplayListBuilder) override;
+};
+
 /**
  * The standard display item to paint the outer CSS box-shadows of a frame.
  */
 class nsDisplayBoxShadowOuter final : public nsPaintedDisplayItem {
  public:
   nsDisplayBoxShadowOuter(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
       : nsPaintedDisplayItem(aBuilder, aFrame), mOpacity(1.0f) {
     MOZ_COUNT_CTOR(nsDisplayBoxShadowOuter);
--- a/widget/CompositorWidget.h
+++ b/widget/CompositorWidget.h
@@ -226,16 +226,34 @@ class CompositorWidget {
   /**
    * Ensure end of composition to back buffer.
    *
    * Called by BasicCompositor on the compositor thread for OMTC drawing
    * after each composition to back buffer.
    */
   virtual already_AddRefed<gfx::SourceSurface> EndBackBufferDrawing();
 
+#ifdef XP_MACOSX
+  /**
+   * Return the opaque region of the widget. This is racy and can only be used
+   * on macOS, where the widget works around the raciness.
+   * Bug 1576491 tracks fixing this properly.
+   * The problem with this method is that it can return values "from the future"
+   * - the compositor might be working on frame N but the widget will return its
+   * opaque region from frame N + 1.
+   * It is believed that this won't lead to visible glitches on macOS due to the
+   * SuspendAsyncCATransactions call when the vibrant region changes or when the
+   * window resizes. Whenever the compositor uses an opaque region that's a
+   * frame ahead, the result it renders won't be shown on the screen; instead,
+   * the next composite will happen with the correct display list, and that's
+   * what's shown on the screen once the FlushRendering call completes.
+   */
+  virtual LayoutDeviceIntRegion GetOpaqueWidgetRegion() { return {}; }
+#endif
+
   /**
    * Observe or unobserve vsync.
    */
   virtual void ObserveVsync(VsyncObserver* aObserver) = 0;
 
   /**
    * Get the compositor options for the compositor associated with this
    * CompositorWidget.
--- a/widget/InProcessCompositorWidget.cpp
+++ b/widget/InProcessCompositorWidget.cpp
@@ -91,16 +91,22 @@ uint32_t InProcessCompositorWidget::GetG
 }
 
 uintptr_t InProcessCompositorWidget::GetWidgetKey() {
   return reinterpret_cast<uintptr_t>(mWidget);
 }
 
 nsIWidget* InProcessCompositorWidget::RealWidget() { return mWidget; }
 
+#ifdef XP_MACOSX
+LayoutDeviceIntRegion InProcessCompositorWidget::GetOpaqueWidgetRegion() {
+  return mWidget->GetOpaqueWidgetRegion();
+}
+#endif
+
 void InProcessCompositorWidget::ObserveVsync(VsyncObserver* aObserver) {
   if (RefPtr<CompositorVsyncDispatcher> cvd =
           mWidget->GetCompositorVsyncDispatcher()) {
     cvd->SetCompositorVsyncObserver(aObserver);
   }
 }
 
 }  // namespace widget
--- a/widget/InProcessCompositorWidget.h
+++ b/widget/InProcessCompositorWidget.h
@@ -28,16 +28,19 @@ class InProcessCompositorWidget : public
   virtual void EndRemoteDrawingInRegion(
       gfx::DrawTarget* aDrawTarget,
       const LayoutDeviceIntRegion& aInvalidRegion) override;
   virtual void CleanupRemoteDrawing() override;
   virtual void CleanupWindowEffects() override;
   virtual bool InitCompositor(layers::Compositor* aCompositor) override;
   virtual LayoutDeviceIntSize GetClientSize() override;
   virtual uint32_t GetGLFrameBufferFormat() override;
+#ifdef XP_MACOSX
+  virtual LayoutDeviceIntRegion GetOpaqueWidgetRegion() override;
+#endif
   virtual void ObserveVsync(VsyncObserver* aObserver) override;
   virtual uintptr_t GetWidgetKey() override;
 
   // If you can override this method, inherit from CompositorWidget instead.
   nsIWidget* RealWidget() override;
 
  protected:
   nsBaseWidget* mWidget;
--- a/widget/cocoa/VibrancyManager.h
+++ b/widget/cocoa/VibrancyManager.h
@@ -22,16 +22,17 @@ class nsChildView;
 namespace mozilla {
 
 enum class VibrancyType {
   LIGHT,
   DARK,
   TOOLTIP,
   MENU,
   HIGHLIGHTED_MENUITEM,
+  SHEET,
   SOURCE_LIST,
   SOURCE_LIST_SELECTION,
   ACTIVE_SOURCE_LIST_SELECTION
 };
 
 /**
  * VibrancyManager takes care of updating the vibrant regions of a window.
  * Vibrancy is a visual look that was introduced on OS X starting with 10.10.
--- a/widget/cocoa/VibrancyManager.mm
+++ b/widget/cocoa/VibrancyManager.mm
@@ -61,16 +61,17 @@ static Class CreateEffectViewClass(BOOL 
 
 static id AppearanceForVibrancyType(VibrancyType aType) {
   Class NSAppearanceClass = NSClassFromString(@"NSAppearance");
   switch (aType) {
     case VibrancyType::LIGHT:
     case VibrancyType::TOOLTIP:
     case VibrancyType::MENU:
     case VibrancyType::HIGHLIGHTED_MENUITEM:
+    case VibrancyType::SHEET:
     case VibrancyType::SOURCE_LIST:
     case VibrancyType::SOURCE_LIST_SELECTION:
     case VibrancyType::ACTIVE_SOURCE_LIST_SELECTION:
       return [NSAppearanceClass performSelector:@selector(appearanceNamed:)
                                      withObject:@"NSAppearanceNameVibrantLight"];
     case VibrancyType::DARK:
       return [NSAppearanceClass performSelector:@selector(appearanceNamed:)
                                      withObject:@"NSAppearanceNameVibrantDark"];
@@ -91,18 +92,20 @@ enum { NSVisualEffectMaterialTitlebar = 
 enum { NSVisualEffectMaterialMenu = 5, NSVisualEffectMaterialSidebar = 7 };
 #endif
 
 static NSUInteger VisualEffectStateForVibrancyType(VibrancyType aType) {
   switch (aType) {
     case VibrancyType::TOOLTIP:
     case VibrancyType::MENU:
     case VibrancyType::HIGHLIGHTED_MENUITEM:
-      // Tooltip and menu windows are never "key", so we need to tell the vibrancy effect to look
-      // active regardless of window state.
+    case VibrancyType::SHEET:
+      // Tooltip and menu windows are never "key" and sheets always looks
+      // active, so we need to tell the vibrancy effect to look active
+      // regardless of window state.
       return NSVisualEffectStateActive;
     default:
       return NSVisualEffectStateFollowsWindowActiveState;
   }
 }
 
 static BOOL HasVibrantForeground(VibrancyType aType) {
   switch (aType) {
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -424,18 +424,16 @@ class nsChildView final : public nsBaseW
   void HandleMainThreadCATransaction();
 
 #ifdef ACCESSIBILITY
   already_AddRefed<mozilla::a11y::Accessible> GetDocumentAccessible();
 #endif
 
   virtual void CreateCompositor() override;
 
-  virtual bool WidgetPaintsBackground() override { return true; }
-
   virtual bool PreRender(mozilla::widget::WidgetRenderingContext* aContext) override;
   virtual void PostRender(mozilla::widget::WidgetRenderingContext* aContext) override;
   virtual RefPtr<mozilla::layers::NativeLayerRoot> GetNativeLayerRoot() override;
 
   virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) override;
 
   virtual void UpdateWindowDraggingRegion(const LayoutDeviceIntRegion& aRegion) override;
   LayoutDeviceIntRegion GetNonDraggableRegion() { return mNonDraggableRegion.Region(); }
@@ -486,16 +484,18 @@ class nsChildView final : public nsBaseW
                                                nsString& aCommitted) override;
 
   virtual void SetPluginFocused(bool& aFocused) override;
 
   bool IsPluginFocused() { return mPluginFocused; }
 
   virtual LayoutDeviceIntPoint GetClientOffset() override;
 
+  virtual LayoutDeviceIntRegion GetOpaqueWidgetRegion() override;
+
   void DispatchAPZWheelInputEvent(mozilla::InputData& aEvent, bool aCanTriggerSwipe);
   nsEventStatus DispatchAPZInputEvent(mozilla::InputData& aEvent);
 
   void SwipeFinished();
 
   nsresult SetPrefersReducedMotionOverrideForTest(bool aValue) override;
   nsresult ResetPrefersReducedMotionOverrideForTest() override;
 
@@ -529,16 +529,18 @@ class nsChildView final : public nsBaseW
   }
 
   void ConfigureAPZCTreeManager() override;
   void ConfigureAPZControllerThread() override;
 
   void UpdateVibrancy(const nsTArray<ThemeGeometry>& aThemeGeometries);
   mozilla::VibrancyManager& EnsureVibrancyManager();
 
+  void UpdateInternalOpaqueRegion();
+
   nsIWidget* GetWidgetForListenerEvents();
 
   struct SwipeInfo {
     bool wantsSwipe;
     uint32_t allowedDirections;
   };
 
   SwipeInfo SendMayStartSwipe(const mozilla::PanGestureInput& aSwipeStartEvent);
@@ -590,16 +592,19 @@ class nsChildView final : public nsBaseW
   LayoutDeviceIntRegion mContentLayerInvalidRegion;
 
   mozilla::UniquePtr<mozilla::VibrancyManager> mVibrancyManager;
   RefPtr<mozilla::SwipeTracker> mSwipeTracker;
   mozilla::UniquePtr<mozilla::SwipeEventQueue> mSwipeEventQueue;
 
   RefPtr<mozilla::CancelableRunnable> mUnsuspendAsyncCATransactionsRunnable;
 
+  // The widget's opaque region. Written on the main thread, read on any thread.
+  mozilla::DataMutex<mozilla::LayoutDeviceIntRegion> mOpaqueRegion;
+
   // This flag is only used when APZ is off. It indicates that the current pan
   // gesture was processed as a swipe. Sometimes the swipe animation can finish
   // before momentum events of the pan gesture have stopped firing, so this
   // flag tells us that we shouldn't allow the remaining events to cause
   // scrolling. It is reset to false once a new gesture starts (as indicated by
   // a PANGESTURE_(MAY)START event).
   bool mCurrentPanGestureBelongsToSwipe;
 
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -231,16 +231,17 @@ nsChildView::nsChildView()
       mParentView(nil),
       mParentWidget(nullptr),
       mViewTearDownLock("ChildViewTearDown"),
       mBackingScaleFactor(0.0),
       mVisible(false),
       mDrawing(false),
       mIsDispatchPaint(false),
       mPluginFocused{false},
+      mOpaqueRegion("nsChildView::mOpaqueRegion"),
       mCurrentPanGestureBelongsToSwipe{false} {}
 
 nsChildView::~nsChildView() {
   if (mSwipeTracker) {
     mSwipeTracker->Destroy();
     mSwipeTracker = nullptr;
   }
 
@@ -492,16 +493,18 @@ nsTransparencyMode nsChildView::GetTrans
 void nsChildView::SetTransparencyMode(nsTransparencyMode aMode) {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   nsCocoaWindow* windowWidget = GetAppWindowWidget();
   if (windowWidget) {
     windowWidget->SetTransparencyMode(aMode);
   }
 
+  UpdateInternalOpaqueRegion();
+
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 void nsChildView::SuppressAnimation(bool aSuppress) {
   GetAppWindowWidget()->SuppressAnimation(aSuppress);
 }
 
 bool nsChildView::IsVisible() const {
@@ -1418,16 +1421,21 @@ LayoutDeviceIntPoint nsChildView::Widget
   FlipCocoaScreenCoordinate(origin);
 
   // convert to device pixels
   return CocoaPointsToDevPixels(origin);
 
   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntPoint(0, 0));
 }
 
+LayoutDeviceIntRegion nsChildView::GetOpaqueWidgetRegion() {
+  auto opaqueRegion = mOpaqueRegion.Lock();
+  return *opaqueRegion;
+}
+
 nsresult nsChildView::SetTitle(const nsAString& title) {
   // child views don't have titles
   return NS_OK;
 }
 
 nsresult nsChildView::GetAttention(int32_t aCycleCount) {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
@@ -1790,16 +1798,18 @@ static Maybe<VibrancyType> ThemeGeometry
     nsITheme::ThemeGeometryType aThemeGeometryType) {
   switch (aThemeGeometryType) {
     case nsNativeThemeCocoa::eThemeGeometryTypeVibrancyLight:
     case nsNativeThemeCocoa::eThemeGeometryTypeVibrantTitlebarLight:
       return Some(VibrancyType::LIGHT);
     case nsNativeThemeCocoa::eThemeGeometryTypeVibrancyDark:
     case nsNativeThemeCocoa::eThemeGeometryTypeVibrantTitlebarDark:
       return Some(VibrancyType::DARK);
+    case nsNativeThemeCocoa::eThemeGeometryTypeSheet:
+      return Some(VibrancyType::SHEET);
     case nsNativeThemeCocoa::eThemeGeometryTypeTooltip:
       return Some(VibrancyType::TOOLTIP);
     case nsNativeThemeCocoa::eThemeGeometryTypeMenu:
       return Some(VibrancyType::MENU);
     case nsNativeThemeCocoa::eThemeGeometryTypeHighlightedMenuItem:
       return Some(VibrancyType::HIGHLIGHTED_MENUITEM);
     case nsNativeThemeCocoa::eThemeGeometryTypeSourceList:
       return Some(VibrancyType::SOURCE_LIST);
@@ -1843,61 +1853,78 @@ static void MakeRegionsNonOverlapping(Re
   MakeRegionsNonOverlappingImpl(unionOfAll, aFirst, aRest...);
 }
 
 void nsChildView::UpdateVibrancy(const nsTArray<ThemeGeometry>& aThemeGeometries) {
   if (!VibrancyManager::SystemSupportsVibrancy()) {
     return;
   }
 
+  LayoutDeviceIntRegion sheetRegion = GatherVibrantRegion(aThemeGeometries, VibrancyType::SHEET);
   LayoutDeviceIntRegion vibrantLightRegion =
       GatherVibrantRegion(aThemeGeometries, VibrancyType::LIGHT);
   LayoutDeviceIntRegion vibrantDarkRegion =
       GatherVibrantRegion(aThemeGeometries, VibrancyType::DARK);
   LayoutDeviceIntRegion menuRegion = GatherVibrantRegion(aThemeGeometries, VibrancyType::MENU);
   LayoutDeviceIntRegion tooltipRegion =
       GatherVibrantRegion(aThemeGeometries, VibrancyType::TOOLTIP);
   LayoutDeviceIntRegion highlightedMenuItemRegion =
       GatherVibrantRegion(aThemeGeometries, VibrancyType::HIGHLIGHTED_MENUITEM);
   LayoutDeviceIntRegion sourceListRegion =
       GatherVibrantRegion(aThemeGeometries, VibrancyType::SOURCE_LIST);
   LayoutDeviceIntRegion sourceListSelectionRegion =
       GatherVibrantRegion(aThemeGeometries, VibrancyType::SOURCE_LIST_SELECTION);
   LayoutDeviceIntRegion activeSourceListSelectionRegion =
       GatherVibrantRegion(aThemeGeometries, VibrancyType::ACTIVE_SOURCE_LIST_SELECTION);
 
-  MakeRegionsNonOverlapping(vibrantLightRegion, vibrantDarkRegion, menuRegion, tooltipRegion,
-                            highlightedMenuItemRegion, sourceListRegion, sourceListSelectionRegion,
-                            activeSourceListSelectionRegion);
+  MakeRegionsNonOverlapping(sheetRegion, vibrantLightRegion, vibrantDarkRegion, menuRegion,
+                            tooltipRegion, highlightedMenuItemRegion, sourceListRegion,
+                            sourceListSelectionRegion, activeSourceListSelectionRegion);
 
   auto& vm = EnsureVibrancyManager();
   bool changed = false;
   changed |= vm.UpdateVibrantRegion(VibrancyType::LIGHT, vibrantLightRegion);
   changed |= vm.UpdateVibrantRegion(VibrancyType::DARK, vibrantDarkRegion);
   changed |= vm.UpdateVibrantRegion(VibrancyType::MENU, menuRegion);
   changed |= vm.UpdateVibrantRegion(VibrancyType::TOOLTIP, tooltipRegion);
   changed |= vm.UpdateVibrantRegion(VibrancyType::HIGHLIGHTED_MENUITEM, highlightedMenuItemRegion);
+  changed |= vm.UpdateVibrantRegion(VibrancyType::SHEET, sheetRegion);
   changed |= vm.UpdateVibrantRegion(VibrancyType::SOURCE_LIST, sourceListRegion);
   changed |= vm.UpdateVibrantRegion(VibrancyType::SOURCE_LIST_SELECTION, sourceListSelectionRegion);
   changed |= vm.UpdateVibrantRegion(VibrancyType::ACTIVE_SOURCE_LIST_SELECTION,
                                     activeSourceListSelectionRegion);
 
+  UpdateInternalOpaqueRegion();
+
   if (changed) {
     SuspendAsyncCATransactions();
   }
 }
 
 mozilla::VibrancyManager& nsChildView::EnsureVibrancyManager() {
   MOZ_ASSERT(mView, "Only call this once we have a view!");
   if (!mVibrancyManager) {
     mVibrancyManager = MakeUnique<VibrancyManager>(*this, [mView vibrancyViewsContainer]);
   }
   return *mVibrancyManager;
 }
 
+void nsChildView::UpdateInternalOpaqueRegion() {
+  MOZ_RELEASE_ASSERT(NS_IsMainThread(), "This should only be called on the main thread.");
+  auto opaqueRegion = mOpaqueRegion.Lock();
+  bool widgetIsOpaque = GetTransparencyMode() == eTransparencyOpaque;
+  if (!widgetIsOpaque) {
+    opaqueRegion->SetEmpty();
+  } else if (VibrancyManager::SystemSupportsVibrancy()) {
+    opaqueRegion->Sub(mBounds, EnsureVibrancyManager().GetUnionOfVibrantRegions());
+  } else {
+    *opaqueRegion = mBounds;
+  }
+}
+
 nsChildView::SwipeInfo nsChildView::SendMayStartSwipe(
     const mozilla::PanGestureInput& aSwipeStartEvent) {
   nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
 
   uint32_t direction = (aSwipeStartEvent.mPanDisplacement.x > 0.0)
                            ? (uint32_t)dom::SimpleGestureEvent_Binding::DIRECTION_RIGHT
                            : (uint32_t)dom::SimpleGestureEvent_Binding::DIRECTION_LEFT;
 
--- a/widget/cocoa/nsNativeThemeCocoa.h
+++ b/widget/cocoa/nsNativeThemeCocoa.h
@@ -38,16 +38,17 @@ class nsNativeThemeCocoa : private nsNat
     eThemeGeometryTypeFullscreenButton,
     eThemeGeometryTypeMenu,
     eThemeGeometryTypeHighlightedMenuItem,
     eThemeGeometryTypeVibrancyLight,
     eThemeGeometryTypeVibrancyDark,
     eThemeGeometryTypeVibrantTitlebarLight,
     eThemeGeometryTypeVibrantTitlebarDark,
     eThemeGeometryTypeTooltip,
+    eThemeGeometryTypeSheet,
     eThemeGeometryTypeSourceList,
     eThemeGeometryTypeSourceListSelection,
     eThemeGeometryTypeActiveSourceListSelection
   };
 
   enum class MenuIcon : uint8_t {
     eCheckmark,
     eMenuArrow,
@@ -414,16 +415,18 @@ class nsNativeThemeCocoa : private nsNat
                                 bool* aShouldRepaint, const nsAttrValue* aOldValue) override;
   NS_IMETHOD ThemeChanged() override;
   bool ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* aFrame,
                            StyleAppearance aAppearance) override;
   bool WidgetIsContainer(StyleAppearance aAppearance) override;
   bool ThemeDrawsFocusForWidget(StyleAppearance aAppearance) override;
   bool ThemeNeedsComboboxDropmarker() override;
   virtual bool WidgetAppearanceDependsOnWindowFocus(StyleAppearance aAppearance) override;
+  virtual bool NeedToClearBackgroundBehindWidget(nsIFrame* aFrame,
+                                                 StyleAppearance aAppearance) override;
   virtual ThemeGeometryType ThemeGeometryTypeForWidget(nsIFrame* aFrame,
                                                        StyleAppearance aAppearance) override;
   virtual Transparency GetWidgetTransparency(nsIFrame* aFrame,
                                              StyleAppearance aAppearance) override;
   mozilla::Maybe<WidgetInfo> ComputeWidgetInfo(nsIFrame* aFrame, StyleAppearance aAppearance,
                                                const nsRect& aRect);
   void DrawProgress(CGContextRef context, const HIRect& inBoxRect, const ProgressParams& aParams);
 
@@ -431,16 +434,17 @@ class nsNativeThemeCocoa : private nsNat
                                  CGFloat aUnifiedHeight, BOOL aIsMain, BOOL aIsFlipped);
 
  protected:
   virtual ~nsNativeThemeCocoa();
 
   LayoutDeviceIntMargin DirectionAwareMargin(const LayoutDeviceIntMargin& aMargin,
                                              nsIFrame* aFrame);
   nsIFrame* SeparatorResponsibility(nsIFrame* aBefore, nsIFrame* aAfter);
+  bool IsWindowSheet(nsIFrame* aFrame);
   ControlParams ComputeControlParams(nsIFrame* aFrame, mozilla::EventStates aEventState);
   MenuBackgroundParams ComputeMenuBackgroundParams(nsIFrame* aFrame,
                                                    mozilla::EventStates aEventState);
   MenuIconParams ComputeMenuIconParams(nsIFrame* aParams, mozilla::EventStates aEventState,
                                        MenuIcon aIcon);
   MenuItemParams ComputeMenuItemParams(nsIFrame* aFrame, mozilla::EventStates aEventState,
                                        bool aIsChecked);
   SegmentParams ComputeSegmentParams(nsIFrame* aFrame, mozilla::EventStates aEventState,
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -2685,16 +2685,25 @@ Maybe<nsNativeThemeCocoa::WidgetInfo> ns
     // Use high-resolution drawing.
     nativeWidgetRect.Scale(0.5f);
     originalHeight *= 0.5f;
   }
 
   EventStates eventState = GetContentState(aFrame, aAppearance);
 
   switch (aAppearance) {
+    case StyleAppearance::Dialog:
+      if (IsWindowSheet(aFrame)) {
+        if (VibrancyManager::SystemSupportsVibrancy()) {
+          return Nothing();
+        }
+        return Some(WidgetInfo::SheetBackground());
+      }
+      return Some(WidgetInfo::DialogBackground());
+
     case StyleAppearance::Menupopup:
       if (VibrancyManager::SystemSupportsVibrancy()) {
         return Nothing();
       }
       return Some(WidgetInfo::MenuBackground(ComputeMenuBackgroundParams(aFrame, eventState)));
 
     case StyleAppearance::Menuarrow:
       return Some(
@@ -3025,18 +3034,21 @@ Maybe<nsNativeThemeCocoa::WidgetInfo> ns
       if (VibrancyManager::SystemSupportsVibrancy()) {
         return Nothing();
       }
       return Some(WidgetInfo::SourceList(FrameIsInActiveWindow(aFrame)));
     }
 
     case StyleAppearance::MozMacSourceListSelection:
     case StyleAppearance::MozMacActiveSourceListSelection: {
-      // We only support vibrancy for source list selections if we're inside
-      // a source list.
+      // If we're in XUL tree, we need to rely on the source list's clear
+      // background display item. If we cleared the background behind the
+      // selections, the source list would not pick up the right font
+      // smoothing background. So, to simplify a bit, we only support vibrancy
+      // if we're in a source list.
       if (VibrancyManager::SystemSupportsVibrancy() && IsInSourceList(aFrame)) {
         return Nothing();
       }
       bool isInActiveWindow = FrameIsInActiveWindow(aFrame);
       if (aAppearance == StyleAppearance::MozMacActiveSourceListSelection) {
         return Some(WidgetInfo::ActiveSourceListSelection(isInActiveWindow));
       }
       return Some(WidgetInfo::InactiveSourceListSelection(isInActiveWindow));
@@ -3354,16 +3366,22 @@ bool nsNativeThemeCocoa::CreateWebRender
   //  - If the case in DrawWidgetBackground draws nothing for the given widget
   //    type, then don't list it here. We will hit the "default: return true;"
   //    case.
   //  - If the case in DrawWidgetBackground draws something simple for the given
   //    widget type, imitate that drawing using WebRender commands.
   //  - If the case in DrawWidgetBackground draws something complicated for the
   //    given widget type, return false here.
   switch (aAppearance) {
+    case StyleAppearance::Dialog:
+      if (IsWindowSheet(aFrame) && VibrancyManager::SystemSupportsVibrancy()) {
+        return true;
+      }
+      return false;
+
     case StyleAppearance::Menupopup:
       if (VibrancyManager::SystemSupportsVibrancy()) {
         return true;
       }
       return false;
 
     case StyleAppearance::Menuarrow:
     case StyleAppearance::Menuitem:
@@ -4255,16 +4273,52 @@ bool nsNativeThemeCocoa::WidgetAppearanc
     case StyleAppearance::Listbox:
     case StyleAppearance::Resizer:
       return false;
     default:
       return true;
   }
 }
 
+bool nsNativeThemeCocoa::IsWindowSheet(nsIFrame* aFrame) {
+  NSWindow* win = NativeWindowForFrame(aFrame);
+  id winDelegate = [win delegate];
+  nsIWidget* widget = [(WindowDelegate*)winDelegate geckoWidget];
+  if (!widget) {
+    return false;
+  }
+  return (widget->WindowType() == eWindowType_sheet);
+}
+
+bool nsNativeThemeCocoa::NeedToClearBackgroundBehindWidget(nsIFrame* aFrame,
+                                                           StyleAppearance aAppearance) {
+  switch (aAppearance) {
+    case StyleAppearance::MozMacSourceList:
+    // If we're in a XUL tree, we don't want to clear the background behind the
+    // selections below, since that would make our source list to not pick up
+    // the right font smoothing background. But since we don't call this method
+    // in nsTreeBodyFrame::BuildDisplayList, we never get here.
+    case StyleAppearance::MozMacSourceListSelection:
+    case StyleAppearance::MozMacActiveSourceListSelection:
+    case StyleAppearance::MozMacVibrancyLight:
+    case StyleAppearance::MozMacVibrancyDark:
+    case StyleAppearance::MozMacVibrantTitlebarLight:
+    case StyleAppearance::MozMacVibrantTitlebarDark:
+    case StyleAppearance::Tooltip:
+    case StyleAppearance::Menupopup:
+    case StyleAppearance::Menuitem:
+    case StyleAppearance::Checkmenuitem:
+      return true;
+    case StyleAppearance::Dialog:
+      return IsWindowSheet(aFrame);
+    default:
+      return false;
+  }
+}
+
 nsITheme::ThemeGeometryType nsNativeThemeCocoa::ThemeGeometryTypeForWidget(
     nsIFrame* aFrame, StyleAppearance aAppearance) {
   switch (aAppearance) {
     case StyleAppearance::MozWindowTitlebar:
       return eThemeGeometryTypeTitlebar;
     case StyleAppearance::Toolbar:
       return eThemeGeometryTypeToolbar;
     case StyleAppearance::Toolbox:
@@ -4287,16 +4341,18 @@ nsITheme::ThemeGeometryType nsNativeThem
       return eThemeGeometryTypeMenu;
     case StyleAppearance::Menuitem:
     case StyleAppearance::Checkmenuitem: {
       EventStates eventState = GetContentState(aFrame, aAppearance);
       bool isDisabled = IsDisabled(aFrame, eventState);
       bool isSelected = !isDisabled && CheckBooleanAttr(aFrame, nsGkAtoms::menuactive);
       return isSelected ? eThemeGeometryTypeHighlightedMenuItem : eThemeGeometryTypeMenu;
     }
+    case StyleAppearance::Dialog:
+      return IsWindowSheet(aFrame) ? eThemeGeometryTypeSheet : eThemeGeometryTypeUnknown;
     case StyleAppearance::MozMacSourceList:
       return eThemeGeometryTypeSourceList;
     case StyleAppearance::MozMacSourceListSelection:
       return IsInSourceList(aFrame) ? eThemeGeometryTypeSourceListSelection
                                     : eThemeGeometryTypeUnknown;
     case StyleAppearance::MozMacActiveSourceListSelection:
       return IsInSourceList(aFrame) ? eThemeGeometryTypeActiveSourceListSelection
                                     : eThemeGeometryTypeUnknown;
@@ -4305,18 +4361,20 @@ nsITheme::ThemeGeometryType nsNativeThem
   }
 }
 
 nsITheme::Transparency nsNativeThemeCocoa::GetWidgetTransparency(nsIFrame* aFrame,
                                                                  StyleAppearance aAppearance) {
   switch (aAppearance) {
     case StyleAppearance::Menupopup:
     case StyleAppearance::Tooltip:
+      return eTransparent;
+
     case StyleAppearance::Dialog:
-      return eTransparent;
+      return IsWindowSheet(aFrame) ? eTransparent : eOpaque;
 
     case StyleAppearance::ScrollbarSmall:
     case StyleAppearance::Scrollbar:
     case StyleAppearance::Scrollcorner: {
       // We don't use custom scrollbars when using overlay scrollbars.
       if (nsLookAndFeel::UseOverlayScrollbars()) {
         return eTransparent;
       }
--- a/widget/nsBaseWidget.h
+++ b/widget/nsBaseWidget.h
@@ -461,16 +461,19 @@ class nsBaseWidget : public nsIWidget, p
   }
   virtual void CleanupRemoteDrawing() {}
   virtual void CleanupWindowEffects() {}
   virtual bool InitCompositor(mozilla::layers::Compositor* aCompositor) {
     return true;
   }
   virtual uint32_t GetGLFrameBufferFormat();
   virtual bool CompositorInitiallyPaused() { return false; }
+#ifdef XP_MACOSX
+  virtual LayoutDeviceIntRegion GetOpaqueWidgetRegion() { return {}; }
+#endif
 
  protected:
   void ResolveIconName(const nsAString& aIconName, const nsAString& aIconSuffix,
                        nsIFile** aResult);
   virtual void OnDestroy();
   void BaseCreate(nsIWidget* aParent, nsWidgetInitData* aInitData);
 
   virtual void ConfigureAPZCTreeManager();