FVWM3(1)

๐Ÿ‘‘ FVWM3 โ€” the fvwm3 manual, bestie edition ๐Ÿ‘‘

okay so this is the manual page for FVWM3(1), aka F? Virtual Window Manager for X11 โ€” yes the F is doing a little mystery thing, we don't question it ๐Ÿ’…. This is part one, and it is LONG, so grab a snack ๐Ÿ“.


โœจ NAME โœจ

fvwm3 โ€” F? Virtual Window Manager for X11 ๐Ÿฆ‹


๐ŸŒธ SYNOPSIS ๐ŸŒธ

fvwm3 [-c config-command] [-d displayname] [-f config-file] [-o logfile]
[-v]

๐Ÿ’– DESCRIPTION ๐Ÿ’–

Fvwm is a window manager for X11, and the whole entire point is that it's optimised for speed. periodt. ๐Ÿ”ฅ

Fvwm is designed to have a small memory footprint, and it is extremely customizable and extendible. There's a large virtual desktop, and there are also multiple disjoint desktops, and you can use them separately or together. The virtual desktop is the one pretending your video screen is actually huge โ€” you just scroll around inside it ๐ŸŒ€. The multiple disjoint desktops pretend there are several screens to work at, except each screen is completely unrelated to the others. no crossover, no shared vibes, nothing. ๐Ÿ’€

Fvwm also gives you keyboard accelerators, which let you do practically all window manager functions from the keyboard โ€” moving and resizing windows, operating the menus, all of it. keyboard main character energy ๐Ÿ‘‘

And here's a thing that lowkey slays: Fvwm does not distinguish between configuration and action commands. Like, configuration commands typically set fonts, colors, menu contents, and key and mouse function bindings, while action commands do things like raising and lowering windows. Fvwm makes no such distinction and lets you change anything at any time. iconic behavior fr fr โœจ


๐Ÿ’… OPTIONS ๐Ÿ’…

