Wandering Thoughts archives


How I select (terminal) windows from the keyboard in FVWM

As part of reorganizing my work desktop to deal with big screens, I decided that I wanted a way to select terminal windows by name from the keyboard, with some form of autocompletion for speed. The goal was to give me a faster way to get a particular terminal window than sweeping my mouse all the way to my taskbar for terminals and finding the specific window I wanted. FVWM doesn't have any native features for this, so I had to bolt something together for this out of pieces.

(To make life simple I decided to not do anything clever about several windows having the same name. If that happened and I picked the name, the system could pick whichever specific window it wanted.)

The most difficult bit is selecting among alternatives from the keyboard with some form of autocompletion. Fortunately I already had a general program that could do this: dmenu, which I was already using as the core of a general 'do things' launcher. Dmenu will read a list of things from standard input, put up a menu/text entry area, let you type to it, and then print out the selection to standard output. All I needed was a way of generating the list of terminal window names and then of making FVWM activate the chosen window.

With the help of the FVWM mailing list I managed to put together both parts of this. Here is what I have. First, the driver script (slightly simplified; the real version also matches gnome-terminal):

# Generate a list of unique names of
# terminal windows.
genwins() {
  xwininfo -root -tree |
  egrep '': \([^)]* "(XTerm|9term)"\)  [0-9]' |
  awk '{print $2}' |
  sed -e 's/^"//' -e 's/":$//' |
  sort -u
# run dmenu to get the answer.
win=$(genwins | dmenu -b -p win -P -t) || exit 1
# pass the selected window to FVWM
echo "Function ToWindow \"$win\"" |
  FvwmCommand -c

(The -P and -t arguments to dmenu are from a personal patch that I did. -t is especially useful because it makes dmenu do shell-like partial autocompletion. The real script also specifies the dmenu colours and font to use. There may be a more elegant command than xwininfo to use for getting the window names, but xwininfo has the virtue of being ready to hand.)

In FVWM, I've defined the ToWindow function as follows (the real one also selects gnome-terminal windows):

 AddToFunc ToWindow
 + I   Current ("XTerm|9term", "$0") Break
 + I   Next ("XTerm|9term", "$0") ToWindow2

 AddToFunc ToWindow2
 + I   Iconify False
 + I   Focus
 + I   Raise
 + I   WarpToWindow 80 20

Update: there is a better way to write ToWindow using FVWM States; I've written it up in FvwmStatesUnderstood.

This does nothing if either there is no such terminal window or the current window is a terminal window with the right name. Otherwise, the named terminal window is deiconified, given the focus (which also switches me to its virtual screen if it's not on the current virtual screen), raised to be on top of everything else, and then the mouse pointer is moved into it. I don't normally like having the mouse pointer moved around on me, but it's necessary here in order to make sure that this window keeps the focus; popping up a window and then immediately having it lose focus was more irritating than having my mouse pointer teleported.

(The odd structure of this as two functions is necessary for internal FVWM reasons. Basically it's the easiest way to insure that nothing happens if there's no such window.)

(I also had to add FvwmCommandS (the FvwmCommands server module) to the set of FVWM modules that my configuration runs, since I hadn't been using it before this.)

PS: This code omits '|Gnome-terminal' in three places purely to shorten the length of the unbreakable lines in this blog entry.

unix/FvwmKeyboardWindows written at 01:13:11; Add Comment

Page tools: See As Normal.
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.