Introduction

With the very soon upcoming new release of OpenBSD I wanted to take a close look to the two default window managers contained in the base system: fvwm 2.2.5 and cwm.

As far as I know the very old version (from 2001) of fvwm2 is contained, because the license was changed to GPL2 in versions afterwards.

I really like the retro look and feel of fvwm and so I thought I would try configuring it.

It is important to only refer to the default .fvwmrc file in /usr/X11R6/lib/X11/fvwm/.fvwmrc and of course to the manpages.

See apropos fvwm.

If you try with google you will find a lot of examples that will not work, because they are for fvwm3 only or for later versions of fvwm2.

For the run command in the menu I use rofi.

I will also show my cwm config file in another post.

Screenshot

The .fvwmrc file below produces the following look and feel:

Desktop

My .fvwmrc

#################################################################
#
# A configuration file for FVWM.
#
#################################################################

IconPath          /usr/X11R6/include/X11/bitmaps
ModulePath        /usr/X11R6/lib/X11/fvwm
PixmapPath        /usr/X11R6/include/X11/pixmaps

MenuStyle * ActiveFore white, HilightBack mediumorchid3, Foreground white, SideColor mediumorchid3, SidePic /home/mw/side.fvwm2.xpm, Background gray45, Font "-misc-spleen-medium-r-normal--24-240-72-72-c-120-iso10646-1"

MenuStyle NoSides ActiveFore white, HilightBack mediumorchid3, Foreground white, Background gray45, Font "-misc-spleen-medium-r-normal--24-240-72-72-c-120-iso10646-1"


# initialize functions for starting FvwmButtons and restarting them
# these are executed at startup and at restart of fvwm buttons
DestroyFunc StartFunction
AddToFunc StartFunction
+       "I" Module FvwmButtons Panel1
+		"I" Module FvwmButtons Panel2
+		"I" Module FvwmButtons Panel3
+		"I" Module FvwmIconMan
+		"I" Module FvwmBacker

*FvwmIconMan*Resolution global
*FvwmIconMan*background gray45
*FvwmIconMan*foreground white
*FvwmIconMan*font 20x13
*FvwmIconMan*1*managergeometry 1x0+0+230
*FvwmIconMan*1*buttongeometry 330x30
*FvwmIconMan*1*title ""
*FvwmIconMan*action Mouse 1 N sendcommand Iconify
*FvwmIconMan*action Mouse 2 N sendcommand WarpToWindow
*FvwmIconMan*action Mouse 3 N sendcommand WarpToWindow

# properties of the buttons
*Panel1Fore Black
*Panel1Back gray45
*Panel1Font -misc-spleen-medium-r-normal--24-240-72-72-c-120-iso10646-1
*Panel1Geometry 330x230+0+0
*Panel1Rows 1

# define the programs executed by the buttons
*Panel1(Swallow(UseOld) "FvwmPager" "Module FvwmPager 0 3")

*FvwmPagerGeometry 330x230+0+0
*FvwmPagerFont none
*FvwmPagerSmallFont -misc-spleen-medium-r-normal--24-240-72-72-c-120-iso10646-1
*FvwmPagerLabel 0 Eins
*FvwmPagerLabel 1 Zwei
*FvwmPagerLabel 2 Drei
*FvwmPagerLabel 3 Vier
*FvwmPagerDeskColor 0 gray25
*FvwmPagerDeskColor 1 gray25
*FvwmPagerDeskColor 2 gray25
*FvwmPagerDeskColor 3 gray25
#*FvwmPagerBack gray45
*FvwmPagerFore mediumorchid3
*FvwmPagerHilight gray45
*FvwmPagerRows 2
*FvwmPagerColumns 2

# Panel2
# properties of the buttons
*Panel2Fore Black
*Panel2Back gray45
*Panel2Font -misc-spleen-medium-r-normal--24-240-72-72-c-120-iso10646-1
*Panel2Geometry 320x80+0-0
*Panel2Rows 1

