fune/widget/ScrollbarDrawingWin.cpp
Emilio Cobos Álvarez de7b391af7 Bug 1749645 - Rename nsNativeBasicTheme{,Cocoa} to Theme{,Cocoa}. r=mstange
We have this situation right now where all the themes are inheriting from
nsNativeBasicTheme. Rename it to a nicer name, and clean up some code while at
it.

In the future I'd like to simplify the inheritance chain to remove
nsNativeTheme altogether (so that all nsITheme implementations use
mozilla::widget::Theme).

That's not hard to do mechanically, but rather than dumping all of
nsNativeTheme into Theme I'd like to do it a bit more carefully, to hopefully
remove a lot of the helpers that nsNativeTheme has to deal with XUL and so on
and use something nicer. Eventually the inheritance chain will be something
like:

 * nsITheme : public nsISupports
 * Theme : public nsITheme, public nsITimerCallback, public nsINamed
 * ThemeCocoa : public Theme
 * nsNativeThemeCocoa : public ThemeCocoa
 * nsNativeThemeWin : public Theme
 * nsNativeThemeGtk : public Theme

Differential Revision: https://phabricator.services.mozilla.com/D135668
2022-01-12 16:33:31 +00:00

176 lines
6.9 KiB
C++

/* -*- 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:
// For scrollbar-width:thin, we don't display the buttons.
if (IsScrollbarWidthThin(aFrame)) {
return LayoutDeviceIntSize{};
}
[[fallthrough]];
case StyleAppearance::ScrollbarVertical:
case StyleAppearance::ScrollbarHorizontal:
case StyleAppearance::ScrollbarthumbVertical:
case StyleAppearance::ScrollbarthumbHorizontal: {
if ((aAppearance == StyleAppearance::ScrollbarHorizontal ||
aAppearance == StyleAppearance::ScrollbarVertical) &&
!aPresContext->UseOverlayScrollbars()) {
return LayoutDeviceIntSize{};
}
// TODO: for short scrollbars it could be nice if the thumb could shrink
// under this size.
auto sizes = GetScrollbarSizes(aPresContext, aFrame);
const bool isHorizontal =
aAppearance == StyleAppearance::ScrollbarHorizontal ||
aAppearance == StyleAppearance::ScrollbarthumbHorizontal ||
aAppearance == StyleAppearance::ScrollbarbuttonLeft ||
aAppearance == StyleAppearance::ScrollbarbuttonRight;
const auto size = isHorizontal ? sizes.mHorizontal : sizes.mVertical;
return LayoutDeviceIntSize{size, size};
}
default:
return LayoutDeviceIntSize{};
}
}
Maybe<nsITheme::Transparency> ScrollbarDrawingWin::GetScrollbarPartTransparency(
nsIFrame* aFrame, StyleAppearance aAppearance) {
if (nsNativeTheme::IsWidgetScrollbarPart(aAppearance)) {
if (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:
case StyleAppearance::Statusbar:
// 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();
}
// Returns the style for custom scrollbar if the scrollbar part frame should
// use the custom drawing path, nullptr otherwise.
//
// Optionally the caller can pass a pointer to aDarkScrollbar for whether
// custom scrollbar may be drawn due to dark background.
/*static*/
ComputedStyle* ScrollbarDrawingWin::GetCustomScrollbarStyle(
nsIFrame* aFrame, bool* aDarkScrollbar) {
ComputedStyle* style = nsLayoutUtils::StyleForScrollbar(aFrame);
if (style->StyleUI()->HasCustomScrollbars()) {
return style;
}
bool useDarkScrollbar = !StaticPrefs::widget_disable_dark_scrollbar() &&
nsNativeTheme::IsDarkBackground(aFrame);
if (useDarkScrollbar || IsScrollbarWidthThin(*style)) {
if (aDarkScrollbar) {
*aDarkScrollbar = useDarkScrollbar;
}
return style;
}
return nullptr;
}
template <typename PaintBackendData>
bool ScrollbarDrawingWin::DoPaintScrollbarThumb(
PaintBackendData& aPaintData, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aElementState, const EventStates& aDocumentState,
const Colors& aColors, const DPIRatio& aDpiRatio) {
sRGBColor thumbColor = ComputeScrollbarThumbColor(
aFrame, aStyle, aElementState, aDocumentState, aColors);
ThemeDrawing::FillRect(aPaintData, aRect, thumbColor);
return true;
}
bool ScrollbarDrawingWin::PaintScrollbarThumb(
DrawTarget& aDrawTarget, const LayoutDeviceRect& aRect, bool aHorizontal,
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aElementState, const EventStates& aDocumentState,
const Colors& aColors, const DPIRatio& aDpiRatio) {
return DoPaintScrollbarThumb(aDrawTarget, aRect, aHorizontal, aFrame, aStyle,
aElementState, aDocumentState, aColors,
aDpiRatio);
}
bool ScrollbarDrawingWin::PaintScrollbarThumb(
WebRenderBackendData& aWrData, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aElementState, const EventStates& aDocumentState,
const Colors& aColors, const DPIRatio& aDpiRatio) {
return DoPaintScrollbarThumb(aWrData, aRect, aHorizontal, aFrame, aStyle,
aElementState, aDocumentState, 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;
}
mHorizontalScrollbarHeight = mVerticalScrollbarWidth = defaultSize;
if (StaticPrefs::widget_non_native_theme_win_scrollbar_use_system_size()) {
mHorizontalScrollbarHeight = LookAndFeel::GetInt(
LookAndFeel::IntID::SystemHorizontalScrollbarHeight, defaultSize);
mVerticalScrollbarWidth = LookAndFeel::GetInt(
LookAndFeel::IntID::SystemVerticalScrollbarWidth, defaultSize);
}
}
} // namespace mozilla::widget