Bug 1833854 - Part 6: Round requested nursery before checking range when changing...
[gecko.git] / widget / ScrollbarDrawingWin.cpp
blobf516f694cb9233c04d9130ce5415f491f450da92
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"
12 #include "Theme.h"
13 #include "nsNativeTheme.h"
15 namespace mozilla::widget {
17 LayoutDeviceIntSize ScrollbarDrawingWin::GetMinimumWidgetSize(
18 nsPresContext* aPresContext, StyleAppearance aAppearance,
19 nsIFrame* aFrame) {
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{};
31 [[fallthrough]];
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
37 // under this size.
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.
51 if (isHorizontal) {
52 size.width *= 2;
53 } else {
54 size.height *= 2;
57 return size;
59 default:
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)) {
70 return style;
72 bool useDarkScrollbar = !StaticPrefs::widget_disable_dark_scrollbar() &&
73 nsNativeTheme::IsDarkBackgroundForScrollbar(aFrame);
74 if (useDarkScrollbar) {
75 return style;
77 return nullptr;
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);
99 default:
100 break;
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);
120 default:
121 break;
124 return Nothing();
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);
136 return true;
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,
146 aDpiRatio);
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,
156 aDpiRatio);
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