# define the programs executed by the buttons
*Panel2(Swallow XClock 'Exec exec xclock -hl white -hd white -padding 0 -fg white -bg gray45')
*Panel2(Swallow XBiff 'Exec exec xbiff -fg white -bg gray45')
*Panel2(Swallow(UseOld,NoKill) "xload" `Exec exec xload -title xload -fg white -bg gray45 -update 3 -nolabel`)
*Panel2(Swallow swallow 'Exec exec xterm -fa \'spleen\' -fs 16 -title swallow +sb -fg white -bg gray45 -e "tput civis; while true; do echo ; /home/mw/cputemp | perl -pe chomp; echo ; /home/mw/mem | perl -pe chomp; sleep 5; clear; done"')

# Panel3
# properties of the buttons
*Panel3Fore Black
*Panel3Back gray45
*Panel3Font -misc-spleen-medium-r-normal--24-240-72-72-c-120-iso10646-1
*Panel3Geometry 480x80+1040-0
*Panel3Rows 1

# define the programs executed by the buttons
*Panel3(Icon xterm.xpm, Action(Mouse 1) Exec exec xterm -title "imac Session" -geometry 170x45 -e "tmux new -A -s imac")
*Panel3(Icon word_processor.xpm, Action(Mouse 1) Exec exec libreoffice --writer)
*Panel3(Icon xpaint.xpm, Action(Mouse 1) Exec exec gimp-3.0)
*Panel3(Icon mail1.xpm, Action(Mouse 1) Exec exec claws-mail)
*Panel3(Icon Monitor.xpm, Action(Mouse 1) Exec exec thunar)
*Panel3(Icon /home/mw/Downloads/netscape.xpm, Action(Mouse 1) Exec exec ungoogled-chromium)

# Panel4
# properties of the buttons
#*Panel4Fore Black
#*Panel4Back gray45
#*Panel4Font -misc-spleen-medium-r-normal--24-240-72-72-c-120-iso10646-1
#*Panel4Geometry 140x70+0-0
#*Panel4Rows 1
#*Panel4(Icon fvwm2.xpm, Action(Mouse 0) Menu CommandMenu Root +0 +73)

# mouse menus
#
# mouse menus defined here. the menus are attached to the mouse buttons later

# this is the command menu for the left mouse button
DestroyMenu CommandMenu
AddToMenu CommandMenu ""  Title
+	"Run..."		Exec exec rofi -show drun -display-drun ""
+	"" 			Nop
+	"Tmux%mini.xterm.xpm%"			Exec exec xterm -title "imac Session" -geometry 170x45 -e "tmux new -A -s imac"
+	"Xterm%mini.xterm.xpm%"			Exec exec xterm -geometry 70x40
+	"Thunar%mini.directory.xpm%"		Exec exec thunar
+	"Chromium%mini.netscape.xpm%"		Exec exec ungoogled-chromium
+	"Claws Mail%mini.letter.xpm%"	Exec exec claws-mail
+	"" 			Nop
+       "Applications"        Popup AppMenu
+	"" 			Nop
+	"Top"			Exec exec xterm -geometry 80x40 -e top
+	"Systat"			Exec exec xterm -geometry 80x40 -e systat
+       "Volume%mini.audiovol.xpm%"        Popup VolumeMenu
+	"" 			Nop
#+       "Start cwm"             Restart cwm
#+ 	"Hibernate (ZZZ)"	FvwmForm HibernateVerify
#+ 	"Suspend (zzz)"		FvwmForm SuspendVerify
+       "System"        Popup HaltMenu
+	"" 			Nop
+	"Lock Screen%mini.xlock.xpm%"		Exec exec xlock
+ 	"Logout%mini.exit.xpm%"		FvwmForm QuitVerify

DestroyMenu HaltMenu
AddToMenu HaltMenu ""  Title
+	"Restart fvwm"		Restart fvwm
+ 	"Reboot"		FvwmForm RebootVerify
+ 	"Shutdown"		FvwmForm ShutdownVerify

DestroyMenu AppMenu
AddToMenu AppMenu ""  Title
+	"Netsurf%mini.netscape.xpm%"		Exec exec netsurf-gtk3
+	"Lagrange%mini.netscape.xpm%"		Exec exec lagrange
+	"Neomutt%mini.letter.xpm%"	Exec exec xterm -e neomutt
+	"Skanlite"		Exec exec skanlite
+	"Vlc"		    Exec exec vlc
+	"Gimp%mini.xpaint.xpm%"		    Exec exec gimp-3.0
+	"Libreoffice Writer"		Exec exec libreoffice --writer
+       "Calculator"            Exec exec xcalc

