Chromium Code Reviews| 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: |
|
Tom (Use chromium acct)
2017/01/25 02:44:40
erg: It's unclear if we want to do this for the ve
Elliot Glaysher
2017/01/25 18:42:09
I'm pretty sure that we want the vertical separato
Tom (Use chromium acct)
2017/01/25 22:25:44
Acknowledged.
| |
| 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 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 355 | 378 |
| 356 SkColor color = SkColorFromColorId(color_id); | 379 SkColor color = SkColorFromColorId(color_id); |
| 357 color_cache_[color_id] = color; | 380 color_cache_[color_id] = color; |
| 358 return color; | 381 return color; |
| 359 } | 382 } |
| 360 | 383 |
| 361 void NativeThemeGtk3::PaintMenuPopupBackground( | 384 void NativeThemeGtk3::PaintMenuPopupBackground( |
| 362 SkCanvas* canvas, | 385 SkCanvas* canvas, |
| 363 const gfx::Size& size, | 386 const gfx::Size& size, |
| 364 const MenuBackgroundExtraParams& menu_background) const { | 387 const MenuBackgroundExtraParams& menu_background) const { |
| 365 PaintWidget(canvas, gfx::Rect(size), GetStyleContextFromCss("GtkMenu#menu")); | 388 PaintWidget(canvas, gfx::Rect(size), GetStyleContextFromCss("GtkMenu#menu"), |
| 389 BG_RENDER_NORMAL, false); | |
| 366 } | 390 } |
| 367 | 391 |
| 368 void NativeThemeGtk3::PaintMenuItemBackground( | 392 void NativeThemeGtk3::PaintMenuItemBackground( |
| 369 SkCanvas* canvas, | 393 SkCanvas* canvas, |
| 370 State state, | 394 State state, |
| 371 const gfx::Rect& rect, | 395 const gfx::Rect& rect, |
| 372 const MenuItemExtraParams& menu_item) const { | 396 const MenuItemExtraParams& menu_item) const { |
| 373 auto context = GetStyleContextFromCss("GtkMenu#menu GtkMenuItem#menuitem"); | 397 auto context = GetStyleContextFromCss("GtkMenu#menu GtkMenuItem#menuitem"); |
| 374 gtk_style_context_set_state(context, StateToStateFlags(state)); | 398 gtk_style_context_set_state(context, StateToStateFlags(state)); |
| 375 PaintWidget(canvas, rect, context); | 399 PaintWidget(canvas, rect, context, BG_RENDER_NORMAL, true); |
| 400 } | |
| 401 | |
| 402 void NativeThemeGtk3::PaintMenuSeparator( | |
|
Tom (Use chromium acct)
2017/01/25 02:44:39
erg: Just so you know, this lets gtk override chro
| |
| 403 SkCanvas* canvas, | |
| 404 State state, | |
| 405 const gfx::Rect& rect, | |
| 406 const MenuSeparatorExtraParams& menu_separator) const { | |
| 407 auto separator_offset = [&](int separator_thickness) { | |
| 408 switch (menu_separator.type) { | |
| 409 case ui::LOWER_SEPARATOR: | |
| 410 return rect.height() - separator_thickness; | |
| 411 case ui::UPPER_SEPARATOR: | |
| 412 return 0; | |
| 413 default: | |
| 414 return rect.height() / 2; | |
| 415 } | |
| 416 }; | |
| 417 if (GtkVersionCheck(3, 20)) { | |
| 418 auto context = | |
| 419 GetStyleContextFromCss("GtkMenu#menu GtkSeparator#separator"); | |
| 420 GtkBorder margin, border, padding; | |
| 421 GtkStateFlags state = gtk_style_context_get_state(context); | |
| 422 gtk_style_context_get_margin(context, state, &margin); | |
| 423 gtk_style_context_get_border(context, state, &border); | |
| 424 gtk_style_context_get_padding(context, state, &padding); | |
| 425 int min_height = 0; | |
| 426 gtk_style_context_get(context, state, "min-height", &min_height, NULL); | |
| 427 int w = rect.width() - margin.left - margin.right; | |
| 428 int h = | |
| 429 min_height + padding.top + padding.bottom + border.top + border.bottom; | |
| 430 int x = margin.left; | |
| 431 int y = separator_offset(h); | |
| 432 PaintWidget(canvas, gfx::Rect(x, y, w, h), context, BG_RENDER_NORMAL, true); | |
| 433 } else { | |
| 434 auto context = | |
| 435 GetStyleContextFromCss("GtkMenu#menu GtkMenuItem#menuitem.separator"); | |
| 436 gboolean wide_separators = false; | |
| 437 gint separator_height = 0; | |
| 438 gtk_style_context_get_style(context, "wide-separators", &wide_separators, | |
| 439 "separator-height", &separator_height, nullptr); | |
| 440 // This code was adapted from gtk/gtkmenuitem.c. For some reason, | |
| 441 // padding is used as the margin. | |
| 442 GtkBorder padding; | |
| 443 gtk_style_context_get_padding(context, gtk_style_context_get_state(context), | |
| 444 &padding); | |
| 445 int w = rect.width() - padding.left - padding.right; | |
| 446 int x = rect.x() + padding.left; | |
| 447 int h = wide_separators ? separator_height : 1; | |
| 448 int y = rect.y() + separator_offset(h); | |
| 449 if (wide_separators) { | |
| 450 PaintWidget(canvas, gfx::Rect(x, y, w, h), context, BG_RENDER_NONE, true); | |
| 451 } else { | |
| 452 SkPaint paint; | |
| 453 paint.setColor(SkColorFromStyleContext(context)); | |
| 454 canvas->drawLine(x, y, x + w, y, paint); | |
| 455 } | |
| 456 } | |
| 376 } | 457 } |
| 377 | 458 |
| 378 void NativeThemeGtk3::PaintFrameTopArea( | 459 void NativeThemeGtk3::PaintFrameTopArea( |
| 379 SkCanvas* canvas, | 460 SkCanvas* canvas, |
| 380 State state, | 461 State state, |
| 381 const gfx::Rect& rect, | 462 const gfx::Rect& rect, |
| 382 const FrameTopAreaExtraParams& frame_top_area) const { | 463 const FrameTopAreaExtraParams& frame_top_area) const { |
| 383 auto context = GetStyleContextFromCss(frame_top_area.use_custom_frame | 464 auto context = GetStyleContextFromCss(frame_top_area.use_custom_frame |
| 384 ? "#headerbar.header-bar.titlebar" | 465 ? "#headerbar.header-bar.titlebar" |
| 385 : "GtkMenuBar#menubar"); | 466 : "GtkMenuBar#menubar"); |
| 386 RemoveBorders(context); | 467 RemoveBorders(context); |
| 387 gtk_style_context_set_state(context, | 468 gtk_style_context_set_state(context, frame_top_area.is_active |
| 388 frame_top_area.is_active | 469 ? GTK_STATE_FLAG_NORMAL |
| 389 ? GTK_STATE_FLAG_NORMAL | 470 : GTK_STATE_FLAG_BACKDROP); |
| 390 : GTK_STATE_FLAG_BACKDROP); | |
| 391 | 471 |
| 392 SkBitmap bitmap = GetWidgetBitmap(rect.size(), context); | 472 SkBitmap bitmap = |
| 473 GetWidgetBitmap(rect.size(), context, BG_RENDER_RECURSIVE, false); | |
| 393 | 474 |
| 394 if (frame_top_area.incognito) { | 475 if (frame_top_area.incognito) { |
| 395 bitmap = SkBitmapOperations::CreateHSLShiftedBitmap( | 476 bitmap = SkBitmapOperations::CreateHSLShiftedBitmap( |
| 396 bitmap, kDefaultTintFrameIncognito); | 477 bitmap, kDefaultTintFrameIncognito); |
| 397 } | 478 } |
| 398 | 479 |
| 399 canvas->drawBitmap(bitmap, rect.x(), rect.y()); | 480 canvas->drawBitmap(bitmap, rect.x(), rect.y()); |
| 400 } | 481 } |
| 401 | 482 |
| 402 } // namespace libgtkui | 483 } // namespace libgtkui |
| OLD | NEW |