DWM

De ArchwikiFR


DWM , ou "Dynamic Window Manager", est un Gestionnaire de fenêtres simple, léger et rapide. Il appartient au projet suckless. Il utilise le principe du tilling pour afficher les fenêtres sur l’écran, c’est-à-dire qu’il utilise au mieux l’espace disponible sur l'écran. Il se configure en modifiant directement le fichier source (en C) et se compile en un seul binaire.

Sommaire

Installation

Pour installer DWM, entrez en console :

pacman -S dwm

Vous pouvez également installer dmenu pour afficher une barre de lancement d'applications.

Vous pouvez également installer DWM à partir des sources via git ou le site officiel de DWM puis compiler. Pour installez git, entrez :

pacman -S git

Placez vous dans le répertoire de votre choix et tapez la commande suivante pour récupérer la version actuelle de DWM :

git clone http://git.suckless.org/dwm

Git va télécharger la version à jour de DWM dans le répertoire ./dwm/. Une fois le téléchargement fini, vous allez pouvoir commencer à configurer DWM. Une fois votre configuration terminée, pour compiler DWM, il suffit de lancer la commande :

make 

Enfin vous pouvez installer DWM avec la commande :

make install
Attention: Installé de cette façon, dwm ne sera pas suivi par le gestionnaire de paquet et l'exécutable se situera par défaut dans /usr/local/bin.

Autre Installation

Vous pouvez aussi récupérer dwm via ABS avec la commande :

abs community/dwm
Note: Par défaut, abs utilise le répertoire /var/abs/ qui n'est accessible que par le root, n'hésitez pas à configurer abs pour pouvoir l'utiliser en utilisateur.

Allez dans le répertoire $ABSROOT/community/dwm et récupérez les sources avec:

makepkg -o

Après avoir effectué les modifications du config.h, compilez, créez le paquet et installez-le avec la commande:

makepkg -ei

Lancement

Pour lancer DWM avec le fichier ~/.xinitrc, il suffit d’appeler DWM de cette façon :

exec dwm

Raccourcis par défaut

Si vous avez installé DWM en utilisant le paquet voici une liste des principaux raccourcis clavier :

 Alt+p lancez dmenu
 Alt+Maj+Enter lancez un terminal (uxterm par défaut)
 Alt+j Sélectionnez la fenêtre suivante
 Alt+k Sélectionnez la fenêtre précédente
 Alt+h Réduire la taille de la master area
 Alt+l Augmentez la taille de la master area
 Alt+Maj+c Fermez la fenêtre courante
 Alt+Maj+q Fermez DWM
 Alt+[0..9] Allez au bureau [0..9]

Configuration

La configuration de DWM ne demande pas d'énormes compétences en programmation mais juste un peu de logique. La personnalisation se base surtout sur le fichier config.def.h mais vous pouvez tout de même, si vous le voulez, ajouter de nouvelles fonctionnalités en modifiant dwm.c. Les premiers paramètres que vous pouvez modifier facilement sont la police utilisée par DWM, et les couleurs de l'environnement. Pour vous donner un exemple de configuration, voici le début de mon config.def.h :

Attention: Il est préférable de configurer le fichier config.h qui est créé à partir de config.def.h lors de la première compilation de dwm. config.h sera pris automatiquement en compte comme fichier de configuration lors des compilations suivantes. Le fichier config.def.h vous servira de fichier de sauvegarde des paramètres par défaut de dwm en cas de pépins avec votre config.h.
 static const char font[]            = "-*-*-medium-*-*-*-10-*-*-*-*-*-*-*";
 static const char normbordercolor[] = "#ababab";
 static const char normbgcolor[]     = "#292929";
 static const char normfgcolor[]     = "#ff6b6b";
 static const char selbordercolor[]  = "#ababab";
 static const char selbgcolor[]      = "#292929";
 static const char selfgcolor[]      = "#ff6b6b";
 static const unsigned int borderpx  = 1;        /* 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 */

Pour éditer le type de police de la statubar de DWM, utilisez la commande xfontsel pour connaître les différentes types de fontes dont X dispose sur votre machine sous leurs formats XLFD (X Logical Font Description). Le choix des couleurs se fait en hexadécimal.

