NOTA: questo è stato testato su un laptop con una scheda grafica guidata i915.
sfondo
NOTA: quando viene collegata una nuova schermata, nessun evento viene inviato all'host, questo è rimasto vero anche dopo la mia ultima modifica. Quindi l'unico modo è usare il polling. Cercando di renderli il più efficienti possibile ...
EDIT # 3
Finalmente c'è una soluzione migliore (tramite ACPI):
Non c'è ancora nessun evento, ma ACPI sembra più efficiente di xrandr
indagare. (Nota: questo richiede moduli del kernel ACPI caricati, ma non richiede i privilegi di root).
La mia soluzione finale (usando bash):
isVgaConnected() {
local crtState
read -a < /proc/acpi/video/VID/CRT0/state crtState
test $(( ( ${crtState[1]} >>4 ) ${1:+*-1+1} )) -ne 0
}
Ora un test:
$ if isVgaConnected; then echo yes; else echo no; fi
yes
È collegato, quindi ora lo scollego:
$ if isVgaConnected; then echo yes; else echo no; fi
no
NOTA: ${1:+*-1+1}
permettere un booleano argomento: se qualcosa è presente , risposta sarebbe essere invertito: ( crtState >> 4 ) * -1 + 1
.
e la sceneggiatura finale:
#!/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
AVVERTENZE: più leggero di xrandr
, ma non irrilevante con un ritardo inferiore a 0,02 secondi, lo script Bash andrà in cima al processo dei mangiatori di risorse ( top
)!
Mentre questo costa ~ 0,001 secondi:
$ time read -a </proc/stat crtStat
Ciò richiede ~ 0,030 sec:
$ read -a < /proc/acpi/video/VID/CRT0/state crtState
Questo è grande! Quindi, a seconda di ciò di cui hai bisogno, delay
potrebbe essere ragionevolmente impostato tra 0.5
e 2
.
EDIT # 2
Ho finalmente trovato qualcosa, usando questo:
Importante dichiarazione di non responsabilità: giocare con /proc
e le /sys
voci potrebbero danneggiare il sistema !!! Quindi non provare quanto segue sui sistemi di produzione.
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
... dopo alcune pulizie di ingressi indesiderati:
for ((i=0;i<=${#watchFileList[@]};i++)); do
[[ "${watchFileList[$i]}" =~ /sys/firmware/acpi/interrupts/sci ]] &&
unset watchFileList[$i] && echo $i
done
Sono stato in grado di leggere questo:
/proc/acpi/video/VID/CRT0/state:state: 0x1d
/proc/acpi/video/VID/CRT0/state:state: 0x0d
/proc/acpi/video/VID/CRT0/state:state: 0x1d
Quando collego, scollego e ricollego il cavo del monitor.
Risposta originale
Quando viene richiesta la configurazione (in esecuzione system/preferences/monitor
o xrandr
), le schede grafiche eseguono un tipo di scansione , pertanto l'esecuzione xrandr -q
fornisce le informazioni, ma è necessario eseguire il polling dello stato.
Ho scansionato tutti i log (kernel, demone, X e così via) cercando in /proc
& /sys
, e chiaramente non sembra esistere nulla che soddisfi la tua richiesta.
Ho provato anche questo:
export spc50="$(printf "%50s" "")"
watch -n1 '
find /proc/acpi/video -type f |
xargs grep -H . |
sed "s/^\([^:]*):/\1'$spc50'}:/;
s/^\(.\{50\}\) *:/\1 /"'
Dopotutto, se esegui System/Preferences/Monitor
mentre non è stato appena collegato o scollegato alcun nuovo schermo, lo strumento apparirà semplicemente (normalmente). Ma se hai già collegato o scollegato uno schermo, a volte eseguirai questo strumento e vedrai il tuo desktop fare un tipo di ripristino o aggiornamento (lo stesso se esegui xrandr
).
Ciò sembra confermare che questo strumento richiede xrandr
(o funziona allo stesso modo) eseguendo periodicamente il polling dello stato, a partire dal momento in cui viene eseguito.
Potresti provare te stesso:
$ for ((i=10;i--;)); do xrandr -q | grep ' connected' | wc -l; sleep 1; done
1
1
1
2
2
2
1
1
1
1
Questo mostrerà quante schermate (display) sono collegate, per 10 secondi.
Mentre questo funziona, collega e / o scollega lo schermo / monitor e guarda cosa succede. Quindi potresti creare una piccola funzione di Bash test:
isVgaConnected() {
local xRandr=$(xrandr -q)
[ "$xRandr" == "${xRandr#*VGA1 con}" ] || return 0
return 1
}
che sarebbe utilizzabile come in:
$ if isVgaConnected; then echo yes; fi
Ma fai attenzione, xrandr
impiega circa 0,140 secondi a 0,200 secondi mentre non si verificano cambiamenti sulle spine e fino a 0,700 secondi ogni volta che qualcosa è stato collegato o scollegato poco prima ( NOTA: sembra non essere un mangiatore di risorse).
EDIT # 1
Per essere sicuro di non insegnare qualcosa di errato, ho cercato nel Web e nei documenti, ma non ho trovato nulla su DBus e schermate .
Infine, ho corso in due finestre diverse dbus-monitor --system
(ho anche giocato con le opzioni) e la piccola sceneggiatura che ho scritto:
$ for ((i=1000;i--;)); do isVgaConnected && echo yes || echo no; sleep .5; done
... e ancora una volta collegato, che scollegato il monitor, molte volte. Quindi ora potrei dire:
- In questa configurazione, utilizzando il driver i915 , non c'è altro modo che correre
xrandr -q
per sapere se un monitor è collegato o meno.
Ma fai attenzione, perché non sembrano esserci altri modi. Ad esempio, xrandr
sembra condividere queste informazioni, quindi il mio desktop GNOME passerebbe xinerama
automaticamente ... quando ho eseguitoxrandr
.
Alcuni documenti