Multiposte 1 carte graphique et Xephyr

Après avoir fait du multiseat avec 2 CG, un changement de PC m’oblige à faire la même chose mais avec une seule carte. J’ai essayé de couvrir au maximum toutes les étapes de la mise en place de la solution.

Tout d’abord le raisonement pour le choix des outils à été le suivant.
[ul][li]Xorg ou Wayland ?[/li][/ul]
La réponse a été rapide. Xorg clairement, Wayland est encore trop récent pour pouvoir le faire et aucun document ne traite pour l’instant de ce problème.

[ul][li]Xnest ou Xephyr ?[/li][/ul]
Xephyr est largement plébiscité et Xnest semble tomber en désuétude. C’est par le développement de Tizen (ex-Meego) que Xephyr semble toujours actif et que de nouvelles fonctionnalités lui sont ajouté. Intel s’en sert intensément et est énormément utilisé pour le développement d’application pour smartphone comme environnement de simulation. (phoronix.com/scan.php?page=n … &px=ODc1NQ).
Un soucis avec Xephyr est que le support de evdev semble ne pas avoir été inclus dans les options de compilations. “evdev” permet de monopoliser les claviers et souries. Du coup il faut refaire le paquet soi-même.

[ul][li]Et la transition avec systemd ?[/li][/ul]
Il ne semble plus y avoir de problème particulier (phoronix.com/forums/showthread.p … -For-X-Org)

[ul][li]Comment gérer 2 écran, 2 session avec une seule carte graphique ?[/li][/ul]
Il faut savoir que Xephyr permet de se greffer sur n’importe quel serveur X afin d’afficher une autre session. Par exemple avec la commande “Xephyr -query 127.0.0.1” vous devez pouvoir vous connecter sur votre propre machine si le protocole “XDMCP” est activé sur votre “DM” (GDM, KDM, XDM, …). Donc le but du jeu sera d’avoir un serveur X qui va “supporter” 2 fenêtre Xephyr. Ces deux dernière se verrons affecter les claviers et les souries de manière exclusif.

[ul][li]Et le DM ? Debian a adopté GDM(3) avec Gnome mais j’aimerais bien m’en passer.[/li][/ul]
Avec GDM (celui de Gnome2) il existe un très bon tutoriel ici : netpatia.blogspot.fr/2009/06/mul … u-904.html
Pour GDM3, le problème est que pour l’instant il ne reprend pas toutes les possibilitées de son ancienne version.
live.gnome.org/GDM/ToDo
"-- Allow per-display X Server commands
BrianCameron: The [server] and [server-foo] sections of the GDM configuration have been disabled. This means that users who depend on novel configurations which require special Xserver commands per-display is not available."

Donc bonne nouvelle, il fallait trouver une alternative en le nom de LightDM, qui est issu de Ubuntu …

Donc pour les pré-requis :
– Ajouter “deb-src ftp.fr.debian.org/debian/ main contrib non-free”
– Installer les paquage dpkg-dev, build-essential, devscripts, lightDM

On récupère toutes les sources du packet source xorg-server qui comprend Xephyr.

 $ apt-get source xserver-xephyr

Puis récupérer toutes les dépendances spécifique au paquet :

$ apt-get build-dep xorg-server

Là il va télécharger un certain nombre de paquet de développement ("-dev"), ils sont marqué comme installé automatiquement, donc un deborphan devrait vous les enlever sans trop de problème. Sinon il existe cette commande pour être sur qu’ils sont marqué en tant que “installé automatiquement”, puis un “apt-get autoclean” les supprimera.

Ensuite tout se passe dans le répertoire “debian”

 $ cd xorg-server-1.12.4/debian

On édite le fichier “changlog” pour monter de version le paquet que l’on va reconstruire. Il est possible de le faire en automatique avec la commande:

debian/$ dch -n

L’option “-n” permet d’incrémenter le numéro de version de façon mineur, c’est à dire l’ajout de “.1” en fin de numéro de version.

Sinon pour le faire en manuel, il faut ajouter une ligne du type suivant au fichier:

xorg-server (2:1.12.4-5.1) UNRELEASED; urgency=low

  * Non-maintainer upload.
  * ajout des paramètre pour Xephyr et evdev

 -- Vous <vous@VotreMachine>  Sun, 03 Mar 2013 22:21:32 +0100

