| Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | 2 | // Use of this source code is governed by a BSD-style license that can be | 
|  | 3 | // found in the LICENSE file. | 
|  | 4 |  | 
|  | 5 | #ifndef CHROME_BROWSER_UI_GTK_GTK_THEME_SERVICE_H_ | 
|  | 6 | #define CHROME_BROWSER_UI_GTK_GTK_THEME_SERVICE_H_ | 
|  | 7 |  | 
|  | 8 | #include <map> | 
|  | 9 | #include <vector> | 
|  | 10 |  | 
|  | 11 | #include "base/compiler_specific.h" | 
|  | 12 | #include "base/lazy_instance.h" | 
|  | 13 | #include "base/memory/scoped_ptr.h" | 
| Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 14 | #include "base/prefs/pref_change_registrar.h" | 
| Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 15 | #include "chrome/browser/themes/theme_service.h" | 
|  | 16 | #include "ui/base/glib/glib_integers.h" | 
|  | 17 | #include "ui/base/gtk/gtk_signal.h" | 
|  | 18 | #include "ui/base/gtk/owned_widget_gtk.h" | 
|  | 19 | #include "ui/gfx/color_utils.h" | 
|  | 20 |  | 
|  | 21 | class Profile; | 
|  | 22 |  | 
| Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 23 | namespace content { | 
|  | 24 | class NotificationObserver; | 
|  | 25 | } | 
|  | 26 |  | 
| Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 27 | namespace extensions { | 
|  | 28 | class Extension; | 
|  | 29 | } | 
|  | 30 |  | 
|  | 31 | namespace gfx { | 
|  | 32 | class CairoCachedSurface; | 
|  | 33 | } | 
|  | 34 |  | 
|  | 35 | namespace ui { | 
|  | 36 | class GtkSignalRegistrar; | 
|  | 37 | } | 
|  | 38 |  | 
|  | 39 | typedef struct _GdkDisplay GdkDisplay; | 
|  | 40 | typedef struct _GdkEventExpose GdkEventExpose; | 
|  | 41 | typedef struct _GdkPixbuf GdkPixbuf; | 
|  | 42 | typedef struct _GtkIconSet GtkIconSet; | 
|  | 43 | typedef struct _GtkStyle GtkStyle; | 
|  | 44 | typedef struct _GtkWidget GtkWidget; | 
|  | 45 |  | 
|  | 46 | // Specialization of ThemeService which supplies system colors. | 
| Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 47 | class GtkThemeService : public ThemeService { | 
| Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 48 | public: | 
|  | 49 | // A list of integer keys for a separate PerDisplaySurfaceMap that keeps | 
|  | 50 | // what would otherwise be static icons on the X11 server. | 
|  | 51 | enum CairoDefaultIcon { | 
|  | 52 | NATIVE_FAVICON = 1, | 
|  | 53 | CHROME_FAVICON, | 
|  | 54 | NATIVE_FOLDER, | 
|  | 55 | CHROME_FOLDER | 
|  | 56 | }; | 
|  | 57 |  | 
|  | 58 | // Returns GtkThemeService, casted from our superclass. | 
|  | 59 | static GtkThemeService* GetFrom(Profile* profile); | 
|  | 60 |  | 
|  | 61 | GtkThemeService(); | 
|  | 62 | virtual ~GtkThemeService(); | 
|  | 63 |  | 
|  | 64 | // Calls |observer|.Observe() for the browser theme with this provider as the | 
|  | 65 | // source. | 
|  | 66 | void InitThemesFor(content::NotificationObserver* observer); | 
|  | 67 |  | 
|  | 68 | // Overridden from ThemeService: | 
|  | 69 | // | 
|  | 70 | // Sets that we aren't using the system theme, then calls | 
|  | 71 | // ThemeService's implementation. | 
|  | 72 | virtual void Init(Profile* profile) OVERRIDE; | 
|  | 73 | virtual gfx::ImageSkia* GetImageSkiaNamed(int id) const OVERRIDE; | 
|  | 74 | virtual gfx::Image GetImageNamed(int id) const OVERRIDE; | 
|  | 75 | virtual SkColor GetColor(int id) const OVERRIDE; | 
|  | 76 | virtual bool HasCustomImage(int id) const OVERRIDE; | 
|  | 77 | virtual void SetTheme(const extensions::Extension* extension) OVERRIDE; | 
|  | 78 | virtual void UseDefaultTheme() OVERRIDE; | 
|  | 79 | virtual void SetNativeTheme() OVERRIDE; | 
|  | 80 | virtual bool UsingDefaultTheme() const OVERRIDE; | 
|  | 81 | virtual bool UsingNativeTheme() const OVERRIDE; | 
| Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 82 | virtual bool ShouldInitWithNativeTheme() const OVERRIDE; | 
| Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 83 |  | 
| Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 84 | // Creates a GtkChromeButton instance, registered with this theme provider, | 
|  | 85 | // with a "destroy" signal to remove it from our internal list when it goes | 
|  | 86 | // away. | 
|  | 87 | GtkWidget* BuildChromeButton(); | 
|  | 88 |  | 
|  | 89 | // Creates a GtkChromeLinkButton instance. We update its state as theme | 
|  | 90 | // changes, and listen for its destruction. | 
|  | 91 | GtkWidget* BuildChromeLinkButton(const std::string& text); | 
|  | 92 |  | 
|  | 93 | // Builds a GtkLabel that is |color| in chrome theme mode, and the normal | 
|  | 94 | // text color in gtk-mode. Like the previous two calls, listens for the | 
|  | 95 | // object's destruction. | 
|  | 96 | GtkWidget* BuildLabel(const std::string& text, const GdkColor& color); | 
|  | 97 |  | 
|  | 98 | // Creates a theme-aware vertical separator widget. | 
|  | 99 | GtkWidget* CreateToolbarSeparator(); | 
|  | 100 |  | 
|  | 101 | // A wrapper around ui::ThemeProvider::GetColor, transforming the result to a | 
|  | 102 | // GdkColor. | 
|  | 103 | GdkColor GetGdkColor(int id) const; | 
|  | 104 |  | 
|  | 105 | // A weighted average between the text color and the background color of a | 
|  | 106 | // label. Used for borders between GTK stuff and the webcontent. | 
|  | 107 | GdkColor GetBorderColor() const; | 
|  | 108 |  | 
|  | 109 | // Returns a set of icons tinted for different GtkStateTypes based on the | 
|  | 110 | // label colors for the IDR resource |id|. | 
|  | 111 | GtkIconSet* GetIconSetForId(int id) const; | 
|  | 112 |  | 
|  | 113 | // This method returns the colors webkit will use for the scrollbars. When no | 
|  | 114 | // colors are specified by the GTK+ theme, this function averages of the | 
|  | 115 | // thumb part and of the track colors. | 
|  | 116 | void GetScrollbarColors(GdkColor* thumb_active_color, | 
|  | 117 | GdkColor* thumb_inactive_color, | 
|  | 118 | GdkColor* track_color); | 
|  | 119 |  | 
|  | 120 | // Expose the inner label. Only used for testing. | 
|  | 121 | GtkWidget* fake_label() { return fake_label_.get(); } | 
|  | 122 |  | 
|  | 123 | // Returns colors that we pass to webkit to match the system theme. | 
|  | 124 | SkColor get_focus_ring_color() const { return focus_ring_color_; } | 
|  | 125 | SkColor get_thumb_active_color() const { return thumb_active_color_; } | 
|  | 126 | SkColor get_thumb_inactive_color() const { return thumb_inactive_color_; } | 
|  | 127 | SkColor get_track_color() const { return track_color_; } | 
|  | 128 | SkColor get_active_selection_bg_color() const { | 
|  | 129 | return active_selection_bg_color_; | 
|  | 130 | } | 
|  | 131 | SkColor get_active_selection_fg_color() const { | 
|  | 132 | return active_selection_fg_color_; | 
|  | 133 | } | 
|  | 134 | SkColor get_inactive_selection_bg_color() const { | 
|  | 135 | return inactive_selection_bg_color_; | 
|  | 136 | } | 
|  | 137 | SkColor get_inactive_selection_fg_color() const { | 
|  | 138 | return inactive_selection_fg_color_; | 
|  | 139 | } | 
|  | 140 | SkColor get_location_bar_text_color() const { | 
|  | 141 | return location_bar_text_color_; | 
|  | 142 | } | 
|  | 143 | SkColor get_location_bar_bg_color() const { | 
|  | 144 | return location_bar_bg_color_; | 
|  | 145 | } | 
|  | 146 |  | 
|  | 147 | // These functions return an image that is not owned by the caller and should | 
|  | 148 | // not be deleted. If |native| is true, get the GTK_STOCK version of the | 
|  | 149 | // icon. | 
|  | 150 | static gfx::Image GetFolderIcon(bool native); | 
|  | 151 | static gfx::Image GetDefaultFavicon(bool native); | 
|  | 152 |  | 
|  | 153 | // Whether we use the GTK theme by default in the current desktop | 
|  | 154 | // environment. Returns true when we GTK defaults to on. | 
|  | 155 | static bool DefaultUsesSystemTheme(); | 
|  | 156 |  | 
|  | 157 | private: | 
|  | 158 | typedef std::map<int, SkColor> ColorMap; | 
|  | 159 | typedef std::map<int, color_utils::HSL> TintMap; | 
|  | 160 | typedef std::map<int, gfx::Image*> ImageCache; | 
|  | 161 |  | 
| Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 162 | // Load theme data from preferences, possibly picking colors from GTK. | 
|  | 163 | virtual void LoadThemePrefs() OVERRIDE; | 
|  | 164 |  | 
|  | 165 | // Let all the browser views know that themes have changed. | 
|  | 166 | virtual void NotifyThemeChanged() OVERRIDE; | 
|  | 167 |  | 
|  | 168 | // Additionally frees the CairoCachedSurfaces. | 
|  | 169 | virtual void FreePlatformCaches() OVERRIDE; | 
|  | 170 |  | 
| Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 171 | // Gets the name of the current icon theme and passes it to our low level XDG | 
|  | 172 | // integration. | 
|  | 173 | void SetXDGIconTheme(); | 
|  | 174 |  | 
| Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 175 | // Extracts colors and tints from the GTK theme, both for the | 
|  | 176 | // ThemeService interface and the colors we send to webkit. | 
|  | 177 | void LoadGtkValues(); | 
|  | 178 |  | 
|  | 179 | // Reads in explicit theme frame colors from the ChromeGtkFrame style class | 
|  | 180 | // or generates them per our fallback algorithm. | 
|  | 181 | GdkColor BuildFrameColors(GtkStyle* frame_style); | 
|  | 182 |  | 
|  | 183 | // Sets the values that we send to webkit to safe defaults. | 
|  | 184 | void LoadDefaultValues(); | 
|  | 185 |  | 
|  | 186 | // Builds all of the tinted menus images needed for custom buttons. This is | 
|  | 187 | // always called on style-set even if we aren't using the gtk-theme because | 
|  | 188 | // the menus are always rendered with gtk colors. | 
|  | 189 | void RebuildMenuIconSets(); | 
|  | 190 |  | 
|  | 191 | // Sets the underlying theme colors/tints from a GTK color. | 
|  | 192 | void SetThemeColorFromGtk(int id, const GdkColor* color); | 
|  | 193 | void SetThemeTintFromGtk(int id, const GdkColor* color); | 
|  | 194 |  | 
|  | 195 | // Creates and returns a frame color, either using |gtk_base| verbatim if | 
|  | 196 | // non-NULL, or tinting |base| with |tint|. Also sets |color_id| and | 
|  | 197 | // |tint_id| to the returned color. | 
|  | 198 | GdkColor BuildAndSetFrameColor(const GdkColor* base, | 
|  | 199 | const GdkColor* gtk_base, | 
|  | 200 | const color_utils::HSL& tint, | 
|  | 201 | int color_id, | 
|  | 202 | int tint_id); | 
|  | 203 |  | 
|  | 204 | // Frees all the created GtkIconSets we use for the chrome menu. | 
|  | 205 | void FreeIconSets(); | 
|  | 206 |  | 
|  | 207 | // Lazily generates each bitmap used in the gtk theme. | 
|  | 208 | SkBitmap GenerateGtkThemeBitmap(int id) const; | 
|  | 209 |  | 
|  | 210 | // Creates a GTK+ version of IDR_THEME_FRAME. Instead of tinting, this | 
|  | 211 | // creates a theme configurable gradient ending with |color_id| at the | 
|  | 212 | // bottom, and |gradient_name| at the top if that color is specified in the | 
|  | 213 | // theme. | 
|  | 214 | SkBitmap GenerateFrameImage(int color_id, | 
|  | 215 | const char* gradient_name) const; | 
|  | 216 |  | 
|  | 217 | // Takes the base frame image |base_id| and tints it with |tint_id|. | 
|  | 218 | SkBitmap GenerateTabImage(int base_id) const; | 
|  | 219 |  | 
|  | 220 | // Tints an icon based on tint. | 
|  | 221 | SkBitmap GenerateTintedIcon(int base_id, | 
|  | 222 | const color_utils::HSL& tint) const; | 
|  | 223 |  | 
|  | 224 | // Returns the tint for buttons that contrasts with the normal window | 
|  | 225 | // background color. | 
|  | 226 | void GetNormalButtonTintHSL(color_utils::HSL* tint) const; | 
|  | 227 |  | 
|  | 228 | // Returns a tint that's the color of the current normal text in an entry. | 
|  | 229 | void GetNormalEntryForegroundHSL(color_utils::HSL* tint) const; | 
|  | 230 |  | 
|  | 231 | // Returns a tint that's the color of the current highlighted text in an | 
|  | 232 | // entry. | 
|  | 233 | void GetSelectedEntryForegroundHSL(color_utils::HSL* tint) const; | 
|  | 234 |  | 
|  | 235 | // Handles signal from GTK that our theme has been changed. | 
|  | 236 | CHROMEGTK_CALLBACK_1(GtkThemeService, void, OnStyleSet, GtkStyle*); | 
|  | 237 |  | 
|  | 238 | // A notification from various GObject destructors that we should | 
|  | 239 | // remove it from our internal list. | 
|  | 240 | CHROMEGTK_CALLBACK_0(GtkThemeService, void, OnDestroyChromeButton); | 
|  | 241 | CHROMEGTK_CALLBACK_0(GtkThemeService, void, OnDestroyChromeLinkButton); | 
|  | 242 | CHROMEGTK_CALLBACK_0(GtkThemeService, void, OnDestroyLabel); | 
|  | 243 |  | 
|  | 244 | CHROMEGTK_CALLBACK_1(GtkThemeService, gboolean, OnSeparatorExpose, | 
|  | 245 | GdkEventExpose*); | 
|  | 246 |  | 
| Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 247 | void OnUsesSystemThemeChanged(); | 
|  | 248 |  | 
| Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 249 | // Whether we should be using gtk rendering. | 
|  | 250 | bool use_gtk_; | 
|  | 251 |  | 
|  | 252 | // GtkWidgets that exist only so we can look at their properties (and take | 
|  | 253 | // their colors). | 
|  | 254 | GtkWidget* fake_window_; | 
|  | 255 | GtkWidget* fake_frame_; | 
|  | 256 | ui::OwnedWidgetGtk fake_label_; | 
|  | 257 | ui::OwnedWidgetGtk fake_entry_; | 
|  | 258 | ui::OwnedWidgetGtk fake_menu_item_; | 
|  | 259 |  | 
|  | 260 | // A list of diferent types of widgets that we hold on to these to notify | 
|  | 261 | // them of theme changes. We do not own these and listen for their | 
|  | 262 | // destruction via OnDestory{ChromeButton,ChromeLinkButton,Label}. | 
|  | 263 | std::vector<GtkWidget*> chrome_buttons_; | 
|  | 264 | std::vector<GtkWidget*> link_buttons_; | 
|  | 265 | std::map<GtkWidget*, GdkColor> labels_; | 
|  | 266 |  | 
|  | 267 | // Tracks all the signals we have connected to on various widgets. | 
|  | 268 | scoped_ptr<ui::GtkSignalRegistrar> signals_; | 
|  | 269 |  | 
|  | 270 | // Tints and colors calculated by LoadGtkValues() that are given to the | 
|  | 271 | // caller while |use_gtk_| is true. | 
|  | 272 | ColorMap colors_; | 
|  | 273 | TintMap tints_; | 
|  | 274 |  | 
|  | 275 | // Colors used to tint certain icons. | 
|  | 276 | color_utils::HSL button_tint_; | 
|  | 277 | color_utils::HSL entry_tint_; | 
|  | 278 | color_utils::HSL selected_entry_tint_; | 
|  | 279 |  | 
|  | 280 | // Colors that we pass to WebKit. These are generated each time the theme | 
|  | 281 | // changes. | 
|  | 282 | SkColor focus_ring_color_; | 
|  | 283 | SkColor thumb_active_color_; | 
|  | 284 | SkColor thumb_inactive_color_; | 
|  | 285 | SkColor track_color_; | 
|  | 286 | SkColor active_selection_bg_color_; | 
|  | 287 | SkColor active_selection_fg_color_; | 
|  | 288 | SkColor inactive_selection_bg_color_; | 
|  | 289 | SkColor inactive_selection_fg_color_; | 
|  | 290 | SkColor location_bar_bg_color_; | 
|  | 291 | SkColor location_bar_text_color_; | 
|  | 292 |  | 
|  | 293 | // A GtkIconSet that has the tinted icons for the NORMAL and PRELIGHT states | 
|  | 294 | // of the IDR_FULLSCREEN_MENU_BUTTON tinted to the respective menu item label | 
|  | 295 | // colors. | 
|  | 296 | GtkIconSet* fullscreen_icon_set_; | 
|  | 297 |  | 
|  | 298 | // Image cache of lazily created images, created when requested by | 
|  | 299 | // GetImageNamed(). | 
|  | 300 | mutable ImageCache gtk_images_; | 
|  | 301 |  | 
|  | 302 | PrefChangeRegistrar registrar_; | 
|  | 303 |  | 
|  | 304 | // This is a dummy widget that only exists so we have something to pass to | 
|  | 305 | // gtk_widget_render_icon(). | 
|  | 306 | static GtkWidget* icon_widget_; | 
|  | 307 |  | 
|  | 308 | // The default folder icon and default bookmark icon for the GTK theme. | 
|  | 309 | // These are static because the system can only have one theme at a time. | 
|  | 310 | // They are cached when they are requested the first time, and cleared when | 
|  | 311 | // the system theme changes. | 
|  | 312 | static base::LazyInstance<gfx::Image> default_folder_icon_; | 
|  | 313 | static base::LazyInstance<gfx::Image> default_bookmark_icon_; | 
|  | 314 | }; | 
|  | 315 |  | 
|  | 316 | #endif  // CHROME_BROWSER_UI_GTK_GTK_THEME_SERVICE_H_ |