Administrivia
  1. Administrativia
  2. Utiliser et configurer XMonad
  3. Appeler Emacs depuis un navigateur, sous un Debian-like

Utiliser et configurer XMonad

(Gabriel Scherer (gasche) @ 2010-07-18 16:49:01)

Comme beaucoup d’utilisateurs d’interface graphique, je n’aime pas beaucoup la souris. Cela fait un certain temps que j’effectue la plupart des tâches avec principalement le clavier, en particulier tout ce qui doit être fait rapidement. La gestion des fenêtres en fait partie : on a envie de pouvoir passer très vite d’un logiciel à un autre (le classique Alt-Tab), d’un bureau virtuel à un autre, etc.

Cela fait donc quelques mois que j’utilise mon gestionnaire de fenêtres (quel qu’il soit, en pratique Kwin ou Xfwm selon l’humeur, mais à mon stage j’utilise Metacity) principalement avec le clavier. De là vient l’idée naturelle : pourquoi ne pas utiliser un gestionnaire de fenêtre pensé pour être utilisé avec le clavier ? Ce serait certainement encore plus adapté.

J’ai donc envisagé plusieurs alternatives (wmii, etc.), sans les tester (la flemme), et j’ai finalement choisi XMonad. C’est hype, c’est minimaliste, c’est codé dans un langage que j’aime bien (Haskell), bien conçu (Zipper et tout le tralala), bien documenté, ils insistent sur le fait d’avoir peu de lignes de code (j’aime bien), et ils essaient d’exprimer formellement et de vérifier des propriétés de leur programme (pas avec Coq, on ne peut pas tout avoir, mais avec QuickCheck).

J’ai donc fait l’effort d’installer XMonad, de lire la documentation de base (je n’ai retenu au départ que cinq raccourcis). Il y a quelques glitches (par exemple au lancement emacs n’occupe pas tout l’espace de sa fenêtre), mais qui n’en a pas ?

J’ai pris un peu de temps pour le configurer, en pratique ça veut dire installer et utiliser deux petits programmes qui « font une seule chose et le font bien », conseillés par la documentation XMonad :

xmobar

une petite barre de tâches que l’on configure en lui envoyant des infos sur l’entrée standard, simplissime.

dmenu

un outil de lancement de programme tout simple (on tappe le nom de l’exécutable jusqu’au moment où on peut auto-compléter, et on fait « Entrée ») ; écrit par les gens de suckless, qui sont cools et aiment Plan9.

Je me suis fait un fichier de configuration XMonad qui résume tout ça, au cas où ça vous intéresse. Dans la suite de ce billet, je détaillerai cette configuration. Ça n’est certainement pas une référence sur l’utilisation de ces outils, j’ai d’ailleurs sans doute fait une ou deux bêtises dans ces configurations, mais le but est de montrer que c’est plutôt facile, au cas où ça motiverait des vocations.


La base de la base

Pour installer XMonad, on peut télécharger la version de développement du code et l’installation à la main, ou passer par le gestionnaire de paquets de son système d’exploitation. La seconde version est évidemment plus simple.

Dans tous les cas, on se retrouve avec une installation plutôt de base, et en particulier un fichier de configuration essentiellement vide. Pour lancer XMonad, il suffit de partir d’une session X sans gestionnaire de fenêtres (par exemple en ayant lancé xinit depuis un terminal) et de lancer xmonad. Comme tout repose sur le clavier, il faut avoir à l’avance une idée des raccourcis ; man xmonad est là pour ça. D’après mon expérience, mod-j (changer de fenêtre), mod-shift-p (lancer une commande) et mod-space (changer de mode d’affichage) sont les seules commandes à retenir pour débuter.

mod-j, mod-k passer le focus à la fenêtre précédente/suivante
mod-[1..9] changer de bureau virtuel
mod-shift-[1..9] déplacer la fenêtre sous le focus vers un bureau virtuel
mod-space changer d’agencement des fenêtres
mod-p lancer dmenu
mod-shift-p lancer une commande

