Bug 1719427: Refactor scrollbar drawing code across platforms. r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D129265
This commit is contained in:
Stephen A Pohl
2021-11-15 12:39:38 +00:00
parent ed6103c5eb
commit d42bf8fe6b
47 changed files with 2343 additions and 2197 deletions

View File

@@ -255,7 +255,7 @@ class nsITheme : public nsISupports {
*/
virtual bool ThemeNeedsComboboxDropmarker() = 0;
virtual bool ThemeSupportsScrollbarButtons() { return true; }
virtual bool ThemeSupportsScrollbarButtons() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsITheme, NS_ITHEME_IID)

475
widget/ScrollbarDrawing.cpp Normal file
View File

@@ -0,0 +1,475 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 2; -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* 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 "ScrollbarDrawing.h"
#include "mozilla/RelativeLuminanceUtils.h"
#include "nsContainerFrame.h"
#include "nsDeviceContext.h"
#include "nsIFrame.h"
#include "nsLayoutUtils.h"
#include "nsLookAndFeel.h"
#include "nsNativeTheme.h"
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::widget;
using ScrollbarParams = ScrollbarDrawing::ScrollbarParams;
using mozilla::RelativeLuminanceUtils;
uint32_t ScrollbarDrawing::sHorizontalScrollbarHeight = 0;
uint32_t ScrollbarDrawing::sVerticalScrollbarWidth = 0;
/* static */
auto ScrollbarDrawing::GetDPIRatioForScrollbarPart(nsPresContext* aPc)
-> DPIRatio {
if (auto* rootPc = aPc->GetRootPresContext()) {
if (nsCOMPtr<nsIWidget> widget = rootPc->GetRootWidget()) {
return widget->GetDefaultScale();
}
}
return DPIRatio(
float(AppUnitsPerCSSPixel()) /
float(aPc->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom()));
}
/*static*/
nsIFrame* ScrollbarDrawing::GetParentScrollbarFrame(nsIFrame* aFrame) {
// Walk our parents to find a scrollbar frame
nsIFrame* scrollbarFrame = aFrame;
do {
if (scrollbarFrame->IsScrollbarFrame()) {
break;
}
} while ((scrollbarFrame = scrollbarFrame->GetParent()));
// We return null if we can't find a parent scrollbar frame
return scrollbarFrame;
}
/*static*/
bool ScrollbarDrawing::IsParentScrollbarRolledOver(nsIFrame* aFrame) {
nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame);
return nsLookAndFeel::GetInt(LookAndFeel::IntID::UseOverlayScrollbars) != 0
? nsNativeTheme::CheckBooleanAttr(scrollbarFrame, nsGkAtoms::hover)
: nsNativeTheme::GetContentState(scrollbarFrame,
StyleAppearance::None)
.HasState(NS_EVENT_STATE_HOVER);
}
/*static*/
bool ScrollbarDrawing::IsParentScrollbarHoveredOrActive(nsIFrame* aFrame) {
nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame);
return scrollbarFrame && scrollbarFrame->GetContent()
->AsElement()
->State()
.HasAtLeastOneOfStates(NS_EVENT_STATE_HOVER |
NS_EVENT_STATE_ACTIVE);
}
/*static*/
bool ScrollbarDrawing::IsScrollbarWidthThin(const ComputedStyle& aStyle) {
auto scrollbarWidth = aStyle.StyleUIReset()->mScrollbarWidth;
return scrollbarWidth == StyleScrollbarWidth::Thin;
}
/*static*/
bool ScrollbarDrawing::IsScrollbarWidthThin(nsIFrame* aFrame) {
ComputedStyle* style = nsLayoutUtils::StyleForScrollbar(aFrame);
return IsScrollbarWidthThin(*style);
}
auto ScrollbarDrawing::GetScrollbarSizes(nsPresContext* aPresContext,
StyleScrollbarWidth aWidth, Overlay)
-> ScrollbarSizes {
uint32_t h = sHorizontalScrollbarHeight;
uint32_t w = sVerticalScrollbarWidth;
if (aWidth == StyleScrollbarWidth::Thin) {
h /= 2;
w /= 2;
}
auto dpi = GetDPIRatioForScrollbarPart(aPresContext);
return {(CSSCoord(w) * dpi).Rounded(), (CSSCoord(h) * dpi).Rounded()};
}
/*static*/
bool ScrollbarDrawing::IsScrollbarTrackOpaque(nsIFrame* aFrame) {
auto trackColor = ComputeScrollbarTrackColor(
aFrame, *nsLayoutUtils::StyleForScrollbar(aFrame),
aFrame->PresContext()->Document()->GetDocumentState(), Colors(aFrame));
return trackColor.a == 1.0f;
}
/*static*/
sRGBColor ScrollbarDrawing::ComputeScrollbarTrackColor(
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors& aColors) {
const nsStyleUI* ui = aStyle.StyleUI();
if (aColors.HighContrast()) {
return aColors.System(StyleSystemColor::Window);
}
if (ShouldUseDarkScrollbar(aFrame, aStyle)) {
return sRGBColor::FromU8(20, 20, 25, 77);
}
if (ui->mScrollbarColor.IsColors()) {
return sRGBColor::FromABGR(
ui->mScrollbarColor.AsColors().track.CalcColor(aStyle));
}
if (aDocumentState.HasAllStates(NS_DOCUMENT_STATE_WINDOW_INACTIVE)) {
return aColors.SystemOrElse(StyleSystemColor::ThemedScrollbarInactive,
[] { return sScrollbarColor; });
}
return aColors.SystemOrElse(StyleSystemColor::ThemedScrollbar,
[] { return sScrollbarColor; });
}
// Don't use the theme color for dark scrollbars if it's not a color (if it's
// grey-ish), as that'd either lack enough contrast, or be close to what we'd do
// by default anyways.
static bool ShouldUseColorForActiveDarkScrollbarThumb(nscolor aColor) {
auto IsDifferentEnough = [](int32_t aChannel, int32_t aOtherChannel) {
return std::abs(aChannel - aOtherChannel) > 10;
};
return IsDifferentEnough(NS_GET_R(aColor), NS_GET_G(aColor)) ||
IsDifferentEnough(NS_GET_R(aColor), NS_GET_B(aColor));
}
/*static*/
sRGBColor ScrollbarDrawing::ComputeScrollbarThumbColor(
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aElementState, const EventStates& aDocumentState,
const Colors& aColors) {
if (!aColors.HighContrast() && ShouldUseDarkScrollbar(aFrame, aStyle)) {
if (aElementState.HasState(NS_EVENT_STATE_ACTIVE) &&
StaticPrefs::widget_non_native_theme_scrollbar_active_always_themed()) {
auto color = LookAndFeel::GetColor(
StyleSystemColor::ThemedScrollbarThumbActive,
LookAndFeel::ColorScheme::Light, LookAndFeel::UseStandins::No);
if (color && ShouldUseColorForActiveDarkScrollbarThumb(*color)) {
return sRGBColor::FromABGR(*color);
}
}
return sRGBColor::FromABGR(ThemeColors::AdjustUnthemedScrollbarThumbColor(
NS_RGBA(249, 249, 250, 102), aElementState));
}
const nsStyleUI* ui = aStyle.StyleUI();
if (ui->mScrollbarColor.IsColors()) {
return sRGBColor::FromABGR(ThemeColors::AdjustUnthemedScrollbarThumbColor(
ui->mScrollbarColor.AsColors().thumb.CalcColor(aStyle), aElementState));
}
auto systemColor = [&] {
if (aDocumentState.HasState(NS_DOCUMENT_STATE_WINDOW_INACTIVE)) {
return StyleSystemColor::ThemedScrollbarThumbInactive;
}
if (aElementState.HasState(NS_EVENT_STATE_ACTIVE)) {
if (aColors.HighContrast()) {
return StyleSystemColor::Selecteditem;
}
return StyleSystemColor::ThemedScrollbarThumbActive;
}
if (aElementState.HasState(NS_EVENT_STATE_HOVER)) {
if (aColors.HighContrast()) {
return StyleSystemColor::Selecteditem;
}
return StyleSystemColor::ThemedScrollbarThumbHover;
}
if (aColors.HighContrast()) {
return StyleSystemColor::Windowtext;
}
return StyleSystemColor::ThemedScrollbarThumb;
}();
return aColors.SystemOrElse(systemColor, [&] {
return sRGBColor::FromABGR(ThemeColors::AdjustUnthemedScrollbarThumbColor(
sScrollbarThumbColor.ToABGR(), aElementState));
});
}
/*static*/
ScrollbarParams ScrollbarDrawing::ComputeScrollbarParams(
nsIFrame* aFrame, const ComputedStyle& aStyle, bool aIsHorizontal) {
ScrollbarParams params;
params.overlay =
nsLookAndFeel::GetInt(LookAndFeel::IntID::UseOverlayScrollbars) != 0;
params.rolledOver = IsParentScrollbarRolledOver(aFrame);
params.small =
aStyle.StyleUIReset()->mScrollbarWidth == StyleScrollbarWidth::Thin;
params.rtl = nsNativeTheme::IsFrameRTL(aFrame);
params.horizontal = aIsHorizontal;
params.onDarkBackground = !StaticPrefs::widget_disable_dark_scrollbar() &&
nsNativeTheme::IsDarkBackground(aFrame);
// Don't use custom scrollbars for overlay scrollbars since they are
// generally good enough for use cases of custom scrollbars.
if (!params.overlay) {
const nsStyleUI* ui = aStyle.StyleUI();
if (ui->HasCustomScrollbars()) {
const auto& colors = ui->mScrollbarColor.AsColors();
params.custom = true;
params.trackColor = colors.track.CalcColor(aStyle);
params.faceColor = colors.thumb.CalcColor(aStyle);
}
}
return params;
}
template <typename PaintBackendData>
bool ScrollbarDrawing::DoPaintDefaultScrollbar(
PaintBackendData& aPaintData, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aElementState, const EventStates& aDocumentState,
const Colors& aColors, const DPIRatio& aDpiRatio) {
if (aFrame->PresContext()->UseOverlayScrollbars() &&
!aElementState.HasAtLeastOneOfStates(NS_EVENT_STATE_HOVER |
NS_EVENT_STATE_ACTIVE)) {
return true;
}
auto scrollbarColor =
ComputeScrollbarTrackColor(aFrame, aStyle, aDocumentState, aColors);
ThemeDrawing::FillRect(aPaintData, aRect, scrollbarColor);
return true;
}
bool ScrollbarDrawing::PaintScrollbar(
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 DoPaintDefaultScrollbar(aDrawTarget, aRect, aHorizontal, aFrame,
aStyle, aElementState, aDocumentState, aColors,
aDpiRatio);
}
bool ScrollbarDrawing::PaintScrollbar(
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 DoPaintDefaultScrollbar(aWrData, aRect, aHorizontal, aFrame, aStyle,
aElementState, aDocumentState, aColors,
aDpiRatio);
}
template <typename PaintBackendData>
bool ScrollbarDrawing::DoPaintDefaultScrollCorner(
PaintBackendData& aPaintData, const LayoutDeviceRect& aRect,
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors& aColors,
const DPIRatio& aDpiRatio) {
auto scrollbarColor =
ComputeScrollbarTrackColor(aFrame, aStyle, aDocumentState, aColors);
ThemeDrawing::FillRect(aPaintData, aRect, scrollbarColor);
return true;
}
bool ScrollbarDrawing::PaintScrollCorner(
DrawTarget& aDrawTarget, const LayoutDeviceRect& aRect, nsIFrame* aFrame,
const ComputedStyle& aStyle, const EventStates& aDocumentState,
const Colors& aColors, const DPIRatio& aDpiRatio) {
return DoPaintDefaultScrollCorner(aDrawTarget, aRect, aFrame, aStyle,
aDocumentState, aColors, aDpiRatio);
}
bool ScrollbarDrawing::PaintScrollCorner(WebRenderBackendData& aWrData,
const LayoutDeviceRect& aRect,
nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aDocumentState,
const Colors& aColors,
const DPIRatio& aDpiRatio) {
return DoPaintDefaultScrollCorner(aWrData, aRect, aFrame, aStyle,
aDocumentState, aColors, aDpiRatio);
}
/*static*/
bool ScrollbarDrawing::ShouldUseDarkScrollbar(nsIFrame* aFrame,
const ComputedStyle& aStyle) {
if (StaticPrefs::widget_disable_dark_scrollbar()) {
return false;
}
if (aStyle.StyleUI()->mScrollbarColor.IsColors()) {
return false;
}
return nsNativeTheme::IsDarkBackground(aFrame);
}
/*static*/
nscolor ScrollbarDrawing::GetScrollbarButtonColor(nscolor aTrackColor,
EventStates aStates) {
// See numbers in GetScrollbarArrowColor.
// This function is written based on ratios between values listed there.
bool isActive = aStates.HasState(NS_EVENT_STATE_ACTIVE);
bool isHover = aStates.HasState(NS_EVENT_STATE_HOVER);
if (!isActive && !isHover) {
return aTrackColor;
}
float luminance = RelativeLuminanceUtils::Compute(aTrackColor);
if (isActive) {
if (luminance >= 0.18f) {
luminance *= 0.134f;
} else {
luminance /= 0.134f;
luminance = std::min(luminance, 1.0f);
}
} else {
if (luminance >= 0.18f) {
luminance *= 0.805f;
} else {
luminance /= 0.805f;
}
}
return RelativeLuminanceUtils::Adjust(aTrackColor, luminance);
}
/*static*/
Maybe<nscolor> ScrollbarDrawing::GetScrollbarArrowColor(nscolor aButtonColor) {
// In Windows 10 scrollbar, there are several gray colors used:
//
// State | Background (lum) | Arrow | Contrast
// -------+------------------+---------+---------
// Normal | Gray 240 (87.1%) | Gray 96 | 5.5
// Hover | Gray 218 (70.1%) | Black | 15.0
// Active | Gray 96 (11.7%) | White | 6.3
//
// Contrast value is computed based on the definition in
// https://www.w3.org/TR/WCAG20/#contrast-ratiodef
//
// This function is written based on these values.
if (NS_GET_A(aButtonColor) == 0) {
// If the button color is transparent, because of e.g.
// scrollbar-color: <something> transparent, then use
// the thumb color, which is expected to have enough
// contrast.
return Nothing();
}
float luminance = RelativeLuminanceUtils::Compute(aButtonColor);
// Color with luminance larger than 0.72 has contrast ratio over 4.6
// to color with luminance of gray 96, so this value is chosen for
// this range. It is the luminance of gray 221.
if (luminance >= 0.72) {
// ComputeRelativeLuminanceFromComponents(96). That function cannot
// be constexpr because of std::pow.
const float GRAY96_LUMINANCE = 0.117f;
return Some(RelativeLuminanceUtils::Adjust(aButtonColor, GRAY96_LUMINANCE));
}
// The contrast ratio of a color to black equals that to white when its
// luminance is around 0.18, with a contrast ratio ~4.6 to both sides,
// thus the value below. It's the lumanince of gray 118.
//
// TODO(emilio): Maybe the button alpha is not the best thing to use here and
// we should use the thumb alpha? It seems weird that the color of the arrow
// depends on the opacity of the scrollbar thumb...
if (luminance >= 0.18) {
return Some(NS_RGBA(0, 0, 0, NS_GET_A(aButtonColor)));
}
return Some(NS_RGBA(255, 255, 255, NS_GET_A(aButtonColor)));
}
std::pair<sRGBColor, sRGBColor> ScrollbarDrawing::ComputeScrollbarButtonColors(
nsIFrame* aFrame, StyleAppearance aAppearance, const ComputedStyle& aStyle,
const EventStates& aElementState, const EventStates& aDocumentState,
const Colors& aColors) {
if (aColors.HighContrast()) {
if (aElementState.HasAtLeastOneOfStates(NS_EVENT_STATE_ACTIVE |
NS_EVENT_STATE_HOVER)) {
return aColors.SystemPair(StyleSystemColor::Selecteditem,
StyleSystemColor::Buttonface);
}
return aColors.SystemPair(StyleSystemColor::Window,
StyleSystemColor::Windowtext);
}
auto trackColor =
ComputeScrollbarTrackColor(aFrame, aStyle, aDocumentState, aColors);
nscolor buttonColor =
GetScrollbarButtonColor(trackColor.ToABGR(), aElementState);
auto arrowColor =
GetScrollbarArrowColor(buttonColor)
.map(sRGBColor::FromABGR)
.valueOrFrom([&] {
return ComputeScrollbarThumbColor(aFrame, aStyle, aElementState,
aDocumentState, aColors);
});
return {sRGBColor::FromABGR(buttonColor), arrowColor};
}
bool ScrollbarDrawing::PaintScrollbarButton(
DrawTarget& aDrawTarget, StyleAppearance aAppearance,
const LayoutDeviceRect& aRect, nsIFrame* aFrame,
const ComputedStyle& aStyle, const EventStates& aElementState,
const EventStates& aDocumentState, const Colors& aColors,
const DPIRatio& aDpiRatio) {
auto [buttonColor, arrowColor] = ComputeScrollbarButtonColors(
aFrame, aAppearance, aStyle, aElementState, aDocumentState, aColors);
aDrawTarget.FillRect(aRect.ToUnknownRect(),
ColorPattern(ToDeviceColor(buttonColor)));
// Start with Up arrow.
float arrowPolygonX[] = {-4.0f, 0.0f, 4.0f, 4.0f, 0.0f, -4.0f};
float arrowPolygonY[] = {0.0f, -4.0f, 0.0f, 3.0f, -1.0f, 3.0f};
const float kPolygonSize = 17;
const int32_t arrowNumPoints = ArrayLength(arrowPolygonX);
switch (aAppearance) {
case StyleAppearance::ScrollbarbuttonUp:
break;
case StyleAppearance::ScrollbarbuttonDown:
for (int32_t i = 0; i < arrowNumPoints; i++) {
arrowPolygonY[i] *= -1;
}
break;
case StyleAppearance::ScrollbarbuttonLeft:
for (int32_t i = 0; i < arrowNumPoints; i++) {
float temp = arrowPolygonX[i];
arrowPolygonX[i] = arrowPolygonY[i];
arrowPolygonY[i] = temp;
}
break;
case StyleAppearance::ScrollbarbuttonRight:
for (int32_t i = 0; i < arrowNumPoints; i++) {
float temp = arrowPolygonX[i];
arrowPolygonX[i] = arrowPolygonY[i] * -1;
arrowPolygonY[i] = temp;
}
break;
default:
return false;
}
ThemeDrawing::PaintArrow(aDrawTarget, aRect, arrowPolygonX, arrowPolygonY,
kPolygonSize, arrowNumPoints, arrowColor);
return true;
}
/*static*/
void ScrollbarDrawing::RecomputeScrollbarParams() {
uint32_t defaultSize = StaticPrefs::widget_non_native_theme_scrollbar_size();
if (StaticPrefs::widget_non_native_theme_win_scrollbar_use_system_size()) {
sHorizontalScrollbarHeight = LookAndFeel::GetInt(
LookAndFeel::IntID::SystemHorizontalScrollbarHeight, defaultSize);
sVerticalScrollbarWidth = LookAndFeel::GetInt(
LookAndFeel::IntID::SystemVerticalScrollbarWidth, defaultSize);
} else {
sHorizontalScrollbarHeight = sVerticalScrollbarWidth = defaultSize;
}
// On GTK, widgets don't account for text scale factor, but that's included
// in the usual DPI computations, so we undo that here, just like
// GetMonitorScaleFactor does it in nsNativeThemeGTK.
float scale =
LookAndFeel::GetFloat(LookAndFeel::FloatID::TextScaleFactor, 1.0f);
if (scale != 1.0f) {
sVerticalScrollbarWidth =
uint32_t(round(float(sVerticalScrollbarWidth) / scale));
sHorizontalScrollbarHeight =
uint32_t(round(float(sHorizontalScrollbarHeight) / scale));
}
}

174
widget/ScrollbarDrawing.h Normal file
View File