Fonction Description
normbordercolor[] Couleur de la bordure pour une fenêtre non sélectionnée
normbgcolor[] Couleur du fond de la barre pour les tags non courants
normfgcolor[] Couleur des tags non courants
selbordercolor[] Couleur de la bordure pour une fenêtre sélectionnée
selbgcolor[] Couleur du fond de la barre pour le tag courant et pour le titre de la fenêtre sélectionnée
selfgcolor[] Couleur du tag courant et du titre de la fenêtre
borderpx Largeur de la bordure entourant les fenêtres
snap Espace en pixels à partir du moment où la fenêtre se colle aux bords de l'écran

Mais l'une des choses les plus intéressantes dans DWM, ce sont les tags que l'on peut modifier :

 /* tagging */
 static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };

Les tags, c'est ce qui s'affiche en haut à gauche de votre écran. Vous pouvez créer par exemple un tag pour Firefox ou un autre pour mplayer etc ... Il suffit de modifier ou d'ajouter les valeurs dans le tableau tags[].

Une dernière chose intéressante à configurer est l'option permettant de respecter les "size hints". En effet, par défaut, DWM les respecte. Cela implique que si vous lancez une application, DWM va attribuer une hauteur et une largeur à la nouvelle fenêtre, mais qu'il va respecter le fait que l'application peut lui indiquer que ces dernières ne respectent pas un certains ratio et DWM va donc en tenir compte. Concrètement, il peut arriver qu'une des fenêtres ouvertes ne prenne pas toute la place de l'écran (en général, il s'agit de quelques pixels au niveau de la hauteur). Pour désactiver cette option, changez simplement cette ligne:

 static const Bool resizehints = True; /* True means respect size hints in tiled resizals */

en

 static const Bool resizehints = False; /* True means respect size hints in tiled resizals */

Les patchs

Un bon moyen d'ajouter des fonctionnalités à DWM, est d'aller ici et de télécharger des patchs, comme par exemple le patch azertykey qui permet d'adapter les raccourcis aux claviers français. Pour appliquer un patch, placez-vous dans le dossier dwm et entrez:

patch -p1 < /chemin/vers/patch.diff

Ou avec git

cd dwm-directory
git apply path/to/patch.diff

Les patchs sont très nombreux. Vous pouvez les trouvez dans la section du site officiel ou dans un sujet consacré sur le forum anglophone.

Clavier AZERTY

L'un des gros problème de DWM, c'est qu'il n'est pas configuré pour un clavier AZERTY. C'est à dire que les combinaisons de touches telles que [Alt][1] [...] [2] ne fonctionnent pas car il y a de mauvaises références dans le config.def.h. Pour résoudre ce problème, il faut connaître l'attribution des touches [1], [2] ... [9] par X. Pour ce faire, il faut ouvrir un terminal et taper xev. xev permet d'afficher certaines informations relatives aux évènements d'entrée de X, notamment ceux créés par notre clavier. Ainsi, nous pouvons connaître les keycodes et les keysyms de nos touches. Pour ma part, j'utilise les touches [1], [2] ... situés juste en haut des lettres puisque je n'ai toujours pas réussi à faire fonctionner mon pavé numérique.

Le tableau Key dans la partie TAGKEYS doit donc ressembler à cela :

	TAGKEYS(                        0x26,                      0)
	TAGKEYS(                        0xe9,                      1)
	TAGKEYS(                        0x22,                      2)
	TAGKEYS(                        0x27,                      3)
	TAGKEYS(                        0x28,                      4)
	TAGKEYS(                        0x2d,                      5)
	TAGKEYS(                        0xe8,                      6)
	TAGKEYS(                        0x5f,                      7)
	TAGKEYS(                        0xe7,                      8)

Les 0x26, 0xe9 etc ... sont les adresses vers les touches [1], [2] etc ... situés en haut des lettres et normalement en dessous de la série des F1, F2 etc ... Grâce à cette modification, vous pourrez naviguer dans DWM en faisant les combinaisons de touches normales telles que : [MOD] + [1] avec [MOD] = [Alt] par défaut. Pour une meilleure utilisation, en particulier avec Firefox, c'est de modifier la touche [MOD] qui équivaut à [Alt] par défaut, pour ce faire, il suffit juste de modifier ceci :

