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