Y a-t-il un événement qui se déclenche lorsque je branche ou déconnecte un moniteur externe dans le DisplayPort de mon ordinateur portable? ACPID et UDEV ne réagissent pas du tout.
J'utilise des graphiques intégrés sur une puce Intel. Ici est une discussion similaire qui a déjà quelques années.
Je ne veux pas utiliser l'interrogation, mais je dois avoir une configuration qui définit automatiquement les paramètres d'affichage selon que l'écran est connecté.
REMARQUE: Ceci a été testé sur un ordinateur portable avec une carte graphique pilotée par i915.
REMARQUE: Lorsqu'un nouvel écran est branché, aucun événement n'est envoyé à l'hôte, cela est resté vrai même après ma dernière édition. La seule façon est donc d'utiliser le sondage. Essayer de les rendre aussi efficaces que possible ...
Enfin, il existe une meilleure solution (via ACPI):
Il n'y a toujours pas d'événement, mais ACPI semble plus efficace que xrandr
pour s'enquérir. (Nota: ceci nécessite des modules du noyau ACPI chargés, mais ne nécessite pas de privilèges root).
Ma solution finale (en utilisant bash):
isVgaConnected() {
local crtState
read -a < /proc/acpi/video/VID/CRT0/state crtState
test $(( ( ${crtState[1]} >>4 ) ${1:+*-1+1} )) -ne 0
}
Maintenant un test:
$ if isVgaConnected; then echo yes; else echo no; fi
yes
Il est branché, alors maintenant je le débranche:
$ if isVgaConnected; then echo yes; else echo no; fi
no
REMARQUE: ${1:+*-1+1}
autorise un argument booléen: Si quelque chose est présent, la réponse serait inversée: ( crtState >> 4 ) * -1 + 1
.
et le script final:
#!/bin/bash
export crtProcEntry=/proc/acpi/video/VID/CRT0/state
isVgaConnected() {
local crtState
read -a < $crtProcEntry crtState
test $(( ( ${crtState[1]} >>4 ) ${1:+*-1+1} )) -ne 0
}
delay=.1
unset switch
isVgaConnected || switch=not
while :;do
while isVgaConnected $switch;do
sleep $delay
done
if [ "$switch" ];then
unset switch
echo VGA IS connected
# doing something while VGA is connected
else
switch=not
echo VGA is NOT connected.
# doing something else, maybe.
fi
done
AVERTISSEMENTS: plus léger que xrandr
, mais pas sans importance avec un retard inférieur à 0,02 secondes, le script Bash ira en haut du processus des mangeurs de ressources (top
)!
Alors que cela coûte ~ 0,001 s:
$ time read -a </proc/stat crtStat
Cela nécessite ~ 0,030 sec:
$ read -a < /proc/acpi/video/VID/CRT0/state crtState
C'est grand! Ainsi, selon ce dont vous avez besoin, delay
peut être raisonnablement défini entre 0.5
et 2
.
J'ai enfin trouvé quelque chose, en utilisant ceci:
Avertissement important: Jouer avec /proc
et /sys
les entrées pourraient briser votre système !!! N'essayez donc pas ce qui suit sur les systèmes de production.
mapfile watchFileList < <(
find /sys /proc -type f 2>/dev/null |
grep -i acpi\\\|i91
)
Prompt=("/" "|" '\' '-');
l=0
while :; do
mapfile watchStat < <(
grep -H . ${watchFileList[@]} 2>/dev/null
)
for ((i=0;i<=${#watchStat[@]};i++)); do
[ "${watchStat[i]}" == "${oldStat[i]}" ] || echo ${watchStat[i]}
done
oldStat=("${watchStat[@]}")
sleep .5
printf "\r%s\r" ${Prompt[l++]}
[ $l -eq 4 ]&&l=0
done
... après un nettoyage des entrées indésirables:
for ((i=0;i<=${#watchFileList[@]};i++)); do
[[ "${watchFileList[$i]}" =~ /sys/firmware/acpi/interrupts/sci ]] &&
unset watchFileList[$i] && echo $i
done
J'ai pu lire ceci:
/proc/acpi/video/VID/CRT0/state:state: 0x1d
/proc/acpi/video/VID/CRT0/state:state: 0x0d
/proc/acpi/video/VID/CRT0/state:state: 0x1d
Lorsque je branche, débranche et rebranche le câble du moniteur.
Lorsque la configuration est demandée (exécution de system/preferences/monitor
ou xrandr
), les cartes graphiques font un type de - scan, donc exécutant xrandr -q
vous donne les informations, mais vous devez interroger le statut.
J'ai analysé tous les journaux (noyau, démon, X et ainsi de suite) en cherchant dans /proc
& /sys
, et rien ne semble clairement exister qui réponde à votre demande.
J'ai aussi essayé ça:
export spc50="$(printf "%50s" "")"
watch -n1 '
find /proc/acpi/video -type f |
xargs grep -H . |
sed "s/^\([^:]*):/\1'$spc50'}:/;
s/^\(.\{50\}\) *:/\1 /"'
Après tout cela, si vous exécutez System/Preferences/Monitor
alors qu'aucun nouvel écran n'a été branché ou débranché, l'outil apparaît simplement (normalement). Mais si vous avez déjà branché ou débranché un écran auparavant, vous exécuterez parfois cet outil et vous verrez votre bureau faire un type de reset ou refresh (idem si vous exécutez xrandr
).
Cela semble confirmer que cet outil demande xrandr
(ou fonctionne de la même manière) en interrogeant l'état périodiquement, en commençant au moment de son exécution.
Vous pouvez vous essayer:
$ for ((i=10;i--;)); do xrandr -q | grep ' connected' | wc -l; sleep 1; done
1
1
1
2
2
2
1
1
1
1
Cela affichera le nombre d'écrans (écrans) connectés, pendant 10 secondes.
Pendant que cela fonctionne, branchez et/ou débranchez votre écran/moniteur et regardez ce qui se passe. Vous pouvez donc créer une petite fonction de test Bash:
isVgaConnected() {
local xRandr=$(xrandr -q)
[ "$xRandr" == "${xRandr#*VGA1 con}" ] || return 0
return 1
}
qui serait utilisable comme dans:
$ if isVgaConnected; then echo yes; fi
Mais attention, xrandr
prend environ 0,140 sec à 0,200 sec alors qu'aucun changement ne se produit sur les fiches et jusqu'à 0,700 seconde chaque fois que quelque chose a été branché ou débranché juste avant ( REMARQUE: Il semble que ce ne soit pas une ressource mangeur).
Pour m'assurer que je n'enseigne pas quelque chose de incorrect, j'ai cherché sur le Web et dans la documentation, mais je n'ai rien trouvé sur DBus et écrans.
Enfin, j'ai exécuté dans deux fenêtres différentes dbus-monitor --system
(J'ai aussi joué avec des options) et le petit script que j'ai écrit:
$ for ((i=1000;i--;)); do isVgaConnected && echo yes || echo no; sleep .5; done
... et encore branché, que débranché le moniteur, plusieurs fois. Alors maintenant, je pourrais dire:
xrandr -q
pour savoir si un moniteur est branché ou non.Mais soyez prudent, car il ne semble pas y avoir d'autres moyens. Par exemple, xrandr
semble partager ces informations, donc mon bureau GNOME basculerait automatiquement vers xinerama
... lorsque j'exécutais xrandr
.
Les lignes suivantes sont apparues dans udevadm monitor
KERNEL[46578.184280] change /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)
UDEV [46578.195887] change /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)
lors de la connexion d'un moniteur au connecteur VGA. Il pourrait donc y avoir un moyen de comprendre cela.
Je suis resté à utiliser srandrd . Il surveille les événements X et déclenche votre script lorsqu'un affichage est connecté ou déconnecté.
Pour ceux qui, pour une raison quelconque, ne veulent pas emprunter la route hotplug, il est toujours possible de ne pas interroger dans un script en utilisant inotifywait:
#!/bin/bash SCREEN_LEFT = DP2 SCREEN_RIGHT = eDP1 START_DELAY = 5 renice +19 $$>/dev/null sleep $ START_DELAY OLD_DUAL = "factice" pendant que [ 1 ]; do DUAL = $ (cat /sys/class/drm/card0-DP-2/status)[.____. diplomatique .____.] if ["$ OLD_DUAL"! = "$ DUAL"]; alors si ["$ DUAL" == "connecté"]; puis echo 'Configuration double moniteur' xrandr --output $ SCREEN_LEFT --auto --rotate normal --pos 0x0 --output $ SCREEN_RIGHT --auto --rotate normal --below $ SCREEN_LEFT Else Echo 'Configuration moniteur unique' Xrandr --auto Fi OLD_DUAL = "$ DUAL" fi inotifywait -q -e close/sys/class/drm/card0-DP-2/status>/dev/null done
Il est préférable de l'invoquer depuis votre .xsessionrc, sans oublier la fin &. L'interrogation avec xrandr a donné de sérieux problèmes d'utilisation sur mon tout nouvel ordinateur portable (la souris se bloquait périodiquement).
Évidemment, il devrait y avoir quelque chose! :) Le système de fichiers/sys indique à l'espace utilisateur le matériel disponible, afin que les outils de l'espace utilisateur (tels que udev ou mdev) puissent remplir dynamiquement un répertoire "/ dev" avec des nœuds de périphérique représentant le matériel actuellement disponible. Linux propose deux interfaces hotplug:/sbin/hotplug et netlink.
Il y a une petite démo C dans le fichier suivant. http://www.kernel.org/doc/pending/hotplug.txt
La plupart du temps, les logiciels système/applications sous Linux utilisaient certaines techniques ipc pour communiquer entre eux. D-Bus est maintenant principalement utilisé avec les applications GNOME et pourrait vous aider.
D-BUS peut faciliter l'envoi d'événements ou de signaux à travers le système, permettant aux différents composants du système de communiquer et, finalement, de mieux s'intégrer. Par exemple, un démon Bluetooth peut envoyer un signal d'appel entrant que votre lecteur de musique peut intercepter, en coupant le son jusqu'à la fin de l'appel.
wiki:
D-Bus fournit à la fois un démon système (pour les événements tels que "nouveau périphérique matériel ajouté" ou "file d'attente d'imprimante modifiée") et un démon par session de connexion par utilisateur (pour les besoins généraux de communication interprocessus entre les applications utilisateur)
Il existe même une bibliothèque Python pour cela, et ubuntu a récemment utilisé cette capacité qui appelait " zeitgeist ".