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 "ScrollbarDrawingWin11.h"
8 #include "mozilla/gfx/Helpers.h"
9 #include "mozilla/Maybe.h"
10 #include "mozilla/StaticPrefs_widget.h"
11 #include "nsLayoutUtils.h"
12 #include "nsNativeBasicTheme.h"
13 #include "nsNativeTheme.h"
15 namespace mozilla::widget
{
17 static LayoutDeviceIntCoord
CSSToScrollbarDeviceSize(
18 CSSCoord aCoord
, nsPresContext
* aPresContext
) {
19 return (aCoord
* ScrollbarDrawing::GetDPIRatioForScrollbarPart(aPresContext
))
23 LayoutDeviceIntSize
ScrollbarDrawingWin11::GetMinimumWidgetSize(
24 nsPresContext
* aPresContext
, StyleAppearance aAppearance
,
26 MOZ_ASSERT(nsNativeTheme::IsWidgetScrollbarPart(aAppearance
));
28 switch (aAppearance
) {
29 case StyleAppearance::ScrollbarbuttonUp
:
30 case StyleAppearance::ScrollbarbuttonDown
:
31 return LayoutDeviceIntSize
{GetVerticalScrollbarWidth(),
32 CSSToScrollbarDeviceSize(14, aPresContext
)};
33 case StyleAppearance::ScrollbarbuttonLeft
:
34 case StyleAppearance::ScrollbarbuttonRight
:
35 return LayoutDeviceIntSize
{CSSToScrollbarDeviceSize(14, aPresContext
),
36 GetHorizontalScrollbarHeight()};
38 return ScrollbarDrawingWin::GetMinimumWidgetSize(aPresContext
,
43 sRGBColor
ScrollbarDrawingWin11::ComputeScrollbarTrackColor(
44 nsIFrame
* aFrame
, const ComputedStyle
& aStyle
,
45 const EventStates
& aDocumentState
, const Colors
& aColors
) {
46 if (aColors
.HighContrast()) {
47 return ScrollbarDrawingWin::ComputeScrollbarTrackColor(
48 aFrame
, aStyle
, aDocumentState
, aColors
);
50 if (ShouldUseDarkScrollbar(aFrame
, aStyle
)) {
51 return sRGBColor::FromU8(23, 23, 23, 255);
53 const nsStyleUI
* ui
= aStyle
.StyleUI();
54 if (ui
->mScrollbarColor
.IsColors()) {
55 return sRGBColor::FromABGR(
56 ui
->mScrollbarColor
.AsColors().track
.CalcColor(aStyle
));
58 return sRGBColor::FromU8(240, 240, 240, 255);
61 sRGBColor
ScrollbarDrawingWin11::ComputeScrollbarThumbColor(
62 nsIFrame
* aFrame
, const ComputedStyle
& aStyle
,
63 const EventStates
& aElementState
, const EventStates
& aDocumentState
,
64 const Colors
& aColors
) {
65 if (aColors
.HighContrast()) {
66 return ScrollbarDrawingWin::ComputeScrollbarThumbColor(
67 aFrame
, aStyle
, aElementState
, aDocumentState
, aColors
);
69 if (ShouldUseDarkScrollbar(aFrame
, aStyle
)) {
70 return sRGBColor::FromU8(149, 149, 149, 255);
72 const nsStyleUI
* ui
= aStyle
.StyleUI();
73 if (ui
->mScrollbarColor
.IsColors()) {
74 return sRGBColor::FromABGR(ThemeColors::AdjustUnthemedScrollbarThumbColor(
75 ui
->mScrollbarColor
.AsColors().thumb
.CalcColor(aStyle
), aElementState
));
77 return sRGBColor::FromU8(133, 133, 133, 255);
80 std::pair
<sRGBColor
, sRGBColor
>
81 ScrollbarDrawingWin11::ComputeScrollbarButtonColors(
82 nsIFrame
* aFrame
, StyleAppearance aAppearance
, const ComputedStyle
& aStyle
,
83 const EventStates
& aElementState
, const EventStates
& aDocumentState
,
84 const Colors
& aColors
) {
85 if (aColors
.HighContrast()) {
86 return ScrollbarDrawingWin::ComputeScrollbarButtonColors(
87 aFrame
, aAppearance
, aStyle
, aElementState
, aDocumentState
, aColors
);
91 ComputeScrollbarTrackColor(aFrame
, aStyle
, aDocumentState
, aColors
);
92 sRGBColor arrowColor
= ComputeScrollbarThumbColor(
93 aFrame
, aStyle
, aElementState
, aDocumentState
, aColors
);
95 if (aElementState
.HasAtLeastOneOfStates(NS_EVENT_STATE_HOVER
|
96 NS_EVENT_STATE_ACTIVE
)) {
97 if (ShouldUseDarkScrollbar(aFrame
, aStyle
)) {
98 arrowColor
= sRGBColor::FromU8(205, 205, 205, 255);
100 arrowColor
= sRGBColor::FromU8(102, 102, 102, 255);
103 return {buttonColor
, arrowColor
};
106 bool ScrollbarDrawingWin11::PaintScrollbarButton(
107 DrawTarget
& aDrawTarget
, StyleAppearance aAppearance
,
108 const LayoutDeviceRect
& aRect
, nsIFrame
* aFrame
,
109 const ComputedStyle
& aStyle
, const EventStates
& aElementState
,
110 const EventStates
& aDocumentState
, const Colors
& aColors
) {
111 if (!ScrollbarDrawing::IsParentScrollbarHoveredOrActive(aFrame
)) {
115 auto [buttonColor
, arrowColor
] = ComputeScrollbarButtonColors(
116 aFrame
, aAppearance
, aStyle
, aElementState
, aDocumentState
, aColors
);
117 aDrawTarget
.FillRect(aRect
.ToUnknownRect(),
118 ColorPattern(ToDeviceColor(buttonColor
)));
120 // Start with Up arrow.
121 float arrowPolygonX
[] = {-5.5f
, 3.5f
, 3.5f
, -0.5f
, -1.5f
, -5.5f
, -5.5f
};
122 float arrowPolygonXActive
[] = {-5.0f
, 3.0f
, 3.0f
, -0.75f
,
123 -1.25f
, -5.0f
, -5.0f
};
124 float arrowPolygonXHover
[] = {-6.0f
, 4.0f
, 4.0f
, -0.25f
,
125 -1.75f
, -6.0f
, -6.0f
};
126 float arrowPolygonY
[] = {2.5f
, 2.5f
, 1.0f
, -4.0f
, -4.0f
, 1.0f
, 2.5f
};
127 float arrowPolygonYActive
[] = {2.0f
, 2.0f
, 0.5f
, -3.5f
, -3.5f
, 0.5f
, 2.0f
};
128 float arrowPolygonYHover
[] = {3.0f
, 3.0f
, 1.5f
, -4.5f
, -4.5f
, 1.5f
, 3.0f
};
129 float* arrowX
= arrowPolygonX
;
130 float* arrowY
= arrowPolygonY
;
131 const float offset
= aFrame
->GetWritingMode().IsPhysicalLTR() ? 1.5f
: -1.5f
;
132 const float kPolygonSize
= 17;
133 const int32_t arrowNumPoints
= ArrayLength(arrowPolygonX
);
135 if (aElementState
.HasState(NS_EVENT_STATE_ACTIVE
)) {
136 arrowX
= arrowPolygonXActive
;
137 arrowY
= arrowPolygonYActive
;
138 } else if (aElementState
.HasState(NS_EVENT_STATE_HOVER
)) {
139 arrowX
= arrowPolygonXHover
;
140 arrowY
= arrowPolygonYHover
;
143 switch (aAppearance
) {
144 case StyleAppearance::ScrollbarbuttonDown
:
145 for (int32_t i
= 0; i
< arrowNumPoints
; i
++) {
149 case StyleAppearance::ScrollbarbuttonUp
:
150 for (int32_t i
= 0; i
< arrowNumPoints
; i
++) {
154 case StyleAppearance::ScrollbarbuttonRight
:
155 for (int32_t i
= 0; i
< arrowNumPoints
; i
++) {
159 case StyleAppearance::ScrollbarbuttonLeft
:
160 std::swap(arrowX
, arrowY
);
166 ThemeDrawing::PaintArrow(aDrawTarget
, aRect
, arrowX
, arrowY
, kPolygonSize
,
167 arrowNumPoints
, arrowColor
);
171 template <typename PaintBackendData
>
172 bool ScrollbarDrawingWin11::DoPaintScrollbarThumb(
173 PaintBackendData
& aPaintData
, const LayoutDeviceRect
& aRect
,
174 bool aHorizontal
, nsIFrame
* aFrame
, const ComputedStyle
& aStyle
,
175 const EventStates
& aElementState
, const EventStates
& aDocumentState
,
176 const Colors
& aColors
, const DPIRatio
& aDpiRatio
) {
177 sRGBColor thumbColor
= ComputeScrollbarThumbColor(
178 aFrame
, aStyle
, aElementState
, aDocumentState
, aColors
);
180 LayoutDeviceRect
thumbRect(aRect
);
182 if (ScrollbarDrawing::IsParentScrollbarHoveredOrActive(aFrame
)) {
184 thumbRect
.height
= 6 * aDpiRatio
.scale
;
185 thumbRect
.y
+= 5 * aDpiRatio
.scale
;
187 thumbRect
.width
= 6 * aDpiRatio
.scale
;
188 if (aFrame
->GetWritingMode().IsPhysicalLTR()) {
189 thumbRect
.x
+= 6 * aDpiRatio
.scale
;
191 thumbRect
.x
+= 5 * aDpiRatio
.scale
;
194 LayoutDeviceCoord radius
=
195 (aHorizontal
? thumbRect
.height
: thumbRect
.width
) / 2.0f
;
197 MOZ_ASSERT(aRect
.Contains(thumbRect
));
199 ThemeDrawing::PaintRoundedRectWithRadius(aPaintData
, thumbRect
, thumbColor
,
200 sRGBColor(), 0, radius
/ aDpiRatio
,
206 thumbRect
.height
= 2 * aDpiRatio
.scale
;
207 thumbRect
.y
+= 7 * aDpiRatio
.scale
;
209 thumbRect
.width
= 2 * aDpiRatio
.scale
;
210 if (aFrame
->GetWritingMode().IsPhysicalLTR()) {
211 thumbRect
.x
+= 8 * aDpiRatio
.scale
;
213 thumbRect
.x
+= 7 * aDpiRatio
.scale
;
216 ThemeDrawing::FillRect(aPaintData
, thumbRect
, thumbColor
);
220 bool ScrollbarDrawingWin11::PaintScrollbarThumb(
221 DrawTarget
& aDrawTarget
, const LayoutDeviceRect
& aRect
, bool aHorizontal
,
222 nsIFrame
* aFrame
, const ComputedStyle
& aStyle
,
223 const EventStates
& aElementState
, const EventStates
& aDocumentState
,
224 const Colors
& aColors
, const DPIRatio
& aDpiRatio
) {
225 return DoPaintScrollbarThumb(aDrawTarget
, aRect
, aHorizontal
, aFrame
, aStyle
,
226 aElementState
, aDocumentState
, aColors
,
230 bool ScrollbarDrawingWin11::PaintScrollbarThumb(
231 WebRenderBackendData
& aWrData
, const LayoutDeviceRect
& aRect
,
232 bool aHorizontal
, nsIFrame
* aFrame
, const ComputedStyle
& aStyle
,
233 const EventStates
& aElementState
, const EventStates
& aDocumentState
,
234 const Colors
& aColors
, const DPIRatio
& aDpiRatio
) {
235 return DoPaintScrollbarThumb(aWrData
, aRect
, aHorizontal
, aFrame
, aStyle
,
236 aElementState
, aDocumentState
, aColors
,
240 } // namespace mozilla::widget