/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim:expandtab:shiftwidth=2:tabstop=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/. */
// for strtod() #include <stdlib.h> #include <dlfcn.h>
staticvoid OnSettingsChange() { if (sIgnoreChangedSettings) { return;
} // TODO: We could be more granular here, but for now assume everything // changed.
LookAndFeel::NotifyChangedAllWindows(widget::ThemeChangeKind::StyleAndLayout);
widget::IMContextWrapper::OnThemeChanged();
}
// DBus interface was started after L&F init so we need to load our settings // from DBus explicitly. if (RecomputeDBusSettings()) {
OnSettingsChange();
}
}
auto pattern = static_cast<cairo_pattern_t*>(g_value_get_boxed(aValue)); if (!pattern) { returnfalse;
}
// Just picking the lightest and darkest colors as simple samples rather // than trying to blend, which could get messy if there are many stops. if (CAIRO_STATUS_SUCCESS !=
cairo_pattern_get_color_stop_rgba(pattern, 0, nullptr, &aDarkColor->red,
&aDarkColor->green, &aDarkColor->blue,
&aDarkColor->alpha)) { returnfalse;
}
auto* pattern = static_cast<cairo_pattern_t*>(g_value_get_boxed(aValue)); if (!pattern) { returnfalse;
}
cairo_surface_t* surface; if (cairo_pattern_get_surface(pattern, &surface) != CAIRO_STATUS_SUCCESS) { returnfalse;
}
cairo_format_t format = cairo_image_surface_get_format(surface); if (format == CAIRO_FORMAT_INVALID) { returnfalse;
} int width = cairo_image_surface_get_width(surface); int height = cairo_image_surface_get_height(surface); int stride = cairo_image_surface_get_stride(surface); if (!width || !height) { returnfalse;
}
// Guesstimate the central pixel would have a sensible color. int x = width / 2; int y = height / 2;
unsignedchar* data = cairo_image_surface_get_data(surface); switch (format) { // Most (all?) GTK images / patterns / etc use ARGB32. case CAIRO_FORMAT_ARGB32: {
size_t offset = x * 4 + y * stride;
uint32_t* pixel = reinterpret_cast<uint32_t*>(data + offset);
*aColor = gfx::sRGBColor::UnusualFromARGB(*pixel).ToABGR(); returntrue;
} default: break;
}
returnfalse;
}
staticbool GetUnicoBorderGradientColors(GtkStyleContext* aContext,
GdkRGBA* aLightColor,
GdkRGBA* aDarkColor) { // Ubuntu 12.04 has GTK engine Unico-1.0.2, which overrides render_frame, // providing its own border code. Ubuntu 14.04 has // Unico-1.0.3+14.04.20140109, which does not override render_frame, and // so does not need special attention. The earlier Unico can be detected // by the -unico-border-gradient style property it registers. // gtk_style_properties_lookup_property() is checked first to avoid the // warning from gtk_style_context_get_property() when the property does // not exist. (gtk_render_frame() of GTK+ 3.16 no longer uses the // engine.) constchar* propertyName = "-unico-border-gradient"; if (!gtk_style_properties_lookup_property(propertyName, nullptr, nullptr)) returnfalse;
// -unico-border-gradient is used only when the CSS node's engine is Unico.
GtkThemingEngine* engine;
GtkStateFlags state = gtk_style_context_get_state(aContext);
gtk_style_context_get(aContext, state, "engine", &engine, nullptr); if (strcmp(g_type_name(G_TYPE_FROM_INSTANCE(engine)), "UnicoEngine") != 0) returnfalse;
// draw_border() of Unico engine uses -unico-border-gradient // in preference to border-color.
GValue value = G_VALUE_INIT;
gtk_style_context_get_property(aContext, propertyName, state, &value);
bool result = GetGradientColors(&value, aLightColor, aDarkColor);
g_value_unset(&value); return result;
}
// Sets |aLightColor| and |aDarkColor| to colors from |aContext|. Returns // true if |aContext| uses these colors to render a visible border. // If returning false, then the colors returned are a fallback from the // border-color value even though |aContext| does not use these colors to // render a border. staticbool GetBorderColors(GtkStyleContext* aContext, GdkRGBA* aLightColor,
GdkRGBA* aDarkColor) { // Determine whether the border on this style context is visible.
GtkStateFlags state = gtk_style_context_get_state(aContext);
GtkBorderStyle borderStyle;
gtk_style_context_get(aContext, state, GTK_STYLE_PROPERTY_BORDER_STYLE,
&borderStyle, nullptr); bool visible = borderStyle != GTK_BORDER_STYLE_NONE &&
borderStyle != GTK_BORDER_STYLE_HIDDEN; if (visible) { // GTK has an initial value of zero for border-widths, and so themes // need to explicitly set border-widths to make borders visible.
GtkBorder border;
gtk_style_context_get_border(aContext, state, &border);
visible = border.top != 0 || border.right != 0 || border.bottom != 0 ||
border.left != 0;
}
if (visible &&
GetUnicoBorderGradientColors(aContext, aLightColor, aDarkColor)) returntrue;
// The initial value for the border-color is the foreground color, and so // this will usually return a color distinct from the background even if // there is no visible border detected.
gtk_style_context_get_border_color(aContext, state, aDarkColor); // TODO GTK3 - update aLightColor // for GTK_BORDER_STYLE_INSET/OUTSET/GROVE/RIDGE border styles. // https://bugzilla.mozilla.org/show_bug.cgi?id=978172#c25
*aLightColor = *aDarkColor; return visible;
}
// Finds ideal cell highlight colors used for unfocused+selected cells distinct // from both Highlight, used as focused+selected background, and the listbox // background which is assumed to be similar to -moz-field void nsLookAndFeel::PerThemeData::InitCellHighlightColors() {
int32_t minLuminosityDifference = NS_SUFFICIENT_LUMINOSITY_DIFFERENCE_BG;
int32_t backLuminosityDifference =
NS_LUMINOSITY_DIFFERENCE(mWindow.mBg, mField.mBg); if (backLuminosityDifference >= minLuminosityDifference) {
mCellHighlight = mWindow; return;
}
uint16_t step = 30; // Lighten the color if the color is very dark if (luminance <= step) {
luminance += step;
} // Darken it if it is very light elseif (luminance >= 255 - step) {
luminance -= step;
} // Otherwise, compute what works best depending on the text luminance. else {
uint16_t textHue, textSat, textLuminance;
uint8_t textAlpha;
NS_RGB2HSV(mCellHighlight.mFg, textHue, textSat, textLuminance, textAlpha); // Text is darker than background, use a lighter shade if (textLuminance < luminance) {
luminance += step;
} // Otherwise, use a darker shade else {
luminance -= step;
}
}
NS_HSV2RGB(mCellHighlight.mBg, hue, sat, luminance, alpha);
}
switch (aID) { // These colors don't seem to be used for anything anymore in Mozilla // The CSS2 colors below are used. case ColorID::Appworkspace: // MDI background color case ColorID::Background: // desktop background case ColorID::Window: case ColorID::Windowframe: case ColorID::MozCombobox:
aColor = mWindow.mBg; break; case ColorID::Windowtext:
aColor = mWindow.mFg; break; case ColorID::MozDialog:
aColor = mDialog.mBg; break; case ColorID::MozDialogtext:
aColor = mDialog.mFg; break; case ColorID::IMESelectedRawTextBackground: case ColorID::IMESelectedConvertedTextBackground: case ColorID::Highlight: // preference selected item,
aColor = mSelectedText.mBg; break; case ColorID::Highlighttext: if (NS_GET_A(mSelectedText.mBg) < 155) {
aColor = NS_SAME_AS_FOREGROUND_COLOR; break;
}
[[fallthrough]]; case ColorID::IMESelectedRawTextForeground: case ColorID::IMESelectedConvertedTextForeground:
aColor = mSelectedText.mFg; break; case ColorID::Selecteditem:
aColor = mSelectedItem.mBg; break; case ColorID::Selecteditemtext:
aColor = mSelectedItem.mFg; break; case ColorID::Accentcolor:
aColor = mAccent.mBg; break; case ColorID::Accentcolortext:
aColor = mAccent.mFg; break; case ColorID::MozCellhighlight:
aColor = mCellHighlight.mBg; break; case ColorID::MozCellhighlighttext:
aColor = mCellHighlight.mFg; break; case ColorID::IMERawInputBackground: case ColorID::IMEConvertedTextBackground:
aColor = NS_TRANSPARENT; break; case ColorID::IMERawInputForeground: case ColorID::IMEConvertedTextForeground:
aColor = NS_SAME_AS_FOREGROUND_COLOR; break; case ColorID::IMERawInputUnderline: case ColorID::IMEConvertedTextUnderline:
aColor = NS_SAME_AS_FOREGROUND_COLOR; break; case ColorID::IMESelectedRawTextUnderline: case ColorID::IMESelectedConvertedTextUnderline:
aColor = NS_TRANSPARENT; break; case ColorID::Scrollbar:
aColor = mThemedScrollbar; break; case ColorID::ThemedScrollbar:
aColor = mThemedScrollbar; if (!ShouldUseThemedScrollbarColor(aID, aColor, mIsDark)) { return NS_ERROR_FAILURE;
} break; case ColorID::ThemedScrollbarInactive:
aColor = mThemedScrollbarInactive; if (!ShouldUseThemedScrollbarColor(aID, aColor, mIsDark)) { return NS_ERROR_FAILURE;
} break; case ColorID::ThemedScrollbarThumb:
aColor = mThemedScrollbarThumb; if (!ShouldUseThemedScrollbarColor(aID, aColor, mIsDark)) { return NS_ERROR_FAILURE;
} break; case ColorID::ThemedScrollbarThumbHover:
aColor = mThemedScrollbarThumbHover; if (!ShouldUseThemedScrollbarColor(aID, aColor, mIsDark)) { return NS_ERROR_FAILURE;
} break; case ColorID::ThemedScrollbarThumbActive:
aColor = mThemedScrollbarThumbActive; if (!ShouldUseThemedScrollbarColor(aID, aColor, mIsDark)) { return NS_ERROR_FAILURE;
} break; case ColorID::ThemedScrollbarThumbInactive:
aColor = mThemedScrollbarThumbInactive; if (!ShouldUseThemedScrollbarColor(aID, aColor, mIsDark)) { return NS_ERROR_FAILURE;
} break;
// css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors case ColorID::Activeborder: // active window border
aColor = mMozWindowActiveBorder; break; case ColorID::Inactiveborder: // inactive window border
aColor = mMozWindowInactiveBorder; break; case ColorID::Graytext: // disabled text in windows, menus, etc.
aColor = mGrayText; break; case ColorID::Activecaption:
aColor = mTitlebar.mBg; break; case ColorID::Captiontext: // text in active window caption (titlebar)
aColor = mTitlebar.mFg; break; case ColorID::Inactivecaption: // inactive window caption
aColor = mTitlebarInactive.mBg; break; case ColorID::Inactivecaptiontext:
aColor = mTitlebarInactive.mFg; break; case ColorID::Infobackground:
aColor = mInfo.mBg; break; case ColorID::Infotext:
aColor = mInfo.mFg; break; case ColorID::Menu:
aColor = mMenu.mBg; break; case ColorID::Menutext:
aColor = mMenu.mFg; break; case ColorID::MozHeaderbar:
aColor = mHeaderBar.mBg; break; case ColorID::MozHeaderbartext:
aColor = mHeaderBar.mFg; break; case ColorID::MozHeaderbarinactive:
aColor = mHeaderBarInactive.mBg; break; case ColorID::MozHeaderbarinactivetext:
aColor = mHeaderBarInactive.mFg; break; case ColorID::Threedface: case ColorID::Buttonface: case ColorID::MozButtondisabledface: // 3-D face color
aColor = mWindow.mBg; break;
case ColorID::Buttontext: // text on push buttons
aColor = mButton.mFg; break;
case ColorID::Buttonhighlight: // 3-D highlighted edge color case ColorID::Threedhighlight: // 3-D highlighted outer edge color
aColor = mThreeDHighlight; break;
case ColorID::Buttonshadow: // 3-D shadow edge color case ColorID::Threedshadow: // 3-D shadow inner edge color
aColor = mThreeDShadow; break; case ColorID::Buttonborder:
aColor = mButtonBorder; break; case ColorID::Threedlightshadow: case ColorID::MozDisabledfield:
aColor = mIsDark ? *GenericDarkColor(aID) : NS_RGB(0xE0, 0xE0, 0xE0); break; case ColorID::Threeddarkshadow:
aColor = mIsDark ? *GenericDarkColor(aID) : NS_RGB(0xDC, 0xDC, 0xDC); break;
case ColorID::MozEventreerow: case ColorID::Field:
aColor = mField.mBg; break; case ColorID::Fieldtext:
aColor = mField.mFg; break; case ColorID::MozSidebar:
aColor = mSidebar.mBg; break; case ColorID::MozSidebartext:
aColor = mSidebar.mFg; break; case ColorID::MozSidebarborder:
aColor = mSidebarBorder; break; case ColorID::MozButtonhoverface:
aColor = mButtonHover.mBg; break; case ColorID::MozButtonhovertext:
aColor = mButtonHover.mFg; break; case ColorID::MozButtonactiveface:
aColor = mButtonActive.mBg; break; case ColorID::MozButtonactivetext:
aColor = mButtonActive.mFg; break; case ColorID::MozMenuhover:
aColor = mMenuHover.mBg; break; case ColorID::MozMenuhovertext:
aColor = mMenuHover.mFg; break; case ColorID::MozMenuhoverdisabled:
aColor = NS_TRANSPARENT; break; case ColorID::MozOddtreerow:
aColor = mOddCellBackground; break; case ColorID::MozNativehyperlinktext:
aColor = mNativeHyperLinkText; break; case ColorID::MozNativevisitedhyperlinktext:
aColor = mNativeVisitedHyperLinkText; break; case ColorID::MozComboboxtext:
aColor = mComboBoxText; break; case ColorID::MozColheader:
aColor = mMozColHeader.mBg; break; case ColorID::MozColheadertext:
aColor = mMozColHeader.mFg; break; case ColorID::MozColheaderhover:
aColor = mMozColHeaderHover.mBg; break; case ColorID::MozColheaderhovertext:
aColor = mMozColHeaderHover.mFg; break; case ColorID::MozColheaderactive:
aColor = mMozColHeaderActive.mBg; break; case ColorID::MozColheaderactivetext:
aColor = mMozColHeaderActive.mFg; break; case ColorID::SpellCheckerUnderline: case ColorID::Mark: case ColorID::Marktext: case ColorID::MozAutofillBackground: case ColorID::TargetTextBackground: case ColorID::TargetTextForeground:
aColor = GetStandinForNativeColor(
aID, mIsDark ? ColorScheme::Dark : ColorScheme::Light); break; default: /* default color is BLACK */
aColor = 0;
res = NS_ERROR_FAILURE; break;
}
nsresult nsLookAndFeel::NativeGetInt(IntID aID, int32_t& aResult) {
nsresult res = NS_OK;
// We use delayed initialization by EnsureInit() here // to make sure mozilla::Preferences is available (Bug 115807). // IntID::UseAccessibilityTheme is requested before user preferences // are read, and so EnsureInit(), which depends on preference values, // is deliberately delayed until required. switch (aID) { case IntID::ScrollButtonLeftMouseButtonAction:
aResult = 0; break; case IntID::ScrollButtonMiddleMouseButtonAction:
aResult = 1; break; case IntID::ScrollButtonRightMouseButtonAction:
aResult = 2; break; case IntID::CaretBlinkTime:
EnsureInit();
aResult = mCaretBlinkTime; break; case IntID::CaretBlinkCount:
EnsureInit();
aResult = mCaretBlinkCount; break; case IntID::CaretWidth:
aResult = 1; break; case IntID::SelectTextfieldsOnKeyFocus: {
GtkSettings* settings;
gboolean select_on_focus;
// |size| is now either pixels or pango-points (not Mozilla-points!)
if (!pango_font_description_get_size_is_absolute(desc)) { // |size| is in pango-points, so convert to pixels.
size *= float(gfxPlatformGtk::GetFontScaleDPI()) / POINTS_PER_INCH_FLOAT;
}
// |size| is now pixels but not scaled for the hidpi displays,
aFontStyle->size = size;
case FontID::Caption: // css2 case FontID::Icon: // css2 case FontID::MessageBox: // css2 case FontID::SmallCaption: // css2 case FontID::StatusBar: // css2 default:
aFontName = mDefaultFontName;
aFontStyle = mDefaultFontStyle; break;
}
// Convert GDK pixels to CSS pixels. // When "layout.css.devPixelsPerPx" > 0, this is not a direct conversion. // The difference produces a scaling of system fonts in proportion with // other scaling from the change in CSS pixel sizes.
aFontStyle.size /= LookAndFeel::GetTextScaleFactor(); returntrue;
}
// It seems GTK doesn't have an API to query if the current theme is "light" or // "dark", so we synthesize it from the CSS2 Window/WindowText colors instead, // by comparing their luminosity. staticbool GetThemeIsDark() {
GdkRGBA bg, fg;
GtkStyleContext* style = GetStyleContext(MOZ_GTK_WINDOW);
gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &bg);
gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &fg); return RelativeLuminanceUtils::Compute(GDK_RGBA_TO_NS_RGBA(bg)) <
RelativeLuminanceUtils::Compute(GDK_RGBA_TO_NS_RGBA(fg));
}
bool nsLookAndFeel::ConfigureAltTheme() {
GtkSettings* settings = gtk_settings_get_default(); // Toggling gtk-application-prefer-dark-theme is not enough generally to // switch from dark to light theme. If the theme didn't change, and we have // a dark theme, try to first remove -Dark{,er,est} from the theme name to // find the light variant. if (mSystemTheme.mIsDark) {
nsCString potentialLightThemeName = mSystemTheme.mName; // clang-format off
constexpr nsLiteralCString kSubstringsToRemove[] = { "-darkest"_ns, "-darker"_ns, "-dark"_ns, "-Darkest"_ns, "-Darker"_ns, "-Dark"_ns, "_darkest"_ns, "_darker"_ns, "_dark"_ns, "_Darkest"_ns, "_Darker"_ns, "_Dark"_ns,
}; // clang-format on bool found = false; for (constauto& s : kSubstringsToRemove) {
potentialLightThemeName = mSystemTheme.mName;
potentialLightThemeName.ReplaceSubstring(s, ""_ns); if (potentialLightThemeName.Length() != mSystemTheme.mName.Length()) {
found = true; break;
}
} if (found) {
LOGLNF(" found potential light variant of %s: %s",
mSystemTheme.mName.get(), potentialLightThemeName.get());
g_object_set(settings, "gtk-theme-name", potentialLightThemeName.get(), "gtk-application-prefer-dark-theme", !mSystemTheme.mIsDark,
nullptr);
moz_gtk_refresh();
if (!GetThemeIsDark()) { returntrue; // Success!
}
}
}
LOGLNF(" didn't work, falling back to default theme"); // If the theme still didn't change enough, fall back to Adwaita with the // appropriate color preference.
g_object_set(settings, "gtk-theme-name", "Adwaita", "gtk-application-prefer-dark-theme", !mSystemTheme.mIsDark,
nullptr);
moz_gtk_refresh();
// If it _still_ didn't change enough, and we're looking for a dark theme, // try to set Adwaita-dark as a theme name. This might be needed in older GTK // versions. if (!mSystemTheme.mIsDark && !GetThemeIsDark()) {
LOGLNF(" last resort Adwaita-dark fallback");
g_object_set(settings, "gtk-theme-name", "Adwaita-dark", nullptr);
moz_gtk_refresh();
}
returnfalse;
}
// We override some adwaita colors from GTK3 to LibAdwaita, see: // https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/named-colors.html void nsLookAndFeel::MaybeApplyAdwaitaOverrides() { auto& dark = mSystemTheme.mIsDark ? mSystemTheme : mAltTheme; auto& light = mSystemTheme.mIsDark ? mAltTheme : mSystemTheme;
// Unconditional special case for Adwaita-dark: In GTK3 we don't have more // proper accent colors, so we use the selected background colors. Those // colors, however, don't have much contrast in dark mode (see bug 1741293). if (dark.mFamily == ThemeFamily::Adwaita) { if (mDBusSettings.HasAccentColor()) {
dark.mAccent = mDBusSettings.mAccentColor;
dark.mSelectedItem = dark.mMenuHover = dark.mAccent;
dark.mNativeHyperLinkText = dark.mNativeVisitedHyperLinkText =
dark.mAccent.mBg;
} else {
dark.mAccent = {NS_RGB(0x35, 0x84, 0xe4), NS_RGB(0xff, 0xff, 0xff)};
}
dark.mSelectedText = dark.mAccent;
}
if (!StaticPrefs::widget_gtk_libadwaita_colors_enabled()) { return;
}
if (light.mFamily == ThemeFamily::Adwaita) { // #323232 is rgba(0,0,0,.8) over #fafafa.
light.mWindow =
light.mDialog = {NS_RGB(0xfa, 0xfa, 0xfa), NS_RGB(0x32, 0x32, 0x32)};
light.mField = {NS_RGB(0xff, 0xff, 0xff), NS_RGB(0x32, 0x32, 0x32)};
// We use the sidebar colors for the headerbar in light mode background // because it creates much better contrast. GTK headerbar colors are white, // and meant to "blend" with the contents otherwise. // #2f2f2f is rgba(0,0,0,.8) over #ebebeb.
light.mSidebar = light.mHeaderBar =
light.mTitlebar = {NS_RGB(0xeb, 0xeb, 0xeb), NS_RGB(0x2f, 0x2f, 0x2f)};
light.mHeaderBarInactive = light.mTitlebarInactive = {
NS_RGB(0xf2, 0xf2, 0xf2), NS_RGB(0x2f, 0x2f, 0x2f)};
light.mThreeDShadow = NS_RGB(0xe0, 0xe0, 0xe0);
light.mSidebarBorder = NS_RGBA(0, 0, 0, 18);
}
// Some of the alt theme colors we can grab from the system theme, if we fell // back to the default light / dark themes. if (fellBackToDefaultTheme) { if (StaticPrefs::widget_gtk_alt_theme_selection()) {
mAltTheme.mSelectedText = mSystemTheme.mSelectedText;
}
if (StaticPrefs::widget_gtk_alt_theme_accent()) {
mAltTheme.mAccent = mSystemTheme.mAccent;
}
}
// Right now we're using the opposite color-scheme theme, make sure to record // it.
mSystemThemeOverridden = true;
UpdateRoundedBottomCornerStyles();
}
Maybe<ColorScheme> nsLookAndFeel::ComputeColorSchemeSetting() {
{ // Check the pref explicitly here. Usually this shouldn't be needed, but // since we can only load one GTK theme at a time, and the pref will // override the effective value that the rest of gecko assumes for the // "system" color scheme, we need to factor it in our GTK theme decisions.
int32_t pref = 0; if (NS_SUCCEEDED(Preferences::GetInt("ui.systemUsesDarkTheme", &pref))) { return Some(pref ? ColorScheme::Dark : ColorScheme::Light);
}
}
return mDBusSettings.mColorScheme;
}
void nsLookAndFeel::Initialize() {
LOGLNF("nsLookAndFeel::Initialize");
MOZ_DIAGNOSTIC_ASSERT(!mInitialized);
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread(), "LookAndFeel init should be done on the main thread");
mInitialized = true;
GtkSettings* settings = gtk_settings_get_default(); if (MOZ_UNLIKELY(!settings)) {
NS_WARNING("EnsureInit: No settings"); return;
}
// Our current theme may be different from the system theme if we're matching // the Firefox theme or using the alt theme intentionally due to the // color-scheme preference. Make sure to restore the original system theme.
RestoreSystemTheme();
// First initialize global settings.
InitializeGlobalSettings();
// Record our system theme settings now.
mSystemTheme.Init();
// Find the alternative-scheme theme (light if the system theme is dark, or // vice versa), configure it and initialize it.
ConfigureAndInitializeAltTheme();
LOGLNF("System Theme: %s. Alt Theme: %s\n", mSystemTheme.mName.get(),
mAltTheme.mName.get());
// Go back to the system theme or keep the alt theme configured, depending on // Firefox theme or user color-scheme preference.
ConfigureFinalEffectiveTheme();
gint blink_time = 0; // In milliseconds
gint blink_timeout = 0; // in seconds
gboolean blink;
g_object_get(settings, "gtk-cursor-blink-time", &blink_time, "gtk-cursor-blink-timeout", &blink_timeout, "gtk-cursor-blink",
&blink, nullptr); // From // https://docs.gtk.org/gtk3/property.Settings.gtk-cursor-blink-timeout.html: // // Setting this to zero has the same effect as setting // GtkSettings:gtk-cursor-blink to FALSE. //
mCaretBlinkTime = blink && blink_timeout ? (int32_t)blink_time : 0;
if (mCaretBlinkTime) { // blink_time * 2 because blink count is a full blink cycle.
mCaretBlinkCount =
std::max(1, int32_t(std::ceil(float(blink_timeout * 1000) /
(float(blink_time) * 2.0f))));
} else {
mCaretBlinkCount = -1;
}
// We need to initialize whole CSD config explicitly because it's queried // as -moz-gtk* media features.
ButtonLayout buttonLayout[TOOLBAR_BUTTONS];
size_t activeButtons =
GetGtkHeaderBarButtonLayout(Span(buttonLayout), &mCSDReversedPlacement); for (size_t i = 0; i < activeButtons; i++) { // We check if a button is represented on the right side of the tabbar. // Then we assign it a value from 3 to 5, instead of 0 to 2 when it is on // the left side. const ButtonLayout& layout = buttonLayout[i];
int32_t* pos = nullptr; switch (layout.mType) { case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
mCSDMinimizeButton = true;
pos = &mCSDMinimizeButtonPosition; break; case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
mCSDMaximizeButton = true;
pos = &mCSDMaximizeButtonPosition; break; case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
mCSDCloseButton = true;
pos = &mCSDCloseButtonPosition; break; default: break;
}
void nsLookAndFeel::ConfigureFinalEffectiveTheme() {
MOZ_ASSERT(mSystemThemeOverridden, "By this point, the alt theme should be configured"); constbool shouldUseSystemTheme = [&] { using ChromeSetting = PreferenceSheet::ChromeColorSchemeSetting; // NOTE: We can't call ColorSchemeForChrome directly because this might run // while we're computing it. switch (PreferenceSheet::ColorSchemeSettingForChrome()) { case ChromeSetting::Light: return !mSystemTheme.mIsDark; case ChromeSetting::Dark: return mSystemTheme.mIsDark; case ChromeSetting::System: break;
}; if (!mColorSchemePreference) { returntrue;
} constbool preferenceIsDark = *mColorSchemePreference == ColorScheme::Dark; return preferenceIsDark == mSystemTheme.mIsDark;
}();
GtkSettings* settings = gtk_settings_get_default(); if (mSystemTheme.mName == mAltTheme.mName) { // Prefer setting only gtk-application-prefer-dark-theme, so we can still // get notified from notify::gtk-theme-name if the user changes the theme.
g_object_set(settings, "gtk-application-prefer-dark-theme",
mAltTheme.mPreferDarkTheme, nullptr);
} else {
g_object_set(settings, "gtk-theme-name", mAltTheme.mName.get(), "gtk-application-prefer-dark-theme",
mAltTheme.mPreferDarkTheme, nullptr);
}
mSystemThemeOverridden = true;
UpdateRoundedBottomCornerStyles();
moz_gtk_refresh();
}
}
{
GdkRGBA light, dark; if (GetGradientColors(&value, &light, &dark)) {
nscolor l = GDK_RGBA_TO_NS_RGBA(light);
nscolor d = GDK_RGBA_TO_NS_RGBA(dark); // Return the one with more contrast. // TODO(emilio): This could do interpolation or what not but seems // overkill. if (NS_LUMINOSITY_DIFFERENCE(l, aForForegroundColor) >
NS_LUMINOSITY_DIFFERENCE(d, aForForegroundColor)) {
*aColor = l;
} else {
*aColor = d;
} returntrue;
}
}
returnfalse;
}
static nscolor GetBackgroundColor(
GtkStyleContext* aStyle, nscolor aForForegroundColor,
GtkStateFlags aState = GTK_STATE_FLAG_NORMAL,
nscolor aOverBackgroundColor = NS_TRANSPARENT) { // Try to synthesize a color from a background-image.
nscolor imageColor = NS_TRANSPARENT; if (GetColorFromBackgroundImage(aStyle, aForForegroundColor, aState,
&imageColor)) { if (NS_GET_A(imageColor) == 255) { return imageColor;
}
}
// If the colors are semi-transparent and the theme provides a // background color, blend with them to get the "final" color, see // bug 1717077. if (NS_GET_A(aPair->mBg) != 255 &&
(gtk_style_context_lookup_color(aStyle, "bg_color", &bg) ||
gtk_style_context_lookup_color(aStyle, "theme_bg_color", &bg))) {
aPair->mBg = NS_ComposeColors(GDK_RGBA_TO_NS_RGBA(bg), aPair->mBg);
}
// A semi-transparent foreground color would be kinda silly, but is done // for symmetry. if (NS_GET_A(aPair->mFg) != 255) {
aPair->mFg = NS_ComposeColors(aPair->mBg, aPair->mFg);
}
returntrue;
}
staticvoid EnsureColorPairIsOpaque(ColorPair& aPair) { // Blend with white, ensuring the color is opaque, so that the UI doesn't have // to care about alpha.
aPair.mBg = NS_ComposeColors(NS_RGB(0xff, 0xff, 0xff), aPair.mBg);
aPair.mFg = NS_ComposeColors(aPair.mBg, aPair.mFg);
}
staticvoid PreferDarkerBackground(ColorPair& aPair) { // We use the darker one unless the foreground isn't really a color (is all // white / black / gray) and the background is, in which case we stick to what // we have. if (RelativeLuminanceUtils::Compute(aPair.mBg) >
RelativeLuminanceUtils::Compute(aPair.mFg) &&
(AnyColorChannelIsDifferent(aPair.mFg) ||
!AnyColorChannelIsDifferent(aPair.mBg))) {
std::swap(aPair.mBg, aPair.mFg);
}
}
GdkRGBA color; // Some themes style the <trough>, while others style the <scrollbar> // itself, so we look at both and compose the colors.
style = GetStyleContext(MOZ_GTK_SCROLLBAR_VERTICAL);
--> --------------------
--> maximum size reached
--> --------------------
¤ Dauer der Verarbeitung: 0.37 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.