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 Maybe
<nsITheme::Transparency
> ScrollbarDrawingWin::GetScrollbarPartTransparency(
58 nsIFrame
* aFrame
, StyleAppearance aAppearance
) {
59 if (nsNativeTheme::IsWidgetScrollbarPart(aAppearance
)) {
60 if (ComputedStyle
* style
= GetCustomScrollbarStyle(aFrame
)) {
61 auto* ui
= style
->StyleUI();
62 if (ui
->mScrollbarColor
.IsAuto() ||
63 ui
->mScrollbarColor
.AsColors().track
.MaybeTransparent()) {
64 return Some(nsITheme::eTransparent
);
66 // These widgets may be thinner than the track, so we need to return
67 // transparent for them to make the track visible.
68 switch (aAppearance
) {
69 case StyleAppearance::ScrollbarthumbHorizontal
:
70 case StyleAppearance::ScrollbarthumbVertical
:
71 case StyleAppearance::ScrollbarbuttonUp
:
72 case StyleAppearance::ScrollbarbuttonDown
:
73 case StyleAppearance::ScrollbarbuttonLeft
:
74 case StyleAppearance::ScrollbarbuttonRight
:
75 return Some(nsITheme::eTransparent
);
80 if (aFrame
->PresContext()->UseOverlayScrollbars()) {
81 return Some(nsITheme::eTransparent
);
85 switch (aAppearance
) {
86 case StyleAppearance::ScrollbarHorizontal
:
87 case StyleAppearance::ScrollbarVertical
:
88 case StyleAppearance::Scrollcorner
:
89 case StyleAppearance::Statusbar
:
90 // Knowing that scrollbars and statusbars are opaque improves
91 // performance, because we create layers for them. This better be
92 // true across all Windows themes! If it's not true, we should
93 // paint an opaque background for them to make it true!
94 // TODO(emilio): Unclear how much this optimization matters in practice
95 // now we're in a WR-only world.
96 return Some(nsITheme::eOpaque
);
104 // Returns the style for custom scrollbar if the scrollbar part frame should
105 // use the custom drawing path, nullptr otherwise.
107 // Optionally the caller can pass a pointer to aDarkScrollbar for whether
108 // custom scrollbar may be drawn due to dark background.
110 ComputedStyle
* ScrollbarDrawingWin::GetCustomScrollbarStyle(
111 nsIFrame
* aFrame
, bool* aDarkScrollbar
) {
112 ComputedStyle
* style
= nsLayoutUtils::StyleForScrollbar(aFrame
);
113 if (style
->StyleUI()->HasCustomScrollbars()) {
116 bool useDarkScrollbar
= !StaticPrefs::widget_disable_dark_scrollbar() &&
117 nsNativeTheme::IsDarkBackground(aFrame
);
118 if (useDarkScrollbar
|| IsScrollbarWidthThin(*style
)) {
119 if (aDarkScrollbar
) {
120 *aDarkScrollbar
= useDarkScrollbar
;
127 template <typename PaintBackendData
>
128 bool ScrollbarDrawingWin::DoPaintScrollbarThumb(
129 PaintBackendData
& aPaintData
, const LayoutDeviceRect
& aRect
,
130 bool aHorizontal
, nsIFrame
* aFrame
, const ComputedStyle
& aStyle
,
131 const EventStates
& aElementState
, const EventStates
& 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
, bool aHorizontal
,
141 nsIFrame
* aFrame
, const ComputedStyle
& aStyle
,
142 const EventStates
& aElementState
, const EventStates
& aDocumentState
,
143 const Colors
& aColors
, const DPIRatio
& aDpiRatio
) {
144 return DoPaintScrollbarThumb(aDrawTarget
, aRect
, aHorizontal
, aFrame
, aStyle
,
145 aElementState
, aDocumentState
, aColors
,
149 bool ScrollbarDrawingWin::PaintScrollbarThumb(
150 WebRenderBackendData
& aWrData
, const LayoutDeviceRect
& aRect
,
151 bool aHorizontal
, nsIFrame
* aFrame
, const ComputedStyle
& aStyle
,
152 const EventStates
& aElementState
, const EventStates
& aDocumentState
,
153 const Colors
& aColors
, const DPIRatio
& aDpiRatio
) {
154 return DoPaintScrollbarThumb(aWrData
, aRect
, aHorizontal
, 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 mHorizontalScrollbarHeight
= mVerticalScrollbarWidth
= defaultSize
;
168 if (StaticPrefs::widget_non_native_theme_win_scrollbar_use_system_size()) {
169 mHorizontalScrollbarHeight
= LookAndFeel::GetInt(
170 LookAndFeel::IntID::SystemHorizontalScrollbarHeight
, defaultSize
);
171 mVerticalScrollbarWidth
= LookAndFeel::GetInt(
172 LookAndFeel::IntID::SystemVerticalScrollbarWidth
, defaultSize
);
176 } // namespace mozilla::widget