Bug 1463687 - Apply scrollbar style of root element to scrollbars of viewport. r?heycam draft
authorXidorn Quan <me@upsuper.org>
Thu, 24 May 2018 16:34:58 +1000
changeset 799638 7de9391de96f7d54324cb86b6ad9efbab0c79c19
parent 799618 4c8b152b4f8571fb1b9e418fddb55cd858259356
push id111138
push userxquan@mozilla.com
push dateFri, 25 May 2018 04:38:02 +0000
reviewersheycam
bugs1463687
milestone62.0a1
Bug 1463687 - Apply scrollbar style of root element to scrollbars of viewport. r?heycam MozReview-Commit-ID: GWmhehtqO1U
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
widget/windows/nsNativeThemeWin.cpp
widget/windows/nsNativeThemeWin.h
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -15,16 +15,17 @@
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/gfx/gfxVars.h"
 #include "mozilla/gfx/PathHelpers.h"
 #include "mozilla/layers/PAPZ.h"
 #include "mozilla/Likely.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/dom/ContentChild.h"
+#include "mozilla/ServoStyleSetInlines.h"
 #include "mozilla/StaticPrefs.h"
 #include "mozilla/Unused.h"
 #include "nsCharTraits.h"
 #include "nsDocument.h"
 #include "nsFontMetrics.h"
 #include "nsPresContext.h"
 #include "nsIContent.h"
 #include "nsFrameList.h"
@@ -10181,8 +10182,51 @@ nsLayoutUtils::ParseFontLanguageOverride
     }
     result = (result << 8) + ch;
   }
   while (index++ < 4) {
     result = (result << 8) + 0x20;
   }
   return result;
 }
+
+/* static */ ComputedStyle*
+nsLayoutUtils::StyleForScrollbar(nsIFrame* aScrollbarPart)
+{
+  // Get the closest non-native-anonymous content node, which should be
+  // the originating element of the scrollbar part. In theory we could
+  // have an XBL binding attached to NAC element, and that binding
+  // creates a scrollable element. It's unlikely we want to control the
+  // style of scrollbars from inside the binding, so that case is not
+  // considered below.
+  nsIContent* content = aScrollbarPart->GetContent();
+  // Note that the content may be a normal element with scrollbar part
+  // value specified for its -moz-appearance, so don't rely on it being
+  // a native anonymous.
+  MOZ_ASSERT(content, "No content for the scrollbar part?");
+  while (content && content->IsInNativeAnonymousSubtree()) {
+    content = content->GetParent();
+  }
+  MOZ_ASSERT(content, "Native anonymous element with no originating node?");
+  // Use the style from the primary frame of the content.
+  // Note: it is important to use the primary frame rather than an
+  // ancestor frame of the scrollbar part for the correct handling of
+  // viewport scrollbar. The content of the scroll frame of the viewport
+  // is the root element, but its style inherits from the viewport.
+  // Since we need to use the style of root element for the viewport
+  // scrollbar, we have to get the style from the primary frame.
+  if (nsIFrame* primaryFrame = content->GetPrimaryFrame()) {
+    return primaryFrame->Style();
+  }
+  // If the element doesn't have primary frame, get the computed style
+  // from the element directly. This can happen on viewport, because
+  // the scrollbar of viewport may be shown when the root element has
+  // > display: none; overflow: scroll;
+  nsPresContext* pc = aScrollbarPart->PresContext();
+  MOZ_ASSERT(content == pc->Document()->GetRootElement(),
+             "Root element is the only case for this fallback "
+             "path to be triggered");
+  RefPtr<ComputedStyle> style =
+    pc->StyleSet()->ResolveServoStyle(content->AsElement());
+  // Dropping the strong reference is fine because the style should be
+  // held strongly by the element.
+  return style.get();
+}
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -3106,16 +3106,22 @@ public:
                                     nscoord aPercentageBasis)
   {
     if (aGap.GetUnit() == eStyleUnit_Normal) {
       return nscoord(0);
     }
     return ResolveToLength<true>(aGap, aPercentageBasis);
   }
 
+  /**
+   * Get the computed style from which the scrollbar style should be
+   * used for the given scrollbar part frame.
+   */
+  static ComputedStyle* StyleForScrollbar(nsIFrame* aScrollbarPart);
+
 private:
   static uint32_t sFontSizeInflationEmPerLine;
   static uint32_t sFontSizeInflationMinTwips;
   static uint32_t sFontSizeInflationLineThreshold;
   static int32_t  sFontSizeInflationMappingIntercept;
   static uint32_t sFontSizeInflationMaxRatio;
   static bool sFontSizeInflationForceEnabled;
   static bool sFontSizeInflationDisabledInMasterProcess;
--- a/widget/windows/nsNativeThemeWin.cpp
+++ b/widget/windows/nsNativeThemeWin.cpp
@@ -14,16 +14,17 @@
 #include "nsSize.h"
 #include "nsTransform2D.h"
 #include "nsThemeConstants.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIContent.h"
 #include "nsIContentInlines.h"
 #include "nsIFrame.h"
+#include "nsLayoutUtils.h"
 #include "nsNameSpaceManager.h"
 #include "nsLookAndFeel.h"
 #include "nsMenuFrame.h"
 #include "nsGkAtoms.h"
 #include <malloc.h>
 #include "nsWindow.h"
 #include "nsIComboboxControlFrame.h"
 #include "prinrval.h"
