TouchpadToggle : Gestion du touchpad

Le touchpad, je ne m'en sers que quand je ne peux pas faire autrement, c'est-à-dire quand je n'ai pas de souris. Par contre quand il est actif il me gène plus qu'autre chose et l'activité des mains sur le clavier provoque bien des erreurs. Il y a bien une touche de fonction prévue à cet usage sur mon ordinateur mais elle ne fonctionne pas nativement dans mon environnement de travail (Archlinux Openbox). Aussi je l'avais tout simplement (et paresseusement) désactivé en mettant dans mon autostart la première commande trouvée sur le web :
$ /usr/bin/synclient TouchpadOff=1 &

Curieusement cela n'affecte que le déplacement du pointeur, mais pas l'activité des boutons. ClickPad=0 résolvait partiellement le problème (le simple clic, mais pas le double) mais la recherche commençait à devenir pénible et je sentais bien que si je voulais une solution pérenne il me fallait reprendre le problème à la base. En l’occurrence la base c'est xorg (tant que Wayland n'aura pas définitivement remplacé xorg), et ça tombe bien, chez xorg ils ont commis un petit outil en ligne de commande pour gérer les périphériques d'entrée : xinput (que vous trouverez dans le paquet xorg-xinput de toutes les bonnes distributions).

Voici donc ma démarche et le petit script qui en résulte (voir à la fin de l'article). À adapter en fonction des besoins et du matériel.

Les objectifs :
  • fonctionner en bascule pour être intégré avec la susdite touche de fonction
  • détecter la présence ou non d'une souris au démarrage de ma session et désactiver le touchpad en fonction
  • afficher le résultat sous forme de notification
  • tout ceci indépendamment de l'environnement graphique

Vérifier les dépendances

avant toute chose vérifier que xinput est disponible, sinon ce n'est pas la peine d'aller plus loin.

if ! command -v xinput >/dev/null; then
    notify-send
--icon=dialog-error -t 7000 $Titre "Dépendance xorg-xinput non trouvée" 2>/tmp/touchpadError
     exit 1
fi

Pour bénéficier des notifications il faut que libnotify soit installé (voir ci-dessous) mais le message d'erreur éventuel sera enregistré dans /tmp

Prise en main de xinput

la commande xinput sans paramètre liste les périphériques détectés. Voici ce que cela donne chez moi :

[vincent@Astor ~]$ xinput
⎡ Virtual core pointer                            id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                  id=4    [slave  pointer  (2)]
⎜   ↳ Logitech USB Receiver                       id=10    [slave  pointer  (2)]
⎜   ↳ Logitech USB Receiver                       id=11    [slave  pointer  (2)]
⎜   ↳ ETPS/2 Elantech Touchpad                    id=15    [slave  pointer  (2)]
⎣ Virtual core keyboard                           id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard                 id=5    [slave  keyboard (3)]
    ↳ Power Button                                id=6    [slave  keyboard (3)]
    ↳ Video Bus                                   id=7    [slave  keyboard (3)]
    ↳ Video Bus                                   id=8    [slave  keyboard (3)]
    ↳ Sleep Button                                id=9    [slave  keyboard (3)]
    ↳ USB2.0 HD UVC WebCam                        id=12    [slave  keyboard (3)]
    ↳ Asus WMI hotkeys                            id=13    [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard                id=14    [slave  keyboard (3)]

Les renseignements qui nous intéressent sont le nom et l'identifiant. Ici on peut voir mon touchpad (ETPS/2 Elantech Touchpad, id=15) et ma souris (Logitech USB Receiver, id=10 et 11).

Pour aller plus loin une lecture de man s'impose. Les commande pour activer et désactiver un périphérique sont :

$ xinput enable identifiant
$ xinput disable identifiant

Arf... et évidement l'identifiant peut changer d'un boot à l'autre. Il faudra donc le lire. Quelque chose comme

DevID=$(xinput | grep "$NomTouchpad" | cut -d"=" -f2 | cut -d $'\\x09' -f1)

ou $NomTouchpad contient le nom du périphérique (ici ETPS/2 Elantech Touchpad)

Évidement si l'on ne trouve pas de touchpad (désactivé dans le BIOS ?) on s’arrêtera là :

if [[ -z $DevID ]]; then
    notify-send
--icon=dialog-info -t 5000 $Titre "Touchpad non trouvé"
    exit
0
fi

Pour savoir l'état d'un périphérique (actif ou nom) la commande est

$ xinput list-props identifiant

Le résultat donne ceci (c'est la 2ème ligne qui nous intéresse) :

$ xinput list-props 15
Device 'ETPS/2 Elantech Touchpad':
    Device Enabled (135):    0
    Coordinate Transformation Matrix (137):    1.000000, 0.000000...etc.

ici la ligne "Device Enabled (135) : 0" nous indique que le touchpad n'est pas actif. Pour isoler la variable on peut faire quelque chose comme ça :

Enabled=$(xinput list-props $DevID | grep Enabled | tail -c2)

Il suffit donc de tester cette variable pour connaître la commande à lancer. Voilà pour le fonctionnement en bascule.

Automatiser la désactivation au démarrage si une souris est détectée

Autant pour la détection du touchpad on peut estimer que le matériel n'évoluera pas pendant la durée de vie de l'ordinateur, autant on peut considérer que changer de souris, ne serait-ce qu’occasionnellement, ça doit pouvoir s'envisager. Donc repérer le périphérique par son nom ne semble pas une bonne idée.

En revanche si l'on observe la liste issue de la commande xinput ci-dessus on voit que la rubrique Virtual Core Pointer ne contient d'autre matériel que le touchpad et la souris. Donc si l'on ne retient que les lignes contenant le mot "pointeur" et ne contenant pas le mot "Virtual", et qu'il y en a au moins 2, ce serait bien le diable s'il n'y avait pas une souris la dedans. Il y a d'autres solutions possibles, notamment lsusb ou lshw, mais outre que cela créerait une dépendance supplémentaire, je n'ai pas trouvé de formulation aussi simple.

Pour savoir si le script est appelé au démarrage on recherchera un paramètre d'appel que l'on aura placé sur la ligne de commande. Et si oui on ne le poursuivra que dans la mesure ou on supposera l'existence d'une souris.

if [[ $1 == "autostart" ]]; then
     if (( $(xinput | grep pointer | grep -vc Virtual) < 2 )); then exit 0; fi
fi

Si le touchpad a été désactivé par erreur un simple appel de la touche de fonction associé le rétablira.

En matière d'autostart la solution la plus standard me semble la création d'un fichier desktop dans $XDG_CONFIG_HOME/autostart/ (généralement ~/.config/autostart). Ça devrait ressembler à ça  :

[Desktop Entry]
Name=TouchpadToggle
GenericName=Touchpad Toggle
Comment=Activation désactivation du touchpad
Exec=touchpadtoggle autostart
Terminal=false
Type=Application
Categories=System;
StartupNotify=false

À noter le paramètre autostart passé sur la ligne de commande et évoqué plus haut pour distinguer l'appel initial d'un appel par la touche de fonction.

Gestion des notifications

Bon, ce n'est pas essentiel, mais tant qu'à faire... La dépendance à installer est libnotify, qui est également dans toutes les distributions. La commande est

$ notify-send [-i icon] [-t millisecondes] [titre] message

Les icônes seront nommées selon les spécification de la freedesktop organisation. Le rendu pourra être différent d'un environnement à l'autre et je ne l'ai testé que sous OpenBox et KDE, j'espère que ça marche partout.

Association à une touche de fonction

Bien sûr il est aisé d'utiliser les raccourcis clavier de l'environnement de bureau que l'on utilise, mais puisque l'on recherche une solution qui marche partout on préférera Xbindkeys. Ça marche avec toutes les touches de fonction et c'est indépendant des environnement de bureau. Après installation (paquet disponible dans toutes les distributions) pensez immédiatement à créer un fichier de configuration vide à la racine de votre répertoire personnel sans quoi vous auriez un message d'erreur à la première utilisation.

$ touch ~/.xbindkeysrc

Ensuite il faut définir la touche à utiliser. Dans mon cas fn→F9

$ xbindkeys -k

Cela provoque l'ouverture d'une petite fenêtre blanche et l'invite à choisir une clef ou une action souris. À la suite de quoi le résultat s'affichera dans le terminal sous cette forme :

You can use one of the two lines after "NoCommand"
in $HOME/.xbindkeysrc to bind a key.
"(Scheme function)"
m:0x10 + c:199
Mod2 + XF86TouchpadToggle

Plus clairement cela nous convie à éditer le fichier de config (~/.xbindkeysrc) et à saisir successivement la commande à exécuter et la clef associée, soit sous forme de couple modificateur / N° de clef (ici m:0x10 + c:199), soit sous forme de nom symbolique (Mod2 + XF86TouchpadToggle). Dans mon cas l'une des deux formules suivante :

# Activation / désactivation du touchpad
"touchpadtoggle"
m:0x10 + c:199

ou encore

# Activation / désactivation du touchpad
"touchpadtoggle"
Mod2 + XF86TouchpadToggle

enfin n'oubliez pas de rajouter xbindkeys avant la ligne qui démarre votre gestionnaire de fenêtre dans votre ~/.xinitrc

Récapitulatif

Si la solution vous intéresse :
  1. Installez si ce n'est déjà fait xorg-xinput, xbindkey et libnotyfy.
  2. Copiez le script ci-dessous dans un répertoire figurant dans votre $PATH (/usr/local/bin semble approprié), nommez le touchpadtoggle et rendez le exécutable (chmod +x /usr/local/bin/touchpadtoggle)
  3. Exécutez xinput et repérez la ligne correspondant à votre touchpad. Personnalisez le script en modifiant le contenu de la variable NomTouchpad
  4. Créez un touchpadtoggle.desktop dans votre répertoire ~/.config.autostart avec les données ci-dessus si vous souhaitez une désactivation automatique à l'ouverture de votre session.
  5. Créez un .xbindkeysrc vide dans votre Home et rajoutez xbindkeys dans votre ~/.xinitrc
  6. Lancez la commande $ xbindkeys -k et récupérer le code de la touche que vous voulez associer au script puis éditez votre .xbindkeysrc en conséquence.

Voilà, j'espère que je n'ai rien oublié, chez moi ça marche impeccablement. Dans tous les cas je serais heureux d'avoir votre retour.

Le script

#! /bin/bash 
######################################################
## TouchpadToggle                                   ##
## Gestion du touchpad avec xinput                  ##
##                                                  ##
## copyleft vgay at vintherine dot org              ##
## version 0.2 du 20140918                          ##
##                                                  ##
## dépendance obligatoire : xorg-xinput             ##
## dépendance optionelle libnotify                  ##
## et xbindkey pour associer ce script à une touche ##
######################################################

### Personnalisation -> mettez ici le nom de votre touchpad tel que trouvé avec la commande xinput.
NomTouchpad="ETPS/2 Elantech Touchpad"
### Début du script

IFS=
$'\\n'
if
! command -v xinput >/dev/null; then notify-send --icon=dialog-error -t 7000 $Titre "Dépendance xorg-xinput non trouvée" 2>/tmp/touchpadError exit 1 fi
Cde[0]=
"xinput enable " Cde[1]="xinput disable " Msg[0]="Touchpad désactivé" Msg[1]="Touchpad activé" Titre="Gestion du touchpad :"
DevID=$(
xinput | grep "$NomTouchpad" | cut -d"=" -f2 | cut -d $'\\x09' -f1) if [[ -z $DevID ]]; then notify-send --icon=dialog-information -t 5000 $Titre "Touchpad non trouvé" exit 0 fi
Enabled=$(
xinput list-props $DevID | grep Enabled | tail -c2)
if [[
$1 == "autostart" ]]; then if (( $(xinput | grep pointer | grep -vc Virtual) < 2 )); then exit 0; fi fi
Message=$(
eval ${Cde[$Enabled]}$DevID 2>&1) Enabled=$(xinput list-props $DevID | grep Enabled | tail -c2) if [[ -z $Message ]]; then notify-send --icon=dialog-information -t 5000 $Titre ${Msg[$Enabled]} else notify-send --icon=dialog-error -t 7000 $Titre $Message fi
Vus : 628
Publié par Vincent Gay : 38