@@ -0,0 +1,174 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_widget_ScrollbarDrawing_h
#define mozilla_widget_ScrollbarDrawing_h
#include "mozilla/EventStates.h"
#include "mozilla/gfx/2D.h"
#include "nsColor.h"
#include "nsITheme.h"
#include "ThemeColors.h"
#include "ThemeDrawing.h"
#include "Units.h"
namespace mozilla::widget {
static constexpr gfx::sRGBColor sScrollbarColor(
gfx::sRGBColor::UnusualFromARGB(0xfff0f0f0));
static constexpr gfx::sRGBColor sScrollbarThumbColor(
gfx::sRGBColor::UnusualFromARGB(0xffcdcdcd));
class ScrollbarDrawing {
protected:
using DPIRatio = mozilla::CSSToLayoutDeviceScale;
using EventStates = mozilla::EventStates;
using DrawTarget = mozilla::gfx::DrawTarget;
using sRGBColor = mozilla::gfx::sRGBColor;
using Colors = ThemeColors;
using ScrollbarSizes = nsITheme::ScrollbarSizes;
using Overlay = nsITheme::Overlay;
using WebRenderBackendData = mozilla::widget::WebRenderBackendData;
public:
ScrollbarDrawing() = default;
virtual ~ScrollbarDrawing() = default;
struct ScrollbarParams {
bool overlay = false;
bool rolledOver = false;
bool small = false;
bool horizontal = false;
bool rtl = false;
bool onDarkBackground = false;
bool custom = false;
// Two colors only used when custom is true.
nscolor trackColor = NS_RGBA(0, 0, 0, 0);
nscolor faceColor = NS_RGBA(0, 0, 0, 0);
};
static DPIRatio GetDPIRatioForScrollbarPart(nsPresContext*);
static nsIFrame* GetParentScrollbarFrame(nsIFrame* aFrame);
static bool IsParentScrollbarRolledOver(nsIFrame* aFrame);
static bool IsParentScrollbarHoveredOrActive(nsIFrame* aFrame);
static bool IsScrollbarWidthThin(const ComputedStyle& aStyle);
static bool IsScrollbarWidthThin(nsIFrame* aFrame);
virtual ScrollbarSizes GetScrollbarSizes(nsPresContext*, StyleScrollbarWidth,
Overlay);
virtual LayoutDeviceIntSize GetMinimumWidgetSize(nsPresContext*,
StyleAppearance aAppearance,
nsIFrame* aFrame) = 0;
virtual Maybe<nsITheme::Transparency> GetScrollbarPartTransparency(
nsIFrame* aFrame, StyleAppearance aAppearance) {
return Nothing();
}
static bool IsScrollbarTrackOpaque(nsIFrame*);
static sRGBColor ComputeScrollbarTrackColor(nsIFrame*, const ComputedStyle&,
const EventStates& aDocumentState,
const Colors&);
static sRGBColor ComputeScrollbarThumbColor(nsIFrame*, const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState,
const Colors&);
static ScrollbarParams ComputeScrollbarParams(nsIFrame* aFrame,
const ComputedStyle& aStyle,
bool aIsHorizontal);
static bool ShouldUseDarkScrollbar(nsIFrame*, const ComputedStyle&);
static nscolor GetScrollbarButtonColor(nscolor aTrackColor, EventStates);
static Maybe<nscolor> GetScrollbarArrowColor(nscolor aButtonColor);
// Returned colors are button, arrow.
std::pair<sRGBColor, sRGBColor> ComputeScrollbarButtonColors(
nsIFrame*, StyleAppearance, const ComputedStyle&,
const EventStates& aElementState, const EventStates& aDocumentState,
const Colors&);
bool PaintScrollbarButton(DrawTarget&, StyleAppearance,
const LayoutDeviceRect&, nsIFrame*,
const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
const DPIRatio&);
virtual bool PaintScrollbarThumb(DrawTarget&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*,
const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState,
const Colors&, const DPIRatio&) = 0;
virtual bool PaintScrollbarThumb(WebRenderBackendData&,
const LayoutDeviceRect&, bool aHorizontal,
nsIFrame*, const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState,
const Colors&, const DPIRatio&) = 0;
template <typename PaintBackendData>
bool DoPaintDefaultScrollbar(PaintBackendData&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*,
const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
const DPIRatio&);
virtual bool PaintScrollbar(DrawTarget&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*, const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
const DPIRatio&);
virtual bool PaintScrollbar(WebRenderBackendData&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*, const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
const DPIRatio&);
virtual bool PaintScrollbarTrack(DrawTarget&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*,
const ComputedStyle&,
const EventStates& aDocumentState,
const Colors&, const DPIRatio&) {
// Draw nothing by default. Subclasses can override this.
return true;
}
virtual bool PaintScrollbarTrack(WebRenderBackendData&,
const LayoutDeviceRect&, bool aHorizontal,
nsIFrame*, const ComputedStyle&,
const EventStates& aDocumentState,
const Colors&, const DPIRatio&) {
// Draw nothing by default. Subclasses can override this.
return true;
}
template <typename PaintBackendData>
bool DoPaintDefaultScrollCorner(PaintBackendData&, const LayoutDeviceRect&,
nsIFrame*, const ComputedStyle&,
const EventStates& aDocumentState,
const Colors&, const DPIRatio&);
virtual bool PaintScrollCorner(DrawTarget&, const LayoutDeviceRect&,
nsIFrame*, const ComputedStyle&,
const EventStates& aDocumentState,
const Colors&, const DPIRatio&);
virtual bool PaintScrollCorner(WebRenderBackendData&, const LayoutDeviceRect&,
nsIFrame*, const ComputedStyle&,
const EventStates& aDocumentState,
const Colors&, const DPIRatio&);
static void RecomputeScrollbarParams();
virtual bool ShouldDrawScrollbarButtons() { return true; }
static uint32_t sHorizontalScrollbarHeight;
static uint32_t sVerticalScrollbarWidth;
};
} // namespace mozilla::widget
#endif

View File

