GNOME : Mon PC refuse toujours de se mettre en veille lorsque je rabats l'écran, et ça fait plus de 10 ans que ça dure !
Mon PC portable tourne sous Ubuntu avec l’environnement GNOME depuis fort fort longtemps, et ça fait plus de 10 ans que le même problème revient encore et toujours. Lorsqu'un moniteur externe est connecté au PC, celui-ci refuse de se mettre en veille lorsque je rabats son écran.
Je sais que certaines personnes bossent uniquement sur leurs écrans externes et que ce comportement peut être souhaitable pour elles, mais ce n'est pas mon cas et j'aimerais bien avoir le choix.
À une époque il existait justement une option pour permettre ce fonctionnement, mais elle a été supprimée aux alentours de 2012 ou 2013, sans aucun remplacement. Jusqu'à présent, j'ai toujours trouvé des workarounds relativement simples et j'ai déjà abordé ce sujet à plusieurs reprises sur ce blog :
- en 2015 : « Mise en veille d'un PC portable sous Ubuntu 15.04 (systemd) »,
- en 2020 : « Ubuntu, GNOME : Mon PC refuse de se mettre en veille lorsque je rabats l’écran »,
- et encore juste avant l'été 2026 : « Journal de bord 2 — Mon passage à Ubuntu 26.04 Resolute Raccoon », partie « Mise en veille en rabattant l'écran ».
Bref, j'ai fait un article à peu près à chaque fois que ma solution de contournement précédente ne fonctionnait plus, et vous l'aurez donc compris, si vous lisez cet article, c'est que le problème est de retour... Encore ! 😅
Mais rassurez-vous, j'ai une solution à vous proposer ! 😉
Note
NOTE DE SERVICE : je suis plutôt bavard sur ce problème dans la suite de cet article. Si les détails ne vous intéressent pas et que vous cherchez juste une solution, sautez directement à la partie intitulée « La solution, pour le moment », je ne vous en voudrais pas ! 😉
Pourquoi on a ce problème ?
À l'origine du problème, on a la suppression de l'option "lid-close-suspend-with-external-monitor" dans le plugin Power de GNOME Settings Daemon (a.k.a gsd-power), qui permettait, comme son nom l'indique, la mise en veille de la machine lorsque son capot était rabattu, et ce même si des écrans externes étaient connectés. Je ne critique pas le bien fondé de ce changement, car je n'en connais pas les tenants et les aboutissants. C'est juste notre point de départ.
Sur Ubuntu, les effets de cette suppression se sont fait ressentir en 2015, avec l'arrivée de systemd dans la distribution. J'imagine qu'on a également dû avoir une grosse mise à jour de GNOME Settings Daemon (ou de son fork pour le bureau Unity ?) dans ces eaux-là.
Mais au final ce n'était pas trop un problème à l'époque, car le module logind de systemd propose des options pour gérer le comportement de la machine lorsqu'on rabat l'écran. Il suffisait donc d'écrire une petite ligne dans son fichier de configuration et le tour était joué. C'était l'objet de mon article de 2015.
Puis en 2017 avec le passage d'Unity à GNOME Shell comme environnement de bureau par défaut, rebelote, c'est de nouveau cassé ! Cette fois c'est sûr, on est passé sur la version upstream (peut être un peu patchée ?) de GNOME Settings Daemon. Et cette nouvelle version vient empêcher logind de mettre en veille la machine lorsque l'on rabat l'écran.
Ce qu'il se passe, c'est que gsd-power met en place un inhibitor qui bloque le comportement configuré dans logind. Il faut bien comprendre que ce n'est pas un bug, c'est délibéré, et ce n'est pas un problème en soi. Faire ça permet de gérer les actions à mener directement du côté de l’environnement de bureau plutôt que dans logind. Ça permet normalement de proposer des jolies options permettant de configurer finement ce qu'il se passe directement dans les fenêtres de configuration de l’environnement de bureau. Plutôt cool en théorie... Sauf que ces options, on les attend toujours du côté de GNOME... 😬
Bref, en 2020 je prends enfin le temps de me pencher de nouveau sur ce problème et je trouve un nouveau contournement relativement acceptable, qui fera donc l'objet d'un nouvel article.
Pour la faire courte, à cette époque gsd-power se basait sur un daemon nommé UPower pour récupérer l'état du lid switch. Et il se trouve que UPower proposait une option permettant d'ignorer la présence de cet interrupteur matériel. Il rapportait donc à gsd-power qu'il n'y avait aucun switch permettant de connaître l'état du capot du laptop, et du coup ce dernier ne définissait pas son inhibiteur dans ce cas-là. Étant donné que logind récupère l'information de son côté (donc sans passer par UPower), il sait quand le capot est rabattu, et comme il n'a pas gsd-power dans les pattes, il peut mettre en veille le PC en réaction si on le configure pour ça.
Tout ça marchait bien, jusqu'à GNOME 50... Dans cette version, gsd-power ne va plus lire l'information sur l'état du switch dans UPower, mais dans logind. Il y a une bonne raison à ce changement : la gestion du lid switch est dépréciée dans UPower depuis un bout de temps, il était donc grand temps de se mettre à jour... Mais du coup, vous le voyez venir la douille ? 😅
logind ne propose pas d'option pour cacher le lid-switch et gsd-power défini donc systématiquement son inhibiteur... qui empêche en retour logind de faire ce qu'on lui demande... Et toujours pas l'ombre d'une option à l'horizon côté GNOME. On est un peu dans une impasse. 😓
À la recherche du nouveau workaround
De guerre lasse, j'avais un peu abandonné l'affaire, jusqu'à ce qu'un nouveau message dans le ticket #111 de GNOME Settings Daemon ne remette une pièce dans la machine et me remotive à chercher une solution à ce problème. 🙃
Supprimer l'inhibiteur ? Erf non, ça c'est trop dégueu !
La première idée que j'ai eue, c'était de supprimer l'inhibiteur qui m'embête... Sauf que les choses ne sont pas si simples. Seule l'application qui l'a mis en place peut le supprimer.
En gros, quand on demande à systemd de nous ajouter un inhibiteur, il nous donne en retour un file descriptor et tant que notre process conserve ce fichier ouvert, l'inhibiteur reste actif. Donc pour le fermer, ça implique d'utiliser gdb en root pour s'attacher au process de gsd-power, puis de trouver le bon descripteur de fichier et de le fermer. Bref, c'est pas totalement infaisable [je me suis d'ailleurs amusé à le faire 😛], mais c'est très très sale... On va chercher une meilleure idée ! 😅
Un nouveau daemon ?
La seconde idée qui m'est venue a été de développer un petit daemon qui monitore l'état du switch et qui demande explicitement la mise en veille lorsque l'écran est rabattu, qu'un moniteur externe soit branché ou non.
J'ai rapidement fait un proof of concept un peu dégueu pour vérifier que ça marchait correctement, et comme ça m'a convaincu, j'ai refait ça au propre et je l'ai publié sur le GitLab de GNOME. Je vous en reparle un peu plus bas si vous voulez le mettre en place. 😉
Corriger le problème une bonne fois pour toutes ?
La dernière idée qui m'est venue, c'était d'essayer de corriger le problème à la source — directement dans le code de gsd-power — au lieu de chercher un N-ième contournement.
J'ai commencé à travailler là-dessus dans la MR !491, mais je ne sais pas encore exactement quelle serait la bonne solution à apporter au problème : faire en sorte que systemd logind ait le dernier mot, ou forcer la mise en veille lorsqu'une option est activée ? Et puis je ne suis pas encore sûr d'arriver à un résultat satisfaisant (je ne suis pas un pro du C/GObject) ni que ma solution sera acceptée et mergée par les mainteneurs de gsd-power. Bref, il reste des inconnues de ce côté.
La solution, pour le moment
En résumé, je travaille actuellement sur deux fronts : une solution de contournement à court terme, afin de résoudre le problème dès maintenant, sur les distributions déjà sorties ; et un correctif dans le logiciel upstream, qui sera mergée un jour, peut-être.
Si vous cherchez une solution qui fonctionne sur votre système actuel pour mettre en veille votre machine lorsque vous rabattez l'écran, vous pouvez donc installer la solution de contournement que j'ai développé.
Il s'agit d'un petit daemon composé d'une cinquantaine de lignes de Python, et qui ne devrait pas nécessiter l'installation de dépendances supplémentaires. Il a seulement besoin de GObject Introspection pour Python et des bindings pour GLib et Gio ; tout ça devrait normalement déjà être installé sur votre système.
Vous trouverez le projet sur le serveur GitLab de GNOME :
Pour l'installer c'est assez simple. Récupérez le code source, soit à l'aide de Git :
git clone https://gitlab.gnome.org/flozz/flozz-lid-closed-suspend.git
Soit en téléchargeant puis en décompressant l'archive de la dernière release que vous trouverez sur cette page :
Ensuite, il faudra ouvrir un terminal et vous rendre dans le dossier que vous venez de cloner (Git) ou de décompresser (archive) :
cd ./flozz-lid-closed-suspend-v1.0.0
Puis lancez le script d'installation (ce dernier appellera automatiquement sudo si nécessaire) :
./install.sh
Et voilà, le logiciel est installé et déjà fonctionnel, vous pouvez rabattre l'écran de votre PC portable, celui-ci devrait partir immédiatement en veille ! 😄
Si jamais vous voulez désinstaller le logiciel, utilisez simplement le script de désinstallation fournit :
./uninstall.sh
Conclusion
J'espère que cet article aura pu vous éclairer sur ce problème — simple en apparence — mais qui implique pourtant plusieurs composants logiciels qui évoluent chacun dans leur coin, à leur rythme, ce qui peut ne va pas sans causer quelques frictions de temps à autre... 😅
J'espère également que ma solution de contournement aura pu vous être utile si vous aviez le même problème que moi, et que j'arriverais à développer et à faire accepter un fix plus pérenne directement dans gsd-power.
À bientôt pour un prochain article ! o/