# window operations for the centre mouse button
DestroyMenu Global-Window-Ops
AddToMenu Global-Window-Ops    ""    Title
+       "Move"          Move-or-Raise2
+       "Resize"        Resize-or-Raise2
+       "Raise"         Raise
+       "Lower"         Lower
+       "(De)Iconify"   Iconify
+       "(Un)Stick"     Stick
+       "(Un)Maximize"  maximize_func
+       ""              Nop
+       "Delete"        Delete
+       "Close"         Close
+       "Destroy"       Destroy
+       ""              Nop
+       "Refresh Screen" Refresh

# window ops for the top left of every window
DestroyMenu Window-Ops
AddToMenu Window-Ops   "Move"          Move-or-Raise
+       "Resize"        Resize-or-Raise
+       "Raise/Lower"   RaiseLower
+       "Iconify"       Iconify
+       "(Un)Stick"     Stick
+       ""              Nop
+       "Delete"        Delete
+       "Close"         Close
+       "Destroy"       Destroy

# sub-menu for the command menu
DestroyMenu VolumeMenu
AddToMenu VolumeMenu  ""  Title
+       "Volume 100%%"          exec sndioctl -q output.level=1
+       "Volume  90%%"          exec sndioctl -q output.level=0.9
+       "Volume  80%%"          exec sndioctl -q output.level=0.8
+       "Volume  70%%"          exec sndioctl -q output.level=0.7
+       "Volume  60%%"          exec sndioctl -q output.level=0.6
+       "Volume  50%%"          exec sndioctl -q output.level=0.5
+       "Volume  40%%"          exec sndioctl -q output.level=0.4
+       "Volume  30%%"          exec sndioctl -q output.level=0.3
+       "Volume  20%%"          exec sndioctl -q output.level=0.2
+       "Volume  10%%"          exec sndioctl -q output.level=0.1
+       "Volume   0%%"          exec sndioctl -q output.level=0

ChangeMenuStyle NoSides AppMenu VolumeMenu HaltMenu

############################################################################
# menus and mouse actions
#
# these are attached to mouse actions later

# this is for the titlebar. double-click to maximise / minimise
DestroyFunc Move-or-Raise
AddToFunc Move-or-Raise	
+               "I" Raise
+				"M" Move
+				"D" Maximize

DestroyFunc Move-or-Raise2
AddToFunc Move-or-Raise2
+               "M" Raise
+				"M" Move
+				"D" Lower

DestroyFunc Maximize-Func
AddToFunc Maximize-Func
+ "C" Maximize     100 100

DestroyFunc Maximize-Func2
AddToFunc Maximize-Func2
+ "I" Current Maximize     100 100

DestroyFunc Move-or-Iconify
AddToFunc Move-or-Iconify
+                               "I" Raise
+                               "M" Move
+                               "D" Iconify

DestroyFunc Resize-or-Raise
AddToFunc Resize-or-Raise      
+                               "I" Raise
+                               "M" Resize
+                               "D" Lower

DestroyFunc Resize-or-Raise2
AddToFunc Resize-or-Raise2     
+                               "M" Raise
+                               "M" Resize
+                               "D" Lower

DestroyFunc Iconify-and-Raise
AddToFunc Iconify-and-Raise    
+                               "I" Iconify
+                               "I" Raise

############################################################################
# mouse actions, depending on location
#
# root window:
# - left mouse button brings up the command menu
# - centre mouse button is the window operations list
# - right mouse button is a window list
#     Button	Context Modifi 	Function
Mouse 1		R   	A       Menu CommandMenu Nop
Mouse 2		R    	A       Menu Global-Window-Ops Nop
Mouse 3		R    	A      	WindowList

# title bar buttons
# left is menu, right is minimise, maximise, close
#     Button	Context Modifi 	Function
Mouse 0		1       A       Menu Window-Ops Close
Mouse 0		2    	A     	Close
Mouse 0		4    	A     	Maximize-Func
Mouse 0		6    	A     	Iconify

