Understanding Rules

This page attempts to describe the 'rules' that appear in Awesome's config file and how they work.

Getting Started
When you first opened  to make your changes, you doubtless encountered this block of code:

awful.rules.rules = { -- All clients will match this rule. { rule = { }, properties = { border_width = beautiful.border_width, border_color = beautiful.border_normal, focus = true, keys = clientkeys, buttons = clientbuttons } }, { rule = { class = "MPlayer" }, properties = { floating = true } }, { rule = { class = "pinentry" }, properties = { floating = true } }, { rule = { class = "gimp" }, properties = { floating = true } }, -- Set Firefox to always map on tags number 2 of screen 1. -- { rule = { class = "Firefox" }, --  properties = { tag = tags[1][2] } }, }

We can vaguely guess what this does, but if we want to truly customize Awesome to meet our needs, we'll need to know more to be able to create our own rules.

The Basic Principle
Basically,  contains an array of instructions, each instruction having two parts.

The first part can be thought of as a "search pattern" which tells Awesome which window attributes you're interested in. The second part can be thought of as the "command" which tells Awesome what to do to the window once it's found one that matches the search pattern you specified.

Matching Windows:,,   and
Awesome can inspect windows for a variety of properties. There are four ways you can match against these properties:


 * To match a window, the window's properties must match all the properties specified in the array assigned to.
 * To match a window, the window's properties must match all the properties specified in the array assigned to.


 * To match a window, the window's properties must match one or more of the properties specified in the array assigned to.
 * To match a window, the window's properties must match one or more of the properties specified in the array assigned to.


 * Any window matching a  or   above is excluded if the window's properties match all of the properties specified in the array assigned to.
 * Any window matching a  or   above is excluded if the window's properties match all of the properties specified in the array assigned to.


 * Any window matching a  or   above is excluded if the window's properties match one or more of the properties specified in the array assigned to.
 * Any window matching a  or   above is excluded if the window's properties match one or more of the properties specified in the array assigned to.

The value of  et al is itself an array that names all the window properties you want Awesome to compare against. This array may be any length, including zero length (empty). Its syntax is as follows:

{ rule = { [ property = value [, property = value, ... ] ] } }

Where property is the name of a window property.

A  with zero properties (empty) will match all windows. An  with zero properties will exclude no windows.

Unlike, for example, rules in a network firewall, there is no early exit to rule processing. All  tests are applied to all windows; a window may be matched by more than one. For each  that matches a window, the corresponding modifications are applied.

For window properties that are strings, the property values you supply to  et al are compared to the window properties using the Lua   function, which performs sub-string and pattern matching. Thus, a  of the form   would match all windows where the character "x" appeared anywhere in the window's   property.

Modifying Windows: and
Once we've matched a window, we'll want to do things to it. There are two ways to tell Awesome how to alter a window.

By far the most common method, the  element is an array of window properties and values. For each value in the  array, Awesome assigns the value to the corresponding property in the matched window.

The syntax for  is as follows:

{ properties = { property = value [, property = value, ... ] } }

Where property is the name of a window property.

property can also be the name of a Lua function. The function is called with the Awesome client object as the first argument, and value as the second argument.

(It is unclear whether the  feature is deprecated.)

You can specify a Lua function to call when a window is matched; the window client is passed to the Lua function as an argument. This can be used to perform more complex operations than are possible using simple property assignment. Like,   takes an array, so you can specify any number of functions to be called against the matched window.

The syntax for  is as follows:

