summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorerg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-03 00:42:29 +0000
committererg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-03 00:42:29 +0000
commita5166af69628552e4bcf746a38f3710cc895eac3 (patch)
tree0d6e0ab20143724111855ac501aad3fd469e6b8d
parent08f91cc8431cc6dea19e3c3ff3a229c71a7fc71f (diff)
downloadchromium_src-a5166af69628552e4bcf746a38f3710cc895eac3.zip
chromium_src-a5166af69628552e4bcf746a38f3710cc895eac3.tar.gz
chromium_src-a5166af69628552e4bcf746a38f3710cc895eac3.tar.bz2
GTK: Initial implementation of using GTK themes, partially based on evan's CL 118358.
A lot of stuff works: - Colors are picked out of the GTK theme. - Buttons use the current GTK button theme. - We use the user's icon theme. A lot of stuff doesn't: - We could do a better job of picking colors for the skylines. - The omnibox hasn't been touched. - UI that's not part of the toolbar hasn't been touched. - We currently fail on themes like HighContrastInverse. TEST=Under Options>Personal Stuff, click GTK Theme. Colors and widgets should be rendered with the current GTK theme stuff. TEST=With chrome open and in GTK Theme mode, change your GTK theme or icon theme. chrome should pick up on the change immediately and reimport the colors and images. http://crbug.com/13967 Review URL: http://codereview.chromium.org/150176 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@19868 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/app/chrome_dll_main.cc3
-rw-r--r--chrome/browser/browser_theme_provider.cc146
-rw-r--r--chrome/browser/browser_theme_provider.h119
-rw-r--r--chrome/browser/gtk/back_forward_button_gtk.cc10
-rw-r--r--chrome/browser/gtk/back_forward_button_gtk.h9
-rw-r--r--chrome/browser/gtk/bookmark_bar_gtk.cc34
-rw-r--r--chrome/browser/gtk/bookmark_bar_gtk.h3
-rw-r--r--chrome/browser/gtk/browser_titlebar.cc2
-rw-r--r--chrome/browser/gtk/browser_toolbar_gtk.cc30
-rw-r--r--chrome/browser/gtk/browser_toolbar_gtk.h6
-rw-r--r--chrome/browser/gtk/browser_window_gtk.cc10
-rw-r--r--chrome/browser/gtk/custom_button.cc57
-rw-r--r--chrome/browser/gtk/custom_button.h26
-rw-r--r--chrome/browser/gtk/find_bar_gtk.cc6
-rw-r--r--chrome/browser/gtk/gtk_chrome_button.cc54
-rw-r--r--chrome/browser/gtk/gtk_chrome_button.h4
-rw-r--r--chrome/browser/gtk/gtk_theme_provider.cc154
-rw-r--r--chrome/browser/gtk/gtk_theme_provider.h61
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.cc16
-rw-r--r--chrome/browser/gtk/options/content_page_gtk.cc14
-rw-r--r--chrome/browser/gtk/options/content_page_gtk.h4
-rwxr-xr-xchrome/browser/gtk/tabs/tab_renderer_gtk.cc2
-rwxr-xr-xchrome/browser/gtk/tabs/tab_strip_gtk.cc2
-rw-r--r--chrome/browser/profile.cc20
-rw-r--r--chrome/browser/profile.h4
-rw-r--r--chrome/chrome.gyp2
-rw-r--r--chrome/common/pref_names.cc4
-rw-r--r--chrome/common/pref_names.h5
-rw-r--r--chrome/test/testing_profile.h1
29 files changed, 665 insertions, 143 deletions
diff --git a/chrome/app/chrome_dll_main.cc b/chrome/app/chrome_dll_main.cc
index de4d822..213a40f 100644
--- a/chrome/app/chrome_dll_main.cc
+++ b/chrome/app/chrome_dll_main.cc
@@ -176,6 +176,9 @@ static void GLibLogHandler(const gchar* log_domain,
!GTK_CHECK_VERSION(2, 16, 1)) {
// http://crbug.com/11133
LOG(ERROR) << "Bug 11133";
+ } else if (strstr(message, "Theme file for default has no") ||
+ strstr(message, "Theme directory")) {
+ LOG(ERROR) << "GTK theme error: " << message;
} else {
#ifdef NDEBUG
LOG(ERROR) << log_domain << ": " << message;
diff --git a/chrome/browser/browser_theme_provider.cc b/chrome/browser/browser_theme_provider.cc
index 314b726..104007f 100644
--- a/chrome/browser/browser_theme_provider.cc
+++ b/chrome/browser/browser_theme_provider.cc
@@ -29,71 +29,78 @@
#include "app/win_util.h"
#endif
+
+namespace themes {
+
// Strings used by themes to identify colors for different parts of our UI.
-static const char* kColorFrame = "frame";
-static const char* kColorFrameInactive = "frame_inactive";
-static const char* kColorFrameIncognito = "frame_incognito";
-static const char* kColorFrameIncognitoInactive =
- "frame_incognito_inactive";
-static const char* kColorToolbar = "toolbar";
-static const char* kColorTabText = "tab_text";
-static const char* kColorBackgroundTabText = "background_tab_text";
-static const char* kColorBookmarkText = "bookmark_text";
-static const char* kColorNTPBackground = "ntp_background";
-static const char* kColorNTPText = "ntp_text";
-static const char* kColorNTPLink = "ntp_link";
-static const char* kColorNTPSection = "ntp_section";
-static const char* kColorNTPSectionText = "ntp_section_text";
-static const char* kColorNTPSectionLink = "ntp_section_link";
-static const char* kColorControlBackground = "control_background";
-static const char* kColorButtonBackground = "button_background";
+const char* kColorFrame = "frame";
+const char* kColorFrameInactive = "frame_inactive";
+const char* kColorFrameIncognito = "frame_incognito";
+const char* kColorFrameIncognitoInactive = "frame_incognito_inactive";
+const char* kColorToolbar = "toolbar";
+const char* kColorTabText = "tab_text";
+const char* kColorBackgroundTabText = "background_tab_text";
+const char* kColorBookmarkText = "bookmark_text";
+const char* kColorNTPBackground = "ntp_background";
+const char* kColorNTPText = "ntp_text";
+const char* kColorNTPLink = "ntp_link";
+const char* kColorNTPSection = "ntp_section";
+const char* kColorNTPSectionText = "ntp_section_text";
+const char* kColorNTPSectionLink = "ntp_section_link";
+const char* kColorControlBackground = "control_background";
+const char* kColorButtonBackground = "button_background";
// Strings used by themes to identify tints to apply to different parts of
// our UI. The frame tints apply to the frame color and produce the
// COLOR_FRAME* colors.
-static const char* kTintButtons = "buttons";
-static const char* kTintFrame = "frame";
-static const char* kTintFrameInactive = "frame_inactive";
-static const char* kTintFrameIncognito = "frame_incognito";
-static const char* kTintFrameIncognitoInactive =
- "frame_incognito_inactive";
-static const char* kTintBackgroundTab = "background_tab";
+const char* kTintButtons = "buttons";
+const char* kTintFrame = "frame";
+const char* kTintFrameInactive = "frame_inactive";
+const char* kTintFrameIncognito = "frame_incognito";
+const char* kTintFrameIncognitoInactive = "frame_incognito_inactive";
+const char* kTintBackgroundTab = "background_tab";
// Strings used by themes to identify miscellaneous numerical properties.
-static const char* kDisplayPropertyNTPAlignment = "ntp_background_alignment";
+const char* kDisplayPropertyNTPAlignment = "ntp_background_alignment";
// Strings used in alignment properties.
-static const char* kAlignmentTop = "top";
-static const char* kAlignmentBottom = "bottom";
-static const char* kAlignmentLeft = "left";
-static const char* kAlignmentRight = "right";
+const char* kAlignmentTop = "top";
+const char* kAlignmentBottom = "bottom";
+const char* kAlignmentLeft = "left";
+const char* kAlignmentRight = "right";
// Default colors.
-static const SkColor kDefaultColorFrame = SkColorSetRGB(77, 139, 217);
-static const SkColor kDefaultColorFrameInactive = SkColorSetRGB(152, 188, 233);
-static const SkColor kDefaultColorFrameIncognito = SkColorSetRGB(83, 106, 139);
-static const SkColor kDefaultColorFrameIncognitoInactive =
+const SkColor kDefaultColorFrame = SkColorSetRGB(77, 139, 217);
+const SkColor kDefaultColorFrameInactive = SkColorSetRGB(152, 188, 233);
+const SkColor kDefaultColorFrameIncognito = SkColorSetRGB(83, 106, 139);
+const SkColor kDefaultColorFrameIncognitoInactive =
SkColorSetRGB(126, 139, 156);
-static const SkColor kDefaultColorToolbar = SkColorSetRGB(210, 225, 246);
-static const SkColor kDefaultColorTabText = SkColorSetRGB(0, 0, 0);
-static const SkColor kDefaultColorBackgroundTabText = SkColorSetRGB(64, 64, 64);
-static const SkColor kDefaultColorBookmarkText = SkColorSetRGB(64, 64, 64);
-static const SkColor kDefaultColorNTPBackground = SkColorSetRGB(255, 255, 255);
-static const SkColor kDefaultColorNTPText = SkColorSetRGB(0, 0, 0);
-static const SkColor kDefaultColorNTPLink = SkColorSetRGB(0, 0, 204);
-static const SkColor kDefaultColorNTPSection = SkColorSetRGB(225, 236, 254);
-static const SkColor kDefaultColorNTPSectionText = SkColorSetRGB(0, 0, 0);
-static const SkColor kDefaultColorNTPSectionLink = SkColorSetRGB(0, 0, 204);
-static const SkColor kDefaultColorControlBackground = NULL;
-static const SkColor kDefaultColorButtonBackground = NULL;
+const SkColor kDefaultColorToolbar = SkColorSetRGB(210, 225, 246);
+const SkColor kDefaultColorTabText = SkColorSetRGB(0, 0, 0);
+const SkColor kDefaultColorBackgroundTabText = SkColorSetRGB(64, 64, 64);
+const SkColor kDefaultColorBookmarkText = SkColorSetRGB(64, 64, 64);
+const SkColor kDefaultColorNTPBackground = SkColorSetRGB(255, 255, 255);
+const SkColor kDefaultColorNTPText = SkColorSetRGB(0, 0, 0);
+const SkColor kDefaultColorNTPLink = SkColorSetRGB(0, 0, 204);
+const SkColor kDefaultColorNTPSection = SkColorSetRGB(225, 236, 254);
+const SkColor kDefaultColorNTPSectionText = SkColorSetRGB(0, 0, 0);
+const SkColor kDefaultColorNTPSectionLink = SkColorSetRGB(0, 0, 204);
+const SkColor kDefaultColorControlBackground = NULL;
+const SkColor kDefaultColorButtonBackground = NULL;
// Default tints.
-static const skia::HSL kDefaultTintButtons = { -1, -1, -1 };
-static const skia::HSL kDefaultTintFrame = { -1, -1, -1 };
-static const skia::HSL kDefaultTintFrameInactive = { -1, 0.5f, 0.72f };
-static const skia::HSL kDefaultTintFrameIncognito = { -1, 0.2f, 0.35f };
-static const skia::HSL kDefaultTintFrameIncognitoInactive = { -1, 0.3f, 0.6f };
-static const skia::HSL kDefaultTintBackgroundTab = { -1, 0.5, 0.75 };
+const skia::HSL kDefaultTintButtons = { -1, -1, -1 };
+const skia::HSL kDefaultTintFrame = { -1, -1, -1 };
+const skia::HSL kDefaultTintFrameInactive = { -1, 0.5f, 0.72f };
+const skia::HSL kDefaultTintFrameIncognito = { -1, 0.2f, 0.35f };
+const skia::HSL kDefaultTintFrameIncognitoInactive = { -1, 0.3f, 0.6f };
+const skia::HSL kDefaultTintBackgroundTab = { -1, 0.5, 0.75 };
+} // namespace themes
+
+// We really want every member of the previous namespace to be exposed
+// here. The alternative is to list every member of namespace themes in a using
+// directive.
+using namespace themes;
// Default display properties.
static const int kDefaultDisplayPropertyNTPAlignment =
@@ -288,19 +295,7 @@ void BrowserThemeProvider::SetTheme(Extension* extension) {
}
void BrowserThemeProvider::UseDefaultTheme() {
- // Clear our image cache.
- ClearCaches();
-
- images_.clear();
- colors_.clear();
- tints_.clear();
- display_properties_.clear();
-
- SaveImageData(NULL);
- SaveColorData();
- SaveTintData();
- SaveDisplayPropertyData();
-
+ ClearAllThemeData();
NotifyThemeChanged();
UserMetrics::RecordAction(L"Themes_Reset", profile_);
}
@@ -560,6 +555,14 @@ std::string BrowserThemeProvider::AlignmentToString(int alignment) {
return vertical_string;
}
+void BrowserThemeProvider::SetColor(const char* key, const SkColor& color) {
+ colors_[kColorFrame] = color;
+}
+
+void BrowserThemeProvider::SetTint(const char* key, const skia::HSL& tint) {
+ tints_[key] = tint;
+}
+
void BrowserThemeProvider::GenerateFrameColors() {
// Generate any secondary frame colors that weren't provided.
skia::HSL frame_hsl = { 0, 0, 0 };
@@ -613,6 +616,21 @@ void BrowserThemeProvider::GenerateFrameImages() {
}
}
+void BrowserThemeProvider::ClearAllThemeData() {
+ // Clear our image cache.
+ ClearCaches();
+
+ images_.clear();
+ colors_.clear();
+ tints_.clear();
+ display_properties_.clear();
+
+ SaveImageData(NULL);
+ SaveColorData();
+ SaveTintData();
+ SaveDisplayPropertyData();
+}
+
SkBitmap* BrowserThemeProvider::GenerateBitmap(int id) {
if (id == IDR_THEME_TAB_BACKGROUND ||
id == IDR_THEME_TAB_BACKGROUND_INCOGNITO) {
diff --git a/chrome/browser/browser_theme_provider.h b/chrome/browser/browser_theme_provider.h
index b43a69c..b0c1b9c 100644
--- a/chrome/browser/browser_theme_provider.h
+++ b/chrome/browser/browser_theme_provider.h
@@ -20,6 +20,71 @@ class Extension;
class Profile;
class DictionaryValue;
+namespace themes {
+
+// Strings used by themes to identify colors for different parts of our UI.
+extern const char* kColorFrame;
+extern const char* kColorFrameInactive;
+extern const char* kColorFrameIncognito;
+extern const char* kColorFrameIncognitoInactive;
+extern const char* kColorToolbar;
+extern const char* kColorTabText;
+extern const char* kColorBackgroundTabText;
+extern const char* kColorBookmarkText;
+extern const char* kColorNTPBackground;
+extern const char* kColorNTPText;
+extern const char* kColorNTPLink;
+extern const char* kColorNTPSection;
+extern const char* kColorNTPSectionText;
+extern const char* kColorNTPSectionLink;
+extern const char* kColorControlBackground;
+extern const char* kColorButtonBackground;
+
+// Strings used by themes to identify tints to apply to different parts of
+// our UI. The frame tints apply to the frame color and produce the
+// COLOR_FRAME* colors.
+extern const char* kTintButtons;
+extern const char* kTintFrame;
+extern const char* kTintFrameInactive;
+extern const char* kTintFrameIncognito;
+extern const char* kTintFrameIncognitoInactive;
+extern const char* kTintBackgroundTab;
+
+// Strings used by themes to identify miscellaneous numerical properties.
+extern const char* kDisplayPropertyNTPAlignment;
+
+// Strings used in alignment properties.
+extern const char* kAlignmentTop;
+extern const char* kAlignmentBottom;
+extern const char* kAlignmentLeft;
+extern const char* kAlignmentRight;
+
+// Default colors.
+extern const SkColor kDefaultColorFrame;
+extern const SkColor kDefaultColorFrameInactive;
+extern const SkColor kDefaultColorFrameIncognito;
+extern const SkColor kDefaultColorFrameIncognitoInactive;
+extern const SkColor kDefaultColorToolbar;
+extern const SkColor kDefaultColorTabText;
+extern const SkColor kDefaultColorBackgroundTabText;
+extern const SkColor kDefaultColorBookmarkText;
+extern const SkColor kDefaultColorNTPBackground;
+extern const SkColor kDefaultColorNTPText;
+extern const SkColor kDefaultColorNTPLink;
+extern const SkColor kDefaultColorNTPSection;
+extern const SkColor kDefaultColorNTPSectionText;
+extern const SkColor kDefaultColorNTPSectionLink;
+extern const SkColor kDefaultColorControlBackground;
+extern const SkColor kDefaultColorButtonBackground;
+
+extern const skia::HSL kDefaultTintButtons;
+extern const skia::HSL kDefaultTintFrame;
+extern const skia::HSL kDefaultTintFrameInactive;
+extern const skia::HSL kDefaultTintFrameIncognito;
+extern const skia::HSL kDefaultTintFrameIncognitoInactive;
+extern const skia::HSL kDefaultTintBackgroundTab;
+} // namespace themes
+
class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>,
public NonThreadSafe,
public ThemeProvider {
@@ -78,10 +143,14 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>,
#endif
// Set the current theme to the theme defined in |extension|.
- void SetTheme(Extension* extension);
+ virtual void SetTheme(Extension* extension);
// Reset the theme to default.
- void UseDefaultTheme();
+ virtual void UseDefaultTheme();
+
+ // Set the current theme to the native theme. On some platforms, the native
+ // theme is the default theme.
+ virtual void SetNativeTheme() { UseDefaultTheme(); }
// Convert a bitfield alignment into a string like "top left". Public so that
// it can be used to generate CSS values. Takes a bitfield of AlignmentMasks.
@@ -91,6 +160,35 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>,
// AlignmentMasks
static int StringToAlignment(const std::string &alignment);
+ protected:
+ // Sets an individual color value.
+ void SetColor(const char* id, const SkColor& color);
+
+ // Sets an individual tint value.
+ void SetTint(const char* id, const skia::HSL& tint);
+
+ // Generate any frame colors that weren't specified.
+ void GenerateFrameColors();
+
+ // Generate any frame images that weren't specified. The resulting images
+ // will be stored in our cache.
+ void GenerateFrameImages();
+
+ // Clears all the override fields and saves the dictionary.
+ void ClearAllThemeData();
+
+ // Load theme data from preferences.
+ virtual void LoadThemePrefs();
+
+ // Let all the browser views know that themes have changed.
+ void NotifyThemeChanged();
+
+ // Loads a bitmap from the theme, which may be tinted or
+ // otherwise modified, or an application default.
+ virtual SkBitmap* LoadThemeBitmap(int id);
+
+ Profile* profile() { return profile_; }
+
private:
typedef std::map<const int, std::string> ImageMap;
typedef std::map<const std::string, SkColor> ColorMap;
@@ -101,10 +199,6 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>,
// true on success.
bool ReadThemeFileData(int id, std::vector<unsigned char>* raw_data);
- // Loads a bitmap from the theme, which may be tinted or
- // otherwise modified, or an application default.
- SkBitmap* LoadThemeBitmap(int id);
-
// Returns the string key for the given tint |id| TINT_* enum value.
const std::string GetTintKey(int id);
@@ -139,13 +233,6 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>,
// strings, they are currently stored as integers.
void SetDisplayPropertyData(DictionaryValue* display_properties);
- // Generate any frame colors that weren't specified.
- void GenerateFrameColors();
-
- // Generate any frame images that weren't specified. The resulting images
- // will be stored in our cache.
- void GenerateFrameImages();
-
// Create any images that aren't pregenerated (e.g. background tab images).
SkBitmap* GenerateBitmap(int id);
@@ -156,12 +243,6 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>,
void SaveTintData();
void SaveDisplayPropertyData();
- // Let all the browser views know that themes have changed.
- void NotifyThemeChanged();
-
- // Load theme data from preferences.
- void LoadThemePrefs();
-
SkColor FindColor(const char* id, SkColor default_color);
// Frees generated images and clears the image cache.
diff --git a/chrome/browser/gtk/back_forward_button_gtk.cc b/chrome/browser/gtk/back_forward_button_gtk.cc
index f354ab4..dd35a0b 100644
--- a/chrome/browser/gtk/back_forward_button_gtk.cc
+++ b/chrome/browser/gtk/back_forward_button_gtk.cc
@@ -25,20 +25,24 @@ BackForwardButtonGtk::BackForwardButtonGtk(Browser* browser, bool is_forward)
last_release_event_flags_(0),
show_menu_factory_(this) {
int normal, active, highlight, depressed, tooltip;
+ const char* stock;
if (is_forward) {
normal = IDR_FORWARD;
active = IDR_FORWARD_P;
highlight = IDR_FORWARD_H;
depressed = IDR_FORWARD_D;
tooltip = IDS_TOOLTIP_FORWARD;
+ stock = GTK_STOCK_GO_FORWARD;
} else {
normal = IDR_BACK;
active = IDR_BACK_P;
highlight = IDR_BACK_H;
depressed = IDR_BACK_D;
tooltip = IDS_TOOLTIP_BACK;
+ stock = GTK_STOCK_GO_BACK;
}
- button_.reset(new CustomDrawButton(normal, active, highlight, depressed));
+ button_.reset(new CustomDrawButton(normal, active, highlight, depressed,
+ stock));
gtk_widget_set_tooltip_text(widget(),
l10n_util::GetStringUTF8(tooltip).c_str());
menu_model_.reset(new BackForwardMenuModelGtk(browser,
@@ -72,6 +76,10 @@ void BackForwardButtonGtk::StoppedShowingMenu() {
button_->UnsetPaintOverride();
}
+void BackForwardButtonGtk::SetUseSystemTheme(bool use_gtk) {
+ button_->SetUseSystemTheme(use_gtk);
+}
+
void BackForwardButtonGtk::ShowBackForwardMenu() {
menu_.reset(new MenuGtk(menu_model_.get(), true));
button_->SetPaintOverride(GTK_STATE_ACTIVE);
diff --git a/chrome/browser/gtk/back_forward_button_gtk.h b/chrome/browser/gtk/back_forward_button_gtk.h
index 693ff40..d63412f 100644
--- a/chrome/browser/gtk/back_forward_button_gtk.h
+++ b/chrome/browser/gtk/back_forward_button_gtk.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_BROWSER_GTK_BACK_FORWARD_BUTTON_GTK_
-#define CHROME_BROWSER_GTK_BACK_FORWARD_BUTTON_GTK_
+#ifndef CHROME_BROWSER_GTK_BACK_FORWARD_BUTTON_GTK_H_
+#define CHROME_BROWSER_GTK_BACK_FORWARD_BUTTON_GTK_H_
#include "base/scoped_ptr.h"
#include "base/task.h"
@@ -27,6 +27,9 @@ class BackForwardButtonGtk {
GtkWidget* widget() { return button_->widget(); }
+ // Advises our CustomDrawButtons on how to render.
+ void SetUseSystemTheme(bool use_gtk);
+
private:
// Executes the browser command.
static void OnClick(GtkWidget* widget, BackForwardButtonGtk* button);
@@ -75,4 +78,4 @@ class BackForwardButtonGtk {
DISALLOW_COPY_AND_ASSIGN(BackForwardButtonGtk);
};
-#endif // CHROME_BROWSER_GTK_BACK_FORWARD_BUTTON_GTK_
+#endif // CHROME_BROWSER_GTK_BACK_FORWARD_BUTTON_GTK_H_
diff --git a/chrome/browser/gtk/bookmark_bar_gtk.cc b/chrome/browser/gtk/bookmark_bar_gtk.cc
index dd06d05..ca12189 100644
--- a/chrome/browser/gtk/bookmark_bar_gtk.cc
+++ b/chrome/browser/gtk/bookmark_bar_gtk.cc
@@ -22,6 +22,7 @@
#include "chrome/browser/gtk/custom_button.h"
#include "chrome/browser/gtk/gtk_chrome_button.h"
#include "chrome/browser/gtk/gtk_dnd_util.h"
+#include "chrome/browser/gtk/gtk_theme_provider.h"
#include "chrome/browser/gtk/nine_box.h"
#include "chrome/browser/gtk/tabs/tab_strip_gtk.h"
#include "chrome/browser/metrics/user_metrics.h"
@@ -45,6 +46,13 @@ const int kInstructionsPadding = 6;
// Color of the instructional text.
const GdkColor kInstructionsColor = GDK_COLOR_RGB(128, 128, 142);
+void SetUseSystemThemeGraphicsOnToolbarItems(GtkToolItem* item, bool use_gtk) {
+ GtkWidget* child = gtk_bin_get_child(GTK_BIN(item));
+ if (GTK_IS_CHROME_BUTTON(child)) {
+ gtk_chrome_button_set_use_gtk_rendering(GTK_CHROME_BUTTON(child), use_gtk);
+ }
+}
+
} // namespace
BookmarkBarGtk::BookmarkBarGtk(Profile* profile, Browser* browser,
@@ -167,6 +175,9 @@ void BookmarkBarGtk::Init(Profile* profile) {
gtk_box_pack_start(GTK_BOX(bookmark_hbox_.get()), other_bookmarks_button_,
FALSE, FALSE, 0);
+
+ // Set the current theme state for all the buttons.
+ UserChangedTheme(profile);
gtk_widget_set_size_request(bookmark_hbox_.get(), -1, 0);
slide_animation_.reset(new SlideAnimation(this));
@@ -260,9 +271,11 @@ void BookmarkBarGtk::BookmarkNodeAdded(BookmarkModel* model,
}
DCHECK(index >= 0 && index <= GetBookmarkButtonCount());
+ GtkToolItem* item = CreateBookmarkToolItem(parent->GetChild(index));
gtk_toolbar_insert(GTK_TOOLBAR(bookmark_toolbar_.get()),
- CreateBookmarkToolItem(parent->GetChild(index)),
- index);
+ item, index);
+ bool use_gtk = GtkThemeProvider::UseSystemThemeGraphics(profile_);
+ SetUseSystemThemeGraphicsOnToolbarItems(item, use_gtk);
SetInstructionState(parent);
}
@@ -321,6 +334,10 @@ void BookmarkBarGtk::CreateAllBookmarkButtons(const BookmarkNode* node) {
gtk_toolbar_insert(GTK_TOOLBAR(bookmark_toolbar_.get()), item, -1);
}
+ // Now that we've made a bunch of toolbar items, we need to make sure they
+ // have the correct theme state.
+ UserChangedTheme(profile_);
+
SetInstructionState(node);
}
@@ -350,6 +367,19 @@ bool BookmarkBarGtk::IsAlwaysShown() {
return profile_->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar);
}
+void BookmarkBarGtk::UserChangedTheme(Profile* profile) {
+ bool use_gtk = GtkThemeProvider::UseSystemThemeGraphics(profile);
+
+ gtk_chrome_button_set_use_gtk_rendering(
+ GTK_CHROME_BUTTON(other_bookmarks_button_), use_gtk);
+
+ gtk_container_foreach(
+ GTK_CONTAINER(bookmark_toolbar_.get()),
+ reinterpret_cast<void (*)(GtkWidget*, void*)>(
+ SetUseSystemThemeGraphicsOnToolbarItems),
+ reinterpret_cast<void*>(use_gtk));
+}
+
void BookmarkBarGtk::AnimationProgressed(const Animation* animation) {
DCHECK_EQ(animation, slide_animation_.get());
diff --git a/chrome/browser/gtk/bookmark_bar_gtk.h b/chrome/browser/gtk/bookmark_bar_gtk.h
index d7f5eb8..3d0c03c 100644
--- a/chrome/browser/gtk/bookmark_bar_gtk.h
+++ b/chrome/browser/gtk/bookmark_bar_gtk.h
@@ -67,6 +67,9 @@ class BookmarkBarGtk : public AnimationDelegate,
// Returns true if the bookmarks bar preference is set to 'always show'.
bool IsAlwaysShown();
+ // Alerts us that the theme changed, and we might need to change theme images.
+ void UserChangedTheme(Profile* profile);
+
// AnimationDelegate implementation ------------------------------------------
virtual void AnimationProgressed(const Animation* animation);
virtual void AnimationEnded(const Animation* animation);
diff --git a/chrome/browser/gtk/browser_titlebar.cc b/chrome/browser/gtk/browser_titlebar.cc
index 70b6a32..2448cae 100644
--- a/chrome/browser/gtk/browser_titlebar.cc
+++ b/chrome/browser/gtk/browser_titlebar.cc
@@ -144,7 +144,7 @@ void BrowserTitlebar::Init() {
CustomDrawButton* BrowserTitlebar::BuildTitlebarButton(int image,
int image_pressed, int image_hot, GtkWidget* box, int tooltip) {
CustomDrawButton* button = new CustomDrawButton(image, image_pressed,
- image_hot, 0);
+ image_hot, 0, NULL);
gtk_widget_add_events(GTK_WIDGET(button->widget()), GDK_POINTER_MOTION_MASK);
g_signal_connect(button->widget(), "clicked", G_CALLBACK(OnButtonClicked),
this);
diff --git a/chrome/browser/gtk/browser_toolbar_gtk.cc b/chrome/browser/gtk/browser_toolbar_gtk.cc
index d7fddfd..8340cef 100644
--- a/chrome/browser/gtk/browser_toolbar_gtk.cc
+++ b/chrome/browser/gtk/browser_toolbar_gtk.cc
@@ -21,6 +21,7 @@
#include "chrome/browser/gtk/go_button_gtk.h"
#include "chrome/browser/gtk/gtk_chrome_button.h"
#include "chrome/browser/gtk/gtk_dnd_util.h"
+#include "chrome/browser/gtk/gtk_theme_provider.h"
#include "chrome/browser/gtk/location_bar_view_gtk.h"
#include "chrome/browser/gtk/nine_box.h"
#include "chrome/browser/gtk/standard_menus.h"
@@ -124,10 +125,12 @@ void BrowserToolbarGtk::Init(Profile* profile,
gtk_box_pack_start(GTK_BOX(toolbar_), back_forward_hbox_, FALSE, FALSE, 0);
reload_.reset(BuildToolbarButton(IDR_RELOAD, IDR_RELOAD_P, IDR_RELOAD_H, 0,
- l10n_util::GetStringUTF8(IDS_TOOLTIP_RELOAD)));
+ l10n_util::GetStringUTF8(IDS_TOOLTIP_RELOAD),
+ GTK_STOCK_REFRESH));
home_.reset(BuildToolbarButton(IDR_HOME, IDR_HOME_P, IDR_HOME_H, 0,
- l10n_util::GetStringUTF8(IDS_TOOLTIP_HOME)));
+ l10n_util::GetStringUTF8(IDS_TOOLTIP_HOME),
+ GTK_STOCK_HOME));
gtk_util::SetButtonTriggersNavigation(home_->widget());
SetUpDragForHomeButton();
@@ -162,6 +165,9 @@ void BrowserToolbarGtk::Init(Profile* profile,
gtk_box_pack_start(GTK_BOX(toolbar_), menus_hbox_, FALSE, FALSE, 0);
+ // Force all the CustomDrawButtons to load the correct rendering style.
+ UserChangedTheme();
+
gtk_widget_show_all(toolbar_);
if (show_home_button_.GetValue()) {
@@ -274,6 +280,19 @@ void BrowserToolbarGtk::UpdateTabContents(TabContents* contents,
location_bar_->Update(should_restore_state ? contents : NULL);
}
+void BrowserToolbarGtk::UserChangedTheme() {
+ bool use_gtk = GtkThemeProvider::UseSystemThemeGraphics(profile_);
+ back_->SetUseSystemTheme(use_gtk);
+ forward_->SetUseSystemTheme(use_gtk);
+ reload_->SetUseSystemTheme(use_gtk);
+ home_->SetUseSystemTheme(use_gtk);
+
+ gtk_chrome_button_set_use_gtk_rendering(
+ GTK_CHROME_BUTTON(page_menu_button_.get()), use_gtk);
+ gtk_chrome_button_set_use_gtk_rendering(
+ GTK_CHROME_BUTTON(app_menu_button_.get()), use_gtk);
+}
+
gfx::Rect BrowserToolbarGtk::GetPopupBounds() const {
GtkWidget* star = star_->widget();
GtkWidget* go = go_->widget();
@@ -297,9 +316,9 @@ gfx::Rect BrowserToolbarGtk::GetPopupBounds() const {
CustomDrawButton* BrowserToolbarGtk::BuildToolbarButton(
int normal_id, int active_id, int highlight_id, int depressed_id,
- const std::string& localized_tooltip) {
+ const std::string& localized_tooltip, const char* stock_id) {
CustomDrawButton* button = new CustomDrawButton(normal_id, active_id,
- highlight_id, depressed_id);
+ highlight_id, depressed_id, stock_id);
gtk_widget_set_tooltip_text(button->widget(),
localized_tooltip.c_str());
@@ -332,7 +351,8 @@ GtkWidget* BrowserToolbarGtk::BuildToolbarMenuButton(
owner->Own(button);
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- gtk_container_set_border_width(GTK_CONTAINER(button), 2);
+ if (!GtkThemeProvider::UseSystemThemeGraphics(profile_))
+ gtk_container_set_border_width(GTK_CONTAINER(button), 2);
gtk_container_add(GTK_CONTAINER(button),
gtk_image_new_from_pixbuf(rb.GetPixbufNamed(icon_id)));
diff --git a/chrome/browser/gtk/browser_toolbar_gtk.h b/chrome/browser/gtk/browser_toolbar_gtk.h
index ed4dc17..9ed0929 100644
--- a/chrome/browser/gtk/browser_toolbar_gtk.h
+++ b/chrome/browser/gtk/browser_toolbar_gtk.h
@@ -78,6 +78,9 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver,
ToolbarStarToggleGtk* star() { return star_.get(); }
+ // Alerts us that the theme changed, and we might need to change theme images.
+ void UserChangedTheme();
+
// Implement AutocompletePopupPositioner, return the position of where the
// Omnibox results popup should go (from the star to the go buttons).
virtual gfx::Rect GetPopupBounds() const;
@@ -90,7 +93,8 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver,
int active_id,
int highlight_id,
int depressed_id,
- const std::string& localized_tooltip);
+ const std::string& localized_tooltip,
+ const char* stock_id);
// Create the star button given the tooltip. Returns the widget created.
ToolbarStarToggleGtk* BuildStarButton(const std::string& localized_tooltip);
diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc
index 2060ca4..529ecd6 100644
--- a/chrome/browser/gtk/browser_window_gtk.cc
+++ b/chrome/browser/gtk/browser_window_gtk.cc
@@ -10,6 +10,7 @@
#include "app/resource_bundle.h"
#include "app/theme_provider.h"
#include "base/base_paths_linux.h"
+#include "base/command_line.h"
#include "base/gfx/gtk_util.h"
#include "base/logging.h"
#include "base/message_loop.h"
@@ -34,6 +35,7 @@
#include "chrome/browser/gtk/edit_search_engine_dialog.h"
#include "chrome/browser/gtk/find_bar_gtk.h"
#include "chrome/browser/gtk/go_button_gtk.h"
+#include "chrome/browser/gtk/gtk_theme_provider.h"
#include "chrome/browser/gtk/import_dialog_gtk.h"
#include "chrome/browser/gtk/infobar_container_gtk.h"
#include "chrome/browser/gtk/keyword_editor_view.h"
@@ -713,6 +715,9 @@ void BrowserWindowGtk::UserChangedTheme() {
SetBackgroundColor();
gdk_window_invalidate_rect(GTK_WIDGET(window_)->window,
&GTK_WIDGET(window_)->allocation, TRUE);
+
+ toolbar_->UserChangedTheme();
+ bookmark_bar_->UserChangedTheme(browser_->profile());
}
int BrowserWindowGtk::GetExtraRenderViewHeight() const {
@@ -1039,9 +1044,8 @@ void BrowserWindowGtk::InitWidgets() {
void BrowserWindowGtk::SetBackgroundColor() {
// TODO(tc): Handle active/inactive colors.
-
- ThemeProvider* theme_provider = browser()->profile()->GetThemeProvider();
-
+ Profile* profile = browser()->profile();
+ ThemeProvider* theme_provider = profile->GetThemeProvider();
SkColor frame_color;
if (browser()->profile()->IsOffTheRecord()) {
frame_color = theme_provider->GetColor(
diff --git a/chrome/browser/gtk/custom_button.cc b/chrome/browser/gtk/custom_button.cc
index e828243..6729ee6 100644
--- a/chrome/browser/gtk/custom_button.cc
+++ b/chrome/browser/gtk/custom_button.cc
@@ -7,6 +7,7 @@
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/basictypes.h"
+#include "base/gfx/gtk_util.h"
#include "grit/theme_resources.h"
@@ -64,26 +65,46 @@ CustomDrawButton::CustomDrawButton(
int normal_id,
int active_id,
int highlight_id,
- int depressed_id)
- : button_base_(normal_id, active_id, highlight_id, depressed_id) {
+ int depressed_id,
+ const char* stock_id)
+ : button_base_(normal_id, active_id, highlight_id, depressed_id),
+ gtk_stock_name_(stock_id),
+ has_expose_signal_handler_(false) {
widget_.Own(gtk_button_new());
GTK_WIDGET_UNSET_FLAGS(widget_.get(), GTK_CAN_FOCUS);
-
- gtk_widget_set_size_request(widget_.get(),
- gdk_pixbuf_get_width(button_base_.pixbufs(0)),
- gdk_pixbuf_get_height(button_base_.pixbufs(0)));
-
- gtk_widget_set_app_paintable(widget_.get(), TRUE);
- // We effectively double-buffer by virtue of having only one image...
- gtk_widget_set_double_buffered(widget_.get(), FALSE);
- g_signal_connect(G_OBJECT(widget_.get()), "expose-event",
- G_CALLBACK(OnExpose), this);
+ SetUseSystemTheme(false);
}
CustomDrawButton::~CustomDrawButton() {
widget_.Destroy();
}
+void CustomDrawButton::SetUseSystemTheme(bool use_gtk) {
+ if (use_gtk && gtk_stock_name_) {
+ gtk_button_set_image(
+ GTK_BUTTON(widget_.get()),
+ gtk_image_new_from_stock(gtk_stock_name_, GTK_ICON_SIZE_BUTTON));
+ gtk_widget_set_size_request(widget_.get(), -1, -1);
+ gtk_widget_set_app_paintable(widget_.get(), FALSE);
+ gtk_widget_set_double_buffered(widget_.get(), TRUE);
+
+ if (has_expose_signal_handler_)
+ gtk_signal_disconnect_by_data(GTK_OBJECT(widget_.get()), this);
+ has_expose_signal_handler_ = false;
+ } else {
+ gtk_widget_set_size_request(widget_.get(),
+ gdk_pixbuf_get_width(button_base_.pixbufs(0)),
+ gdk_pixbuf_get_height(button_base_.pixbufs(0)));
+
+ gtk_widget_set_app_paintable(widget_.get(), TRUE);
+ // We effectively double-buffer by virtue of having only one image...
+ gtk_widget_set_double_buffered(widget_.get(), FALSE);
+ g_signal_connect(G_OBJECT(widget_.get()), "expose-event",
+ G_CALLBACK(OnCustomExpose), this);
+ has_expose_signal_handler_ = true;
+ }
+}
+
void CustomDrawButton::SetPaintOverride(GtkStateType state) {
button_base_.set_paint_override(state);
gtk_widget_queue_draw(widget_.get());
@@ -95,14 +116,16 @@ void CustomDrawButton::UnsetPaintOverride() {
}
// static
-gboolean CustomDrawButton::OnExpose(GtkWidget* widget,
- GdkEventExpose* e,
- CustomDrawButton* button) {
+gboolean CustomDrawButton::OnCustomExpose(GtkWidget* widget,
+ GdkEventExpose* e,
+ CustomDrawButton* button) {
return button->button_base_.OnExpose(widget, e);
}
// static
CustomDrawButton* CustomDrawButton::CloseButton() {
- return new CustomDrawButton(IDR_CLOSE_BAR, IDR_CLOSE_BAR_P,
- IDR_CLOSE_BAR_H, 0);
+ CustomDrawButton* button =
+ new CustomDrawButton(IDR_CLOSE_BAR, IDR_CLOSE_BAR_P,
+ IDR_CLOSE_BAR_H, 0, NULL);
+ return button;
}
diff --git a/chrome/browser/gtk/custom_button.h b/chrome/browser/gtk/custom_button.h
index 0e54732..143a090 100644
--- a/chrome/browser/gtk/custom_button.h
+++ b/chrome/browser/gtk/custom_button.h
@@ -45,7 +45,8 @@ class CustomDrawButtonBase {
};
// CustomDrawButton is a plain button where all its various states are drawn
-// with static images.
+// with static images. In GTK rendering mode, it will show the standard button
+// with GTK |stock_id|.
class CustomDrawButton {
public:
// The constructor takes 4 resource ids. If a resource doesn't exist for a
@@ -53,7 +54,8 @@ class CustomDrawButton {
CustomDrawButton(int normal_id,
int active_id,
int highlight_id,
- int depressed_id);
+ int depressed_id,
+ const char* stock_id);
explicit CustomDrawButton(const std::string& filename);
~CustomDrawButton();
@@ -69,6 +71,12 @@ class CustomDrawButton {
int width() const { return widget_->allocation.width; }
int height() const { return widget_->allocation.height; }
+ // Sets properties on the GtkButton returned by widget(). By default, the
+ // button is very boring. This will either give it an image from the
+ // |gtk_stock_name_| if |use_gtk| is true or will use the chrome frame
+ // images.
+ void SetUseSystemTheme(bool use_gtk);
+
// Set the state to draw. We will paint the widget as if it were in this
// state.
void SetPaintOverride(GtkStateType state);
@@ -80,16 +88,22 @@ class CustomDrawButton {
static CustomDrawButton* CloseButton();
private:
- // Callback for expose, used to draw the custom graphics.
- static gboolean OnExpose(GtkWidget* widget,
- GdkEventExpose* e,
- CustomDrawButton* obj);
+ // Callback for custom button expose, used to draw the custom graphics.
+ static gboolean OnCustomExpose(GtkWidget* widget,
+ GdkEventExpose* e,
+ CustomDrawButton* obj);
// The actual button widget.
OwnedWidgetGtk widget_;
CustomDrawButtonBase button_base_;
+ // The stock icon name.
+ const char* gtk_stock_name_;
+
+ // Whether we have an expose signal handler we may need to remove.
+ bool has_expose_signal_handler_;
+
DISALLOW_COPY_AND_ASSIGN(CustomDrawButton);
};
diff --git a/chrome/browser/gtk/find_bar_gtk.cc b/chrome/browser/gtk/find_bar_gtk.cc
index e8e70d3..54fe240 100644
--- a/chrome/browser/gtk/find_bar_gtk.cc
+++ b/chrome/browser/gtk/find_bar_gtk.cc
@@ -163,7 +163,8 @@ void FindBarGtk::InitWidgets() {
l10n_util::GetStringUTF8(IDS_FIND_IN_PAGE_CLOSE_TOOLTIP).c_str());
find_next_button_.reset(new CustomDrawButton(IDR_FINDINPAGE_NEXT,
- IDR_FINDINPAGE_NEXT_H, IDR_FINDINPAGE_NEXT_H, IDR_FINDINPAGE_NEXT_P));
+ IDR_FINDINPAGE_NEXT_H, IDR_FINDINPAGE_NEXT_H, IDR_FINDINPAGE_NEXT_P,
+ NULL));
g_signal_connect(G_OBJECT(find_next_button_->widget()), "clicked",
G_CALLBACK(OnClicked), this);
gtk_widget_set_tooltip_text(find_next_button_->widget(),
@@ -172,7 +173,8 @@ void FindBarGtk::InitWidgets() {
FALSE, FALSE, 0);
find_previous_button_.reset(new CustomDrawButton(IDR_FINDINPAGE_PREV,
- IDR_FINDINPAGE_PREV_H, IDR_FINDINPAGE_PREV_H, IDR_FINDINPAGE_PREV_P));
+ IDR_FINDINPAGE_PREV_H, IDR_FINDINPAGE_PREV_H, IDR_FINDINPAGE_PREV_P,
+ NULL));
g_signal_connect(G_OBJECT(find_previous_button_->widget()), "clicked",
G_CALLBACK(OnClicked), this);
gtk_widget_set_tooltip_text(find_previous_button_->widget(),
diff --git a/chrome/browser/gtk/gtk_chrome_button.cc b/chrome/browser/gtk/gtk_chrome_button.cc
index 558e610..6b35716 100644
--- a/chrome/browser/gtk/gtk_chrome_button.cc
+++ b/chrome/browser/gtk/gtk_chrome_button.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/gtk/gtk_chrome_button.h"
#include "base/basictypes.h"
+#include "base/gfx/gtk_util.h"
#include "chrome/browser/gtk/nine_box.h"
#include "grit/app_resources.h"
@@ -27,6 +28,10 @@ typedef struct _GtkChromeButtonPrivate GtkChromeButtonPrivate;
struct _GtkChromeButtonPrivate {
int paint_state;
+
+ // If true, we use images provided by the theme instead of GTK's default
+ // button rendering.
+ gboolean use_gtk_rendering;
};
G_DEFINE_TYPE(GtkChromeButton, gtk_chrome_button, GTK_TYPE_BUTTON)
@@ -66,6 +71,7 @@ static void gtk_chrome_button_class_init(GtkChromeButtonClass* button_class) {
static void gtk_chrome_button_init(GtkChromeButton* button) {
GtkChromeButtonPrivate* priv = GTK_CHROME_BUTTON_GET_PRIVATE(button);
priv->paint_state = -1;
+ priv->use_gtk_rendering = FALSE;
gtk_widget_set_app_paintable(GTK_WIDGET(button), TRUE);
@@ -78,19 +84,34 @@ static gboolean gtk_chrome_button_expose(GtkWidget* widget,
int paint_state = priv->paint_state < 0 ?
GTK_WIDGET_STATE(widget) : priv->paint_state;
- NineBox* nine_box = NULL;
- if (paint_state == GTK_STATE_PRELIGHT)
- nine_box = g_nine_box_prelight;
- else if (paint_state == GTK_STATE_ACTIVE)
- nine_box = g_nine_box_active;
-
- // Only draw theme graphics if we have some.
- if (nine_box)
- nine_box->RenderToWidget(widget);
-
- gtk_container_propagate_expose(GTK_CONTAINER(widget),
- gtk_bin_get_child(GTK_BIN(widget)),
- event);
+ if (priv->use_gtk_rendering) {
+ // We have the superclass handle this expose when we aren't using custom
+ // rendering AND we're in either the prelight or active state so that we
+ // get the button border for the current GTK theme drawn.
+ if (paint_state == GTK_STATE_PRELIGHT || paint_state == GTK_STATE_ACTIVE) {
+ (*GTK_WIDGET_CLASS(gtk_chrome_button_parent_class)->expose_event)
+ (widget, event);
+ } else {
+ // Otherwise, we're still responsible for rendering our children.
+ gtk_container_propagate_expose(GTK_CONTAINER(widget),
+ gtk_bin_get_child(GTK_BIN(widget)),
+ event);
+ }
+ } else {
+ NineBox* nine_box = NULL;
+ if (paint_state == GTK_STATE_PRELIGHT)
+ nine_box = g_nine_box_prelight;
+ else if (paint_state == GTK_STATE_ACTIVE)
+ nine_box = g_nine_box_active;
+
+ // Only draw theme graphics if we have some.
+ if (nine_box)
+ nine_box->RenderToWidget(widget);
+
+ gtk_container_propagate_expose(GTK_CONTAINER(widget),
+ gtk_bin_get_child(GTK_BIN(widget)),
+ event);
+ }
return TRUE; // Don't propagate, we are the default handler.
}
@@ -118,4 +139,11 @@ void gtk_chrome_button_unset_paint_state(GtkChromeButton* button) {
gtk_widget_queue_draw(GTK_WIDGET(button));
}
+void gtk_chrome_button_set_use_gtk_rendering(GtkChromeButton* button,
+ gboolean value) {
+ g_return_if_fail(GTK_IS_CHROME_BUTTON(button));
+ GtkChromeButtonPrivate *priv = GTK_CHROME_BUTTON_GET_PRIVATE(button);
+ priv->use_gtk_rendering = value;
+}
+
G_END_DECLS
diff --git a/chrome/browser/gtk/gtk_chrome_button.h b/chrome/browser/gtk/gtk_chrome_button.h
index c1437d4..921e1e2 100644
--- a/chrome/browser/gtk/gtk_chrome_button.h
+++ b/chrome/browser/gtk/gtk_chrome_button.h
@@ -45,6 +45,10 @@ void gtk_chrome_button_set_paint_state(GtkChromeButton* button,
// Revert to using the widget's current state for painting.
void gtk_chrome_button_unset_paint_state(GtkChromeButton* button);
+// Whether we should use custom theme images or let GTK take care of it.
+void gtk_chrome_button_set_use_gtk_rendering(GtkChromeButton* button,
+ gboolean value);
+
G_END_DECLS
#endif // CHROME_BROWSER_GTK_GTK_CHROME_BUTTON_H_
diff --git a/chrome/browser/gtk/gtk_theme_provider.cc b/chrome/browser/gtk/gtk_theme_provider.cc
new file mode 100644
index 0000000..f030398
--- /dev/null
+++ b/chrome/browser/gtk/gtk_theme_provider.cc
@@ -0,0 +1,154 @@
+// Copyright (c) 2009 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/gtk/gtk_theme_provider.h"
+
+#include <gtk/gtk.h>
+
+#include "base/gfx/gtk_util.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/profile.h"
+#include "chrome/common/pref_names.h"
+#include "grit/theme_resources.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+
+namespace {
+
+// The size of the rendered toolbar image.
+const int kToolbarImageWidth = 64;
+const int kToolbarImageHeight = 128;
+
+} // namespace
+
+GtkThemeProvider::GtkThemeProvider()
+ : BrowserThemeProvider(),
+ fake_window_(gtk_window_new(GTK_WINDOW_TOPLEVEL)) {
+ // Only realized widgets receive style-set notifications, which we need to
+ // broadcast new theme images and colors.
+ gtk_widget_realize(fake_window_);
+ g_signal_connect(fake_window_, "style-set", G_CALLBACK(&OnStyleSet), this);
+}
+
+GtkThemeProvider::~GtkThemeProvider() {
+ gtk_widget_destroy(fake_window_);
+}
+
+void GtkThemeProvider::SetTheme(Extension* extension) {
+ profile()->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, false);
+ BrowserThemeProvider::SetTheme(extension);
+}
+
+void GtkThemeProvider::UseDefaultTheme() {
+ profile()->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, false);
+ BrowserThemeProvider::UseDefaultTheme();
+}
+
+void GtkThemeProvider::SetNativeTheme() {
+ profile()->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, true);
+ ClearAllThemeData();
+ LoadGtkValues();
+ NotifyThemeChanged();
+}
+
+// static
+bool GtkThemeProvider::UseSystemThemeGraphics(Profile* profile) {
+ return profile->GetPrefs()->GetBoolean(prefs::kUsesSystemTheme);
+}
+
+void GtkThemeProvider::LoadThemePrefs() {
+ if (profile()->GetPrefs()->GetBoolean(prefs::kUsesSystemTheme)) {
+ LoadGtkValues();
+ } else {
+ BrowserThemeProvider::LoadThemePrefs();
+ }
+}
+
+SkBitmap* GtkThemeProvider::LoadThemeBitmap(int id) {
+ if (id == IDR_THEME_TOOLBAR && UseSystemThemeGraphics(profile())) {
+ GtkStyle* style = gtk_rc_get_style(fake_window_);
+ GdkColor* color = &style->bg[GTK_STATE_NORMAL];
+ SkBitmap* bitmap = new SkBitmap;
+ bitmap->setConfig(SkBitmap::kARGB_8888_Config,
+ kToolbarImageWidth, kToolbarImageHeight);
+ bitmap->allocPixels();
+ bitmap->eraseRGB(color->red >> 8, color->green >> 8, color->blue >> 8);
+ return bitmap;
+ } else {
+ return BrowserThemeProvider::LoadThemeBitmap(id);
+ }
+}
+
+// static
+void GtkThemeProvider::OnStyleSet(GtkWidget* widget,
+ GtkStyle* previous_style,
+ GtkThemeProvider* provider) {
+ if (provider->profile()->GetPrefs()->GetBoolean(prefs::kUsesSystemTheme)) {
+ provider->ClearAllThemeData();
+ provider->LoadGtkValues();
+ provider->NotifyThemeChanged();
+ }
+}
+
+void GtkThemeProvider::LoadGtkValues() {
+ GtkStyle* style = gtk_rc_get_style(fake_window_);
+
+ SetThemeColorFromGtk(themes::kColorFrame, &style->bg[GTK_STATE_SELECTED]);
+ SetThemeColorFromGtk(themes::kColorFrameInactive,
+ &style->bg[GTK_STATE_INSENSITIVE]);
+ // TODO(erg): Incognito images.
+ SetThemeColorFromGtk(themes::kColorToolbar,
+ &style->bg[GTK_STATE_NORMAL]);
+ SetThemeColorFromGtk(themes::kColorTabText,
+ &style->text[GTK_STATE_NORMAL]);
+ SetThemeColorFromGtk(themes::kColorBackgroundTabText,
+ &style->text[GTK_STATE_NORMAL]);
+ SetThemeColorFromGtk(themes::kColorBookmarkText,
+ &style->text[GTK_STATE_NORMAL]);
+ SetThemeColorFromGtk(themes::kColorControlBackground,
+ &style->bg[GTK_STATE_NORMAL]);
+ SetThemeColorFromGtk(themes::kColorButtonBackground,
+ &style->bg[GTK_STATE_NORMAL]);
+
+ SetThemeTintFromGtk(themes::kTintButtons, &style->bg[GTK_STATE_SELECTED],
+ themes::kDefaultTintButtons);
+ SetThemeTintFromGtk(themes::kTintFrame, &style->bg[GTK_STATE_SELECTED],
+ themes::kDefaultTintFrame);
+ SetThemeTintFromGtk(themes::kTintFrameInactive,
+ &style->bg[GTK_STATE_SELECTED],
+ themes::kDefaultTintFrameInactive);
+ SetThemeTintFromGtk(themes::kTintFrameIncognito,
+ &style->bg[GTK_STATE_SELECTED],
+ themes::kDefaultTintFrameIncognito);
+ SetThemeTintFromGtk(themes::kTintFrameIncognitoInactive,
+ &style->bg[GTK_STATE_SELECTED],
+ themes::kDefaultTintFrameIncognitoInactive);
+ SetThemeTintFromGtk(themes::kTintBackgroundTab,
+ &style->bg[GTK_STATE_SELECTED],
+ themes::kDefaultTintBackgroundTab);
+
+ GenerateFrameColors();
+ GenerateFrameImages();
+}
+
+void GtkThemeProvider::SetThemeColorFromGtk(const char* id, GdkColor* color) {
+ SetColor(id, SkColorSetRGB(color->red >> 8,
+ color->green >> 8,
+ color->blue >> 8));
+}
+
+void GtkThemeProvider::SetThemeTintFromGtk(const char* id, GdkColor* color,
+ const skia::HSL& default_tint) {
+ skia::HSL hsl;
+ skia::SkColorToHSL(SkColorSetRGB((color->red >> 8),
+ (color->green >> 8),
+ (color->blue >> 8)), hsl);
+ if (default_tint.s != -1)
+ hsl.s = default_tint.s;
+
+ if (default_tint.l != -1)
+ hsl.l = default_tint.l;
+ SetTint(id, hsl);
+}
+
diff --git a/chrome/browser/gtk/gtk_theme_provider.h b/chrome/browser/gtk/gtk_theme_provider.h
new file mode 100644
index 0000000..88f0fed
--- /dev/null
+++ b/chrome/browser/gtk/gtk_theme_provider.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2009 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.
+
+#ifndef CHROME_BROWSER_GTK_GTK_THEME_PROVIDER_H_
+#define CHROME_BROWSER_GTK_GTK_THEME_PROVIDER_H_
+
+#include "chrome/browser/browser_theme_provider.h"
+
+#include "skia/ext/skia_utils.h"
+
+class Profile;
+
+typedef struct _GtkStyle GtkStyle;
+typedef struct _GtkWidget GtkWidget;
+
+// Specialization of BrowserThemeProvider which supplies system colors.
+class GtkThemeProvider : public BrowserThemeProvider {
+ public:
+ GtkThemeProvider();
+ virtual ~GtkThemeProvider();
+
+ // Overridden from BrowserThemeProvider:
+ //
+ // Sets that we aren't using the system theme, then calls
+ // BrowserThemeProvider's implementation.
+ virtual void SetTheme(Extension* extension);
+ virtual void UseDefaultTheme();
+ virtual void SetNativeTheme();
+
+ // Whether we should use the GTK system theme.
+ static bool UseSystemThemeGraphics(Profile* profile);
+
+ private:
+ // Load theme data from preferences, possibly picking colors from GTK.
+ virtual void LoadThemePrefs();
+
+ // Possibly creates a theme specific version of theme_toolbar_default.
+ // (minimally acceptable version right now, which is just a fill of the bg
+ // color; this should instead invoke gtk_draw_box(...) for complex theme
+ // engines.)
+ virtual SkBitmap* LoadThemeBitmap(int id);
+
+ // Handles signal from GTK that our theme has been changed.
+ static void OnStyleSet(GtkWidget* widget,
+ GtkStyle* previous_style,
+ GtkThemeProvider* provider);
+
+ void LoadGtkValues();
+
+ // Sets the underlying theme colors/tints from a GTK color.
+ void SetThemeColorFromGtk(const char* id, GdkColor* color);
+ void SetThemeTintFromGtk(const char* id, GdkColor* color,
+ const skia::HSL& default_tint);
+
+ // A GtkWidget that exists only so we can look at its properties (and take
+ // its colors).
+ GtkWidget* fake_window_;
+};
+
+#endif // CHROME_BROWSER_GTK_GTK_THEME_PROVIDER_H_
diff --git a/chrome/browser/gtk/location_bar_view_gtk.cc b/chrome/browser/gtk/location_bar_view_gtk.cc
index 118287d..b10712a 100644
--- a/chrome/browser/gtk/location_bar_view_gtk.cc
+++ b/chrome/browser/gtk/location_bar_view_gtk.cc
@@ -15,6 +15,7 @@
#include "chrome/browser/alternate_nav_url_fetcher.h"
#include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h"
#include "chrome/browser/command_updater.h"
+#include "chrome/browser/gtk/gtk_theme_provider.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/gtk_util.h"
#include "chrome/common/page_transition_types.h"
@@ -116,10 +117,17 @@ void LocationBarViewGtk::Init() {
G_CALLBACK(&HandleExposeThunk), this);
GtkWidget* align = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
- gtk_alignment_set_padding(GTK_ALIGNMENT(align),
- kTopMargin + kBorderThickness,
- kBottomMargin + kBorderThickness,
- kEditLeftRightPadding, kEditLeftRightPadding);
+ // TODO(erg): Redo this so that it adjusts during theme changes.
+ if (GtkThemeProvider::UseSystemThemeGraphics(profile_)) {
+ gtk_alignment_set_padding(GTK_ALIGNMENT(align),
+ 0, 0,
+ kEditLeftRightPadding, kEditLeftRightPadding);
+ } else {
+ gtk_alignment_set_padding(GTK_ALIGNMENT(align),
+ kTopMargin + kBorderThickness,
+ kBottomMargin + kBorderThickness,
+ kEditLeftRightPadding, kEditLeftRightPadding);
+ }
gtk_container_add(GTK_CONTAINER(align), location_entry_->widget());
gtk_box_pack_start(GTK_BOX(hbox_.get()), align, TRUE, TRUE, 0);
diff --git a/chrome/browser/gtk/options/content_page_gtk.cc b/chrome/browser/gtk/options/content_page_gtk.cc
index 49d1c3e..1130912 100644
--- a/chrome/browser/gtk/options/content_page_gtk.cc
+++ b/chrome/browser/gtk/options/content_page_gtk.cc
@@ -171,6 +171,12 @@ GtkWidget* ContentPageGtk::InitBrowsingDataGroup() {
GtkWidget* ContentPageGtk::InitThemesGroup() {
GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
+ // GTK theme button.
+ GtkWidget* gtk_theme_button = gtk_button_new_with_label("GTK Theme");
+ g_signal_connect(G_OBJECT(gtk_theme_button), "clicked",
+ G_CALLBACK(OnGtkThemeButtonClicked), this);
+ gtk_box_pack_start(GTK_BOX(hbox), gtk_theme_button, FALSE, FALSE, 0);
+
// Reset themes button.
GtkWidget* themes_reset_button = gtk_button_new_with_label(
l10n_util::GetStringUTF8(IDS_THEMES_RESET_BUTTON).c_str());
@@ -198,6 +204,14 @@ void ContentPageGtk::OnClearBrowsingDataButtonClicked(GtkButton* widget,
}
// static
+void ContentPageGtk::OnGtkThemeButtonClicked(GtkButton* widget,
+ ContentPageGtk* page) {
+ page->UserMetricsRecordAction(L"Options_GtkThemeSet",
+ page->profile()->GetPrefs());
+ page->profile()->SetNativeTheme();
+}
+
+// static
void ContentPageGtk::OnResetDefaultThemeButtonClicked(GtkButton* widget,
ContentPageGtk* page) {
page->UserMetricsRecordAction(L"Options_ThemesReset",
diff --git a/chrome/browser/gtk/options/content_page_gtk.h b/chrome/browser/gtk/options/content_page_gtk.h
index 95b044e0..17f58e4 100644
--- a/chrome/browser/gtk/options/content_page_gtk.h
+++ b/chrome/browser/gtk/options/content_page_gtk.h
@@ -37,6 +37,10 @@ class ContentPageGtk : public OptionsPageBase {
static void OnClearBrowsingDataButtonClicked(GtkButton* widget,
ContentPageGtk* page);
+ // Callback for the GTK theme button.
+ static void OnGtkThemeButtonClicked(GtkButton* widget,
+ ContentPageGtk* page);
+
// Callback for reset default theme button.
static void OnResetDefaultThemeButtonClicked(GtkButton* widget,
ContentPageGtk* page);
diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk.cc b/chrome/browser/gtk/tabs/tab_renderer_gtk.cc
index 1a045ba..a8de38a 100755
--- a/chrome/browser/gtk/tabs/tab_renderer_gtk.cc
+++ b/chrome/browser/gtk/tabs/tab_renderer_gtk.cc
@@ -681,7 +681,7 @@ bool TabRendererGtk::ShouldShowCloseBox() const {
CustomDrawButton* TabRendererGtk::MakeCloseButton() {
CustomDrawButton* button = new CustomDrawButton(IDR_TAB_CLOSE,
- IDR_TAB_CLOSE_P, IDR_TAB_CLOSE_H, IDR_TAB_CLOSE);
+ IDR_TAB_CLOSE_P, IDR_TAB_CLOSE_H, IDR_TAB_CLOSE, NULL);
g_signal_connect(G_OBJECT(button->widget()), "clicked",
G_CALLBACK(OnCloseButtonClicked), this);
diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.cc b/chrome/browser/gtk/tabs/tab_strip_gtk.cc
index 338c0e2d..bb32927 100755
--- a/chrome/browser/gtk/tabs/tab_strip_gtk.cc
+++ b/chrome/browser/gtk/tabs/tab_strip_gtk.cc
@@ -1571,7 +1571,7 @@ void TabStripGtk::SetTabBounds(TabGtk* tab, const gfx::Rect& bounds) {
CustomDrawButton* TabStripGtk::MakeNewTabButton() {
CustomDrawButton* button = new CustomDrawButton(IDR_NEWTAB_BUTTON,
- IDR_NEWTAB_BUTTON_P, IDR_NEWTAB_BUTTON_H, 0);
+ IDR_NEWTAB_BUTTON_P, IDR_NEWTAB_BUTTON_H, 0, NULL);
g_signal_connect(G_OBJECT(button->widget()), "clicked",
G_CALLBACK(OnNewTabClicked), this);
diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc
index 5d0ccec..0034792 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -45,6 +45,10 @@
#include "grit/locale_settings.h"
#include "net/base/force_tls_state.h"
+#if defined(OS_LINUX)
+#include "chrome/browser/gtk/gtk_theme_provider.h"
+#endif
+
using base::Time;
using base::TimeDelta;
@@ -116,6 +120,9 @@ void Profile::RegisterUserPrefs(PrefService* prefs) {
prefs->RegisterBooleanPref(prefs::kEnableSpellCheck, true);
prefs->RegisterBooleanPref(prefs::kEnableAutoSpellCorrect, true);
prefs->RegisterBooleanPref(prefs::kEnableUserScripts, false);
+#if defined(OS_LINUX)
+ prefs->RegisterBooleanPref(prefs::kUsesSystemTheme, false);
+#endif
prefs->RegisterStringPref(prefs::kCurrentThemeID, L"");
prefs->RegisterDictionaryPref(prefs::kCurrentThemeImages);
prefs->RegisterDictionaryPref(prefs::kCurrentThemeColors);
@@ -287,6 +294,10 @@ class OffTheRecordProfileImpl : public Profile,
GetOriginalProfile()->SetTheme(extension);
}
+ virtual void SetNativeTheme() {
+ GetOriginalProfile()->SetNativeTheme();
+ }
+
virtual void ClearTheme() {
GetOriginalProfile()->ClearTheme();
}
@@ -922,7 +933,11 @@ bool ProfileImpl::HasCreatedDownloadManager() const {
void ProfileImpl::InitThemes() {
if (!created_theme_provider_) {
+#if defined(OS_LINUX)
+ scoped_refptr<BrowserThemeProvider> themes(new GtkThemeProvider);
+#else
scoped_refptr<BrowserThemeProvider> themes(new BrowserThemeProvider);
+#endif
themes->Init(this);
created_theme_provider_ = true;
theme_provider_.swap(themes);
@@ -934,6 +949,11 @@ void ProfileImpl::SetTheme(Extension* extension) {
theme_provider_.get()->SetTheme(extension);
}
+void ProfileImpl::SetNativeTheme() {
+ InitThemes();
+ theme_provider_.get()->SetNativeTheme();
+}
+
void ProfileImpl::ClearTheme() {
InitThemes();
theme_provider_.get()->UseDefaultTheme();
diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h
index 7190cc7..302d222a 100644
--- a/chrome/browser/profile.h
+++ b/chrome/browser/profile.h
@@ -188,6 +188,9 @@ class Profile {
// Set the theme to the specified extension.
virtual void SetTheme(Extension* extension) = 0;
+ // Set the theme to the machine's native theme.
+ virtual void SetNativeTheme() = 0;
+
// Clear the theme and reset it to default.
virtual void ClearTheme() = 0;
@@ -340,6 +343,7 @@ class ProfileImpl : public Profile,
virtual DownloadManager* GetDownloadManager();
virtual void InitThemes();
virtual void SetTheme(Extension* extension);
+ virtual void SetNativeTheme();
virtual void ClearTheme();
virtual ThemeProvider* GetThemeProvider();
virtual ThumbnailStore* GetThumbnailStore();
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index bdd4e17..c4b25a7 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -995,6 +995,8 @@
'browser/gtk/gtk_dnd_util.h',
'browser/gtk/gtk_floating_container.cc',
'browser/gtk/gtk_floating_container.h',
+ 'browser/gtk/gtk_theme_provider.cc',
+ 'browser/gtk/gtk_theme_provider.h',
'browser/gtk/hung_renderer_dialog_gtk.cc',
'browser/gtk/import_dialog_gtk.cc',
'browser/gtk/import_dialog_gtk.h',
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 159e643..426adb1 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -249,6 +249,10 @@ const wchar_t kPrintingPageHeaderRight[] = L"printing.page.header.right";
const wchar_t kPrintingPageFooterLeft[] = L"printing.page.footer.left";
const wchar_t kPrintingPageFooterCenter[] = L"printing.page.footer.center";
const wchar_t kPrintingPageFooterRight[] = L"printing.page.footer.right";
+#if defined(OS_LINUX)
+// GTK specific preference on whether we should match the system GTK theme.
+const wchar_t kUsesSystemTheme[] = L"extensions.theme.use_system";
+#endif
const wchar_t kCurrentThemeID[] = L"extensions.theme.id";
const wchar_t kCurrentThemeImages[] = L"extensions.theme.images";
const wchar_t kCurrentThemeColors[] = L"extensions.theme.colors";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 5f561c4..96b2caf 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -7,6 +7,8 @@
#ifndef CHROME_COMMON_PREF_NAMES_H_
#define CHROME_COMMON_PREF_NAMES_H_
+#include "build/build_config.h"
+
namespace prefs {
// Profile prefs
@@ -89,6 +91,9 @@ extern const wchar_t kPrintingPageHeaderRight[];
extern const wchar_t kPrintingPageFooterLeft[];
extern const wchar_t kPrintingPageFooterCenter[];
extern const wchar_t kPrintingPageFooterRight[];
+#if defined(OS_LINUX)
+extern const wchar_t kUsesSystemTheme[];
+#endif
extern const wchar_t kCurrentThemeID[];
extern const wchar_t kCurrentThemeImages[];
extern const wchar_t kCurrentThemeColors[];
diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h
index d791fdd..b360ac2 100644
--- a/chrome/test/testing_profile.h
+++ b/chrome/test/testing_profile.h
@@ -134,6 +134,7 @@ class TestingProfile : public Profile {
}
virtual void InitThemes() { }
virtual void SetTheme(Extension* extension) { }
+ virtual void SetNativeTheme() { }
virtual void ClearTheme() { }
virtual ThemeProvider* GetThemeProvider() {
return theme_provider_.get();