инструмент для автоматического применения конфигурации randr, когда подключен внешний дисплей

<p>есть ли инструмент, который позволяет:</p><ul> <li>запоминать текущую конфигурацию randr (положение, ориентация, разрешение и т. д.) для каждого монитора,</li> <li>автоматически применить последнюю удачную конфигурацию, как только дисплей будет подключен, без необходимости возиться с апплетами или xrandr (1)?</li> </ul><p>конфигурации должны быть применены для каждого пользователя, для каждого дисплея.</p><p>если такого инструмента нет в дикой природе, я бы хотел собрать его сам, но, насколько я вижу, я не могу сказать, что монитор подключен. нужно ли опрашивать xrandr -q? время от времени, чтобы выяснить, что выход был подключен или отключен, или есть более эффективный способ сделать это? можно ли настроить udev именно на это?</p>

<p>я использую этот простой (самодельный) скрипт, который опрашивает randr и переключается между lvds1 и vga1, когда vga подключается/отключается. (для <strong> [~ # ~] hdmi [~ # ~] </strong> в следующем файле сценария измените все <code>vga1</code> до <code>hdmi1</code>)</p><p>это грязное решение, но оно работает просто отлично.</p><p>он настроен для моей настройки: вам, скорее всего, придется изменить выходные имена randr (<code>lvds1</code> а также <code>vga1</code>) и <a href="https://unix.stackexchange.com/questions/11888/randr-not-recognizing-monitor">в отличие от меня</a> вам, вероятно, будет хорошо с вашим стандартным режимом randr для vga.</p><pre><code>#!/bin/bash # setting up new mode for my vga xrandr --newmode "1920x1080" 148.5 1920 2008 2052 2200 1080 1089 1095 1125 +hsync +vsync xrandr --addmode vga1 1920x1080 # default monitor is lvds1 monitor=lvds1 # functions to switch from lvds1 to vga and vice versa function activatevga { echo "switching to vga1" xrandr --output vga1 --mode 1920x1080 --dpi 160 --output lvds1 --off monitor=vga1 } function deactivatevga { echo "switching to lvds1" xrandr --output vga1 --off --output lvds1 --auto monitor=lvds1 } # functions to check if vga is connected and in use function vgaactive { [ $monitor = "vga1" ] } function vgaconnected { ! xrandr | grep "^vga1" | grep disconnected } # actual script while true do if ! vgaactive && vgaconnected then activatevga fi if vgaactive && ! vgaconnected then deactivatevga fi sleep 1s done полные шаги:  поставьте вышеприведенный скрипт (homemademonitor.sh) в выбранный вами каталог   сделайте исполняемый файл .sh набрав следующую команду в терминале chmod +x homemademonitor.sh   запустите файл .sh ./homemademonitor.sh  

отвечая на "[a] способ узнать, что монитор был подключен" часть вопроса:поддержка по-прежнему немного варьируется, но в последних ядрах есть некоторая поддержка для генерации событий udev, когда происходит горячее подключение дисплея. с ядром 2.6.38 и оборудованием ati x1400 я получаю событие при первом подключении vga-дисплея, но никаких событий при последующих отключениях или повторных подключениях дисплея не происходит. <a href="https://stackoverflow.com/questions/5469828/how-to-create-a-callback-for-monitor-plugged-on-an-intel-graphics">аппаратное обеспечение intel может иметь лучшую поддержку. собственный драйвер nvidia в настоящее время не поддерживает kms; я не пробовал искать события горячей замены на оборудовании nvidia, но я сомневаюсь, что это сработает.если вы хотите поэкспериментировать с udev, попробуйте выполнить следующие действия: обновить до новейшего ядра убедитесь, что настройка режима ядра (kms) включена. если включено, об этом следует сообщать в выводе вашего ядра. мой говорит [drm] radeon kernel modesetting enabled а также [drm] initializing kernel modesetting запустить udevadm monitor --property и посмотрите, будут ли сообщения о событиях, когда вы отключаете дисплеи если вы получаете события udev на дисплее hotplug, вы можете запустить скрипт с правилом udev, например:action=="change", subsystem=="drm", hotplug=="1", run+="/path/to/hotplug.sh" <strong> примечание: </strong> это будет  не сработает, если вы используете графический процессор nvidia с проприетарным двоичным драйвером, поскольку он не использует kms. вы будете  нет получать любые события udev.

что касается инструмента, который может хранить профили конфигурации монитора для каждого пользователя и для каждого дисплея, <a href="https://github.com/phillipberndt/autorandr/">autorandr сделает именно это.в моем ноутбуке есть карта nvidia, поэтому я использую <a href="http://willem.engen.nl/projects/disper/">дисперсный бэкэнд вместо xrandr. autorandr будет использовать disper в качестве бэкэнда для управления вашими мониторами, если вы называете его как autodisper. для остальной части этого поста я буду ссылаться на это как autorandr для согласованности.вы можете сохранить профили с помощью autorandr --save profile_name. запуск autorandr сам по себе даст вам список профилей и определит, какой из них обнаружен в качестве текущей конфигурации.например:$ autorandr laptop syncmaster19 (detected) </code></pre><p>вы можете настроить автоматическую загрузку соответствующего профиля для текущей конфигурации с помощью <code>autorandr --change</code>. эта команда в сочетании с правилом udev для запуска, когда он подключен в горячем режиме, будет делать то, что вы просили.</p><p>в качестве дополнительной меры предосторожности я добавил <code>--default laptop</code> к этой команде, которая по умолчанию будет отображать экран ноутбука, если нет сохраненного профиля, соответствующего текущей конфигурации. таким образом, полная команда, которую я использую для переключения дисплеев:</p><pre><code>autorandr --change --default laptop </code></pre><p>к сожалению, моя машина не выдает вывод udev, когда я подключаю монитор к горячему подключению. я использую проприетарные драйверы nvidia, так что это не удивительно. поэтому я связал его с ключом xf68display (fn-f8), что почти так же хорошо.</p>

<p>я использовал предложенное выше правило udev вместе со сценарием shell, который выглядит как</p><pre><code>#!/bin/sh dmode="$(cat /sys/class/drm/card0-vga-1/status)" export display=:0 export xauthority=/home/yourusername/.xauthority if [ "${dmode}" = disconnected ]; then /usr/bin/xrandr --auto elif [ "${dmode}" = connected ];then /usr/bin/xrandr --output vga1 --auto --right-of lvds1 else /usr/bin/xrandr --auto fi часть xauthority важна, так же как и экспорт display, вы можете использовать echo $display</code> чтобы узнать, какому числу он равен. используйте <code>xrandr -q</code> чтобы увидеть внешние мониторы, которые у вас есть. последнее утверждение просто, чтобы убедиться, что вы никогда не застряли без дисплея.</p>

<p>небольшая программа, которая ждет, пока x-сервер уведомит ее об измененной конфигурации монитора, а затем выполнит заданную команду (например, <code>autorandr</code>, упомянутый в другом ответе), доступна по адресу: <a href="https://bitbucket.org/portix/srandrd/overview">https: // bitbucket .org/portix/srandrd/обзор</a> </p><p>похоже, это более чистое решение, использующее <code>udev</code> (где вам нужно беспокоиться о поиске подходящего x-сервера и т.д.)</p>

<p>если вам нужно, чтобы он автоматически обнаруживал отображение при подключении, кажется, что самое чистое решение - добавить правило udev для запуска сценария, содержащего ваши команды xrandr. вот пример решения одного пользователя <a href="https://bbs.archlinux.org/viewtopic.php?pid=1329375#p1329375">1</a> :</p><p><strong> отслеживать (выводить) события udev с помощью <code>udevadm</code> </strong><br> этот шаг будет наиболее важным для каждого пользователя. запустить <code>udevadm monitor --environment --udev</code>. затем подключите кабель hdmi.</p><p><strong> правило udev </strong><br> основываясь на выводе вышеприведенной команды, пользователь создал это правило udev в <code>/etc/udev/rules.d/95-monitor-hotplug.rules</code>.</p><pre><code>kernel=="card0", subsystem=="drm", env{display}=":0", env{xauthority}="/home/dan/.xauthority", run+="/usr/local/bin/hotplug\_monitor.sh" </code></pre><p>обратите внимание на используемые переменные среды, поэтому xrandr будет запускаться под профилем пользователя.</p><p><strong> скрипт xrandr hotplug\_monitor.sh </strong></p><p>вы можете настроить параметры xrandr в соответствии с вашими потребностями.</p><pre><code>#! /usr/bin/bash export display=:0 export xauthority=/home/dan/.xauthority function connect(){ xrandr --output hdmi1 --right-of lvds1 --preferred --primary --output lvds1 --preferred } function disconnect(){ xrandr --output hdmi1 --off } xrandr | grep "hdmi1 connected" &> /dev/null && connect || disconnect </code></pre>

<p>для тех, кто по какой-либо причине не хочет идти по маршруту горячего подключения, все еще возможно не опрашивать в скрипте с использованием inotifywait:</p><pre> #!/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 сделано </pre><p>опрос xrandr дал серьезные проблемы с юзабилити на моем новом ноутбуке (мышь периодически зависала).</p>

<p>для упрощения, например, в xfce, пожалуйста, установите "arandr", который должен быть доступен в ваших дистрибутивах. сконфигурируйте ваш дисплей, используя "arandr", затем сохраните его, например, как "displaylayout". арандр должен добавить для вас расширение ".sh", чтобы его можно было напрямую использовать в "функции connect ()", как написано в сценарии "hotplug\_monitor.sh", упомянутом выше iyrin, например:</p><pre><code>function connect(){ /path/to/displaylayout.sh } </code></pre><p>чтобы использовать механизм отключения, добавьте вверху скрипта чуть ниже "#!/bin/bash" примерно так:</p><pre><code>#!/bin/bash # plugged\_external=`xrandr | awk /"connected [0-9]"/'{print $1}' xrandr обнаружит дисплей и передаст вывод в awk, который отфильтрует его по регулярному выражению "connected", за которым следует цифра, которая, по сути, и есть то, что нам нужно. по моему мнению, нет необходимости совпадать с точным разрешением в регулярном выражении, потому что основной дисплей отображается как "подключенный основной", за которым следует число, то есть разрешение. тогда awk "print $ 1" будет печатать только первый столбец, который в этом случае является именем внешнего монитора, и это будет сохранено в переменной plugged\_external. далее вместо фиксированного отображаемого имени "hdmi1" в скрипте $ plugged_external можно использовать так:function disconnect(){ xrandr --output $plugged\_external --off } xrandr | grep "$plugged_external connected" &> /dev/null && connect || disconnect 

я думаю, что люди, которые смотрят на этот вопрос, не те, кто хочет использовать gnome, и те, кто использует gnome, не должны были бы смотреть на этот вопрос, но в интересах полноты:gnome имеет эту встроенную функциональность. если вы измените настройку через gnome-control-center, gnome-settings-daemon запомнит это (в .config/monitors.xml) и автоматически применяет его при подключении или отключении монитора.к сожалению, конфигурация в файле monitors.xml плохо документирована. смотрите вопрос <a href="https://unix.stackexchange.com/questions/152586/what-do-the-tags-in-monitors-xml-do">здесь . инструменты отображения гномов также не имеют возможности настройки панорамирования, масштабирования для каждого монитора и не уменьшают масштаб. поскольку многие люди используют экран ноутбука hidpi вместе с обычным экраном dpi, инструментов недостаточно, чтобы получить работоспособное решение.я видел это <a href="https://wiki.gnome.org/howdoi/hidpi">упомянуто как элемент дорожной карты для wayland хотя, когда это наконец произойдет, мы можем увидеть исправление упомянутых проблем. до тех пор в gnome я просто запускаю скрипт запуска после задержки, чтобы настроить xrandr вручную.

при использовании решения peoro я получил дополнительный вывод от xrandr, поэтому я использовал опцию -c для grep, которая подсчитывает количество совпадений. я адаптировал его для hdmi и добавил аудио переключатель:#!/bin/bash # adapted from http://unix.stackexchange.com/questions/4489/ # default monitor is lvds1 monitor=lvds1 # functions to switch from lvds1 to hdmi1 function activatehdmi { xrandr --output hdmi1 --mode 1920x1080 --dpi 160 --output lvds1 --off pactl set-card-profile 0 output:hdmi-stereo-extra1 monitor=hdmi1 } function deactivatehdmi { xrandr --output hdmi1 --off --output lvds1 --auto pactl set-card-profile 0 output:analog-stereo monitor=lvds1 } # functions to check if hdmi is connected and in use function hdmiactive { [ $monitor = "hdmi1" ] } function hdmiconnected { [[ `xrandr | grep "^hdmi1" | grep -c disconnected` -eq 0 ]] } # actual script while true do if ! hdmiactive && hdmiconnected then activatehdmi fi if hdmiactive && ! hdmiconnected then deactivatehdmi fi sleep 1s done </code></pre>

<p>редактирование моего ответа, чтобы упростить настройку.</p><p>установите autorandr для автоматизации макета экрана в xrandr, загрузите последнюю версию .deb из <a href="https://github.com/nalipaz/autorandr/releases">https://github.com/nalipaz/autorandr/releases</a> и запустите:</p><pre><code>dpkg -i [file] </code></pre><p>настройка авторандра с сохраненными макетами экрана</p><pre><code>autorandr --save [docked|mobile|home|etc] </code></pre><p>например, на моем ноутбуке без подключенных мониторов я настроил arandr так, как хочу, затем запустил:</p><pre><code>autorandr --save mobile </code></pre><p>затем подключил мой hdmi и перенастроил arandr, затем запустил:</p><pre><code>autorandr --save docked </code></pre><p>после настройки каждого макета, который вы можете запустить (замените "mobile" на предыдущее предпочтительное имя, я использовал mobile):</p><pre><code>autorandr --default mobile </code></pre><p>теперь, когда autorandr полностью настроен, вы можете автоматизировать процесс, установив пакет, который будет запрашивать подключенные дисплеи и запускать <code>autorandr --change</code> при обнаружении. да, я знаю об udev, и вы можете настроить его, если он работает для вас, но в моем тестировании udev не работал для моего hdmi последовательно. это работало только 1 из каждых 20 штепселей/отключений или около того, и иногда это просто останавливалось вообще.</p><p>загрузите последнюю версию .deb здесь: <a href="https://github.com/nalipaz/poll-xrandr/releases/">https://github.com/nalipaz/poll-xrandr/releases/</a> и установите с</p><pre><code>dpkg -i [file] </code></pre><p>скорее всего, необходимо выполнить больше задач после завершения <code>autorandr --change</code>, autorandr позволяет вставлять эти команды в файл ~/.autorandr/postswitch. сделайте следующее:</p><pre><code>cd ~/.autorandr/ && touch postswitch && chmod +x postswitch </code></pre><p>теперь отредактируйте файл postswitch, чтобы он был похож на следующее:</p><pre><code>#!/bin/bash if pidof conky > /dev/null 2>&1; then killall conky fi (sleep 2s && xrandr-adjust-brightness restore -q) & (sleep 2s && nitrogen --restore) & (sleep 3s && conky -q) & </code></pre><p>кроме того, вы, вероятно, захотите добавить autorandr и poll-xrandr в свои стартапы, что-то вроде следующих двух команд:</p><pre><code>autorandr --change & poll-xrandr & </code></pre><p>отключите или подключите монитор и наблюдайте за волшебством!</p>