{ callback = { function [, function, ... ] }

Where function is any Lua function that accepts an Awesome client object as an argument.

Window Properties
A complete list of all the window properties that Awesome knows how to look for and change may be found at the end of the client page in the Lua API documentation. Many of these property names are self-explanatory.

Unfortunately, some of these properties directly expose internal X Windows property values, some of which are relatively obscure, and the descriptions on the Lua API page are unhelpfully terse. To craft useful rules, however, you will need to understand some of them. The program, which is standard on all X Windows-based systems, can be enormously helpful in understanding some of this mish-mash. To use :
 * Open a command line window.
 * Type the command  and press Enter.  Your mouse cursor will change to a cross-hair.
 * Using the mouse, point at the window you're interested in and click on it. The X Windows properties of that window will be printed to the command terminal.

In particular,  can be extremely useful in understanding the distinction between the ,  , and   properties.

Here's a brief list of window properties supported by Awesome and some hopefully enlightening descriptions.

This is generally the contents of the window's titlebar at any given instant. The  of a window is a string, and may be changed at any time by the program. Since many programs are known to change this frequently (Firefox being an obvious example), this may be of limited use in  matching.

In the  output, this is the value of the   property.

This is a name unique to the program -- usually a camel-cased version of the program's name. The  of a window is a string, is read-only, and is hard-coded by the program that created it -- that is, the program decides what its class value is, and it can't be changed after the fact. No matter how many copies of xterm you've launched, or what their window titles have been changed to, all those windows will have the same class value ("XTerm"). Thus, a window's class may be used to uniquely associate with a particular program.

In the  output, the class is the second value of the   property.

The Weird One. The  of a window is a string, and can be set to any value at program startup.

is an obscure feature of X Windows that sees little use these days. It provides a way to differentiate between windows that may be the same underlying executable, but are being used in different roles. For example, if you had a an xterm window that was exclusively used to read your mail, you may wish to change its  property so that it could be distinguished from every other xterm window.

Most X Windows programs let you change the value of  by using the (unhelpfully named) command line argument. If you don't otherwise specify a value for, it typically takes the value of argv[0] (the name you used to launch the program).

There are exceptions to this rule, however -- most notably, Firefox. The  of Firefox is "Firefox". However, the  of all of Firefox's browser windows is "Navigator". This is probably a historical left-over from when Mozilla (Firefox's progenitor) was not just a Web browser, but also a mail reader and HTML editor. All of Mozilla's open windows would have the class "Mozilla", but the mail reader and HTML editor windows would each have different  values. So if you wanted to change the properties of the Web browser windows, but leave the mail reader windows alone, you'd match against an  value of "Navigator".

In the  output, the instance is the first value of the   property.

You can play with this using  and see how   and   interrelate. As an example, open a command line shell and launch an xterm normally:

$ xterm

Then inspect it with :

WM_CLASS(STRING) = "xterm", "XTerm"

Now launch xterm with a different  using the   argument:

$ xterm -name farkleberry

will report the following:

WM_CLASS(STRING) = "farkleberry", "XTerm"

Finally, just for laughs, create a softlink that points to xterm, and then launch xterm using the softlink:

$ ln -s /usr/bin/xterm barfoo $ ./barfoo

will report the following:

WM_CLASS(STRING) = "barfoo", "XTerm"

The type of the window. The window's  is a string, and may have one of the following values:
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)

A window's type may be changed, but doing so may cause unexpected behavior.

A unique ID number identifying that window and no other. The  value is an integer, is read-only, and is uniquely assigned to the window on its creation. The ID persists for the life of the window, and is destroyed when the window is closed. Window IDs are never reused during a given login session.

Sometimes set by applications, but typically unused by Awesome. (Other windows managers may use this property in conjuction with  and   to uniquely identify windows such that they can be saved and restored across login sessions.)

In the  output, the   is the value of the WM_WINDOW_ROLE property, if present.

Additional Properties
In addition to the window properties listed on the Lua API documentation page, there are properties provided by awful directly:


 * Boolean; changes the floating attribute of the window.
 * Boolean; changes the floating attribute of the window.


 * String; changes the window's tag to the specified value.
 * String; changes the window's tag to the specified value.


 * String; switches the desktop to the tag of the specified value.
 * String; switches the desktop to the tag of the specified value.


 * Integer; changes the window's location/dimensions.
 * Integer; changes the window's location/dimensions.
 * Integer; changes the window's location/dimensions.
 * Integer; changes the window's location/dimensions.
 * Integer; changes the window's location/dimensions.


 * Boolean; when true, gives the input focus to the matched window. This property is always applied last, regardless of the order it appears in the   array.
 * Boolean; when true, gives the input focus to the matched window. This property is always applied last, regardless of the order it appears in the   array.

Interpreting
So now that we have a basic understanding of rules, we can better interpret the default set of rules that ships with Awesome. Let's look at them again:

awful.rules.rules = { -- All clients will match this rule. { rule = { }, properties = { border_width = beautiful.border_width, border_color = beautiful.border_normal, focus = true, keys = clientkeys, buttons = clientbuttons } }, { rule = { class = "MPlayer" }, properties = { floating = true } }, { rule = { class = "pinentry" }, properties = { floating = true } }, { rule = { class = "gimp" }, properties = { floating = true } }, -- Set Firefox to always map on tags number 2 of screen 1. -- { rule = { class = "Firefox" }, --  properties = { tag = tags[1][2] } }, }

