View on
Brian Keck > xchar > xchar


Annotate this POD

View/Report Bugs


xchar - single character names for X windows and geometries


Brian Keck,


Xchar is a set of programs for keyboard (mouseless) management (raising, focussing, moving, resizing) of X windows. It includes a taskbar. It is useful if you use so many windows that they can't all be seen at once.

Xchar is not a 'window manager' like fvwm or metacity. In fact it only works if such a window manager is running.

Xchar's novelty is the use of one-character names for windows (such as 'f' for Firefox). It also uses one-character names for screen geometries. These character mappings are normally defined by the user.

Most of the work in installing Xchar is in adjusting the sample configfiles to define these 2 mappings, and in adding key mappings to your window manager configfile.

The main programs are the daemon xtb, and the 2 commands xup and xmv. The daemon displays a vertical taskbar, each slot showing the character and iconname of the corresponding window. It is typically started soon after X (and the window manager). Currently it doesn't react to events in the taskbar (mouse clicks, key presses, etc). The command xup takes a window character argument. The command xmv takes a window character or an X window id argument, and a geometry character argument. Both these commands are normally run indirectly by a window manager key mapping. For example modifier1-f might cause xup to raise and focus firefox, and modifier2-p might cause xmv to move and resize the window with keyboard focus to geometry 'p'.

The daemon is responsible for creating the character->window mapping. How it does this is defined by the configfile $HOME/.xtb, which includes a function that maps instance names to sequences of characters. The former is the usual X instance name (eg 'xterm' and 'Firefox-bin'). A sequence is allowed because there may be several windows with the same instance name. Xchar is nicer if these clashes are avoided, such as by using 'xterm -name xterm/c' and mapping xterm/c to 'c'.

The daemon sets a property _XCHAR_CHAR on each window, containing the window's character. The commands, when they take a window character argument, search the toplevel windows for one whose _XCHAR_CHAR matches.

The character->geometry mapping is defined in the configfile $HOME/.screens. By geometry is meant X geometry, such as 484x745+438+0. The command xmv makes no distinction between moving and resizing, just changing a window's geometry to that specified. It understands an extra wrinkle concerning zeros. A geometry is used by xmv in combination with an existing window. A zero width or height in the geometry is replaced by the window's width or height. A double 0 has the same effect with x and y, as in 0x0-444+00.

The distribution contains two other commands. One is 'xtc', which sends simple messages to the daemon via the taskbar property _XCHAR_MSG. The set of messages changes by the week, but probably permanent members are 'exit', 'restart', and 'dump'. The other is 'xterms', whose main arguments are of the form p.w, where p is a geometry character and w is a window character. For each such argument xterms starts an xterm at the geometry 'p' and instance name xterm/w.


The syntax of the configfiles is Perl's. They are trivial to parse, because all the programs are in Perl. Even if you don't know Perl, the sample configfiles in the distribution (and below) should make it easy to create your own. Both should end in expressions evaluating to hash references. See later sections for details of these hashes.

Much of the code of Xchar is factored out into the module X11::Tops (in the Xchar distribution). All the programs in Xchar except 'xterms' use it. X11::Tops in turn uses the widely available module X11::Protocol (CPAN and Debian (libx11-protocol-perl) at least).

The daemon also depends on the universally available module Tk.

Common code related to the character->geometry mapping is in the module X11::Screens (in the Xchar distribution). It is used by xmv and xterms, and itself depends on Tk.

The daemon depends on the window manager supporting some of the Extended Window Manager Hints, namely _NET_CLIENT_LIST _NET_ACTIVE_WINDOW _NET_CLIENT_LIST_STACKING (as well as the usual WM_CLASS etc). This seems to be the case for many window managers, though Xchar has only been tested with fvwm (which judging from the changelog has supported EWMH since 2001).

The command xmv moves windows directly, rather than via the window manager. That is, by ConfigureWindow rather than _NET_MOVERESIZE_WINDOW. There's no reason known this couldn't be changed if the latter has advantages.