#define MODKEY Mod1Mask

par cela :

#define MODKEY Mod4Mask

Pour que la touche [MOD] devienne celle qui détient le logo Windows situé entre [Fn] et [Alt]. Pour que tout ceci s'applique, vous devez compiler en tapant ceci :

make clean && sudo make install

Il suffit alors d'éteindre votre gestionnaire de fenêtres (si vous êtes sous DWM, [MOD] + [Shift] + [Q] éteint DWM) et de vous reconnecter avec comme gestionnaire de fenêtres le DWM situé dans /usr/local/bin/dwm.

Clavier BÉPO

Le tableau Key dans la partie TAGKEYS pour un clavier BÉPO :

	TAGKEYS(                        0x22,                      0)
 	TAGKEYS(                        0xab,                      1)
 	TAGKEYS(                        0xbb,                      2)
 	TAGKEYS(                        0x28,                      3)
 	TAGKEYS(                        0x29,                      4)
 	TAGKEYS(                        0x40,                      5)
 	TAGKEYS(                        0x2b,                      6)
 	TAGKEYS(                        0x2d,                      7)
 	TAGKEYS(                        0x2f,                      8)

Pavé numérique

Pour ceux qui comme moi auraient un pavé numérique et qui voudraient bien changer de bureau à l'aide de celui-ci, cette partie est faite pour vous. Comme il est expliqué plus haut, DWM ne connait pas le clavier AZERTY, il faut donc lui dire quelles sont les touches pour le pavé numérique. Pour ce faire, nous utiliserons la même méthode qui est expliquée plus en haut en utilisant xev. Cependant, pour des raisons que j'ignore, il faut que le voyant Numlock ne soit pas activé pour savoir les keycodes de nos touches. Si tout se passe correctement, on obtient ceci :

	KP_End pour la touche 1 du pavé numérique
	KP_Down pour la touche 2
	KP_Next pour la touche 3
	KP_Left pour la touche 4
	KP_Begin pour la touche 5
	KP_Right pour la touche 6
	KP_Home pour la touche 7
	KP_Up pour la touche 8
	KP_Prior pour la touche 9

Maintenant, nous pouvons modifier le code de config.def.h. Cependant, il faut faire une toute petite modification pour que tout marche ! Il faut rajouter XK_ à tous nos keycodes comme cela et pour les autres touches qu'utilise DWM. Ainsi, pour pouvoir utiliser le pavé numérique pour changer de bureau, le tableau Key dans la partie TAGKEYS doit donc ressembler à cela :

	TAGKEYS(                        XK_KP_End,                      0)
	TAGKEYS(                        XK_KP_Down,                     1)
	TAGKEYS(                        XK_KP_Next,                     2)
	TAGKEYS(                        XK_KP_Left,                     3)
	TAGKEYS(                        XK_KP_Begin,                    4)
	TAGKEYS(                        XK_KP_Right,                    5)
	TAGKEYS(                        XK_KP_Home,                     6)
	TAGKEYS(                        XK_KP_Up,                       7)
	TAGKEYS(                        XK_KP_Prior,                    8)

Il suffit maintenant de compiler le tout avec make clean && sudo make install ! Et c'est terminé.

Touches multimédia

Si vous possédez un portable, ou encore un clavier avec des touches multimédia, il est très facile de les configurer pour qu'elles fonctionnent avec DWM. Voici par exemple un bout de ma configuration qui permet d'utiliser les touches multimédia pour contrôler ncmpcpp.

Dans un premier temps, il faut ajouter les commandes que vous souhaitez exécuter:

 static const char *next[]     = { "ncmpcpp", "next", NULL };
 static const char *prev[]     = { "ncmpcpp", "prev", NULL };
 static const char *toogle[]   = { "ncmpcpp", "toggle", NULL };
 static const char *volup[]    = { "amixer", "set" , "PCM", "10\%+", NULL};
 static const char *voldown[]  = { "amixer", "set" , "PCM", "10\%-", NULL};

Puis il suffit d'ajouter les raccourcis clavier dans le tableau "keys" en utilisant les définitions suivantes (vous pouvez les trouvez dans le fichier /usr/include/X11/XF86keysym.h):

 XF86XK_AudioLowerVolume
 XF86XK_AudioMute
 XF86XK_AudioRaiseVolume
 XF86XK_AudioPlay
 XF86XK_AudioStop
 XF86XK_AudioPrev
 XF86XK_AudioNext