These are the command line options that fvwm recognizes, bestie:

  • -i | --clientid id โ€” this one is used when fvwm is started by a session manager. Should not be used by a user. ๐Ÿ™ˆ
  • -c | --cmd config-command โ€” makes fvwm use config-command instead of 'Read config' (or 'Read .fvwm2rc') as its initialization command. (Quick note: you can give up to 10 -f and -c parameters, and they're executed in the order you specified. ๐Ÿซถ)

Any module started by command line arguments is assumed to be a module that sends back config commands. All command line modules have to quit before fvwm proceeds on to the StartFunction and setting border decorations and styles. There's a potential deadlock if you start a module other than FvwmPerl โ€” but there is a timeout, so fvwm eventually gets going. ๐Ÿ˜ฎ๐Ÿ’จ

For example: starting the pager this way hangs fvwm until the timeout, but this next one should work well:

fvwm -c "AddToFunc StartFunction I Module FvwmPager"
  • -d | --display displayname โ€” manage the display called displayname instead of the name you'd get from the environment variable $DISPLAY. ๐Ÿ–ฅ๏ธ
  • -f config-file โ€” makes fvwm read config-file instead of ~/.fvwm/config as its initialization file. $FVWM_USERDIR can also be used to change the location of the default user directory ~/.fvwm. ๐Ÿ“
  • -o logfile โ€” write log messages to logfile. If logfile is '-', log to the console. (Heads up: this does not turn on logging โ€” see the -v option for that. ๐Ÿ‘€)
  • -h | --help โ€” a short usage description gets printed. cute and quick ๐ŸŽ€
  • -r | --replace โ€” try to take over from a previously running wm. โš ๏ธ This does not work unless the other wm is ICCCM2 2.0 compliant.
  • -F | --restore state-file โ€” used when fvwm is started by a session manager. Should not be used by a user. ๐Ÿ™ˆ
  • -V | --version โ€” prints the version of fvwm to stderr. It also prints information about the compiled in features as stated at compiletime. โญ
  • -C | --visual visual-class โ€” makes fvwm use visual-class for the window borders and menus. visual-class can be "StaticGray", "GrayScale", "StaticColor", "PseudoColor", "TrueColor" or "DirectColor". ๐ŸŒˆ
  • -I | --visualid id โ€” makes fvwm use id as the visual id for the window borders and menus. id can be specified as N for decimal or 0xN for hexadecimal. See the man page of xdpyinfo for a list of supported visuals. ๐Ÿ”
  • -l | --color-limit limit โ€” specifies a limit on the colors used in image, gradient and possibly simple colors used by fvwm. Fr, fvwm (and all the modules) uses a palette with at most limit colors. This option is only useful with screens that display 256 colors (or less) with a dynamic visual (PseudoColor, GrayScale or DirectColor). The default depends on your X server and how you run fvwm, and in most cases that default is reasonable. ๐Ÿ‘Œ The -l option should be used only if you encounter problems with colors.

By default, fvwm tries to detect large pre-allocated palettes. If such a palette is detected, fvwm uses it, and a priori the -l must not be used. Moreover, in this case the -A and -S options are forced. Note that XFree-4.2 pre-allocates 244 colors (if you use a driver with Render support), leaving only a few free colors โ€” this may lead to some color problems (and nothing can be done ๐Ÿ˜ญ). XFree-4.3 or better pre-allocate only 85 colors.

If no pre-allocated palette is auto detected, the defaults are as follow:

Display depth 8 (256 colors)

  • PseudoColor: 68 (4x4x4 color cube + 4 grey)
  • GrayScale: 64 regular grey
  • DirectColor: 32 (3x3x3 color cube + 5 grey)

Display depth 4 (16 colors)

  • PseudoColor: 10 (2x2x2 color cube + 2 grey)
  • GrayScale: 8 regular grey
  • DirectColor: 10 (2x2x2 color cube + 2 grey)

Note that if you use a private color map (i.e., fvwm is started with the -C or the -I options), then other defaults are used.

So now โ€” what do you do if you encounter problems with colors? First thing: check if you really cannot run your X server with depth 15, 16 or better. Check your X server documentation. ๐Ÿ“– Note that some hardware can support two different depths on the same screen (typically depth 8 and depth 24). If depth 8 is the default, you can force fvwm to use the best depth by using the -C option with TrueColor as argument.

So now let's assume you're forced to run in depth 8 with a dynamic visual, because your hardware/driver can't do better, or because you need to use an application which needs to run under this mode (e.g., because this application needs read-write colors). What you should understand is that you have only 256 colors, and all the applications which use the default color map must share these colors. ๐Ÿ˜ฉ The main problem is that there are applications which use a lot โ€” or even all โ€” the colors. If you use such an application you may have no more free colors, and some applications (which used only a few colors) may fail to start or be unusable.

There are three things that can be done (and fvwm does not really play a particular role here โ€” all applications are concerned):

  1. Run the applications which waste your (default) color map with a private color map. For example, run netscape with the -install option, run KDE or QT applications with the --cmap option, use the -C option for fvwm. The disadvantage of this method is that it's visually disturbing (see the ColormapFocus command for a better control of the color maps switching). ๐Ÿ™ƒ
  2. Limit the number of colors that the applications use. Again, some applications have options to specify a given color limit. With fvwm you may try various values: 61 (a special "visual" palette), 56 (a 4x4x3 color cube plus 6 grey), 29 (a 3x3x3 color cube plus 2 grey), 10 or 9. Also, you may use the -L option. However, limiting the number of colors is not the definitive solution. ๐Ÿ™…
  3. The definitive solution is to try to cause applications which use a lot of colors to use the same colors. This is a difficult task, as there are no formal standards for this goal. However, some toolkits as QT and GTK use color cubes as palettes. So, the idea is to configure your applications/toolkits to all use the same color cube. Moreover, you can use the colors in this color cube in your X resources configuration files and/or as arguments to colors options.

Fvwm can use any color cube of the form RxGxB with 2 <= R <= 6, R = G, R-1 =< B <= R and B >= 2. To get an RxGxB color cube, give an argument to -l an integer c >= R*G*B and < (R+1)(G+1)*B if B=R and < R*G(B+1) if B < R (and different from 61). If c > R*G*B, then some grey may be added to the color cube. ๐ŸงŠ

You can use the PrintInfo Colors [1] command to get information on your fvwm colors setting. In particular, this command prints the palette used by fvwm in rgb format (the last integer gives the number of times fvwm has allocated the colors). ๐ŸŽจ

  • -L | --strict-color-limit โ€” if the screen displays 256 colors (or less) and has a dynamic visual, this causes fvwm to use its palette for all the colors. By default, the palette is used only for images and gradients. ๐Ÿ–Œ๏ธ
  • -P | --visual-palette โ€” if the screen displays 256 colors (or less) and has a dynamic visual, this option causes fvwm to use a palette designed for limiting the "visual" color distance between the points of the palette. Moreover, for better color sharing, if possible, colors with a name in the X rgb data base are used for defining the colors (with the hope that applications and images prefer to use named colors). ๐Ÿซถ If the -l option is not used, this palette has 61 colors. This palette is also automatically selected if 61 or 9 is used as argument to the -l option. โญ
  • -A | --allocate-palette โ€” if the screen displays 256 colors (or less) and has a dynamic visual, this option causes fvwm to allocate all the colors of its palette at start up, for reserving these colors for future use. This option forces the -static-palette option. By default, fvwm allocates (reserves) a color in its palette only if it needs this color. ๐Ÿ’พ
  • -S | --static-palette โ€” if the screen displays 256 colors (or less) and has a dynamic visual, this option causes fvwm to never free the colors in its palette. By default, when fvwm does not need a color any more it frees this color, so that a new color can be used. This option may speed up image loading and save a few bits of memory. โšก
  • --debug-stack-ring โ€” enables stack ring debugging. This option is only intended for internal debugging and should only be used by developers. ๐Ÿ› ๏ธ (not for us, bestie, we stay in our lane ๐Ÿ’…)
  • -v | --verbose โ€” enables debug logging. It writes in append mode to the fvwm log file, which is ~/.fvwm/fvwm3-output.log by default. See the ENVIRONMENT section on how to override this location on fvwm3 startup using $FVWM_USERDIR or $FVWM3_LOGFILE. ๐Ÿ“

Logging can also be dynamically toggled on and off using signals:

SIGUSR1 : used as a signal to restart Fvwm
SIGUSR2 : used as a signal to toggle opening/closing debug log file

okay and there's so much more where that came from โ€” this page keeps going ๐Ÿฆ‹

โœจ ANATOMY OF A WINDOW โœจ

okay bestie, let's get into the glow-up of a window ๐Ÿ’… Fvwm puts a decorative border around most windows, and that border is literally made of a bar on each side plus a tiny L-shaped section on each corner. There's also an extra top bar called the title-bar that shows the window's name. And you can have up to 10 title-bar buttons, no cap. The top, side, and bottom bars together are the side-bars, and the corner pieces are the frame. ๐ŸŽ€

With the built-in minimal configuration:

  • Dragging mouse button 1 in the frame or side-bars starts a resize operation.
  • Dragging mouse button 2 in the frame or side-bars starts a move operation.
  • There are raise/lower operations bound to a single click on borders. Same for the window title.

Up to ten title-bar buttons may exist. Their use is completely user definable, fr fr. One popular config uses one button on the left for a list of window options, and two buttons on the right to iconify and maximize. Another popular config adds a close button to the right. The number of title-bar buttons used depends on which ones have mouse actions bound to them. See the Mouse command. ๐Ÿ–ฑ๏ธ


๐ŸŒˆ THE VIRTUAL DESKTOP ๐ŸŒˆ

Fvwm provides multiple virtual desktops for users who wish to use them. The screen is a viewport onto a desktop which may be larger than the screen. Several distinct desktops can be accessed (concept: one desktop for each project, or one desktop for each application, when view applications are distinct). Since each desktop can be larger than the physical screen, divided into m by n pages which are each the size of the physical screen, windows which are larger than the screen or large groups of related windows can easily be viewed. ๐Ÿฆ‹

The (m by n) size (i.e. number of pages) of the virtual desktops can be changed any time, by using the DesktopSize command. All virtual desktops must be (are) the same size. The total number of distinct desktops does not need to be specified, but is limited to approximately 4 billion total. All windows on a range of desktops can be viewed in the FvwmPager, a miniature view of the desktops. The pager is an accessory program, called a module, which is not essential for the window manager to operate. Windows may also be listed using the WindowList command or the FvwmIconMan module. ๐Ÿ‘‘

Fvwm keeps the windows on the desktop in a layered stacking order; a window in a lower layer never obscures a window in a higher layer. The layer of a window can be changed by using the Layer command. The concept of layers is a generalization of the StaysOnTop flag of older fvwm versions. The StaysOnTop and StaysPut Style options are now implemented by putting the windows in suitable layers and the previously missing StaysOnBottom Style option has been added. ๐Ÿ’…

Sticky windows are windows which transcend the virtual desktop by "Sticking to the screen's glass". They always stay put on the screen. This is convenient for things like clocks and xbiffs, so you only need to run one such gadget and it always stays with you. Icons can also be made to stick to the glass, if desired. ๐Ÿ•ฐ๏ธ

Window geometries are specified relative to the current viewport. That is:

xterm -geometry +0+0

creates a window in the upper left hand corner of the visible portion of the screen. It is permissible to specify geometries which place windows on the virtual desktop, but off the screen. For example, if the visible screen is 1000 by 1000 pixels, and the desktop size is 3x3, and the current viewport is at the upper left hand corner of the desktop, invoking:

xterm -geometry +1000+1000

places a window just off of the lower right hand corner of the screen. It can be found by moving the mouse to the lower right hand corner of the screen and waiting for it to scroll into view. A geometry specified as something like:

xterm -geometry -5-5

places the window's lower right hand corner 5 pixels from the lower right corner of the visible portion of the screen. Not all applications support window geometries with negative offsets. Some applications place the window's upper right hand corner 5 pixels above and to the left of the upper left hand corner of the screen; others may do just plain bizarre things. ๐Ÿ˜ญ

There is a fvwm-specific extension to geometry strings which can also enforce the geometry is relative to the given screen. For example:

xterm -geometry +0+0@n

Where 'n' can be one of a RandR monitor name, or an assigned monitor number. For more details, see the RANDR SUPPORT section. โœจ

There are several ways to cause a window to map onto a desktop or page other than the currently active one. The geometry technique mentioned above (specifying x,y coordinates larger than the physical screen size), however, suffers from the limitation of being interpreted relative to the current viewport: the window may not consistently appear on a specific page, unless you always invoke the application from the same page. ๐Ÿ™ˆ

A better way to place windows on a different page, screen or desk from the currently mapped viewport is to use the StartsOnPage or StartsOnScreen style specification (the successors to the older StartsOnDesk style) in your config file. The placement is consistent: it does not depend on your current location on the virtual desktop. ๐Ÿ’ฏ

Some applications that understand standard Xt command line arguments and X resources, like xterm and xfontsel, allow the user to specify the start-up desk or page on the command line:

xterm -xrm "*Desk:1"

starts an xterm on desk number 1;

xterm -xrm "*Page:3 2 1"

starts an xterm two pages to the right and one down from the upper left hand page of desk number 3. Not all applications understand the use of these options, however. You could achieve the same results with the following lines in your .Xdefaults file:

XTerm*Desk: 1

or

XTerm*Page: 3 2 1

๐ŸŒธ RANDR MULTI-SCREEN SUPPORT ๐ŸŒธ

Fvwm best supports multiple screens using the RandR X11 protocol. If fvwm isn't built with the RandR protocol then the multi screen support is very limited, and it is suggested to rebuild with RandR. It is also recommended to use 'EdgeScroll 0 0' on multi-screen displays to avoid changing pages when moving the mouse between screens. ๐Ÿ–ฅ๏ธ

If Fvwm has been compiled with RandR support then it tracks the outputs (displays) which it finds. These outputs are stored by name, which can be found by running using the xrandr(1) command. ๐Ÿ”

When Fvwm detects monitors, it adds them to a tree with a defined order, and each monitor is assigned a number. That order is top-down, left-to-right, so for example, the following diagram illustrates a monitor layout and their assigned number.

A (0)
B (1)   C (2)    D (3)

Hence it is possible to then refer to the 2nd monitor and print its name via expansion variables as:

$[monitor.1.name]

Which would print the name, B. ๐Ÿ…ฑ๏ธ

In doing so, Fvwm tracks events from RandR, such as when a given output changes size, or has been added or removed. ๐Ÿ”„

These are controlled by FvwmEvent. ๐ŸŽ›๏ธ


๐ŸŽ€ DESKTOP BEHAVIOUR ๐ŸŽ€

Because Fvwm has the capability to track outputs, Fvwm can be told how to handle those. This is controlled via the DesktopConfiguration command. By default, Fvwm treats all outputs it finds as one large screen, although Fvwm can be told to treat screens independently of each other. ๐ŸชŸ

๐ŸŒฑ INITIALIZATION (aka the glow-up moment) โœจ

So when fvwm wakes up, the very first thing it does is go looking for a config file โ€” the one that describes your key and button bindings, plus like a million other things. The format of those files gets explained later, bestie, don't worry.

fvwm kicks things off by running this command:

Read config

That hunts for a file called config in the $FVWM_USERDIR and $FVWM_DATADIR directories, exactly like Read describes. If that flops, fvwm goes and checks a bunch of other files for backward compatibility. Here's the complete list of every location it queries in the default installation (and it only uses the first one it finds):

$HOME/.fvwm/config
/usr/local/share/fvwm/config

$HOME/.fvwm/.fvwm2rc
$HOME/.fvwm2rc
/usr/local/share/fvwm/.fvwm2rc
/usr/local/share/fvwm/system.fvwm2rc
/etc/system.fvwm2rc
๐Ÿ’€ Heads up: those last 5 locations are not guaranteed to be supported in the future. They're giving legacy, not main character.

If fvwm genuinely can't find a config file, the left mouse button, or

or

keys on the root window bring up menus and forms that can create a starting configuration file for you. Cute, right? ๐ŸŽ€


fvwm sets two environment variables, and its children inherit them. Meet the duo:

  • $DISPLAY โ€” describes the display fvwm is running on. It might be unix:0.0 or :0.0, which doesn't work too well when you pass it through ssh to another machine, ngl.
  • $HOSTDISPLAY โ€” a network-ready description of the display. $HOSTDISPLAY always uses the TCP/IP transport protocol (even for a local connection), so use $DISPLAY for local connections instead, since it may use Unix-domain sockets, which are faster. โšก

If you wanna start some apps or modules alongside fvwm, you could just drop

Exec app

or

Module FvwmXxx

into your config โ€” but that is not recommended. Only do it if you know what you're doing, fr fr. It's usually important to start applications or modules after the entire config is read, because the config holds styles and module configs that affect how windows look and behave. Starting early is giving chaos.

The standard way to start apps or modules on fvwm's startup is to add them to an initialization function โ€” usually StartFunction or InitFunction. That way they only launch once fvwm is done reading and executing the config file. โœจ


fvwm has three special functions for initialization:

  • StartFunction โ€” executed on startups and restarts.
  • InitFunction โ€” executed during initialization, just after StartFunction.
  • RestartFunction โ€” executed during restarts, just after StartFunction.

These functions can be customized in your config file using the AddToFunc command (described later, bestie, patience ๐Ÿ’…) to start up modules, xterms, or literally whatever you want fvwm to launch for you.

fvwm also has a special exit function: ExitFunction, executed when exiting or restarting, before actually quitting. Perfect for explicitly killing modules and stuff. ๐Ÿงน


Now, if fvwm is running under a session manager, SessionInitFunction and SessionRestartFunction get executed instead of InitFunction and RestartFunction. This is a total lifesaver because it lets your config file work great both under a session manager and without one.

Generally it is a bad idea to start xterms or other applications in "Session*" functions. ๐Ÿ™ˆ

Also, you might wanna start different modules depending on whether you're under a session manager or not. For the same kind of reason, SessionExitFunction is used instead of ExitFunction.

DestroyFunc StartFunction
AddToFunc StartFunction
 + I Module FvwmPager * *
 + I Module FvwmButtons

DestroyFunc InitFunction
AddToFunc InitFunction
 + I Module FvwmBanner
 + I Module FvwmIconMan
 + I Exec xsetroot -solid cyan
 + I Exec xterm
 + I Exec netscape

DestroyFunc RestartFunction
AddToFunc RestartFunction
 + I Module FvwmIconMan

DestroyFunc SessionInitFunction
AddToFunc SessionInitFunction
 + I Module FvwmBanner

DestroyFunc SessionRestartFunction
AddToFunc SessionRestartFunction
 + I Nop

You do not need to define all the special functions โ€” if some are empty, that's fine, they just vibe. ๐ŸŒธ Also note: all these special functions can now be emulated using StartFunction and ExitFunction, like this:

DestroyFunc StartFunction
AddToFunc StartFunction
 + I Test (Init) Module FvwmBanner
 + I Module FvwmPager * *
 + I Test (Restart) Beep

DestroyFunc ExitFunction
AddToFunc ExitFunction
 + I Test (Quit) Echo Bye-bye
 + I KillModule MyBuggyModule
 + I Test (ToRestart) Beep

๐Ÿ”ง COMPILATION OPTIONS

fvwm comes with a whole bunch of compile-time options, and ngl, they matter. If you're having trouble using a certain command or feature, go check whether support for it was even included at compile time. All the optional features are described in the config.h file that gets generated during compilation. ๐Ÿ‘‘


๐Ÿ–ผ๏ธ ICONS AND IMAGES

fvwm can load .xbm, .xpm, .png and .svg images. Let's break it down:

  • XBM images are monochrome. fvwm can always display XBM files. Periodt.
  • XPM and PNG formats are color images.
  • SVG is a vector graphics image format.

Compile-time options determine whether fvwm can display XPM, PNG or SVG icons and images. Peep the INSTALL.fvwm file for more info. ๐Ÿ“–

The related SHAPE compile-time option can make fvwm display spiffy shaped icons. ๐Ÿ’…

๐ŸŽจ SVG rendering options

SVG images are generated from (XML) text files. A really simple SVG file might look something like this:

<svg width="120" height="80">
<rect fill="red"     width="40" height="40"  x="0"   y="0"  />
<rect fill="lime"    width="40" height="40"  x="40"  y="0"  />
<rect fill="blue"    width="40" height="40"  x="80"  y="0"  />
<rect fill="cyan"    width="40" height="40"  x="0"   y="40" />
<rect fill="magenta" width="40" height="40"  x="40"  y="40" />
<rect fill="yellow"  width="40" height="40"  x="80"  y="40" />
</svg>

By default, SVG images are rendered exactly how the image creator intended them to be. But since SVG is a vector graphics format, the images can be rendered at any chosen size and rotation โ€” which means, for example, you can use the same icon file rendered at different sizes for the Icon and MiniIcon styles. Iconic, honestly. โœจ

The rendering options are specified as a string appended to the SVG filename, like this:

_image.svg_:[!] [(1) _size_] [(2) _position_] [(3) _rotation_] [(4) _scale_] ...

{empty}(1) [-]_width_{x}[-]_height_

{empty}(2) {- | +}_xpos_{- | +}_ypos_

{empty}(3) @[-]_angle_

{empty}(4) {* | }[-]_factor_[x | y]

The option string always starts with a colon (':') to separate it from the filename. An empty option string can skip that colon, but it might still be a good idea to include it anyway, to prevent ambiguity if the filename contains any colon. ๐Ÿซถ

filename_without_colon.svg
filename:with:colon.svg:

An exclamation point ('!') transposes the entire final image (including the rendering area) โ€” meaning all the horizontal and all the vertical coordinates get swapped with each other. Wild, right? ๐Ÿ”„

image.svg:!

width and height specify the dimensions of the rendering area in pixels, i.e. the dimensions of the resulting image. The actual image is fitted to fill the entire rendering area.

image.svg:60x60

Use a width or height value of 0 to keep the aspect ratio. ๐ŸŽ€

image.svg:0x60
image.svg:60x0

A '-' before width mirrors the rendering area horizontally.

image.svg:-0x0

A '-' before height mirrors the rendering area vertically.

image.svg:0x-0

xpos and ypos specify a translation of the image in pixels. A positive xpos value moves the image to the right. A positive ypos value moves it down. Moving it partially outside of the rendering area results in a cropped image.

image.svg:-30-0
image.svg:-0+10
image.svg:-30+10

angle specifies a rotation around the actual image center in degrees. This might result in a cropped image. A positive value rotates the image clockwise. Floating point values are recognized. ๐ŸŒ€

image.svg:@180
image.svg:@-90
image.svg:@30
image.svg:@57.3

factor specifies a scaling of the actual image (not the rendering area). Scaling it up results in a cropped image. Floating point values are recognized. Division by zero is ignored. If factor is directly followed by an 'x' or a 'y', the scaling is horizontal or vertical respectively. Otherwise the scaling is uniform. ๐Ÿ“

image.svg:*2
image.svg:/2
image.svg:/3x
image.svg:/2y

Scaling down a translated or rotated image can prevent cropping. Little hack, big brain. ๐Ÿง 

image.svg:@30*0.6

Repeated usage of translation, rotation, and scaling is allowed. Translation and rotation are additive. Scaling is multiplicative.

image.svg:*2/3
image.svg:/3x/2y

When combining affine transformations, the scaling is always done first, then the rotation, and finally the translation. That's the order, no negotiating.

image.svg:-30+10@30/3x/2y

Use a negative scale factor to mirror the actual image.

image.svg:-30+10@30/-3x/2y

Mirroring of the rendering area is done after any scaling, rotation or translation of the image.

image.svg:-0x0-30+10@30/3x/2y

Transposing is done last of all, after everything else.

image.svg:!-0x0-30+10@30/3x/2y

๐Ÿงฉ MODULES

A module is a separate program that runs as a separate Unix process, but transmits commands to fvwm for fvwm to execute. Users can write their own modules to do any weird or bizarre manipulations โ€” without bloating or affecting the integrity of fvwm itself. Bestie, that's the whole point. ๐Ÿ’–

Modules must be spawned by fvwm so it can set up two pipes for fvwm and the module to communicate over. Those pipes are already open for the module when it starts, and the file descriptors for the pipes are handed to it as command line arguments. ๐Ÿซถ

Modules can be spawned by fvwm at any time during the X session using the Module command. Modules can live for the duration of the X session, or they can do a single task and dip. If the module is still active when fvwm is told to quit, then fvwm closes the communication pipes and waits to receive a SIGCHLD from the module โ€” that's the module confirming it noticed the pipe closure and exited.

If modules fail to detect the pipe closure, fvwm exits after approximately 30 seconds anyway. No cap. โฐ

The number of simultaneously executing modules is limited by the operating system's maximum number of simultaneously open files โ€” usually between 60 and 256.

Modules simply transmit commands to the fvwm command engine. Commands are formatted just as in the case of a mouse binding in the config setup file. Certain auxiliary information is also transmitted, as in the sample module FvwmButtons. โœจ

Please refer to the Module Commands section for details. ๐Ÿ‘€

๐Ÿ’– ICCCM COMPLIANCE ๐Ÿ’–

Okay so fvwm is out here trying to be ICCCM 2.0 compliant, bestie. Peep http://tronche.com/gui/x/icccm/ for the tea. But here's the thing โ€” ICCCM says apps should be able to receive any keystroke, which lowkey does NOT vibe with the keyboard-shortcut approach fvwm (and basically every other wm) uses. Specifically? You cannot have the same keyboard shortcuts working with your fvwm and another fvwm running inside Xnest (a nested X server running in a window). Same whole problem with mouse bindings, fr fr. ๐Ÿ˜ญ

The ICCCM also says that windows with the property

WM_HINTS(WM_HINTS):
Client accepts input or input focus: False

should NOT be handed the keyboard input focus by the window manager. Those windows can grab input focus all on their own though. Problem is, a whole bunch of apps set this property and then still expect the wm to give them keyboard focus anyway ๐Ÿ™ˆ. So fvwm has a window style, Lenience, which lets fvwm overlook this ICCCM rule. And even with this style, ngl, it's not guaranteed that the application accepts focus.

The glow-up from ICCCM 1.1 to 2.0 includes the ability to take over from a running ICCCM 2.0 compliant window manager. So this:

fvwm; vi ~/.fvwm/config; fvwm -replace

resembles the Restart command. It's not exactly the same, since killing the previously running wm may terminate your X session, if the wm was started as the last client in your .Xclients or .Xsession file. โš ๏ธ

Further additions: support for client-side colormap installation (check the ICCCM for the deets) and the urgency hint. Clients can set this hint in the WM_HINTS property of their window and expect the wm to attract the user's attention to the window. Fvwm has two re-definable functions for exactly this, "UrgencyFunc" and "UrgencyDoneFunc", which get executed when the flag is set/cleared. Their default definitions are:

AddToFunc UrgencyFunc
 + I Iconify off
 + I FlipFocus
 + I Raise
 + I WarpToWindow !raise 5p 5p
AddToFunc UrgencyDoneFunc
 + I Nop

โœจ EXTENDED WINDOW MANAGER HINTS โœจ

Fvwm also attempts to respect the extended window manager hints (ewmh, or EWMH for short) spec: https://specifications.freedesktop.org/wm-spec/wm-spec-1.3.html plus some extensions of it. ๐Ÿซถ

This support is configurable with styles and commands, and those styles and commands all have EWMH as the prefix (so you can find them super easily in this man page, iykyk).

There's a new Context 'D' for the Key, PointerKey, Mouse commands. This context is for desktop applications (such as kdesktop and Nautilus desktop).

When a compliant taskbar asks fvwm to activate a window (typically when you click a button that represents a window in such a taskbar), fvwm calls the complex function EWMHActivateWindowFunc, which by default is Iconify Off, Focus and Raise. You can redefine this function, periodt. Like:

DestroyFunc EWMHActivateWindowFunc
AddToFunc EWMHActivateWindowFunc I Iconify Off
+ I Focus
+ I Raise
+ I WarpToWindow 50 50

...which additionally warps the pointer to the center of the window. ๐Ÿ‘‘

The EWMH spec introduces the notion of Working Area. Without ewmh support the Working Area is the full visible screen (or all your screens if you have a multi head setup with RandR). But compliant applications (such as a panel) can ask to reserve space at the edge of the screen. If that happens, the Working Area is your full visible screen minus these reserved spaces. And if a panel can be hidden by clicking a button, the Working Area does not change (since you can unhide the panel at any time), but the Dynamic Working Area is updated: the space reserved by the panel gets removed (and added back again if you pop up the panel). The Dynamic Working Area may be used when fvwm places or maximizes a window. To find out if an application reserves space you can type "xprop | grep _NET_WM_STRUT" in a terminal and select the application. If four numbers show up, then those numbers define the reserved space as explained in the EwmhBaseStruts command.


๐ŸŽ€ CONFIGURATION ๐ŸŽ€

Configuration Files

The configuration file is what describes mouse and button bindings, colors, the virtual display size, and related items. The initialization configuration file is typically called config (or .fvwm2rc). And by using the Read command, it's easy peasy to read in new configuration files as you go. ๐Ÿ’…

Lines beginning with '#' are ignored by fvwm. Lines starting with '*' are expected to contain module configuration commands (rather than configuration commands for fvwm itself). Like in shell scripts, embedded newlines in a configuration file line can be quoted by preceding them with a backslash. All lines linked in this fashion are treated as a single line, and the newline itself is ignored. โœจ

Fvwm makes no distinction between configuration commands and action commands, so anything mentioned in the fvwm commands section can be placed on a line by itself for fvwm to execute as it reads the configuration file, or it can be placed as an executable command in a menu or bound to a mouse button or a keyboard key. It is left as an exercise for the user to decide which function makes sense for initialization and which ones make sense for run-time. ๐Ÿ˜Œ

Supplied Configuration

A sample configuration file is supplied with the fvwm distribution. It's well commented and can be used as a source of examples for fvwm configuration. It may be copied from /usr/local/share/fvwm/config file. ๐Ÿ“

Alternatively, the built-in menu (accessible when no configuration file is found) has options to create an initial config file for the user. So no worries if you're starting from zero, bestie. ๐ŸŒธ

๐ŸŽ€ FONTS ๐ŸŽ€

okay bestie, this is the glow-up section. It's all about text and how pretty (or cursed) it looks. โœจ

โœจ Font names and font loading โœจ

The fonts used for the text of a window title, icon titles, menus and geometry window can be specified by using the Font and IconFont Style, the Font MenuStyle and the DefaultFont commands. Also, all the Modules which use text have configuration command(s) to specify font(s). All these styles and commands take a font name as an argument. This section explains what is a font name for fvwm and which fonts fvwm loads. so yes we are going to explain the whole thing, no skips ๐Ÿ’…

First, you can use what we can call a usual font name, for example:

    -adobe-courier-bold-r-normal--10-100-75-75-m-60-ISO8859-1
    -adobe-courier-bold-r-normal--10-*
    -*-fixed-medium-o-normal--14-*-ISO8859-15

That is, you can use an X Logical Font Description (XLFD for short). Then the "first" font which matches the description is loaded and used. This "first" font depends of your font path and also of your locale. Fonts which match the locale charset are loaded in priority order. For example with

    -adobe-courier-bold-r-normal--10-*

if the locale charset is ISO8859-1, then fvwm tries to load a font which matches

    -adobe-courier-bold-r-normal--10-*-ISO8859-1

with the locale charset ISO8859-15 fvwm tries to load

    -adobe-courier-bold-r-normal--10-*-ISO8859-15.

A font name can be given as an extended XLFD. This is a comma separated list of (simple) XLFD font names, for example:

    -adobe-courier-bold-r-normal--14-*,-*-courier-medium-r-normal--14-*

Each simple font name is tried until a matching font with the locale charset is found and if this fails each simple font name is tried without constraint on the charset. it's giving backup plans for your backup plans ๐Ÿฆ‹

More details on the XLFD can be found in the X manual page, the X Logical Font Description Conventions document (called xlfd) and the XLoadFont and XCreateFontSet manual pages. Some useful font utilities are: xlsfonts, xfontsel, xfd and xset.

If you have Xft support you can specify an Xft font name (description) of a true type (or Type1) font prefixed by "xft:", for example:

    "xft:Luxi Mono"
    "xft:Luxi Mono:Medium:Roman:size=14:encoding=iso8859-1"

The "first" font which matches the description is loaded. This first font depends on the XftConfig configuration file with Xft1 and on the /etc/fonts/fonts.conf file with Xft2. One may read the Xft manual page and the fontconfig man page with Xft2. The first string which follows "xft:" is always considered as the family. With the second example Luxi Mono is the Family (Other XFree TTF families: "Luxi Serif", "Luxi Sans"), Medium is the Weight (other possible weights: Light, DemiBold, Bold, Black), Roman is the slant or the style (other possibilities: Regular, Oblique, Italic) size specifies the point size (for a pixel size use pixelsize=), encoding allows for enforce a charset (iso8859-1 or iso10646-1 only; if no encoding is given the locale charset is assumed). An important parameter is "minspace=bool" where bool is True or False. If bool is False (the default?) Xft gives a greater font height to fvwm than if bool is True. This may modify text placement, icon and window title height, line spacing in menus and FvwmIdent, button height in some fvwm modules ...etc. With a LCD monitor you may try to add "rgba=mode" where mode is either rgb, bgr, vrgb or vbgr to enable subpixel rendering. The best mode depends on the way your LCD cells are arranged. You can pass other specifications in between ":", as "foundry=foundry_name", "spacing=type" where type can be monospace, proportional or charcell, "charwidth=integer", "charheight=integer" or "antialias=bool" where bool is True or False. It seems that these parameters are not always taken in account. lowkey chaotic of them tbh ๐Ÿ™ˆ

To determine which Xft fonts are really loaded you can export XFT_DEBUG=1 before starting fvwm and take a look to the error log. With Xft2 you may use fc-list to list the available fonts. Anyway, Xft support is experimental (from the X and the fvwm point of view) and the quality of the rendering depends on number of parameters (the XFree and the freetype versions and your video card(s)). experimental bestie, read that again ๐Ÿ’€

After an Xft font name you can add after a ";" an XLFD font name (simple or extended) as:

    xft:Verdana:pixelsize=14;-adobe-courier-bold-r-normal--14-*

then, if either loading the Xft font fails or fvwm has no Xft support, fvwm loads the font -adobe-courier-bold-r-normalโ€”14-*. This allows for writing portable configuration files. portable config files are the moment, we love a fallback ๐Ÿ‘‘


โœจ Font and string encoding โœจ

Once a font is loaded, fvwm finds its encoding (or charset) using its name (the last two fields of the name). fvwm assumes that the strings which are displayed with this font use this encoding (an exception is that if an iso10646-1 font is loaded, then UTF-8 is assumed for string encoding). In a normal situation, (i) a font is loaded by giving a font name without specifying the encoding, (ii) the encoding of the loaded font is the locale encoding, and then (iii) the strings in the fvwm configuration files should use the locale encoding as well as the window and icon name. With Xft the situation is bit different as Xft supports only iso10646-1 and iso8859-1. If you do not specify one of these encodings in the Xft font name, then fvwm does strings conversion using (iii). Note that with multibyte fonts (and in particular with "CJK" fonts) for good text rendering, the locale encoding should be the charset of the font.

To override the previous rules, it is possible to specify the string encoding in the beginning of a font description as follow:

    StringEncoding=enc:_full_font_name_

where enc is an encoding supported by fvwm (usually font name charset plus some unicode encodings: UTF-8, USC-2, USC-4 and UTF-16).

For example, you may use an iso8859-1 locale charset and have an FvwmForm in Russian using koi8-r encoding. In this case, you just have to ask FvwmForm to load a koi8-r font by specifying the encoding in the font name. With a multibyte language, (as multibyte font works well only if the locale encoding is the charset of the font), you should use an iso10646-1 font:

    StringEncoding=jisx0208.1983-0:-*-fixed-medium-r-*-ja-*-iso10646-1

or

    "StringEncoding=jisx0208.1983-0:xft:Bitstream Cyberbit"

if your FvwmForm configuration uses jisx0208.1983-0 encoding. Another possibility is to use UTF-8 encoding for your FvwmForm configuration and use an iso10646-1 font:

    -*-fixed-medium-r-*-ja-*-iso10646-1

or

    "StringEncoding=UTF-8:xft:Bitstream Cyberbit"

or equivalently

    "xft:Bitstream Cyberbit:encoding=iso10646-1"

In general iso10646-1 fonts together with UTF-8 string encoding allows the display of any characters in a given menu, FvwmForm etc. ANY characters. that is the dream fr fr ๐ŸŒˆ

More and more, unicode is used and text files use UTF-8 encoding. However, in practice the characters used range over your locale charset. For saving memory (an iso10646-1 font may have a very large number of characters) or because you have a pretty font without an iso10646-1 charset, you can specify the string encoding to be UTF-8 and use a font in the locale charset:

    StringEncoding=UTF-8:-*-pretty_font-*-12-*

In most cases, fvwm correctly determines the encoding of the font. However, some fonts do not end with valid encoding names. When the font name isnโ€™t normal, for example:

    -misc-fixed-*--20-*-my_utf8-36

you need to add the encoding after the font name using a slash as a delimiter. For example:

    MenuStyle * Font -misc-fixed-*--20-*-my_utf8-36/iso10646-1

If fvwm finds an encoding, fvwm uses the iconv system functions to do conversion between encodings. Unfortunately, there are no standards. For conversion between iso8859-1 and UTF-8: a GNU system uses "ISO-8859-1" and other systems use "iso881" to define the converters (these two names are supported by fvwm). Moreover, in some cases it may be necessary to use machine specific converters. So, if you experience problems you can try to get information on your iconv implementation ("man iconv" may help) and put the name which defines the converter between the font encoding and UTF-8 at the end of the font name after the encoding hint and a / (another possible solution is to use GNU libiconv). For example use:

    Style * Font -misc-fixed-*--14-*-iso8859-1/*/latin1

to use latin1 for defining the converter for the iso8859-1 encoding. The "*" in between the "/" says to fvwm to determine the encoding from the end of the font name. Use:

    Style * Font \
    -misc-fixed-*--14-*-local8859-6/iso8859-6/local_iso8859_6_iconv

to force fvwm to use the font with iso8859-6 as the encoding (this is useful for bi-directionality) and to use local_iso8859_6_iconv for defining the converters. yes queen, force it ๐Ÿ’œ


โœจ Font Shadow Effects โœจ

Fonts can be given 3d effects. At the beginning of the font name (or just after a possible StringEncoding specification) add

    Shadow=size [offset] [directions]]:

size is a positive integer which specifies the number of pixels of shadow. offset is an optional positive integer which defines the number of pixels to offset the shadow from the edge of the character. The default offset is zero. directions is an optional set of directions the shadow emanates from the character. The directions are a space separated list of fvwm directions:

  • N, North, Top, t, Up, u, -
  • E, East, Right, r, Right, r, ]
  • S, South, Bottom, b, Down, d, _
  • W, West, Left, l, Left, l, [
  • NE, NorthEast, TopRight, tr, UpRight, ur, ^
  • SE, SouthEast, BottomRight, br, DownRight, dr, >
  • SW, SouthWest, BottomLeft, bl, DownLeft, dl, v
  • NW, NorthWest, TopLeft, tl, UpLeft, ul, <
  • C, Center, Centre, .

A shadow is displayed in each given direction. All is equivalent to all the directions. The default direction is BottomRight. With the Center direction, the shadow surrounds the whole string. Since this is a super set of all other directions, it is a waste of time to specify this along with any other directions. don't do redundant work bestie, we're not about that ๐Ÿ“

The shadow effect only works with colorsets. The color of the shadow is defined by using the fgsh option of the Colorset command. Please refer to the Colorsets section for details about colorsets.

Note: It can be difficult to find the font, fg, fgsh and bg colors to make this effect look good, but it can look quite good. and when it hits, it HITS ๐Ÿ’–

๐Ÿ’– BI-DIRECTIONAL TEXT ๐Ÿ’–

Arabic and Hebrew text need bi-directional text support to show up right, bestie โ€” what that means is logical strings have to be converted before their visual presentation, so the left-to-right and right-to-left sub-strings get figured out and reshuffled. In fvwm this happens automatically in window titles, menus, module labels and other places if the fonts used for displaying that text are one of the charsets that require bidi (bi-directional) support. Like, that includes iso8859-6, iso8859-8 and iso10646-1 (unicode), but not the other iso8859-* fonts. ๐Ÿ™ˆ

This bi-directional text support is done using the fribidi library compile time option, see INSTALL.fvwm.


โŒจ๏ธ KEYBOARD SHORTCUTS โŒจ๏ธ

Almost every single window manager operation can be done from the keyboard, so mouse-less operation should totally be possible. On top of scrolling around the virtual desktop by binding the Scroll command to appropriate keys, Popup, Move, Resize, and literally any other command can be bound to keys too. Once a command is started, the pointer is moved by using the up, down, left, and right arrows, and the action is terminated by pressing return. Hold down the Shift key and the pointer movement goes in bigger steps; hold down the control key and the pointer movement goes in smaller steps. Standard emacs and vi cursor movement controls can be used instead of the arrow keys. ๐Ÿ’…


๐ŸŒธ SESSION MANAGEMENT ๐ŸŒธ

Fvwm supports session management according to the X Session Management Protocol. It saves and restores window position, size, stacking order, desk, stickiness, shadiness, maximizedness, iconifiedness for all windows. Furthermore, some global state is saved.

Fvwm doesn't save any information regarding styles, decors, functions or menus. So if you change any of these resources during a session (e.g. by issuing Style commands or by using various modules), those changes are lost after saving and restarting the session. To become permanent, such changes have to be added to the configuration file. No cap. ๐Ÿ˜ญ


โœ… BOOLEAN ARGUMENTS โœ…

A number of commands take one or several boolean arguments. These take a few equivalent inputs: "yes", "on", "true", "t" and "y" all evaluate to true, while "no", "off", "false", "f" and "n" evaluate to false. Some commands allow "toggle" too, which means the feature is disabled if it's currently enabled and vice versa. Slay. ๐Ÿ”ฅ


๐Ÿ–ฑ๏ธ BUILTIN KEY AND MOUSE BINDINGS ๐Ÿ–ฑ๏ธ

The following commands are built-in to fvwm:

Key Help R A Popup MenuFvwmRoot
Key F1 R A Popup MenuFvwmRoot
Key Tab A M WindowList Root c c NoDeskSort
Key Escape A MC EscapeFunc

Mouse 1 R A Menu MenuFvwmRoot
Mouse 1 T   A FuncFvwmRaiseLowerX Move
Mouse 1 FS  A FuncFvwmRaiseLowerX Resize
Mouse 2 FST A FuncFvwmRaiseLowerX Move

AddToFunc FuncFvwmRaiseLowerX
+ I Raise
+ M $0
+ D Lower

The Help and F1 keys invoke a built-in menu that fvwm creates. This is primarily for new users that have not created their own configuration file. Either key on the root (background) window pops up a menu to help you get started. ๐Ÿซถ

The Tab key pressed anywhere with the Alt key (same as the key on PC keyboards) held down pop-ups a window list.

Mouse button 1 on the title-bar or side frame can move, raise or lower a window.

Mouse button 1 on the window corners can resize, raise or lower a window.

You can override or remove these bindings. To remove the window list binding, use this:

Key Tab A M -

๐Ÿš€ COMMAND EXECUTION ๐Ÿš€

๐Ÿงฉ Module and Function Commands ๐Ÿงฉ

If fvwm encounters a command that it doesn't recognize, it checks to see if the specified command should have been

Function (rest of command)

or

Module (rest of command)

This allows complex functions or modules to be invoked in a manner which is fairly transparent to the configuration file. Iconic behaviour, honestly. โœจ

Example: the config file contains the line

HelpMe

Fvwm looks for an fvwm command called "HelpMe", and fails. Next it looks for a user-defined complex function called "HelpMe". If no such function exists, fvwm tries to execute a module called "HelpMe". It's giving escalation, but make it polite. ๐Ÿ’€

โณ Delayed Execution of Commands โณ

Note: There are many commands that affect look and feel of specific, some or all windows, like Style, Mouse, Colorset, TitleStyle and many others. For performance reasons such changes are not applied immediately but only when fvwm is idle, i.e. no user interaction or module input is pending. Specifically, new Style options that are set in a function are not applied until after the function has completed. This can sometimes lead to unwanted effects. ๐Ÿ˜ญ

To force that all pending changes are applied immediately, use the UpdateStyles, Refresh or RefreshWindow commands. Periodt. ๐Ÿ’…


๐ŸŽ€ QUOTING ๐ŸŽ€

Quotes are required only when needed to make fvwm consider two or more words to be a single argument. Unnecessary quoting is allowed. If you want a quote character in your text, you must escape it by using the backslash character. For example, if you have a pop-up menu called "Window-Ops", then you do not need quotes:

Popup Window-Ops

but if you replace the dash with a space, then you need quotes:

Popup "Window Ops"

The supported quoting characters are double quotes, single quotes and reverse single quotes. All three kinds of quotes are treated in the same way. Single characters can be quoted with a preceding backslash. Quoting single characters works even inside other kinds of quotes. Lowkey elegant. ๐ŸŒˆ


๐Ÿฆ‹ COMMAND EXPANSION ๐Ÿฆ‹

Whenever an fvwm command line is executed, fvwm performs parameter expansion. A parameter is a '$' followed by a word enclosed in brackets ($[...]) or a single special character. If fvwm encounters an unquoted parameter on the command line it expands it to a string indicated by the parameter name. Unknown parameters are left untouched. Parameter expansion is performed before quoting. To get a literal '$' use "$$".

If a command is prefixed with a '-' parameter expansion isn't performed. This applies to the command immediately following the '-', in which the expansion normally would have taken place. When used together with other prefix commands it must be added before the other prefix.

Example:

Pick -Exec exec xmessage '$[w.name]'

opens an xmessage dialog with "$[w.name]" unexpanded.

The longer variables may contain additional variables inside the name, which are expanded before the outer variable.

In earlier versions of fvwm, some single letter variables were supported. It is deprecated now, since they cause a number of problems. You should use the longer substitutes instead. ๐Ÿ‘‘

Example:

# Print the current desk number, horizontal page number
# and the window's class (unexpanded here, no window).
Echo $[desk.n] $[page.nx] $[w.class]

Note: If the command is called outside a window context, it prints "$[w.class]" instead of the class name. It is usually not enough to have the pointer over a window to have a context window. To force using the window with the focus, the Current command can be used:

Current Echo $[desk.n] $[page.nx] $[w.class]

The parameters known by fvwm are:

  • $$ โ€” A literal '$'.
  • $. โ€” The absolute directory of the currently Read file. Intended for creating relative and relocatable configuration trees. If used outside of any read file, the returned value is '.'.
  • $0 to $9 โ€” The positional parameters given to a complex function (a function that has been defined with the AddToFunc command). "$0" is replaced with the first parameter, "$1" with the second parameter and so on. If the corresponding parameter is undefined, the "$..." is deleted from the command line.
  • $* โ€” All positional parameters given to a complex function. This includes parameters that follow after "$9".
  • $[n] โ€” The n:th positional parameter given to a complex function, counting from 0. If the corresponding parameter is undefined, the "$[n]" is deleted from the command line. The parameter is expanded unquoted.
  • $[n-m] โ€” The positional parameters given to a complex function, starting with parameter n and ending with parameter m. If all the corresponding parameters are undefined, the "$[...]" is deleted from the command line. If only some of the parameters are defined, all defined parameters are expanded, and the remaining silently ignored. All parameters are expanded unquoted.
  • $[n-] โ€” All the positional parameters given to a complex function, starting with parameter n. If all the corresponding parameters are undefined, the "$[...]" is deleted from the command line. All parameters are expanded unquoted.
  • $[*] โ€” All the positional parameters given to a complex function. This is equivalent of $[0-].
  • $[version.num] โ€” The version number, like "2.6.0".
  • $[version.info] โ€” The version info, which contains the SHA of the latest commit (if compiled from git), or "(relesaed)" if a compiled from a release tarball.
  • $[version.line] โ€” The first line printed by the --version command line option.
  • $[vp.x] $[vp.y] $[vp.width] $[vp.height] โ€” Either coordinate or the width or height of the current viewport.
  • $[wa.x] $[wa.y] $[wa.width] $[wa.height] โ€” Either coordinate or the width or height of the EWMH working area.
  • $[dwa.x] $[dwa.y] $[dwa.width] $[dwa.height] โ€” Either coordinate or the width or height of the dynamic EWMH working area.
  • $[desk.count] โ€” The number of desktops defined with the DesktopName command.
  • $[desk.n] โ€” The current desk number.
  • $[desk.name<n>] โ€” These parameters are replaced with the name of the desktop number <n> that is defined with the DesktopName command. If no name is defined, then the default name is returned.
  • $[desk.width] $[desk.height] โ€” The width or height of the whole desktop, i.e. the width or height multiplied by the number of pages in x or y direction.
  • $[desk.pagesx] $[desk.pagesy] โ€” The number of total pages in a desk in x or y direction. This is the same as the values set by DesktopSize.
  • $[page.nx] $[page.ny] โ€” The current page numbers, by X and Y axes, starting from 0. page is equivalent to area in the GNOME terminology.
  • $[w.id] โ€” The window-id (expressed in hex, e.g. 0x10023c) of the window the command was called for or "$[w.id]" if no window is associated with the command.
  • $[w.name] $[w.iconname] $[w.class] $[w.resource] $[w.visiblename] $[w.iconfile] $[w.miniiconfile] $[w.iconfile.svgopts] $[w.miniiconfile.svgopts] โ€” okay bestie, this grab-bag hands you the window's name, its icon name, its resource class, its resource name, its visible name, the file name of its icon or mini icon as set by the Icon or MiniIcon style (and yeah, the full path too, if the file was actually found on disk), and โ€” if fvwm got compiled with SVG support ๐Ÿ’… โ€” the icon or mini icon svg rendering options, leading colon included. If there's no window attached to the command, you just get the unexpanded "$[w.<attribute>]" string back. No drama.

Lowkey important though: those first 5 variables can hold literally any kind of character, so they come pre-quoted. Which means the value is wrapped in single quote characters, and any single quote hanging out inside gets a backslash in front of it. That's the whole reason commands like this:

Style $[w.resource] Icon norm/network.png

actually work, no matter what cursed special symbols the value is carrying โ€” spaces, weird quotes, all of it. ๐Ÿซถ

And about that visible name: it's the value returned from the literal title of the window shown in the titlebar. Usually it's the same as $[w.name] once expanded โ€” but if you're using IndexedWindowName, then the difference actually matters and it lets you reference the specific window by its visible name, so you can drop it into stuff like Style commands. โœจ

  • $[w.x] $[w.y] $[w.width] $[w.height] โ€” either coordinate, or the width or height of the current window, as long as it's not iconified. If no window is associated with the command, or the window is iconified, the string just stays exactly as it is. ๐Ÿ™ˆ
  • $[w.pagex] $[w.pagey] โ€” the X or Y page the window is chilling on.
  • $[w.desk] โ€” the number of the desk the window is shown on. If the window is sticky, it uses the current desk number instead.
  • $[w.layer] โ€” the layer of the window. That's it, that's the tweet.
  • $[w.screen] โ€” the screen name the window is on.
  • $[cw.x] $[cw.y] $[cw.width] $[cw.height] โ€” same energy as $[w.โ€ฆ] but it gives you the geometry of the client part of the window. Translation: the border and title are not counted. ๐Ÿ’…
  • $[i.x], $[it.x], $[ip.x] $[i.y], $[it.y], $[ip.y] $[i.width], $[it.width], $[ip.width] $[i.height], $[it.height], $[ip.height] โ€” again like $[w.โ€ฆ], but now it's the geometry of the icon ($[i.โ€ฆ]), the icon title ($[it.โ€ฆ]), or the icon picture ($[ip.โ€ฆ]). ๐ŸŽ€
  • $[pointer.x] $[pointer.y] โ€” the position of the pointer on the screen. If the pointer is not on the screen, these don't expand at all.
  • $[pointer.wx] $[pointer.wy] โ€” the position of the pointer inside the selected window. And if the pointer is not on the screen, or the window is iconified, or there's no window selected โ€” nope, not expanding. ๐Ÿ’€
  • $[pointer.cx] $[pointer.cy] โ€” the position of the pointer in the client portion of the selected window. If the pointer is not on the screen, or the window is shaded or iconified, or no window is selected, these don't expand either.
  • $[pointer.screen] โ€” the screen name the pointer is currently on.
This one is deprecated โ€” use $[monitor.current] instead. ๐Ÿ‘‘
  • $[monitor.<n>.x], $[monitor.<n>.y], $[monitor.<n>.width], $[monitor.<n>.height], $[monitor.<n>.desk], $[monitor.<n>.pagex], $[monitor.<n>.pagey] $[monitor.primary], $[monitor.prev_primary], $[monitor.current], $[monitor.prev] $[monitor.output], $[monitor.number] $[monitor.count], $[monitor.<n>.prev_desk], $[monitor.<n>.prev_pagex], $[monitor.<n>.prev_pagey] โ€” returns info about the selected monitor. And bestie, these can be nested, like:
$[monitor.$[monitor.primary].width]

<n> should be a valid xrandr(1) output name.

So, the breakdown:

  • "x" gives you the monitor's x position; "y" gives you the monitor's y position; "width" gives you the monitor's width in pixels; "height" gives you the monitor's height in pixels. ๐Ÿ“
  • "number" gives you the monitor's position within the tree. See RANDR SUPPORT.
  • "current" is the same as the deprecated $[screen.pointer] variable โ€” the monitor that's got the mouse pointer. ๐Ÿ–ฑ๏ธ
  • "prev" gives you the previously focused monitor, or the empty string if there isn't one.
  • "count" gives you the number of active monitors.
  • "desk" gives you the current desk displayed on the referenced monitor.
  • "pagex" gives you the X page on the referenced monitor.
  • "pagey" gives you the Y page of the referenced monitor.
  • "primary" is the name of the output set as primary via xrandr(1).
  • "prev_primary" is the name of the output that was the previous primary monitor.
  • "prev_desk" gives you the previous desk on the referenced monitor.
  • "prev_pagex" gives you the previous X page on the referenced monitor.
  • "prev_pagey" gives you the previous Y page on the referenced monitor.
  • $[screen] โ€” the screen number fvwm is running on. Chef's kiss for setups with multiple screens. ๐ŸŒˆ
  • $[screen.count] โ€” the total number of screens detected.
Deprecated, babe โ€” use $[monitor.count] instead.
  • $[fg.cs<n>] $[bg.cs<n>] $[hilight.cs<n>] $[shadow.cs<n>] $[fgsh.cs<n>] โ€” these get replaced with the name of the foreground (fg), background (bg), hilight (hilight), shadow (shadow), or font shadow (fgsh) color defined in colorset <n> (swap <n> for zero or a positive integer). So like, "$[fg.cs3]" expands to the name of the foreground color of colorset 3, in rgb:rrrr/gggg/bbbb form. ๐ŸŽจ

Now if you append .lighten<p> or .darken<p> to the parameters, you instead get a color lighter or darker than the one in colorset <n>, by a percentage value <p> (between 0 and 100). So "$[bg.cs3.lighten15]" expands to the background color of colorset 3, then lightened 15%, in rgb:rrrr/gggg/bbbb form. โœจ

And if you tack .hash on the end, the color output uses #rrggbb form instead of rgb:rrrr/gggg/bbbb. Example: $[bg.cs3.hash] or $[bg.cs3.lighten15.hash].

Details about colorsets live in the Colorsets section โ€” go read it, iykyk. ๐Ÿ’œ

  • $[math.+.<x>,<y>] $[math.-.<x>,<y>] $[math.*.<x>,<y>] $[math./.<x>,<y>] $[math.%.<x>,<y>] $[math.^.<x>,<y>] $[math.<.<x>,<y>] $[math.>.<x>,<y>] โ€” math time, bestie! ๐Ÿงฎ These do basic arithmetic on the integers <x> and <y>. You can add (+), subtract (-), multiply (*), divide (/), modulus (%), and exponentiate (^). Maximum (>) returns the greater of the two values, and minimum (<) the lesser. Super useful when you're computing panel sizes or window locations relative to a monitor โ€” for instance $[math.-.$[monitor.$[monitor.primary].height],200] subtracts 200 pixels from the height of the primary monitor. And you can nest these for more complex operations: $[math.+.$[math.*.3,5],$[math.-.4,-2]] gets replaced with 21. ๐Ÿ”ฅ

The comma in "<x>,<y>" is there to allow for a future possibility of using floats. All operations use C integer mathematics. The result of integer division is the quotient. The modulus gets you the remainder of the integer division. Note that the C modulus returns negative remainders for negative values. And finally, the exponentiation operation returns 1 if <y> is negative. No cap.

  • $[schedule.last] โ€” replaced by the id of the last command scheduled with the Schedule command, even if that command was already executed.
  • $[schedule.next] โ€” replaced by the id the next command used with Schedule will get (unless a different id is specified explicitly, obviously ๐Ÿ’…).
  • $[cond.rc] โ€” the return code of the last conditional command. Heads up: this variable is only valid inside a function and can not be used in a conditional command. Go read the section Conditional Commands in the command list.
  • $[func.context] โ€” the context character of the running command, as used in the Mouse, Key, or PointerKey command. Handy, for example, with:
Mouse 3 FS N WindowShade $$[func.context]
  • $[debuglog.state] โ€” either 0 (debug log closed) or 1. Tells you the current state of the debugging and logging facility. ๐Ÿ›
  • $[gt.str] โ€” returns the translation of str by looking in the current locale catalogs. If no translation is found, str comes back as is. See the LocalePath command.
  • $[infostore.key] โ€” returns the value of the item stored in the InfoStore at the given key. If there's no key present, you get the unexpanded string back. ๐Ÿ™ƒ
  • $[...] โ€” if the string inside the braces isn't any of the above, fvwm tries to find an environment variable with that name and swaps in its value if one turns up (so like, "$[PAGER]" could become "more"). Otherwise the string is left exactly as it is.

Some examples live in the description of the AddToFunc command. ๐Ÿซถ


๐ŸŒธ SCRIPTING AND COMPLEX FUNCTIONS ๐ŸŒธ

So, to pull off the more complex effects, fvwm ships a whole toolbox of commands that level up its scripting abilities. You can read scripts from a file with Read, from the output of a command with PipeRead, or write them as a complex function with the AddToFunc command. For the curious girlies: section 7 of the fvwm FAQ shows some real-life applications of scripting. ๐Ÿ‘‘

Go check the sections User Functions and Shell Commands and Conditional Commands for the details.

โš ๏ธ A word of warning, and I mean it: during execution of complex functions, fvwm needs to take all input from the mouse pointer (the pointer is "grabbed", in the slang of X). No other programs can receive any input from the pointer while a function is running. This can genuinely confuse some programs. For example, the xwd program refuses to make screen shots when it's run from a complex function. If you want that same functionality, use the Read or PipeRead command instead. ๐Ÿ’€

Please refer to the fvwm3menus man page. That's the whole vibe. โœจ


๐Ÿ‘‘ LIST OF FVWM COMMANDS ๐Ÿ‘‘

Please refer to the fvwm3commands and fvwm3styles man pages. Go forth, bestie. ๐Ÿ’…

๐ŸŒ ENVIRONMENT ๐ŸŒ

okay bestie, here's the tea on the environment variables that literally change how fvwm behaves ๐Ÿ’– These are the ones that matter:

  • DISPLAY โ€” fvwm boots up on this display, unless you slide the -display option in instead. she's got options, we love that for her โœจ
  • FVWM_USERDIR โ€” this is the plug for figuring out your data directory, aka where fvwm reads and writes files. if it's not already set, fvwm sets it to $HOME/.fvwm, which is the default user data directory. no cap ๐Ÿ’…
  • FVWM3_LOGFILE โ€” tells fvwm where to put the path and filename for logging debug info from fvwm3. by default the debug log gets written to $FVWM_USERDIR/fvwm3-output.log. but listen: if you give it an absolute path (one starting with /), then $FVWM_USERDIR is ignored entirely โ€” otherwise the log lands at $FVWM_USERDIR/$FVWM3_LOGFILE. pick your fighter ๐Ÿซถ
  • FVWM_DATADIR โ€” fvwm sets this one itself, to the directory holding fvwm config and module data ๐ŸŽ€
  • FVWM_MODULEDIR โ€” also set by fvwm, pointing at the directory with the standard fvwm modules ๐Ÿ‘‘
  • SESSION_MANAGER โ€” fvwm tries to reach out and contact this session manager, like hey girl hey ๐Ÿ“ž
  • SESSION_MANAGER_NAME โ€” this one's mostly here to sniff out whether xsm is running, so we can work around its bug ๐Ÿ™ˆ if this variable is set to "xsm", then DiscardCommand gets set the way xsm expects it, not the way XSMP requires. so if you're running fvwm under xsm, you should set this variable to "xsm" โ€” otherwise your old state files just... don't get removed. messy ๐Ÿ’€
  • SM_SAVE_DIR โ€” if this is set, fvwm saves its session data right in this directory. if not, it falls back to $HOME. also fyi, the state files are named .fs-?????? and normally get cleaned up automatically once they're not needed anymore ๐Ÿงนโœจ

๐Ÿซถ AUTHORS ๐Ÿซถ

Robert Nation, with help from many people, built on twm code, which was written by Tom LaStrange. after Robert Nation came Charles Hines, then Brady Montz. and currently? fvwm is developed by a whole crew of people on the fvwm-workers mailing list โ€” it's giving community, it's giving collab, we stan ๐ŸŒธ


Fvwm and every single module, script and other file that comes with the distribution are subject to the GNU General Public License (GPL). for the full deets, please go read the COPYING file that came bundled with fvwm ๐Ÿ’œ


๐Ÿ› BUGS ๐Ÿ›

got a bug report? send it to the fvwm-workers mailing list at fvwm-workers@fvwm.org ๐Ÿ“ฌ they're listening, bestie.

the official fvwm homepage lives at http://fvwm.org/ โ€” go say hi ๐Ÿฆ‹


and that's a wrap on this whole page, gorgeous ๐Ÿ’… this was FVWM3(1), dated 2026-06-28, and you just read the entire thing from top to bottom like a true main character. go forth and configure your windows, you absolute icon ๐Ÿ‘‘๐Ÿ’–

๐Ÿ“ฆ where this page comes from