Gtk Theme Creation Guide

author: Tim Orford      date: Jan 06

Contents

introduction
general widget properties
gtkrc files
widget examples
fonts
key bindings
engines
icons
cursors
further reading

introduction:

Gtk programmers will tell you that writing a gtk theme is easy. If you have a full understanding of how gtk is put together, then that may be so, but if you dont have an intimate knowledge of the gtk api and you want to change the visual appearance of your gtk apps then this document may hopefully save you some swearing while you go through the process of trial and error trying to figure out what works and what doesnt. Its not difficult stuff, but can appear to be somewhat random and non-intuitive due to its close correlation with the underlying widget structure.

This document applies only to Gtk2, although Gtk1.2 themes are quite similar.

Warning: this document is incomplete. The gnome.org tutorial may be useful.


theme browsing

LXAppearance is a great new tool for browsing gtk and icon themes. Also good are gtk-chtheme, and the older and slightly buggy gtk-theme-switch.

general widget properties:

There are several 'directives' to change the attributes of a widget.

There are several states a widget can be in, and you can set different colors, pixmaps and fonts for each state. These states are:


gtkrc files:

file location
rc files are named "gtkrc" and may be located in many places depending on how the system is configured. There will usually be a global repository somewhere such as /usr/share/themes/ where gtkrc files are contained within a subdirectory named after the theme. There is often a ~/.gtk-2.0/gtkrc file which may be either an rc file, a link to an rc file, or a stub containing an include of another gtkrc file.

colours:
colours can be specified in several different ways:
-by name: Gtk knows all names from the X color database /usr/lib/X11/rgb.txt
eg "red"
-one of the hexadecimal forms "#rrrrggggbbbb", "#rrrgggbbb", "#rrggbb", or "#rgb", where r, g and b are hex digits. They must be in quotes.
-as a triplet { r, g, b}, where r, g and b are either integers in the range 0-65635 or floats in the range 0.0-1.0.
eg {1.00, 0.00, 0.00} for red.

Gtk 2.10 introduced the "gtk-color-scheme" property. This contains a list of colours. gtk-color-scheme = "fg_color : white tooltip_bg_color: black" The meaning of the colour names is explained in http://live.gnome.org/GnomeArt/Tutorials/GtkThemes/SymbolicColors. Apparently this setting doesnt work under all circumstances.

binding styles to widget classes:
The syntax is of the form: class "GtkButton" style "my-button"
This would bind the my-button style to all instances of GtkButton.
Alternatively you can use the form: widget_class "*Text*" style "bright_yellow"
where a "*" can be used as a wildcard in the class string, in this example to bind the bright_yellow style to any widget with "Text" in its the name.
To select a widget class only if it is a child of a particular widget class, eg the header of a treeview. use this type of notation: widget_class "*TreeView*Button*" style "mystyle" Standard shell globbing is used, so * represents zero or more chars, and ? represents any single character.

RC styles bound with widget take precedence over RC styles bound with widget_class, which, in turn, take precedence over RC styles bound with class. If multiple declarations are made for the same widget class, the later one takes priority. This can be overridden by specifying a priority highest, rc, theme, application, gtk, lowest
eg: widget_class "*Button*" style : highest "mystyle".
This aspect is easily overlooked, and can be a big source of problems if you are not careful.

application specific styles:
if the application developer has explicitly exposed an element, it can be styled by specifying that element name in a gtkrc file.
eg if an app has an element called 'funky bar', you can style it using: widget "funky bar" style "mystyle"

widget specific styles:
the gtk api docs list some 'style properties' which are specific to a certain widget type. You can include them in an rc file with the syntax: eg: GtkWidget::focus-line-width = 2
These properties are also applicable to child widget-types, so for example, as most widgets are derived from GtkWidget, style properties of GtkWidget can also be used for these other widgets.
A list of widget style properties can be obtained via the object hierarchy in the api documentation. A more convenient listing of these can be found at ajgenius.us.

toplevel declarations:
(taken from the official gtk2 documentation)

An RC file is a text file which is composed of a sequence of declarations. '#' characters delimit comments and the portion of a line after a '#' is ignored when parsing an RC file.

The possible toplevel declarations are:

binding name { ... }

Declares a binding set.

class pattern [ style | binding [ : priority ]] name

Specifies a style or binding set for a particular branch of the inheritance hierarchy.

include filename

Parses another file at this point. If filename is not an absolute filename, it is searched in the directories of the currently open RC files.