Pour éviter de réinstaller tout Xorg avec le nouveau numéro de version il faut éditer le fichier “debian/control” et modifier la dépendance de Xephyr (ligne ~283). Pour cela il faut remplacer le

Depends :
  xserver-common (>= ${source:Version})

Par :

Depends :
  xserver-common (>= 2:1.12.4-5)

Le numéro doit être en accord avec la version de votre Xorg actuellement installé sur votre machine.
Sinon cette modification est directement possible dans le .deb, toujours dans le fichier “DEBIAN/control”. Pour cela il faut prendre le .deb que vous avez construit, le décompresser, modifier le fichier et faire la commande “dpkg-deb -b <nom du répertoire contenant les fichiers>”. Mais il est plus pratique de le faire avant.

Je ne vous conseille pas de mettre une numéro de version trop élevé car cela pourrait engendrer une incompatibilité avec les futurs versions de Xorg.

Ensuite nous allons modifier les options de compilation en éditant le fichier “rules”, c’est le Makefile de la construction du packet.
Localisez “confflags_main” (ligne ~133) et ajouter les lignes suivant juste en dessous de “–enable-kdrive” (ligne ~156)

 --enable-kdrive-evdev \
 --enable-kdrive-mouse \
 --enable-kdrive-kbd \

Passons maintenant à la recompilation proprement dite :

Et laisser la compilation et la création des paquets se faire … cela peut prendre quelques minutes.

Si pour une raison il vous faut refaire entièrement la compilation il faut d’abord faire la commande suivante

Si c’est juste refaire les “.deb” (correction du numéro de dépendance, …), alors cette commande suffit.

Enfin pour installer votre paket (qui se trouve dans le répertoire supérieur) il faut faire :

Ou de manière graphique avec GDebi.

Pour rappel le principe seras d’avoir une session X qui va héberger 2 sessions Xephyr qui serviront les différents sièges.
Tout d’abord nous allons faire un fichier de conf pour le serveur Xorg. Pour ne pas démarrer de rien on peut lancer la commande (en root) “Xorg -configure” qui génère le fichier “xorg.conf.new” dans “/root”. Ensuite on fait un petit “xrandr” pour identifier les sorties disponibles.

$ xrandr

Screen 0: minimum 320 x 200, current 1920 x 1200, maximum 8192 x 8192
DVI-0 disconnected (normal left inverted right x axis y axis)
HDMI-0 connected 1920x1200+0+0 (normal left inverted right x axis y axis) 593mm

“DVI-0” & “HDMI-0” sont les 2 disponibles sur la machine. On peux aussi trouver du “VGA-0” ou “LVDS” pour les écrans de portables.
Dans cet exemple on peut avoir un “/etc/xorg.conf” comme suivant :

##################################################################
Section "Monitor"
	Identifier  "HannsG"
	Option      "PreferredMode" "1920x1200"
	Option      "DPMS" "true"
	Option		"Primary" "true"
EndSection

Section "Monitor"
	Identifier  "Acer"
	Option      "PreferredMode" "1680x1050"
	Option      "DPMS" "true"
EndSection

Section "Device"
	Identifier  "card0"
	Driver      "radeon"
	# Ici on associe les sorties video avec une section "Monitor"
	# On remarquera le "Monitor" devant le nom des sortie, c'est indispensable (cf : http://www.x.org/archive/current/doc/man/man5/xorg.conf.5.xhtml#heading12)
	Option      "Monitor-HDMI-0" "HannsG"
	Option      "Monitor-DVI-0" "Acer"
EndSection

##################################################################

Section "Screen"
	Identifier  "ecran1"
	Device      "card0"
	Monitor     "HansG"
	DefaultDepth 24
	SubSection "Display"
 		Depth   24
		Virtual 3600 1200
	EndSubSection
EndSection

Section "ServerLayout"
	Identifier    "dualscreen"
	Screen      0  "ecran1"
EndSection
##################################################################

Nous allons maintenant regarder la configuration de LightDM d’un peu plus près. Le fichier de configuration par défaut expose toutes les options possibles du dit fichier. Nous allons garder le strict minimum
Pour cela éditons le fichier /etc/lightd/lightdm.conf