Faites bien attention de ne pas utiliser MODKEY dans le tableau, mais la valeur '0' de la manière suivante:

 { 0,           XF86XK_AudioPrev,      spawn,      {.v = prev } },

L'autre manière qui marchera à tous les coups, si les définitions au-dessus ne marchent pas chez vous, est l'utilisation de la commande xev afin d'obtenir le code en hexadécimal de la touche voulue.

La pression de la touche dans la fenêtre de xev renverra son "contents of X events" (cf. man xev).

Par exemple lors de la pression de la touche Lecture, on obtiendra :

 KeyRelease event, serial 27, synthetic NO, window 0x1c00001,
   root 0xad, subw 0x0, time 11764695, (373,300), root:(373,315),
   state 0x0, keycode 172 (keysym 0x1008ff14, XF86AudioPlay), same_screen YES,
   XLookupString gives 0 bytes: 
   XFilterEvent returns: False

Ainsi le code hexadécimal de la touche Lecture est 0x1008ff14, ce qui est l'équivalent en hexadécimal de XF86XK_AudioPlay sur ma machine.

Avec ces techniques, vous pouvez configurer l'ensemble des touches de votre clavier.

Les règles

Dans votre config.h, la partie à configurer pour faire des règles est celle-ci :

static Rule rules[] = {
    /* class      instance    title       tags mask     isfloating */
    { "Gimp",     NULL,       NULL,       0,            True },
    { "Firefox",  NULL,       NULL,       1 << 8,       True },
};

Premièrement si vous voulez attribuer des règles à vos fenêtres, il va falloir récupèrer leurs WM_CLASS. Pour ce faire, utiliser la commande xprop et cliquer sur la fenêtre désirée avec votre souris.

Par exemple pour obtenir le WM_CLASS de icecat :

$ xprop WM_CLASS
WM_CLASS(STRING) = "Navigator", "GNU IceCat" 

Dans un deuxième temps, pour compléter vos règles vous allez devoir indiquer sur quel tag vous désirez que votre fenêtre s'ouvre.

Dwm a une façon particulière de gérer ses tag.

Par exemple :

le tag 1 est représenté par la représentation binaire d'entier 000000001,
le tag 2 est représenté par la représentation binaire d'entier 000000010,
…
le tag 9 est représenté par la représentation binaire d'entier 100000000.
le tag 1 + le tag 2 est représenté par la représentation binaire d'entier 000000011.
le tag 7 + le tag 3 est représenté par la représentation binaire d'entier 001000100.

Comme le tag 1 est représenté en binaire sur un entier par 000000001, si on lui applique un déplacement de bit, par exemple d'un bit, ce qui donne 1<<1 on obtiendra 000000010 soit le tag 2. De même, si on lui applique un déplacement de 2 bits, soit 1<<2 on obtiendra 000000100 => le tag 3.

Donc pour signifier à dwm, je veux que tu m'affiches icecat sur mon tag 6, on doit faire la règle comme ça :

 { "GNU IceCat",     NULL,       NULL,       1<<5,            True }, // car 1<<5 = 36 sur un entier en base dix soit 000100000 en binaire

Plus d'informations sur les tag mask de dwm ici.

La Statusbar

Généralité

La statusbar de dwm est généré de la manière suivante : la sortie standard du programme xsetroot est pris comme argument d'entrée standard par le programme dwm qui l'affichera alors dans sa statusbar.

Par exemple :

xsetroot -name "echo HelloWorld" & #affichera HelloWorld dans votre statusbar.

De cette manière, votre statusbar sera statique. Si vous désirez l'afficher de manière dynamique, il vous faudra utiliser une boucle.

Par exemple une boucle pour afficher l'heure :

while true; do xsetroot -name "$(date && sleep 1)"; done &

Pour automatiser tout ça, placez la ligne ci-dessus dans votre .xinitrc avant l'exécution de dwm.

Vous pouvez aussi bien lancé un script bash par xsetroot ou lui faire lire la sortie du programme Conky. Voir même coder un programme en dur pour afficher des informations dans votre statusbar.