# button 1 in frame or sides is a resize-or-raise, in icons is a move or
# de-iconify, and on top does a move-or-raise
#     Button	Context Modifi 	Function
Mouse 1 	FS      A       Resize-or-Raise
Mouse 1		I       A       Move-or-Iconify
Mouse 1		T       A       Move-or-Raise

# button 2 in an icon is de-iconify, in Corners/Sides/Titlebar gets Ops Menu
#     Button	Context Modifi 	Function
#Mouse 2 	I       A       Iconify
Mouse 2 	FST     A       Menu Window-Ops Nop
# Button 3 does a raise-lower on anything
#Mouse 3 	TSIF    A       RaiseLower

############################################################################
# "are you sure?" for hibernate, suspend, logout, reboot, and shutdown

*HibernateVerifyGrabServer
*HibernateVerifyWarpPointer
*HibernateVerifyCommand  Beep
*HibernateVerifyLine          center
*HibernateVerifyText          "Do you really want to hibernate?"
*HibernateVerifyLine          expand
*HibernateVerifyButton   quit      "Hibernate"  ^M
*HibernateVerifyCommand  exec ZZZ
*HibernateVerifyButton   quit      "Cancel"  ^[
*HibernateVerifyCommand  Nop
Style "HibernateVerify" NoTitle, NoHandles, BorderWidth 3

*SuspendVerifyGrabServer
*SuspendVerifyWarpPointer
*SuspendVerifyCommand  Beep
*SuspendVerifyLine          center
*SuspendVerifyText          "Do you really want to suspend?"
*SuspendVerifyLine          expand
*SuspendVerifyButton   quit      "Suspend"  ^M
*SuspendVerifyCommand  exec zzz
*SuspendVerifyButton   quit      "Cancel"  ^[
*SuspendVerifyCommand  Nop
Style "SuspendVerify" NoTitle, NoHandles, BorderWidth 3

*QuitVerifyGrabServer
*QuitVerifyWarpPointer
*QuitVerifyCommand  Beep
*QuitVerifyLine          center
*QuitVerifyText          "Do you really want to logout?"
*QuitVerifyLine          expand
*QuitVerifyButton   quit      "Logout"  ^M
*QuitVerifyCommand  Quit
*QuitVerifyButton   quit      "Cancel"  ^[
*QuitVerifyCommand  Nop
Style "QuitVerify" NoTitle, NoHandles, BorderWidth 3

*RebootVerifyGrabServer
*RebootVerifyWarpPointer
*RebootVerifyCommand  Beep
*RebootVerifyLine          center
*RebootVerifyText          "Do you really want to reboot?"
*RebootVerifyLine          expand
*RebootVerifyButton   quit      "Reboot"  ^M
*RebootVerifyCommand  exec shutdown -r now
*RebootVerifyButton   quit      "Cancel"  ^[
*RebootVerifyCommand  Nop
Style "RebootVerify" NoTitle, NoHandles, BorderWidth 3

*ShutdownVerifyGrabServer
*ShutdownVerifyWarpPointer
*ShutdownVerifyCommand  Beep
*ShutdownVerifyLine          center
*ShutdownVerifyText          "Do you really want to shutdown?"
*ShutdownVerifyLine          expand
*ShutdownVerifyButton   quit      "Shutdown"  ^M
*ShutdownVerifyCommand  exec shutdown -p now  
*ShutdownVerifyButton   quit      "Cancel"  ^[
*ShutdownVerifyCommand  Nop
Style "ShutdownVerify" NoTitle, NoHandles, BorderWidth 3

############################################################################
# colors and fonts and styles
#
# window in focus
HilightColor		linen mediumorchid3

# all other windows 
Style "*" Color linen/gray45

# fonts for title bar and icon label
WindowFont              -misc-spleen-medium-r-normal--24-240-72-72-c-120-iso10646-1
IconFont                -misc-spleen-medium-r-normal--24-240-72-72-c-120-iso10646-1

# icons go in bottom left
#Style "*" IconBox 0 0 1000 2560, IconGrid 70 70
Style "*" NoIcon

# keep the last focus while in root window
Style "*" SloppyFocus

Style "vlc" NoTitle, NoHandles, BorderWidth 0

# windows auto-raise after these many milliseconds
Module FvwmAuto 300

# down and up in less than these milliseconds to be considered a click
ClickTime 250

# opaque moves. 100 means all windows (ie, up to 100% of screen size) are
# moved opaquely.
OpaqueMoveSize 100

# suppress the pager. desktop sizes are the same as the virtual desktop size
DeskTopSize 1x1 

# window placement. use smart placement when available, ie, no overlap other
# windows. if smart placement is not available, then use random placement as
# a fallback
Style "*" SmartPlacement, RandomPlacement

# window styles
Style "Fvwm*"		NoTitle, Sticky, WindowListSkip, NoHandles, BorderWidth 0

# draw the three buttons at the top right of windows (close, maximise,
# minimise) using vectors
# close button, top right
ButtonStyle 2 Vector 16 20x20@1 30x20@1 50x40@1 70x20@1 80x20@1 80x30@0 60x50@0 80x80@0 70x80@0 50x60@0 30x80@0 20x80@0 20x70@0 40x50@1 20x30@0 20x20@1
# maximise button, to the left of close button
ButtonStyle 4 Vector 4 50x25@1 75x75@0 25x75@0 50x25@1
# minimise button, to the left of the maximise button
ButtonStyle 6 Vector 4 50x75@1 25x25@1 75x25@1 50x75@0

# alternatively, use bitmaps instead of vectors:
#
# ImagePath      /usr/X11R6/include/X11/pixmaps
# AddButtonStyle 2 Pixmap button-close.xpm
# AddButtonStyle 4 Pixmap button-max.xpm
# AddButtonStyle 6 Pixmap button-horiz.xpm

# make everything line up (snap) with each other. number is pixels proximity
SnapAttraction 10
# or, use this to only snap windows:
# SnapAttraction 10 Windows

# alt-tabbing
Key Tab A M Next (CurrentDesk !Iconic) Focus
# alt-shift-tabbing to reverse
# Key Tab A SM Prev (CurrentDesk !Iconic) Focus
#
# Launch terminal
Key Return A 4 Exec exec xterm -geometry 70x40
# Launch Run...
Key space A 4 Exec exec rofi -show drun -display-drun ""

# Move between desktops
Key Tab A 4 Desk 1 0 3
Key 1 A 4 Desk 0 0
Key 2 A 4 Desk 0 1
Key 3 A 4 Desk 0 2
Key 4 A 4 Desk 0 3
Mouse 4 R A Desk 1 0 3
Mouse 5 R A Desk -1 0 3

*FvwmBackerDesk 0 -solid #d8cf7f
*FvwmBackerDesk 1 -solid gray35
*FvwmBackerDesk 2 -solid #ffffcc
*FvwmBackerDesk 3 -solid steelblue

Key f A 4 Maximize-Func2

OpenBSD specific scripts

For displaying memory usage and cpu temperature I use these scripts:

#!/bin/sh

MEM=$(top -n | grep Memory | awk {'print $3'} | cut -d "/" -f 1)
echo "${MEM}"
#!/bin/sh

temp=`echo $(sysctl hw.sensors.cpu0.temp0) | cut -d "=" -f 2 | cut -d "." -f 1`
echo "${temp}°C"

Font

The font I use for fvwm2 and the other userland programs is spleen. It is the same font as the font for OpenBSD’s tty. This font is only available for tty as a default. It can also be installed for the other userland programs:

pkg_add spleen

Source: Spleen Font

In order to make the font work in fvwm2 I had to put the following line into my .xsession file:

xset +fp /usr/local/share/fonts/spleen/

Special Thanks

My gratitude goes to the project:

github.com/bfmartin/fvwm-config-on-openbsd

It was a great source of inspiration.

Conclusion

I really like this old fvwm and it is especially great that it lives in base. In my setup I use FvwmIconMan, FvwmButtons and FvwmBacker at startup.

I tinkered with the module FvwmIconBox, but I prefer the simplicity of this setup.