[LightDM]
 greeter-user=root
 user-authority-in-system-dir=false

 [SeatDefaults]
 xserver-allow-tcp=false
 greeter-hide-users=false
 user-session=lightdm-xsession
 session-wrapper=/etc/X11/Xsession

 [Seat:1]
 xserver-command=/etc/lightdm/Xephyr-command.sh -p 1 -t 1680x1050 -P evdev -s /dev/input/by-id/usb-Logitech_USB-PS_2_Optical_Mouse-event-mouse -c /dev/input/by-id/usb-TrulyErgonomic.com_Truly_Ergonomic_Computer_Keyboard-event-kbd -v bepo 
 greeter-setup-script=/etc/lightdm/Xephyr-greeter-setup.sh -p 1
 greeter-session=lightdm-greeter

[Seat:2]
 xserver-command=/etc/lightdm/Xephyr-command.sh -p 2 -t 1920x1200 -P evdev -s /dev/input/by-id/usb-B16_b_02_USB-PS_2_Optical_Mouse-event-mouse -c /dev/input/by-path/platform-i8042-serio-0-event-kbd
 greeter-setup-script=/etc/lightdm/Xephyr-greeter-setup.sh -p 2 -d 1680,0
 greeter-session=lightdm-greeter

Il y a plusieurs chose à savoir concernant le fonctionnement de LightDM afin de comprendre ce qui est fait.
– La section “SeatDefault” est commune à tous les siège définit après
– Chaque “Seat” est exécuté dans l’ordre dans un VT différent et ce même si, dans notre cas, tout se passe dans le VT7 ([url=https://code.launchpad.net/~andrzejtp2010/lightdm/lightdm-trunk-xephyr-multiseat/+merge/120286]un patch[url] à été proposé pour palier à ce problème mais il n’a pas été accepté … pour l’instant)
– Chaque propriétés de tous les “Seat” sont lancé dans un ordre précis, d’abord tous les “xserver-command”, puis tous les “greeter-setup-script”, enfin tous les “greeter-session”. Si vous mettez d’autres propriétés elle seront exécuter suivant leur ordre pré-établi.
– Si les “greeter” se termine, lightDM coupe le “xserver-command” correspondant. De même si le “xserver-command” se termine le greeter est coupé.

Donc pour que tout se positionne correctement il faut
– D’abord lancer le serveur X qui servira de support, ce qui est fait en le mettant en tant que premier “Seat”
– Lancer les fenêtres Xephyr avec les optons qui vont bien, ce qui est fait avec le script “Xephyr-command.sh” et ses arguments
– Simuler un “greeter” pour le “Seat :0” afin que le serveur X ne soit pas tuer par lightDM, ce qui est fait avec le script “fake-greeter”
– Exécuter un script qui va placer les fenêtre Xephyr si besoin et initialiser les variables d’environnement correctement, fait avec “Xephyr-greeter-setup.sh
– Exécuter les “greeter” dans les fenêtre Xephyr

Pour le faux greeter du serveur X il faut créer un fichier dans “/usr/share/xgreeters/fake-greeter.desktop” et y copier son contenu :

[Desktop Entry]
Name=LightDM fake greeter
Comment=This runs no greeter at all, it should only be run from LightDM
Exec=sleep infinity
Type=Application
X-Ubuntu-Gettext-Domain=lightdm

Après tout cela nous allons créer un script qui permettra de créer (“Xephyr-command.sh”) et un autre pour placer les fenêtre à l’écran (“Xephyr-greeter-setup.sh”).
Tout d’abord il est nécessaire d’installer le petit utilitaire “wmctrl” avec

Le contenue du fichier “Xephyr-command.sh

#!/bin/sh
# 2013-03 @ Mimoza
# http://www.isalo.org/wiki.debian-fr/Multiseat

####### Les fonctions #############

usage() {
  echo "Usage : $nom [OPTION...] -p numéroDePoste"
  echo "Usage : $nom -h|--help"
  echo "Options :"
  echo "\t -t, taille : Doit être de la forme 9999x9999, (dafaut = 1024x768)"
  echo "\t -s, sourie : /dev/input/[by-path|by-id]/...event-mouse"
  echo "\t -c, clavier : /dev/input/[by-path|by-id]/...event-kbd"
  echo "\t -l, layout : fr, es, en, ... (défaut = fr)"
  echo "\t -v, variant : fr, latin9, bepo, ... (défaut = <vide>)"
  echo "\t -P, Pilote : ephyr ou evdev (défaut = ephyr)"
}

testExecutable() {
	XEPHYR=`whereis -b Xephyr | cut -d' ' -f2`
}


####### VALEURS PAR DEFAUT #############
POSTE=$$ #On récupère le PID du process courant
TAILLE="1024x768"
SOURIE=
CLAVIER=
LAYOUT="fr"
XRACINE=0 # Permet de spécifier le serveur X à utiliser si différent du 0
PILOTE=ephyr # Test = ephyr ; Prod = evdev

####### ANALYSE DES OPTIONS #############
# Mode debug
set -x

# récupération du nom du script
nom=`basename $0`

# Cas particulier de sans option
if [ $# -lt 1 ]; then usage; exit 1; fi


# Vérification des outils disponibles
testExecutable
if [ -z "$XEPHYR" ]; then
	echo "Executable manquant :"
	echo "Xephyr : "$XEPHYR
	exit 2
fi

# Analyse des autres options
OPTIND=0

while getopts ":p:t:s:c:l:v:P:h" option
do
	echo "(-- option:'$option'  ind:'$OPTIND' optarg:'$OPTARG' --)"
	case $option in
		p|poste)
			POSTE=$OPTARG
		;;

		t|taille)
			TAILLE="$OPTARG"
		;;

		s|sourie)
			SOURIE=$OPTARG
			if  ! [ -r $SOURIE ];then
				echo "La sourie n'est pas accessible"
				exit 3
			fi
		;;

		c|clavier)
			CLAVIER=$OPTARG
			if  ! [ -r $CLAVIER ];then
				echo "Le clavier n'est pas accessible"
				exit 4
			fi
		;;

		l|layout)
			LAYOUT=$OPTARG
		;;

		v|variant)
			VARIANT=$OPTARG
		;;

		P|Pilote)
			PILOTE=$OPTARG
		;;

		h|help)
			usage
			exit 1
		;;

		:)
			echo "l'option '$OPTARG' nécessite un argument"
		;;

		\?) echo " option '$OPTARG'  INVALIDE" >&2
	esac
done

####### TRAITEMENT EFFECTIF #############
# Mise en place des variable d'environnement
export DISPLAY=:$XRACINE
export XAUTHORITY=/var/run/lightdm/root/:$XRACINE

# Construction de la ligne d"argument
OPTIONS=""

if [ -n "${TAILLE}" ]; then
	OPTIONS=" -screen ${TAILLE}"
fi

if [ -n "${CLAVIER}" ]; then
	if [ -n "${LAYOUT}" ]; then
		OPTIONS=$OPTIONS" -keybd $PILOTE,,device=${CLAVIER},xkbrules=evdev,xkbmodel=evdev,xkblayout=${LAYOUT}"
		if [ -n "${VARIANT}" ]; then
			OPTIONS=$OPTIONS",xkbvariant=${VARIANT}"
		fi
	fi
fi

if [ -n "${SOURIE}" ]; then
	OPTIONS=$OPTIONS" -mouse $PILOTE,,device=${SOURIE}"
fi

# Lancement de Xephyr en arrière plan
echo "$XEPHYR -retro $OPTIONS :$POSTE"
exec $XEPHYR -retro  $OPTIONS :$POSTE

Petite explication sur la dernière ligne. Le “exec” fait en sorte que ce soit le processus de Xephyr qui prend la place du script, donc il reprend le PID et tout ce qui va bien. Ca permet surtout à ce que le signal USR1 que Xephyr lance au PPID, soit bien récupéré par LightDM et que ce dernier continue son fonctionnement normalement.

Le contenue du fichier “Xephyr-greeter-setup.sh

#!/bin/sh
# 2013-03 @ Mimoza
# http://www.isalo.org/wiki.debian-fr/Multiseat

####### Les fonctions #############

usage() {
  echo "Usage : $nom [OPTION...] -p|--poste numéroDePoste"
  echo "Usage : $nom -h|--help"
  echo "Options :"
  echo "\t -d, --deplacement : de la forme 'x,y' (en pixel)"
  echo "\t -v, --vt : 7, 8, 9, 10, 11 (defaut = 7)"
}

