Index: chrome/browser/ui/libgtkui/native_theme_gtk3.cc |
diff --git a/chrome/browser/ui/libgtkui/native_theme_gtk3.cc b/chrome/browser/ui/libgtkui/native_theme_gtk3.cc |
index 74399f075518c5051a9e7a6a0b420f459de3a8fa..a593b1427c87fdf4e181a09c9b010133bdf334da 100644 |
--- a/chrome/browser/ui/libgtkui/native_theme_gtk3.cc |
+++ b/chrome/browser/ui/libgtkui/native_theme_gtk3.cc |
@@ -20,8 +20,17 @@ namespace libgtkui { |
namespace { |
+enum BackgroundRenderMode { |
+ BG_RENDER_NORMAL, |
+ BG_RENDER_NONE, |
+ BG_RENDER_RECURSIVE, |
+}; |
+ |
SkBitmap GetWidgetBitmap(const gfx::Size& size, |
- GtkStyleContext* context) { |
+ GtkStyleContext* context, |
+ BackgroundRenderMode bg_mode, |
+ bool render_frame) { |
+ DCHECK(bg_mode != BG_RENDER_NONE || render_frame); |
SkBitmap bitmap; |
bitmap.allocN32Pixels(size.width(), size.height()); |
bitmap.eraseColor(0); |
@@ -32,8 +41,18 @@ SkBitmap GetWidgetBitmap(const gfx::Size& size, |
cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, size.width())); |
cairo_t* cr = cairo_create(surface); |
- RenderBackground(size, cr, context); |
- gtk_render_frame(context, cr, 0, 0, size.width(), size.height()); |
+ switch (bg_mode) { |
+ case BG_RENDER_NORMAL: |
+ gtk_render_background(context, cr, 0, 0, size.width(), size.height()); |
+ break; |
+ case BG_RENDER_RECURSIVE: |
+ RenderBackground(size, cr, context); |
+ break; |
+ case BG_RENDER_NONE: |
+ break; |
+ } |
+ if (render_frame) |
+ gtk_render_frame(context, cr, 0, 0, size.width(), size.height()); |
cairo_destroy(cr); |
cairo_surface_destroy(surface); |
return bitmap; |
@@ -41,8 +60,12 @@ SkBitmap GetWidgetBitmap(const gfx::Size& size, |
void PaintWidget(SkCanvas* canvas, |
const gfx::Rect& rect, |
- GtkStyleContext* context) { |
- canvas->drawBitmap(GetWidgetBitmap(rect.size(), context), rect.x(), rect.y()); |
+ GtkStyleContext* context, |
+ BackgroundRenderMode bg_mode, |
+ bool render_frame) { |
+ canvas->drawBitmap( |
+ GetWidgetBitmap(rect.size(), context, bg_mode, render_frame), rect.x(), |
+ rect.y()); |
} |
GtkStateFlags StateToStateFlags(NativeThemeGtk3::State state) { |
@@ -99,7 +122,7 @@ SkColor SkColorFromColorId(ui::NativeTheme::ColorId color_id) { |
return GetFgColor( |
"GtkMenu#menu GtkMenuItem#menuitem GtkLabel#label.accelerator"); |
case ui::NativeTheme::kColorId_MenuSeparatorColor: |
- // MenuButton borders are used the same way as menu separators in Chrome. |
+ // MenuButton borders are used as vertical menu separators in Chrome. |
case ui::NativeTheme::kColorId_EnabledMenuButtonBorderColor: |
case ui::NativeTheme::kColorId_FocusedMenuButtonBorderColor: |
case ui::NativeTheme::kColorId_HoverMenuButtonBorderColor: |
@@ -125,7 +148,7 @@ SkColor SkColorFromColorId(ui::NativeTheme::ColorId color_id) { |
case ui::NativeTheme::kColorId_LinkPressed: |
if (GtkVersionCheck(3, 12)) |
return GetFgColor("GtkLabel#label.link:link:hover:active"); |
- // fallthrough |
+ // fallthrough |
case ui::NativeTheme::kColorId_LinkEnabled: { |
if (GtkVersionCheck(3, 12)) { |
return GetFgColor("GtkLabel#label.link:link"); |
@@ -368,7 +391,8 @@ void NativeThemeGtk3::PaintMenuPopupBackground( |
SkCanvas* canvas, |
const gfx::Size& size, |
const MenuBackgroundExtraParams& menu_background) const { |
- PaintWidget(canvas, gfx::Rect(size), GetStyleContextFromCss("GtkMenu#menu")); |
+ PaintWidget(canvas, gfx::Rect(size), GetStyleContextFromCss("GtkMenu#menu"), |
+ BG_RENDER_RECURSIVE, false); |
} |
void NativeThemeGtk3::PaintMenuItemBackground( |
@@ -378,7 +402,64 @@ void NativeThemeGtk3::PaintMenuItemBackground( |
const MenuItemExtraParams& menu_item) const { |
auto context = GetStyleContextFromCss("GtkMenu#menu GtkMenuItem#menuitem"); |
gtk_style_context_set_state(context, StateToStateFlags(state)); |
- PaintWidget(canvas, rect, context); |
+ PaintWidget(canvas, rect, context, BG_RENDER_NORMAL, true); |
+} |
+ |
+void NativeThemeGtk3::PaintMenuSeparator( |
+ SkCanvas* canvas, |
+ State state, |
+ const gfx::Rect& rect, |
+ const MenuSeparatorExtraParams& menu_separator) const { |
+ auto separator_offset = [&](int separator_thickness) { |
+ switch (menu_separator.type) { |
+ case ui::LOWER_SEPARATOR: |
+ return rect.height() - separator_thickness; |
+ case ui::UPPER_SEPARATOR: |
+ return 0; |
+ default: |
+ return rect.height() / 2; |
+ } |
+ }; |
+ if (GtkVersionCheck(3, 20)) { |
+ auto context = |
+ GetStyleContextFromCss("GtkMenu#menu GtkSeparator#separator"); |
+ GtkBorder margin, border, padding; |
+ GtkStateFlags state = gtk_style_context_get_state(context); |
+ gtk_style_context_get_margin(context, state, &margin); |
+ gtk_style_context_get_border(context, state, &border); |
+ gtk_style_context_get_padding(context, state, &padding); |
+ int min_height = 0; |
+ gtk_style_context_get(context, state, "min-height", &min_height, NULL); |
+ int w = rect.width() - margin.left - margin.right; |
+ int h = |
+ min_height + padding.top + padding.bottom + border.top + border.bottom; |
+ int x = margin.left; |
+ int y = separator_offset(h); |
+ PaintWidget(canvas, gfx::Rect(x, y, w, h), context, BG_RENDER_NORMAL, true); |
+ } else { |
+ auto context = |
+ GetStyleContextFromCss("GtkMenu#menu GtkMenuItem#menuitem.separator"); |
+ gboolean wide_separators = false; |
+ gint separator_height = 0; |
+ gtk_style_context_get_style(context, "wide-separators", &wide_separators, |
+ "separator-height", &separator_height, nullptr); |
+ // This code was adapted from gtk/gtkmenuitem.c. For some reason, |
+ // padding is used as the margin. |
+ GtkBorder padding; |
+ gtk_style_context_get_padding(context, gtk_style_context_get_state(context), |
+ &padding); |
+ int w = rect.width() - padding.left - padding.right; |
+ int x = rect.x() + padding.left; |
+ int h = wide_separators ? separator_height : 1; |
+ int y = rect.y() + separator_offset(h); |
+ if (wide_separators) { |
+ PaintWidget(canvas, gfx::Rect(x, y, w, h), context, BG_RENDER_NONE, true); |
+ } else { |
+ SkPaint paint; |
+ paint.setColor(SkColorFromStyleContext(context)); |
+ canvas->drawLine(x, y, x + w, y, paint); |
+ } |
+ } |
} |
void NativeThemeGtk3::PaintFrameTopArea( |
@@ -390,12 +471,12 @@ void NativeThemeGtk3::PaintFrameTopArea( |
? "#headerbar.header-bar.titlebar" |
: "GtkMenuBar#menubar"); |
RemoveBorders(context); |
- gtk_style_context_set_state(context, |
- frame_top_area.is_active |
- ? GTK_STATE_FLAG_NORMAL |
- : GTK_STATE_FLAG_BACKDROP); |
+ gtk_style_context_set_state(context, frame_top_area.is_active |
+ ? GTK_STATE_FLAG_NORMAL |
+ : GTK_STATE_FLAG_BACKDROP); |
- SkBitmap bitmap = GetWidgetBitmap(rect.size(), context); |
+ SkBitmap bitmap = |
+ GetWidgetBitmap(rect.size(), context, BG_RENDER_RECURSIVE, false); |
if (frame_top_area.incognito) { |
bitmap = SkBitmapOperations::CreateHSLShiftedBitmap( |