1 /* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "ScrollbarDrawingWin.h"
8 #include "mozilla/gfx/Helpers.h"
9 #include "mozilla/Maybe.h"
10 #include "mozilla/StaticPrefs_widget.h"
11 #include "nsLayoutUtils.h"
13 #include "nsNativeTheme.h"
15 namespace mozilla::widget
{
17 LayoutDeviceIntSize
ScrollbarDrawingWin::GetMinimumWidgetSize(
18 nsPresContext
* aPresContext
, StyleAppearance aAppearance
,
20 MOZ_ASSERT(nsNativeTheme::IsWidgetScrollbarPart(aAppearance
));
22 switch (aAppearance
) {
23 case StyleAppearance::ScrollbarbuttonUp
:
24 case StyleAppearance::ScrollbarbuttonDown
:
25 case StyleAppearance::ScrollbarbuttonLeft
:
26 case StyleAppearance::ScrollbarbuttonRight
:
27 // For scrollbar-width:thin, we don't display the buttons.
28 if (IsScrollbarWidthThin(aFrame
)) {
29 return LayoutDeviceIntSize
{};
32 case StyleAppearance::ScrollbarVertical
:
33 case StyleAppearance::ScrollbarHorizontal
:
34 case StyleAppearance::ScrollbarthumbVertical
:
35 case StyleAppearance::ScrollbarthumbHorizontal
: {
36 // TODO: for short scrollbars it could be nice if the thumb could shrink
38 auto relevantSize
= GetScrollbarSize(aPresContext
, aFrame
);
39 const bool isHorizontal
=
40 aAppearance
== StyleAppearance::ScrollbarHorizontal
||
41 aAppearance
== StyleAppearance::ScrollbarthumbHorizontal
||
42 aAppearance
== StyleAppearance::ScrollbarbuttonLeft
||
43 aAppearance
== StyleAppearance::ScrollbarbuttonRight
;
44 auto size
= LayoutDeviceIntSize
{relevantSize
, relevantSize
};
45 if (aAppearance
== StyleAppearance::ScrollbarHorizontal
||
46 aAppearance
== StyleAppearance::ScrollbarVertical
) {
47 // Always reserve some space in the right direction. Historically we've
48 // reserved 2 times the size in the other axis (for the buttons).
49 // We do this even when painting thin scrollbars just for consistency,
50 // though there just one would probably do there.
60 return LayoutDeviceIntSize
{};
64 // Returns the style for custom scrollbar if the scrollbar part frame should
65 // use the custom drawing path, nullptr otherwise.
66 const ComputedStyle
* GetCustomScrollbarStyle(nsIFrame
* aFrame
) {
67 const ComputedStyle
* style
= nsLayoutUtils::StyleForScrollbar(aFrame
);
68 if (style
->StyleUI()->HasCustomScrollbars() ||
69 ScrollbarDrawing::IsScrollbarWidthThin(*style
)) {
72 bool useDarkScrollbar
= !StaticPrefs::widget_disable_dark_scrollbar() &&
73 nsNativeTheme::IsDarkBackgroundForScrollbar(aFrame
);
74 if (useDarkScrollbar
) {
80 Maybe
<nsITheme::Transparency
> ScrollbarDrawingWin::GetScrollbarPartTransparency(
81 nsIFrame
* aFrame
, StyleAppearance aAppearance
) {
82 if (nsNativeTheme::IsWidgetScrollbarPart(aAppearance
)) {
83 if (const ComputedStyle
* style
= GetCustomScrollbarStyle(aFrame
)) {
84 auto* ui
= style
->StyleUI();
85 if (ui
->mScrollbarColor
.IsAuto() ||
86 ui
->mScrollbarColor
.AsColors().track
.MaybeTransparent()) {
87 return Some(nsITheme::eTransparent
);
89 // These widgets may be thinner than the track, so we need to return
90 // transparent for them to make the track visible.
91 switch (aAppearance
) {
92 case StyleAppearance::ScrollbarthumbHorizontal
:
93 case StyleAppearance::ScrollbarthumbVertical
:
94 case StyleAppearance::ScrollbarbuttonUp
:
95 case StyleAppearance::ScrollbarbuttonDown
:
96 case StyleAppearance::ScrollbarbuttonLeft
:
97 case StyleAppearance::ScrollbarbuttonRight
:
98 return Some(nsITheme::eTransparent
);
103 if (aFrame
->PresContext()->UseOverlayScrollbars()) {
104 return Some(nsITheme::eTransparent
);
108 switch (aAppearance
) {
109 case StyleAppearance::ScrollbarHorizontal
:
110 case StyleAppearance::ScrollbarVertical
:
111 case StyleAppearance::Scrollcorner
:
112 case StyleAppearance::Statusbar
:
113 // Knowing that scrollbars and statusbars are opaque improves
114 // performance, because we create layers for them. This better be
115 // true across all Windows themes! If it's not true, we should
116 // paint an opaque background for them to make it true!
117 // TODO(emilio): Unclear how much this optimization matters in practice
118 // now we're in a WR-only world.
119 return Some(nsITheme::eOpaque
);
127 template <typename PaintBackendData
>
128 bool ScrollbarDrawingWin::DoPaintScrollbarThumb(
129 PaintBackendData
& aPaintData
, const LayoutDeviceRect
& aRect
,
130 ScrollbarKind aScrollbarKind
, nsIFrame
* aFrame
, const ComputedStyle
& aStyle
,
131 const ElementState
& aElementState
, const DocumentState
& aDocumentState
,
132 const Colors
& aColors
, const DPIRatio
& aDpiRatio
) {
133 sRGBColor thumbColor
= ComputeScrollbarThumbColor(
134 aFrame
, aStyle
, aElementState
, aDocumentState
, aColors
);
135 ThemeDrawing::FillRect(aPaintData
, aRect
, thumbColor
);
139 bool ScrollbarDrawingWin::PaintScrollbarThumb(
140 DrawTarget
& aDrawTarget
, const LayoutDeviceRect
& aRect
,
141 ScrollbarKind aScrollbarKind
, nsIFrame
* aFrame
, const ComputedStyle
& aStyle
,
142 const ElementState
& aElementState
, const DocumentState
& aDocumentState
,
143 const Colors
& aColors
, const DPIRatio
& aDpiRatio
) {
144 return DoPaintScrollbarThumb(aDrawTarget
, aRect
, aScrollbarKind
, aFrame
,
145 aStyle
, aElementState
, aDocumentState
, aColors
,
149 bool ScrollbarDrawingWin::PaintScrollbarThumb(
150 WebRenderBackendData
& aWrData
, const LayoutDeviceRect
& aRect
,
151 ScrollbarKind aScrollbarKind
, nsIFrame
* aFrame
, const ComputedStyle
& aStyle
,
152 const ElementState
& aElementState
, const DocumentState
& aDocumentState
,
153 const Colors
& aColors
, const DPIRatio
& aDpiRatio
) {
154 return DoPaintScrollbarThumb(aWrData
, aRect
, aScrollbarKind
, aFrame
, aStyle
,
155 aElementState
, aDocumentState
, aColors
,
159 void ScrollbarDrawingWin::RecomputeScrollbarParams() {
160 uint32_t defaultSize
= kDefaultWinScrollbarSize
;
161 uint32_t overrideSize
=
162 StaticPrefs::widget_non_native_theme_scrollbar_size_override();
163 if (overrideSize
> 0) {
164 defaultSize
= overrideSize
;
166 ConfigureScrollbarSize(defaultSize
);
168 if (StaticPrefs::widget_non_native_theme_win_scrollbar_use_system_size()) {
169 ConfigureScrollbarSize(LookAndFeel::GetInt(
170 LookAndFeel::IntID::SystemScrollbarSize
, defaultSize
));
174 } // namespace mozilla::widget