testExecutable() {
	XWININFO=`whereis -b xwininfo | cut -d' ' -f2`
	WMCTRL=`whereis -b wmctrl | cut -d' ' -f2`
}


####### VALEURS PAR DEFAUT #############
POSTE=$$ #On récupère le PID du process courant
DEPLACEMENT=
VT=7
XRACINE=0 # Permet de spécifier le serveur X à utiliser si différent du 0
ATTENTE=3 # temps en seconde avant de déclencher le "chvt" pour revenir sur le bon VT

####### ANALYSE DES OPTIONS #############
# Mode debug
set -x

# récupération du nom du script
nom=`basename $0`

# Cas particulier de sans option
if [ $# -lt 1 ]; then usage; exit 1; fi


# Vérification des outils disponibles
testExecutable
if [ -z "$XWININFO" -o -z "$WMCTRL" ]; then
	echo "Executable manquant :"
	echo "xwininfo : "$XWININFO
	echo "wmctrl : "$WMCTRL
	exit 2
fi

# Analyse des autres options
OPTIND=0

while getopts ":p:d:v:h" option
do
	echo "(-- option:'$option'  ind:'$OPTIND' optarg:'$OPTARG' --)"
	case $option in
		p|poste)
			POSTE=$OPTARG
		;;

		d|deplacement)
			DEPLACEMENT="$OPTARG"
		;;
	
		v|vt)
			VT=$OPTARG
		;;

		h|help)
			usage
			exit 1
		;;

		:)
			echo "l'option '$OPTARG' nécessite un argument"
		;;

		\?) echo " option '$OPTARG'  INVALIDE" >&2
	esac
done

####### TRAITEMENT EFFECTIF #############
# Mise en place des variable d'environnement
export DISPLAY=:$XRACINE
export XAUTHORITY=/var/run/lightdm/root/:$XRACINE

# Vieux Hack tout bancal pour revenir au bon VT sans patcher LightDM
(sleep $ATTENTE ; chvt $VT)&

# Deplacement de la fenetre si besoin
if [ -n "$DEPLACEMENT" ]; then
	#On recherche l'ID de la fenêtre Xephyr
        XEP=`XAUTHORITY=/var/run/lightdm/root/:$XRACINE $XWININFO -root -children -all -display :$XRACINE | grep "Xephyr on :$POSTE" --max-count=1`;

	if [ -z "$XEP" ]; then
		echo "fenêtre Xephyr non trouvé pour le poste $POSTE"
		exit 5
	fi
    XEPHYR_WIN_ID=`echo ${XEP} | cut -d' ' -f1`;
    $WMCTRL 2>&1 -v -i -r ${XEPHYR_WIN_ID} -e 0,${DEPLACEMENT},-1,-1;
	if [ $? -ne 0 ]; then
		echo "Erreur lors du déplacement de la fenêtre Xephyr pour le poste $POSTE"
		exit 7
	fi
fi

# Mise en place des variables d'environnement pour le greeter (utile ?)
export DISPLAY=:$POSTE
export XAUTHORITY=/var/run/lightdm/root/:$POSTE

Petite explication concernant la ligne suivante
[ code](sleep $ATTENTE ; chvt $VT)&[/code]
Comme je n’ai pas patché LightDM pour éviter le changement de VT et que Xephyr m’empêche de faire un Ctrl+Alt+7 (avec le driver evdev) pour revenir au bon VT, j’ai du mettre en place un automatisme. Certes c’est loin d’être parfait mais ça rempli correctement son office.

Et voilà, tout est prêt pour le redémarrage et admirer les mires de login sur leur écran respectif.

Un grand merci a ce site pour m’avoir prémaché le travail … ce qui ne m’a pas empéché d’apporter quelques améliorations à sa solution.
beforeafterx.blogspot.fr/2012/08 … dm-12.html option

PS : Je laisse les paquets Xephyr en 32 et 64 bits pour faciliter le travaille :wink: (il faut enlever l’extension txt)

edit : une page wiki a été faite isalo.org/wiki.debian-fr/Multiposte
xserver-xephyr_1.12.4-6_i386.deb.txt (999 KB)
xserver-xephyr_1.12.4-5.1_amd64.deb.txt (995 KB)