@@ -3,46 +3,42 @@
* 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 "nsNativeBasicThemeAndroid.h"
#include "ScrollbarDrawingAndroid.h"
#include "mozilla/ClearOnShutdown.h"
#include "nsStyleConsts.h"
#include "nsIFrame.h"
#include "nsNativeTheme.h"
auto nsNativeBasicThemeAndroid::GetScrollbarSizes(nsPresContext* aPresContext,
StyleScrollbarWidth aWidth,
Overlay aOverlay)
-> ScrollbarSizes {
// We force auto-width scrollbars because scrollbars on android are already
// thin enough.
return nsNativeBasicTheme::GetScrollbarSizes(
aPresContext, StyleScrollbarWidth::Auto, aOverlay);
}
using namespace mozilla;
using namespace mozilla::widget;
NS_IMETHODIMP
nsNativeBasicThemeAndroid::GetMinimumWidgetSize(
nsPresContext* aPresContext, nsIFrame* aFrame, StyleAppearance aAppearance,
mozilla::LayoutDeviceIntSize* aResult, bool* aIsOverridable) {
if (!IsWidgetScrollbarPart(aAppearance)) {
return nsNativeBasicTheme::GetMinimumWidgetSize(
aPresContext, aFrame, aAppearance, aResult, aIsOverridable);
}
LayoutDeviceIntSize ScrollbarDrawingAndroid::GetMinimumWidgetSize(
nsPresContext* aPresContext, StyleAppearance aAppearance,
nsIFrame* aFrame) {
MOZ_ASSERT(nsNativeTheme::IsWidgetScrollbarPart(aAppearance));
auto sizes =
GetScrollbarSizes(aPresContext, StyleScrollbarWidth::Auto, Overlay::Yes);
aResult->SizeTo(sizes.mHorizontal, sizes.mHorizontal);
MOZ_ASSERT(sizes.mHorizontal == sizes.mVertical);
*aIsOverridable = true;
return NS_OK;
return LayoutDeviceIntSize{sizes.mHorizontal, sizes.mVertical};
}
auto ScrollbarDrawingAndroid::GetScrollbarSizes(nsPresContext* aPresContext,
StyleScrollbarWidth aWidth,
Overlay aOverlay)
-> ScrollbarSizes {
// We force auto-width scrollbars because scrollbars on android are already
// thin enough.
return ScrollbarDrawing::GetScrollbarSizes(
aPresContext, StyleScrollbarWidth::Auto, aOverlay);
}
template <typename PaintBackendData>
void nsNativeBasicThemeAndroid::DoPaintScrollbarThumb(
void ScrollbarDrawingAndroid::DoPaintScrollbarThumb(
PaintBackendData& aPaintData, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aElementState, const EventStates& aDocumentState,
const Colors& aColors, DPIRatio aDpiRatio) {
const Colors& aColors, const DPIRatio& aDpiRatio) {
// TODO(emilio): Maybe do like macOS and draw a stroke?
const auto color = ComputeScrollbarThumbColor(aFrame, aStyle, aElementState,
aDocumentState, aColors);
@@ -59,48 +55,27 @@ void nsNativeBasicThemeAndroid::DoPaintScrollbarThumb(
const LayoutDeviceCoord radius =
(aHorizontal ? thumbRect.height : thumbRect.width) / 2.0f;
PaintRoundedRectWithRadius(aPaintData, thumbRect, color,
sRGBColor::White(0.0f), 0.0f, radius / aDpiRatio,
aDpiRatio);
ThemeDrawing::PaintRoundedRectWithRadius(aPaintData, thumbRect, color,
sRGBColor::White(0.0f), 0.0f,
radius / aDpiRatio, aDpiRatio);
}
bool nsNativeBasicThemeAndroid::PaintScrollbarThumb(
bool ScrollbarDrawingAndroid::PaintScrollbarThumb(
DrawTarget& aDt, const LayoutDeviceRect& aRect, bool aHorizontal,
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aElementState, const EventStates& aDocumentState,
const Colors& aColors, DPIRatio aDpiRatio) {
const Colors& aColors, const DPIRatio& aDpiRatio) {
DoPaintScrollbarThumb(aDt, aRect, aHorizontal, aFrame, aStyle, aElementState,
aDocumentState, aColors, aDpiRatio);
return true;
}
bool nsNativeBasicThemeAndroid::PaintScrollbarThumb(
bool ScrollbarDrawingAndroid::PaintScrollbarThumb(
WebRenderBackendData& aWrData, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aElementState, const EventStates& aDocumentState,
const Colors& aColors, DPIRatio aDpiRatio) {
const Colors& aColors, const DPIRatio& aDpiRatio) {
DoPaintScrollbarThumb(aWrData, aRect, aHorizontal, aFrame, aStyle,
aElementState, aDocumentState, aColors, aDpiRatio);
return true;
}
already_AddRefed<nsITheme> do_GetAndroidNonNativeThemeDoNotUseDirectly() {
static mozilla::StaticRefPtr<nsITheme> gInstance;
if (MOZ_UNLIKELY(!gInstance)) {
gInstance = new nsNativeBasicThemeAndroid();
ClearOnShutdown(&gInstance);
}
return do_AddRef(gInstance);
}
#ifdef ANDROID
already_AddRefed<nsITheme> do_GetBasicNativeThemeDoNotUseDirectly() {
return do_GetAndroidNonNativeThemeDoNotUseDirectly();
}
already_AddRefed<nsITheme> do_GetNativeThemeDoNotUseDirectly() {
// Android doesn't have a native theme.
return do_GetBasicNativeThemeDoNotUseDirectly();
}
#endif

View File

@@ -0,0 +1,51 @@
/* -*- 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/. */
#ifndef mozilla_widget_ScrollbarDrawingAndroid_h
#define mozilla_widget_ScrollbarDrawingAndroid_h
#include "nsITheme.h"
#include "ScrollbarDrawing.h"
namespace mozilla::widget {
class ScrollbarDrawingAndroid final : public ScrollbarDrawing {
public:
ScrollbarDrawingAndroid() = default;
virtual ~ScrollbarDrawingAndroid() = default;
LayoutDeviceIntSize GetMinimumWidgetSize(nsPresContext*,
StyleAppearance aAppearance,
nsIFrame* aFrame) override;
ScrollbarSizes GetScrollbarSizes(nsPresContext*, StyleScrollbarWidth,
Overlay) override;
template <typename PaintBackendData>
void DoPaintScrollbarThumb(PaintBackendData&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
const DPIRatio&);
bool PaintScrollbarThumb(DrawTarget&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
const DPIRatio&) override;
bool PaintScrollbarThumb(WebRenderBackendData&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
const DPIRatio&) override;
bool ShouldDrawScrollbarButtons() override { return false; }
};
} // namespace mozilla::widget
#endif

View File

@@ -4,63 +4,26 @@
* 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 "ScrollbarDrawingMac.h"
#include "ScrollbarDrawingCocoa.h"
#include "mozilla/gfx/Helpers.h"
#include "mozilla/RelativeLuminanceUtils.h"
#include "nsLayoutUtils.h"
#include "nsIFrame.h"
#include "nsLookAndFeel.h"
#include "mozilla/StaticPrefs_widget.h"
#include "nsContainerFrame.h"
#include "nsIFrame.h"
#include "nsLayoutUtils.h"
#include "nsLookAndFeel.h"
#include "nsNativeTheme.h"
namespace mozilla {
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::widget;
using namespace gfx;
LayoutDeviceIntSize ScrollbarDrawingCocoa::GetMinimumWidgetSize(
nsPresContext* aPresContext, StyleAppearance aAppearance,
nsIFrame* aFrame) {
MOZ_ASSERT(nsNativeTheme::IsWidgetScrollbarPart(aAppearance));
namespace widget {
static nsIFrame* GetParentScrollbarFrame(nsIFrame* aFrame) {
// Walk our parents to find a scrollbar frame
nsIFrame* scrollbarFrame = aFrame;
do {
if (scrollbarFrame->IsScrollbarFrame()) {
break;
}
} while ((scrollbarFrame = scrollbarFrame->GetParent()));
// We return null if we can't find a parent scrollbar frame
return scrollbarFrame;
}
static bool IsParentScrollbarRolledOver(nsIFrame* aFrame) {
nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame);
return nsLookAndFeel::GetInt(LookAndFeel::IntID::UseOverlayScrollbars) != 0
? nsNativeTheme::CheckBooleanAttr(scrollbarFrame, nsGkAtoms::hover)
: nsNativeTheme::GetContentState(scrollbarFrame,
StyleAppearance::None)
.HasState(NS_EVENT_STATE_HOVER);
}
CSSIntCoord ScrollbarDrawingMac::GetScrollbarSize(StyleScrollbarWidth aWidth,
bool aOverlay) {
bool isSmall = aWidth == StyleScrollbarWidth::Thin;
if (aOverlay) {
return isSmall ? 14 : 16;
}
return isSmall ? 11 : 15;
}
LayoutDeviceIntCoord ScrollbarDrawingMac::GetScrollbarSize(
StyleScrollbarWidth aWidth, bool aOverlay, float aDpiRatio) {
CSSIntCoord size = GetScrollbarSize(aWidth, aOverlay);
if (aDpiRatio >= 2.0f) {
return int32_t(size) * 2;
}
return int32_t(size);
}
LayoutDeviceIntSize ScrollbarDrawingMac::GetMinimumWidgetSize(
StyleAppearance aAppearance, nsIFrame* aFrame, float aDpiRatio) {
auto minSize = [&] {
switch (aAppearance) {
case StyleAppearance::ScrollbarthumbHorizontal:
@@ -78,11 +41,6 @@ LayoutDeviceIntSize ScrollbarDrawingMac::GetMinimumWidgetSize(
LookAndFeel::GetInt(LookAndFeel::IntID::UseOverlayScrollbars));
return IntSize{size, size};
}
case StyleAppearance::MozMenulistArrowButton: {
auto size =
GetScrollbarSize(StyleScrollbarWidth::Auto, /* aOverlay = */ false);
return IntSize{size, size};
}
case StyleAppearance::ScrollbarbuttonUp:
case StyleAppearance::ScrollbarbuttonDown:
return IntSize{15, 16};
@@ -94,42 +52,46 @@ LayoutDeviceIntSize ScrollbarDrawingMac::GetMinimumWidgetSize(
}
}();
if (aDpiRatio >= 2.0f) {
auto dpi = GetDPIRatioForScrollbarPart(aPresContext).scale;
if (dpi >= 2.0f) {
return LayoutDeviceIntSize{minSize.width * 2, minSize.height * 2};
}
return LayoutDeviceIntSize{minSize.width, minSize.height};
}
ScrollbarParams ScrollbarDrawingMac::ComputeScrollbarParams(
nsIFrame* aFrame, const ComputedStyle& aStyle, bool aIsHorizontal) {
ScrollbarParams params;
params.overlay =
nsLookAndFeel::GetInt(LookAndFeel::IntID::UseOverlayScrollbars) != 0;
params.rolledOver = IsParentScrollbarRolledOver(aFrame);
params.small =
aStyle.StyleUIReset()->mScrollbarWidth == StyleScrollbarWidth::Thin;
params.rtl = nsNativeTheme::IsFrameRTL(aFrame);
params.horizontal = aIsHorizontal;
params.onDarkBackground = !StaticPrefs::widget_disable_dark_scrollbar() &&
nsNativeTheme::IsDarkBackground(aFrame);
// Don't use custom scrollbars for overlay scrollbars since they are
// generally good enough for use cases of custom scrollbars.
if (!params.overlay) {
const nsStyleUI* ui = aStyle.StyleUI();
if (ui->HasCustomScrollbars()) {
const auto& colors = ui->mScrollbarColor.AsColors();
params.custom = true;
params.trackColor = colors.track.CalcColor(aStyle);
params.faceColor = colors.thumb.CalcColor(aStyle);
}
/*static*/
CSSIntCoord ScrollbarDrawingCocoa::GetScrollbarSize(StyleScrollbarWidth aWidth,
bool aOverlay) {
bool isSmall = aWidth == StyleScrollbarWidth::Thin;
if (aOverlay) {
return isSmall ? 14 : 16;
}
return params;
return isSmall ? 11 : 15;
}
auto ScrollbarDrawingMac::GetThumbRect(const Rect& aRect,
const ScrollbarParams& aParams,
float aScale) -> ThumbRect {
/*static*/
LayoutDeviceIntCoord ScrollbarDrawingCocoa::GetScrollbarSize(
StyleScrollbarWidth aWidth, bool aOverlay, DPIRatio aDpiRatio) {
CSSIntCoord size = GetScrollbarSize(aWidth, aOverlay);
if (aDpiRatio.scale >= 2.0f) {
return int32_t(size) * 2;
}
return int32_t(size);
}
auto ScrollbarDrawingCocoa::GetScrollbarSizes(nsPresContext* aPresContext,
StyleScrollbarWidth aWidth,
Overlay aOverlay)
-> ScrollbarSizes {
auto size = GetScrollbarSize(aWidth, aOverlay == Overlay::Yes,
GetDPIRatioForScrollbarPart(aPresContext));
return {size, size};
}
/*static*/
auto ScrollbarDrawingCocoa::GetThumbRect(const Rect& aRect,
const ScrollbarParams& aParams,
float aScale) -> ThumbRect {
// This matches the sizing checks in GetMinimumWidgetSize etc.
aScale = aScale >= 2.0f ? 2.0f : 1.0f;
@@ -224,10 +186,10 @@ static ScrollbarTrackDecorationColors ComputeScrollbarTrackDecorationColors(
return result;
}
bool ScrollbarDrawingMac::GetScrollbarTrackRects(const Rect& aRect,
const ScrollbarParams& aParams,
float aScale,
ScrollbarTrackRects& aRects) {
/*static*/
bool ScrollbarDrawingCocoa::GetScrollbarTrackRects(
const Rect& aRect, const ScrollbarParams& aParams, float aScale,
ScrollbarTrackRects& aRects) {
if (aParams.overlay && !aParams.rolledOver) {
// Non-hovered overlay scrollbars don't have a track. Draw nothing.
return false;
@@ -293,10 +255,11 @@ bool ScrollbarDrawingMac::GetScrollbarTrackRects(const Rect& aRect,
return true;
}
bool ScrollbarDrawingMac::GetScrollCornerRects(const Rect& aRect,
const ScrollbarParams& aParams,
float aScale,
ScrollCornerRects& aRects) {
/*static*/
bool ScrollbarDrawingCocoa::GetScrollCornerRects(const Rect& aRect,
const ScrollbarParams& aParams,
float aScale,
ScrollCornerRects& aRects) {
if (aParams.overlay && !aParams.rolledOver) {
// Non-hovered overlay scrollbars don't have a corner. Draw nothing.
return false;
@@ -360,5 +323,129 @@ bool ScrollbarDrawingMac::GetScrollCornerRects(const Rect& aRect,
return true;
}
} // namespace widget
} // namespace mozilla
template <typename PaintBackendData>
void ScrollbarDrawingCocoa::DoPaintScrollbarThumb(
PaintBackendData& aPaintData, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aElementState, const EventStates& aDocumentState,
const DPIRatio& aDpiRatio) {
ScrollbarParams params = ComputeScrollbarParams(aFrame, aStyle, aHorizontal);
auto thumb = GetThumbRect(aRect.ToUnknownRect(), params, aDpiRatio.scale);
auto thumbRect = LayoutDeviceRect::FromUnknownRect(thumb.mRect);
LayoutDeviceCoord radius =
(params.horizontal ? thumbRect.Height() : thumbRect.Width()) / 2.0f;
ThemeDrawing::PaintRoundedRectWithRadius(
aPaintData, thumbRect, thumbRect, sRGBColor::FromABGR(thumb.mFillColor),
sRGBColor::White(0.0f), 0.0f, radius / aDpiRatio, aDpiRatio);
if (!thumb.mStrokeColor) {
return;
}
// Paint the stroke if needed.
thumbRect.Inflate(thumb.mStrokeOutset + thumb.mStrokeWidth);
radius = (params.horizontal ? thumbRect.Height() : thumbRect.Width()) / 2.0f;
ThemeDrawing::PaintRoundedRectWithRadius(
aPaintData, thumbRect, sRGBColor::White(0.0f),
sRGBColor::FromABGR(thumb.mStrokeColor), thumb.mStrokeWidth,
radius / aDpiRatio, aDpiRatio);
}
bool ScrollbarDrawingCocoa::PaintScrollbarThumb(
DrawTarget& aDt, const LayoutDeviceRect& aRect, bool aHorizontal,
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aElementState, const EventStates& aDocumentState,
const Colors&, const DPIRatio& aDpiRatio) {
// TODO: Maybe respect the UseSystemColors setting?
DoPaintScrollbarThumb(aDt, aRect, aHorizontal, aFrame, aStyle, aElementState,
aDocumentState, aDpiRatio);
return true;
}
bool ScrollbarDrawingCocoa::PaintScrollbarThumb(
WebRenderBackendData& aWrData, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aElementState, const EventStates& aDocumentState,
const Colors&, const DPIRatio& aDpiRatio) {
// TODO: Maybe respect the UseSystemColors setting?
DoPaintScrollbarThumb(aWrData, aRect, aHorizontal, aFrame, aStyle,
aElementState, aDocumentState, aDpiRatio);
return true;
}
template <typename PaintBackendData>
void ScrollbarDrawingCocoa::DoPaintScrollbarTrack(
PaintBackendData& aPaintData, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, const DPIRatio& aDpiRatio) {
ScrollbarParams params = ComputeScrollbarParams(aFrame, aStyle, aHorizontal);
ScrollbarTrackRects rects;
if (GetScrollbarTrackRects(aRect.ToUnknownRect(), params, aDpiRatio.scale,
rects)) {
for (const auto& rect : rects) {
ThemeDrawing::FillRect(aPaintData,
LayoutDeviceRect::FromUnknownRect(rect.mRect),
sRGBColor::FromABGR(rect.mColor));
}
}
}
bool ScrollbarDrawingCocoa::PaintScrollbarTrack(
DrawTarget& aDt, const LayoutDeviceRect& aRect, bool aHorizontal,
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors&,
const DPIRatio& aDpiRatio) {
// TODO: Maybe respect the UseSystemColors setting?
DoPaintScrollbarTrack(aDt, aRect, aHorizontal, aFrame, aStyle, aDocumentState,
aDpiRatio);
return true;
}
bool ScrollbarDrawingCocoa::PaintScrollbarTrack(
WebRenderBackendData& aWrData, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors&,
const DPIRatio& aDpiRatio) {
// TODO: Maybe respect the UseSystemColors setting?
DoPaintScrollbarTrack(aWrData, aRect, aHorizontal, aFrame, aStyle,
aDocumentState, aDpiRatio);
return true;
}
template <typename PaintBackendData>
void ScrollbarDrawingCocoa::DoPaintScrollCorner(
PaintBackendData& aPaintData, const LayoutDeviceRect& aRect,
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, const DPIRatio& aDpiRatio) {
ScrollbarParams params = ComputeScrollbarParams(aFrame, aStyle, false);
ScrollCornerRects rects;
if (GetScrollCornerRects(aRect.ToUnknownRect(), params, aDpiRatio.scale,
rects)) {
for (const auto& rect : rects) {
ThemeDrawing::FillRect(aPaintData,
LayoutDeviceRect::FromUnknownRect(rect.mRect),
sRGBColor::FromABGR(rect.mColor));
}
}
}
bool ScrollbarDrawingCocoa::PaintScrollCorner(
DrawTarget& aDt, const LayoutDeviceRect& aRect, nsIFrame* aFrame,
const ComputedStyle& aStyle, const EventStates& aDocumentState,
const Colors&, const DPIRatio& aDpiRatio) {
// TODO: Maybe respect the UseSystemColors setting?
DoPaintScrollCorner(aDt, aRect, aFrame, aStyle, aDocumentState, aDpiRatio);
return true;
}
bool ScrollbarDrawingCocoa::PaintScrollCorner(WebRenderBackendData& aWrData,
const LayoutDeviceRect& aRect,
nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aDocumentState,
const Colors&,
const DPIRatio& aDpiRatio) {
// TODO: Maybe respect the UseSystemColors setting?
DoPaintScrollCorner(aWrData, aRect, aFrame, aStyle, aDocumentState,
aDpiRatio);
return true;
}

View File

@@ -0,0 +1,111 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_widget_ScrollbarDrawingCocoa_h
#define mozilla_widget_ScrollbarDrawingCocoa_h
#include "ScrollbarDrawing.h"
#include "mozilla/Array.h"
#include "nsNativeBasicTheme.h"
namespace mozilla::widget {
class ScrollbarDrawingCocoa final : public ScrollbarDrawing {
public:
ScrollbarDrawingCocoa() = default;
virtual ~ScrollbarDrawingCocoa() = default;
struct FillRectType {
gfx::Rect mRect;
nscolor mColor;
};
// The caller can draw this rectangle with rounded corners as appropriate.
struct ThumbRect {
gfx::Rect mRect;
nscolor mFillColor;
nscolor mStrokeColor;
float mStrokeWidth;
float mStrokeOutset;
};
using ScrollbarTrackRects = Array<FillRectType, 4>;
using ScrollCornerRects = Array<FillRectType, 7>;
LayoutDeviceIntSize GetMinimumWidgetSize(nsPresContext*,
StyleAppearance aAppearance,
nsIFrame* aFrame) override;
static CSSIntCoord GetScrollbarSize(StyleScrollbarWidth aWidth,
bool aOverlay);
static LayoutDeviceIntCoord GetScrollbarSize(StyleScrollbarWidth aWidth,
bool aOverlay,
DPIRatio aDpiRatio);
ScrollbarSizes GetScrollbarSizes(nsPresContext*, StyleScrollbarWidth,
Overlay) override;
static ThumbRect GetThumbRect(const gfx::Rect& aRect,
const ScrollbarParams& aParams, float aScale);
static bool GetScrollbarTrackRects(const gfx::Rect& aRect,
const ScrollbarParams& aParams,
float aScale, ScrollbarTrackRects& aRects);
static bool GetScrollCornerRects(const gfx::Rect& aRect,
const ScrollbarParams& aParams, float aScale,
ScrollCornerRects& aRects);
template <typename PaintBackendData>
void DoPaintScrollbarThumb(PaintBackendData&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aElementState,
const EventStates& aDocumentState,
const DPIRatio&);
bool PaintScrollbarThumb(DrawTarget&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*, const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
const DPIRatio&) override;
bool PaintScrollbarThumb(WebRenderBackendData&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*, const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
const DPIRatio&) override;
template <typename PaintBackendData>
void DoPaintScrollbarTrack(PaintBackendData&, const LayoutDeviceRect&, bool,
nsIFrame*, const ComputedStyle&,
const EventStates&, const DPIRatio&);
bool PaintScrollbarTrack(DrawTarget&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors&,
const DPIRatio&) override;
bool PaintScrollbarTrack(WebRenderBackendData&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors&,
const DPIRatio&) override;
template <typename PaintBackendData>
void DoPaintScrollCorner(PaintBackendData&, const LayoutDeviceRect&,
nsIFrame*, const ComputedStyle&, const EventStates&,
const DPIRatio&);
bool PaintScrollCorner(DrawTarget&, const LayoutDeviceRect& aRect,
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors&,
const DPIRatio&) override;
bool PaintScrollCorner(WebRenderBackendData&, const LayoutDeviceRect& aRect,
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors&,
const DPIRatio&) override;
bool ShouldDrawScrollbarButtons() override { return false; }
};
} // namespace mozilla::widget
#endif

View File

@@ -3,59 +3,27 @@
* 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 "nsNativeBasicThemeGTK.h"
#include "ScrollbarDrawingGTK.h"
#include "nsLayoutUtils.h"
#include "nsIFrame.h"
#include "nsContainerFrame.h"
#include "mozilla/dom/Document.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/gfx/Helpers.h"
#include "mozilla/StaticPrefs_widget.h"
#include "nsLayoutUtils.h"
#include "nsNativeTheme.h"
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::widget;
already_AddRefed<nsITheme> do_GetBasicNativeThemeDoNotUseDirectly() {
static StaticRefPtr<nsITheme> gInstance;
if (MOZ_UNLIKELY(!gInstance)) {
gInstance = new nsNativeBasicThemeGTK();
ClearOnShutdown(&gInstance);
}
return do_AddRef(gInstance);
}
LayoutDeviceIntSize ScrollbarDrawingGTK::GetMinimumWidgetSize(
nsPresContext* aPresContext, StyleAppearance aAppearance,
nsIFrame* aFrame) {
MOZ_ASSERT(nsNativeTheme::IsWidgetScrollbarPart(aAppearance));
nsITheme::Transparency nsNativeBasicThemeGTK::GetWidgetTransparency(
nsIFrame* aFrame, StyleAppearance aAppearance) {
if (!aFrame->PresContext()->UseOverlayScrollbars() &&
(aAppearance == StyleAppearance::ScrollbarVertical ||
aAppearance == StyleAppearance::ScrollbarHorizontal) &&
IsScrollbarTrackOpaque(aFrame)) {
return eOpaque;
}
return nsNativeBasicTheme::GetWidgetTransparency(aFrame, aAppearance);
}
bool nsNativeBasicThemeGTK::ThemeSupportsScrollbarButtons() {
return StaticPrefs::widget_non_native_theme_gtk_scrollbar_allow_buttons();
}
NS_IMETHODIMP
nsNativeBasicThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext,
nsIFrame* aFrame,
StyleAppearance aAppearance,
LayoutDeviceIntSize* aResult,
bool* aIsOverridable) {
if (!IsWidgetScrollbarPart(aAppearance)) {
return nsNativeBasicTheme::GetMinimumWidgetSize(
aPresContext, aFrame, aAppearance, aResult, aIsOverridable);
}
DPIRatio dpiRatio = GetDPIRatioForScrollbarPart(aPresContext);
ComputedStyle* style = nsLayoutUtils::StyleForScrollbar(aFrame);
const ComputedStyle* style = nsLayoutUtils::StyleForScrollbar(aFrame);
auto sizes = GetScrollbarSizes(
aPresContext, style->StyleUIReset()->mScrollbarWidth, Overlay::No);
MOZ_ASSERT(sizes.mHorizontal == sizes.mVertical);
aResult->SizeTo(sizes.mHorizontal, sizes.mHorizontal);
LayoutDeviceIntSize size{sizes.mHorizontal, sizes.mVertical};
if (aAppearance == StyleAppearance::ScrollbarHorizontal ||
aAppearance == StyleAppearance::ScrollbarVertical ||
aAppearance == StyleAppearance::ScrollbarthumbHorizontal ||
@@ -65,52 +33,41 @@ nsNativeBasicThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext,
const bool isVertical =
aAppearance == StyleAppearance::ScrollbarVertical ||
aAppearance == StyleAppearance::ScrollbarthumbVertical;
auto dpi = GetDPIRatioForScrollbarPart(aPresContext);
if (isVertical) {
aResult->height = thumbSize * dpiRatio;
size.height = thumbSize * dpi;
} else {
aResult->width = thumbSize * dpiRatio;
size.width = thumbSize * dpi;
}
}
*aIsOverridable = true;
return NS_OK;
return size;
}
static nsIFrame* GetParentScrollbarFrame(nsIFrame* aFrame) {
// Walk our parents to find a scrollbar frame
nsIFrame* scrollbarFrame = aFrame;
do {
if (scrollbarFrame->IsScrollbarFrame()) {
break;
}
} while ((scrollbarFrame = scrollbarFrame->GetParent()));
Maybe<nsITheme::Transparency> ScrollbarDrawingGTK::GetScrollbarPartTransparency(
nsIFrame* aFrame, StyleAppearance aAppearance) {
if (!aFrame->PresContext()->UseOverlayScrollbars() &&
(aAppearance == StyleAppearance::ScrollbarVertical ||
aAppearance == StyleAppearance::ScrollbarHorizontal) &&
IsScrollbarTrackOpaque(aFrame)) {
return Some(nsITheme::eOpaque);
}
// We return null if we can't find a parent scrollbar frame
return scrollbarFrame;
}
static bool IsParentScrollbarHoveredOrActive(nsIFrame* aFrame) {
nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame);
return scrollbarFrame && scrollbarFrame->GetContent()
->AsElement()
->State()
.HasAtLeastOneOfStates(NS_EVENT_STATE_HOVER |
NS_EVENT_STATE_ACTIVE);
return Nothing();
}
template <typename PaintBackendData>
bool nsNativeBasicThemeGTK::DoPaintScrollbarThumb(
bool ScrollbarDrawingGTK::DoPaintScrollbarThumb(
PaintBackendData& aPaintData, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aElementState, const EventStates& aDocumentState,
const Colors& aColors, DPIRatio aDpiRatio) {
const Colors& aColors, const DPIRatio& aDpiRatio) {
sRGBColor thumbColor = ComputeScrollbarThumbColor(
aFrame, aStyle, aElementState, aDocumentState, aColors);
LayoutDeviceRect thumbRect(aRect);
if (aFrame->PresContext()->UseOverlayScrollbars() &&
!IsParentScrollbarHoveredOrActive(aFrame)) {
!ScrollbarDrawing::IsParentScrollbarHoveredOrActive(aFrame)) {
if (aHorizontal) {
thumbRect.height *= 0.5;
thumbRect.y += thumbRect.height;
@@ -135,27 +92,35 @@ bool nsNativeBasicThemeGTK::DoPaintScrollbarThumb(
? (aHorizontal ? thumbRect.height : thumbRect.width) / 2.0f
: 0.0f;
PaintRoundedRectWithRadius(aPaintData, thumbRect, thumbColor, sRGBColor(), 0,
radius / aDpiRatio, aDpiRatio);
ThemeDrawing::PaintRoundedRectWithRadius(aPaintData, thumbRect, thumbColor,
sRGBColor(), 0, radius / aDpiRatio,
aDpiRatio);
return true;
}
bool nsNativeBasicThemeGTK::PaintScrollbarThumb(
bool ScrollbarDrawingGTK::PaintScrollbarThumb(
DrawTarget& aDrawTarget, const LayoutDeviceRect& aRect, bool aHorizontal,
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aElementState, const EventStates& aDocumentState,
const Colors& aColors, DPIRatio aDpiRatio) {
const Colors& aColors, const DPIRatio& aDpiRatio) {
return DoPaintScrollbarThumb(aDrawTarget, aRect, aHorizontal, aFrame, aStyle,
aElementState, aDocumentState, aColors,
aDpiRatio);
}
bool nsNativeBasicThemeGTK::PaintScrollbarThumb(
bool ScrollbarDrawingGTK::PaintScrollbarThumb(
WebRenderBackendData& aWrData, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aElementState, const EventStates& aDocumentState,
const Colors& aColors, DPIRatio aDpiRatio) {
const Colors& aColors, const DPIRatio& aDpiRatio) {
return DoPaintScrollbarThumb(aWrData, aRect, aHorizontal, aFrame, aStyle,
aElementState, aDocumentState, aColors,
aDpiRatio);
}
bool ScrollbarDrawingGTK::ShouldDrawScrollbarButtons() {
if (StaticPrefs::widget_non_native_theme_enabled()) {
return StaticPrefs::widget_non_native_theme_gtk_scrollbar_allow_buttons();
}
return true;
}

View File

@@ -1,48 +1,51 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
/* -*- 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/. */
#ifndef nsNativeBasicThemeGTK_h
#define nsNativeBasicThemeGTK_h
#ifndef mozilla_widget_ScrollbarDrawingGTK_h
#define mozilla_widget_ScrollbarDrawingGTK_h
#include "nsNativeBasicTheme.h"
#include "nsITheme.h"
#include "nsNativeTheme.h"
#include "ScrollbarDrawing.h"
class nsNativeBasicThemeGTK : public nsNativeBasicTheme {
namespace mozilla::widget {
class ScrollbarDrawingGTK final : public ScrollbarDrawing {
public:
nsNativeBasicThemeGTK() = default;
ScrollbarDrawingGTK() = default;
virtual ~ScrollbarDrawingGTK() = default;
Transparency GetWidgetTransparency(nsIFrame*, StyleAppearance) override;
LayoutDeviceIntSize GetMinimumWidgetSize(nsPresContext*,
StyleAppearance aAppearance,
nsIFrame* aFrame) override;
NS_IMETHOD GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame*,
StyleAppearance,
mozilla::LayoutDeviceIntSize* aResult,
bool* aIsOverridable) override;
Maybe<nsITheme::Transparency> GetScrollbarPartTransparency(
nsIFrame* aFrame, StyleAppearance aAppearance) override;
bool PaintScrollbarThumb(DrawTarget&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*,
const ComputedStyle& aStyle,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
DPIRatio) override;
bool PaintScrollbarThumb(WebRenderBackendData&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*,
const ComputedStyle& aStyle,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
DPIRatio) override;
template <typename PaintBackendData>
bool DoPaintScrollbarThumb(PaintBackendData&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*, const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
DPIRatio);
const DPIRatio&);
bool PaintScrollbarThumb(DrawTarget&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*,
const ComputedStyle& aStyle,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
const DPIRatio&) override;
bool PaintScrollbarThumb(WebRenderBackendData&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*,
const ComputedStyle& aStyle,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
const DPIRatio&) override;
bool ThemeSupportsScrollbarButtons() override;
protected:
virtual ~nsNativeBasicThemeGTK() = default;
bool ShouldDrawScrollbarButtons() override;
};
} // namespace mozilla::widget
#endif

View File

@@ -1,79 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_widget_ScrollbarDrawing_h
#define mozilla_widget_ScrollbarDrawing_h
#include "nsColor.h"
#include "nsITheme.h"
#include "Units.h"
#include "mozilla/Array.h"
namespace mozilla {
namespace gfx {
class DrawTarget;
}
namespace widget {
struct ScrollbarParams {
bool overlay = false;
bool rolledOver = false;
bool small = false;
bool horizontal = false;
bool rtl = false;
bool onDarkBackground = false;
bool custom = false;
// Two colors only used when custom is true.
nscolor trackColor = NS_RGBA(0, 0, 0, 0);
nscolor faceColor = NS_RGBA(0, 0, 0, 0);
};
class ScrollbarDrawingMac final {
public:
struct FillRect {
gfx::Rect mRect;
nscolor mColor;
};
static CSSIntCoord GetScrollbarSize(StyleScrollbarWidth, bool aOverlay);
static LayoutDeviceIntCoord GetScrollbarSize(StyleScrollbarWidth,
bool aOverlay, float aDpiRatio);
static LayoutDeviceIntSize GetMinimumWidgetSize(StyleAppearance aAppearance,
nsIFrame* aFrame,
float aDpiRatio);
static ScrollbarParams ComputeScrollbarParams(nsIFrame* aFrame,
const ComputedStyle& aStyle,
bool aIsHorizontal);
// The caller can draw this rectangle with rounded corners as appropriate.
struct ThumbRect {
gfx::Rect mRect;
nscolor mFillColor;
nscolor mStrokeColor;
float mStrokeWidth;
float mStrokeOutset;
};
static ThumbRect GetThumbRect(const gfx::Rect& aRect,
const ScrollbarParams& aParams, float aScale);
using ScrollbarTrackRects = Array<FillRect, 4>;
static bool GetScrollbarTrackRects(const gfx::Rect& aRect,
const ScrollbarParams& aParams,
float aScale, ScrollbarTrackRects&);
using ScrollCornerRects = Array<FillRect, 7>;
static bool GetScrollCornerRects(const gfx::Rect& aRect,
const ScrollbarParams& aParams, float aScale,
ScrollCornerRects&);
};
} // namespace widget
} // namespace mozilla
#endif

View File

@@ -0,0 +1,152 @@
/* -*- 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 "nsNativeBasicTheme.h"
#include "nsNativeTheme.h"
using mozilla::ComputedStyle;
using mozilla::EventStates;
using mozilla::Maybe;
using mozilla::Nothing;
using mozilla::Some;
using mozilla::StyleAppearance;
using mozilla::StyleScrollbarWidth;
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::ScrollbarthumbVertical:
case StyleAppearance::ScrollbarthumbHorizontal: {
auto* style = nsLayoutUtils::StyleForScrollbar(aFrame);
auto width = style->StyleUIReset()->mScrollbarWidth;
auto sizes = GetScrollbarSizes(aPresContext, width, Overlay::No);
// TODO: for short scrollbars it could be nice if the thumb could shrink
// under this size.
const bool isHorizontal =
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;
}
}
}
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!
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);
}

View File

@@ -0,0 +1,50 @@
/* -*- 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/. */
#ifndef mozilla_widget_ScrollbarDrawingWin_h
#define mozilla_widget_ScrollbarDrawingWin_h
#include "nsITheme.h"
#include "nsNativeTheme.h"
#include "ScrollbarDrawing.h"
namespace mozilla::widget {
class ScrollbarDrawingWin final : public ScrollbarDrawing {
public:
ScrollbarDrawingWin() = default;
virtual ~ScrollbarDrawingWin() = default;
LayoutDeviceIntSize GetMinimumWidgetSize(nsPresContext*,
StyleAppearance aAppearance,
nsIFrame* aFrame) override;
Maybe<nsITheme::Transparency> GetScrollbarPartTransparency(
nsIFrame* aFrame, StyleAppearance aAppearance) override;
static ComputedStyle* GetCustomScrollbarStyle(nsIFrame* aFrame,
bool* aDarkScrollbar = nullptr);
template <typename PaintBackendData>
bool DoPaintScrollbarThumb(PaintBackendData&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*, const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
const DPIRatio&);
bool PaintScrollbarThumb(DrawTarget&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*, const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
const DPIRatio&) override;
bool PaintScrollbarThumb(WebRenderBackendData&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*, const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
const DPIRatio&) override;
};
} // namespace mozilla::widget
#endif

233
widget/ThemeColors.cpp Normal file
View File

@@ -0,0 +1,233 @@
/* -*- 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 "ThemeColors.h"
#include "mozilla/RelativeLuminanceUtils.h"
#include "mozilla/StaticPrefs_widget.h"
#include "ThemeDrawing.h"
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::widget;
struct ColorPalette {
ColorPalette(nscolor aAccent, nscolor aForeground);
constexpr ColorPalette(sRGBColor aAccent, sRGBColor aForeground,
sRGBColor aLight, sRGBColor aDark, sRGBColor aDarker)
: mAccent(aAccent),
mForeground(aForeground),
mAccentLight(aLight),
mAccentDark(aDark),
mAccentDarker(aDarker) {}
constexpr static ColorPalette Default() {
return ColorPalette(
sDefaultAccent, sDefaultAccentForeground,
sRGBColor::UnusualFromARGB(0x4d008deb), // Luminance: 25.04791%
sRGBColor::UnusualFromARGB(0xff0250bb), // Luminance: 9.33808%
sRGBColor::UnusualFromARGB(0xff054096) // Luminance: 5.90106%
);
}
// Ensure accent color is opaque by blending with white. This serves two
// purposes: On one hand, it avoids surprises if we overdraw. On the other, it
// makes our math below make more sense, as we want to match the browser
// style, which has an opaque accent color.
static nscolor EnsureOpaque(nscolor aAccent) {
if (NS_GET_A(aAccent) != 0xff) {
return NS_ComposeColors(NS_RGB(0xff, 0xff, 0xff), aAccent);
}
return aAccent;
}
static nscolor GetLight(nscolor aAccent) {
// The luminance from the light color divided by the one of the accent color
// in the default palette.
constexpr float kLightLuminanceScale = 25.048f / 13.693f;
const float lightLuminanceAdjust = ThemeColors::ScaleLuminanceBy(
RelativeLuminanceUtils::Compute(aAccent), kLightLuminanceScale);
nscolor lightColor =
RelativeLuminanceUtils::Adjust(aAccent, lightLuminanceAdjust);
return NS_RGBA(NS_GET_R(lightColor), NS_GET_G(lightColor),
NS_GET_B(lightColor), 0x4d);
}
static nscolor GetDark(nscolor aAccent) {
// Same deal as above (but without the alpha).
constexpr float kDarkLuminanceScale = 9.338f / 13.693f;
const float darkLuminanceAdjust = ThemeColors::ScaleLuminanceBy(
RelativeLuminanceUtils::Compute(aAccent), kDarkLuminanceScale);
return RelativeLuminanceUtils::Adjust(aAccent, darkLuminanceAdjust);
}
static nscolor GetDarker(nscolor aAccent) {
// Same deal as above.
constexpr float kDarkerLuminanceScale = 5.901f / 13.693f;
const float darkerLuminanceAdjust = ThemeColors::ScaleLuminanceBy(
RelativeLuminanceUtils::Compute(aAccent), kDarkerLuminanceScale);
return RelativeLuminanceUtils::Adjust(aAccent, darkerLuminanceAdjust);
}
sRGBColor mAccent;
sRGBColor mForeground;
// Note that depending on the exact accent color, lighter/darker might really
// be inverted.
sRGBColor mAccentLight;
sRGBColor mAccentDark;
sRGBColor mAccentDarker;
};
static nscolor ThemedAccentColor(bool aBackground) {
MOZ_ASSERT(StaticPrefs::widget_non_native_theme_use_theme_accent());
// TODO(emilio): In the future we should probably add dark-color-scheme
// support for non-native form controls.
return ColorPalette::EnsureOpaque(LookAndFeel::Color(
aBackground ? LookAndFeel::ColorID::MozAccentColor
: LookAndFeel::ColorID::MozAccentColorForeground,
LookAndFeel::ColorScheme::Light, LookAndFeel::UseStandins::No));
}
static ColorPalette sDefaultPalette = ColorPalette::Default();
ColorPalette::ColorPalette(nscolor aAccent, nscolor aForeground) {
mAccent = sRGBColor::FromABGR(aAccent);
mForeground = sRGBColor::FromABGR(aForeground);
mAccentLight = sRGBColor::FromABGR(GetLight(aAccent));
mAccentDark = sRGBColor::FromABGR(GetDark(aAccent));
mAccentDarker = sRGBColor::FromABGR(GetDarker(aAccent));
}
ThemeAccentColor::ThemeAccentColor(const ComputedStyle& aStyle) {
const auto& color = aStyle.StyleUI()->mAccentColor;
if (color.IsColor()) {
mAccentColor.emplace(
ColorPalette::EnsureOpaque(color.AsColor().CalcColor(aStyle)));
} else {
MOZ_ASSERT(color.IsAuto());
}
}
sRGBColor ThemeAccentColor::Get() const {
if (!mAccentColor) {
return sDefaultPalette.mAccent;
}
return sRGBColor::FromABGR(*mAccentColor);
}
sRGBColor ThemeAccentColor::GetForeground() const {
if (!mAccentColor) {
return sDefaultPalette.mForeground;
}
return sRGBColor::FromABGR(
ThemeColors::ComputeCustomAccentForeground(*mAccentColor));
}
sRGBColor ThemeAccentColor::GetLight() const {
if (!mAccentColor) {
return sDefaultPalette.mAccentLight;
}
return sRGBColor::FromABGR(ColorPalette::GetLight(*mAccentColor));
}
sRGBColor ThemeAccentColor::GetDark() const {
if (!mAccentColor) {
return sDefaultPalette.mAccentDark;
}
return sRGBColor::FromABGR(ColorPalette::GetDark(*mAccentColor));
}
sRGBColor ThemeAccentColor::GetDarker() const {
if (!mAccentColor) {
return sDefaultPalette.mAccentDarker;
}
return sRGBColor::FromABGR(ColorPalette::GetDarker(*mAccentColor));
}
bool ThemeColors::ShouldBeHighContrast(const nsPresContext& aPc) {
// We make sure that we're drawing backgrounds, since otherwise layout will
// darken our used text colors etc anyways, and that can cause contrast issues
// with dark high-contrast themes.
return aPc.GetBackgroundColorDraw() &&
PreferenceSheet::PrefsFor(*aPc.Document())
.NonNativeThemeShouldBeHighContrast();
}
/*static*/
void ThemeColors::RecomputeAccentColors() {
MOZ_RELEASE_ASSERT(NS_IsMainThread());
if (!StaticPrefs::widget_non_native_theme_use_theme_accent()) {
sDefaultPalette = ColorPalette::Default();
return;
}
sDefaultPalette =
ColorPalette(ThemedAccentColor(true), ThemedAccentColor(false));
}
/*static*/
nscolor ThemeColors::ComputeCustomAccentForeground(nscolor aColor) {
// Contrast ratio is defined in
// https://www.w3.org/TR/WCAG20/#contrast-ratiodef as:
//
// (L1 + 0.05) / (L2 + 0.05)
//
// Where L1 is the lighter color, and L2 is the darker one. So we determine
// whether we're dark or light and resolve the equation for the target ratio.
//
// So when lightening:
//
// L1 = k * (L2 + 0.05) - 0.05
//
// And when darkening:
//
// L2 = (L1 + 0.05) / k - 0.05
//
const float luminance = RelativeLuminanceUtils::Compute(aColor);
// We generally prefer white unless we can't because the color is really light
// and we can't provide reasonable contrast.
const float ratioWithWhite = 1.05f / (luminance + 0.05f);
const bool canBeWhite =
ratioWithWhite >=
StaticPrefs::layout_css_accent_color_min_contrast_ratio();
if (canBeWhite) {
return NS_RGB(0xff, 0xff, 0xff);
}
const float targetRatio =
StaticPrefs::layout_css_accent_color_darkening_target_contrast_ratio();
const float targetLuminance = (luminance + 0.05f) / targetRatio - 0.05f;
return RelativeLuminanceUtils::Adjust(aColor, targetLuminance);
}
nscolor ThemeColors::AdjustUnthemedScrollbarThumbColor(nscolor aFaceColor,
EventStates aStates) {
// In Windows 10, scrollbar thumb has the following colors:
//
// State | Color | Luminance
// -------+----------+----------
// Normal | Gray 205 | 61.0%
// Hover | Gray 166 | 38.1%
// Active | Gray 96 | 11.7%
//
// This function is written based on the ratios between the values.
bool isActive = aStates.HasState(NS_EVENT_STATE_ACTIVE);
bool isHover = aStates.HasState(NS_EVENT_STATE_HOVER);
if (!isActive && !isHover) {
return aFaceColor;
}
float luminance = RelativeLuminanceUtils::Compute(aFaceColor);
if (isActive) {
// 11.7 / 61.0
luminance = ScaleLuminanceBy(luminance, 0.192f);
} else {
// 38.1 / 61.0
luminance = ScaleLuminanceBy(luminance, 0.625f);
}
return RelativeLuminanceUtils::Adjust(aFaceColor, luminance);
}

106
widget/ThemeColors.h Normal file
View File

@@ -0,0 +1,106 @@
/* -*- 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/. */
#ifndef mozilla_widget_ThemeColors_h
#define mozilla_widget_ThemeColors_h
#include "mozilla/dom/Document.h"
#include "mozilla/gfx/Types.h"
#include "mozilla/LookAndFeel.h"
#include "nsIFrame.h"
namespace mozilla::widget {
static constexpr gfx::sRGBColor sDefaultAccent(
gfx::sRGBColor::UnusualFromARGB(0xff0060df)); // Luminance: 13.69346%
static constexpr gfx::sRGBColor sDefaultAccentForeground(
gfx::sRGBColor::OpaqueWhite());
class ThemeAccentColor {
protected:
using sRGBColor = mozilla::gfx::sRGBColor;
using ComputedStyle = mozilla::ComputedStyle;
Maybe<nscolor> mAccentColor;
public:
explicit ThemeAccentColor(const ComputedStyle& aStyle);
virtual ~ThemeAccentColor() = default;
sRGBColor Get() const;
sRGBColor GetForeground() const;
sRGBColor GetLight() const;
sRGBColor GetDark() const;
sRGBColor GetDarker() const;
};
// Widget color information associated to a particular frame.
class ThemeColors {
protected:
using Document = mozilla::dom::Document;
using sRGBColor = mozilla::gfx::sRGBColor;
using LookAndFeel = mozilla::LookAndFeel;
using StyleSystemColor = mozilla::StyleSystemColor;
using AccentColor = ThemeAccentColor;
const AccentColor mAccentColor;
const Document& mDoc;
const bool mHighContrast;
const LookAndFeel::ColorScheme mColorScheme;
public:
explicit ThemeColors(const nsIFrame* aFrame)
: mAccentColor(*aFrame->Style()),
mDoc(*aFrame->PresContext()->Document()),
mHighContrast(ShouldBeHighContrast(*aFrame->PresContext())),
mColorScheme(LookAndFeel::ColorSchemeForFrame(aFrame)) {}
virtual ~ThemeColors() = default;
[[nodiscard]] static float ScaleLuminanceBy(float aLuminance, float aFactor) {
return aLuminance >= 0.18f ? aLuminance * aFactor : aLuminance / aFactor;
}
const AccentColor& Accent() const { return mAccentColor; }
bool HighContrast() const { return mHighContrast; }
bool IsDark() const { return mColorScheme == LookAndFeel::ColorScheme::Dark; }
nscolor SystemNs(StyleSystemColor aColor) const {
return LookAndFeel::Color(aColor, mColorScheme,
LookAndFeel::ShouldUseStandins(mDoc, aColor));
}
sRGBColor System(StyleSystemColor aColor) const {
return sRGBColor::FromABGR(SystemNs(aColor));
}
template <typename Compute>
sRGBColor SystemOrElse(StyleSystemColor aColor, Compute aCompute) const {
if (auto color = LookAndFeel::GetColor(
aColor, mColorScheme,
LookAndFeel::ShouldUseStandins(mDoc, aColor))) {
return sRGBColor::FromABGR(*color);
}
return aCompute();
}
std::pair<sRGBColor, sRGBColor> SystemPair(StyleSystemColor aFirst,
StyleSystemColor aSecond) const {
return std::make_pair(System(aFirst), System(aSecond));
}
// Whether we should use system colors (for high contrast mode).
static bool ShouldBeHighContrast(const nsPresContext&);
static void RecomputeAccentColors();
static nscolor ComputeCustomAccentForeground(nscolor aColor);
static nscolor AdjustUnthemedScrollbarThumbColor(nscolor aFaceColor,
EventStates aStates);
};
} // namespace mozilla::widget
#endif

178
widget/ThemeDrawing.cpp Normal file
View File

@@ -0,0 +1,178 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "ThemeDrawing.h"
/*static*/
void ThemeDrawing::FillRect(DrawTarget& aDt, const LayoutDeviceRect& aRect,
const sRGBColor& aColor) {
aDt.FillRect(aRect.ToUnknownRect(), ColorPattern(ToDeviceColor(aColor)));
}
/*static*/
void ThemeDrawing::FillRect(WebRenderBackendData& aWrData,
const LayoutDeviceRect& aRect,
const sRGBColor& aColor) {
const bool kBackfaceIsVisible = true;
auto dest = wr::ToLayoutRect(aRect);
aWrData.mBuilder.PushRect(dest, dest, kBackfaceIsVisible,
wr::ToColorF(ToDeviceColor(aColor)));
}
/*static*/
LayoutDeviceIntCoord ThemeDrawing::SnapBorderWidth(const CSSCoord& aCssWidth,
const DPIRatio& aDpiRatio) {
if (aCssWidth == 0.0f) {
return 0;
}
return std::max(LayoutDeviceIntCoord(1), (aCssWidth * aDpiRatio).Truncated());
}
/*static*/
void ThemeDrawing::PaintArrow(DrawTarget& aDrawTarget,
const LayoutDeviceRect& aRect,
const float aArrowPolygonX[],
const float aArrowPolygonY[],
const float aArrowPolygonSize,
const int32_t aArrowNumPoints,
const sRGBColor aFillColor) {
const float scale = ScaleToFillRect(aRect, aArrowPolygonSize);
auto center = aRect.Center().ToUnknownPoint();
RefPtr<PathBuilder> builder = aDrawTarget.CreatePathBuilder();
Point p =
center + Point(aArrowPolygonX[0] * scale, aArrowPolygonY[0] * scale);
builder->MoveTo(p);
for (int32_t i = 1; i < aArrowNumPoints; i++) {
p = center + Point(aArrowPolygonX[i] * scale, aArrowPolygonY[i] * scale);
builder->LineTo(p);
}
RefPtr<Path> path = builder->Finish();
aDrawTarget.Fill(path, ColorPattern(ToDeviceColor(aFillColor)));
}
void ThemeDrawing::PaintRoundedRectWithRadius(
WebRenderBackendData& aWrData, const LayoutDeviceRect& aRect,
const LayoutDeviceRect& aClipRect, const sRGBColor& aBackgroundColor,
const sRGBColor& aBorderColor, const CSSCoord& aBorderWidth,
const CSSCoord& aRadius, const DPIRatio& aDpiRatio) {
const bool kBackfaceIsVisible = true;
const LayoutDeviceCoord borderWidth(SnapBorderWidth(aBorderWidth, aDpiRatio));
const LayoutDeviceCoord radius(aRadius * aDpiRatio);
const wr::LayoutRect dest = wr::ToLayoutRect(aRect);
const wr::LayoutRect clip = wr::ToLayoutRect(aClipRect);
// Push the background.
if (aBackgroundColor.a != 0.0f) {
auto backgroundColor = wr::ToColorF(ToDeviceColor(aBackgroundColor));
wr::LayoutRect backgroundRect = [&] {
LayoutDeviceRect bg = aRect;
bg.Deflate(borderWidth);
return wr::ToLayoutRect(bg);
}();
if (radius == 0.0f) {
aWrData.mBuilder.PushRect(backgroundRect, clip, kBackfaceIsVisible,
backgroundColor);
} else {
// NOTE(emilio): This follows DisplayListBuilder::PushRoundedRect and
// draws the rounded fill as an extra thick rounded border instead of a
// rectangle that's clipped to a rounded clip. Refer to that method for a
// justification. See bug 1694269.
LayoutDeviceCoord backgroundRadius =
std::max(0.0f, float(radius) - float(borderWidth));
wr::BorderSide side = {backgroundColor, wr::BorderStyle::Solid};
const wr::BorderSide sides[4] = {side, side, side, side};
float h = backgroundRect.width() * 0.6f;
float v = backgroundRect.height() * 0.6f;
wr::LayoutSideOffsets widths = {v, h, v, h};
wr::BorderRadius radii = {{backgroundRadius, backgroundRadius},
{backgroundRadius, backgroundRadius},
{backgroundRadius, backgroundRadius},
{backgroundRadius, backgroundRadius}};
aWrData.mBuilder.PushBorder(backgroundRect, clip, kBackfaceIsVisible,
widths, {sides, 4}, radii);
}
}
if (borderWidth != 0.0f && aBorderColor.a != 0.0f) {
// Push the border.
const auto borderColor = ToDeviceColor(aBorderColor);
const auto side = wr::ToBorderSide(borderColor, StyleBorderStyle::Solid);
const wr::BorderSide sides[4] = {side, side, side, side};
const LayoutDeviceSize sideRadius(radius, radius);
const auto widths =
wr::ToBorderWidths(borderWidth, borderWidth, borderWidth, borderWidth);
const auto wrRadius =
wr::ToBorderRadius(sideRadius, sideRadius, sideRadius, sideRadius);
aWrData.mBuilder.PushBorder(dest, clip, kBackfaceIsVisible, widths,
{sides, 4}, wrRadius);
}
}
void ThemeDrawing::PaintRoundedRectWithRadius(
DrawTarget& aDrawTarget, const LayoutDeviceRect& aRect,
const LayoutDeviceRect& aClipRect, const sRGBColor& aBackgroundColor,
const sRGBColor& aBorderColor, const CSSCoord& aBorderWidth,
const CSSCoord& aRadius, const DPIRatio& aDpiRatio) {
const LayoutDeviceCoord borderWidth(SnapBorderWidth(aBorderWidth, aDpiRatio));
const bool needsClip = !(aRect == aClipRect);
if (needsClip) {
aDrawTarget.PushClipRect(aClipRect.ToUnknownRect());
}
LayoutDeviceRect rect(aRect);
// Deflate the rect by half the border width, so that the middle of the
// stroke fills exactly the area we want to fill and not more.
rect.Deflate(borderWidth * 0.5f);
LayoutDeviceCoord radius(aRadius * aDpiRatio - borderWidth * 0.5f);
// Fix up the radius if it's too large with the rect we're going to paint.
{
LayoutDeviceCoord min = std::min(rect.width, rect.height);
if (radius * 2.0f > min) {
radius = min * 0.5f;
}
}
Maybe<ColorPattern> backgroundPattern;
if (aBackgroundColor.a != 0.0f) {
backgroundPattern.emplace(ToDeviceColor(aBackgroundColor));
}
Maybe<ColorPattern> borderPattern;
if (borderWidth != 0.0f && aBorderColor.a != 0.0f) {
borderPattern.emplace(ToDeviceColor(aBorderColor));
}
if (borderPattern || backgroundPattern) {
if (radius != 0.0f) {
RectCornerRadii radii(radius, radius, radius, radius);
RefPtr<Path> roundedRect =
MakePathForRoundedRect(aDrawTarget, rect.ToUnknownRect(), radii);
if (backgroundPattern) {
aDrawTarget.Fill(roundedRect, *backgroundPattern);
}
if (borderPattern) {
aDrawTarget.Stroke(roundedRect, *borderPattern,
StrokeOptions(borderWidth));
}
} else {
if (backgroundPattern) {
aDrawTarget.FillRect(rect.ToUnknownRect(), *backgroundPattern);
}
if (borderPattern) {
aDrawTarget.StrokeRect(rect.ToUnknownRect(), *borderPattern,
StrokeOptions(borderWidth));
}
}
}
if (needsClip) {
aDrawTarget.PopClip();
}
}

79
widget/ThemeDrawing.h Normal file
View File

@@ -0,0 +1,79 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_widget_ThemeDrawing_h
#define mozilla_widget_ThemeDrawing_h
#include "mozilla/layers/IpcResourceUpdateQueue.h"
#include "mozilla/layers/RenderRootStateManager.h"
#include "mozilla/layers/StackingContextHelper.h"
#include "RetainedDisplayListBuilder.h"
namespace mozilla::widget {
struct WebRenderBackendData {
wr::DisplayListBuilder& mBuilder;
wr::IpcResourceUpdateQueue& mResources;
const layers::StackingContextHelper& mSc;
layers::RenderRootStateManager* mManager;
};
class ThemeDrawing {
protected:
using DrawTarget = gfx::DrawTarget;
using sRGBColor = gfx::sRGBColor;
using DPIRatio = CSSToLayoutDeviceScale;
public:
virtual ~ThemeDrawing() = 0;
static void FillRect(DrawTarget&, const LayoutDeviceRect&, const sRGBColor&);
static void FillRect(WebRenderBackendData&, const LayoutDeviceRect&,
const sRGBColor&);
// Returns the right scale for points in a aSize x aSize sized box, centered
// at 0x0 to fill aRect in the smaller dimension.
static float ScaleToFillRect(const LayoutDeviceRect& aRect,
const float& aSize) {
return std::min(aRect.width, aRect.height) / aSize;
}
static LayoutDeviceIntCoord SnapBorderWidth(const CSSCoord& aCssWidth,
const DPIRatio& aDpiRatio);
static void PaintArrow(DrawTarget&, const LayoutDeviceRect&,
const float aArrowPolygonX[],
const float aArrowPolygonY[],
const float aArrowPolygonSize,
const int32_t aArrowNumPoints,
const sRGBColor aFillColor);
static void PaintRoundedRectWithRadius(
DrawTarget&, const LayoutDeviceRect& aRect,
const LayoutDeviceRect& aClipRect, const sRGBColor& aBackgroundColor,
const sRGBColor& aBorderColor, const CSSCoord& aBorderWidth,
const CSSCoord& aRadius, const DPIRatio&);
static void PaintRoundedRectWithRadius(
WebRenderBackendData&, const LayoutDeviceRect& aRect,
const LayoutDeviceRect& aClipRect, const sRGBColor& aBackgroundColor,
const sRGBColor& aBorderColor, const CSSCoord& aBorderWidth,
const CSSCoord& aRadius, const DPIRatio&);
template <typename PaintBackendData>
static void PaintRoundedRectWithRadius(PaintBackendData& aData,
const LayoutDeviceRect& aRect,
const sRGBColor& aBackgroundColor,
const sRGBColor& aBorderColor,
const CSSCoord& aBorderWidth,
const CSSCoord& aRadius,
const DPIRatio& aDpiRatio) {
PaintRoundedRectWithRadius(aData, aRect, aRect, aBackgroundColor,
aBorderColor, aBorderWidth, aRadius, aDpiRatio);
}
};
} // namespace mozilla::widget
#endif

View File

@@ -16,8 +16,10 @@
#include "mozilla/java/GeckoAppShellWrappers.h"
#include "mozilla/java/GeckoRuntimeWrappers.h"
#include "mozilla/java/GeckoSystemStateListenerWrappers.h"
#include "ThemeColors.h"
using namespace mozilla;
using namespace mozilla::widget;
static const char16_t UNICODE_BULLET = 0x2022;
@@ -191,10 +193,9 @@ nsresult nsLookAndFeel::NativeGetColor(ColorID aID, ColorScheme aColorScheme,
case ColorID::MozCellhighlighttext:
case ColorID::Selecteditemtext:
case ColorID::MozAccentColorForeground:
aColor = UseNativeAccent()
? nsNativeBasicTheme::ComputeCustomAccentForeground(
mSystemColors.colorAccent)
: widget::sDefaultAccentForeground.ToABGR();
aColor = UseNativeAccent() ? ThemeColors::ComputeCustomAccentForeground(
mSystemColors.colorAccent)
: widget::sDefaultAccentForeground.ToABGR();
break;
case ColorID::Fieldtext:
aColor = NS_RGB(0x1a, 0x1a, 0x1a);

View File

@@ -64,7 +64,6 @@ UNIFIED_SOURCES += [
"nsMenuItemX.mm",
"nsMenuUtilsX.mm",
"nsMenuX.mm",
"nsNativeBasicThemeCocoa.cpp",
"nsPrintDialogX.mm",
"nsPrintSettingsServiceX.mm",
"nsPrintSettingsX.mm",
@@ -113,6 +112,7 @@ include("/ipc/chromium/chromium-config.mozbuild")
FINAL_LIBRARY = "xul"
LOCAL_INCLUDES += [
"/dom/events",
"/dom/media/platforms/apple",
"/layout/base",
"/layout/forms",

View File

@@ -1,192 +0,0 @@
/* -*- 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 "nsNativeBasicThemeCocoa.h"
#include "mozilla/gfx/Helpers.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/LookAndFeel.h"
#include "mozilla/ServoStyleConsts.h"
#include "MacThemeGeometryType.h"
already_AddRefed<nsITheme> do_GetBasicNativeThemeDoNotUseDirectly() {
static mozilla::StaticRefPtr<nsITheme> gInstance;
if (MOZ_UNLIKELY(!gInstance)) {
gInstance = new nsNativeBasicThemeCocoa();
ClearOnShutdown(&gInstance);
}
return do_AddRef(gInstance);
}
NS_IMETHODIMP
nsNativeBasicThemeCocoa::GetMinimumWidgetSize(
nsPresContext* aPresContext, nsIFrame* aFrame, StyleAppearance aAppearance,
mozilla::LayoutDeviceIntSize* aResult, bool* aIsOverridable) {
if (!IsWidgetScrollbarPart(aAppearance)) {
return nsNativeBasicTheme::GetMinimumWidgetSize(
aPresContext, aFrame, aAppearance, aResult, aIsOverridable);
}
DPIRatio dpiRatio = GetDPIRatioForScrollbarPart(aPresContext);
*aIsOverridable = false;
*aResult = ScrollbarDrawingMac::GetMinimumWidgetSize(aAppearance, aFrame,
dpiRatio.scale);
return NS_OK;
}
bool nsNativeBasicThemeCocoa::ThemeSupportsWidget(nsPresContext* aPc,
nsIFrame* aFrame,
StyleAppearance aAppearance) {
switch (aAppearance) {
case StyleAppearance::Tooltip:
return true;
default:
break;
}
return nsNativeBasicTheme::ThemeSupportsWidget(aPc, aFrame, aAppearance);
}
nsITheme::ThemeGeometryType nsNativeBasicThemeCocoa::ThemeGeometryTypeForWidget(
nsIFrame* aFrame, StyleAppearance aAppearance) {
switch (aAppearance) {
case StyleAppearance::Tooltip:
return eThemeGeometryTypeTooltip;
default:
break;
}
return nsNativeBasicTheme::ThemeGeometryTypeForWidget(aFrame, aAppearance);
}
auto nsNativeBasicThemeCocoa::GetScrollbarSizes(nsPresContext* aPresContext,
StyleScrollbarWidth aWidth,
Overlay aOverlay)
-> ScrollbarSizes {
auto size = ScrollbarDrawingMac::GetScrollbarSize(
aWidth, aOverlay == Overlay::Yes,
GetDPIRatioForScrollbarPart(aPresContext).scale);
return {size, size};
}
template <typename PaintBackendData>
void nsNativeBasicThemeCocoa::DoPaintScrollbarThumb(
PaintBackendData& aPaintData, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aElementState, const EventStates& aDocumentState,
DPIRatio aDpiRatio) {
ScrollbarParams params =
ScrollbarDrawingMac::ComputeScrollbarParams(aFrame, aStyle, aHorizontal);
auto thumb = ScrollbarDrawingMac::GetThumbRect(aRect.ToUnknownRect(), params,
aDpiRatio.scale);
auto thumbRect = LayoutDeviceRect::FromUnknownRect(thumb.mRect);
LayoutDeviceCoord radius =
(params.horizontal ? thumbRect.Height() : thumbRect.Width()) / 2.0f;
PaintRoundedRectWithRadius(
aPaintData, thumbRect, thumbRect, sRGBColor::FromABGR(thumb.mFillColor),
sRGBColor::White(0.0f), 0.0f, radius / aDpiRatio, aDpiRatio);
if (!thumb.mStrokeColor) {
return;
}
// Paint the stroke if needed.
thumbRect.Inflate(thumb.mStrokeOutset + thumb.mStrokeWidth);
radius = (params.horizontal ? thumbRect.Height() : thumbRect.Width()) / 2.0f;
PaintRoundedRectWithRadius(aPaintData, thumbRect, sRGBColor::White(0.0f),
sRGBColor::FromABGR(thumb.mStrokeColor),
thumb.mStrokeWidth, radius / aDpiRatio, aDpiRatio);
}
bool nsNativeBasicThemeCocoa::PaintScrollbarThumb(
DrawTarget& aDt, const LayoutDeviceRect& aRect, bool aHorizontal,
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aElementState, const EventStates& aDocumentState,
const Colors&, DPIRatio aDpiRatio) {
// TODO: Maybe respect the UseSystemColors setting?
DoPaintScrollbarThumb(aDt, aRect, aHorizontal, aFrame, aStyle, aElementState,
aDocumentState, aDpiRatio);
return true;
}
bool nsNativeBasicThemeCocoa::PaintScrollbarThumb(
WebRenderBackendData& aWrData, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aElementState, const EventStates& aDocumentState,
const Colors&, DPIRatio aDpiRatio) {
// TODO: Maybe respect the UseSystemColors setting?
DoPaintScrollbarThumb(aWrData, aRect, aHorizontal, aFrame, aStyle,
aElementState, aDocumentState, aDpiRatio);
return true;
}
template <typename PaintBackendData>
void nsNativeBasicThemeCocoa::DoPaintScrollbarTrack(
PaintBackendData& aPaintData, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, DPIRatio aDpiRatio) {
ScrollbarParams params =
ScrollbarDrawingMac::ComputeScrollbarParams(aFrame, aStyle, aHorizontal);
ScrollbarDrawingMac::ScrollbarTrackRects rects;
if (ScrollbarDrawingMac::GetScrollbarTrackRects(aRect.ToUnknownRect(), params,
aDpiRatio.scale, rects)) {
for (const auto& rect : rects) {
FillRect(aPaintData, LayoutDeviceRect::FromUnknownRect(rect.mRect),
sRGBColor::FromABGR(rect.mColor));
}
}
}
bool nsNativeBasicThemeCocoa::PaintScrollbarTrack(
DrawTarget& aDt, const LayoutDeviceRect& aRect, bool aHorizontal,
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors&, DPIRatio aDpiRatio) {
// TODO: Maybe respect the UseSystemColors setting?
DoPaintScrollbarTrack(aDt, aRect, aHorizontal, aFrame, aStyle, aDocumentState,
aDpiRatio);
return true;
}
bool nsNativeBasicThemeCocoa::PaintScrollbarTrack(
WebRenderBackendData& aWrData, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors&, DPIRatio aDpiRatio) {
// TODO: Maybe respect the UseSystemColors setting?
DoPaintScrollbarTrack(aWrData, aRect, aHorizontal, aFrame, aStyle,
aDocumentState, aDpiRatio);
return true;
}
template <typename PaintBackendData>
void nsNativeBasicThemeCocoa::DoPaintScrollCorner(
PaintBackendData& aPaintData, const LayoutDeviceRect& aRect,
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, DPIRatio aDpiRatio) {
ScrollbarParams params =
ScrollbarDrawingMac::ComputeScrollbarParams(aFrame, aStyle, false);
ScrollbarDrawingMac::ScrollCornerRects rects;
if (ScrollbarDrawingMac::GetScrollCornerRects(aRect.ToUnknownRect(), params,
aDpiRatio.scale, rects)) {
for (const auto& rect : rects) {
FillRect(aPaintData, LayoutDeviceRect::FromUnknownRect(rect.mRect),
sRGBColor::FromABGR(rect.mColor));
}
}
}
bool nsNativeBasicThemeCocoa::PaintScrollCorner(
DrawTarget& aDt, const LayoutDeviceRect& aRect, nsIFrame* aFrame,
const ComputedStyle& aStyle, const EventStates& aDocumentState,
const Colors&, DPIRatio aDpiRatio) {
// TODO: Maybe respect the UseSystemColors setting?
DoPaintScrollCorner(aDt, aRect, aFrame, aStyle, aDocumentState, aDpiRatio);
return true;
}
bool nsNativeBasicThemeCocoa::PaintScrollCorner(
WebRenderBackendData& aWrData, const LayoutDeviceRect& aRect,
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors&, DPIRatio aDpiRatio) {
// TODO: Maybe respect the UseSystemColors setting?
DoPaintScrollCorner(aWrData, aRect, aFrame, aStyle, aDocumentState,
aDpiRatio);
return true;
}

View File

@@ -1,107 +0,0 @@
/* -*- Mode: C++; tab-width: 2; 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/. */
#ifndef nsNativeBasicThemeCocoa_h
#define nsNativeBasicThemeCocoa_h
#include "nsNativeBasicTheme.h"
#include "ScrollbarDrawingMac.h"
class nsNativeBasicThemeCocoa : public nsNativeBasicTheme {
public:
nsNativeBasicThemeCocoa() = default;
using ScrollbarParams = mozilla::widget::ScrollbarParams;
using ScrollbarDrawingMac = mozilla::widget::ScrollbarDrawingMac;
NS_IMETHOD GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aFrame,
StyleAppearance aAppearance,
mozilla::LayoutDeviceIntSize* aResult,
bool* aIsOverridable) override;
ScrollbarSizes GetScrollbarSizes(nsPresContext*, StyleScrollbarWidth,
Overlay) override;
template <typename PaintBackendData>
void DoPaintScrollbarThumb(PaintBackendData&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aElementState,
const EventStates& aDocumentState, DPIRatio);
bool PaintScrollbarThumb(DrawTarget&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
DPIRatio) override;
bool PaintScrollbarThumb(WebRenderBackendData&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
DPIRatio) override;
template <typename PaintBackendData>
void DoPaintScrollbarTrack(PaintBackendData&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aDocumentState,
DPIRatio aDpiRatio);
bool PaintScrollbarTrack(DrawTarget&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors&,
DPIRatio) override;
bool PaintScrollbarTrack(WebRenderBackendData&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors&,
DPIRatio) override;
bool PaintScrollbar(DrawTarget&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
DPIRatio) override {
// Draw nothing; the scrollbar track is drawn in PaintScrollbarTrack.
return true;
}
bool PaintScrollbar(WebRenderBackendData&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
DPIRatio) override {
// Draw nothing; the scrollbar track is drawn in PaintScrollbarTrack.
return true;
}
template <typename PaintBackendData>
void DoPaintScrollCorner(PaintBackendData&, const LayoutDeviceRect& aRect,
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState,
DPIRatio aDpiRatio);
bool PaintScrollCorner(DrawTarget&, const LayoutDeviceRect& aRect,
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors&,
DPIRatio aDpiRatio) override;
bool PaintScrollCorner(WebRenderBackendData&, const LayoutDeviceRect& aRect,
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors&,
DPIRatio aDpiRatio) override;
ThemeGeometryType ThemeGeometryTypeForWidget(nsIFrame*,
StyleAppearance) override;
bool ThemeSupportsWidget(nsPresContext*, nsIFrame*, StyleAppearance) override;
protected:
virtual ~nsNativeBasicThemeCocoa() = default;
};
#endif

View File

@@ -16,7 +16,8 @@
#include "nsCOMPtr.h"
#include "nsAtom.h"
#include "nsNativeTheme.h"
#include "ScrollbarDrawingMac.h"
#include "nsNativeBasicThemeCocoa.h"
#include "ScrollbarDrawingCocoa.h"
@class MOZCellDrawWindow;
@class MOZCellDrawView;
@@ -32,7 +33,10 @@ class DrawTarget;
} // namespace gfx
} // namespace mozilla
class nsNativeThemeCocoa : private nsNativeTheme, public nsITheme {
class nsNativeThemeCocoa : public nsNativeBasicThemeCocoa {
protected:
using ScrollbarDrawingCocoa = mozilla::widget::ScrollbarDrawingCocoa;
public:
enum class MenuIcon : uint8_t {
eCheckmark,
@@ -168,7 +172,7 @@ class nsNativeThemeCocoa : private nsNativeTheme, public nsITheme {
bool reverse = false;
};
using ScrollbarParams = mozilla::widget::ScrollbarParams;
using ScrollbarParams = mozilla::widget::ScrollbarDrawing::ScrollbarParams;
enum Widget : uint8_t {
eColorFill, // mozilla::gfx::sRGBColor
@@ -308,9 +312,7 @@ class nsNativeThemeCocoa : private nsNativeTheme, public nsITheme {
enum Widget mWidget;
};
using ScrollbarDrawingMac = mozilla::widget::ScrollbarDrawingMac;
nsNativeThemeCocoa();
explicit nsNativeThemeCocoa(mozilla::UniquePtr<ScrollbarDrawing>&& aScrollbarDrawingCocoa);
NS_DECL_ISUPPORTS_INHERITED

View File

@@ -53,6 +53,7 @@
using namespace mozilla;
using namespace mozilla::gfx;
using mozilla::dom::HTMLMeterElement;
using ScrollbarDrawingCocoa = mozilla::widget::ScrollbarDrawingCocoa;
#define DRAW_IN_FRAME_DEBUG 0
#define SCROLLBARS_VISUAL_DEBUG 0
@@ -400,7 +401,9 @@ static bool IsInSourceList(nsIFrame* aFrame) {
NS_IMPL_ISUPPORTS_INHERITED(nsNativeThemeCocoa, nsNativeTheme, nsITheme)
nsNativeThemeCocoa::nsNativeThemeCocoa() {
nsNativeThemeCocoa::nsNativeThemeCocoa(
mozilla::UniquePtr<ScrollbarDrawing>&& aScrollbarDrawingCocoa)
: nsNativeBasicThemeCocoa(std::move(aScrollbarDrawingCocoa)) {
NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
kMaxFocusRingWidth = 7;
@@ -2513,7 +2516,7 @@ Maybe<nsNativeThemeCocoa::WidgetInfo> nsNativeThemeCocoa::ComputeWidgetInfo(
case StyleAppearance::Scrollcorner: {
bool isHorizontal = aAppearance == StyleAppearance::ScrollbarthumbHorizontal ||
aAppearance == StyleAppearance::ScrollbartrackHorizontal;
ScrollbarParams params = ScrollbarDrawingMac::ComputeScrollbarParams(
ScrollbarParams params = GetScrollbarDrawing().ComputeScrollbarParams(
aFrame, *nsLayoutUtils::StyleForScrollbar(aFrame), isHorizontal);
switch (aAppearance) {
case StyleAppearance::ScrollbarthumbVertical:
@@ -2629,7 +2632,7 @@ void nsNativeThemeCocoa::RenderWidget(const WidgetInfo& aWidgetInfo,
}
case Widget::eScrollbarThumb: {
ScrollbarParams params = aWidgetInfo.Params<ScrollbarParams>();
auto thumb = ScrollbarDrawingMac::GetThumbRect(aWidgetRect, params, aScale);
auto thumb = ScrollbarDrawingCocoa::GetThumbRect(aWidgetRect, params, aScale);
float cornerRadius = (params.horizontal ? thumb.mRect.Height() : thumb.mRect.Width()) / 2.0f;
aDrawTarget.FillRoundedRect(RoundedRect(thumb.mRect, RectCornerRadii(cornerRadius)),
ColorPattern(ToDeviceColor(thumb.mFillColor)));
@@ -2646,8 +2649,8 @@ void nsNativeThemeCocoa::RenderWidget(const WidgetInfo& aWidgetInfo,
}
case Widget::eScrollbarTrack: {
ScrollbarParams params = aWidgetInfo.Params<ScrollbarParams>();
ScrollbarDrawingMac::ScrollbarTrackRects rects;
if (ScrollbarDrawingMac::GetScrollbarTrackRects(aWidgetRect, params, aScale, rects)) {
ScrollbarDrawingCocoa::ScrollbarTrackRects rects;
if (ScrollbarDrawingCocoa::GetScrollbarTrackRects(aWidgetRect, params, aScale, rects)) {
for (const auto& rect : rects) {
aDrawTarget.FillRect(rect.mRect, ColorPattern(ToDeviceColor(rect.mColor)));
}
@@ -2656,8 +2659,8 @@ void nsNativeThemeCocoa::RenderWidget(const WidgetInfo& aWidgetInfo,
}
case Widget::eScrollCorner: {
ScrollbarParams params = aWidgetInfo.Params<ScrollbarParams>();
ScrollbarDrawingMac::ScrollCornerRects rects;
if (ScrollbarDrawingMac::GetScrollCornerRects(aWidgetRect, params, aScale, rects)) {
ScrollbarDrawingCocoa::ScrollCornerRects rects;
if (ScrollbarDrawingCocoa::GetScrollCornerRects(aWidgetRect, params, aScale, rects)) {
for (const auto& rect : rects) {
aDrawTarget.FillRect(rect.mRect, ColorPattern(ToDeviceColor(rect.mColor)));
}
@@ -2913,7 +2916,7 @@ bool nsNativeThemeCocoa::CreateWebRenderCommandsForWidget(
case StyleAppearance::ScrollbartrackHorizontal:
case StyleAppearance::ScrollbartrackVertical: {
const ComputedStyle& style = *nsLayoutUtils::StyleForScrollbar(aFrame);
ScrollbarParams params = ScrollbarDrawingMac::ComputeScrollbarParams(
ScrollbarParams params = GetScrollbarDrawing().ComputeScrollbarParams(
aFrame, style, aAppearance == StyleAppearance::ScrollbartrackHorizontal);
if (params.overlay && !params.rolledOver) {
// There is no scrollbar track, draw nothing and return true.
@@ -3145,7 +3148,7 @@ bool nsNativeThemeCocoa::GetWidgetOverflow(nsDeviceContext* aContext, nsIFrame*
auto nsNativeThemeCocoa::GetScrollbarSizes(nsPresContext* aPresContext, StyleScrollbarWidth aWidth,
Overlay aOverlay) -> ScrollbarSizes {
auto size = ScrollbarDrawingMac::GetScrollbarSize(aWidth, aOverlay == Overlay::Yes);
auto size = ScrollbarDrawingCocoa::GetScrollbarSize(aWidth, aOverlay == Overlay::Yes);
if (IsHiDPIContext(aPresContext->DeviceContext())) {
size *= 2;
}
@@ -3161,6 +3164,11 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame*
aResult->SizeTo(0, 0);
*aIsOverridable = true;
if (IsWidgetScrollbarPart(aAppearance)) {
return nsNativeBasicThemeCocoa::GetMinimumWidgetSize(aPresContext, aFrame, aAppearance, aResult,
aIsOverridable);
}
switch (aAppearance) {
case StyleAppearance::Button: {
aResult->SizeTo(pushButtonSettings.minimumSizes[miniControlSize].width,
@@ -3291,24 +3299,9 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame*
break;
}
case StyleAppearance::ScrollbarthumbHorizontal:
case StyleAppearance::ScrollbarthumbVertical:
case StyleAppearance::ScrollbarHorizontal:
case StyleAppearance::ScrollbarVertical:
case StyleAppearance::ScrollbartrackVertical:
case StyleAppearance::ScrollbartrackHorizontal:
case StyleAppearance::ScrollbarbuttonUp:
case StyleAppearance::ScrollbarbuttonDown:
case StyleAppearance::ScrollbarbuttonLeft:
case StyleAppearance::ScrollbarbuttonRight: {
*aIsOverridable = false;
*aResult = ScrollbarDrawingMac::GetMinimumWidgetSize(aAppearance, aFrame, 1.0f);
break;
}
case StyleAppearance::MozMenulistArrowButton:
*aResult = ScrollbarDrawingMac::GetMinimumWidgetSize(aAppearance, aFrame, 1.0f);
break;
return nsNativeBasicThemeCocoa::GetMinimumWidgetSize(aPresContext, aFrame, aAppearance,
aResult, aIsOverridable);
case StyleAppearance::Resizer: {
HIThemeGrowBoxDrawInfo drawInfo;
@@ -3663,7 +3656,7 @@ already_AddRefed<nsITheme> do_GetNativeThemeDoNotUseDirectly() {
static nsCOMPtr<nsITheme> inst;
if (!inst) {
inst = new nsNativeThemeCocoa();
inst = new nsNativeThemeCocoa(MakeUnique<ScrollbarDrawingCocoa>());
ClearOnShutdown(&inst);
}

View File

@@ -28,6 +28,8 @@ extern mozilla::LazyLogModule gWidgetWaylandLog;
# define LOGWAYLAND(args)
#endif /* MOZ_LOGGING */
using namespace mozilla::gl;
namespace mozilla::widget {
#define BUFFER_BPP 4

View File

@@ -55,7 +55,6 @@ UNIFIED_SOURCES += [
"nsGtkKeyUtils.cpp",
"nsImageToPixbuf.cpp",
"nsLookAndFeel.cpp",
"nsNativeBasicThemeGTK.cpp",
"nsSound.cpp",
"nsToolkit.cpp",
"nsWidgetFactory.cpp",

View File

@@ -31,7 +31,7 @@
#include "mozilla/ScopeExit.h"
#include "mozilla/WidgetUtilsGtk.h"
#include "ScreenHelperGTK.h"
#include "nsNativeBasicThemeGTK.h"
#include "ScrollbarDrawing.h"
#include "gtkdrawing.h"
#include "nsStyleConsts.h"
@@ -47,6 +47,7 @@
#include "nsCSSColorUtils.h"
using namespace mozilla;
using namespace mozilla::widget;
#ifdef MOZ_LOGGING
# include "mozilla/Logging.h"
@@ -1518,12 +1519,11 @@ void nsLookAndFeel::PerThemeData::Init() {
mMozScrollbar = mThemedScrollbar = widget::sScrollbarColor.ToABGR();
mThemedScrollbarInactive = widget::sScrollbarColor.ToABGR();
mThemedScrollbarThumb = widget::sScrollbarThumbColor.ToABGR();
mThemedScrollbarThumbHover =
nsNativeBasicTheme::AdjustUnthemedScrollbarThumbColor(
mThemedScrollbarThumb, NS_EVENT_STATE_HOVER);
mThemedScrollbarThumbHover = ThemeColors::AdjustUnthemedScrollbarThumbColor(
mThemedScrollbarThumb, NS_EVENT_STATE_HOVER);
mThemedScrollbarThumbActive =
nsNativeBasicTheme::AdjustUnthemedScrollbarThumbColor(
mThemedScrollbarThumb, NS_EVENT_STATE_ACTIVE);
ThemeColors::AdjustUnthemedScrollbarThumbColor(mThemedScrollbarThumb,
NS_EVENT_STATE_ACTIVE);
mThemedScrollbarThumbInactive = mThemedScrollbarThumb;
}

View File

@@ -44,6 +44,7 @@
#include "nsWindow.h"
#include "nsLayoutUtils.h"
#include "nsNativeBasicTheme.h"
#include "ScrollbarDrawingGTK.h"
#ifdef MOZ_X11
# ifdef CAIRO_HAS_XLIB_SURFACE
@@ -58,6 +59,7 @@ using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::widget;
using mozilla::dom::HTMLInputElement;
using ScrollbarDrawingGTK = mozilla::widget::ScrollbarDrawingGTK;
static int gLastGdkError;
@@ -96,7 +98,9 @@ static inline gint GetMonitorScaleFactor(nsIFrame* aFrame) {
return GetMonitorScaleFactor(aFrame->PresContext());
}
nsNativeThemeGTK::nsNativeThemeGTK() {
nsNativeThemeGTK::nsNativeThemeGTK(
mozilla::UniquePtr<ScrollbarDrawing>&& aScrollbarDrawingGTK)
: nsNativeBasicTheme(std::move(aScrollbarDrawingGTK)) {
if (moz_gtk_init() != MOZ_GTK_SUCCESS) {
memset(mDisabledWidgetTypes, 0xff, sizeof(mDisabledWidgetTypes));
return;
@@ -1049,7 +1053,7 @@ nsNativeThemeGTK::DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
const nsRect& aDirtyRect,
DrawOverflow aDrawOverflow) {
if (IsWidgetNonNative(aFrame, aAppearance) != NonNative::No) {
return nsNativeBasicThemeGTK::DrawWidgetBackground(
return nsNativeBasicTheme::DrawWidgetBackground(
aContext, aFrame, aAppearance, aRect, aDirtyRect, aDrawOverflow);
}
@@ -1178,7 +1182,7 @@ bool nsNativeThemeGTK::CreateWebRenderCommandsForWidget(
mozilla::layers::RenderRootStateManager* aManager, nsIFrame* aFrame,
StyleAppearance aAppearance, const nsRect& aRect) {
if (IsWidgetNonNative(aFrame, aAppearance) != NonNative::No) {
return nsNativeBasicThemeGTK::CreateWebRenderCommandsForWidget(
return nsNativeBasicTheme::CreateWebRenderCommandsForWidget(
aBuilder, aResources, aSc, aManager, aFrame, aAppearance, aRect);
}
return false;
@@ -1389,8 +1393,8 @@ bool nsNativeThemeGTK::GetWidgetOverflow(nsDeviceContext* aContext,
StyleAppearance aAppearance,
nsRect* aOverflowRect) {
if (IsWidgetNonNative(aFrame, aAppearance) != NonNative::No) {
return nsNativeBasicThemeGTK::GetWidgetOverflow(aContext, aFrame,
aAppearance, aOverflowRect);
return nsNativeBasicTheme::GetWidgetOverflow(aContext, aFrame, aAppearance,
aOverflowRect);
}
nsIntMargin extraSize;
@@ -1418,8 +1422,8 @@ auto nsNativeThemeGTK::IsWidgetNonNative(nsIFrame* aFrame,
return NonNative::Always;
}
// We can't draw light widgets if the current GTK theme is dark or vice versa.
if (nsNativeBasicThemeGTK::ThemeSupportsWidget(aFrame->PresContext(), aFrame,
aAppearance) &&
if (nsNativeBasicTheme::ThemeSupportsWidget(aFrame->PresContext(), aFrame,
aAppearance) &&
LookAndFeel::ColorSchemeForFrame(aFrame) !=
LookAndFeel::ColorSchemeForChrome()) {
return NonNative::BecauseColorMismatch;
@@ -1434,7 +1438,7 @@ nsNativeThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext,
LayoutDeviceIntSize* aResult,
bool* aIsOverridable) {
if (IsWidgetNonNative(aFrame, aAppearance) == NonNative::Always) {
return nsNativeBasicThemeGTK::GetMinimumWidgetSize(
return nsNativeBasicTheme::GetMinimumWidgetSize(
aPresContext, aFrame, aAppearance, aResult, aIsOverridable);
}
@@ -1683,7 +1687,7 @@ nsNativeThemeGTK::WidgetStateChanged(nsIFrame* aFrame,
*aShouldRepaint = false;
if (IsWidgetNonNative(aFrame, aAppearance) != NonNative::No) {
return nsNativeBasicThemeGTK::WidgetStateChanged(
return nsNativeBasicTheme::WidgetStateChanged(
aFrame, aAppearance, aAttribute, aShouldRepaint, aOldValue);
}
@@ -1794,8 +1798,8 @@ nsNativeThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext,
}
if (IsWidgetNonNative(aFrame, aAppearance) == NonNative::Always) {
return nsNativeBasicThemeGTK::ThemeSupportsWidget(aPresContext, aFrame,
aAppearance);
return nsNativeBasicTheme::ThemeSupportsWidget(aPresContext, aFrame,
aAppearance);
}
if (IsWidgetScrollbarPart(aAppearance)) {
@@ -1946,7 +1950,7 @@ bool nsNativeThemeGTK::ThemeNeedsComboboxDropmarker() { return false; }
nsITheme::Transparency nsNativeThemeGTK::GetWidgetTransparency(
nsIFrame* aFrame, StyleAppearance aAppearance) {
if (IsWidgetNonNative(aFrame, aAppearance) != NonNative::No) {
return nsNativeBasicThemeGTK::GetWidgetTransparency(aFrame, aAppearance);
return nsNativeBasicTheme::GetWidgetTransparency(aFrame, aAppearance);
}
switch (aAppearance) {
@@ -1973,8 +1977,8 @@ auto nsNativeThemeGTK::GetScrollbarSizes(nsPresContext* aPresContext,
StyleScrollbarWidth aWidth,
Overlay aOverlay) -> ScrollbarSizes {
if (StaticPrefs::widget_non_native_theme_enabled()) {
return nsNativeBasicThemeGTK::GetScrollbarSizes(aPresContext, aWidth,
aOverlay);
return nsNativeBasicTheme::GetScrollbarSizes(aPresContext, aWidth,
aOverlay);
}
CSSIntCoord vertical;
@@ -1994,13 +1998,6 @@ auto nsNativeThemeGTK::GetScrollbarSizes(nsPresContext* aPresContext,
return {int32_t(vertical) * scale, int32_t(horizontal) * scale};
}
bool nsNativeThemeGTK::ThemeSupportsScrollbarButtons() {
if (StaticPrefs::widget_non_native_theme_enabled()) {
return nsNativeBasicThemeGTK::ThemeSupportsScrollbarButtons();
}
return true;
}
already_AddRefed<nsITheme> do_GetNativeThemeDoNotUseDirectly() {
static nsCOMPtr<nsITheme> inst;
@@ -2008,7 +2005,7 @@ already_AddRefed<nsITheme> do_GetNativeThemeDoNotUseDirectly() {
if (gfxPlatform::IsHeadless()) {
inst = new HeadlessThemeGTK();
} else {
inst = new nsNativeThemeGTK();
inst = new nsNativeThemeGTK(MakeUnique<ScrollbarDrawingGTK>());
}
ClearOnShutdown(&inst);
}

View File

@@ -11,12 +11,13 @@
#include "nsAtom.h"
#include "nsNativeTheme.h"
#include "nsStyleConsts.h"
#include "nsNativeBasicThemeGTK.h"
#include "nsNativeBasicTheme.h"
#include "ScrollbarDrawingGTK.h"
#include <gtk/gtk.h>
#include "gtkdrawing.h"
class nsNativeThemeGTK final : public nsNativeBasicThemeGTK {
class nsNativeThemeGTK final : public nsNativeBasicTheme {
public:
// The nsITheme interface.
NS_IMETHOD DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
@@ -84,9 +85,8 @@ class nsNativeThemeGTK final : public nsNativeBasicThemeGTK {
ScrollbarSizes GetScrollbarSizes(nsPresContext*, StyleScrollbarWidth,
Overlay) override;
bool ThemeSupportsScrollbarButtons() override;
nsNativeThemeGTK();
explicit nsNativeThemeGTK(
mozilla::UniquePtr<ScrollbarDrawing>&& aScrollbarDrawingGTK);
protected:
virtual ~nsNativeThemeGTK();

View File

@@ -21,6 +21,7 @@
#include "nsIPrintSettingsService.h"
#include "nsPIDOMWindow.h"
#include "nsIGIOService.h"
#include "nsServiceManagerUtils.h"
#include "WidgetUtils.h"
#include "WidgetUtilsGtk.h"
#include "nsIObserverService.h"

View File

@@ -54,6 +54,8 @@ class HeadlessThemeGTK final : private nsNativeTheme, public nsITheme {
ScrollbarSizes GetScrollbarSizes(nsPresContext*, StyleScrollbarWidth,
Overlay) override;
bool ThemeSupportsScrollbarButtons() override { return true; }
protected:
virtual ~HeadlessThemeGTK() = default;
};

View File

@@ -201,8 +201,7 @@ UNIFIED_SOURCES += [
"nsHTMLFormatConverter.cpp",
"nsIWidgetListener.cpp",
"nsNativeBasicTheme.cpp",
# Android non-native theme is built on all platforms for RDM.
"nsNativeBasicThemeAndroid.cpp",
"nsNativeBasicThemeCocoa.cpp",
"nsPrimitiveHelpers.cpp",
"nsPrintSettingsImpl.cpp",
"nsSoundProxy.cpp",
@@ -213,9 +212,15 @@ UNIFIED_SOURCES += [
"PuppetWidget.cpp",
"RemoteLookAndFeel.cpp",
"Screen.cpp",
"ScrollbarDrawingMac.cpp",
"ScrollbarDrawing.cpp",
"ScrollbarDrawingAndroid.cpp",
"ScrollbarDrawingCocoa.cpp",
"ScrollbarDrawingGTK.cpp",
"ScrollbarDrawingWin.cpp",
"SharedWidgetUtils.cpp",
"TextEventDispatcher.cpp",
"ThemeColors.cpp",
"ThemeDrawing.cpp",
"TouchResampler.cpp",
"VsyncDispatcher.cpp",
"WidgetEventImpl.cpp",

View File

@@ -7,6 +7,7 @@
#include "nsClipboardHelper.h"
// basics
#include "nsComponentManagerUtils.h"
#include "nsCOMPtr.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"

View File

@@ -12,6 +12,7 @@
#include "nsXULAppAPI.h"
#include "nsContentUtils.h"
#include "nsStringStream.h"
#include "PermissionMessageUtils.h"
using namespace mozilla;
using namespace mozilla::dom;

View File

@@ -51,8 +51,8 @@ nsresult nsDragServiceProxy::InvokeDragSessionImpl(
nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
cookieJarSettings = mSourceDocument->CookieJarSettings();
net::CookieJarSettingsArgs csArgs;
net::CookieJarSettings::Cast(cookieJarSettings)->Serialize(csArgs);
mozilla::net::CookieJarSettingsArgs csArgs;
mozilla::net::CookieJarSettings::Cast(cookieJarSettings)->Serialize(csArgs);
LayoutDeviceIntRect dragRect;
if (mHasImage || mSelection) {

File diff suppressed because it is too large Load Diff

View File

@@ -13,6 +13,7 @@
#include "mozilla/gfx/Types.h"
#include "nsITheme.h"
#include "nsNativeTheme.h"
#include "ScrollbarDrawing.h"
namespace mozilla {
@@ -20,11 +21,6 @@ enum class StyleSystemColor : uint8_t;
namespace widget {
static constexpr gfx::sRGBColor sDefaultAccent(
gfx::sRGBColor::UnusualFromARGB(0xff0060df)); // Luminance: 13.69346%
static constexpr gfx::sRGBColor sDefaultAccentForeground(
gfx::sRGBColor::OpaqueWhite());
static constexpr gfx::sRGBColor sColorGrey10(
gfx::sRGBColor::UnusualFromARGB(0xffe9e9ed));
static constexpr gfx::sRGBColor sColorGrey10Alpha50(
@@ -55,13 +51,6 @@ static constexpr gfx::sRGBColor sColorMeterRed10(
static constexpr gfx::sRGBColor sColorMeterRed20(
gfx::sRGBColor::UnusualFromARGB(0xff810220));
static constexpr gfx::sRGBColor sScrollbarColor(
gfx::sRGBColor::UnusualFromARGB(0xfff0f0f0));
static constexpr gfx::sRGBColor sScrollbarBorderColor(gfx::sRGBColor(1.0f, 1.0f,
1.0f));
static constexpr gfx::sRGBColor sScrollbarThumbColor(
gfx::sRGBColor::UnusualFromARGB(0xffcdcdcd));
static const CSSCoord kMinimumColorPickerHeight = 32.0f;
static const CSSCoord kMinimumRangeThumbSize = 20.0f;
static const CSSCoord kMinimumDropdownArrowButtonWidth = 18.0f;
@@ -96,10 +85,16 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
using RectCornerRadii = mozilla::gfx::RectCornerRadii;
using LayoutDeviceCoord = mozilla::LayoutDeviceCoord;
using LayoutDeviceRect = mozilla::LayoutDeviceRect;
class AccentColor;
class Colors;
using Colors = mozilla::widget::ThemeColors;
using AccentColor = mozilla::widget::ThemeAccentColor;
using ScrollbarDrawing = mozilla::widget::ScrollbarDrawing;
using WebRenderBackendData = mozilla::widget::WebRenderBackendData;
public:
explicit nsNativeBasicTheme(
mozilla::UniquePtr<ScrollbarDrawing>&& aScrollbarDrawing)
: mScrollbarDrawing(std::move(aScrollbarDrawing)) {}
static void Init();
static void Shutdown();
static void LookAndFeelChanged();
@@ -114,13 +109,6 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
const nsRect& aDirtyRect,
DrawOverflow) override;
struct WebRenderBackendData {
mozilla::wr::DisplayListBuilder& mBuilder;
mozilla::wr::IpcResourceUpdateQueue& mResources;
const mozilla::layers::StackingContextHelper& mSc;
mozilla::layers::RenderRootStateManager* mManager;
};
bool CreateWebRenderCommandsForWidget(
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
@@ -163,24 +151,15 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
bool ThemeNeedsComboboxDropmarker() override;
ScrollbarSizes GetScrollbarSizes(nsPresContext*, StyleScrollbarWidth,
Overlay) override;
static nscolor AdjustUnthemedScrollbarThumbColor(nscolor, EventStates);
static nscolor GetScrollbarButtonColor(nscolor aTrackColor, EventStates);
static mozilla::Maybe<nscolor> GetScrollbarArrowColor(nscolor aButtonColor);
static nscolor ComputeCustomAccentForeground(nscolor aAccent);
nscoord GetCheckboxRadioPrefSize() override;
protected:
nsNativeBasicTheme() = default;
virtual ~nsNativeBasicTheme() = default;
static DPIRatio GetDPIRatioForScrollbarPart(nsPresContext*);
static DPIRatio GetDPIRatio(nsPresContext*, StyleAppearance);
static DPIRatio GetDPIRatio(nsIFrame*, StyleAppearance);
// Whether we should use system colors (for high contrast mode).
static bool ShouldBeHighContrast(const nsPresContext&);
std::pair<sRGBColor, sRGBColor> ComputeCheckboxColors(const EventStates&,
StyleAppearance,
const Colors&);
@@ -207,21 +186,6 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
const EventStates& aMeterState, const Colors&);
std::array<sRGBColor, 3> ComputeFocusRectColors(const Colors&);
static bool ShouldUseDarkScrollbar(nsIFrame*, const ComputedStyle&);
bool IsScrollbarTrackOpaque(nsIFrame*);
sRGBColor ComputeScrollbarTrackColor(nsIFrame*, const ComputedStyle&,
const EventStates& aDocumentState,
const Colors&);
sRGBColor ComputeScrollbarThumbColor(nsIFrame*, const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState,
const Colors&);
// Returned colors are button, arrow.
std::pair<sRGBColor, sRGBColor> ComputeScrollbarButtonColors(
nsIFrame*, StyleAppearance, const ComputedStyle&,
const EventStates& aElementState, const EventStates& aDocumentState,
const Colors&);
template <typename PaintBackendData>
void PaintRoundedFocusRect(PaintBackendData&, const LayoutDeviceRect&,
const Colors&, DPIRatio, CSSCoord aRadius,
@@ -230,35 +194,6 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
void PaintAutoStyleOutline(nsIFrame*, PaintBackendData&,
const LayoutDeviceRect&, const Colors&, DPIRatio);
static void PaintRoundedRectWithRadius(DrawTarget&,
const LayoutDeviceRect& aRect,
const LayoutDeviceRect& aClipRect,
const sRGBColor& aBackgroundColor,
const sRGBColor& aBorderColor,
CSSCoord aBorderWidth,
CSSCoord aRadius, DPIRatio);
static void PaintRoundedRectWithRadius(WebRenderBackendData&,
const LayoutDeviceRect& aRect,
const LayoutDeviceRect& aClipRect,
const sRGBColor& aBackgroundColor,
const sRGBColor& aBorderColor,
CSSCoord aBorderWidth,
CSSCoord aRadius, DPIRatio);
template <typename PaintBackendData>
static void PaintRoundedRectWithRadius(PaintBackendData& aData,
const LayoutDeviceRect& aRect,
const sRGBColor& aBackgroundColor,
const sRGBColor& aBorderColor,
CSSCoord aBorderWidth,
CSSCoord aRadius, DPIRatio aDpiRatio) {
PaintRoundedRectWithRadius(aData, aRect, aRect, aBackgroundColor,
aBorderColor, aBorderWidth, aRadius, aDpiRatio);
}
static void FillRect(DrawTarget&, const LayoutDeviceRect&, const sRGBColor&);
static void FillRect(WebRenderBackendData&, const LayoutDeviceRect&,
const sRGBColor&);
void PaintCheckboxControl(DrawTarget& aDrawTarget, const LayoutDeviceRect&,
const EventStates&, const Colors&, DPIRatio);
void PaintCheckMark(DrawTarget&, const LayoutDeviceRect&, const EventStates&,
@@ -295,10 +230,6 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
template <typename PaintBackendData>
void PaintMenulist(PaintBackendData&, const LayoutDeviceRect&,
const EventStates&, const Colors&, DPIRatio);
void PaintArrow(DrawTarget&, const LayoutDeviceRect&,
const float aArrowPolygonX[], const float aArrowPolygonY[],
const float aArrowPolygonSize, const int32_t aArrowNumPoints,
const sRGBColor aFillColor);
void PaintMenulistArrowButton(nsIFrame*, DrawTarget&, const LayoutDeviceRect&,
const EventStates&);
void PaintSpinnerButton(nsIFrame*, DrawTarget&, const LayoutDeviceRect&,
@@ -316,88 +247,12 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
void PaintButton(nsIFrame*, PaintBackendData&, const LayoutDeviceRect&,
const EventStates&, const Colors&, DPIRatio);
void PaintScrollbarButton(DrawTarget&, StyleAppearance,
const LayoutDeviceRect&, nsIFrame*,
const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
DPIRatio);
virtual bool PaintScrollbarThumb(DrawTarget&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*,
const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState,
const Colors&, DPIRatio);
virtual bool PaintScrollbarThumb(WebRenderBackendData&,
const LayoutDeviceRect&, bool aHorizontal,
nsIFrame*, const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState,
const Colors&, DPIRatio);
template <typename PaintBackendData>
bool DoPaintDefaultScrollbarThumb(PaintBackendData&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*,
const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState,
const Colors&, DPIRatio);
virtual bool PaintScrollbar(DrawTarget&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*, const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
DPIRatio);
virtual bool PaintScrollbar(WebRenderBackendData&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*, const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
DPIRatio);
template <typename PaintBackendData>
bool DoPaintDefaultScrollbar(PaintBackendData&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*,
const ComputedStyle&,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
DPIRatio);
virtual bool PaintScrollbarTrack(DrawTarget&, const LayoutDeviceRect&,
bool aHorizontal, nsIFrame*,
const ComputedStyle&,
const EventStates& aDocumentState,
const Colors&, DPIRatio) {
// Draw nothing by default. Subclasses can override this.
return true;
}
virtual bool PaintScrollbarTrack(WebRenderBackendData&,
const LayoutDeviceRect&, bool aHorizontal,
nsIFrame*, const ComputedStyle&,
const EventStates& aDocumentState,
const Colors&, DPIRatio) {
// Draw nothing by default. Subclasses can override this.
return true;
}
virtual bool PaintScrollCorner(DrawTarget&, const LayoutDeviceRect&,
nsIFrame*, const ComputedStyle&,
const EventStates& aDocumentState,
const Colors&, DPIRatio);
virtual bool PaintScrollCorner(WebRenderBackendData&, const LayoutDeviceRect&,
nsIFrame*, const ComputedStyle&,
const EventStates& aDocumentState,
const Colors&, DPIRatio);
template <typename PaintBackendData>
bool DoPaintDefaultScrollCorner(PaintBackendData&, const LayoutDeviceRect&,
nsIFrame*, const ComputedStyle&,
const EventStates& aDocumentState,
const Colors&, DPIRatio);
static CSSIntCoord sHorizontalScrollbarHeight;
static CSSIntCoord sVerticalScrollbarWidth;
static void PrefChangedCallback(const char*, void*) { LookAndFeelChanged(); }
static void RecomputeAccentColors();
static void RecomputeScrollbarParams();
ScrollbarDrawing& GetScrollbarDrawing() const { return *mScrollbarDrawing; }
mozilla::UniquePtr<ScrollbarDrawing> mScrollbarDrawing;
bool ThemeSupportsScrollbarButtons() override;
};
#endif

View File

@@ -1,100 +0,0 @@
/* -*- Mode: C++; tab-width: 2; 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/. */
#ifndef nsNativeBasicThemeAndroid_h
#define nsNativeBasicThemeAndroid_h
#include "nsNativeBasicTheme.h"
class nsNativeBasicThemeAndroid final : public nsNativeBasicTheme {
public:
nsNativeBasicThemeAndroid() = default;
NS_IMETHOD GetMinimumWidgetSize(nsPresContext*, nsIFrame*, StyleAppearance,
mozilla::LayoutDeviceIntSize* aResult,
bool* aIsOverridable) override;
ScrollbarSizes GetScrollbarSizes(nsPresContext*, StyleScrollbarWidth,
Overlay) override;
template <typename PaintBackendData>
void DoPaintScrollbarThumb(PaintBackendData&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
DPIRatio);
bool PaintScrollbarThumb(DrawTarget&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
DPIRatio) override;
bool PaintScrollbarThumb(WebRenderBackendData&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
DPIRatio) override;
bool PaintScrollbarTrack(DrawTarget&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors&,
DPIRatio) override {
// There's no visible track on android.
return true;
}
bool PaintScrollbarTrack(WebRenderBackendData&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors&,
DPIRatio) override {
// There's no visible track on Android.
return true;
}
bool PaintScrollbar(DrawTarget&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
DPIRatio) override {
// Draw nothing, we only draw the thumb.
return true;
}
bool PaintScrollbar(WebRenderBackendData&, const LayoutDeviceRect& aRect,
bool aHorizontal, nsIFrame* aFrame,
const ComputedStyle& aStyle,
const EventStates& aElementState,
const EventStates& aDocumentState, const Colors&,
DPIRatio) override {
// Draw nothing, we only draw the thumb.
return true;
}
bool PaintScrollCorner(DrawTarget&, const LayoutDeviceRect& aRect,
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors&,
DPIRatio aDpiRatio) override {
// Draw nothing, we only draw the thumb.
return true;
}
bool PaintScrollCorner(WebRenderBackendData&, const LayoutDeviceRect& aRect,
nsIFrame* aFrame, const ComputedStyle& aStyle,
const EventStates& aDocumentState, const Colors&,
DPIRatio aDpiRatio) override {
// Draw nothing, we only draw the thumb.
return true;
}
bool ThemeSupportsScrollbarButtons() override { return false; }
protected:
virtual ~nsNativeBasicThemeAndroid() = default;
};
#endif

View File

@@ -0,0 +1,55 @@
/* -*- 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 "nsNativeBasicThemeCocoa.h"
#include "cocoa/MacThemeGeometryType.h"
#include "gfxPlatform.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/gfx/Helpers.h"
#include "mozilla/LookAndFeel.h"
#include "mozilla/ServoStyleConsts.h"
using ScrollbarDrawingCocoa = mozilla::widget::ScrollbarDrawingCocoa;
using namespace mozilla::gfx;
NS_IMETHODIMP
nsNativeBasicThemeCocoa::GetMinimumWidgetSize(
nsPresContext* aPresContext, nsIFrame* aFrame, StyleAppearance aAppearance,
mozilla::LayoutDeviceIntSize* aResult, bool* aIsOverridable) {
if (aAppearance == StyleAppearance::MozMenulistArrowButton) {
auto size = ScrollbarDrawingCocoa::GetScrollbarSize(
StyleScrollbarWidth::Auto, /* aOverlay = */ false,
GetDPIRatio(aFrame, aAppearance));
aResult->SizeTo(size, size);
return NS_OK;
}
return nsNativeBasicTheme::GetMinimumWidgetSize(
aPresContext, aFrame, aAppearance, aResult, aIsOverridable);
}
nsITheme::ThemeGeometryType nsNativeBasicThemeCocoa::ThemeGeometryTypeForWidget(
nsIFrame* aFrame, StyleAppearance aAppearance) {
switch (aAppearance) {
case StyleAppearance::Tooltip:
return eThemeGeometryTypeTooltip;
default:
break;
}
return nsNativeBasicTheme::ThemeGeometryTypeForWidget(aFrame, aAppearance);
}
bool nsNativeBasicThemeCocoa::ThemeSupportsWidget(nsPresContext* aPc,
nsIFrame* aFrame,
StyleAppearance aAppearance) {
switch (aAppearance) {
case StyleAppearance::Tooltip:
return true;
default:
break;
}
return nsNativeBasicTheme::ThemeSupportsWidget(aPc, aFrame, aAppearance);
}

View File

@@ -0,0 +1,36 @@
/* -*- Mode: C++; tab-width: 2; 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/. */
#ifndef nsNativeBasicThemeCocoa_h
#define nsNativeBasicThemeCocoa_h
#include "nsNativeBasicTheme.h"
#include "ScrollbarDrawingCocoa.h"
class nsNativeBasicThemeCocoa : public nsNativeBasicTheme {
protected:
using ScrollbarDrawingCocoa = mozilla::widget::ScrollbarDrawingCocoa;
public:
explicit nsNativeBasicThemeCocoa(
mozilla::UniquePtr<ScrollbarDrawing>&& aScrollbarDrawing)
: nsNativeBasicTheme(std::move(aScrollbarDrawing)) {}
NS_IMETHOD GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aFrame,
StyleAppearance aAppearance,
mozilla::LayoutDeviceIntSize* aResult,
bool* aIsOverridable) override;
ThemeGeometryType ThemeGeometryTypeForWidget(nsIFrame*,
StyleAppearance) override;
bool ThemeSupportsWidget(nsPresContext*, nsIFrame*, StyleAppearance) override;
protected:
virtual ~nsNativeBasicThemeCocoa() = default;
};
#endif

View File

@@ -5,7 +5,9 @@
#include "nsPrinterCUPS.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/GkRustUtils.h"
#include "mozilla/Preferences.h"
#include "mozilla/StaticPrefs_print.h"
#include "nsTHashtable.h"
#include "nsPaper.h"
@@ -14,6 +16,7 @@
#include "plstr.h"
using namespace mozilla;
using MarginDouble = mozilla::gfx::MarginDouble;
// Requested attributes for IPP requests, just the CUPS version now.
static constexpr Array<const char* const, 1> requestedAttributes{

View File

@@ -6,12 +6,19 @@
#include "nsPrinterListBase.h"
#include "PrintBackgroundTask.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/gfx/Rect.h"
#include "mozilla/IntegerRange.h"
#include "mozilla/intl/Localization.h"
#include "mozilla/Maybe.h"
#include "mozilla/RefPtr.h"
#include "xpcpublic.h"
using namespace mozilla;
using mozilla::ErrorResult;
using mozilla::intl::Localization;
using PrinterInfo = nsPrinterListBase::PrinterInfo;
using MarginDouble = mozilla::gfx::MarginDouble;
nsPrinterListBase::nsPrinterListBase() = default;
nsPrinterListBase::~nsPrinterListBase() = default;

View File

@@ -1,133 +0,0 @@
/* -*- 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 "ScrollbarUtil.h"
#include "mozilla/Maybe.h"
#include "mozilla/RelativeLuminanceUtils.h"
#include "mozilla/StaticPrefs_widget.h"
#include "nsLayoutUtils.h"
#include "nsNativeTheme.h"
#include "nsNativeBasicTheme.h"
using mozilla::ComputedStyle;
using mozilla::EventStates;
using mozilla::Maybe;
using mozilla::Nothing;
using mozilla::RelativeLuminanceUtils;
using mozilla::Some;
using mozilla::StyleAppearance;
using mozilla::StyleScrollbarWidth;
namespace StaticPrefs = mozilla::StaticPrefs;
/*static*/
bool ScrollbarUtil::IsScrollbarWidthThin(ComputedStyle* aStyle) {
auto scrollbarWidth = aStyle->StyleUIReset()->mScrollbarWidth;
return scrollbarWidth == StyleScrollbarWidth::Thin;
}
/*static*/
bool ScrollbarUtil::IsScrollbarWidthThin(nsIFrame* aFrame) {
ComputedStyle* style = nsLayoutUtils::StyleForScrollbar(aFrame);
return IsScrollbarWidthThin(style);
}
/*static*/
ComputedStyle* ScrollbarUtil::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;
}
/*static*/
nscolor ScrollbarUtil::GetScrollbarTrackColor(nsIFrame* aFrame) {
bool darkScrollbar = false;
ComputedStyle* style = GetCustomScrollbarStyle(aFrame, &darkScrollbar);
if (style) {
const nsStyleUI* ui = style->StyleUI();
auto* customColors = ui->mScrollbarColor.IsAuto()
? nullptr
: &ui->mScrollbarColor.AsColors();
if (customColors) {
return customColors->track.CalcColor(*style);
}
}
return darkScrollbar ? NS_RGBA(20, 20, 25, 77) : NS_RGB(240, 240, 240);
}
/*static*/
nscolor ScrollbarUtil::GetScrollbarThumbColor(nsIFrame* aFrame,
EventStates aEventStates) {
bool darkScrollbar = false;
ComputedStyle* style = GetCustomScrollbarStyle(aFrame, &darkScrollbar);
nscolor color =
darkScrollbar ? NS_RGBA(249, 249, 250, 102) : NS_RGB(205, 205, 205);
if (style) {
const nsStyleUI* ui = style->StyleUI();
auto* customColors = ui->mScrollbarColor.IsAuto()
? nullptr
: &ui->mScrollbarColor.AsColors();
if (customColors) {
color = customColors->thumb.CalcColor(*style);
}
}
return nsNativeBasicTheme::AdjustUnthemedScrollbarThumbColor(color,
aEventStates);
}
/*static*/
Maybe<nsITheme::Transparency> ScrollbarUtil::GetScrollbarPartTransparency(
nsIFrame* aFrame, StyleAppearance aAppearance) {
if (nsNativeTheme::IsWidgetScrollbarPart(aAppearance)) {
if (ComputedStyle* style = ScrollbarUtil::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;
}
}
}
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!
return Some(nsITheme::eOpaque);
default:
break;
}
return Nothing();
}

View File

@@ -1,36 +0,0 @@
/* -*- 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/. */
#ifndef ScrollbarUtil_h
#define ScrollbarUtil_h
#include "nsITheme.h"
#include "nsNativeTheme.h"
class ScrollbarUtil {
public:
static bool IsScrollbarWidthThin(mozilla::ComputedStyle* aStyle);
static bool IsScrollbarWidthThin(nsIFrame* aFrame);
// 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 mozilla::ComputedStyle* GetCustomScrollbarStyle(
nsIFrame* aFrame, bool* aDarkScrollbar = nullptr);
static nscolor GetScrollbarTrackColor(nsIFrame* aFrame);
static nscolor GetScrollbarThumbColor(nsIFrame* aFrame,
mozilla::EventStates aEventStates);
static mozilla::Maybe<nsITheme::Transparency> GetScrollbarPartTransparency(
nsIFrame* aFrame, mozilla::StyleAppearance aAppearance);
protected:
ScrollbarUtil() = default;
virtual ~ScrollbarUtil() = default;
};
#endif

View File

@@ -75,7 +75,6 @@ UNIFIED_SOURCES += [
"nsDataObjCollection.cpp",
"nsDragService.cpp",
"nsLookAndFeel.cpp",
"nsNativeBasicThemeWin.cpp",
"nsNativeDragSource.cpp",
"nsNativeDragTarget.cpp",
"nsNativeThemeWin.cpp",
@@ -92,7 +91,6 @@ UNIFIED_SOURCES += [
"OSKVRManager.cpp",
"RemoteBackbuffer.cpp",
"ScreenHelperWin.cpp",
"ScrollbarUtil.cpp",
"SystemStatusBar.cpp",
"TaskbarPreview.cpp",
"TaskbarPreviewButton.cpp",

View File

@@ -1,27 +0,0 @@
/* -*- 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 "nsNativeBasicThemeWin.h"
#include "mozilla/ClearOnShutdown.h"
#include "ScrollbarUtil.h"
nsITheme::Transparency nsNativeBasicThemeWin::GetWidgetTransparency(
nsIFrame* aFrame, StyleAppearance aAppearance) {
if (auto transparency =
ScrollbarUtil::GetScrollbarPartTransparency(aFrame, aAppearance)) {
return *transparency;
}
return nsNativeBasicTheme::GetWidgetTransparency(aFrame, aAppearance);
}
already_AddRefed<nsITheme> do_GetBasicNativeThemeDoNotUseDirectly() {
static mozilla::StaticRefPtr<nsITheme> gInstance;
if (MOZ_UNLIKELY(!gInstance)) {
gInstance = new nsNativeBasicThemeWin();
ClearOnShutdown(&gInstance);
}
return do_AddRef(gInstance);
}

View File

@@ -1,22 +0,0 @@
/* -*- Mode: C++; tab-width: 2; 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/. */
#ifndef nsNativeBasicThemeWin_h
#define nsNativeBasicThemeWin_h
#include "nsNativeBasicTheme.h"
class nsNativeBasicThemeWin : public nsNativeBasicTheme {
public:
nsNativeBasicThemeWin() = default;
Transparency GetWidgetTransparency(nsIFrame*, StyleAppearance) override;
protected:
virtual ~nsNativeBasicThemeWin() = default;
};
#endif

View File

@@ -5,57 +5,59 @@
#include "nsNativeThemeWin.h"
#include <algorithm>
#include <malloc.h>
#include "gfxContext.h"
#include "gfxPlatform.h"
#include "gfxWindowsNativeDrawing.h"
#include "gfxWindowsPlatform.h"
#include "gfxWindowsSurface.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/EventStates.h"
#include "mozilla/gfx/Types.h" // for Color::FromABGR
#include "mozilla/Logging.h"
#include "mozilla/RelativeLuminanceUtils.h"
#include "mozilla/StaticPrefs_layout.h"
#include "mozilla/StaticPrefs_widget.h"
#include "mozilla/WindowsVersion.h"
#include "mozilla/gfx/Types.h" // for Color::FromABGR
#include "nsNativeBasicTheme.h"
#include "nsColor.h"
#include "nsComboboxControlFrame.h"
#include "nsDeviceContext.h"
#include "nsRect.h"
#include "nsSize.h"
#include "nsTransform2D.h"
#include "nsStyleConsts.h"
#include "nsPresContext.h"
#include "nsGkAtoms.h"
#include "nsIContent.h"
#include "nsIContentInlines.h"
#include "nsIFrame.h"
#include "nsLayoutUtils.h"
#include "nsNameSpaceManager.h"
#include "nsLookAndFeel.h"
#include "nsMenuFrame.h"
#include "nsGkAtoms.h"
#include <malloc.h>
#include "nsWindow.h"
#include "nsComboboxControlFrame.h"
#include "prinrval.h"
#include "ScrollbarUtil.h"
#include "WinUtils.h"
#include "gfxPlatform.h"
#include "gfxContext.h"
#include "gfxWindowsPlatform.h"
#include "gfxWindowsSurface.h"
#include "gfxWindowsNativeDrawing.h"
#include "nsNameSpaceManager.h"
#include "nsNativeBasicTheme.h"
#include "nsPresContext.h"
#include "nsRect.h"
#include "nsSize.h"
#include "nsStyleConsts.h"
#include "nsTransform2D.h"
#include "nsUXThemeData.h"
#include "nsUXThemeConstants.h"
#include <algorithm>
#include "nsWindow.h"
#include "prinrval.h"
#include "WinUtils.h"
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::widget;
using ScrollbarDrawingWin = mozilla::widget::ScrollbarDrawingWin;
extern mozilla::LazyLogModule gWindowsLog;
NS_IMPL_ISUPPORTS_INHERITED(nsNativeThemeWin, nsNativeTheme, nsITheme)
nsNativeThemeWin::nsNativeThemeWin()
: mProgressDeterminateTimeStamp(TimeStamp::Now()),
nsNativeThemeWin::nsNativeThemeWin(
mozilla::UniquePtr<ScrollbarDrawing>&& aScrollbarDrawingWin)
: nsNativeBasicTheme(std::move(aScrollbarDrawingWin)),
mProgressDeterminateTimeStamp(TimeStamp::Now()),
mProgressIndeterminateTimeStamp(TimeStamp::Now()),
mBorderCacheValid(),
mMinimumWidgetSizeCacheValid(),
@@ -71,8 +73,8 @@ bool nsNativeThemeWin::IsWidgetNonNative(nsIFrame* aFrame,
StyleAppearance aAppearance) {
// We only know how to draw light widgets, so we defer to the non-native
// theme when appropriate.
return nsNativeBasicThemeWin::ThemeSupportsWidget(aFrame->PresContext(),
aFrame, aAppearance) &&
return nsNativeBasicTheme::ThemeSupportsWidget(aFrame->PresContext(), aFrame,
aAppearance) &&
LookAndFeel::ColorSchemeForFrame(aFrame) ==
LookAndFeel::ColorScheme::Dark;
}
@@ -1492,7 +1494,7 @@ nsNativeThemeWin::DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
const nsRect& aDirtyRect,
DrawOverflow aDrawOverflow) {
if (IsWidgetNonNative(aFrame, aAppearance)) {
return nsNativeBasicThemeWin::DrawWidgetBackground(
return nsNativeBasicTheme::DrawWidgetBackground(
aContext, aFrame, aAppearance, aRect, aDirtyRect, aDrawOverflow);
}
@@ -1891,7 +1893,7 @@ bool nsNativeThemeWin::CreateWebRenderCommandsForWidget(
layers::RenderRootStateManager* aManager, nsIFrame* aFrame,
StyleAppearance aAppearance, const nsRect& aRect) {
if (IsWidgetNonNative(aFrame, aAppearance)) {
return nsNativeBasicThemeWin::CreateWebRenderCommandsForWidget(
return nsNativeBasicTheme::CreateWebRenderCommandsForWidget(
aBuilder, aResources, aSc, aManager, aFrame, aAppearance, aRect);
}
return false;
@@ -2148,8 +2150,8 @@ bool nsNativeThemeWin::GetWidgetOverflow(nsDeviceContext* aContext,
StyleAppearance aAppearance,
nsRect* aOverflowRect) {
if (IsWidgetNonNative(aFrame, aAppearance)) {
return nsNativeBasicThemeWin::GetWidgetOverflow(aContext, aFrame,
aAppearance, aOverflowRect);
return nsNativeBasicTheme::GetWidgetOverflow(aContext, aFrame, aAppearance,
aOverflowRect);
}
/* This is disabled for now, because it causes invalidation problems --
@@ -2591,11 +2593,11 @@ nsITheme::ThemeGeometryType nsNativeThemeWin::ThemeGeometryTypeForWidget(
nsITheme::Transparency nsNativeThemeWin::GetWidgetTransparency(
nsIFrame* aFrame, StyleAppearance aAppearance) {
if (IsWidgetNonNative(aFrame, aAppearance)) {
return nsNativeBasicThemeWin::GetWidgetTransparency(aFrame, aAppearance);
return nsNativeBasicTheme::GetWidgetTransparency(aFrame, aAppearance);
}
if (auto transparency =
ScrollbarUtil::GetScrollbarPartTransparency(aFrame, aAppearance)) {
if (auto transparency = GetScrollbarDrawing().GetScrollbarPartTransparency(
aFrame, aAppearance)) {
return *transparency;
}
@@ -2826,7 +2828,7 @@ nsresult nsNativeThemeWin::ClassicGetMinimumWidgetSize(
case StyleAppearance::ScrollbarbuttonUp:
case StyleAppearance::ScrollbarbuttonDown:
// For scrollbar-width:thin, we don't display the buttons.
if (!ScrollbarUtil::IsScrollbarWidthThin(aFrame)) {
if (!ScrollbarDrawing::IsScrollbarWidthThin(aFrame)) {
(*aResult).width = ::GetSystemMetrics(SM_CXVSCROLL);
(*aResult).height = ::GetSystemMetrics(SM_CYVSCROLL);
}
@@ -2835,7 +2837,7 @@ nsresult nsNativeThemeWin::ClassicGetMinimumWidgetSize(
case StyleAppearance::ScrollbarbuttonLeft:
case StyleAppearance::ScrollbarbuttonRight:
// For scrollbar-width:thin, we don't display the buttons.
if (!ScrollbarUtil::IsScrollbarWidthThin(aFrame)) {
if (!ScrollbarDrawing::IsScrollbarWidthThin(aFrame)) {
(*aResult).width = ::GetSystemMetrics(SM_CXHSCROLL);
(*aResult).height = ::GetSystemMetrics(SM_CYHSCROLL);
}
@@ -2903,7 +2905,7 @@ nsresult nsNativeThemeWin::ClassicGetMinimumWidgetSize(
}
// If scrollbar-width is thin, divide the thickness by two to make
// it look more compact.
if (ScrollbarUtil::IsScrollbarWidthThin(aFrame)) {
if (ScrollbarDrawing::IsScrollbarWidthThin(aFrame)) {
aResult->width >>= 1;
}
*aIsOverridable = false;
@@ -2918,7 +2920,7 @@ nsresult nsNativeThemeWin::ClassicGetMinimumWidgetSize(
}
// If scrollbar-width is thin, divide the thickness by two to make
// it look more compact.
if (ScrollbarUtil::IsScrollbarWidthThin(aFrame)) {
if (ScrollbarDrawing::IsScrollbarWidthThin(aFrame)) {
aResult->height >>= 1;
}
*aIsOverridable = false;
@@ -3920,13 +3922,48 @@ uint32_t nsNativeThemeWin::GetWidgetNativeDrawingFlags(
}
}
static nscolor GetScrollbarTrackColor(nsIFrame* aFrame) {
bool darkScrollbar = false;
ComputedStyle* style =
ScrollbarDrawingWin::GetCustomScrollbarStyle(aFrame, &darkScrollbar);
if (style) {
const nsStyleUI* ui = style->StyleUI();
auto* customColors = ui->mScrollbarColor.IsAuto()
? nullptr
: &ui->mScrollbarColor.AsColors();
if (customColors) {
return customColors->track.CalcColor(*style);
}
}
return darkScrollbar ? NS_RGBA(20, 20, 25, 77) : NS_RGB(240, 240, 240);
}
static nscolor GetScrollbarThumbColor(nsIFrame* aFrame,
EventStates aEventStates) {
bool darkScrollbar = false;
ComputedStyle* style =
ScrollbarDrawingWin::GetCustomScrollbarStyle(aFrame, &darkScrollbar);
nscolor color =
darkScrollbar ? NS_RGBA(249, 249, 250, 102) : NS_RGB(205, 205, 205);
if (style) {
const nsStyleUI* ui = style->StyleUI();
auto* customColors = ui->mScrollbarColor.IsAuto()
? nullptr
: &ui->mScrollbarColor.AsColors();
if (customColors) {
color = customColors->thumb.CalcColor(*style);
}
}
return ThemeColors::AdjustUnthemedScrollbarThumbColor(color, aEventStates);
}
// This tries to draw a Windows 10 style scrollbar with given colors.
bool nsNativeThemeWin::MayDrawCustomScrollbarPart(gfxContext* aContext,
nsIFrame* aFrame,
StyleAppearance aAppearance,
const nsRect& aRect,
const nsRect& aClipRect) {
ComputedStyle* style = ScrollbarUtil::GetCustomScrollbarStyle(aFrame);
ComputedStyle* style = ScrollbarDrawingWin::GetCustomScrollbarStyle(aFrame);
if (!style) {
return false;
}
@@ -3941,7 +3978,7 @@ bool nsNativeThemeWin::MayDrawCustomScrollbarPart(gfxContext* aContext,
gfxRect clipRect = ThebesRect(NSRectToSnappedRect(aClipRect, p2a, *dt));
ctx->Clip(clipRect);
nscolor trackColor = ScrollbarUtil::GetScrollbarTrackColor(aFrame);
nscolor trackColor = GetScrollbarTrackColor(aFrame);
switch (aAppearance) {
case StyleAppearance::ScrollbarHorizontal:
@@ -3977,8 +4014,7 @@ bool nsNativeThemeWin::MayDrawCustomScrollbarPart(gfxContext* aContext,
switch (aAppearance) {
case StyleAppearance::ScrollbarthumbVertical:
case StyleAppearance::ScrollbarthumbHorizontal: {
nscolor faceColor =
ScrollbarUtil::GetScrollbarThumbColor(aFrame, eventStates);
nscolor faceColor = GetScrollbarThumbColor(aFrame, eventStates);
ctx->SetColor(sRGBColor::FromABGR(faceColor));
ctx->Rectangle(bgRect);
ctx->Fill();
@@ -3989,7 +4025,7 @@ bool nsNativeThemeWin::MayDrawCustomScrollbarPart(gfxContext* aContext,
case StyleAppearance::ScrollbarbuttonLeft:
case StyleAppearance::ScrollbarbuttonRight: {
nscolor buttonColor =
nsNativeBasicTheme::GetScrollbarButtonColor(trackColor, eventStates);
ScrollbarDrawingWin::GetScrollbarButtonColor(trackColor, eventStates);
ctx->SetColor(sRGBColor::FromABGR(buttonColor));
ctx->Rectangle(bgRect);
ctx->Fill();
@@ -4035,11 +4071,9 @@ bool nsNativeThemeWin::MayDrawCustomScrollbarPart(gfxContext* aContext,
ctx->ClosePath();
// And paint the arrow.
nscolor arrowColor =
nsNativeBasicTheme::GetScrollbarArrowColor(buttonColor)
.valueOrFrom([&] {
return ScrollbarUtil::GetScrollbarThumbColor(aFrame,
eventStates);
});
ScrollbarDrawingWin::GetScrollbarArrowColor(buttonColor)
.valueOrFrom(
[&] { return GetScrollbarThumbColor(aFrame, eventStates); });
ctx->SetColor(sRGBColor::FromABGR(arrowColor));
ctx->Fill();
break;
@@ -4058,7 +4092,7 @@ already_AddRefed<nsITheme> do_GetNativeThemeDoNotUseDirectly() {
static nsCOMPtr<nsITheme> inst;
if (!inst) {
inst = new nsNativeThemeWin();
inst = new nsNativeThemeWin(MakeUnique<ScrollbarDrawingWin>());
ClearOnShutdown(&inst);
}

View File

@@ -7,21 +7,27 @@
#ifndef nsNativeThemeWin_h
#define nsNativeThemeWin_h
#include "nsITheme.h"
#include "nsCOMPtr.h"
#include <windows.h>
#include "gfxTypes.h"
#include "mozilla/Maybe.h"
#include "mozilla/TimeStamp.h"
#include "nsAtom.h"
#include "nsCOMPtr.h"
#include "nsITheme.h"
#include "nsNativeBasicTheme.h"
#include "nsNativeTheme.h"
#include "nsSize.h"
#include "nsStyleConsts.h"
#include "nsUXThemeConstants.h"
#include "nsUXThemeData.h"
#include "nsNativeBasicThemeWin.h"
#include "gfxTypes.h"
#include <windows.h>
#include "mozilla/Maybe.h"
#include "mozilla/TimeStamp.h"
#include "nsSize.h"
#include "ScrollbarDrawingWin.h"
class nsNativeThemeWin : public nsNativeBasicThemeWin {
namespace mozilla::widget {
class nsNativeThemeWin : public nsNativeBasicTheme {
protected:
using ScrollbarDrawingWin = mozilla::widget::ScrollbarDrawingWin;
virtual ~nsNativeThemeWin();
public:
@@ -99,7 +105,8 @@ class nsNativeThemeWin : public nsNativeBasicThemeWin {
ScrollbarSizes GetScrollbarSizes(nsPresContext*, StyleScrollbarWidth,
Overlay) override;
nsNativeThemeWin();
explicit nsNativeThemeWin(
mozilla::UniquePtr<ScrollbarDrawing>&& aScrollbarDrawingWin);
protected:
mozilla::Maybe<nsUXThemeClass> GetThemeClass(StyleAppearance aAppearance);
@@ -181,4 +188,6 @@ class nsNativeThemeWin : public nsNativeBasicThemeWin {
SIZE mGutterSizeCache;
};
} // namespace mozilla::widget
#endif