Let's work through them in order. Again, each rule is composed of two parts -- the matching part and the command part. The first rule's matching part is as follows:

{ rule = { },

As mentioned above, a  with an empty property array will match all windows. Thus, the following command part will be applied to all windows:

properties = { border_width = beautiful.border_width, border_color = beautiful.border_normal, focus = true, keys = clientkeys, buttons = clientbuttons } },

This is a  operation, so the array of property values it contains will be assigned to the matched window (which in this case is all windows):


 * The window's border width and color are set to the values in the theme currently loaded into.
 * The window's border width and color are set to the values in the theme currently loaded into.
 * The window's border width and color are set to the values in the theme currently loaded into.


 * The input focus is given to the window. This may seem slightly confusing until you consider that the rule set is applied not just at Awesome startup, but also to every new window as it is created.  Since we want newly opened windows to have the input focus, we put this property here.
 * The input focus is given to the window. This may seem slightly confusing until you consider that the rule set is applied not just at Awesome startup, but also to every new window as it is created.  Since we want newly opened windows to have the input focus, we put this property here.


 * We bind the set of  and   we created earlier to the window.  This makes all windows have the same UI behavior.
 * We bind the set of  and   we created earlier to the window.  This makes all windows have the same UI behavior.
 * We bind the set of  and   we created earlier to the window.  This makes all windows have the same UI behavior.

The rest of the rules are fairly simple. As mentioned above, there is no early exit in rule processing. All rules are tested against all windows. So just because a window matched the  above doesn't mean we're done. The next  is:

{ rule = { class = "MPlayer" }, properties = { floating = true } },

For all windows whose  contains "MPlayer", set the floating attribute on the window. This prevents Awesome from automatically resizing it.

{ rule = { class = "pinentry" }, properties = { floating = true } },

For all windows whose  contains "pinentry" (usually a utility that asks for your password), set the floating attribute on the window.

{ rule = { class = "gimp" }, properties = { floating = true } },

For all windows whose  contains "gimp", set the floating property on the window.

But... Hang on a second; this looks weird to me. By convention, most  names are capitalized. Let's actually launch GIMP 2.8.0 and inspect it using. GIMP actually opens three windows by default, so let's first look at the main image window:

WM_CLASS(STRING) = "gimp", "Gimp"

Interesting. The  of GIMP is "gimp", but the   is actually "Gimp" (capitalized). The other two windows also have the same  and   values. That means the  as specified above won't work.

Okay, let's fix it:

{ rule = { class = "Gimp" }, properties = { floating = true } },

There, all better.

Incidentally, it turns out that GIMP uses the  property to differentiate its windows, so you can use it in your rules:

Main Image Window: WM_WINDOW_ROLE(STRING) = "gimp-image-window"

Toolbox Window: WM_WINDOW_ROLE(STRING) = "gimp-toolbox"

Dock Window: WM_WINDOW_ROLE(STRING) = "gimp-dock"

BTW, it may have occurred to you that, except for the  name, all of the previous three rules are identical. As such, they can be collapsed into a single  entry as follows:

{ rule_any = { class = {"MPlayer", "pinentry", "Gimp"} }, properties = { floating = true } },

Examples
This section lists some more complex examples along with explanations about how they work, to help provide a starting point for more complex setups.

Using except
{ rule_any = { class = { "psi", "Psi" } }, except = { instance = "main" }, callback = awful.client.setslave },

This rule is for the Psi IM client. It makes sure every Psi window is set as a slave window, except the contact list which is left as master. This allows the contact list to always remain visible and in the same place, even as chat windows are opened and closed, providing the tag has been configured correctly.

In this case, the rule is required to affect these three windows:

You can see here the class (second WM_CLASS string) is "psi" for the first two, but "Psi" with a capital P for the third. So in order to match all these windows, we need to use rule_any with both variants, so the rule will match any of the given class names.

However we don't want the rule to match the contact list, so we specify an except value and use the instance (first WM_CLASS string) of the contact list. We use this value since it is not shared by any of the other windows, so we will only exclude the contact list and nothing else.

We now have a rule which will match all Psi windows except for the contact list, so the action we specify for this rule is to call the awful.client.setslave function. This will make the Psi windows slaves, leaving the contact list set to master.

Related Pages

 * awful.rules
 * Lua documentation for the module awful.rules, which implements the rule processing functionality.


 * Example of applications rules
 * Various rules for common applications mostly to mark floating windows as such when necessary.