L’inconvénient du fichier de configuration minimaliste, c’est qu’il faut rajouter tout ce qu’on veut configurer en plus. On peut le faire en lisant la doc mais c’est assez délicat : je trouve qu’on s’en sort beaucoup plus vite en bidouillant un exemple qui fonctionne déjà. J’ai donc téléchargé le modèle de configuration XMonad, un long fichier Haskell qui fait la même chose que la configuration par défaut, mais plus bruyamment. On peut alors jeter un coup d’oeil aux différentes parties de la conf, et bidouiller ce qui nous plaît.

Le reste du post est organisé comme une description du diff entre ma configuration XMonad et ce modèle (template) fourni : un bout du diff, et un commentaire sur la signification de la chose, et éventuellement les informations et les fichiers liés.


Imports sans grand intérêt

+import XMonad.Layout.NoBorders
+import XMonad.Hooks.DynamicLog
+import XMonad.Hooks.ManageDocks

Trois imports de bibliothèque en haut du fichier de configuration. Certaines parties de la configuration que j’ai changées dépendent de ces imports. Vous allez voir.

Dans XMonad, la fenêtre qui a le focus est entourée d’une fine et élégante bordure rouge. NoBorders permettra de configurer les dispositions de fenêtres (Layout) pour que les fenêtres en mode plein écran ne soient pas entourées : une telle fenêtre étant seule à l’écran, on se doute bien qu’elle a le focus.

ManageDocks permettra de réserver un peu d’espace d’affichage pour la barre de tâches xmobar. DynamicLog servira à envoyer en continu à cette barre de tâches des informations sur le système.

Changement du terminal par défaut

 -- The preferred terminal program, which is used in a binding below and by
 -- certain contrib modules.
 --
-myTerminal      = "xterm"
+myTerminal      = "gnome-terminal"

Attention à ne pas confondre les -, + du diff, et les -- qui dénotent un commentaire Haskell.

J’utilise gnome-terminal par défaut, parce qu’il affiche bien l’unicode (j’utilise beaucoup de lettres grecques dans mes programmes) et possède des tabs, ce qui reste bien pratique. Les gens de suckless, que j’ai déjà mentionnés car ils s’ocupent de dmenu, ont un outil qui s’appelle tabbed, qui permet en théorie d’apporter des tabs de l’extérieur à des programmes individuels, c’est sympa mais j’ai la flemme d’essayer.

Choix de la touche mod pour les raccourcis

-myModMask       = mod1Mask
+myModMask       = mod3Mask

La touche nommée mod dans la parlance XMonad est la touche centrale, utilisée pour la grande majorité des raccourcis claviers. C’est une touche abstraite, et on peut choisir la touche physique du clavier à laquelle elle correspond. On pourra l’associer par exemple à la touche « Contrôle » pour avoir des raccourcis de la forme ctrl+j, ou à la touche « Alt » pour avoir alt+j.

En réalité, l’association n’est pas si directe, elle passe par le serveur X, qui reçoit de votre clavier des keycodes (« code des touches » ?), et les transforme en keysyms (« symbole des touches » ?), qui sont ensuite envoyés aux applications. Dans XMonad, on choisit quel keysym représentera la touche mod, mais on peut aussi changer la touche en amont en s’attaquant directement à la traduction des keycodes, qui est faite par xmodmap, un outil du serveur X.

C’est d’ailleurs ce que je fais : j’ai mis le symbole mod3 comme touche mod dans XMonad, mais j’utilise xmodmap pour envoyer la touche « Caps lock » vers le symbole mod3. C’est fait dans un petit script, que j’ai nommé startxmonad.sh, qui appelle xmodmap juste avant le lancement de xmonad :

setxkbmap us intl
xmodmap -e "remove Lock = Caps_Lock"
xmodmap -e "add Mod3 = Caps_Lock"
xmonad

On charge la disposition par défaut du clavier, on réassigne la touche Caps_Lock au keysym Mod3, et le tour est joué.

Bureaux virtuels

-myWorkspaces    = ["1","2","3","4","5","6","7","8","9"]
+myWorkspaces    = with_tags ["web", "bibli", "code", "redac"]
+                where with_tags li = li ++ map show [(1 + length li)..9]

XMonad a l’équivalent des bureaux virtuels, qu’il appelle workspaces. On peut se déplacer dans le bureau virtuel numéro N avec le raccourci mod-N (mod-1, mod-2…). Par défaut, le nom de chaque workspace est son numéro, et c’est ce que ma barre de tâches affiche. Ma modification sert à donner aux quatre premiers bureaux des noms plus mignons et sémantiques, qui reflètent l’utilisation que j’en fait. La ligne where sert à montrer que je maîtrise le Haskell à fond, et que les bureaux suivants gardent leur numéro jusqu’à 9.

Légères modifications des dispositions des fenêtres

 -- The available layouts.  Note that each layout is separated by |||,
 -- which denotes layout choice.
 --
-myLayout = tiled ||| Mirror tiled ||| Full
+myLayout = avoidStruts (tiled ||| Mirror tiled ||| noBorders Full)

Comme dit au moment des imports, XMonad permet de choisir entre plusieurs dispositions de fenêtres différentes. J’ai repris les modes déjà présents (un mode plein-écran, Full, et deux modes avec une fenêtre principale, occupant la moitié de l’écran, et des fenêtres secondaires), en la modifiant légèrement. noBorders retire l’encadré rouge du mode plein écran, et avoidStruts sert à réserver de l’espace pour la barre de tâches ; je ne l’ai pas inventé tout seul, je l’ai lu dans la documentation.

Ajout de cas particuliers de fenêtres flottantes

 myManageHook = composeAll
     [ className =? "MPlayer"        --> doFloat
     , className =? "Gimp"           --> doFloat
+    , className =? "Display"        --> doFloat
+    , className =? "XVroot"         --> doFloat
     , resource  =? "desktop_window" --> doIgnore
     , resource  =? "kdesktop"       --> doIgnore ]

Par défaut, XMonad essaie de faire en sorte que chaque fenêtre occupe le maximum d’espace disponible. C’est chouette en général, mais ça peut devenir très laid quand on veut par exemple voir une image, et qu’elle est redimensionnée, sans respect des proportions, pour remplir parfaitement la place libre entre les fenêtres existantes. doFloat sert à rendre certaines fenêtres flottantes (non redimensionnées), et className =? fait visiblement un test sur la classe de la fenêtre X. Je ne connais pas les subtilités des fenêtres X, mais il y avait des lignes déjà présentes pour montrer l’exemple, et j’ai lu sur internet qu’il fallait utiliser l’utilitaire xprop pour récupérer la classe d’une fenêtre X. J’ai rajouté display et xv, mes visionnaires d’image en ligne de commande préférés (saviez-vous que display d’ImageMagick gère même le format de graphes dot quand il est compilé avec les bonnes options ?), et ça marche.

Configuration de xmobar

 -- Run xmonad with the settings you specify. No need to modify this.
 --
-main = xmonad defaults
+main = xmonad =<< xmobar defaults

main est la grosse fonction de Haskell, le moment où on lance carrément XMonad et tout. Je l’ai modifiée comme suggéré par la documentation de DynamicLog, pour qu’elle envoie des informations à xmobar, ma barre de tâches.

xmobar est un petit programme qui affiche une barre de tâches, lui aussi écrit en Haskell. Il faut le configurer indépendamment, concrètement j’ai mis le fichier suivant sous le nom ~/.xmonad/xmobarrc :

