Skip to main content

Автоматическое определение подключенного монитора

Порой приходится довольно часто подключать/отключать дополнительный монитор от ноутбука, и не всегда в установленном дистрибутиве присутствует (если вообще есть) нормальное определение на данное действие. Попробуем исправить это упущение.

Итак, нам понадобится создать всего 2 файла для автоматического распознавания подключенного монитора. Сразу оговорюсь, что данный скрипт написан с целью ознакомления с подобной возможностью и поддерживает только один дополнительный выход, хотя никто не мешает дописать его для «трехголовой» карточки.

Начнем с выяснения названий выходов нашей видеокарты, для этого выполним команду xrandr в консоли (у кого нет — ставим пакет x11-xserver-utils). На выходе мы должны получить что-то вроде такого:

Screen 0: minimum 320 x 200, current 3200 x 1080, maximum 8192 x 8192
LVDS1 connected 1280x800+0+0 (normal left inverted right x axis y axis) 331mm x 207mm
   1280x800       60.0*+
   1024x768       60.0  
   800x600        60.3     56.2  
   640x480        59.9  
VGA1 connected 1920x1080+1280+0 (normal left inverted right x axis y axis) 477mm x 268mm
   1920x1080      60.0*+
   1680x1050      60.0  
   1600x900       60.0  
   1280x1024      75.0     60.0  
   1440x900       59.9  
   1280x800       59.8  
   1152x864       75.0  
   1280x720       60.0  
   1024x768       75.1     70.1     60.0  
   832x624        74.6  
   800x600        72.2     75.0     60.3     56.2  
   640x480        72.8     75.0     66.7     60.0  
   720x400        70.1  
TV1 unknown connection (normal left inverted right x axis y axis)
   848x480        59.9 +
   640x480        59.9 +
   1024x768       59.9  
   800x600        59.9

Вот мы и получили наши имена выходов, а именно TV1, LVDS1 и VGA1.

Теперь напишем правило для UDEV, писать придется от рута. Создадим файл /etc/udev/rules.d/99-monitor-interrupt.rules с таким содержимым:

SUBSYSTEM=="drm", ACTION=="change", RUN+="/usr/local/sbin/auto-xrandr"

Теперь у нас есть правило, которое при подключении и/или отключении выполняет некий скрипт auto-xrandr. Осталось создать последний (опять же от рута) файл /usr/local/sbin/auto-xrandr со следующим содержанием:

#!/bin/sh

PATH=/bin:/sbin:/usr/bin:/usr/sbin
SOCK_PATH=/tmp/.X11-unix
EXTERNAL_OUTPUT="VGA1"
INTERNAL_OUTPUT="LVDS1"
EXTERNAL_LOCATION="right"

case "$EXTERNAL_LOCATION" in
	left|LEFT)
		EXTERNAL_LOCATION="--left-of $INTERNAL_OUTPUT"
		;;
	right|RIGHT)
		EXTERNAL_LOCATION="--right-of $INTERNAL_OUTPUT"
		;;
	top|TOP|above|ABOVE)
		EXTERNAL_LOCATION="--above $INTERNAL_OUTPUT"
		;;
	bottom|BOTTOM|below|BELOW)
		EXTERNAL_LOCATION="--below $INTERNAL_OUTPUT"
		;;
	*)
		EXTERNAL_LOCATION="--left-of $INTERNAL_OUTPUT"
		;;
esac

try_set_xrandr()
{
	export DISPLAY=$1
	export XAUTHORITY=$2/.Xauthority
	xrandr >>/dev/null 2>&1
	[ $? -ne 0 ] && return 1
	xrandr >>/tmp/udev.log 2>&1
	xrandr | grep $EXTERNAL_OUTPUT | grep " connected " >>/dev/null 2>&1
	if [ $? -eq 0 ] ; then
		xrandr --output $INTERNAL_OUTPUT --auto --output $EXTERNAL_OUTPUT --auto $EXTERNAL_LOCATION >/dev/null 2>&1
		# Alternative command in case of trouble:
		# (sleep 2; xrandr --output $INTERNAL_OUTPUT --auto --output $EXTERNAL_OUTPUT --auto $EXTERNAL_LOCATION) &
	else
		xrandr --output $INTERNAL_OUTPUT --auto --output $EXTERNAL_OUTPUT --off >/dev/null 2>&1
	fi
}

HOMES=""
for HOME in `cat /etc/passwd | cut -d':' -f6`
do
	[ ! -f ${HOME}/.Xauthority ] && continue
	HOMES="${HOME} ${HOMES}"
done


for SOCKET in ${SOCK_PATH}/X*
do
	[ ! -S $SOCKET ] && continue
	LEN=`expr length $SOCKET`
	SOCK=":`expr substr $SOCKET $LEN 1`"

	for HOME in ${HOMES}
	do
		try_set_xrandr $SOCK $HOME
		[ $? -eq 1 ] && try_set_xrandr $SOCK.0 $HOME
	done
done

Делаем этот файл исполняемым:

sudo chmod +x /usr/local/sbin/auto-xrandr

Теперь поясню зачем нам в начале статьи нужны были имена выходов видеокарты. Нам нужно выбрать основной (или внутренний для ноутбука) выход. В моём случае это LVDS1 (на ноутбуке), соответственно он и прописан в переменной INTERNAL_OUTPUT. В EXTERNAL_OUTPUT нужно прописать второй выход, к которому, собственно, и подключается второй монитор.

Теперь о расположении второго монитора, оно регулируется переменной EXTERNAL_LOCATION, которая может принимать значения left, right, top и bottom (слева, справа, сверху или снизу соответственно от внутреннего монитора/выхода).

В переменной SOCK_PATH содержится путь до локальных сокетов сервера X11, в моём случае это /tmp/.X11-unix. В данной папке лежат файлики с именами X0, X1 и т.п., где окончание соответствует номеру X сервера. Бывает, что на одном компьютере запущено и два X сервера параллельно (как вариант, на 7 и на 8 терминале), соответственно, для обоих и приходится менять разрешения.

Теперь следующее пояснение по скрипту, xrandr в оном выполняется вне окружения, и ему не известны параметры авторизации, поэтому приходится перебирать всех пользователей и искать в их домашних папках файл Xauthority, дабы дать понять утилите что доступ до сервера у нас все же есть и мы сможем сменить настройки экрана.

Ну, и ещё одно дополнение, не всегда удается подключиться по короткому имени X дисплея (например, «:0»), поэтому иногда приходится обращаться по полному имени («:0.0»).

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *