[ home ]
Keith Burnett, ping dot keith atthingy gmail dot com, August 2011
Dwm is a tiling window manager for X based GUIs. This page explains how to make a customised dwm work with the Gnome Desktop Manager (gdm) alongside other desktop sessions in Debian Squeeze.
The steps below will lead to a decent 'desktop environment' using dmenu and dwm...
It is not a bad idea to try the repository version of dwm for a week or two to get a feel for the way a dynamically tiled window manager works. You might need to add a desktop file so that there is an entry for dwm in the session menu. This depends on which version of Debian or Ubuntu you are using, so check the appropriate forum for dwm threads.
Assuming that you are a convert to dwm, you will want to customise appearance and behaviour, and that requires compilation, so you have to uninstall the repository version before compiling from source. To uninstall dwm, just
su
apt-get remove dwm
apt-get update
exit
I aim to use dwm as my default desktop, and I need to be able to automount CDs, USB sticks, external hard drives for backups and so on. Thunar, part of the XFCE4 desktop, provides automounting easily.
I use scrot for screen grabs, and feh is used to set the wallpaper in the dwm-start script shown below. Feh has many other uses.
su
apt-get install thunar feh scrot
exit
Use the commands below as root, originally published in a Debian forums post by Loomx.
su
apt-get install libc6 libx11-6 libxinerama1
apt-get build-dep dwm
apt-get install make gcc
apt-get install feh
apt-get install suckless-tools
exit
You won't need to install suckless-tools if you have already installed and removed the stock binary dwm package. The dmenu provides the only way of loading programs other than launching them from a terminal.
Next, in your home create a directory to put the build files in and get the Debain source package and unpack it.
mkdir ~/build
cd ~/build
su
apt-get source dwm
cd dwm_5.8.2 (or whatever version number you find)
exit
You edit config.h to change the settings for dwm. You may need to copy config.default.h or config.def.h to config.h if there is not a config.h file to begin with.
I would suggesting compiling dwm with the 'stock' config.h first just to make sure everything works, then start to change the configurations.
To compile, issue the command below as root in the dwm-5.8.2 directory...
make clean install
Above command installs at /usr/local/bin.
You can edit config.h then re-issue this command, and the new installation will write over the old one. You won't see changes until you log out of dwm by using MOD-Shift-Q and logging in again.
My minimally changed config.h is at the end of this page. A quick search for 'dwm config.h' will pull up many other examples.
You need to provide a dwm.desktop file at /usr/share/xsessions/dwm.desktop to have a dwm entry in the session menu on the log-in screen. My desktop file does not start dwm directly, it points to a start up script dwm-start at /usr/local/bin. You may find a dwm.desktop file already on your computer if you installed the repository version of dwm, then removed it. That file can be edited using nano from root, or you can copy this one and write over the old one.
[Desktop Entry]
Encoding=UTF-8
Name=dwm
Comment=This session starts dwm
Exec=/usr/local/bin/dwm-start
Type=Application
You copy the files to /usr/local/bin using cp as root, just change to the directory in your home drive where you wrote dwm.desktop and dwm-start and...
su
cp dwm.desktop /usr/share/xsessions/
cp dwm-start /usr/local/bin/dwm-start
chmod 755 /usr/local/bin/dwm-start
exit
The dwm-start script sets the background (using feh) and starts the dropbox daemon, and then calls dwm last of all. I pinched this script and the dwm.desktop file from Johan Guldmyr's blog post.
#!/bin/sh
# xsetroot is a way of putting stuff on the top bar
# the loop reads some information in to variables
# which xsetroot shoves out to the top bar every
# 10 seconds.
while true; do
# memory free, note use of backticks AND apostrophes in the line below
memfreak2=`grep MemFree /proc/meminfo | awk '{ print $2 }'`;
memfreak=$(( $memfreak2/1024 ));
# time
CLK=$( date +'%a %b %d %R')
# Johan warns not to put the pipe character | just after the speech marks
xsetroot -name "$memfreak MB | $CLK "
sleep 10
done & # end of the loop
# background
sleep 1
feh -z -Z --bg-scale /home/yourusername/Pictures/trees.jpg
# start the dropbox daemon and any other start up programs
# the & after the program location allows the rest of the
# script file to be read and executed
/home/yourusername/.dropbox-dist/dropboxd &
# start dwm last as it never returns control to this script
exec /usr/local/bin/dwm > /dev/null
Next, alter the sudo file to allow sudo without password for shutdown operations. Then you can make a simple one line script that allows dmenu to run the sudo shutdown command and shut your computer down. I personally use hibernate more as then I can resume where I left off. I would suggest reading the Debian Wiki page about sudo before following the recipe below.
su
visudo
Add these lines to the sudoers file
# User alias specification
User_Alias MYADMINS = myusername, anotherusername
# Cmnd alias specification
Cmnd_Alias SHUTDOWN = /sbin/shutdown, /sbin/reboot, /sbin/halt, /usr/sbin/pm-hibernate
Cmnd_Alias PKGMGMT = /usr/bin/dpkg, /usr/bin/apt-get, /usr/bin/apt-get
# User privilege specification
MYADMINS ALL = PKGMGMT, SHUTDOWN
root ALL=(ALL) ALL
# Allow members of group sudo to execute any command
# (Note that later entries override this, so you might need to move
# it further down)
%sudo ALL=(ALL) ALL
#
#includedir /etc/sudoers.d
MYADMINS ALL= NOPASSWD: SHUTDOWN
Its the last line that means sudo shutdown will shut the pc down without a password, and that line must be after the root ALL line.
Dmenu is used to invoke all software, so a small one line script called hibernate allows me to hibernate the PC directly (I use this a lot to avoid time lost loading software and setting up windows. The file 'hibernate' has just one line.
echo `sudo pm-hibernate`
and is saved with 755 permissions at /usr/local/bin, which is on the path and which dmenu picks up. Note that the command is surrounded by 'back ticks', not ordinary speech marks or aprostrophes. Back ticks tell the bash interpreter to run the command within them. See section 3.4.5 of the Bash Beginners Guide.
Similar one liners could be added for shutdown, e.g.
echo `sudo /sbin/shutdown -h -P now`
Below are the command line commands to copy the files and set the permissions.
su
cp shutdown /usr/local/bin
chmod 755 /usr/local/bin/shutdown
exit
My config.h is below. The only changes I have made are to change the top bar background colour to black, highlight the current window with a 2px wide red border, make the main pane of the tiled layout is two thirds of the screen (roughly 1280 px on my 1920 monitor). The most important modification is to set MODKEY to Mod4Mask, so the windows key replaces the Alt key. The Alt key is used in too many other applications.
/* See LICENSE file for copyright and license details. */
/* appearance */
static const char font[] = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*";
static const char normbordercolor[] = "#cccccc";
static const char normbgcolor[] = "#cccccc";
static const char normfgcolor[] = "#000000";
static const char selbordercolor[] = "#FF0000";
static const char selbgcolor[] = "#000000";
static const char selfgcolor[] = "#ffffff";
static const unsigned int borderpx = 2; /* border pixel of windows */
static const unsigned int snap = 32; /* snap pixel */
static const Bool showbar = True; /* False means no bar */
static const Bool topbar = True; /* False means bottom bar */
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
static const Rule rules[] = {
/* class instance title tags mask isfloating monitor */
{ "Gimp", NULL, NULL, 0, True, -1 },
{ "Firefox", NULL, NULL, 1 << 8, False, -1 },
};
/* layout(s) */
static const float mfact = 0.67; /* factor of master area size [0.05..0.95] */
static const Bool resizehints = True; /* True means respect size hints in tiled resizals */
static const Layout layouts[] = {
/* symbol arrange function */
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
};
/* key definitions */
#define MODKEY Mod4Mask
#define TAGKEYS(KEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
/* commands */
static const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-nb", normbgcolor, "-nf", \
normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL };
static const char *termcmd[] = { "x-terminal-emulator", NULL };
static Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
{ MODKEY, XK_b, togglebar, {0} },
{ MODKEY, XK_j, focusstack, {.i = +1 } },
{ MODKEY, XK_k, focusstack, {.i = -1 } },
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
{ MODKEY, XK_Return, zoom, {0} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
{ MODKEY, XK_period, focusmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
TAGKEYS( XK_4, 3)
TAGKEYS( XK_5, 4)
TAGKEYS( XK_6, 5)
TAGKEYS( XK_7, 6)
TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
{ MODKEY|ShiftMask, XK_q, quit, {0} },
};
/* button definitions */
/* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static Button buttons[] = {
/* click event mask button function argument */
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
{ ClkWinTitle, 0, Button2, zoom, {0} },
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
};
I'd like to build a .deb package for use on other computers using dkpg, but, so far I have not worked out how to modify the configuration then recompile the 'debian way'. See my post on the Debian forums for some advice on packaging approaches from user stevepusser. It gives you an insight into the amount of detailed work involved in preparing programs for repositories.
Keith Burnett, Last update: Fri Dec 02 2011