Sep 30 2009

Personnaliser le clavier sous Linux avec Xkb

Category: Configuration,Linux

Résumé

Cet article aborde succinctement la personnalisation du clavier sous Linux, distribution Debian en l'occurrence, à l'aide de l'utilitaire Xkb (pour « X keyboard extension »). Pour des informations plus complètes sur le sujet, se reporter à la page « Personnaliser le clavier » du wiki de Mandriva.


Xmodmad est obsolète

La méthode la plus utilisée pour modifier le mapping (« la cartographie » en français) du clavier consiste à passer par l'utilitaire xmodmap ; cette méthode est obsolète depuis au moins 2003 comme le souligne ce document :
NOTE: Xmodmap is obsolete, please use the Xkb extensions. Future releases of XFree86 might not even support user's defined xmodmaps. Nous utiliserons donc Xkb pour personnaliser le clavier.


Configuration générique

La configuration par défaut (pour tous les utilisateurs) du clavier sous X est donnée par le fichier /etc/X11/xorg.conf, elle ressemble en général à cela:

Section "InputDevice"
  Identifier  "Generic Keyboard"
  Driver      "kbd"
  Option      "XkbRules" "xorg"
  Option      "XkbModel" "pc105"
  Option      "XkbLayout" "fr"
  Option      "XkbVariant" "oss"
EndSection
        

Cela signifie que l'on utilise le pilote kbd (pour KeyBoard driver) et que l'on passe à Xkb les options de configuration par défaut, à savoir: les règles définies par xorg, un clavier pc105 français et la variante oss qui permet d'obtenir facilement les lettres À, Ç, É, È etc en utilisant la touche CapsLock (on peut voir à quoi ressemble cette disposition ICI).

Personnalisation de la configuration du clavier

Il s'agit ici de configurer le clavier d'un utilisateur donné.

Fichier de configuration de base

Pour afficher l'équivalent Xkb de la configuration faite pas xorg il suffit d'exécuter la commande setxkbmap -print. Ainsi la commande setxkbmap -print > ~/pi-keymap va créer, dans votre home, le fichier pi-keymap ci-dessous. Pour plus d'information sur la structure de ce fichiers voir ICI.
C'est ce fichier que nous allons modifier pour personnaliser le clavier:

xkb_keymap {
        xkb_keycodes  { include "evdev+aliases(azerty)" };
        xkb_types     { include "complete"      };
        xkb_compat    { include "complete"      };
        xkb_symbols   { include "pc+fr(oss)+inet(evdev)+level3(ralt_switch)"    };
        xkb_geometry  { include "pc(pc105)"     };
};
        

La modification de ce fichier ne deviendra effective qu'après avoir exécuté la commande xkbcomp -w 0 ~/.pi-keymap $DISPLAY.

Mapper une touche dont on connaît le keycode

Rappel sur le keycode

Le keycode d'une touche est un nombre entier associé par le serveur X à cette touche. Pour connaître le keycode d'une touche, on peut utiliser l'utilitaire xev en ligne de commande. Par exemple, après avoir tapé la commande xev, la pression de la touche de navigation Retour arrière déclenche les messages suivants:

KeyPress event, serial 28, synthetic NO, window 0x3200001,
    root 0x66, subw 0x0, time 5779783, (18,329), root:(18,345),
    state 0x0, keycode 166 (keysym 0x1008ff26, XF86Back), same_screen YES,
    XLookupString gives 0 bytes:
    XmbLookupString gives 0 bytes:
    XFilterEvent returns: False

KeyRelease event, serial 28, synthetic NO, window 0x3200001,
    root 0x66, subw 0x0, time 5779837, (18,329), root:(18,345),
    state 0x0, keycode 166 (keysym 0x1008ff26, XF86Back), same_screen YES,
    XLookupString gives 0 bytes:
    XFilterEvent returns: False
        

