Jak mogę wykryć, kiedy monitor jest podłączony lub odłączony?


53

Czy jest jakieś zdarzenie, które jest wywoływane po podłączeniu lub wyjęciu zewnętrznego monitora do DisplayPort mojego laptopa? ACPID i UDEV wcale nie reagują.

Używam wbudowanej grafiki na chipie Intel. Oto podobna dyskusja, która ma już kilka lat.

Nie chcę używać odpytywania, ale muszę mieć konfigurację, która automatycznie ustawia ustawienia wyświetlania w zależności od tego, czy wyświetlacz jest podłączony.


4
Można to zrobić za pomocą udev. Jaka jest twoja wersja jądra? Czy używasz KMS (ustawienia trybu jądra)?
Andy,

Dziękuję za odpowiedź. Nie jestem pewien co do KMS, ale jak powiedziałem w pytaniu, udev nie wysyła żadnych zdarzeń. ( monitor udevadm - właściwość w ogóle nie reaguje)
janoliver

@Andy: kiedy to się ostatnio pojawiło , wydawało się, że większość systemów wymaga odpytywania. Jeśli znalazłeś sposób na wywołanie zdarzenia udev, czy możesz odpowiedzieć na to pytanie?
Gilles „SO- przestań być zły”

1
W końcu uruchomiłem ładowanie i915 jako modułu jądra.
janoliver

3
Możesz użyć xrandr lub disper, aby wykryć, czy monitor zewnętrzny został podłączony. Github.com/wertarbyte/autorandr może pokazać, jak z nich korzystać. Ale xrandr / disper może nie obsługiwać twojej karty graficznej.
numer

Odpowiedzi:


13

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ż xrandrzapytanie. (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, delaymożna rozsądnie ustawić pomiędzy 0.5a 2.

EDYCJA 2

W końcu znalazłem coś, używając tego:

Ważna informacja: Zabawa /proci /syswpisy 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/monitorlub xrandr), karty graficzne wykonują rodzaj skanowania , więc uruchomienie xrandr -qdaje ci informacje, ale musisz sprawdzić status.

Przeskanowałem wszystkie logi (jądro, demon, X i tak dalej) przeszukując /proci /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/Monitorgdy 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, xrandrzajmuje 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 -qaby sprawdzić, czy monitor jest podłączony czy nie.

Ale zachowaj ostrożność, ponieważ wydaje się, że nie ma innych sposobów. Na przykład xrandrwydaje się , że udostępnia te informacje, więc mój pulpit GNOME przełączyłby się xineramaautomatycznie na ... po uruchomieniuxrandr .

Niektóre dokumenty


4

Pojawiły się następujące wiersze 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)

podczas podłączania monitora do złącza VGA. Więc może istnieć sposób, aby to rozgryźć.


Dzięki nVidia 9800 GT i zastrzeżonym sterownikom monitor udevadm nic nie pokazuje po podłączeniu monitora HDMI. Jakiego sprzętu / sterowników używasz?
frankster

Szkoda, że ​​to nie jest dla mnie niezawodne. Czasami otrzymuję te komunikaty o zdarzeniach, kiedy podłączam monitor, a czasem nie.
Tobias

3

Dla tych, którzy z jakiegokolwiek powodu nie chcą wybrać trasy hotplug, nadal można nie odpytywać w skrypcie za pomocą inotifywait:

#! / bin / bash

SCREEN_LEFT = DP2
SCREEN_RIGHT = eDP1
START_DELAY = 5

renice +19 $$> / dev / null

spać $ START_DELAY

OLD_DUAL = „manekin”

podczas gdy [1]; zrobić
    DUAL = $ (cat / sys / class / drm / card0-DP-2 / status)

    if [„$ OLD_DUAL”! = „$ DUAL”]; następnie
        jeśli [„$ DUAL” == „podłączony”]; następnie
            echo „Konfiguracja podwójnego monitora”
            xrandr --output $ SCREEN_LEFT --auto --rotate normal --pos 0x0 --output $ SCREEN_RIGHT --auto --rotate normal - poniżej $ SCREEN_LEFT
        jeszcze
            echo „Konfiguracja pojedynczego monitora”
            xrandr --auto
        fi

        OLD_DUAL = „$ DUAL”
    fi

    inotifywait -q -e close / sys / class / drm / card0-DP-2 / status> / dev / null
gotowy

Najlepiej wywołać go z twojego .xsessionrc, nie zapominając o zakończeniu &. Sondowanie za pomocą xrandr spowodowało poważne problemy z użytecznością na moim nowym laptopie (mysz od czasu do czasu przestała działać).


Nie pomyślałbym, że możesz używać inotify /proci po prostu inotifywait -q -e close /sys/class/drm/card0-DP-2/status nie kończyło się to po odłączeniu DP-2 w moim systemie
nhed

3

Wsadziłem do korzystania srandrd . Monitoruje zdarzenia X i uruchamia skrypt, gdy ekran zostanie podłączony lub rozłączony.


0

Oczywiście powinno być coś! :) System plików / sys informuje przestrzeń użytkownika, jaki sprzęt jest dostępny, więc narzędzia przestrzeni użytkownika (takie jak udev lub mdev) mogą dynamicznie zapełniać katalog „/ dev” węzłami urządzeń reprezentującymi aktualnie dostępny sprzęt. Linux udostępnia dwa interfejsy hotplug: / sbin / hotplug i netlink.

W poniższym pliku znajduje się małe demo C. http://www.kernel.org/doc/pending/hotplug.txt


0

Większość oprogramowania systemowego / aplikacyjnego w Linuksie używało dzisiaj niektórych technik ipc do komunikacji między sobą. D-Bus jest obecnie używany głównie w aplikacjach GNOME i może pomóc.

Linux Journal:

D-BUS może ułatwiać wysyłanie zdarzeń lub sygnałów przez system, umożliwiając różnym komponentom w systemie komunikację, a ostatecznie lepszą integrację. Na przykład połączenie Bluetooth może wysłać sygnał połączenia przychodzącego, który może przechwycić odtwarzacz muzyki, wyciszając głośność do momentu zakończenia połączenia.

wiki:

D-Bus dostarcza zarówno demona systemowego (w przypadku zdarzeń takich jak „dodano nowe urządzenie sprzętowe” lub „zmieniono kolejkę drukarki”), jak i demona sesji dla użytkownika (dla ogólnych potrzeb komunikacji między procesami między aplikacjami użytkownika)

Jest nawet biblioteka Pythona, a Ubuntu niedawno użył tej zdolności, która nazywała się „ Zeitgeist ”.


-6

Graficznie widać, czy monitor jest rozpoznawany Monitor, wiem, że można to znaleźć na Ubuntu, Fedorze i innych w tej (lub podobnej) lokalizacji.

System / Preferencje / Monitor

Możesz włączyć / wyłączyć dowolny monitor lub używać go jednocześnie z duplikatem obrazu na obu monitorach lub niezależnych monitorach


2
Poprosił o zdarzenie, które zostanie wywołane, gdy monitor zostanie podłączony / odłączony
Michael Mrozek

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.