Xorg & X11
Pendant longtemps j’utilisais i3 sans vraiment comprendre ce qu’il y avait en dessous. Je savais vaguement que X11 c’était “le truc qui gère l’affichage”, mais je confondais X11, X.Org et Xorg, je ne comprenais pas ce que faisait vraiment mon window manager par rapport au serveur, et j’avais des questions sur les sockets, le tearing que je voyais sur YouTube, etc.
Cet article, c’est ce que j’ai compris après avoir creusé tout ça.
Pourquoi ça existe
Section intitulée « Pourquoi ça existe »Sur Linux, l’affichage graphique n’est pas intégré dans le noyau. Le kernel gère le matériel (GPU, clavier, souris) mais il ne dessine rien à l’écran. Il fallait un système séparé pour ça - c’est le rôle du X Window System, aussi appelé X11 ou simplement X.
X a été créé dans les années 80 au MIT. Le principe fondateur c’est le modèle client-serveur, et c’est là que j’ai bloqué la première fois.
X11, X.Org, Xorg - trois choses différentes
Section intitulée « X11, X.Org, Xorg - trois choses différentes »J’avais tendance à utiliser ces trois noms comme des synonymes. C’est pas la même chose :
| Nom | Ce que c’est |
|---|---|
| X Window System / X11 | Le protocole et la spécification. Un standard qui définit comment clients et serveurs se parlent. |
| X.Org Foundation | L’organisation qui maintient l’implémentation open source. A pris le relais de XFree86 au début des années 2000. |
| Xorg | Le binaire du serveur X, l’implémentation concrète. C’est ce qui tourne sur la machine. |
X11 est le protocole, X.Org est l’organisation, Xorg est le logiciel. D’où la confusion.
Le modèle client-serveur - et pourquoi c’est contre-intuitif
Section intitulée « Le modèle client-serveur - et pourquoi c’est contre-intuitif »Dans X11, les rôles sont inversés par rapport à ce qu’on imagine :
- Le serveur X (Xorg) tourne sur la machine physique. Il “possède” l’écran, le clavier, la souris.
- Les clients X sont les applications - Firefox, le terminal, i3. Ils demandent au serveur d’afficher des choses.
Donc quand on lance Firefox, Firefox est le client. Il envoie des requêtes genre “dessine un rectangle ici, écris ce texte là” à Xorg, qui exécute.
Ce qui m’a aidé à comprendre : le modèle client-serveur c’est juste un modèle de communication asymétrique. Le serveur possède une ressource et attend. Le client en a besoin et initie la connexion. “Serveur” ça veut juste dire “celui qui sert quelque chose” - ici Xorg sert l’accès à l’affichage, donc c’est le serveur, même s’il tourne sur le propre laptop.
Les sockets - comment clients et serveur se parlent
Section intitulée « Les sockets - comment clients et serveur se parlent »Client et serveur communiquent via des sockets. J’avais l’impression qu’un socket c’était “pour le réseau”. En fait c’est une abstraction kernel pour un point de communication bidirectionnel entre deux processus. Il en existe plusieurs types :
| Type | Identifiant | Usage |
|---|---|---|
| TCP/IP socket | IP + port | Communication via le réseau |
| Unix Domain Socket (UDS) | Chemin dans le filesystem (/tmp/.X11-unix/X0) | Communication locale, sans passer par la stack réseau |
L’UDS est plus rapide : le kernel copie directement entre les buffers des deux processus, sans simuler un réseau. L’API est quasi identique (connect(), send(), recv()) - X11 n’a pas besoin de savoir lequel il utilise.
Quand Xorg démarre, il ouvre les deux :
/tmp/.X11-unix/X0- pour les clients locaux (toutes les applis)- Port TCP
6000 + numéro de display- pour les connexions distantes
Le socket dans /tmp c’est juste un point de rendez-vous dans le filesystem. C’est temporaire (disparu au reboot), pas un fichier de stockage - les données transitent dans les buffers kernel entre processus.
Les pipes (
|dans le shell) sont la version unidirectionnelle :ls | grep foocrée un canal où ls écrit et grep lit, sens unique.
Sécurité et numéro de display
Section intitulée « Sécurité et numéro de display »Un port 6000 ouvert c’est une surface d’attaque. Le modèle de sécurité de X11 est historiquement très faible. En pratique, Xorg moderne démarre souvent avec -nolisten tcp pour n’écouter que sur l’UDS local. Pour vérifier :
ss -tlnp | grep 6000# rien → Xorg n'écoute pas sur TCPLa variable DISPLAY=:0 dit aux clients “connecte-toi au display 0 sur la machine locale”. Format complet : hostname:display.screen, ex monpc:0.0. Port correspondant : 6000 + numéro de display.
Ce qu’Xorg fait vraiment
Section intitulée « Ce qu’Xorg fait vraiment »Xorg ne dessine pas lui-même les pixels. La chaîne complète :
graph LR A["Appli (client X)"] --> B[Xorg] --> C["DRM/KMS (kernel)"] --> D[GPU] --> E[écran]- DRM (Direct Rendering Manager) - sous-système kernel qui donne accès au GPU
- KMS (Kernel Mode Setting) - gère la résolution, le refresh rate, les connecteurs
Pour le rendu 3D/accéléré (une fenêtre OpenGL par exemple), l’appli peut même parler directement au GPU via DRI sans tout faire passer par Xorg. Xorg reste au courant mais ne gère pas les pixels dans ce cas.
Xorg c’est donc surtout un arbitre : qui a le focus, qui affiche où, quelle fenêtre est au-dessus. Le modèle est event-driven : un client fait une requête de dessin → Xorg l’exécute, met à jour le framebuffer ; le GPU/écran lit le framebuffer à son propre rythme (60Hz, 144Hz…) indépendamment.
i3 dans tout ça
Section intitulée « i3 dans tout ça »Avant de creuser, j’avais collé X11 et i3 dans ma tête comme si c’était la même chose. En réalité la séparation est propre :
- Xorg gère les fenêtres comme des objets bruts (une fenêtre = une surface rectangulaire avec un ID)
- i3 est un client X spécial qui demande à Xorg le contrôle du placement. Il dit à Xorg où déplacer et redimensionner les surfaces, via des requêtes
ConfigureWindow,MapWindow…
i3 n’est pas dans le chemin du rendu. On pourrait croire que ça passe par Firefox → i3 → Xorg, mais non :
graph LR subgraph faux["Faux"] F1[Firefox] --> I1[i3] --> X1[Xorg] --> D1[DRM] --> G1[GPU] --> E1[écran] endgraph LR subgraph reel["Ce qui se passe vraiment"] F2[Firefox] --> X2[Xorg] --> D2[DRM] --> G2[GPU] --> E2[écran] I2["i3 (placement)"] --> X2 endi3 décide où va une fenêtre, puis il sort du chemin. C’est pour ça qu’on peut tuer i3 et lancer un autre WM sans redémarrer X - les fenêtres survivent.
Les événements clavier
Section intitulée « Les événements clavier »Xorg possède le clavier dans le sens où il est le seul à lire /dev/input/eventX. Le kernel détecte “touche A” → Xorg lit → dispatche au client qui a le focus.
i3 dit à Xorg : “quand tu vois Super+Enter, donne-le moi même si je n’ai pas le focus”. C’est un grab. Xorg filtre et route les événements avant de les passer aux clients.
Firefox ne stocke pas les frappes - il les traite immédiatement dans sa boucle d’événements. C’est différent du monde TTY : dans un terminal sans appli graphique, les frappes arrivent dans un buffer kernel (/dev/tty*) qui accumule jusqu’à Enter (mode canonical). Avec Xorg on est dans un autre monde - Xorg lit depuis /dev/input/eventX (pas un TTY) et pousse les événements via le socket X11.
Le tearing que j’avais sous YouTube
Section intitulée « Le tearing que j’avais sous YouTube »Sous i3, quand je regardais des vidéos avec des mouvements rapides, j’avais une coupure horizontale à l’écran. Je pensais que c’était mon iGPU qui galérait. En fait c’est du tearing - un problème de synchronisation.
L’écran rafraîchit à fréquence fixe - 60Hz = il lit le framebuffer 60 fois par seconde, de haut en bas. Le GPU lui écrit dans ce framebuffer à son propre rythme. Si le GPU écrit pendant que l’écran est en train de lire, l’écran va lire le haut de l’ancienne image et le bas de la nouvelle. C’est la coupure.
VSync (Vertical Synchronization, pas Virtual) force le GPU à n’écrire une nouvelle frame qu’au moment du vblank - le signal “vertical blank”, l’instant où l’écran a fini son scan et repart du haut. C’est un héritage des CRT où le canon à électrons devait physiquement se repositionner - le terme est resté sur les LCD.
Avec VSync classique, si le GPU rate le vblank il doit attendre le suivant - le framerate tombe de 60 à 30fps d’un coup, pas à 59. FreeSync/GSync font l’inverse : c’est l’écran qui s’adapte au rythme du GPU. Nécessite un écran compatible.
La solution sous i3 - Picom
Section intitulée « La solution sous i3 - Picom »i3 est un WM sans compositeur. Un compositeur prend les surfaces rendues par chaque appli et les assemble en une image finale avant de l’envoyer à l’écran. Sans compositeur, chaque appli écrit plus ou moins directement dans le framebuffer, rien ne synchronise au vblank.
La solution c’est d’ajouter Picom :
vsync = truePicom intercepte tout le rendu, recomposite, synchronise au vblank. Le tearing disparaît.
La machine distante n’a pas besoin d’un serveur Xorg. Elle a besoin que les applis sachent parler X11 - ce que toute appli graphique sait faire via libX11/xcb.
Avec ssh -X machine :
- SSH crée un tunnel chiffré
- SSH côté distant crée un display fictif (ex
:10) avec un socket local - Les applis voient
DISPLAY=:10, se connectent à ce socket - SSH intercepte, chiffre, envoie les données X11 à travers le tunnel
- L’Xorg local reçoit et affiche
L’appli ne sait pas qu’elle parle à travers un réseau - elle pense juste parler à un serveur X normal. ssh -X ne passe pas par le port 6000 - il tunnelise X11 à travers SSH de façon chiffrée.
X11 date de 1984. Les problèmes structurels :
- Sécurité nulle : n’importe quel client peut lire les événements des autres. Un keylogger en X11 c’est 20 lignes de code, aucun privilège requis.
- Goulot d’étranglement : toutes les applis passent par Xorg même pour du rendu local
- Compositing greffé via l’extension Composite, pas prévu à l’origine
Wayland supprime le serveur central. Le compositeur parle directement à DRM/KMS. Sous Wayland la chaîne devient :
graph LR A[Firefox] --> B["Sway (WM + compositeur)"] --> C["DRM/KMS"] --> D[GPU] --> E[écran]Sway absorbe le rôle d’Xorg et de Picom. Il est l’unique interlocuteur de DRM et maîtrise le timing → tearing structurellement impossible.
Le protocole Wayland n’est pas prévu pour transiter sur le réseau - ssh -X n’existe pas sous Wayland. L’alternative c’est Waypipe (waypipe ssh user@serveur nomdelappli), moins mature mais fonctionnel.
Migration depuis i3
Section intitulée « Migration depuis i3 »i3 est un client X11 pur, il ne tourne pas sous Wayland. L’équivalent c’est Sway : même config, même logique, quasi drop-in replacement. Ce qui peut coincer : certaines vieilles applis passent par XWayland (couche de compatibilité X11 sous Wayland) qui réintroduit les limitations X11 pour ces applis.
Ce que j’en retiens
Section intitulée « Ce que j’en retiens »La clé c’est de séparer les niveaux : X11 est le protocole, Xorg est le binaire qui l’implémente, i3 est un client comme les autres (placement uniquement, pas dans le chemin du rendu), DRM/KMS c’est le kernel qui parle au GPU. Picom colle la synchronisation qui manque à i3. Wayland refait tout depuis zéro avec le compositeur comme interlocuteur unique de DRM.