Hack and / - Automate your Desktop with wmctrl

Why move, resize and shade windows by hand when a program can do it for you?

Okay, I'll admit it; I'm addicted to automation. A Roomba vacuums for me, my
main router checks its DSL connection and automatically resets my DSL modem
if it's down, my porch light is motion-sensitive, and my bin directories
are full of homegrown scripts I use to automate mundane computer tasks.
There is something so satisfying when you can reduce a long series of steps
down to a single script and just run that script.

When most people think of automation with scripts, they think about the
command line. After all, most scripts are concerned with standard
command-line fare, such as pipes, simple logic, redirection and parsing
text output. These days, much of the work on the desktop is done without a
terminal, so it would be nice if you could automate some of those more
mundane graphical tasks too. A tool called wmctrl can do exactly that. wmctrl
provides a command-line interface to standard window management tasks, so
you can resize and move windows, change desktops, toggle sticky and rolled-up statuses on a window and much more, all from a shell script.

wmctrl is a common package in most modern distributions, so you should be
able to install it with your distribution's package manager. Otherwise, you
can obtain the source from wmctrl's main Web site
(www.sweb.cz/tripie/utils/wmctrl) and build it.
One of the
great things about wmctrl is that it isn't
window-manager-specific. It
changes your windows via Extended Window Manager Hints (EWMH), and because most
the popular window managers these days (such as GNOME's Metacity, KDE's
KWin, Compiz Fusion and Fluxbox) support EWMH, not only will wmctrl likely
work with your window manager, but also if you decide to change to a different
window manager, your wmctrl scripts probably will work just the same.

Quake Terminal

One of the best ways to illustrate the power of wmctrl is to create a
script that turns a regular terminal into a Quake terminal. For those of
you who haven't played any games from the Quake
series, when you press the ` key in
Quake, a terminal pops down from the top of the screen so you can type
commands. This type of terminal is very handy on a cluttered desktop, but
you even could use this to create a type of “boss button” to make a window
disappear quickly.

In this example, I create a terminal that I've titled “Quake
Term”,
but you can change this script to work with the title of any window on your
desktop. If you are unsure how wmctrl will view your window's title, run
wmctrl with the -l option to show information about all the windows on
your desktop:

The very last field in this output is the title of a particular window, and
this is the information wmctrl can use to identify windows for which you want to
script actions. To create a basic Quake Term, you just need a
single wmctrl command:

#!/bin/sh
wmctrl -r 'Quake Term' -b toggle,shaded

The -r option tells wmctrl the window title on which to act, and the -b option
tells wmctrl either to add, remove or toggle up to two different window
properties (in this case, the shaded state of my window). The wmctrl man
page lists all the available properties you can tweak with this and any
other options.

Note that wmctrl scripts work best if windows have unique titles.
If you have multiple windows open with the same title, you might
not shade the right one. Each terminal sets its title differently, but for
instance, on a GNOME terminal, you can change the title within your profile
settings (right-click on the terminal and select Edit Current
Profile).

I use a modified version of the above command that not only shades the
window, but also moves it to the back below any other windows. The script
also keeps track of the toggled state with a temporary file so that I can
be sure the shaded and stacked states stay in sync:

I simply bind Super-` to run the above script, and then I can toggle my
terminal up and down with a quick key sequence.

Quake terminals are handy, but you can do much more powerful things
with wmctrl. One of the most handy scripts I've created with wmctrl
solves a problem I've had when I chat in IRC and browse the Web at the same
time—it's a pain to resize both windows so you can see both, just to
resize them back when you are done chatting or browsing. wmctrl lets you
resize and move windows, provided you know how to describe the new window
location and geometry. With this in mind, I've created a script that toggles
between two states: normal mode and chat mode. In chat mode, my IRC window
shrinks and moves so that it sits in a narrow strip at the top of the
screen, and my Web browser resizes to be shorter so I can see both windows at the
same time. Then, I can run the script again, and the windows move back to
their normal locations.

To create the script, first arrange your two windows (in my example, one
with “Irssi Term” in the title and one with
“Firefox” in the title) how you
normally want them, and then run a special wmctrl command to list all
the windows on your desktop along with their geometry and size
information:

In this output, the -G option adds four extra columns in the middle. These
columns represent the x-offset, y-offset, width and height, respectively.
So,
in the case of Firefox, the x-offset is 6, the y-offset is 96, the width
is 1040, and the height is 708. Jot down these values for the two windows
you want to script, and then resize and move them to reflect your “chat
mode”. Next, run the command again and jot down the new values.

wmctrl provides the -e argument that allows you to modify the position and
size of a window. The argument actually takes five integer values in a
row—g,x,y,w,h—where g is the gravity of the window (usually put 0 here),
x and y are the x and y coordinates for the top-left corner of the window,
and w and h are the width and height, respectively. So, if I had moved my
Firefox terminal and wanted to move it back to the above coordinates, I
would run the following:

wmctrl -r Firefox -e '0,6,0,1040,708'

If you look carefully, you might notice I changed the y coordinate to 0
instead of 96. I've found that in some window managers, the geometry
the window manager reports to wmctrl is different from reality. Basically,
you need to do a little trial and error and tweak the
coordinates so that everything lines up just right. Once you are satisfied
with your respective wmctrl commands, you can throw them in a script very
similar to the one I used above for the Quake terminal:

I noticed that with the current window manager (Compiz), when I ran this
command,
some bug—either in wmctrl or, more likely, in the window
manager—caused
Firefox to move from my second desktop to my current desktop. If this
happens to you, there's a simple fix. Simply add the following line above the
if statement in the script:

wmctrl -o 1281,0

wmctrl has commands both for shifting to different desktops and also to
different viewports. Because Compiz often uses multiple viewports instead of
desktops, the above command moves me to the second viewport (my desktops
are 1280x768, so 1281,0 corresponds to the top corner of my second
viewport).

wmctrl has a lot of power. I recommend looking at its man
page and reading about the large number of available options. The real power
in wmctrl, however, lies in your ability to imagine new and interesting
ways to script window manager actions. My next project is to create a
“reset” script that moves all the windows on all my desktops to
precise locations and sizes, in case they all are moved around and resized.
Sure, I could do all that by hand, but then I'd miss this great opportunity
for automation.

Kyle Rankin is a Senior Systems Administrator in the San Francisco Bay Area
and the author of a number of books, including Knoppix
Hacks and Ubuntu
Hacks for O'Reilly Media. He is currently the president of the
North Bay
Linux Users' Group.

Kyle Rankin is Chief Security Officer at Purism, a company focused on computers that respect your privacy, security, and freedom. He is the author of
many books including Linux Hardening in Hostile Networks, DevOps Troubleshooting and The Official Ubuntu