As mentioned, the Perl code in the configfiles ends in an expression evaluating to a hash reference. The daemon configfile is the simpler, the hash it refers to having only 3 keys:

  { char => sub { ... },
    order => [ ... ],
    picture => [ ... ],

The 'char' sub has already been described.

The 'order' array is an array of characters that specifies the order of slots in the taskbar. To simplify the expression, this array can have repetitions - a character's place in the order is determined by its first occurrence in the array.

The elements of the 'picture' array are themselves references to arrays. Each of the latter arrays specifies a Unix command and its arguments. The daemon normally executes one of these commands when it starts, after adding two arguments. These extra arguments are a size such as -170x400 and the file name /tmp/xtb. The command is supposed to write an image into this file. The image format can be any supported by Tk (BMP, GIF, JPEG, PNG, PPM, PGM, XBM, XPM). The image is used to pad the taskbar (at the bottom) to the height of the screen.

A complete example is the following:

    { my @reserved;
      push @reserved, qw(x r s o h);
      push @reserved, qw(a c e f g j k t y z , . - =);
      my %reserved;
      $reserved{$_} = 1 for @reserved;
      my @spare;
      for ('a' .. 'z') { push(@spare, $_) unless $reserved{$_}; }
      { char => sub { # arg = instance name from WM_CLASS
          local $_ = shift;
          m-/(.)$-     ?  $1             :
          /acroread/i  ?  ['a', @spare]  :
          /xchat/      ?  ['c', @spare]  :
          /ethereal/   ?  ['e', @spare]  :
          /gecko/      ?  ['f', @spare]  : # firefox
          /gv/i        ?  ['g', @spare]  :
          /sjphone/i   ?  ['j', @spare]  :
          /kaffeine/   ?  ['k', @spare]  :
          /TeXmacs/    ?  ['t', @spare]  :
          /skype/i     ?  ['y', @spare]  :
          /SWT/        ?  ['z', @spare]  : # azureus
          /xtb./       ?  [',', ';' ]    :
          /xtb/        ?  '.'            :
          /^$/         ?  ['-', '=']     :
          /./          ?  ['A' .. 'Z']   :
        order => [
          qw(0 . , ; f F c C e E a A g G z Z t T j J k K r x s h o),
          1 .. 9, qw(i q I Q), 'a' .. 'z', 'A' .. 'Z', '-', '='
        picture => [
          [qw(irand -m-^apod.*(/image|galax|nebula|cloud)- -a -y 6d)],
          [qw(irand -m-^apod/- -y 4d -a)],

The command irand is not in the Xchar distribution.


The geometry configfile is designed to be used on different displays, or more precisely on displays of different sizes. The toplevel keys essentially name the display. The file might contain:

    vaio => {
        width => 1368,
        height => 768,
        chars => { ... }

where no other entry matches 1368 and 768. The module X11::Screens finds the current display's width, height, depth, and resolution (using Tk). If the width and height match the vaio entry then X11::Screens will provide the character->geometry mapping specified in the vaio 'chars' hash. If you have two displays with the same width and height but want to use different geometries, you can do this by adding depth and resolution (dots per inch) keys, provided the displays differ in at least one of these.

The chars hash looks like:

    chars => {
        0 => {
          geometry => ['72x10+0+0', '436x130+0+0'],
        a => {
          geometry => ['72x57+-1+0', '436x745+-1+0'],
        b => {
          geometry => ['80x57+438+0', '484x745+438+0'],
        c => {
          geometry => ['80x74-0+0', '444x744-0+0'],
        1 => {
          geometry => ['72x18+0+0', '436x238+0+0'],
        2 => {
          geometry => ['72x18+0+255', '436x238+0+255'],
        3 => {
          geometry => ['72x18+0-2', '436x238+0-2'],
        4 => {
          geometry => ['80x18+438+0', '484x238+438+0'],
        5 => {
          geometry => ['80x18+438+255', '484x238+438+255'],
        6 => {
          geometry => ['80x18+438-2', '484x238+438-2'],
        7 => ['88x23--2+0', '444x234--2+0'],
        8 => ['88x23--2+252', '444x234--2+252'],
        9 => ['88x24--2-2', '444x244--2-2'],
        f => ['120x74+438+0', '760x745+438+0'],
        x => '0x0-930+00',
        y => '0x0-444+00',
        z => '0x0--1+00',

The term %{$common{unicode6}} is defined at the start of the file by

    %common = (
        unicode6 => {
          unicode => 1,
          normal => '-*-*-medium-r-*--13-*-*-*-c-60-iso10646-*',
          bold => '-*-*-bold-r-*--13-*-*-*-c-60-iso10646-*',

Where the geometry values are references to an array of two geometries, the obvious one of the two is assumed to have width and height in character rather than pixel units. These are used by the command xterms, the other by xmv.




Brian Keck <>


  $Source: /home/keck2/xwin/taskbar/makemaker/RCS/xchar.pod,v $
  $Revision: 1.9 $
  $Date: 2007/07/05 17:07:23 $
  xchar version 0.2
syntax highlighting: