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 |