Ce qui nous permet de conclure que la touche en question porte le doux nom de XF86Back (c'est plus exactement son keysym) et que son keycode est 166. D'ailleurs, si l'on a la curiosité d'ouvrir le fichier /usr/share/X11/xkb/symbols/inet on verra, vers la ligne 145 le code suivant

key <I166>   {      [ XF86Back              ]       };
        

On comprends alors comment procéder pour modifier le comportement de cette touche. Dans le cas présent la touche XF86Back correspond au « retour arrière » des navigateurs WEB et, comme la plupart des navigateurs utilisent le raccourci Alt-Left pour aller en arrière, il est légitime de vouloir changer le comportement de XF86Back en, par exemple, « faire défiler la page vers le bas ».

Assignons à la touche de keycode 166 le même comportement que la touche PgeUp

Comme nous l'avons compris, il nous suffit de reprendre le code précédent en modifiant XF86Back par le keysym de la touche PgeUp; un coup de xev donne immédiatement le keysym Prior. D'ailleurs, dans le fichier /usr/share/X11/xkb/symbols/pc se trouve la ligne définissant la touche en question:

key <PGUP> {	[  Prior		]	};
        

Ainsi, pour assigner la fonction Prior à la touche de keycode 166, et tant qu'on y est la fonction Next à la touche de keycode 167, on mettra dans le fichier pi-keymap:

xkb_symbols   {
              include "pc+fr(oss)+inet(evdev)+level3(ralt_switch)"
              key <I167> { [ Next ] };   // La touche de keycode 167 devient pgDown
              key <I166> { [ Prior ] }; // La touche de keycode 166 devient pgUp
};
        

Mapper la touche [espace] pour avoir une espace insécable

Avant de poursuivre il faut savoir qu'une touche possède par défaut plusieurs niveau:
 niveau 1 → touche pressée ;
 niveau 2 → majuscules+touche ;
 niveau 3 → Alt_Graph+touche ;
 niveau 4 → Alt_Graph+Majuscules+touche.
Ainsi le code ci-dessous permet de générer la lettre grec pi (π) avec le raccourci AltGr-p et Π avec le raccourci AltGr-Shift-p. Pour savoir pourquoi AD10 est le nom symbolique de « p », il faut jeter un œil ici.

key <AD10> { [ p,P,Greek_pi,Greek_PI ] };
        

Pour que le raccourci Shift-espace génère une espace insécable il suffit donc d'associer correctement la touche [espace] à la liste de caractères qu'elle doit générer suivant la touche modificatrice utilisée; cela donne:

// ␣ ; (espace insécable) ; _ ; (espace insécable fin)
key <SPCE> { [ space, nobreakspace, underscore, U202F ] };
        

On aura noté le « U » devant le 202F qui est le codage Unicode de « l'espace fine insécable ». Ainsi, Shift-espace donne une espace insécable, AltGr-espace donne une « barre en dessous » (underscore) et enfin AltGr-Shift-espace donne une espace fine insécable.

Modifier une touche modificatrice

Quand on utilise un gestionnaire de fenêtre comme Xmonad conjointement à Emacs sur un ordinateur portatif qui n'a ni « touche Widows » ni « touche Menu » avec en plus une « touche Fonction » qui merdoie marche mal... on change d'ordinateur on peut dissocier les « touches Control » pour utiliser le Control_Left comme touche de Control standard et réserver Control_Right à Xmonad. Voici le code qui permet de réaliser cette prouesse; il affecte la touche Control_R au modificateur Mod3:

xkb_symbols   {
              include "pc+fr(oss)+inet(evdev)+level3(ralt_switch)"
              modifier_map Mod3 { Control_R };
              };
        

Sans autre précaution, la commande xkbcomp -w 0 ~/.pi-keymap $DISPLAY retournera le charmant message d'erreur suivant:

Error:            Control_R added to symbol map for multiple modifiers
                  Using Mod3, ignoring Control.
        

Ce qui signifie clairement que le Control_R est bien devenu une touche modificatrice émancipée :-), qu'elle est accessible via Mod3 et qu'elle sera ignorée de Control; c'est bien ce que nous voulions... mais bon... si on pouvait éviter les messages d'erreurs...
Or donc, pour éviter ce message d'erreur qui n'en est pas un, en fait, il suffit de copier le fichier /usr/share/X11/xkb/symbols/pc en, par exemple, /usr/share/X11/xkb/symbols/pi_pc puis de remplacer dans icelui la ligne modifier_map Control{ Control_L, Control_R }; par modifier_map Control{ Control_L };
Ainsi, au lieu d'inclure le fichier pc, il suffit maintenant d'inclure le fichier pi_pc:

xkb_symbols   {
              include "pi_pc+fr(oss)+inet(evdev)+level3(ralt_switch)"
              modifier_map Mod3 { Control_R };
              };
        

Conclusion

