| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/libgtkui/native_theme_gtk3.h" | 5 #include "chrome/browser/ui/libgtkui/native_theme_gtk3.h" |
| 6 | 6 |
| 7 #include <gtk/gtk.h> | 7 #include <gtk/gtk.h> |
| 8 | 8 |
| 9 #include "chrome/browser/ui/libgtkui/chrome_gtk_frame.h" | 9 #include "chrome/browser/ui/libgtkui/chrome_gtk_frame.h" |
| 10 #include "chrome/browser/ui/libgtkui/chrome_gtk_menu_subclasses.h" | 10 #include "chrome/browser/ui/libgtkui/chrome_gtk_menu_subclasses.h" |
| 11 #include "chrome/browser/ui/libgtkui/gtk_util.h" | 11 #include "chrome/browser/ui/libgtkui/gtk_util.h" |
| 12 #include "chrome/browser/ui/libgtkui/skia_utils_gtk.h" | 12 #include "chrome/browser/ui/libgtkui/skia_utils_gtk.h" |
| 13 #include "ui/gfx/color_palette.h" | 13 #include "ui/gfx/color_palette.h" |
| 14 #include "ui/gfx/color_utils.h" | 14 #include "ui/gfx/color_utils.h" |
| 15 #include "ui/gfx/geometry/rect.h" | 15 #include "ui/gfx/geometry/rect.h" |
| 16 #include "ui/gfx/skbitmap_operations.h" | 16 #include "ui/gfx/skbitmap_operations.h" |
| 17 #include "ui/native_theme/native_theme_dark_aura.h" | 17 #include "ui/native_theme/native_theme_dark_aura.h" |
| 18 | 18 |
| 19 namespace libgtkui { | 19 namespace libgtkui { |
| 20 | 20 |
| 21 namespace { | 21 namespace { |
| 22 | 22 |
| 23 enum BackgroundRenderMode { |
| 24 BG_RENDER_NORMAL, |
| 25 BG_RENDER_NONE, |
| 26 BG_RENDER_RECURSIVE, |
| 27 }; |
| 28 |
| 23 SkBitmap GetWidgetBitmap(const gfx::Size& size, | 29 SkBitmap GetWidgetBitmap(const gfx::Size& size, |
| 24 GtkStyleContext* context) { | 30 GtkStyleContext* context, |
| 31 BackgroundRenderMode bg_mode, |
| 32 bool render_frame) { |
| 33 DCHECK(bg_mode != BG_RENDER_NONE || render_frame); |
| 25 SkBitmap bitmap; | 34 SkBitmap bitmap; |
| 26 bitmap.allocN32Pixels(size.width(), size.height()); | 35 bitmap.allocN32Pixels(size.width(), size.height()); |
| 27 bitmap.eraseColor(0); | 36 bitmap.eraseColor(0); |
| 28 | 37 |
| 29 cairo_surface_t* surface = cairo_image_surface_create_for_data( | 38 cairo_surface_t* surface = cairo_image_surface_create_for_data( |
| 30 static_cast<unsigned char*>(bitmap.getAddr(0, 0)), CAIRO_FORMAT_ARGB32, | 39 static_cast<unsigned char*>(bitmap.getAddr(0, 0)), CAIRO_FORMAT_ARGB32, |
| 31 size.width(), size.height(), | 40 size.width(), size.height(), |
| 32 cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, size.width())); | 41 cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, size.width())); |
| 33 cairo_t* cr = cairo_create(surface); | 42 cairo_t* cr = cairo_create(surface); |
| 34 | 43 |
| 35 RenderBackground(size, cr, context); | 44 switch (bg_mode) { |
| 36 gtk_render_frame(context, cr, 0, 0, size.width(), size.height()); | 45 case BG_RENDER_NORMAL: |
| 46 gtk_render_background(context, cr, 0, 0, size.width(), size.height()); |
| 47 break; |
| 48 case BG_RENDER_RECURSIVE: |
| 49 RenderBackground(size, cr, context); |
| 50 break; |
| 51 case BG_RENDER_NONE: |
| 52 break; |
| 53 } |
| 54 if (render_frame) |
| 55 gtk_render_frame(context, cr, 0, 0, size.width(), size.height()); |
| 37 cairo_destroy(cr); | 56 cairo_destroy(cr); |
| 38 cairo_surface_destroy(surface); | 57 cairo_surface_destroy(surface); |
| 39 return bitmap; | 58 return bitmap; |
| 40 } | 59 } |
| 41 | 60 |
| 42 void PaintWidget(SkCanvas* canvas, | 61 void PaintWidget(SkCanvas* canvas, |
| 43 const gfx::Rect& rect, | 62 const gfx::Rect& rect, |
| 44 GtkStyleContext* context) { | 63 GtkStyleContext* context, |
| 45 canvas->drawBitmap(GetWidgetBitmap(rect.size(), context), rect.x(), rect.y()); | 64 BackgroundRenderMode bg_mode, |
| 65 bool render_frame) { |
| 66 canvas->drawBitmap( |
| 67 GetWidgetBitmap(rect.size(), context, bg_mode, render_frame), rect.x(), |
| 68 rect.y()); |
| 46 } | 69 } |
| 47 | 70 |
| 48 GtkStateFlags StateToStateFlags(NativeThemeGtk3::State state) { | 71 GtkStateFlags StateToStateFlags(NativeThemeGtk3::State state) { |
| 49 switch (state) { | 72 switch (state) { |
| 50 case NativeThemeGtk3::kDisabled: | 73 case NativeThemeGtk3::kDisabled: |
| 51 return GTK_STATE_FLAG_INSENSITIVE; | 74 return GTK_STATE_FLAG_INSENSITIVE; |
| 52 case NativeThemeGtk3::kHovered: | 75 case NativeThemeGtk3::kHovered: |
| 53 return GTK_STATE_FLAG_PRELIGHT; | 76 return GTK_STATE_FLAG_PRELIGHT; |
| 54 case NativeThemeGtk3::kNormal: | 77 case NativeThemeGtk3::kNormal: |
| 55 return GTK_STATE_FLAG_NORMAL; | 78 return GTK_STATE_FLAG_NORMAL; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 case ui::NativeTheme::kColorId_SelectedMenuItemForegroundColor: | 115 case ui::NativeTheme::kColorId_SelectedMenuItemForegroundColor: |
| 93 return GetFgColor( | 116 return GetFgColor( |
| 94 "GtkMenu#menu GtkMenuItem#menuitem:selected GtkLabel#label"); | 117 "GtkMenu#menu GtkMenuItem#menuitem:selected GtkLabel#label"); |
| 95 case ui::NativeTheme::kColorId_DisabledMenuItemForegroundColor: | 118 case ui::NativeTheme::kColorId_DisabledMenuItemForegroundColor: |
| 96 return GetFgColor( | 119 return GetFgColor( |
| 97 "GtkMenu#menu GtkMenuItem#menuitem:disabled GtkLabel#label"); | 120 "GtkMenu#menu GtkMenuItem#menuitem:disabled GtkLabel#label"); |
| 98 case ui::NativeTheme::kColorId_MenuItemSubtitleColor: | 121 case ui::NativeTheme::kColorId_MenuItemSubtitleColor: |
| 99 return GetFgColor( | 122 return GetFgColor( |
| 100 "GtkMenu#menu GtkMenuItem#menuitem GtkLabel#label.accelerator"); | 123 "GtkMenu#menu GtkMenuItem#menuitem GtkLabel#label.accelerator"); |
| 101 case ui::NativeTheme::kColorId_MenuSeparatorColor: | 124 case ui::NativeTheme::kColorId_MenuSeparatorColor: |
| 102 // MenuButton borders are used the same way as menu separators in Chrome. | 125 // MenuButton borders are used as vertical menu separators in Chrome. |
| 103 case ui::NativeTheme::kColorId_EnabledMenuButtonBorderColor: | 126 case ui::NativeTheme::kColorId_EnabledMenuButtonBorderColor: |
| 104 case ui::NativeTheme::kColorId_FocusedMenuButtonBorderColor: | 127 case ui::NativeTheme::kColorId_FocusedMenuButtonBorderColor: |
| 105 case ui::NativeTheme::kColorId_HoverMenuButtonBorderColor: | 128 case ui::NativeTheme::kColorId_HoverMenuButtonBorderColor: |
| 106 if (GtkVersionCheck(3, 20)) | 129 if (GtkVersionCheck(3, 20)) |
| 107 return GetBgColor("GtkMenu#menu GtkSeparator#separator"); | 130 return GetBgColor("GtkMenu#menu GtkSeparator#separator"); |
| 108 else | 131 else |
| 109 return GetFgColor("GtkMenu#menu GtkMenuItem#menuitem.separator"); | 132 return GetFgColor("GtkMenu#menu GtkMenuItem#menuitem.separator"); |
| 110 | 133 |
| 111 // Label | 134 // Label |
| 112 case ui::NativeTheme::kColorId_LabelEnabledColor: | 135 case ui::NativeTheme::kColorId_LabelEnabledColor: |
| 113 return GetFgColor("GtkLabel#label"); | 136 return GetFgColor("GtkLabel#label"); |
| 114 case ui::NativeTheme::kColorId_LabelDisabledColor: | 137 case ui::NativeTheme::kColorId_LabelDisabledColor: |
| 115 return GetFgColor("GtkLabel#label:disabled"); | 138 return GetFgColor("GtkLabel#label:disabled"); |
| 116 case ui::NativeTheme::kColorId_LabelTextSelectionColor: | 139 case ui::NativeTheme::kColorId_LabelTextSelectionColor: |
| 117 return GetFgColor("GtkLabel#label #selection:selected"); | 140 return GetFgColor("GtkLabel#label #selection:selected"); |
| 118 case ui::NativeTheme::kColorId_LabelTextSelectionBackgroundFocused: | 141 case ui::NativeTheme::kColorId_LabelTextSelectionBackgroundFocused: |
| 119 return GetBgColor("GtkLabel#label #selection:selected"); | 142 return GetBgColor("GtkLabel#label #selection:selected"); |
| 120 | 143 |
| 121 // Link | 144 // Link |
| 122 case ui::NativeTheme::kColorId_LinkDisabled: | 145 case ui::NativeTheme::kColorId_LinkDisabled: |
| 123 return SkColorSetA( | 146 return SkColorSetA( |
| 124 SkColorFromColorId(ui::NativeTheme::kColorId_LinkEnabled), 0xBB); | 147 SkColorFromColorId(ui::NativeTheme::kColorId_LinkEnabled), 0xBB); |
| 125 case ui::NativeTheme::kColorId_LinkPressed: | 148 case ui::NativeTheme::kColorId_LinkPressed: |
| 126 if (GtkVersionCheck(3, 12)) | 149 if (GtkVersionCheck(3, 12)) |
| 127 return GetFgColor("GtkLabel#label.link:link:hover:active"); | 150 return GetFgColor("GtkLabel#label.link:link:hover:active"); |
| 128 // fallthrough | 151 // fallthrough |
| 129 case ui::NativeTheme::kColorId_LinkEnabled: { | 152 case ui::NativeTheme::kColorId_LinkEnabled: { |
| 130 if (GtkVersionCheck(3, 12)) { | 153 if (GtkVersionCheck(3, 12)) { |
| 131 return GetFgColor("GtkLabel#label.link:link"); | 154 return GetFgColor("GtkLabel#label.link:link"); |
| 132 } | 155 } |
| 133 auto link_context = GetStyleContextFromCss("GtkLabel#label.view"); | 156 auto link_context = GetStyleContextFromCss("GtkLabel#label.view"); |
| 134 GdkColor* color; | 157 GdkColor* color; |
| 135 gtk_style_context_get_style(link_context, "link-color", &color, nullptr); | 158 gtk_style_context_get_style(link_context, "link-color", &color, nullptr); |
| 136 if (color) { | 159 if (color) { |
| 137 SkColor ret_color = SkColorSetRGB(color->red / 255, color->green / 255, | 160 SkColor ret_color = SkColorSetRGB(color->red / 255, color->green / 255, |
| 138 color->blue / 255); | 161 color->blue / 255); |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 | 384 |
| 362 SkColor color = SkColorFromColorId(color_id); | 385 SkColor color = SkColorFromColorId(color_id); |
| 363 color_cache_[color_id] = color; | 386 color_cache_[color_id] = color; |
| 364 return color; | 387 return color; |
| 365 } | 388 } |
| 366 | 389 |
| 367 void NativeThemeGtk3::PaintMenuPopupBackground( | 390 void NativeThemeGtk3::PaintMenuPopupBackground( |
| 368 SkCanvas* canvas, | 391 SkCanvas* canvas, |
| 369 const gfx::Size& size, | 392 const gfx::Size& size, |
| 370 const MenuBackgroundExtraParams& menu_background) const { | 393 const MenuBackgroundExtraParams& menu_background) const { |
| 371 PaintWidget(canvas, gfx::Rect(size), GetStyleContextFromCss("GtkMenu#menu")); | 394 PaintWidget(canvas, gfx::Rect(size), GetStyleContextFromCss("GtkMenu#menu"), |
| 395 BG_RENDER_RECURSIVE, false); |
| 372 } | 396 } |
| 373 | 397 |
| 374 void NativeThemeGtk3::PaintMenuItemBackground( | 398 void NativeThemeGtk3::PaintMenuItemBackground( |
| 375 SkCanvas* canvas, | 399 SkCanvas* canvas, |
| 376 State state, | 400 State state, |
| 377 const gfx::Rect& rect, | 401 const gfx::Rect& rect, |
| 378 const MenuItemExtraParams& menu_item) const { | 402 const MenuItemExtraParams& menu_item) const { |
| 379 auto context = GetStyleContextFromCss("GtkMenu#menu GtkMenuItem#menuitem"); | 403 auto context = GetStyleContextFromCss("GtkMenu#menu GtkMenuItem#menuitem"); |
| 380 gtk_style_context_set_state(context, StateToStateFlags(state)); | 404 gtk_style_context_set_state(context, StateToStateFlags(state)); |
| 381 PaintWidget(canvas, rect, context); | 405 PaintWidget(canvas, rect, context, BG_RENDER_NORMAL, true); |
| 406 } |
| 407 |
| 408 void NativeThemeGtk3::PaintMenuSeparator( |
| 409 SkCanvas* canvas, |
| 410 State state, |
| 411 const gfx::Rect& rect, |
| 412 const MenuSeparatorExtraParams& menu_separator) const { |
| 413 auto separator_offset = [&](int separator_thickness) { |
| 414 switch (menu_separator.type) { |
| 415 case ui::LOWER_SEPARATOR: |
| 416 return rect.height() - separator_thickness; |
| 417 case ui::UPPER_SEPARATOR: |
| 418 return 0; |
| 419 default: |
| 420 return rect.height() / 2; |
| 421 } |
| 422 }; |
| 423 if (GtkVersionCheck(3, 20)) { |
| 424 auto context = |
| 425 GetStyleContextFromCss("GtkMenu#menu GtkSeparator#separator"); |
| 426 GtkBorder margin, border, padding; |
| 427 GtkStateFlags state = gtk_style_context_get_state(context); |
| 428 gtk_style_context_get_margin(context, state, &margin); |
| 429 gtk_style_context_get_border(context, state, &border); |
| 430 gtk_style_context_get_padding(context, state, &padding); |
| 431 int min_height = 0; |
| 432 gtk_style_context_get(context, state, "min-height", &min_height, NULL); |
| 433 int w = rect.width() - margin.left - margin.right; |
| 434 int h = |
| 435 min_height + padding.top + padding.bottom + border.top + border.bottom; |
| 436 int x = margin.left; |
| 437 int y = separator_offset(h); |
| 438 PaintWidget(canvas, gfx::Rect(x, y, w, h), context, BG_RENDER_NORMAL, true); |
| 439 } else { |
| 440 auto context = |
| 441 GetStyleContextFromCss("GtkMenu#menu GtkMenuItem#menuitem.separator"); |
| 442 gboolean wide_separators = false; |
| 443 gint separator_height = 0; |
| 444 gtk_style_context_get_style(context, "wide-separators", &wide_separators, |
| 445 "separator-height", &separator_height, nullptr); |
| 446 // This code was adapted from gtk/gtkmenuitem.c. For some reason, |
| 447 // padding is used as the margin. |
| 448 GtkBorder padding; |
| 449 gtk_style_context_get_padding(context, gtk_style_context_get_state(context), |
| 450 &padding); |
| 451 int w = rect.width() - padding.left - padding.right; |
| 452 int x = rect.x() + padding.left; |
| 453 int h = wide_separators ? separator_height : 1; |
| 454 int y = rect.y() + separator_offset(h); |
| 455 if (wide_separators) { |
| 456 PaintWidget(canvas, gfx::Rect(x, y, w, h), context, BG_RENDER_NONE, true); |
| 457 } else { |
| 458 SkPaint paint; |
| 459 paint.setColor(SkColorFromStyleContext(context)); |
| 460 canvas->drawLine(x, y, x + w, y, paint); |
| 461 } |
| 462 } |
| 382 } | 463 } |
| 383 | 464 |
| 384 void NativeThemeGtk3::PaintFrameTopArea( | 465 void NativeThemeGtk3::PaintFrameTopArea( |
| 385 SkCanvas* canvas, | 466 SkCanvas* canvas, |
| 386 State state, | 467 State state, |
| 387 const gfx::Rect& rect, | 468 const gfx::Rect& rect, |
| 388 const FrameTopAreaExtraParams& frame_top_area) const { | 469 const FrameTopAreaExtraParams& frame_top_area) const { |
| 389 auto context = GetStyleContextFromCss(frame_top_area.use_custom_frame | 470 auto context = GetStyleContextFromCss(frame_top_area.use_custom_frame |
| 390 ? "#headerbar.header-bar.titlebar" | 471 ? "#headerbar.header-bar.titlebar" |
| 391 : "GtkMenuBar#menubar"); | 472 : "GtkMenuBar#menubar"); |
| 392 RemoveBorders(context); | 473 RemoveBorders(context); |
| 393 gtk_style_context_set_state(context, | 474 gtk_style_context_set_state(context, frame_top_area.is_active |
| 394 frame_top_area.is_active | 475 ? GTK_STATE_FLAG_NORMAL |
| 395 ? GTK_STATE_FLAG_NORMAL | 476 : GTK_STATE_FLAG_BACKDROP); |
| 396 : GTK_STATE_FLAG_BACKDROP); | |
| 397 | 477 |
| 398 SkBitmap bitmap = GetWidgetBitmap(rect.size(), context); | 478 SkBitmap bitmap = |
| 479 GetWidgetBitmap(rect.size(), context, BG_RENDER_RECURSIVE, false); |
| 399 | 480 |
| 400 if (frame_top_area.incognito) { | 481 if (frame_top_area.incognito) { |
| 401 bitmap = SkBitmapOperations::CreateHSLShiftedBitmap( | 482 bitmap = SkBitmapOperations::CreateHSLShiftedBitmap( |
| 402 bitmap, kDefaultTintFrameIncognito); | 483 bitmap, kDefaultTintFrameIncognito); |
| 403 } | 484 } |
| 404 | 485 |
| 405 canvas->drawBitmap(bitmap, rect.x(), rect.y()); | 486 canvas->drawBitmap(bitmap, rect.x(), rect.y()); |
| 406 } | 487 } |
| 407 | 488 |
| 408 } // namespace libgtkui | 489 } // namespace libgtkui |
| OLD | NEW |