Hotplugging a Secondary Display on Linux

GNU/Linux has been ready for the desktop for quite some time. And yet, when trying to tell the world about how ready Desktop Linux is, using a well prepared Open Office presentation, I am often faced with having to smile and say, oops looks like I need to restart X windows before my computer [Linux] can detect the LCD projector.

Lets face it, there are still some glitches here and there but the FOSS community is working hard at solving those problems, one by one. One such problem has been the inability to plug in an external display such as an external monitor or LCD projector and get it to "just work" without having to restart X Windows. That was until Xorg 7.3 came along!

Ever since I heard of Xorg 7.3 a couple of months earlier, I waited eagerly. Xorg 7.3 was finally released earlier this month. Unfortunately I was too busy to install it (i wanted to update other gentoo packages before I did this). Finally this weekend, I managed to upgrade my system (emerge -avuDN world) and get xorg 7.3 working!

Before I get to the monitor plugging, I'd like to make few comments on my experience doing this on Gentoo. First off, after emerging X org 7.3, X didn't start at all! Turned out that the upgrade process didn't recompile some dependency packages because their version hadn't changed. These are pretty much Gentoo specific issues and your not going to have to worry about it on binary based distros.

The other problem I had was with my synaptic touch pad not working. While trying to figure that out, I remembered that xorg 7.3 is supposed to have INPUT hotplugging and work even without an xorg.conf configuration file. So I renamed /etc/X11/xorg.conf and restarted zapped X (Ctrl+Alt+BS), and everything worked beautifully -- sort of. The synaptic touchpad worked and everything seemed fine, except I was having problems with compiz-fusion, the 3D stuff. I could get the 3D cube to rotate and see the wobbly effect but was unable to see what I was typing in the terminal. I could also not see any icons on certain windows such as of ccsm. It took me about an hour to figure out this was actually a problem with using an auto detected xorg.conf. So in the end, I reverted back to the old xorg.conf and found how to get synaptic working on it (thanks to google of course). Here is how my synaptic configuration on xorg.conf now looks like:

Section "ServerLayout"
Identifier " Configured"
Screen 0 "Screen0" 0 0

#InputDevice "TouchPad" "AlwaysCore" # Old setting
#InputDevice "Mouse0" "CorePointer" # Old setting
InputDevice "TouchPad" "CorePointer" # New for xorg 7.3
InputDevice "Mouse0" "SendCoreEvents"

InputDevice "Keyboard0" "CoreKeyboard"
Option "AIGLX" "true"

Section "InputDevice"
Driver "synaptics"
Identifier "TouchPad"
Option "SendCoreEvents"
Option "Protocol" "auto-dev"
Option "SHMConfig" "on"

Anyway, so now for the good stuff! I plugged in my 17" monitor to the VGA out of the notebook and waited. The signal not detected sign went away and the screen was pitch black. It was on indefinitely on standby. I zapped X again to restart it and this time got a display on the monitor. Hmmm not the hotplug I had in mind. A bit disappointed I wanted to get to the bottom of this - I mean hotplugging was supposed to be the main feature.

Turns out you can turn on a secondary display without restarting (zapping) X and here is how:

Meet the updated version of xrandr. You should have xrandr 1.2 for this to work.

# xrandr -v
Server reports RandR version 1.2

To get a list of displays available along with its status issue:

# xrandr -q
Screen 0: minimum 320 x 200, current 1280 x 800, maximum 2432 x 864
VGA connected (normal left inverted right x axis y axis)
1152x864 74.8
1024x768 84.9 75.1 70.1 60.0
832x624 74.6
800x600 99.7 84.9 72.2 75.0 60.3
640x480 99.8 84.6 75.0 72.8 60.0
720x400 70.1
640x350 70.1
LVDS connected 1280x800+0+0 (normal left inverted right x axis y axis) 331mm x 207mm
1280x800 60.0*+
1024x768 60.0
800x600 60.3
640x480 59.9
TV disconnected (normal left inverted right x axis y axis)

The output of xrandr -q shows two devices, VGA which represents my VGA out and is also shown to be connected to the monitor and LVDS, my LCD display. A third TV out is shown but is unfortunately not physically available on my notebook model :(

To enable my VGA out display and show an exact copy of whats on my LCD:

xrandr --output VGA --auto

This should automatically pick out the preferred resolution for the monitor and enable it. Alternatively if you want to specify the resolution from one of the modes supported (as given by xrandr -q):

xrandr --output VGA --mode 1024x768

You can turn off the external display by issuing

xrandr --output VGA --off

If you want you can create a VGA out toggle script and assign it to a keyboard short cut.

# vi ~/
XRANDR_OUT=`xrandr -q`
if echo "$XRANDR_OUT"|grep -q 'VGA connected'; then
echo 'Detected VGA connected';
if [ `echo "$XRANDR_OUT"|grep '*'|wc -l` -gt 1 ];then
echo 'Turning off VGA';
xrandr --output VGA --off
echo 'Turning on VGA';
xrandr --output VGA --auto
echo 'No VGA connected!';

Ok now for some fun stuff with xrandr! RandR was built to rotate the screen so lets try a rotation on the second screen:

# xrandr --output VGA --rotate left
# xrandr --output VGA --rotate right
# xrandr --output VGA --rotate normal

That last line will restore all rotations. Feeling dizzy? If not try these cool tricks:

# xrandr --output VGA --reflect x
# xrandr --output VGA --reflect y
# xrandr --output VGA --reflect xy
# xrandr --output VGA --reflect normal

Finally, wouldn't it be nice to extend your desktop to two displays. Well its now possible without having special dual head monitor settings in xorg.conf and even on an intel card! (with two vga outs of course).

There is a catch - you need to predefine the maximum combined resolution so that X server will pre-allocate that memory. Currently on intel cards, this means not enough memory for AIGLX/Compiz /3D. So I recommend creating a separate xorg.conf file for this purpose.

# vi /etc/xorg.conf
Section "Screen"
Identifier "Screen0"
Monitor "Monitor0"
Device "Card0"
DefaultDepth 24

SubSection "Display"
Viewport 0 0
Depth 24
Virtual 2432 864

# xrandr --output VGA --left-of LVDS

xrandr dual head
Depending on your monitor being to the left, right, above or below of your LCD screen you should use the proper option (see man xrandr).

Thats it for now.