GTK+ also tries to load a locale-specific variant of the included file.

module_path path

Sets a path (a list of directories separated by colons) that will be searched for theme engines referenced in RC files.

pixmap_path path

Sets a path (a list of directories separated by colons) that will be searched for pixmaps referenced in RC files.

style name [ = parent ] { ... }

Declares a style.

widget pattern [ style | binding [ : priority ]] name

Specifies a style or binding set for a particular group of widgets by matching on the widget pathname.

widget_class pattern [ style | binding [ : priority ]] name

Specifies a style or binding set for a particular group of widgets by matching on the class pathname.


widget examples:

This information applies to the default gtk theme engine. Other engines may be slightly different and often have additional properties. The gnome.org wiki now has detailed theming information for each widget.

  • paned: (two windows with a handle in between)
  • statusbar:

    fonts:

    The font entry from gtk1 which used X-font-strings is no longer used. Gtk2 uses the font_name composite entry instead.
    eg: font_name = "Luxi Sans Bold Italic 9"
    The format is that of a pango string, so you can refer to the pango docs for details. There are three options you can specify, any of them being optional: font-family, style, size.

    Font-family is a comma separated list. Presumably a space in the font name is ok.

    Style includes such things as Bold. Separate multiple styles with a space.

    Size is in pts. You dont include "pts" in the string. Default size appears to be 10. Unfortunately you cannot specify a relative size such as a percentage.


    key bindings:

    Emacs keybindings such as Control-A and Control-E to move to the ends of lines can be enabled by adding the line:
    gtk-key-theme-name = "Emacs"

    Editing of menu accelerators by pressing an accelerator over the menu item is disabled by default. To enable, it, add:
    gtk-can-change-accels = 1
    This is a global option and cannot be made as part of a style declaration.

    By default, when a text entry widget gets focus, the entire contents are selected. To disable this behavior, and prevent the X selection being overwritten, add:
    gtk-entry-select-on-focus = 0

    In theory, keyboard shortcuts can be bound to internal application signals. Not sure of a practical use for this.

    binding name {
      bind key { 
        signalname (param, ...)
        ...
      }
      ...
    }
    


    engines:

    Owen Taylor on theme engines

    warning: gtk theme engines are low level code and using a buggy engine can crash your applications.

    There is a short chapter in the gnome app dev guide.

    Q: How to disable a theme engine for a widget style that inherits from another style?

    http://ajgenius.us/Gnome/Themes/Tutorials/index.php?id=ThemeEngines

    examples:


    icons:

    eg:
    pixmap_path "/path/to/icons" style "normal" { stock["gtk-close"] = {{"close-icon.png"}} stock["gtk-go-up"] = {{"up-icon.png"}} stock["gtk-home"] = {{"home-icon.png"}} stock["gtk-refresh"] = {{"refresh-icon.png"}} stock["gtk-zoom-in"] = {{"zoom-in-icon.png"}} stock["gtk-zoom-fit"] = {{"zoom-fit-icon.png"}} stock["gtk-jump-to"] = {{"jump-to-icon.png"}} stock["gtk-sort-ascending"] = {{"sort-icon.png"}} stock["gtk-help"] = {{"help-icon.png"}} stock["rox-show-hidden"] = {{"hidden-icon.png"}} stock["rox-show-details"] = {{"details-icon.png"}} stock["rox-select"] = {{"select-icon.png"}} } See the list of stock icons in the Gtk documentation for details.

    You can specify the icon theme using: gtk-icon-theme-name = "Tango". The name of the icon theme can be found in the index.theme file in the theme folder (probably ~/.icons or /usr/share/icons).

    To change the size of the icons: gtk-toolbar-icon-size = 16,16

    To change the look of certain apps' toolbars (like gedit), add one of the following lines: gtk-toolbar-style = GTK_TOOLBAR_ICONS #Only icons gtk-toolbar-style = GTK_TOOLBAR_TEXT #Only text gtk-toolbar-style = GTK_TOOLBAR_BOTH #Both icons and text gtk-toolbar-style = GTK_TOOLBAR_BOTH_HORIZ #Icons and text next to the icons


    cursors:

    this is not related to gtk, but you can change the mouse cursors. A list of available cursor sets can be seen at kdelook. Change the Inherits line in default/index.theme to one of the themes listed in /usr/share/cursors/ or similar. You can also use ~/.Xdefaults file as well.

    further reading:

    gtk tutorial
    gtk api ref
    theme tutorial