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_ |