NAME

Xchar

AUTHOR

Brian Keck, bwkeck@gmail.com

DESCRIPTION

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 positions. These character mappings are normally defined by the user.

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

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 position 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 under the mouse to position 'p'.

The daemon is responsible for creating the character->window mapping. How it does this is defined by the configuration file $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->position mapping is defined in the configuration file $HOME/.screens. By position 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 position character and w is a window character. For each such argument xterms starts an xterm at the position 'p' and instance name xterm/w.

DETAILS

The syntax of the configuration files is Perl's. They are trivial to parse, because all the programs are in Perl. Even if you don't know Perl, the sample configuration files 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->position 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.

DAEMON CONFIGURATION FILE

As mentioned, the Perl code in the configuration files ends in an expression evaluating to a hash reference. The daemon configuration file 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']   :
      undef;
    },
    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.

POSITION CONFIGURATION FILE

The position configuration file 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->position 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'],
      %{$common{unicode6}},
    },
    a => {
      geometry => ['72x57+-1+0', '436x745+-1+0'],
      %{$common{unicode6}},
    },
    b => {
      geometry => ['80x57+438+0', '484x745+438+0'],
      %{$common{unicode6}},
    },
    c => {
      geometry => ['80x74-0+0', '444x744-0+0'],
    },
    1 => {
      geometry => ['72x18+0+0', '436x238+0+0'],
      %{$common{unicode6}},
    },
    2 => {
      geometry => ['72x18+0+255', '436x238+0+255'],
      %{$common{unicode6}},
    },
    3 => {
      geometry => ['72x18+0-2', '436x238+0-2'],
      %{$common{unicode6}},
    },
    4 => {
      geometry => ['80x18+438+0', '484x238+438+0'],
      %{$common{unicode6}},
    },
    5 => {
      geometry => ['80x18+438+255', '484x238+438+255'],
      %{$common{unicode6}},
    },
    6 => {
      geometry => ['80x18+438-2', '484x238+438-2'],
      %{$common{unicode6}},
    },
    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.

FVWM CONFIGURATION

xxx