Config { font = "xft:DejaVu Sans-8:"
       , bgColor = "black"
       , fgColor = "grey"
       , position = Top
       , lowerOnStart = True
       , commands = [ Run StdinReader
                    , Run Network "eth0" ["-L","0","-H","32","--normal","green","--high","red"] 10
                    , Run Network "eth1" ["-L","0","-H","32","--normal","green","--high","red"] 10
                    , Run Cpu ["-L","3","-H","50","--normal","green","--high","red"] 10
                    , Run Memory ["-t","Mem: <usedratio>%"] 10
                    , Run Date "%a %b %_d %Y %H:%M:%S" "date" 10
                    ]
       , sepChar = "%"
       , alignSep = "}{"
       , template = " %StdinReader% }{ %cpu% | %memory% | <fc=#ee9a00>%date%</fc>"
       }

Je l’ai encore une fois adapté d’une configuration donnée dans la documentation. En gros, la disposition de la barre ressemble à ce qui est marqué dans template, et les définitions / configurations sont celles du champ commands. La partie StdinReader lit sur l’entrée standard, c’est-à-dire les informations données par xmonad, et affiche donc, sans que je lui ai rien demandé, mes bureaux virtuels en mettant en valeur celui sur lequel je me trouve, le nom de la disposition de fenêtres courantes, et le titre de la fenêtre qui a le focus. Le reste, c’est moi qui l’ai configuré comme un grand, ce sont des stats sur l’utilisation du CPU, de la mémoire (ça sert à rien mais c’est classe), et l’heure qu’il est (très utile par contre).

Utilisation avec Gnome

À mon stage, j’utilise une machine debian avec Gnome. Je pourrais installer autre chose, mais je n’aime pas beaucoup faire de l’administration sur mes heures de travail, et j’avais envie d’essayer pour voir comment ce bureau progresse.

À l’occasion d’un changement de machine, j’ai essayé la combinaison Gnome+Xmonad : utilise Gnome comme gestionnaire de bureau, mais avec Xmonad à la place de Metacity comme gestionnaire de fenêtre. C’est très facile à mettre en place, la démarche est expliquée dans la documentation. J’ai utilisé la solution la plus simple, à savoir créer /usr/share/applications/xmonad.desktop et /usr/share/xsessions/xmonad.desktop, et choisir Xmonad depuis GDM.

Ça donne un environnement assez agréable : la barre de tâches et la plupart des utilitaires Gnome sont actifs, ce qui est pratique pour avoir par exemple l’applet NetworkManager depuis notre session Xmonad (on pourrait peut-être coder quelque chose d’équivalent pour xmobar). mod-p appelle le lanceur d’application Gnome (que je trouve en réalité moins agréable que dmenu car plus intrusif), donc l’intégration est plutôt bonne.

Pour mon portable, qui a un petit écran 13", je préfère la sobriété et la finesse d’une xmobar configurée à la spartiate, mais je pense que les amateurs de gnome seraient satisfaits de la combinaison Gnome+Xmonad.

Multi-écran

Toujours à mon stage, j’utilise deux écrans. XMonad a, de base, un bon support du multi-écran : il met un bureau virtuel sur chaque écran, et on peut facilement changer le focus d’un écran à l’autre ou déplacer des applications.


Le mot de la fin

Voilà, j’ai fait le tour de ma configuration XMonad. C’est vraiment pas très compliqué. Est-ce que ça vaut le coup ?

Ce dont j’avais peur, c’est que ces outils (les tiling window managers) soient trop élite pour moi : le truc qu’il faut comprendre en profondeur pour pouvoir utiliser, et après on est super-productif de la mort, mais il faut commencer par se farcir des kilomètres de doc. En pratique ce n’est pas du tout l’expérience que j’ai vécue avec Xmonad, j’ai juste retenu deux ou trois raccourcis indispensables et bidouillé un peu la configuration en copiant-collant lâchement ce que je trouvais sur le net, et en quelques essais j’ai quelque chose de simpliste qui me convient bien.

Je pense que je suis essentiellement aussi productif qu’avant, avec Kwin ou Xfwm, et c’est vrai que je m’embête moins à agrandir mes fenêtres, les changer de bureau ou d’écran, etc. L’avantage principal reste le sentiment satisfaisant et rassurant d’utiliser un outil simple, que l’on peut modifier si l’on veut, et adapté à l’usage qu’on en fait.