Après avoir rappelé les rudiments de la configuration clavier du serveur X, les notions de keycode, de keysym et comment les obtenir grâce à xev, nous avons vu comment personnaliser la configuration du clavier en modifiant une touche d'après son keysym ou son keycode en utilisant des variables prédéfinies (comme Next, Prior, Greek_pi etc) ou le codage Unicode d'un caractère (comme 202F pour l'espace fine insécable).
Vous trouverez ci-après la configuration complète du clavier tel que je l'utilise actuellement avec Xmonad. Pour charger automatiquement cette configuration, il suffit d'ajouter dans votre fichier ~/.xsession la commande xkbcomp -w 0 -R/usr/share/X11/xkb/ ~/.pi-keymap $DISPLAY.

//Table pi_fr
default xkb_keymap "pi_fr"  {
    xkb_keycodes  {
                  include "evdev+aliases(azerty)"
                  };
    xkb_types     { include "complete"	};
    xkb_compat    { include "complete"	};
    xkb_symbols   {
                  // /usr/share/X11/xkb/symbols/pc/pi_pc est une
                  // copie de /usr/share/X11/xkb/symbols/pc
                  // à laquelle on remplacé la ligne
                  // modifier_map Control{ Control_L, Control_R };
                  // par modifier_map Control{ Control_L };
                  include "pi_pc+fr(oss)+inet(evdev)+level3(ralt_switch)"

                  // AltGr-I167 : ↣ ; AltGr-Shift-I167 : ↣
                  key <I167> { [ Next , Next , U21A3, U21D2 ] };

                  // AltGr-I166 : ↢ ; AltGr-Shift-I166 : ⇐
                  key <I166> { [ Prior, Prior, U21A2, U21D0 ] };

                  // AltGr-Up : ↑ ; AltGr-Shift-Up : ↥
                  key   <UP> { [ Up   , Up   , U2191, U21A5 ]	};

                  // AltGr-Down : ↓ ; AltGr-Shift-Down : ↧
                  key <DOWN> { [ Down , Down , U2193, U21A7 ]	};

                  // AltGr-Left : ← ; AltGr-Shift-Left : ↤
                  key <LEFT> { [ Left , Left , U2190, U21A4 ]	};

                  // AltGr-Right : → ; AltGr-Shift-Right : ↦
                  key <RGHT> { [ Right , Right , U2192, U21A6 ]	};

                  // ␣ ; (espace insécable) ; _ ; (espace insécable fin)
                  key <SPCE> { [ space, nobreakspace, underscore, U202F ] };

                  // AltGr-P : π ; AltGr-Shift-p : Π
                  key <AD10> { [ p,P,Greek_pi,Greek_PI ] };

                  //modifier_map Control { Control_L };
                  modifier_map Mod3 { Control_R };
                  };
    xkb_geometry  { include "pc(pc105)"	};
};
      

Et, pour finir cette article en beauté, la cartographie du clavier que l'on obtient en ascii art.

// Unicode French derivative
// Loose refactoring of the historic Linux French keyboard layout
//
// Copyright © 2006-2008 Nicolas Mailhot <nicolas dot mailhot at laposte dot net>
//
// Credits (fr-latin1, fr-latin0, fr-latin9)
//   © 199x-1996 René Cougnenc ✝
//   © 1997-2002 Guylhem Aznar <clavier at externe dot net>
//   © 2003-2006 Nicolas Mailhot <nicolas dot mailhot at laposte dot net>
//
// ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┲━━━━━━━━━┓
// │ ³ ¸ │ 1 ̨ │ 2 É │ 3 ˘ │ 4 — │ 5 – │ 6 ‑ │ 7 È │ 8 ™ │ 9 Ç │ 0 À │ ° ≠ │ + ± ┃ ⌫ Retour┃
// │ ² ¹ │ & ˇ │ é ~ │ " # │ ' { │ ( [ │ - | │ è ` │ _ \ │ ç ^ │ à @ │ ) ] │ = } ┃  arrière┃
// ┢━━━━━┷━┱───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┺━┳━━━━━━━┫
// ┃       ┃ A Æ │ Z  │ E ¢ │ R Ê │ T Þ │ Y Ÿ │ U Û │ I Î │ O Œ │ P Π │ ¨ ˚ │ £ Ø ┃Entrée ┃
// ┃Tab ↹  ┃ a æ │ z â │ e € │ r ê │ t þ │ y ÿ │ u û │ i î │ o œ │ p π │ ^ ~ │ $ ø ┃   ⏎   ┃
// ┣━━━━━━━┻┱────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┺┓      ┃
// ┃        ┃ Q Ä │ S „ │ D Ë │ F ‚ │ G ¥ │ H Ð │ J Ü │ K Ï │ L Ŀ │ M Ö │ % Ù │ µ ̄ ┃      ┃
// ┃Maj ⇬   ┃ q ä │ s ß │ d ë │ f ‘ │ g ’ │ h ð │ j ü │ k ï │ l ŀ │ m ö │ ù ' │ * ` ┃      ┃
// ┣━━━━━━━┳┹────┬┴────┬┴────┬┴────┬┴────┬┴────┬┴────┬┴────┬┴────┬┴────┬┴────┲┷━━━━━┻━━━━━━┫
// ┃       ┃ > ≥ │ W “ │ X ” │ C ® │ V ← │ B ↑ │ N → │ ? … │ . . │ / ∕ │ § − ┃             ┃
// ┃Shift ⇧┃ < ≤ │ w « │ x » │ c © │ v ⍽ │ b ↓ │ n ¬ │ , ¿ │ ; × │ : ÷ │ ! ¡ ┃Shift ⇧      ┃
// ┣━━━━━━━╋━━━━━┷━┳━━━┷━━━┱─┴─────┴─────┴─────┴─────┴─────┴───┲━┷━━━━━╈━━━━━┻━┳━━━━━━━┳━━━┛
// ┃       ┃       ┃       ┃ ␣         Espace fine insécable ⍽ ┃       ┃       ┃       ┃
// ┃Ctrl   ┃Meta   ┃Alt    ┃ ␣ Espace       Espace insécable ⍽ ┃AltGr ⇮┃Menu   ┃Ctrl   ┃
// ┗━━━━━━━┻━━━━━━━┻━━━━━━━┹───────────────────────────────────┺━━━━━━━┻━━━━━━━┻━━━━━━━┛