Themes are in a simple XML-subset format. There are multiple versions of the theme format, and a given theme can support more than one format. Version 1: THEMEDIR/metacity-1/metacity-theme-1.xml (original metacity format) Version 2: THEMEDIR/metacity-1/metacity-theme-2.xml Version 3: THEMEDIR/metacity-1/metacity-theme-3.xml The subdirectory name is "metacity-1" in all versions. As you might expect, older versions of marco will not understand newer theme formats. However, newer versions will use old themes. Marco will always use the newest theme format it understands that the X server supports. Some format versions are only supported if you have the right X server features. Each format *requires* the corresponding filename. If you put version 2 format features in the metacity-1/metacity-theme-1.xml file, then marco will get angry. This document has separate sections for each format version. You may want to read the document in reverse order, since the base features are discussed under version 1. New Features in Theme Format Version 3.5 ======================================== Add support for app-menu button in window decorations. This was only used by Mutter and here is only to support this Theme Format Version. New Features in Theme Format Version 3.4 ======================================== An additional color type is added to pick up custom colors defined in the GTK+ theme's CSS: gtk:custom(name,fallback) where refers to a custom color defined with @define-color in the GTK+ theme, and provides an alternative color definition in case the color referenced by is not found. New Features in Theme Format Version 3.3 ======================================== Add two additional button background functions - left_single_background and right_single_background - for button groups with just a single button. There are now additional frame states to style left/right tiled windows differently ("tiled_left", "tiled_right", "tiled_left_and_shaded", "tiled_right_and_shaded") New Features in Theme Format Version 3.2 ======================================== A new window type 'attached' is added for modal dialogs which are attached to their parent window. (When the attach_modal_dialogs preference is turned on.) If no style is defined for the 'attached' window type, the 'border' window type will be used instead. New Features in Theme Format Version 3.1 ======================================== Additional predefined variables are added for positioning expressions: frame_x_center: the X center of the entire frame, with respect to the piece currently being drawn. frame_y_center: the Y center of the entire frame, with respect to the piece currently being drawn. The element now supports an "ellipsize_width" attribute. When specified, this gives a width at which to ellipsize the title. If not specified, the title will simply be clipped to the title area. New Features in Theme Format Version 3 ====================================== Format version 3 has exactly one new feature; any element in the file can now have a version attribute: version="[<|<=|=>|>] MAJOR.MINOR" (< and > should be to be entity escaped as < and >). If this version check is not met, then the element and its children will be ignored. This allows having alternate sections of the theme file for older and newer version of the Metacity theme format. When placed on the toplevel <metacity_theme> element, an unsatisfied version check will not just cause the contents of the file to be ignored, it will also cause the lookup of a theme file to proceed on and look for an older format 2 or format 1 file. This allows making a metacity-theme-3.xml file that is only used the format version 3.2 or newer is supported, and using metacity-theme-1.xml for older window managers. New Features in Theme Format Version 2 ====================================== The optional attributes rounded_top_left, rounded_top_right, rounded_bottom_left and rounded_bottom_right on <frame_geometry> should now be the radius of the corner in pixels. You may still use the values "false" for 0 and "true" for 5, which means v1 values will still work just fine. <frame_geometry> has a new optional attribute, hide_buttons. If this is true, no buttons will be displayed on the titlebar. Anywhere you can use a positive integer, you can use an integer constant. As well as constant integers and reals, you may define constant colours, thus: <constant name="RevoltingPink" value="#FF00FF"/> <constant name="Background" value="gtk:bg[NORMAL]"/> <frame_style> has two new optional attributes, background and alpha. If you specify alpha, you must specify background. background is a colour used for the background of the frame. alpha is the transparency as a real between 0.0 and 1.0. If the current X server does not support alpha channels, the value is ignored. The filename attribute of <image> may begin with "theme:". If so, the rest of the string is the name of a theme icon. The 64x64 version of the icon is used, except for fallback mini_icons, which use the 16x16 version. This does not affect ordinary resizing. For example: <button function="close" state="normal"> <draw_ops> <include name="active_button"/> <image filename="theme:mate-logout" x="2" y="2" width="width-4" height="height-4"/> <!-- Note: not "theme:mate-logout.png" or similar. --> </draw_ops> </button> <menu_icon>s are parsed but ignored. Fallback icons can be specified using <fallback>. There are two optional arguments, icon and mini_icon. The values of these arguments are identical to that of the filename attribute of <image>. Fallback icons are used when a window does not supply its own icon. If a fallback icon is not specified with <fallback>, Marco will use a built-in icon, as in metacity-theme-1. The <arc> element, as well as the original start_angle and end_angle attributes, may be given from and to attributes. The values of these attributes are given in degrees clockwise, with 0 being straight up. For example: <arc from="0.0" to="90.0" filled="true" color="#FF00FF" x="0" y="5" width="15" height="15"/> <frame state="shaded"> may now take an optional resize attribute, with the same interpretation as the resize attribute on <frame state="normal">. If this attribute is omitted for state="shaded", it defaults to "both". (If it is omitted for state="normal", it remains an error.) In addition to the four <button> functions which are required in metacity-theme-1, there are six new functions in metacity-theme-2: shade, unshade, above, unabove, stick and unstick. Overview of Theme Format Version 1 ================================== <?xml version="1.0"?> <metacity_theme> <!-- Only one info section is allowed --> <info> <name>Foo</name> <author>Foo P. Bar</author> <copyright>whoever, 2002</copyright> <date>Jan 31 2005</date> <description>A sentence about the theme.</description> </info> <!-- define a frame geometry to be referenced later --> <!-- frame_geometry has an optional has_title attribute which determines whether the title text height is included in the height calculation. if not specified, defaults to true. It also has an optional text_size="medium" attribute (same sizes as with Pango markup, xx-small thru medium thru xx-large) Finally it has optional args rounded_top_left=true, rounded_top_right=true, rounded_bottom_left=true, rounded_bottom_right=true. --> <frame_geometry name="normal" has_title="true" title_scale="medium"> <distance name="left_width" value="6"/> <distance name="right_width" value="6"/> <distance name="bottom_height" value="7"/> <distance name="left_titlebar_edge" value="6"/> <distance name="right_titlebar_edge" value="6"/> <distance name="button_width" value="17"/> <distance name="button_height" value="17"/> <!-- alternative to button_width button_height distances --> <aspect_ratio name="button" value="1.0"/> <distance name="title_vertical_pad" value="4"/> <border name="title_border" left="3" right="12" top="4" bottom="3"/> <border name="button_border" left="0" right="0" top="1" bottom="1"/> </frame_geometry> <!-- inheritance is allowed; simply overwrites values from parent --> <frame_geometry name="borderless" parent="normal"> <distance name="left_width" value="0"/> <distance name="right_width" value="0"/> <distance name="bottom_height" value="0"/> <distance name="left_titlebar_edge" value="0"/> <distance name="right_titlebar_edge" value="0"/> </frame_geometry> <!-- define a constant to use in positions/sizes of draw operations; constant names must start with a capital letter. --> <constant name="LineOffset" value="3"/> <!-- define drawing operations to be referenced later; these draw-op lists can also be placed inline. Positions/lengths are given as expressions. Operators are: +,-,*,/,%,`max`,`min` All operators are infix including `max` and `min`, i.e. "2 `max` 5" Some variables are predefined, and constants can also be used. Variables are: width - width of target area height - height of target area object_width - natural width of object being drawn object_height - natural height of object being drawn left_width - distance from left of frame to client window right_width - distance from right of frame to client window top_height - distance from top of frame to client window bottom_height - distance from bottom of frame to client window mini_icon_width - width of mini icon for window mini_icon_height - height of mini icon icon_width - width of large icon icon_height - height of large icon title_width - width of title text title_height - height of title text All these are always defined, except object_width/object_height which only exists for <image> right now. --> <draw_ops name="demo_all_ops"> <line color="#00FF00" x1="LineOffset" y1="0" x2="0" y2="height"/> <line color="gtk:fg[NORMAL]" x1="width - 1" y1="0" x2="width - 1" y2="height" width="3" dash_on_length="2" dash_off_length="3"/> <rectangle color="blend/gtk:fg[NORMAL]/gtk:bg[NORMAL]/0.7" x="0" y="0" width="width - 1" height="height - 1" filled="true"/> <arc color="dark gray" x="0" y="0" width="width - 1" height="height - 1" filled="false" start_angle="30" extent_angle="180"/> <tint color="orange" alpha="0.5" x="0" y="0" width="width" height="height"/> <!-- may be vertical, horizontal, diagonal --> <gradient type="diagonal" x="10" y="30" width="width / 3" height="height / 4"> <!-- any number of colors allowed here. A color can be a color name like "blue" (look at gcolorsel), a hex color as in HTML (#FFBB99), or a color from the gtk theme given as "gtk:base[NORMAL]", "gtk:fg[ACTIVE]", etc. --> <color value="gtk:fg[SELECTED]"/> <!-- color obtained by a 0.5 alpha composite of the second color onto the first --> <color value="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.5"/> </gradient> <!-- image has an optional colorize="#color" attribute to give the image a certain color --> <image filename="foo.png" alpha="0.7" x="10" y="30" width="width / 3" height="height / 4"/> <gtk_arrow state="normal" shadow="in" arrow="up" filled="true" x="2" y="2" width="width - 4" height="height - 4"/> <gtk_box state="normal" shadow="out" x="2" y="2" width="width - 4" height="height - 4"/> <gtk_vline state="normal" x="2" y1="0" y2="height"/> <!-- window's icon --> <icon alpha="0.7" x="10" y="30" width="width / 3" height="height / 4"/> <!-- window's title --> <title color="gtk:text[NORMAL]" x="20" y="30"/> <!-- include another draw ops list; has optional x/y/width/height attrs --> <include name="some_other_draw_ops"/> <!-- tile another draw ops list; has optional x/y/width/height/tile_xoffset/tile_yoffset --> <tile name="some_other_draw_ops" tile_width="10" tile_height="10"/> </draw_ops> <frame_style name="normal" geometry="normal"> <!-- How to draw each piece of the frame. For each piece, a draw_ops can be given inline or referenced by name. If a piece is omitted, then nothing will be drawn for that piece. For each piece, the "width" and "height" variables in coordinate expressions refers to the dimensions of the piece, the origin is at the top left of the piece. So <rectangle x="0" y="0" width="width-1" height="height-1"/> will outline a piece. --> <piece position="entire_background" draw_ops="demo_all_ops"/> <piece position="left_titlebar_edge"> <draw_ops> <line color="#00FF00" x1="0" y1="0" x2="0" y2="height"/> </draw_ops> </piece> <!-- The complete list of frame pieces: entire_background: whole frame titlebar: entire area above the app's window titlebar_middle: area of titlebar_background not considered part of an edge left_titlebar_edge: left side of titlebar background right_titlebar_edge: right side of titlebar background top_titlebar_edge: top side of titlebar background bottom_titlebar_edge: bottom side of titlebar background title: the title area (doesn't include buttons) left_edge: left edge of the frame right_edge: right edge of the frame bottom_edge: bottom edge of the frame overlay: same area as entire_background, but drawn after drawing all sub-pieces instead of before --> <!-- For buttons, drawing methods have to be provided for each of three states: normal, pressed, prelight and the button function or position must be provided: close, maximize, minimize, menu, left_left_background, left_middle_background, left_right_background, right_left_background, right_middle_background, right_right_background So a working theme needs 3*4 = 12 button declarations and a theme may have up to 3*10 = 30 button declarations in order to handle button-rearrangement preferences. (The name "function" for the attribute is from before the background values existed.) --> <button function="close" state="normal" draw_ops="previously_named"/> <button function="menu" state="normal"> <draw_ops> <icon alpha="0.7" x="0" y="0" width="object_width" height="object_height"/> </draw_ops> </button> </frame_style> <!-- styles can inherit from each other with the parent="" attribute. In a subclass anything can be re-specified to override the parent style. --> <frame_style name="focused" parent="normal"> <piece position="title"> <draw_ops> <rectangle color="gtk:bg[SELECTED]" x="0" y="0" width="width-1" height="height-1"/> <title color="gtk:fg[SELECTED]" x="(width - title_width) / 2" y="(height - title_height) / 2"/> </draw_ops> </piece> </frame_style> <!-- Maps styles to states of frame. Focus: yes (focused), no (not focused) Window states: normal, maximized, shaded, maximized_and_shaded Window resizability: none, vertical, horizontal, both Everything unspecified just does the same as unfocused/normal/both. only state="normal" needs a resize="" attribute. --> <frame_style_set name="normal"> <frame focus="yes" state="normal" resize="both" style="focused"/> <frame focus="no" state="normal" resize="both" style="normal"/> </frame_style_set> <!-- Each window type needs a style set Types: normal, dialog, modal_dialog, menu, utility, border --> <window type="normal" style_set="normal"/> <!-- For menu icons, drawing methods are needed for the same four types as the buttons, and GTK states (insensitive,prelight,normal,etc.) --> <menu_icon function="close" state="normal" draw_ops="previously_named"/> </metacity_theme>