Commit 419a91a1 authored by thomasanderson's avatar thomasanderson Committed by Commit bot

Gtk3: More fixes and refactorings

This CL
* Uses entry colors instead of window colors for the NTP
* Fixes a leak involving ScopedGObject
* Simplifies how background and border colors are calculated
* Adds the ".label" class only on versions of Gtk before 3.20
* Fixes text selection colors on one theme
* Updates the doc to reflect the new way colors are calculated

BUG=132847

Review-Url: https://codereview.chromium.org/2683953005
Cr-Commit-Position: refs/heads/master@{#449709}
parent b0e1c97b
......@@ -822,14 +822,15 @@ void GtkUi::LoadGtkValues() {
colors_[ThemeProperties::COLOR_BACKGROUND_TAB_TEXT] =
color_utils::BlendTowardOppositeLuma(toolbar_text_color, 50);
// Color drawn around the location bar.
colors_[ThemeProperties::COLOR_LOCATION_BAR_BORDER] =
SkColor location_bar_border =
GetBorderColor("GtkToolbar#toolbar GtkEntry#entry");
if (SkColorGetA(location_bar_border)) {
colors_[ThemeProperties::COLOR_LOCATION_BAR_BORDER] = location_bar_border;
}
inactive_selection_bg_color_ =
GetBgColor("GtkEntry#entry:backdrop #selection:selected");
inactive_selection_bg_color_ = GetSelectedBgColor("GtkEntry#entry:backdrop");
inactive_selection_fg_color_ =
GetFgColor("GtkEntry#entry:backdrop #selection:selected");
GetSelectedTextColor("GtkEntry#entry:backdrop");
SkColor toolbar_separator_horizontal =
GetSeparatorColor("GtkToolbar#toolbar GtkSeparator#separator.horizontal");
......@@ -865,10 +866,8 @@ void GtkUi::LoadGtkValues() {
header_button_inactive_border;
}
SkColor ntp_bg = GetBgColor("");
colors_[ThemeProperties::COLOR_NTP_BACKGROUND] = ntp_bg;
colors_[ThemeProperties::COLOR_NTP_TEXT] =
color_utils::GetReadableColor(GetFgColor("GtkLabel#label"), ntp_bg);
colors_[ThemeProperties::COLOR_NTP_BACKGROUND] = GetBgColor("GtkEntry#entry");
colors_[ThemeProperties::COLOR_NTP_TEXT] = GetFgColor("GtkEntry#entry");
colors_[ThemeProperties::COLOR_NTP_HEADER] =
GetBorderColor("GtkButton#button");
#endif
......@@ -876,13 +875,13 @@ void GtkUi::LoadGtkValues() {
colors_[ThemeProperties::COLOR_TOOLBAR] = toolbar_color;
colors_[ThemeProperties::COLOR_CONTROL_BACKGROUND] = toolbar_color;
colors_[ThemeProperties::COLOR_NTP_LINK] =
native_theme_->GetSystemColor(ui::NativeTheme::kColorId_LinkEnabled);
colors_[ThemeProperties::COLOR_NTP_LINK] = native_theme_->GetSystemColor(
ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused);
// Generate the colors that we pass to WebKit.
SetScrollbarColors();
focus_ring_color_ = native_theme_->GetSystemColor(
ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused);
focus_ring_color_ =
native_theme_->GetSystemColor(ui::NativeTheme::kColorId_LinkEnabled);
// Some GTK themes only define the text selection colors on the GtkEntry
// class, so we need to use that for getting selection colors.
......
This diff is collapsed.
......@@ -98,10 +98,10 @@ class CairoSurface {
// Get the drawing context for GTK to use.
cairo_t* cairo() { return cairo_; }
// If |only_frame_pixels| is false, returns the average of all
// pixels in the surface, otherwise returns the average of only the
// edge pixels.
SkColor GetAveragePixelValue(bool only_frame_pixels);
// Returns the average of all pixels in the surface. If |frame| is
// true, the resulting alpha will be the average alpha, otherwise it
// will be the max alpha across all pixels.
SkColor GetAveragePixelValue(bool frame);
private:
cairo_surface_t* surface_;
......@@ -112,18 +112,18 @@ class CairoSurface {
// |major|.|minor|.|micro|.
bool GtkVersionCheck(int major, int minor = 0, int micro = 0);
// Similar in spirit to a std::unique_ptr.
template <typename T>
class ScopedGObject {
public:
explicit ScopedGObject(T* obj) : obj_(obj) {
// Increase the reference count of |obj_|, removing the floating
// reference if it has one.
g_object_ref_sink(obj_);
// Remove the floating reference from |obj_| if it has one.
if (g_object_is_floating(obj_))
g_object_ref_sink(obj_);
DCHECK(G_OBJECT(obj_)->ref_count == 1);
}
ScopedGObject(const ScopedGObject<T>& other) : obj_(other.obj_) {
g_object_ref(obj_);
}
ScopedGObject(const ScopedGObject<T>& other) = delete;
ScopedGObject(ScopedGObject<T>&& other) : obj_(other.obj_) {
other.obj_ = nullptr;
......@@ -131,15 +131,10 @@ class ScopedGObject {
~ScopedGObject() {
if (obj_)
g_object_unref(obj_);
Unref();
}
ScopedGObject<T>& operator=(const ScopedGObject<T>& other) {
g_object_ref(other.obj_);
g_object_unref(obj_);
obj_ = other.obj_;
return *this;
}
ScopedGObject<T>& operator=(const ScopedGObject<T>& other) = delete;
ScopedGObject<T>& operator=(ScopedGObject<T>&& other) {
g_object_unref(obj_);
......@@ -151,10 +146,35 @@ class ScopedGObject {
operator T*() { return obj_; }
private:
void Unref() { g_object_unref(obj_); }
T* obj_;
};
template <>
inline void ScopedGObject<GtkStyleContext>::Unref() {
// Versions of GTK earlier than 3.15.4 had a bug where a g_assert
// would be triggered when trying to free a GtkStyleContext that had
// a parent whose only reference was the child context in question.
// This is a hack to work around that case. See GTK commit
// "gtkstylecontext: Don't try to emit a signal when finalizing".
GtkStyleContext* context = obj_;
while (context) {
GtkStyleContext* parent = gtk_style_context_get_parent(context);
if (parent && G_OBJECT(context)->ref_count == 1 &&
!GtkVersionCheck(3, 15, 4)) {
g_object_ref(parent);
gtk_style_context_set_parent(context, nullptr);
} else {
g_object_unref(context);
return;
}
context = parent;
}
}
typedef ScopedGObject<GtkStyleContext> ScopedStyleContext;
typedef ScopedGObject<GtkCssProvider> ScopedCssProvider;
// If |context| is NULL, creates a new top-level style context
// specified by parsing |css_node|. Otherwise, creates the child
......@@ -170,10 +190,11 @@ ScopedStyleContext AppendCssNodeToStyleContext(GtkStyleContext* context,
// must g_object_unref() the returned context.
ScopedStyleContext GetStyleContextFromCss(const char* css_selector);
SkColor SkColorFromStyleContext(GtkStyleContext* context);
SkColor GetFgColorFromStyleContext(GtkStyleContext* context);
// Removes all border-type properties on |context| and all of its parents.
void RemoveBorders(GtkStyleContext* context);
// Overrides properties on |context| and all its parents with those
// provided by |css|.
void ApplyCssToContext(GtkStyleContext* context, const char* css);
// Get the 'color' property from the style context created by
// GetStyleContextFromCss(|css_selector|).
......@@ -186,15 +207,18 @@ void RenderBackground(const gfx::Size& size,
GtkStyleContext* context);
// Renders a background from the style context created by
// GetStyleContextFromCss(|css_selector|) into a single pixel and
// returns the color.
// GetStyleContextFromCss(|css_selector|) into a 24x24 bitmap and
// returns the average color.
SkColor GetBgColor(const char* css_selector);
// If there is a border, renders the border from the style context
// created by GetStyleContextFromCss(|css_selector|) into a single
// pixel and returns the color. Otherwise returns kInvalidColor.
// Renders the border from the style context created by
// GetStyleContextFromCss(|css_selector|) into a 24x24 bitmap and
// returns the average color.
SkColor GetBorderColor(const char* css_selector);
SkColor GetSelectedTextColor(const char* css_selector);
SkColor GetSelectedBgColor(const char* css_selector);
// Get the color of the GtkSeparator specified by |css_selector|.
SkColor GetSeparatorColor(const char* css_selector);
#endif
......
......@@ -16,24 +16,18 @@ mostly a list of about 80 colors (see //src/ui/native_theme/native_theme.h)
overridden by the theme. Chromium usually doesn't use GTK to render entire
widgets, but instead tries to determine colors from them.
There are three types of colors Chromium needs from widgets:
* Foreground color: determined by the CSS "color" property
* Background color: determined by the CSS "background-color" and "background-image" properties
* Border color: determined by the "border-color", "border-image",
"border-style", and "border-width" properties
Backgrounds and borders are complicated because in general they might have
multiple gradients or images. To get the color, Chromium uses GTK to render the
background or border into a single pixel and uses the resulting color for
theming. This mostly gives reasonable results, but in case theme authors do not
like the resulting color, they have the option to theme Chromium widgets
specially.
Chromium needs foreground, background and border colors from widgets. The
foreground color is simply taken from the CSS "color" property. Backgrounds and
borders are complicated because in general they might have multiple gradients or
images. To get the color, Chromium uses GTK to render the background or border
into a 24x24 bitmap and uses the average color for theming. This mostly gives
reasonable results, but in case theme authors do not like the resulting color,
they have the option to theme Chromium widgets specially.
## Note to GTK theme authors: How to theme Chromium widgets
Every widget Chromium uses will have a "chromium" style class added to it. For
example, a texfield selector might look like:
example, a textfield selector might look like:
```
.window.background.chromium .entry.chromium
......@@ -59,11 +53,6 @@ they might use:
For GTK3.20 or later, themes will as usual have to replace ".entry" with
"entry".
Additional requirements for border colors to be picked up:
* Must have a border-style that is not none.
* Must have a border-width that is nonzero.
The list of CSS selectors that Chromium uses to determine its colors is in
//src/chrome/browser/ui/libgtkui/native_theme_gtk3.cc.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment