Bug 1463687 - Apply scrollbar style of root element to scrollbars of viewport. r?heycam
MozReview-Commit-ID: GWmhehtqO1U
--- 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,