зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1702676 - Change public LookAndFeel API to accept a color scheme. r=mstange
This shouldn't change behavior, but is the biggest cross-platform part of the change so I'd like to get it landed sooner rather than later. The two calls like: GetColor(ColorID::TextSelectBackground, color); if (color == 0x000000) { mColorTextSelectForeground = NS_RGB(0xff, 0xff, 0xff); } else { mColorTextSelectForeground = NS_DONT_CHANGE_COLOR; } that I'm removing are just broken. They were calling the version of GetColor the function that took a default value when the color wasn't available, not the version of the color with the outparam. To prevent such mistakes, add two signatures, GetColor(), returning a Maybe<nscolor> and Color(), returning a color with a fallback. Differential Revision: https://phabricator.services.mozilla.com/D110651
This commit is contained in:
Родитель
70c869cd11
Коммит
f7f84a3c53
|
@ -216,9 +216,10 @@ void nsListControlFrame::PaintFocus(DrawTarget* aDrawTarget, nsPoint aPt) {
|
|||
}
|
||||
|
||||
// set up back stop colors and then ask L&F service for the real colors
|
||||
nscolor color = LookAndFeel::GetColor(
|
||||
nscolor color = LookAndFeel::Color(
|
||||
lastItemIsSelected ? LookAndFeel::ColorID::WidgetSelectForeground
|
||||
: LookAndFeel::ColorID::WidgetSelectBackground);
|
||||
: LookAndFeel::ColorID::WidgetSelectBackground,
|
||||
this);
|
||||
|
||||
nsCSSRendering::PaintFocus(presContext, aDrawTarget, fRect, color);
|
||||
}
|
||||
|
|
|
@ -443,7 +443,7 @@ DeviceColor nsDisplaySelectionOverlay::ComputeColor() const {
|
|||
}
|
||||
|
||||
return ApplyTransparencyIfNecessary(
|
||||
LookAndFeel::GetColor(colorID, NS_RGB(255, 255, 255)));
|
||||
LookAndFeel::Color(colorID, mFrame, NS_RGB(255, 255, 255)));
|
||||
}
|
||||
|
||||
void nsDisplaySelectionOverlay::Paint(nsDisplayListBuilder* aBuilder,
|
||||
|
|
|
@ -1363,17 +1363,17 @@ void nsHTMLFramesetBorderFrame::PaintBorder(DrawTarget* aDrawTarget,
|
|||
|
||||
if (widthInPixels <= 0) return;
|
||||
|
||||
ColorPattern bgColor(ToDeviceColor(LookAndFeel::GetColor(
|
||||
LookAndFeel::ColorID::WidgetBackground, NS_RGB(200, 200, 200))));
|
||||
ColorPattern bgColor(ToDeviceColor(LookAndFeel::Color(
|
||||
LookAndFeel::ColorID::WidgetBackground, this, NS_RGB(200, 200, 200))));
|
||||
|
||||
ColorPattern fgColor(ToDeviceColor(LookAndFeel::GetColor(
|
||||
LookAndFeel::ColorID::WidgetForeground, NS_RGB(0, 0, 0))));
|
||||
ColorPattern fgColor(ToDeviceColor(LookAndFeel::Color(
|
||||
LookAndFeel::ColorID::WidgetForeground, this, NS_RGB(0, 0, 0))));
|
||||
|
||||
ColorPattern hltColor(ToDeviceColor(LookAndFeel::GetColor(
|
||||
LookAndFeel::ColorID::Widget3DHighlight, NS_RGB(255, 255, 255))));
|
||||
ColorPattern hltColor(ToDeviceColor(LookAndFeel::Color(
|
||||
LookAndFeel::ColorID::Widget3DHighlight, this, NS_RGB(255, 255, 255))));
|
||||
|
||||
ColorPattern sdwColor(ToDeviceColor(LookAndFeel::GetColor(
|
||||
LookAndFeel::ColorID::Widget3DShadow, NS_RGB(128, 128, 128))));
|
||||
ColorPattern sdwColor(ToDeviceColor(LookAndFeel::Color(
|
||||
LookAndFeel::ColorID::Widget3DShadow, this, NS_RGB(128, 128, 128))));
|
||||
|
||||
ColorPattern color(ToDeviceColor(NS_RGB(255, 255, 255))); // default to white
|
||||
if (mVisibility) {
|
||||
|
|
|
@ -357,7 +357,7 @@ class nsTextPaintStyle {
|
|||
float* aRelativeSize, uint8_t* aStyle);
|
||||
|
||||
// if this returns false, we don't need to draw underline.
|
||||
static bool GetSelectionUnderline(nsPresContext* aPresContext, int32_t aIndex,
|
||||
static bool GetSelectionUnderline(nsIFrame*, int32_t aIndex,
|
||||
nscolor* aLineColor, float* aRelativeSize,
|
||||
uint8_t* aStyle);
|
||||
|
||||
|
@ -3899,14 +3899,13 @@ void nsTextPaintStyle::GetHighlightColors(nscolor* aForeColor,
|
|||
}
|
||||
|
||||
if (!customColors) {
|
||||
nscolor backColor =
|
||||
LookAndFeel::GetColor(LookAndFeel::ColorID::TextHighlightBackground);
|
||||
nscolor foreColor =
|
||||
LookAndFeel::GetColor(LookAndFeel::ColorID::TextHighlightForeground);
|
||||
nscolor backColor = LookAndFeel::Color(
|
||||
LookAndFeel::ColorID::TextHighlightBackground, mFrame);
|
||||
nscolor foreColor = LookAndFeel::Color(
|
||||
LookAndFeel::ColorID::TextHighlightForeground, mFrame);
|
||||
EnsureSufficientContrast(&foreColor, &backColor);
|
||||
*aForeColor = foreColor;
|
||||
*aBackColor = backColor;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4034,9 +4033,9 @@ void nsTextPaintStyle::InitCommonColors() {
|
|||
mFrameBackgroundColor = NS_ComposeColors(defaultBgColor, bgColor);
|
||||
|
||||
mSystemFieldForegroundColor =
|
||||
LookAndFeel::GetColor(LookAndFeel::ColorID::Fieldtext);
|
||||
LookAndFeel::Color(LookAndFeel::ColorID::Fieldtext, mFrame);
|
||||
mSystemFieldBackgroundColor =
|
||||
LookAndFeel::GetColor(LookAndFeel::ColorID::Field);
|
||||
LookAndFeel::Color(LookAndFeel::ColorID::Field, mFrame);
|
||||
|
||||
if (bgFrame->IsThemed()) {
|
||||
// Assume a native widget has sufficient contrast always
|
||||
|
@ -4049,11 +4048,11 @@ void nsTextPaintStyle::InitCommonColors() {
|
|||
"default background color is not opaque");
|
||||
|
||||
nscolor defaultWindowBackgroundColor =
|
||||
LookAndFeel::GetColor(LookAndFeel::ColorID::WindowBackground);
|
||||
LookAndFeel::Color(LookAndFeel::ColorID::WindowBackground, mFrame);
|
||||
nscolor selectionTextColor =
|
||||
LookAndFeel::GetColor(LookAndFeel::ColorID::TextSelectForeground);
|
||||
LookAndFeel::Color(LookAndFeel::ColorID::TextSelectForeground, mFrame);
|
||||
nscolor selectionBGColor =
|
||||
LookAndFeel::GetColor(LookAndFeel::ColorID::TextSelectBackground);
|
||||
LookAndFeel::Color(LookAndFeel::ColorID::TextSelectBackground, mFrame);
|
||||
|
||||
mSufficientContrast = std::min(
|
||||
std::min(NS_SUFFICIENT_LUMINOSITY_DIFFERENCE,
|
||||
|
@ -4101,12 +4100,12 @@ bool nsTextPaintStyle::InitSelectionColorsAndShadow() {
|
|||
}
|
||||
|
||||
nscolor selectionBGColor =
|
||||
LookAndFeel::GetColor(LookAndFeel::ColorID::TextSelectBackground);
|
||||
LookAndFeel::Color(LookAndFeel::ColorID::TextSelectBackground, mFrame);
|
||||
|
||||
switch (selectionStatus) {
|
||||
case nsISelectionController::SELECTION_ATTENTION: {
|
||||
mSelectionBGColor = LookAndFeel::GetColor(
|
||||
LookAndFeel::ColorID::TextSelectBackgroundAttention);
|
||||
mSelectionBGColor = LookAndFeel::Color(
|
||||
LookAndFeel::ColorID::TextSelectBackgroundAttention, mFrame);
|
||||
mSelectionBGColor =
|
||||
EnsureDifferentColors(mSelectionBGColor, selectionBGColor);
|
||||
break;
|
||||
|
@ -4116,8 +4115,8 @@ bool nsTextPaintStyle::InitSelectionColorsAndShadow() {
|
|||
break;
|
||||
}
|
||||
default: {
|
||||
mSelectionBGColor = LookAndFeel::GetColor(
|
||||
LookAndFeel::ColorID::TextSelectBackgroundDisabled);
|
||||
mSelectionBGColor = LookAndFeel::Color(
|
||||
LookAndFeel::ColorID::TextSelectBackgroundDisabled, mFrame);
|
||||
mSelectionBGColor =
|
||||
EnsureDifferentColors(mSelectionBGColor, selectionBGColor);
|
||||
break;
|
||||
|
@ -4125,7 +4124,7 @@ bool nsTextPaintStyle::InitSelectionColorsAndShadow() {
|
|||
}
|
||||
|
||||
mSelectionTextColor =
|
||||
LookAndFeel::GetColor(LookAndFeel::ColorID::TextSelectForeground);
|
||||
LookAndFeel::Color(LookAndFeel::ColorID::TextSelectForeground, mFrame);
|
||||
|
||||
if (mResolveColors) {
|
||||
// On MacOS X, only the background color gets set,
|
||||
|
@ -4145,8 +4144,8 @@ bool nsTextPaintStyle::InitSelectionColorsAndShadow() {
|
|||
: mFrame->GetVisitedDependentColor(
|
||||
&nsStyleText::mWebkitTextFillColor);
|
||||
if (frameColor == mSelectionBGColor) {
|
||||
mSelectionTextColor = LookAndFeel::GetColor(
|
||||
LookAndFeel::ColorID::TextSelectForegroundCustom);
|
||||
mSelectionTextColor = LookAndFeel::Color(
|
||||
LookAndFeel::ColorID::TextSelectForegroundCustom, mFrame);
|
||||
}
|
||||
} else {
|
||||
EnsureSufficientContrast(&mSelectionTextColor, &mSelectionBGColor);
|
||||
|
@ -4207,12 +4206,12 @@ void nsTextPaintStyle::InitSelectionStyle(int32_t aIndex) {
|
|||
if (styleIDs->mForeground == LookAndFeel::ColorID::End) {
|
||||
foreColor = NS_SAME_AS_FOREGROUND_COLOR;
|
||||
} else {
|
||||
foreColor = LookAndFeel::GetColor(styleIDs->mForeground);
|
||||
foreColor = LookAndFeel::Color(styleIDs->mForeground, mFrame);
|
||||
}
|
||||
if (styleIDs->mBackground == LookAndFeel::ColorID::End) {
|
||||
backColor = NS_TRANSPARENT;
|
||||
} else {
|
||||
backColor = LookAndFeel::GetColor(styleIDs->mBackground);
|
||||
backColor = LookAndFeel::Color(styleIDs->mBackground, mFrame);
|
||||
}
|
||||
|
||||
// Convert special color to actual color
|
||||
|
@ -4233,8 +4232,7 @@ void nsTextPaintStyle::InitSelectionStyle(int32_t aIndex) {
|
|||
nscolor lineColor;
|
||||
float relativeSize;
|
||||
uint8_t lineStyle;
|
||||
GetSelectionUnderline(mPresContext, aIndex, &lineColor, &relativeSize,
|
||||
&lineStyle);
|
||||
GetSelectionUnderline(mFrame, aIndex, &lineColor, &relativeSize, &lineStyle);
|
||||
|
||||
if (mResolveColors)
|
||||
lineColor = GetResolvedForeColor(lineColor, foreColor, backColor);
|
||||
|
@ -4248,19 +4246,18 @@ void nsTextPaintStyle::InitSelectionStyle(int32_t aIndex) {
|
|||
}
|
||||
|
||||
/* static */
|
||||
bool nsTextPaintStyle::GetSelectionUnderline(nsPresContext* aPresContext,
|
||||
int32_t aIndex,
|
||||
bool nsTextPaintStyle::GetSelectionUnderline(nsIFrame* aFrame, int32_t aIndex,
|
||||
nscolor* aLineColor,
|
||||
float* aRelativeSize,
|
||||
uint8_t* aStyle) {
|
||||
NS_ASSERTION(aPresContext, "aPresContext is null");
|
||||
NS_ASSERTION(aFrame, "aFrame is null");
|
||||
NS_ASSERTION(aRelativeSize, "aRelativeSize is null");
|
||||
NS_ASSERTION(aStyle, "aStyle is null");
|
||||
NS_ASSERTION(aIndex >= 0 && aIndex < 5, "Index out of range");
|
||||
|
||||
StyleIDs& styleID = SelectionStyleIDs[aIndex];
|
||||
|
||||
nscolor color = LookAndFeel::GetColor(styleID.mLine);
|
||||
nscolor color = LookAndFeel::Color(styleID.mLine, aFrame);
|
||||
int32_t style = LookAndFeel::GetInt(styleID.mLineStyle);
|
||||
if (style > NS_STYLE_TEXT_DECORATION_STYLE_MAX) {
|
||||
NS_ERROR("Invalid underline style value is specified");
|
||||
|
@ -7375,7 +7372,7 @@ bool nsTextFrame::CombineSelectionUnderlineRect(nsPresContext* aPresContext,
|
|||
sd->mSelectionType);
|
||||
if (sd->mSelectionType == SelectionType::eSpellCheck) {
|
||||
if (!nsTextPaintStyle::GetSelectionUnderline(
|
||||
aPresContext, index, nullptr, &relativeSize, ¶ms.style)) {
|
||||
this, index, nullptr, &relativeSize, ¶ms.style)) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
|
@ -7389,8 +7386,7 @@ bool nsTextFrame::CombineSelectionUnderlineRect(nsPresContext* aPresContext,
|
|||
params.style = ToStyleLineStyle(rangeStyle);
|
||||
relativeSize = rangeStyle.mIsBoldLine ? 2.0f : 1.0f;
|
||||
} else if (!nsTextPaintStyle::GetSelectionUnderline(
|
||||
aPresContext, index, nullptr, &relativeSize,
|
||||
¶ms.style)) {
|
||||
this, index, nullptr, &relativeSize, ¶ms.style)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1713,8 +1713,8 @@ void nsDisplayMathMLSelectionRect::Paint(nsDisplayListBuilder* aBuilder,
|
|||
mFrame->PresContext()->AppUnitsPerDevPixel(),
|
||||
*drawTarget);
|
||||
// get color to use for selection from the look&feel object
|
||||
nscolor bgColor = LookAndFeel::GetColor(
|
||||
LookAndFeel::ColorID::TextSelectBackground, NS_RGB(0, 0, 0));
|
||||
nscolor bgColor =
|
||||
LookAndFeel::Color(LookAndFeel::ColorID::TextSelectBackground, mFrame);
|
||||
drawTarget->FillRect(rect, ColorPattern(ToDeviceColor(bgColor)));
|
||||
}
|
||||
|
||||
|
@ -1869,8 +1869,8 @@ void nsMathMLChar::PaintForeground(nsIFrame* aForFrame,
|
|||
&nsStyleText::mWebkitTextFillColor);
|
||||
if (aIsSelected) {
|
||||
// get color to use for selection from the look&feel object
|
||||
fgColor = LookAndFeel::GetColor(LookAndFeel::ColorID::TextSelectForeground,
|
||||
fgColor);
|
||||
fgColor = LookAndFeel::Color(LookAndFeel::ColorID::TextSelectForeground,
|
||||
aForFrame, fgColor);
|
||||
}
|
||||
aRenderingContext.SetColor(sRGBColor::FromABGR(fgColor));
|
||||
aRenderingContext.Save();
|
||||
|
|
|
@ -693,52 +693,10 @@ bool Gecko_IsDocumentBody(const Element* aElement) {
|
|||
return doc && doc->GetBodyElement() == aElement;
|
||||
}
|
||||
|
||||
static bool ShouldUseStandinsForNativeColorForNonNativeTheme(
|
||||
const Document& aDoc, LookAndFeel::ColorID aColor) {
|
||||
using ColorID = LookAndFeel::ColorID;
|
||||
if (!aDoc.ShouldAvoidNativeTheme()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The native theme doesn't use system colors backgrounds etc, except when in
|
||||
// high-contrast mode, so spoof some of the colors with stand-ins to prevent
|
||||
// lack of contrast.
|
||||
switch (aColor) {
|
||||
case ColorID::Buttonface:
|
||||
case ColorID::Buttontext:
|
||||
case ColorID::MozButtonhoverface:
|
||||
case ColorID::MozButtonhovertext:
|
||||
case ColorID::MozGtkButtonactivetext:
|
||||
|
||||
case ColorID::MozCombobox:
|
||||
case ColorID::MozComboboxtext:
|
||||
|
||||
case ColorID::Field:
|
||||
case ColorID::Fieldtext:
|
||||
|
||||
case ColorID::Graytext:
|
||||
|
||||
return !PreferenceSheet::PrefsFor(aDoc)
|
||||
.NonNativeThemeShouldUseSystemColors();
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nscolor Gecko_GetLookAndFeelSystemColor(int32_t aId, const Document* aDoc) {
|
||||
auto colorId = static_cast<LookAndFeel::ColorID>(aId);
|
||||
const bool useStandinsForNativeColors =
|
||||
ShouldUseStandinsForNativeColorForNonNativeTheme(*aDoc, colorId) ||
|
||||
(nsContentUtils::UseStandinsForNativeColors() &&
|
||||
!nsContentUtils::IsChromeDoc(aDoc));
|
||||
|
||||
AutoWriteLock guard(*sServoFFILock);
|
||||
nscolor result = 0;
|
||||
LookAndFeel::GetColor(colorId, useStandinsForNativeColors, &result);
|
||||
return result;
|
||||
return LookAndFeel::Color(colorId, *aDoc);
|
||||
}
|
||||
|
||||
bool Gecko_MatchLang(const Element* aElement, nsAtom* aOverrideLang,
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "mozilla/StaticPrefs_devtools.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
#include "mozilla/ServoBindings.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
|
@ -88,30 +89,28 @@ void PreferenceSheet::Prefs::Load(bool aIsChrome) {
|
|||
mFocusRingStyle = StaticPrefs::browser_display_focus_ring_style();
|
||||
mFocusRingOnAnything = StaticPrefs::browser_display_focus_ring_on_anything();
|
||||
|
||||
const bool usePrefColors = !aIsChrome && !mUseAccessibilityTheme &&
|
||||
const bool useStandins = nsContentUtils::UseStandinsForNativeColors();
|
||||
const bool usePrefColors = !useStandins && !aIsChrome && !mUseAccessibilityTheme &&
|
||||
!StaticPrefs::browser_display_use_system_colors();
|
||||
|
||||
if (nsContentUtils::UseStandinsForNativeColors()) {
|
||||
mDefaultColor = LookAndFeel::GetColorUsingStandins(
|
||||
LookAndFeel::ColorID::Windowtext, mDefaultColor);
|
||||
mDefaultBackgroundColor = LookAndFeel::GetColorUsingStandins(
|
||||
LookAndFeel::ColorID::Window, mDefaultBackgroundColor);
|
||||
mLinkColor = LookAndFeel::GetColorUsingStandins(
|
||||
LookAndFeel::ColorID::MozNativehyperlinktext, mLinkColor);
|
||||
} else if (usePrefColors) {
|
||||
if (usePrefColors) {
|
||||
GetColor("browser.display.background_color", mDefaultBackgroundColor);
|
||||
GetColor("browser.display.foreground_color", mDefaultColor);
|
||||
GetColor("browser.anchor_color", mLinkColor);
|
||||
} else {
|
||||
mDefaultColor = LookAndFeel::GetColor(
|
||||
LookAndFeel::ColorID::WindowForeground, mDefaultColor);
|
||||
mDefaultBackgroundColor = LookAndFeel::GetColor(
|
||||
LookAndFeel::ColorID::WindowBackground, mDefaultBackgroundColor);
|
||||
mLinkColor = LookAndFeel::GetColor(
|
||||
LookAndFeel::ColorID::MozNativehyperlinktext, mLinkColor);
|
||||
using ColorID = LookAndFeel::ColorID;
|
||||
const auto standins = LookAndFeel::UseStandins(useStandins);
|
||||
// TODO(emilio): In the future we probably want to keep both sets of colors
|
||||
// around or something.
|
||||
const auto scheme = LookAndFeel::ColorScheme::Light;
|
||||
mDefaultColor = LookAndFeel::Color(
|
||||
ColorID::WindowForeground, scheme, standins, mDefaultColor);
|
||||
mDefaultBackgroundColor = LookAndFeel::Color(
|
||||
ColorID::WindowBackground, scheme, standins, mDefaultBackgroundColor);
|
||||
mLinkColor = LookAndFeel::Color(
|
||||
ColorID::MozNativehyperlinktext, scheme, standins, mLinkColor);
|
||||
}
|
||||
|
||||
if (mUseAccessibilityTheme && !nsContentUtils::UseStandinsForNativeColors()) {
|
||||
if (mUseAccessibilityTheme && !useStandins) {
|
||||
mActiveLinkColor = mLinkColor;
|
||||
// Visited link color is produced by preserving the foreground's green
|
||||
// and averaging the foreground and background for the red and blue.
|
||||
|
|
|
@ -294,8 +294,8 @@ void nsTableCellFrame::DecorateForSelection(DrawTarget* aDrawTarget,
|
|||
if (displaySelection == nsISelectionController::SELECTION_DISABLED) {
|
||||
bordercolor = NS_RGB(176, 176, 176); // disabled color
|
||||
} else {
|
||||
bordercolor =
|
||||
LookAndFeel::GetColor(LookAndFeel::ColorID::TextSelectBackground);
|
||||
bordercolor = LookAndFeel::Color(
|
||||
LookAndFeel::ColorID::TextSelectBackground, this);
|
||||
}
|
||||
nscoord threePx = nsPresContext::CSSPixelsToAppUnits(3);
|
||||
if ((mRect.width > threePx) && (mRect.height > threePx)) {
|
||||
|
|
|
@ -55,7 +55,6 @@ using namespace mozilla;
|
|||
using namespace mozilla::gfx;
|
||||
using mozilla::dom::Document;
|
||||
using mozilla::dom::Event;
|
||||
using mozilla::layers::APZCCallbackHelper;
|
||||
using mozilla::layers::AsyncDragMetrics;
|
||||
using mozilla::layers::InputAPZContext;
|
||||
using mozilla::layers::ScrollbarData;
|
||||
|
@ -293,7 +292,7 @@ void nsDisplaySliderMarks::PaintMarks(nsDisplayListBuilder* aDisplayListBuilder,
|
|||
|
||||
// Use the text highlight color for the tick marks.
|
||||
nscolor highlightColor =
|
||||
LookAndFeel::GetColor(LookAndFeel::ColorID::TextHighlightBackground);
|
||||
LookAndFeel::Color(LookAndFeel::ColorID::TextHighlightBackground, mFrame);
|
||||
DeviceColor fillColor = ToDeviceColor(highlightColor);
|
||||
fillColor.a = 0.3; // make the mark mostly transparent
|
||||
|
||||
|
|
|
@ -128,8 +128,11 @@ already_AddRefed<nsWebBrowser> nsWebBrowser::Create(
|
|||
MOZ_ASSERT(browser->mDocShell == docShell);
|
||||
|
||||
// get the system default window background colour
|
||||
LookAndFeel::GetColor(LookAndFeel::ColorID::WindowBackground,
|
||||
&browser->mBackgroundColor);
|
||||
//
|
||||
// TODO(emilio): Can we get the color-scheme from somewhere here?
|
||||
browser->mBackgroundColor = LookAndFeel::Color(
|
||||
LookAndFeel::ColorID::WindowBackground, LookAndFeel::ColorScheme::Light,
|
||||
LookAndFeel::UseStandins::No);
|
||||
|
||||
// HACK ALERT - this registration registers the nsDocShellTreeOwner as a
|
||||
// nsIWebBrowserListener so it can setup its MouseListener in one of the
|
||||
|
|
|
@ -14,12 +14,19 @@
|
|||
#include "nsColor.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/widget/ThemeChangeKind.h"
|
||||
|
||||
struct gfxFontStyle;
|
||||
|
||||
class nsIFrame;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
class Document;
|
||||
}
|
||||
|
||||
namespace widget {
|
||||
class FullLookAndFeel;
|
||||
} // namespace widget
|
||||
|
@ -422,31 +429,55 @@ class LookAndFeel {
|
|||
|
||||
using FontID = mozilla::StyleSystemFont;
|
||||
|
||||
/**
|
||||
* GetColor() return a native color value (might be overwritten by prefs) for
|
||||
* aID. Some platforms don't return an error even if the index doesn't
|
||||
* match any system colors. And also some platforms may initialize the
|
||||
* return value even when it returns an error. Therefore, if you want to
|
||||
* use a color for the default value, you should use the other GetColor()
|
||||
* which returns nscolor directly.
|
||||
*
|
||||
* NOTE:
|
||||
* ColorID::TextSelectForeground might return NS_DONT_CHANGE_COLOR.
|
||||
* ColorID::IME* might return NS_TRANSPARENT, NS_SAME_AS_FOREGROUND_COLOR or
|
||||
* NS_40PERCENT_FOREGROUND_COLOR.
|
||||
* These values have particular meaning. Then, they are not an actual
|
||||
* color value.
|
||||
*/
|
||||
static nsresult GetColor(ColorID aID, nscolor* aResult);
|
||||
// Whether we should use a light or dark appearance.
|
||||
//
|
||||
// This is currently ignored (but won't be for long).
|
||||
enum class ColorScheme : uint8_t { Light, Dark };
|
||||
|
||||
/**
|
||||
* This variant of GetColor() takes an extra Boolean parameter that allows
|
||||
* the caller to ask that hard-coded color values be substituted for
|
||||
* native colors (used when it is desireable to hide system colors to
|
||||
* avoid system fingerprinting).
|
||||
*/
|
||||
static nsresult GetColor(ColorID aID, bool aUseStandinsForNativeColors,
|
||||
nscolor* aResult);
|
||||
// Whether standins for native colors should be used (that is, colors faked,
|
||||
// taken from win7, mostly). This forces light appearance, effectively.
|
||||
enum class UseStandins : bool { No, Yes };
|
||||
|
||||
// Returns a native color value (might be overwritten by prefs) for a given
|
||||
// color id.
|
||||
//
|
||||
// NOTE:
|
||||
// ColorID::TextSelectForeground might return NS_DONT_CHANGE_COLOR.
|
||||
// ColorID::IME* might return NS_TRANSPARENT, NS_SAME_AS_FOREGROUND_COLOR or
|
||||
// NS_40PERCENT_FOREGROUND_COLOR.
|
||||
// These values have particular meaning. Then, they are not an actual
|
||||
// color value.
|
||||
static Maybe<nscolor> GetColor(ColorID, ColorScheme, UseStandins);
|
||||
|
||||
// Gets the color with appropriate defaults for UseStandins, ColorScheme etc
|
||||
// for a given document.
|
||||
static Maybe<nscolor> GetColor(ColorID, const dom::Document&);
|
||||
|
||||
// Gets the color with appropriate defaults for UseStandins, ColorScheme etc
|
||||
// for a given frame.
|
||||
//
|
||||
// TODO(emilio): This right now just peeks the document out of the frame's
|
||||
// pres context, but in the future we actually want to look at the style to
|
||||
// get the right color scheme, to implement the color-scheme property.
|
||||
static Maybe<nscolor> GetColor(ColorID, const nsIFrame*);
|
||||
|
||||
// Versions of the above which returns the color if found, or a default (which
|
||||
// defaults to opaque black) otherwise.
|
||||
static nscolor Color(ColorID aId, ColorScheme aScheme,
|
||||
UseStandins aUseStandins,
|
||||
nscolor aDefault = NS_RGB(0, 0, 0)) {
|
||||
return GetColor(aId, aScheme, aUseStandins).valueOr(aDefault);
|
||||
}
|
||||
|
||||
static nscolor Color(ColorID aId, const dom::Document& aDoc,
|
||||
nscolor aDefault = NS_RGB(0, 0, 0)) {
|
||||
return GetColor(aId, aDoc).valueOr(aDefault);
|
||||
}
|
||||
|
||||
static nscolor Color(ColorID aId, nsIFrame* aFrame,
|
||||
nscolor aDefault = NS_RGB(0, 0, 0)) {
|
||||
return GetColor(aId, aFrame).valueOr(aDefault);
|
||||
}
|
||||
|
||||
/**
|
||||
* GetInt() and GetFloat() return a int or float value for aID. The result
|
||||
|
@ -456,28 +487,9 @@ class LookAndFeel {
|
|||
* use a value for the default value, you should use the other method which
|
||||
* returns int or float directly.
|
||||
*/
|
||||
static nsresult GetInt(IntID aID, int32_t* aResult);
|
||||
static nsresult GetInt(IntID, int32_t* aResult);
|
||||
static nsresult GetFloat(FloatID aID, float* aResult);
|
||||
|
||||
static nscolor GetColor(ColorID aID, nscolor aDefault = NS_RGB(0, 0, 0)) {
|
||||
nscolor result = NS_RGB(0, 0, 0);
|
||||
if (NS_FAILED(GetColor(aID, &result))) {
|
||||
return aDefault;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static nscolor GetColorUsingStandins(ColorID aID,
|
||||
nscolor aDefault = NS_RGB(0, 0, 0)) {
|
||||
nscolor result = NS_RGB(0, 0, 0);
|
||||
if (NS_FAILED(GetColor(aID,
|
||||
true, // aUseStandinsForNativeColors
|
||||
&result))) {
|
||||
return aDefault;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int32_t GetInt(IntID aID, int32_t aDefault = 0) {
|
||||
int32_t result;
|
||||
if (NS_FAILED(GetInt(aID, &result))) {
|
||||
|
|
|
@ -33,7 +33,6 @@ class nsLookAndFeel final : public nsXPLookAndFeel {
|
|||
nscolor mColorTextSelectBackground;
|
||||
nscolor mColorTextSelectBackgroundDisabled;
|
||||
nscolor mColorHighlight;
|
||||
nscolor mColorTextSelectForeground;
|
||||
nscolor mColorAlternateSelectedControlText;
|
||||
nscolor mColorControlText;
|
||||
nscolor mColorText;
|
||||
|
|
|
@ -30,7 +30,6 @@ nsLookAndFeel::nsLookAndFeel()
|
|||
mColorTextSelectBackground(0),
|
||||
mColorTextSelectBackgroundDisabled(0),
|
||||
mColorHighlight(0),
|
||||
mColorTextSelectForeground(0),
|
||||
mColorAlternateSelectedControlText(0),
|
||||
mColorControlText(0),
|
||||
mColorText(0),
|
||||
|
@ -167,7 +166,7 @@ nsresult nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) {
|
|||
aColor = mColorHighlight;
|
||||
break;
|
||||
case ColorID::TextSelectForeground:
|
||||
aColor = mColorTextSelectForeground;
|
||||
aColor = NS_DONT_CHANGE_COLOR;
|
||||
break;
|
||||
case ColorID::Highlighttext: // CSS2 color
|
||||
case ColorID::MozAccentColorForeground:
|
||||
|
@ -602,8 +601,6 @@ void nsLookAndFeel::EnsureInit() {
|
|||
|
||||
NS_OBJC_BEGIN_TRY_IGNORE_BLOCK
|
||||
|
||||
nscolor color;
|
||||
|
||||
bool appearanceIsDark = false;
|
||||
|
||||
if (@available(macOS 10.14, *)) {
|
||||
|
@ -627,13 +624,6 @@ void nsLookAndFeel::EnsureInit() {
|
|||
|
||||
mColorHighlight = GetColorFromNSColor([NSColor alternateSelectedControlColor]);
|
||||
|
||||
GetColor(ColorID::TextSelectBackground, color);
|
||||
if (color == 0x000000) {
|
||||
mColorTextSelectForeground = NS_RGB(0xff, 0xff, 0xff);
|
||||
} else {
|
||||
mColorTextSelectForeground = NS_DONT_CHANGE_COLOR;
|
||||
}
|
||||
|
||||
mColorAlternateSelectedControlText =
|
||||
GetColorFromNSColor([NSColor alternateSelectedControlTextColor]);
|
||||
|
||||
|
|
|
@ -211,6 +211,11 @@ const static bool kUseSimpleContextDefault = false;
|
|||
* to refer selection colors of GtkTextView via our widget.
|
||||
******************************************************************************/
|
||||
|
||||
static Maybe<nscolor> GetSystemColor(LookAndFeel::ColorID aId) {
|
||||
return LookAndFeel::GetColor(aId, LookAndFeel::ColorScheme::Light,
|
||||
LookAndFeel::UseStandins::No);
|
||||
}
|
||||
|
||||
class SelectionStyleProvider final {
|
||||
public:
|
||||
static SelectionStyleProvider* GetInstance() {
|
||||
|
@ -254,31 +259,27 @@ class SelectionStyleProvider final {
|
|||
// colors can be controlled by a ":selected" CSS rule.
|
||||
nsAutoCString style(":selected{");
|
||||
// FYI: LookAndFeel always returns selection colors of GtkTextView.
|
||||
nscolor selectionForegroundColor;
|
||||
if (NS_SUCCEEDED(
|
||||
LookAndFeel::GetColor(LookAndFeel::ColorID::TextSelectForeground,
|
||||
&selectionForegroundColor))) {
|
||||
if (auto selectionForegroundColor =
|
||||
GetSystemColor(LookAndFeel::ColorID::TextSelectForeground)) {
|
||||
double alpha =
|
||||
static_cast<double>(NS_GET_A(selectionForegroundColor)) / 0xFF;
|
||||
static_cast<double>(NS_GET_A(*selectionForegroundColor)) / 0xFF;
|
||||
style.AppendPrintf("color:rgba(%u,%u,%u,",
|
||||
NS_GET_R(selectionForegroundColor),
|
||||
NS_GET_G(selectionForegroundColor),
|
||||
NS_GET_B(selectionForegroundColor));
|
||||
NS_GET_R(*selectionForegroundColor),
|
||||
NS_GET_G(*selectionForegroundColor),
|
||||
NS_GET_B(*selectionForegroundColor));
|
||||
// We can't use AppendPrintf here, because it does locale-specific
|
||||
// formatting of floating-point values.
|
||||
style.AppendFloat(alpha);
|
||||
style.AppendPrintf(");");
|
||||
}
|
||||
nscolor selectionBackgroundColor;
|
||||
if (NS_SUCCEEDED(
|
||||
LookAndFeel::GetColor(LookAndFeel::ColorID::TextSelectBackground,
|
||||
&selectionBackgroundColor))) {
|
||||
if (auto selectionBackgroundColor =
|
||||
GetSystemColor(LookAndFeel::ColorID::TextSelectBackground)) {
|
||||
double alpha =
|
||||
static_cast<double>(NS_GET_A(selectionBackgroundColor)) / 0xFF;
|
||||
static_cast<double>(NS_GET_A(*selectionBackgroundColor)) / 0xFF;
|
||||
style.AppendPrintf("background-color:rgba(%u,%u,%u,",
|
||||
NS_GET_R(selectionBackgroundColor),
|
||||
NS_GET_G(selectionBackgroundColor),
|
||||
NS_GET_B(selectionBackgroundColor));
|
||||
NS_GET_R(*selectionBackgroundColor),
|
||||
NS_GET_G(*selectionBackgroundColor),
|
||||
NS_GET_B(*selectionBackgroundColor));
|
||||
style.AppendFloat(alpha);
|
||||
style.AppendPrintf(");");
|
||||
}
|
||||
|
|
|
@ -1223,10 +1223,11 @@ bool nsNativeThemeGTK::CreateWebRenderCommandsForWidget(
|
|||
switch (aAppearance) {
|
||||
case StyleAppearance::Window:
|
||||
case StyleAppearance::Dialog:
|
||||
aBuilder.PushRect(
|
||||
bounds, bounds, true,
|
||||
wr::ToColorF(ToDeviceColor(LookAndFeel::GetColor(
|
||||
LookAndFeel::ColorID::WindowBackground, NS_RGBA(0, 0, 0, 0)))));
|
||||
aBuilder.PushRect(bounds, bounds, true,
|
||||
wr::ToColorF(ToDeviceColor(LookAndFeel::Color(
|
||||
LookAndFeel::ColorID::WindowBackground,
|
||||
LookAndFeel::ColorScheme::Light,
|
||||
LookAndFeel::UseStandins::No, NS_TRANSPARENT))));
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
|
|
@ -85,11 +85,7 @@ nsresult HeadlessLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) {
|
|||
aColor = NS_RGB(0xaa, 0xaa, 0xaa);
|
||||
break;
|
||||
case ColorID::TextSelectForeground:
|
||||
GetColor(ColorID::TextSelectBackground, aColor);
|
||||
if (aColor == 0x000000)
|
||||
aColor = NS_RGB(0xff, 0xff, 0xff);
|
||||
else
|
||||
aColor = NS_DONT_CHANGE_COLOR;
|
||||
aColor = NS_DONT_CHANGE_COLOR;
|
||||
break;
|
||||
case ColorID::Widget3DHighlight:
|
||||
aColor = NS_RGB(0xa0, 0xa0, 0xa0);
|
||||
|
|
|
@ -72,9 +72,12 @@ static LayoutDeviceIntCoord SnapBorderWidth(
|
|||
|
||||
static nscolor ThemedAccentColor(bool aBackground) {
|
||||
MOZ_ASSERT(StaticPrefs::widget_non_native_theme_use_theme_accent());
|
||||
nscolor color = LookAndFeel::GetColor(
|
||||
// TODO(emilio): In the future we should probably add dark-color-scheme
|
||||
// support for non-native form controls.
|
||||
nscolor color = LookAndFeel::Color(
|
||||
aBackground ? LookAndFeel::ColorID::MozAccentColor
|
||||
: LookAndFeel::ColorID::MozAccentColorForeground);
|
||||
: LookAndFeel::ColorID::MozAccentColorForeground,
|
||||
LookAndFeel::ColorScheme::Light, LookAndFeel::UseStandins::No);
|
||||
if (NS_GET_A(color) != 0xff) {
|
||||
// Blend with white, ensuring the color is opaque to avoid surprises if we
|
||||
// overdraw.
|
||||
|
@ -196,7 +199,20 @@ static bool IsScrollbarWidthThin(nsIFrame* aFrame) {
|
|||
}
|
||||
|
||||
static sRGBColor SystemColor(StyleSystemColor aColor) {
|
||||
return sRGBColor::FromABGR(LookAndFeel::GetColor(aColor));
|
||||
// TODO(emilio): We could not hardcode light appearance here with a bit of
|
||||
// work, but doesn't matter for now.
|
||||
return sRGBColor::FromABGR(LookAndFeel::Color(
|
||||
aColor, LookAndFeel::ColorScheme::Light, LookAndFeel::UseStandins::No));
|
||||
}
|
||||
|
||||
template <typename Compute>
|
||||
static sRGBColor SystemColorOrElse(StyleSystemColor aColor, Compute aCompute) {
|
||||
if (auto color =
|
||||
LookAndFeel::GetColor(aColor, LookAndFeel::ColorScheme::Light,
|
||||
LookAndFeel::UseStandins::No)) {
|
||||
return sRGBColor::FromABGR(*color);
|
||||
}
|
||||
return aCompute();
|
||||
}
|
||||
|
||||
static std::pair<sRGBColor, sRGBColor> SystemColorPair(
|
||||
|
@ -539,17 +555,16 @@ sRGBColor nsNativeBasicTheme::ComputeScrollbarColor(
|
|||
if (ShouldUseDarkScrollbar(aFrame, aStyle)) {
|
||||
return sRGBColor::FromU8(20, 20, 25, 77);
|
||||
}
|
||||
nscolor color;
|
||||
if (ui->mScrollbarColor.IsColors()) {
|
||||
color = ui->mScrollbarColor.AsColors().track.CalcColor(aStyle);
|
||||
} else if (aDocumentState.HasAllStates(NS_DOCUMENT_STATE_WINDOW_INACTIVE)) {
|
||||
color = LookAndFeel::GetColor(LookAndFeel::ColorID::ThemedScrollbarInactive,
|
||||
sScrollbarColor.ToABGR());
|
||||
} else {
|
||||
color = LookAndFeel::GetColor(LookAndFeel::ColorID::ThemedScrollbar,
|
||||
sScrollbarColor.ToABGR());
|
||||
return sRGBColor::FromABGR(
|
||||
ui->mScrollbarColor.AsColors().track.CalcColor(aStyle));
|
||||
}
|
||||
return gfx::sRGBColor::FromABGR(color);
|
||||
if (aDocumentState.HasAllStates(NS_DOCUMENT_STATE_WINDOW_INACTIVE)) {
|
||||
return SystemColorOrElse(StyleSystemColor::ThemedScrollbarInactive,
|
||||
[] { return sScrollbarColor; });
|
||||
}
|
||||
return SystemColorOrElse(StyleSystemColor::ThemedScrollbar,
|
||||
[] { return sScrollbarColor; });
|
||||
}
|
||||
|
||||
nscolor nsNativeBasicTheme::AdjustUnthemedScrollbarThumbColor(
|
||||
|
@ -668,7 +683,6 @@ sRGBColor nsNativeBasicTheme::ComputeScrollbarThumbColor(
|
|||
}
|
||||
|
||||
const nsStyleUI* ui = aStyle.StyleUI();
|
||||
nscolor color;
|
||||
if (ui->mScrollbarColor.IsColors()) {
|
||||
return sRGBColor::FromABGR(AdjustUnthemedScrollbarThumbColor(
|
||||
ui->mScrollbarColor.AsColors().thumb.CalcColor(aStyle), aElementState));
|
||||
|
@ -696,11 +710,10 @@ sRGBColor nsNativeBasicTheme::ComputeScrollbarThumbColor(
|
|||
return StyleSystemColor::ThemedScrollbarThumb;
|
||||
}();
|
||||
|
||||
if (NS_FAILED(LookAndFeel::GetColor(systemColor, &color))) {
|
||||
color = AdjustUnthemedScrollbarThumbColor(sScrollbarThumbColor.ToABGR(),
|
||||
aElementState);
|
||||
}
|
||||
return gfx::sRGBColor::FromABGR(color);
|
||||
return SystemColorOrElse(systemColor, [&] {
|
||||
return sRGBColor::FromABGR(AdjustUnthemedScrollbarThumbColor(
|
||||
sScrollbarThumbColor.ToABGR(), aElementState));
|
||||
});
|
||||
}
|
||||
|
||||
std::pair<sRGBColor, sRGBColor>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsFont.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "nsNativeBasicTheme.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
|
@ -24,6 +25,8 @@
|
|||
#include "mozilla/StaticPrefs_findbar.h"
|
||||
#include "mozilla/StaticPrefs_ui.h"
|
||||
#include "mozilla/StaticPrefs_widget.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/PreferenceSheet.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/widget/WidgetMessageUtils.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
@ -62,7 +65,7 @@ struct nsLookAndFeelFloatPref {
|
|||
template <typename Index, typename Value, Index kEnd>
|
||||
class EnumeratedCache {
|
||||
static constexpr uint32_t ChunkFor(Index aIndex) {
|
||||
return uint32_t(aIndex) >> 5; // >> 5 is the same as / 32.
|
||||
return uint32_t(aIndex) >> 5; // >> 5 is the same as / 32.
|
||||
}
|
||||
static constexpr uint32_t BitFor(Index aIndex) {
|
||||
return 1u << (uint32_t(aIndex) & 31);
|
||||
|
@ -1047,15 +1050,69 @@ void LookAndFeel::NotifyChangedAllWindows(widget::ThemeChangeKind aKind) {
|
|||
}
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult LookAndFeel::GetColor(ColorID aID, nscolor* aResult) {
|
||||
return nsLookAndFeel::GetInstance()->GetColorValue(aID, false, *aResult);
|
||||
static bool ShouldUseStandinsForNativeColorForNonNativeTheme(
|
||||
const dom::Document& aDoc, LookAndFeel::ColorID aColor) {
|
||||
using ColorID = LookAndFeel::ColorID;
|
||||
if (!aDoc.ShouldAvoidNativeTheme()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The native theme doesn't use system colors backgrounds etc, except when in
|
||||
// high-contrast mode, so spoof some of the colors with stand-ins to prevent
|
||||
// lack of contrast.
|
||||
switch (aColor) {
|
||||
case ColorID::Buttonface:
|
||||
case ColorID::Buttontext:
|
||||
case ColorID::MozButtonhoverface:
|
||||
case ColorID::MozButtonhovertext:
|
||||
case ColorID::MozGtkButtonactivetext:
|
||||
|
||||
case ColorID::MozCombobox:
|
||||
case ColorID::MozComboboxtext:
|
||||
|
||||
case ColorID::Field:
|
||||
case ColorID::Fieldtext:
|
||||
|
||||
case ColorID::Graytext:
|
||||
|
||||
return !PreferenceSheet::PrefsFor(aDoc)
|
||||
.NonNativeThemeShouldUseSystemColors();
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult LookAndFeel::GetColor(ColorID aID, bool aUseStandinsForNativeColors,
|
||||
nscolor* aResult) {
|
||||
return nsLookAndFeel::GetInstance()->GetColorValue(
|
||||
aID, aUseStandinsForNativeColors, *aResult);
|
||||
static LookAndFeel::ColorScheme ColorSchemeForDocument(const dom::Document&) {
|
||||
// TODO(emilio): Actually compute a useful color scheme.
|
||||
return LookAndFeel::ColorScheme::Light;
|
||||
}
|
||||
|
||||
// static
|
||||
Maybe<nscolor> LookAndFeel::GetColor(ColorID aId, ColorScheme,
|
||||
UseStandins aUseStandins) {
|
||||
// TODO(emilio): Actually use ColorScheme.
|
||||
nscolor result;
|
||||
nsresult rv = nsLookAndFeel::GetInstance()->GetColorValue(
|
||||
aId, bool(aUseStandins), result);
|
||||
if (NS_FAILED(rv)) {
|
||||
return Nothing();
|
||||
}
|
||||
return Some(result);
|
||||
}
|
||||
|
||||
Maybe<nscolor> LookAndFeel::GetColor(ColorID aId, const dom::Document& aDoc) {
|
||||
const bool useStandins =
|
||||
ShouldUseStandinsForNativeColorForNonNativeTheme(aDoc, aId) ||
|
||||
(nsContentUtils::UseStandinsForNativeColors() &&
|
||||
!nsContentUtils::IsChromeDoc(&aDoc));
|
||||
return GetColor(aId, ColorSchemeForDocument(aDoc), UseStandins(useStandins));
|
||||
}
|
||||
|
||||
Maybe<nscolor> LookAndFeel::GetColor(ColorID aId, const nsIFrame* aFrame) {
|
||||
return GetColor(aId, *aFrame->PresContext()->Document());
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
Загрузка…
Ссылка в новой задаче