Added another monitor onto my Linux desktop, and soon got sick on clicking the “Extend to Right” every time I turned the monitor on. So, started to investigate how to enable this automatically, I mean, Windows does this well. So, so googling I went. However, the found a lot of posts talking about using a Udev rule, calling a script. I tried this route for a while, and when my head really hurt, came across a post on https://bbs.archlinux.org/viewtopic.php?id=170294. His symptoms mimicked mine: wouldn’t work when called through Udev, but would through command line; If I put a sleep loop in the script, then after 5 seconds or so, it would work. So, he touted another method using Systemd instead.
Basically”
Create a Udev rule (/etc/udev/rules.d/99-monitor-hotplug.rules:
ACTION=="change", KERNEL=="card0", SUBSYSTEM=="drm", RUN+="/bin/systemctl start monitor_plug.service"
then, restart Idev with service udev restart
Next, create a service in systemd:
create a /etc/systemd/system/monitor_plug.service with the following code
[Unit] Description=Monitor hotplug [Service] Type=simple RemainAfterExit=no ExecStart=/usr/local/bin/monitor-hotplug.sh [Install] WantedBy=multi-user.target
Load that into the system with systemd enable monitor-hotplug
Last step is to create the code for the script (/usr/local/bin/monitor-hotplug.sh) – this has changed on upgrade to Ubuntu 18.04. Previously (on 16.04), monitor was called DP1, now it is called DP-1. Same for HDMI, was HDMI1, but now HDMI-1. You cannot set a variable with a hyphen (-) in it in bash, so this broke the script. Work around was to change how we declare the variable to remove the hyphen. Also, the value of the variable was changed from yes, to the device name (with hyphen). Then, change the direct names in the xrandr commands to be the variables instead.
#!/bin/bash
#Adapt this script to your needs.
DEVICES=$(find /sys/class/drm/*/status)
#inspired by /etc/acpd/lid.sh and the function it sources
echo "##### Monitor start script #####" >> /tmp/monitor
displaynum=`ls /tmp/.X11-unix/* | sed s#/tmp/.X11-unix/X##`
display=":$displaynum.0"
#export DISPLAY=":$displaynum.0"
export DISPLAY=":0"
# from https://wiki.archlinux.org/index.php/Acpid#Laptop_Monitor_Power_Off
#export XAUTHORITY=$(ps -C Xorg -f --no-header | sed -n 's/.*-auth //; s/ -[^ ].*//; p')
#export DISPLAY=$(w -h -s | grep ":[0-9]\W" | head -1 | awk '{print $2}')
X_USER=$(w -h -s | grep ":[0-9]\W" | head -1 | awk '{print $1}')
export XAUTHORITY=/home/$X_USER/.Xauthority
#export XAUTHORITY="/home/kelvins/.Xauthority"
echo $XAUTHORITY >> /tmp/monitor
echo $X_USER >> /tmp/monitor
echo $DISPLAY >> /tmp/monitor
#this while loop declare the $HDMI1 $VGA1 $LVDS1 and others if they are plugged in
while read l
do
dir=$(dirname $l);
status=$(cat $l);
dev=$(echo $dir | cut -d\- -f 2-);
echo "Dev is $dev" >> /tmp/monitor
if [ $(expr match $dev "HDMI") != "0" ]
then
#REMOVE THE -X- part from HDMI-X-n
dev=HDMI${dev#HDMI-?}
# 4/10/2020 - Ubuntu 18.04 different from 16.04
# else
# dev=$(echo $dev | tr -d '-')
fi
if [ "connected" == "$status" ]
then
echo $dev "connected" >> /tmp/monitor
# declare $dev="yes";
declare $(echo $dev | tr -d '-')=$dev;
fi
done <<< "$DEVICES"
echo `date` >> /tmp/monitor
if [ ! -z "$HDMI1" -a ! -z "$VGA1" ]
then
echo "HDMI1 and VGA1 are plugged in" >> /tmp/monitor
xrandr --output LVDS1 --off
xrandr --output VGA1 --mode 1920x1080 --noprimary
xrandr --output HDMI1 --mode 1920x1080 --right-of VGA1 --primary
#elif [ ! -z "$HDMI1" -a -z "$VGA1" ]; then
# echo "HDMI1 is plugged in, but not VGA1"
# xrandr --output LVDS1 --off
# xrandr --output VGA1 --off
# xrandr --output HDMI1 --mode 1920x1080 --primary
elif [ ! -z "$DP1" -a ! -z "$HDMI1" ]
then
echo "HDMI1 and DP1 are plugged in" >> /tmp/monitor
# while ! xrandr | grep 'DP1 connected' ; do sleep 1; done;
/usr/bin/xrandr --output $DP1 --mode 1920x1080 --primary
# /usr/bin/xrandr --output DP1 --auto
echo $? >> /tmp/monitor
/usr/bin/xrandr --output $HDMI1 --noprimary --right-of $DP1
echo $? >> /tmp/monitor
elif [ -z "$HDMI1" -a ! -z "$VGA1" ]; then
echo "VGA1 is plugged in, but not HDMI1" >> /tmp/monitor
xrandr --output LVDS1 --off
# xrandr --output HDMI1 --off
xrandr --output VGA1 --mode 1920x1080 --primary
elif [ ! -z "$HDMI1" -a -z "$DP1" ]; then
echo "HDMI1 is plugged in, DP1 is not" >> /tmp/monitor
/usr/bin/xrandr --output $DP1 --off
/usr/bin/xrandr --output $HDMI1 --primary
else
echo "No external monitors are plugged in" >> /tmp/monitor
xrandr --output LVDS1 --off
# xrandr --output HDMI1 --off
xrandr --output LVDS1 --mode 1366x768 --primary
fi
Change the script to be executable with chmod +x /usr/local/bin/monitor-hotplug.sh