Index: chrome/browser/ui/libgtk2ui/native_theme_gtk2.cc |
diff --git a/chrome/browser/ui/libgtk2ui/native_theme_gtk2.cc b/chrome/browser/ui/libgtk2ui/native_theme_gtk2.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6fbe3c268d68b0dbb57e45ae1ec56b0d88ef4163 |
--- /dev/null |
+++ b/chrome/browser/ui/libgtk2ui/native_theme_gtk2.cc |
@@ -0,0 +1,260 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/ui/libgtk2ui/native_theme_gtk2.h" |
+ |
+#include <gtk/gtk.h> |
+ |
+#include "chrome/browser/ui/libgtk2ui/skia_utils_gtk2.h" |
+#include "ui/gfx/color_utils.h" |
+#include "ui/gfx/path.h" |
+#include "ui/gfx/rect.h" |
+#include "ui/gfx/size.h" |
+#include "ui/native_theme/common_theme.h" |
+ |
+namespace { |
+ |
+// Theme colors returned by GetSystemColor(). |
+const SkColor kInvalidColorIdColor = SkColorSetRGB(255, 0, 128); |
+// Tree |
+const SkColor kTreeBackground = SK_ColorWHITE; |
+const SkColor kTreeTextColor = SK_ColorBLACK; |
+const SkColor kTreeSelectedTextColor = SK_ColorBLACK; |
+const SkColor kTreeSelectionBackgroundColor = SkColorSetRGB(0xEE, 0xEE, 0xEE); |
+const SkColor kTreeArrowColor = SkColorSetRGB(0x7A, 0x7A, 0x7A); |
+// Table |
+const SkColor kTableBackground = SK_ColorWHITE; |
+const SkColor kTableTextColor = SK_ColorBLACK; |
+const SkColor kTableSelectedTextColor = SK_ColorBLACK; |
+const SkColor kTableSelectionBackgroundColor = SkColorSetRGB(0xEE, 0xEE, 0xEE); |
+const SkColor kTableGroupingIndicatorColor = SkColorSetRGB(0xCC, 0xCC, 0xCC); |
+ |
+} // namespace |
+ |
+ |
+namespace libgtk2ui { |
+ |
+// static |
+NativeThemeGtk2* NativeThemeGtk2::instance() { |
+ CR_DEFINE_STATIC_LOCAL(NativeThemeGtk2, s_native_theme, ()); |
+ return &s_native_theme; |
+} |
+ |
+NativeThemeGtk2::NativeThemeGtk2() |
+ : fake_window_(NULL), |
+ fake_menu_item_(NULL) { |
+} |
+ |
+NativeThemeGtk2::~NativeThemeGtk2() { |
+ if (fake_window_) |
+ gtk_widget_destroy(fake_window_); |
+ fake_entry_.Destroy(); |
+ fake_label_.Destroy(); |
+ fake_button_.Destroy(); |
+ fake_menu_.Destroy(); |
+} |
+ |
+SkColor NativeThemeGtk2::GetSystemColor(ColorId color_id) const { |
+ switch (color_id) { |
+ // TODO(erg): Still need to fish the colors out of trees and tables. |
+ |
+ // Tree |
+ case kColorId_TreeBackground: |
+ return kTreeBackground; |
+ case kColorId_TreeText: |
+ return kTreeTextColor; |
+ case kColorId_TreeSelectedText: |
+ case kColorId_TreeSelectedTextUnfocused: |
+ return kTreeSelectedTextColor; |
+ case kColorId_TreeSelectionBackgroundFocused: |
+ case kColorId_TreeSelectionBackgroundUnfocused: |
+ return kTreeSelectionBackgroundColor; |
+ case kColorId_TreeArrow: |
+ return kTreeArrowColor; |
+ |
+ // Table |
+ case kColorId_TableBackground: |
+ return kTableBackground; |
+ case kColorId_TableText: |
+ return kTableTextColor; |
+ case kColorId_TableSelectedText: |
+ case kColorId_TableSelectedTextUnfocused: |
+ return kTableSelectedTextColor; |
+ case kColorId_TableSelectionBackgroundFocused: |
+ case kColorId_TableSelectionBackgroundUnfocused: |
+ return kTableSelectionBackgroundColor; |
+ case kColorId_TableGroupingIndicatorColor: |
+ return kTableGroupingIndicatorColor; |
+ |
+ default: |
+ // Fall through. |
+ break; |
+ } |
+ |
+ return GdkColorToSkColor(GetSystemGdkColor(color_id)); |
+} |
+ |
+void NativeThemeGtk2::PaintMenuPopupBackground( |
+ SkCanvas* canvas, |
+ const gfx::Size& size, |
+ const MenuBackgroundExtraParams& menu_background) const { |
+ if (menu_background.corner_radius > 0) { |
+ SkPaint paint; |
+ paint.setStyle(SkPaint::kFill_Style); |
+ paint.setFlags(SkPaint::kAntiAlias_Flag); |
+ paint.setColor(GetSystemColor(kColorId_MenuBackgroundColor)); |
+ |
+ gfx::Path path; |
+ SkRect rect = SkRect::MakeWH(SkIntToScalar(size.width()), |
+ SkIntToScalar(size.height())); |
+ SkScalar radius = SkIntToScalar(menu_background.corner_radius); |
+ SkScalar radii[8] = {radius, radius, radius, radius, |
+ radius, radius, radius, radius}; |
+ path.addRoundRect(rect, radii); |
+ |
+ canvas->drawPath(path, paint); |
+ } else { |
+ canvas->drawColor(GetSystemColor(kColorId_MenuBackgroundColor), |
+ SkXfermode::kSrc_Mode); |
+ } |
+} |
+ |
+GdkColor NativeThemeGtk2::GetSystemGdkColor(ColorId color_id) const { |
+ switch (color_id) { |
+ // Windows |
+ case kColorId_WindowBackground: |
+ return GetWindowStyle()->bg[GTK_STATE_NORMAL]; |
+ |
+ // Dialogs |
+ case kColorId_DialogBackground: |
+ return GetWindowStyle()->bg[GTK_STATE_NORMAL]; |
+ |
+ // FocusableBorder |
+ case kColorId_FocusedBorderColor: |
+ return GetEntryStyle()->bg[GTK_STATE_SELECTED]; |
+ case kColorId_UnfocusedBorderColor: |
+ return GetEntryStyle()->text_aa[GTK_STATE_NORMAL]; |
+ |
+ // MenuItem |
+ case kColorId_EnabledMenuItemForegroundColor: |
+ return GetMenuItemStyle()->text[GTK_STATE_NORMAL]; |
+ case kColorId_DisabledMenuItemForegroundColor: |
+ return GetMenuItemStyle()->text[GTK_STATE_INSENSITIVE]; |
+ // TODO(erg): We also need a FocusedMenuItemForegroundColor, since the |
+ // accessibility theme HighContrastInverse is unreadable without it. That |
+ // will require careful threading through existing menu code though. |
+ case kColorId_FocusedMenuItemBackgroundColor: |
+ return GetMenuItemStyle()->bg[GTK_STATE_SELECTED]; |
+ case kColorId_MenuBorderColor: |
+ case kColorId_MenuSeparatorColor: { |
+ return GetMenuItemStyle()->text[GTK_STATE_INSENSITIVE]; |
+ } |
+ case kColorId_MenuBackgroundColor: |
+ return GetMenuStyle()->bg[GTK_STATE_NORMAL]; |
+ |
+ // Label |
+ case kColorId_LabelEnabledColor: |
+ return GetLabelStyle()->text[GTK_STATE_NORMAL]; |
+ case kColorId_LabelDisabledColor: |
+ return GetLabelStyle()->text[GTK_STATE_INSENSITIVE]; |
+ case kColorId_LabelBackgroundColor: |
+ return GetWindowStyle()->bg[GTK_STATE_NORMAL]; |
+ |
+ // TextButton |
+ case kColorId_TextButtonBackgroundColor: |
+ return GetButtonStyle()->bg[GTK_STATE_NORMAL]; |
+ case kColorId_TextButtonEnabledColor: |
+ return GetButtonStyle()->text[GTK_STATE_NORMAL]; |
+ case kColorId_TextButtonDisabledColor: |
+ return GetButtonStyle()->text[GTK_STATE_INSENSITIVE]; |
+ case kColorId_TextButtonHighlightColor: |
+ return GetButtonStyle()->base[GTK_STATE_SELECTED]; |
+ case kColorId_TextButtonHoverColor: |
+ return GetButtonStyle()->text[GTK_STATE_NORMAL]; |
+ |
+ // Textfield |
+ case kColorId_TextfieldDefaultColor: |
+ return GetEntryStyle()->text[GTK_STATE_NORMAL]; |
+ case kColorId_TextfieldDefaultBackground: |
+ return GetEntryStyle()->base[GTK_STATE_NORMAL]; |
+ case kColorId_TextfieldReadOnlyColor: |
+ return GetEntryStyle()->text[GTK_STATE_INSENSITIVE]; |
+ case kColorId_TextfieldReadOnlyBackground: |
+ return GetEntryStyle()->base[GTK_STATE_INSENSITIVE]; |
+ case kColorId_TextfieldSelectionColor: |
+ return GetEntryStyle()->text[GTK_STATE_SELECTED]; |
+ case kColorId_TextfieldSelectionBackgroundFocused: |
+ return GetEntryStyle()->base[GTK_STATE_SELECTED]; |
+ case kColorId_TextfieldSelectionBackgroundUnfocused: |
+ return GetEntryStyle()->base[GTK_STATE_ACTIVE]; |
+ |
+ // Tree |
+ // Table |
+ |
+ default: |
+ // Fall through |
+ break; |
+ } |
+ |
+ return SkColorToGdkColor(kInvalidColorIdColor); |
+} |
+ |
+GtkWidget* NativeThemeGtk2::GetRealizedWindow() const { |
+ if (!fake_window_) { |
+ fake_window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
+ gtk_widget_realize(fake_window_); |
+ } |
+ |
+ return fake_window_; |
+} |
+ |
+GtkStyle* NativeThemeGtk2::GetWindowStyle() const { |
+ return gtk_rc_get_style(GetRealizedWindow()); |
+} |
+ |
+GtkStyle* NativeThemeGtk2::GetEntryStyle() const { |
+ if (!fake_entry_.get()) { |
+ fake_entry_.Own(gtk_entry_new()); |
+ |
+ // The fake entry needs to be in the window so it can be realized sow e can |
+ // use the computed parts of the style. |
+ gtk_container_add(GTK_CONTAINER(GetRealizedWindow()), fake_entry_.get()); |
+ gtk_widget_realize(fake_entry_.get()); |
+ } |
+ return gtk_rc_get_style(fake_entry_.get()); |
+} |
+ |
+GtkStyle* NativeThemeGtk2::GetLabelStyle() const { |
+ if (!fake_label_.get()) |
+ fake_label_.Own(gtk_label_new("")); |
+ |
+ return gtk_rc_get_style(fake_label_.get()); |
+} |
+ |
+GtkStyle* NativeThemeGtk2::GetButtonStyle() const { |
+ if (!fake_button_.get()) |
+ fake_button_.Own(gtk_button_new()); |
+ |
+ return gtk_rc_get_style(fake_button_.get()); |
+} |
+ |
+GtkStyle* NativeThemeGtk2::GetMenuStyle() const { |
+ if (!fake_menu_.get()) |
+ fake_menu_.Own(gtk_menu_new()); |
+ return gtk_rc_get_style(fake_menu_.get()); |
+} |
+ |
+GtkStyle* NativeThemeGtk2::GetMenuItemStyle() const { |
+ if (!fake_menu_item_) { |
+ if (!fake_menu_.get()) |
+ fake_menu_.Own(gtk_menu_new()); |
+ |
+ fake_menu_item_ = gtk_menu_item_new(); |
+ gtk_menu_shell_append(GTK_MENU_SHELL(fake_menu_.get()), fake_menu_item_); |
+ } |
+ |
+ return gtk_rc_get_style(fake_menu_item_); |
+} |
+ |
+} // namespace libgtk2ui |