REMARQUE: ceci a été testé sur un ordinateur portable avec une carte graphique pilotée par i915.
Contexte
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 modification. Donc, le seul moyen est d'utiliser polling. Essayer de les rendre aussi efficaces que possible ...
EDIT # 3
Enfin, il existe une meilleure solution (via ACPI):
Il n'y a toujours pas d'événement, mais ACPI semble plus efficace que xrandr
de s'enquérir. (Nota: Cela nécessite des modules de 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
C'est branché, alors maintenant je le débranche:
$ if isVgaConnected; then echo yes; else echo no; fi
no
REMARQUE: ${1:+*-1+1}
permettre un booléen argument: Si quelque chose est présent , serait inversée réponse: ( 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 non sans importance, avec un délai inférieur à 0,02 seconde, le script Bash ira au sommet du processus des utilisateurs de ressources ( top
)!
Bien que cela coûte ~ 0.001 seconde:
$ time read -a </proc/stat crtStat
Cela nécessite ~ 0.030 seconde:
$ read -a < /proc/acpi/video/VID/CRT0/state crtState
C'est grand! Donc, en fonction de vos besoins, vous delay
pouvez choisir entre 0.5
et 2
.
EDIT # 2
J'ai enfin trouvé quelque chose, en utilisant ceci:
Avertissement important: Jouer avec /proc
et les /sys
entrées peuvent casser votre système !!! Alors n'essayez 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 non désirées:
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.
Réponse originale
Lorsque la configuration est demandée (en cours d'exécution system/preferences/monitor
ou xrandr
), les cartes graphiques effectuent un type d' analyse . Par conséquent, l'exécution xrandr -q
vous donne les informations, mais vous devez interroger l'état.
J'ai parcouru tous les journaux (noyau, démon, X, etc.) en cherchant dans /proc
& /sys
, et rien ne semble exister qui puisse satisfaire votre requête.
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 courez System/Preferences/Monitor
alors qu’aucun nouvel écran n’a été branché, ni débranché, l’outil apparaîtra simplement (normalement). Mais si vous avez déjà branché ou débranché un écran, vous exécuterez parfois cet outil et votre bureau affichera un type de réinitialisation ou d' actualisation (identique si vous exécutez xrandr
).
Cela semble confirmer que cet outil demande xrandr
(ou fonctionne de la même manière) en interrogeant périodiquement l’état de l’état, à partir du moment où il est exécuté.
Vous pouvez essayer vous-même:
$ 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 combien d'écrans (écrans) sont 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, cela xrandr
prend environ 0.140 sec à 0.200 sec quand aucun changement ne se produit sur les fiches et jusqu’à 0.700 secondes chaque fois que quelque chose était branché ou débranché juste avant ( NOTE: cela ne semble pas être un mangeur de ressources).
EDIT # 1
Pour m'assurer que je n'enseigne pas quelque chose d'incorrect, j'ai effectué des recherches sur le Web et dans la documentation, mais je n'ai rien trouvé sur DBus et Screens .
Enfin, j’ai couru 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:
- Dans cette configuration, à l' aide du pilote i915 , il n'y a pas d'autre moyen que de lancer l'exécution
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 cette information, mon bureau GNOME passerait xinerama
automatiquement à ... quand je courraisxrandr
.
Quelques docs