|  | # Linux GTK Theme Integration | 
|  |  | 
|  | The GTK+ port of Chromium has a mode where we try to match the user's GTK theme | 
|  | (which can be enabled under Wrench -> Options -> Personal Stuff -> Set to GTK+ | 
|  | theme). The heuristics often don't pick good colors due to a lack of information | 
|  | in the GTK themes. | 
|  |  | 
|  | Starting in Chrome 9, we're providing a new way for theme authors to control our | 
|  | GTK+ theming mode. I am not sure of the earliest build these showed up in, but I | 
|  | know 9.0.597 works. | 
|  |  | 
|  | ## Describing the previous heuristics | 
|  |  | 
|  | The frame heuristics were simple. Query the `bg[SELECTED]` and `bg[INSENSITIVE]` | 
|  | colors on the `MetaFrames` class and darken them slightly. This usually worked | 
|  | OK until the rise of themes that try to make a unified titlebar/menubar look. At | 
|  | roughly that time, it seems that people stopped specifying color information for | 
|  | the `MetaFrames` class and this has lead to the very orange chrome frame on | 
|  | Maverick. | 
|  |  | 
|  | `MetaFrames` is (was?) a class that was used to communicate frame color data to | 
|  | the window manager around the Hardy days. (It's still defined in most of | 
|  | [XFCE's themes](http://packages.ubuntu.com/maverick/gtk2-engines-xfce)). In | 
|  | chrome's implementation, `MetaFrames` derives from `GtkWindow`. | 
|  |  | 
|  | If you are happy with the defaults that chrome has picked, no action is | 
|  | necessary on the part of the theme author. | 
|  |  | 
|  | ## Introducing `ChromeGtkFrame` | 
|  |  | 
|  | For cases where you want control of the colors chrome uses, Chrome gives you a | 
|  | number of style properties for injecting colors and other information about how | 
|  | to draw the frame. For example, here's the proposed modifications to Ubuntu's | 
|  | Ambiance: | 
|  |  | 
|  | ``` | 
|  | style "chrome-gtk-frame" | 
|  | { | 
|  | ChromeGtkFrame::frame-color = @fg_color | 
|  | ChromeGtkFrame::inactive-frame-color = lighter(@fg_color) | 
|  |  | 
|  | ChromeGtkFrame::frame-gradient-size = 16 | 
|  | ChromeGtkFrame::frame-gradient-color = "#5c5b56" | 
|  |  | 
|  | ChromeGtkFrame::scrollbar-trough-color = @bg_color | 
|  | ChromeGtkFrame::scrollbar-slider-prelight-color = "#F8F6F2" | 
|  | ChromeGtkFrame::scrollbar-slider-normal-color = "#E7E0D3" | 
|  | } | 
|  |  | 
|  | class "ChromeGtkFrame" style "chrome-gtk-frame" | 
|  | ``` | 
|  |  | 
|  | ### Frame color properties | 
|  |  | 
|  | These are the frame's main solid color. | 
|  |  | 
|  | | **Property** | **Type** | **Description** | **If unspecified** | | 
|  | |:-------------|:---------|:----------------|:-------------------| | 
|  | | `frame-color` | `GdkColor` | The main color of active chrome windows. | Darkens `MetaFrame::bg[SELECTED]` | | 
|  | | `inactive-frame-color` | `GdkColor` | The main color of inactive chrome windows. | Darkens `MetaFrame::bg[INSENSITIVE]` | | 
|  | | `incognito-frame-color` | `GdkColor` | The main color of active incognito windows. | Tints `frame-color` by the default incognito tint | | 
|  | | `incognito-inactive-frame-color` | `GdkColor` | The main color of inactive incognito windows. | Tints `inactive-frame-color` by the default incognito tint | | 
|  |  | 
|  | ### Frame gradient properties | 
|  |  | 
|  | Chrome's frame (along with many normal window manager themes) have a slight | 
|  | gradient at the top, before filling the rest of the frame background image with | 
|  | a solid color. For example, the top `frame-gradient-size` pixels would be a | 
|  | gradient starting from `frame-gradient-color` at the top to `frame-color` at the | 
|  | bottom, with the rest of the frame being filled with `frame-color`. | 
|  |  | 
|  | | **Property** | **Type** | **Description** | **If unspecified** | | 
|  | |:-------------|:---------|:----------------|:-------------------| | 
|  | | `frame-gradient-size` | Integers 0 through 128 | How large the gradient should be. Set to zero to disable drawing a gradient | Defaults to 16 pixels tall | | 
|  | | `frame-gradient-color` | `GdkColor` | Top color of the gradient | Lightens `frame-color` | | 
|  | | `inactive-frame-gradient-color` | `GdkColor` | Top color of the inactive gradient | Lightents `inactive-frame-color` | | 
|  | | `incognito-frame-gradient-color` | `GdkColor` | Top color of the incognito gradient | Lightens `incognito-frame-color` | | 
|  | | `incognito-inactive-frame-gradient-color` | `GdkColor` | Top color of the incognito inactive gradient. | Lightens `incognito-inactive-frame-color` | | 
|  |  | 
|  | ### Scrollbar control | 
|  |  | 
|  | Because widget rendering is done in a separate, sandboxed process that doesn't | 
|  | have access to the X server or the filesystem, there's no current way to do | 
|  | GTK+ widget rendering. We instead pass WebKit a few colors and let it draw a | 
|  | default scrollbar. We have a very | 
|  | [complex fallback](http://git.chromium.org/gitweb/?p=chromium.git;a=blob;f=chrome/browser/gtk/gtk_theme_provider.cc;h=a57ab6b182b915192c84177f1a574914c44e2e71;hb=3f873177e192f5c6b66ae591b8b7205d8a707918#l424) | 
|  | where we render the widget and then average colors if this information isn't | 
|  | provided. | 
|  |  | 
|  | | **Property** | **Type** | **Description** | | 
|  | |:-------------|:---------|:----------------| | 
|  | | `scrollbar-slider-prelight-color` | `GdkColor` | Color of the slider on mouse hover. | | 
|  | | `scrollbar-slider-normal-color` | `GdkColor` | Color of the slider otherwise | | 
|  | | `scrollbar-trough-color` | `GdkColor` | Color of the scrollbar trough | | 
|  |  | 
|  | ## Anticipated Q&A | 
|  |  | 
|  | ### Will you patch themes upstream? | 
|  |  | 
|  | I am at the very least hoping we can get Radiance and Ambiance patches since we | 
|  | make very poor frame decisions on those themes, and hopefully a few others. | 
|  |  | 
|  | ### How about control over the min/max/close buttons? | 
|  |  | 
|  | I actually tried this locally. There's a sort of uncanny valley effect going on; | 
|  | as the frame looks more native, it's more obvious that it isn't behaving like a | 
|  | native frame. (Also my implementation added a startup time hit.) | 
|  |  | 
|  | ### Why use style properties instead of (i.e.) bg[STATE]? | 
|  |  | 
|  | There's no way to distinguish between colors set on different classes. Using | 
|  | style properties allows us to be backwards compatible and maintain the | 
|  | heuristics since not everyone is going to modify their themes for chromium (and | 
|  | the heuristics do a reasonable job). | 
|  |  | 
|  | ### Why now? | 
|  |  | 
|  | *   I (erg@) was putting off major changes to the window frame stuff in | 
|  | anticipation of finally being able to use GTK+'s theme rendering for the | 
|  | window border with client side decorations, but client side decorations | 
|  | either isn't happening or isn't happening anytime soon, so there's no | 
|  | justification for pushing this task off into the future. | 
|  | *   Chrome looks pretty bad under Ambiance on Maverick. | 
|  |  | 
|  | ### Details about `MetaFrames` and `ChromeGtkFrame` relationship and history? | 
|  |  | 
|  | `MetaFrames` is a class that was used in metacity to communicate color | 
|  | information to the window manager. During the Hardy Heron days, we slurped up | 
|  | the data and used it as a key part of our heuristics. At least on my Lucid Lynx | 
|  | machine, none of the GNOME GTK+ themes have `MetaFrames` styling. (As mentioned | 
|  | above, several of the XFCE themes do, though.) | 
|  |  | 
|  | Internally to chrome, our `ChromeGtkFrame` class inherits from `MetaFrames` | 
|  | (again, which inherits from `GtkWindow`) so any old themes that style the | 
|  | `MetaFrames` class are backwards compatible. |