UWAGA: Zostało to przetestowane na laptopie z kartą graficzną napędzaną i915.
tło
UWAGA: Po podłączeniu nowego ekranu do hosta nie jest wysyłane żadne zdarzenie, pozostało to prawdą nawet po mojej ostatniej edycji. Więc jedynym sposobem jest użycie odpytywania. Staramy się, aby były jak najbardziej efektywne ...
EDYCJA 3
Wreszcie istnieje jedno lepsze rozwiązanie (poprzez ACPI):
Nadal nie ma zdarzenia, ale ACPI wydaje się bardziej wydajne niż xrandr
zapytanie. (Uwaga: Wymaga to załadowania modułów jądra ACPI, ale nie wymaga uprawnień roota).
Moje ostateczne rozwiązanie (używając bash):
isVgaConnected() {
local crtState
read -a < /proc/acpi/video/VID/CRT0/state crtState
test $(( ( ${crtState[1]} >>4 ) ${1:+*-1+1} )) -ne 0
}
Teraz test:
$ if isVgaConnected; then echo yes; else echo no; fi
yes
Jest podłączony, więc teraz go odłączam:
$ if isVgaConnected; then echo yes; else echo no; fi
no
UWAGA: ${1:+*-1+1}
pozwalają na logiczną argumentację: Jeśli coś jest obecny , odpowiedź byłaby odwrócona: ( crtState >> 4 ) * -1 + 1
.
i ostatni skrypt:
#!/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
OSTRZEŻENIA: lżejszy xrandr
, ale nie bez znaczenia, z opóźnieniem mniejszym niż 0,02 sekundy, skrypt Bash przejdzie na szczyt procesu zjadaczy zasobów ( top
)!
Chociaż kosztuje to ~ 0,001 s:
$ time read -a </proc/stat crtStat
Wymaga to ~ 0,030 s:
$ read -a < /proc/acpi/video/VID/CRT0/state crtState
To jest duże! Więc w zależności od potrzeb, delay
można rozsądnie ustawić pomiędzy 0.5
a 2
.
EDYCJA 2
W końcu znalazłem coś, używając tego:
Ważna informacja: Zabawa /proc
i /sys
wpisy mogą uszkodzić twój system !!! Więc nie próbuj poniższych rozwiązań w systemach produkcyjnych.
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
... po pewnym czyszczeniu niechcianych wpisów:
for ((i=0;i<=${#watchFileList[@]};i++)); do
[[ "${watchFileList[$i]}" =~ /sys/firmware/acpi/interrupts/sci ]] &&
unset watchFileList[$i] && echo $i
done
Byłem w stanie to przeczytać:
/proc/acpi/video/VID/CRT0/state:state: 0x1d
/proc/acpi/video/VID/CRT0/state:state: 0x0d
/proc/acpi/video/VID/CRT0/state:state: 0x1d
Po podłączeniu, odłączeniu i ponownym podłączeniu kabla monitora.
Oryginalna odpowiedź
Gdy konfiguracja zostanie zapytana (uruchomiona system/preferences/monitor
lub xrandr
), karty graficzne wykonują rodzaj skanowania , więc uruchomienie xrandr -q
daje ci informacje, ale musisz sprawdzić status.
Przeskanowałem wszystkie logi (jądro, demon, X i tak dalej) przeszukując /proc
i /sys
, i najwyraźniej nic nie istnieje, co spełnia twoje żądanie.
Też tego próbowałem:
export spc50="$(printf "%50s" "")"
watch -n1 '
find /proc/acpi/video -type f |
xargs grep -H . |
sed "s/^\([^:]*):/\1'$spc50'}:/;
s/^\(.\{50\}\) *:/\1 /"'
Po tym wszystkim, jeśli uruchomisz, System/Preferences/Monitor
gdy nowy ekran nie został właśnie podłączony ani odłączony, narzędzie pojawi się po prostu (normalnie). Ale jeśli wcześniej podłączyłeś lub odłączyłeś ekran, czasami uruchomisz to narzędzie i zobaczysz, że Twój pulpit dokonuje resetowania lub odświeżania (to samo, jeśli uruchamiasz xrandr
).
Wydaje się to potwierdzać, że to narzędzie prosi xrandr
(lub działa w ten sam sposób) okresowo odpytując status, zaczynając od momentu uruchomienia.
Możesz spróbować sam:
$ for ((i=10;i--;)); do xrandr -q | grep ' connected' | wc -l; sleep 1; done
1
1
1
2
2
2
1
1
1
1
Spowoduje to wyświetlenie liczby podłączonych ekranów przez 10 sekund.
Gdy to działa, podłącz i / lub odłącz ekran / monitor i sprawdź, co się stanie. Więc możesz stworzyć małą funkcję testową Bash:
isVgaConnected() {
local xRandr=$(xrandr -q)
[ "$xRandr" == "${xRandr#*VGA1 con}" ] || return 0
return 1
}
które byłyby użyteczne jak w:
$ if isVgaConnected; then echo yes; fi
Ale bądź ostrożny, xrandr
zajmuje to około 0,140 sek. Do 0,200 sek., A żadna zmiana nie następuje na wtyczkach i do 0,700 sek. Za każdym razem, gdy coś zostało podłączone lub odłączone tuż przed ( UWAGA: Wydaje się, że nie jest to pożeracz zasobów).
EDYCJA 1
Aby upewnić się, że nie uczę czegoś niepoprawnego, przeszukałem Internet i dokumenty, ale nie znalazłem nic na temat DBus i ekranów .
Na koniec uruchomiłem dwa różne okna dbus-monitor --system
(również bawiłem się opcjami) i napisałem mały skrypt:
$ for ((i=1000;i--;)); do isVgaConnected && echo yes || echo no; sleep .5; done
... i ponownie podłączany, niż odłączany monitor, wiele razy. Teraz mógłbym powiedzieć:
- W tej konfiguracji, przy użyciu sterownika i915 , nie ma innego sposobu niż uruchomienie,
xrandr -q
aby sprawdzić, czy monitor jest podłączony czy nie.
Ale zachowaj ostrożność, ponieważ wydaje się, że nie ma innych sposobów. Na przykład xrandr
wydaje się , że udostępnia te informacje, więc mój pulpit GNOME przełączyłby się xinerama
automatycznie na ... po uruchomieniuxrandr
.
Niektóre dokumenty