A tool for automatically applying RandR configuration when external display is plugged in
Regarding a tool which can store monitor configuration profiles on a per-user and per-display basis, autorandr will do exactly that.
My laptop has an NVIDIA card, so I use the disper backend instead of xrandr. Autorandr will use disper as the backend to manage your monitors if you call it as autodisper
. For the rest of this post though, I'll refer to it as autorandr
for consistency.
You can save profiles with autorandr --save profile_name
. Running autorandr
by itself will then give you a list of profiles, and identify which one is detected as the current configuration.
For instance:
$ autorandr
laptop
syncmaster19 (detected)
You can tell it to automatically load the appropriate profile for the current configuration with autorandr --change
. This command, paired with a udev rule to run it when it is hotplugged, would do what you requested.
As an added precaution I've appended --default laptop
to that command, which will make it default to the laptop's display if there is no saved profile that matches the current configuration. So the full command I use to switch displays is:
autorandr --change --default laptop
Unfortunately my machine doesn't give any udev output when I hotplug my monitor. I'm using the NVIDIA proprietary drivers, so that isn't surprising. So I have bound it to the XF68Display key (Fn-F8) for now, which is almost as good.
I'm using this simple (homemade) script that keeps polling RandR and switches between LVDS1 and VGA1 when VGA gets connected/disconnected. (For HDMI outputs, in the following script file, change all the VGA1
to HDMI1
)
It's a dirty solution, yet it's working just fine.
It's customized for my setup: you'll most likely need to change RandR output names (LVDS1
and VGA1
) and unlike me you'll probably be fine with your RandR default mode for VGA.
#!/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
Full Steps:
Put above script (
homemadeMonitor.sh
) into you preferred directoryMake the .sh file executable by typing the following command in the terminal
chmod +x homemadeMonitor.sh
Run the .sh file
./homemadeMonitor.sh
Responding to the "[a] way to tell that a monitor has been plugged in" part of the question:
The support still varies quite a bit, but with recent kernels there is some support for generating udev events when a display hotplug occurs. With kernel 2.6.38 and ATI X1400 hardware, I get an event the first time I connect a VGA display but no events on subsequent disconnects or reconnects of the display. Intel hardware may have better support. The NVIDIA proprietary driver does not currently support KMS; I haven't tried looking for hotplug events on NVIDIA hardware, but I'm doubtful it would work.
If you want to experiment with udev you could try the following steps:
- update to the newest kernel
- make sure that kernel mode setting (KMS) is enabled. If enabled, it should be reported in your kernel output. Mine says
[drm] radeon kernel modesetting enabled
and[drm] initializing kernel modesetting
- run
udevadm monitor --property
and see if events are reported when you (dis-)connect displays
If you are getting udev events on display hotplug, you can trigger a script with a udev rule like:
ACTION=="change", SUBSYSTEM=="drm", HOTPLUG=="1", RUN+="/path/to/hotplug.sh"
Note: This will not work if you use an nVIDIA GPU with the proprietary binary driver, since it does not use KMS. You will not get any udev events.