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 if ((aAppearance
== StyleAppearance::ScrollbarHorizontal
||
37 aAppearance
== StyleAppearance::ScrollbarVertical
) &&
38 !aPresContext
->UseOverlayScrollbars()) {
39 return LayoutDeviceIntSize
{};
41 // TODO: for short scrollbars it could be nice if the thumb could shrink
43 auto sizes
= GetScrollbarSizes(aPresContext
, aFrame
);
44 const bool isHorizontal
=
45 aAppearance
== StyleAppearance::ScrollbarHorizontal
||
46 aAppearance
== StyleAppearance::ScrollbarthumbHorizontal
||
47 aAppearance
== StyleAppearance::ScrollbarbuttonLeft
||
48 aAppearance
== StyleAppearance::ScrollbarbuttonRight
;
49 const auto size
= isHorizontal
? sizes
.mHorizontal
: sizes
.mVertical
;
50 return LayoutDeviceIntSize
{size
, size
};
53 return LayoutDeviceIntSize
{};
57 // Returns the style for custom scrollbar if the scrollbar part frame should
58 // use the custom drawing path, nullptr otherwise.
59 const ComputedStyle
* GetCustomScrollbarStyle(nsIFrame
* aFrame
) {
60 const ComputedStyle
* style
= nsLayoutUtils::StyleForScrollbar(aFrame
);
61 if (style
->StyleUI()->HasCustomScrollbars() ||
62 ScrollbarDrawing::IsScrollbarWidthThin(*style
)) {
65 bool useDarkScrollbar
= !StaticPrefs::widget_disable_dark_scrollbar() &&
66 nsNativeTheme::IsDarkBackgroundForScrollbar(aFrame
);
67 if (useDarkScrollbar
) {
73 Maybe
<nsITheme::Transparency
> ScrollbarDrawingWin::GetScrollbarPartTransparency(
74 nsIFrame
* aFrame
, StyleAppearance aAppearance
) {
75 if (nsNativeTheme::IsWidgetScrollbarPart(aAppearance
)) {
76 if (const ComputedStyle
* style
= GetCustomScrollbarStyle(aFrame
)) {
77 auto* ui
= style
->StyleUI();
78 if (ui
->mScrollbarColor
.IsAuto() ||
79 ui
->mScrollbarColor
.AsColors().track
.MaybeTransparent()) {
80 return Some(nsITheme::eTransparent
);
82 // These widgets may be thinner than the track, so we need to return
83 // transparent for them to make the track visible.
84 switch (aAppearance
) {
85 case StyleAppearance::ScrollbarthumbHorizontal
:
86 case StyleAppearance::ScrollbarthumbVertical
:
87 case StyleAppearance::ScrollbarbuttonUp
:
88 case StyleAppearance::ScrollbarbuttonDown
:
89 case StyleAppearance::ScrollbarbuttonLeft
:
90 case StyleAppearance::ScrollbarbuttonRight
:
91 return Some(nsITheme::eTransparent
);
96 if (aFrame
->PresContext()->UseOverlayScrollbars()) {
97 return Some(nsITheme::eTransparent
);
101 switch (aAppearance
) {
102 case StyleAppearance::ScrollbarHorizontal
:
103 case StyleAppearance::ScrollbarVertical
:
104 case StyleAppearance::Scrollcorner
:
105 case StyleAppearance::Statusbar
:
106 // Knowing that scrollbars and statusbars are opaque improves
107 // performance, because we create layers for them. This better be
108 // true across all Windows themes! If it's not true, we should
109 // paint an opaque background for them to make it true!
110 // TODO(emilio): Unclear how much this optimization matters in practice
111 // now we're in a WR-only world.
112 return Some(nsITheme::eOpaque
);
120 template <typename PaintBackendData
>
121 bool ScrollbarDrawingWin::DoPaintScrollbarThumb(
122 PaintBackendData
& aPaintData
, const LayoutDeviceRect
& aRect
,
123 ScrollbarKind aScrollbarKind
, nsIFrame
* aFrame
, const ComputedStyle
& aStyle
,
124 const ElementState
& aElementState
, const DocumentState
& aDocumentState
,
125 const Colors
& aColors
, const DPIRatio
& aDpiRatio
) {
126 sRGBColor thumbColor
= ComputeScrollbarThumbColor(
127 aFrame
, aStyle
, aElementState
, aDocumentState
, aColors
);
128 ThemeDrawing::FillRect(aPaintData
, aRect
, thumbColor
);
132 bool ScrollbarDrawingWin::PaintScrollbarThumb(
133 DrawTarget
& aDrawTarget
, const LayoutDeviceRect
& aRect
,
134 ScrollbarKind aScrollbarKind
, nsIFrame
* aFrame
, const ComputedStyle
& aStyle
,
135 const ElementState
& aElementState
, const DocumentState
& aDocumentState
,
136 const Colors
& aColors
, const DPIRatio
& aDpiRatio
) {
137 return DoPaintScrollbarThumb(aDrawTarget
, aRect
, aScrollbarKind
, aFrame
,
138 aStyle
, aElementState
, aDocumentState
, aColors
,
142 bool ScrollbarDrawingWin::PaintScrollbarThumb(
143 WebRenderBackendData
& aWrData
, const LayoutDeviceRect
& aRect
,
144 ScrollbarKind aScrollbarKind
, nsIFrame
* aFrame
, const ComputedStyle
& aStyle
,
145 const ElementState
& aElementState
, const DocumentState
& aDocumentState
,
146 const Colors
& aColors
, const DPIRatio
& aDpiRatio
) {
147 return DoPaintScrollbarThumb(aWrData
, aRect
, aScrollbarKind
, aFrame
, aStyle
,
148 aElementState
, aDocumentState
, aColors
,
152 void ScrollbarDrawingWin::RecomputeScrollbarParams() {
153 uint32_t defaultSize
= kDefaultWinScrollbarSize
;
154 uint32_t overrideSize
=
155 StaticPrefs::widget_non_native_theme_scrollbar_size_override();
156 if (overrideSize
> 0) {
157 defaultSize
= overrideSize
;
159 mHorizontalScrollbarHeight
= mVerticalScrollbarWidth
= defaultSize
;
161 if (StaticPrefs::widget_non_native_theme_win_scrollbar_use_system_size()) {
162 mHorizontalScrollbarHeight
= LookAndFeel::GetInt(
163 LookAndFeel::IntID::SystemHorizontalScrollbarHeight
, defaultSize
);
164 mVerticalScrollbarWidth
= LookAndFeel::GetInt(
165 LookAndFeel::IntID::SystemVerticalScrollbarWidth
, defaultSize
);
169 } // namespace mozilla::widget