Exemple avec un script bash

Fichier: .xinitrc
while true; do xsetroot -name "$(./monScript.sh)"; done &
exec /usr/local/bin/dwm
Fichier: monScript.sh
#!/bin/sh
date +"Time %H:%M %d/%m"

Exemple avec Conky

Fichier: .xinitrc
conky | while read -r; do xsetroot -name "$REPLY"; done &
exec /usr/local/bin/dwm
Fichier: .conkyrc
out_to_console yes
out_to_x no
background no
update_interval 2
total_run_times 0
use_spacer none

TEXT
Time ${time %H:%M %d/%m}

Exemple avec Conky & Dzen2

Un alternative à conky seul est l'utilisation du couple de commande conky & dzen2. Dzen2 vous permettra d'inclure des icons et des couleurs dans votre statusbar par Conky. Pour ceci, il vous faudra installer depuis AUR le paquet dzen2.

Fichier: .xinitrc
(sleep 1 && conky | dzen2 -fg '#FFFFFF' -bg '#000000' -fn '-*-fixed-bold-*-*-*-14-*-*-*-*-*-*-*' -ta r -x 500 ) &
# Options de dzen2
# -fg = foreground color
# -bg = background color
# -fn = font 
# -ta = alignement of title window content: l(eft), c(enter), r(ight)
# -x = x position
exec /usr/local/bin/dwm
Fichier: .conkyrc
out_to_console yes
out_to_x no
background no
update_interval 2
total_run_times 0
use_spacer none

TEXT
^i(/chemin/vers/l'/icon.xbm) ^fg(\CouleurEnHexadécimal)Time ${time %H:%M %d/%m}^fg()

Pour plus de détails sur les options et les nombreuses autres possibilités de dzen2 aller voir sa documentation ainsi que son site.

Exemple en code C

Si vous êtes un perfectionniste dans l'âme, vous pouvez coder un programme en C pour votre statusbar :

Fichier: .xinitrc
./statusbar &
exec /usr/local/bin/dwm
Fichier: statusbar.c
//Compilation: gcc -g -Wall -lX11 statusbar.c -o statusbar
//Le code parle de lui même avec man

#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h>//va_list vsnprintf
#include<X11/Xlib.h>//Display XOpenDisplay XStoreName DefaultRootWindow XSync XCloseDisplay
#include<unistd.h>//sleep
#include<time.h>//time tm localtime

static Display *display;

char *
chaineDeCaracteresAssembles(char *chaineDArguments,...)
{
  va_list listeDesArguments;
  char *chaineDeCaracteres;
  int longueurEnOctet;

  va_start(listeDesArguments,chaineDArguments);
  longueurEnOctet=vsnprintf(NULL,0,chaineDArguments,listeDesArguments);
  va_end(listeDesArguments);
  chaineDeCaracteres=malloc(++longueurEnOctet);
  if(chaineDeCaracteres==NULL) { perror("malloc dans chaineDeCaracteresAssembles"); exit(1); }
  va_start(listeDesArguments,chaineDArguments);
  vsnprintf(chaineDeCaracteres,longueurEnOctet,chaineDArguments,listeDesArguments);
  va_end(listeDesArguments);

  return chaineDeCaracteres;
}

char *
heureEtDate()
{
  time_t tim=time(NULL);
  struct tm *structureTm;

  structureTm=localtime(&tim);
  if(structureTm==NULL) { perror("localtime"); exit(1); }

  return chaineDeCaracteresAssembles("%.2d:%.2d %.2d/%.2d",structureTm->tm_hour,structureTm->tm_min,structureTm->tm_mday,structureTm->tm_mon+1);
}

int
main(void)
{
  char *statusBar;
  char *date;

  if(!(display=XOpenDisplay(NULL))) { perror("impossible d'ouvrir le display.\n"); return 1; }
  while(1)
  {
    date=heureEtDate();
    statusBar=chaineDeCaracteresAssembles("Time %s",date);
    XStoreName(display,DefaultRootWindow(display),statusBar);
    XSync(display,False);
    sleep(1);
    free(statusBar);
    free(date);
  }

  XCloseDisplay(display);
  return 0;
}
Outils personnels
Autres langues