@@ -1546,20 +1547,22 @@ IsWidgetScrollbarPart(uint8_t aWidgetTyp
 
 NS_IMETHODIMP
 nsNativeThemeWin::DrawWidgetBackground(gfxContext* aContext,
                                        nsIFrame* aFrame,
                                        uint8_t aWidgetType,
                                        const nsRect& aRect,
                                        const nsRect& aDirtyRect)
 {
-  if (aFrame->StyleUserInterface()->HasCustomScrollbars() &&
-      IsWidgetScrollbarPart(aWidgetType)) {
-    return DrawCustomScrollbarPart(aContext, aFrame, aWidgetType,
-                                   aRect, aDirtyRect);
+  if (IsWidgetScrollbarPart(aWidgetType)) {
+    ComputedStyle* style = nsLayoutUtils::StyleForScrollbar(aFrame);
+    if (style->StyleUserInterface()->HasCustomScrollbars()) {
+      return DrawCustomScrollbarPart(aContext, aFrame, style,
+                                     aWidgetType, aRect, aDirtyRect);
+    }
   }
 
   HANDLE theme = GetTheme(aWidgetType);
   if (!theme)
     return ClassicDrawWidgetBackground(aContext, aFrame, aWidgetType, aRect, aDirtyRect); 
 
   // ^^ without the right sdk, assume xp theming and fall through.
   if (nsUXThemeData::CheckForCompositor()) {
@@ -4258,29 +4261,29 @@ GetScrollbarArrowColor(nscolor aTrackCol
   }
   return NS_RGB(255, 255, 255);
 }
 
 // This tries to draw a Windows 10 style scrollbar with given colors.
 nsresult
 nsNativeThemeWin::DrawCustomScrollbarPart(gfxContext* aContext,
                                           nsIFrame* aFrame,
+                                          ComputedStyle* aStyle,
                                           uint8_t aWidgetType,
                                           const nsRect& aRect,
                                           const nsRect& aClipRect)
 {
-  ComputedStyle* style = aFrame->Style();
-  MOZ_ASSERT(!style->StyleUserInterface()->mScrollbarFaceColor.mIsAuto ||
-             !style->StyleUserInterface()->mScrollbarTrackColor.mIsAuto);
+  MOZ_ASSERT(!aStyle->StyleUserInterface()->mScrollbarFaceColor.mIsAuto ||
+             !aStyle->StyleUserInterface()->mScrollbarTrackColor.mIsAuto);
 
   gfxRect tr(aRect.X(), aRect.Y(), aRect.Width(), aRect.Height()),
           dr(aClipRect.X(), aClipRect.Y(),
              aClipRect.Width(), aClipRect.Height());
 
-  nscolor trackColor = GetScrollbarTrackColor(style);
+  nscolor trackColor = GetScrollbarTrackColor(aStyle);
   HBRUSH dcBrush = (HBRUSH) GetStockObject(DC_BRUSH);
 
   gfxFloat p2a = gfxFloat(aFrame->PresContext()->AppUnitsPerDevPixel());
   tr.Scale(1.0 / p2a);
   dr.Scale(1.0 / p2a);
 
   RefPtr<gfxContext> ctx = aContext;
 
@@ -4306,17 +4309,17 @@ nsNativeThemeWin::DrawCustomScrollbarPar
         gfxRect tr2 = tr;
         gfxFloat dev2css = round(AppUnitsPerCSSPixel() / p2a);
         if (aWidgetType == NS_THEME_SCROLLBARTHUMB_VERTICAL) {
           tr2.Deflate(dev2css, 0);
         } else {
           tr2.Deflate(0, dev2css);
         }
         nativeDrawing.TransformToNativeRect(tr2, widgetRect);
-        nscolor faceColor = GetScrollbarFaceColor(style);
+        nscolor faceColor = GetScrollbarFaceColor(aStyle);
         ::SetDCBrushColor(hdc, ToColorRef(faceColor));
         ::FillRect(hdc, &widgetRect, dcBrush);
         break;
       }
       case NS_THEME_SCROLLBARBUTTON_UP:
       case NS_THEME_SCROLLBARBUTTON_DOWN:
       case NS_THEME_SCROLLBARBUTTON_LEFT:
       case NS_THEME_SCROLLBARBUTTON_RIGHT: {
--- a/widget/windows/nsNativeThemeWin.h
+++ b/widget/windows/nsNativeThemeWin.h
@@ -111,16 +111,17 @@ protected:
   nsresult ClassicGetMinimumWidgetSize(nsIFrame* aFrame, uint8_t aWidgetType,
                                        mozilla::LayoutDeviceIntSize* aResult,
                                        bool* aIsOverridable);
   bool ClassicThemeSupportsWidget(nsIFrame* aFrame, uint8_t aWidgetType);
   void DrawCheckedRect(HDC hdc, const RECT& rc, int32_t fore, int32_t back,
                        HBRUSH defaultBack);
   nsresult DrawCustomScrollbarPart(gfxContext* aContext,
                                    nsIFrame* aFrame,
+                                   mozilla::ComputedStyle* aStyle,
                                    uint8_t aWidgetType,
                                    const nsRect& aRect,
                                    const nsRect& aClipRect);
   uint32_t GetWidgetNativeDrawingFlags(uint8_t aWidgetType);
   int32_t StandardGetState(nsIFrame* aFrame, uint8_t aWidgetType, bool wantFocused);
   bool IsMenuActive(nsIFrame* aFrame, uint8_t aWidgetType);
   RECT CalculateProgressOverlayRect(nsIFrame* aFrame, RECT* aWidgetRect,
                                     bool aIsVertical, bool aIsIndeterminate,