it-swarm-ru.tech

Как я могу определить, когда монитор подключен или отключен?

Есть ли какое-либо событие, которое запускается, когда я подключаю или отключаю внешний монитор к DisplayPort моего ноутбука? ACPID и UDEV вообще не реагируют.

Я использую встроенную графику на чипе Intel. Здесь - похожая дискуссия, которой уже пару лет.

Я не хочу использовать опрос, но мне нужно иметь некоторую конфигурацию, которая автоматически устанавливает параметры дисплея в зависимости от того, подключен ли дисплей.

54
janoliver

ПРИМЕЧАНИЕ: это было проверено на ноутбуке с графической картой с приводом i915.


Фон

ПРИМЕЧАНИЕ: Когда подключен новый экран, хосту не отправляется событие, оно остается верным даже после моего последнего редактирования. Таким образом, единственный способ - использовать опрос. Пытаясь сделать их максимально эффективными ...

Правка № 3

Наконец, есть одно лучшее решение (через ACPI):

Пока еще нет событий, но ACPI кажется более эффективным, чем xrandr, чтобы узнать. (Примечание: для этого требуются загруженные модули ядра ACPI, но не требуются права root).

Мое окончательное решение (с использованием bash):

isVgaConnected() {
    local crtState
    read -a < /proc/acpi/video/VID/CRT0/state crtState
    test $(( ( ${crtState[1]} >>4 ) ${1:+*-1+1} )) -ne 0
}

Теперь тест:

$ if isVgaConnected; then echo yes; else echo no; fi 
yes

Он подключен, так что теперь я отключаю его:

$ if isVgaConnected; then echo yes; else echo no; fi 
no

ПРИМЕЧАНИЕ: ${1:+*-1+1} разрешить аргумент логическое значение: если что-то присутствует, ответ будет инвертированным: ( crtState >> 4 ) * -1 + 1.

и последний сценарий:

#!/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

ПРЕДУПРЕЖДЕНИЯ: легче, чем xrandr, но не менее важно с задержкой меньше, чем 0.02 секунд сценарий Bash перейдет к началу процесса пожирателей ресурсов (top)!

Пока это стоит ~ 0,001 сек:

$ time read -a </proc/stat crtStat

Это требует ~ 0,030 сек:

$ read -a < /proc/acpi/video/VID/CRT0/state crtState

Это большое! Таким образом, в зависимости от того, что вам нужно, delay может быть разумно установлено между 0.5 а также 2.

Правка № 2

Я наконец-то нашел что-то, используя это:

Важный отказ от ответственности: Игра с /proc а также /sys записи могут сломать вашу систему !!! Так что не пытайтесь сделать следующее на производственных системах.

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

... после некоторой очистки от нежелательных записей:

for ((i=0;i<=${#watchFileList[@]};i++)); do
  [[ "${watchFileList[$i]}" =~ /sys/firmware/acpi/interrupts/sci ]] &&
      unset watchFileList[$i] && echo $i
done

Я был в состоянии прочитать это:

/proc/acpi/video/VID/CRT0/state:state: 0x1d
/proc/acpi/video/VID/CRT0/state:state: 0x0d
/proc/acpi/video/VID/CRT0/state:state: 0x1d

Когда я подключаю, отключаю и снова подключаю кабель монитора.

Когда конфиг запрашивается (работает system/preferences/monitor или xrandr), видеокарты выполняют тип сканирование, поэтому выполняется xrandr -q дать вам информацию, но вы должны опросить статус.

Я просмотрел все журналы (ядро, демон, X и т.д.), Просматривая /proc & /sys, и явно не существует ничего, что могло бы удовлетворить вашу просьбу.

Я тоже попробовал это:

export spc50="$(printf "%50s" "")"
watch -n1  '
    find /proc/acpi/video -type f |
        xargs grep -H . |
        sed "s/^\([^:]*):/\1'$spc50'}:/;
             s/^\(.\{50\}\) *:/\1 /"'

После всего этого, если вы запустите System/Preferences/Monitor пока новый экран не был подключен или отключен, инструмент будет отображаться просто (обычно). Но если вы ранее подключали или отключали экран, иногда вы запускаете этот инструмент, и вы видите, что ваш рабочий стол делает вид сбросить или обновить (то же самое, если вы запускаете xrandr).

Кажется, это подтверждает, что этот инструмент запрашивает xrandr (или работает аналогичным образом), периодически опрашивая состояние, начиная с момента его запуска.

Вы можете попробовать себя:

$ for ((i=10;i--;)); do xrandr -q | grep ' connected' | wc -l; sleep 1; done
1
1
1
2
2
2
1
1
1
1

Это покажет, сколько экранов (дисплеев) подключено, за 10 секунд.

Пока это работает, подключите и/или отключите ваш экран/монитор и посмотрите, что происходит. Таким образом, вы можете создать небольшую тестовую функцию Bash:

isVgaConnected() {
    local xRandr=$(xrandr -q)
    [ "$xRandr" == "${xRandr#*VGA1 con}" ] || return 0
    return 1
}

который будет использоваться как в:

$ if isVgaConnected; then echo yes; fi

Но будьте осторожны, xrandr занимает около от 0,140 с до 0,200 с , в то время как на вилках не происходит никаких изменений и до 0,700 с всякий раз, когда что-то было подключено или отключено непосредственно перед ( ПРИМЕЧАНИЕ: Кажется, это не пожиратель ресурсов).

Правка # 1

Чтобы убедиться, что я не преподаю что-то неправильное, я искал в Интернете и документах, но ничего не нашел о DBus and Screens.

Наконец, я запустил в двух разных окнах dbus-monitor --system (Я тоже играл с опциями) и небольшой сценарий, который я написал:

$ for ((i=1000;i--;)); do isVgaConnected && echo yes || echo no; sleep .5; done

... и снова подключил, чем отключил монитор, много раз. Теперь я могу сказать:

  • В этой конфигурации с использованием драйвера i915 нет другого способа, кроме запуска xrandr -q чтобы узнать, подключен ли монитор или нет.

Но будьте осторожны, потому что, похоже, других путей нет. Например, xrandr, похоже, делится этой информацией, поэтому мой рабочий стол GNOME переключился бы на xinerama автоматически ... , когда я запустил xrandr.

Некоторые документы

14
F. Hauri

Следующие строки появились в 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)

при подключении монитора к VGA-разъему. Так что может быть способ выяснить это.

4
sebastianwagner

Я придерживался использования srandrd . Он отслеживает события X и запускает ваш сценарий, когда дисплей подключается или отключается.

3
scorpp

Для тех, кто по какой-либо причине не хочет идти по маршруту горячего подключения, все еще возможно не опрашивать в скрипте с использованием inotifywait:

 #!/Bin/Баш 
 
 SCREEN_LEFT = DP2 
 SCREEN_RIGHT = eDP1 
 START_DELAY = 5 
 
 renice +19 $$>/dev/null 
 
 sleep $ START_DELAY 
 
 OLD_DUAL = "dummy" 
 
 while [ 1]; do 
 DUAL = $ (cat /sys/class/drm/card0-DP-2/status)

 if ["$ OLD_DUAL"! = "$ DUAL"]; затем 
 if ["$ DUAL" == "подключен"]; затем 
 echo 'Настройка двух мониторов' 
 xrandr --output $ SCREEN_LEFT --auto --rotate normal --pos 0x0 - output $ SCREEN_RIGHT --auto --rotate normal --below $ SCREEN_LEFT 
 Else 
 Echo 'Настройка одного монитора' 
 Xrandr --auto 
 Fi 
 
 OLD_DUAL = "$ DUAL" 
 fi 
 
 inotifywait -q -e close/sys/class/drm/card0-DP-2/status>/dev/null 
 сделано 
 

Лучше всего вызывать его из .xsessionrc, не забывая окончание &. Опрос xrandr дал серьезные проблемы с юзабилити на моем новом ноутбуке (мышь периодически зависала).

3
Balzola

Очевидно, что-то должно быть! Файловая система :)/sys сообщает пользовательскому пространству, какое оборудование доступно, поэтому инструменты пользовательского пространства (такие как udev или mdev) могут динамически заполнять каталог "/ dev" узлами устройства, представляющими доступное в настоящее время оборудование. Linux предоставляет два интерфейса горячего подключения:/sbin/hotplug и netlink.

В следующем файле есть небольшая демонстрация C. http://www.kernel.org/doc/pending/hotplug.txt

0
roncsak

В основном системное/прикладное программное обеспечение в Linux сегодня использует некоторые методы ipc для связи друг с другом. D-Bus теперь в основном используется с приложениями GNOME и может помочь.

Linux Journal:

D-BUS может облегчать отправку событий или сигналов через систему, позволяя различным компонентам системы обмениваться данными и, в конечном итоге, лучше интегрироваться. Например, демон Bluetooth может отправлять сигнал входящего вызова, который может перехватить ваш музыкальный проигрыватель, приглушая громкость до завершения вызова.

вики:

D-Bus предоставляет как системный демон (для таких событий, как "добавленное новое аппаратное устройство" или "очередь принтера изменена"), так и демон для сеанса входа в систему для каждого пользователя (для общих потребностей межпроцессного взаимодействия между пользовательскими приложениями)

Для этого есть даже библиотека Python), и Ubuntu недавно использовала эту способность, которая называется " zeitgeist ".

0
Amir Naghizadeh