Dynamic multi-headed Ubuntu laptop with NVIDIA
I've run Ubuntu desktop on a Thinkpad t61 for a number of years and moved on to a w520 maybe a year ago. I wanted to be able to support multiple monitors and change them out on the fly without a reboot. I also wanted a solution that would work with xmonad. While reading about Xorg and Nvidia I found the number of dead ends to be extremely frustrating. There is a ton of advice. Much of it is dated. Much of it is just plain wrong. My advice as of the date above is to use the "nvidia" driver with TwinView. This works for me today.
I'd highly suggest reading the Nvidia Manual before searching any further on the web for answers.
Figuring out what you have
$ dpkg -l | grep nvidia
ii nvidia-common 0.2.30.1 Find obsolete NVIDIA drivers
ii nvidia-current 270.41.06-0ubuntu1.1 NVIDIA binary Xorg driver, kernel module and VDPAU library
ii nvidia-settings 270.29-0ubuntu1 Tool of configuring the NVIDIA graphics driver
$ sudo lshw -c video
*-display
...
configuration: driver=nvidia latency=0
...
$ jockey-text -l
xorg:nvidia_current - NVIDIA accelerated graphics driver (Proprietary, Enabled, Not in use)
If you are not seeing similar results, you are probably running the nv or nouveau driver. See system > administration > additional drivers.
Behold the elusive dynamic xorg.conf!
You should use nvidia-settings to generate an xorg.conf that will work as a correct starting point. Ensure that you write it to disk. Have every monitor you plan to use plugged in before you generate it.
Then look below at the screen/metamodes line. It says I'm either going to have the default monitor to the left with a secondary monitor starting 1920 pixels to the right, or I'm going to have the default monitor and nothing else. Shuffling this around correctly should yield predictable results. I then use a script (see below) to alternate between them.
Option "metamodes" "DFP-0: nvidia-auto-select +0+0, DFP-1: nvidia-auto-select +1920+0; DFP-0: nvidia-auto-select +0+0, DFP-1: null"
$ sudo vi /etc/X11/xorg.conf
Section "Device"
Identifier "Default Device"
Option "NoLogo" "True"
EndSection
# nvidia-settings: X configuration file generated by nvidia-settings
# nvidia-settings: version 270.29 (buildd@allspice) Sat Feb 26 14:42:07 UTC 2011
Section "ServerLayout"
Identifier "Layout0"
Screen 0 "Screen0" 0 0
InputDevice "Keyboard0" "CoreKeyboard"
InputDevice "Mouse0" "CorePointer"
Option "Xinerama" "0"
EndSection
Section "Files"
EndSection
Section "InputDevice"
# generated from default
Identifier "Mouse0"
Driver "mouse"
Option "Protocol" "auto"
Option "Device" "/dev/psaux"
Option "Emulate3Buttons" "no"
Option "ZAxisMapping" "4 5"
EndSection
Section "InputDevice"
# generated from default
Identifier "Keyboard0"
Driver "kbd"
EndSection
Section "Monitor"
# HorizSync source: edid, VertRefresh source: edid
Identifier "Monitor0"
VendorName "Unknown"
ModelName "LEN"
HorizSync 56.5 - 67.8
VertRefresh 40.0 - 60.0
Option "DPMS"
EndSection
Section "Device"
Identifier "Device0"
Driver "nvidia"
VendorName "NVIDIA Corporation"
BoardName "Quadro 1000M"
Option "RegistryDwords" "EnableBrightnessControl=1"
EndSection
Section "Screen"
Identifier "Screen0"
Device "Device0"
Monitor "Monitor0"
DefaultDepth 24
Option "TwinView" "1"
Option "metamodes" "DFP-0: nvidia-auto-select +0+0, DFP-1: nvidia-auto-select +1920+0; DFP-0: nvidia-auto-select +0+0, DFP-1: null"
SubSection "Display"
Depth 24
EndSubSection
EndSection
Making it dynamic
Switching from separate monitors to the default only is not handled in this setup; although, it could be done. Instead, just use the display and kbd scripts to make the switch. In my setup I'm using the apple keyboad with the separate monitor. The super key needs to be swapped as well for this setup, which is what the kbd script does. If you don't use an apple keyboard, remove that part.
display.rb
1 def current_size
2 data = `xrandr -q 2> /dev/null`
3 data.match(/current (\d{1,4} x \d{1,4}),/)[1]
4 end
5
6 def multihead?
7 current_size == '3840 x 1080'
8 end
9
10 def standalone?
11 current_size == '1920 x 1080'
12 end
13
14 if multihead?
15 `xrandr -s 1`
16 `kbd pc`
17 else
18 `xrandr -s 0`
19 `kbd apple`
20 end
kbd.rb
UPDATE 6/22/12: This will not work under unity 2d. See Unity 2D Keyboard Configuration with setxkbmap
1 KEY = "/desktop/gnome/peripherals/keyboard/kbd/options"
2 APPLE = "[grp\tgrp:shift_caps_toggle,altwin\taltwin:swap_lalt_lwin]"
3 PC = "[grp\tgrp:shift_caps_toggle]"
4
5 val = case ARGV[0]
6 when 'apple'
7 APPLE
8 when 'pc'
9 PC
10 else
11 current = `gconftool-2 --get #{KEY}`
12 current =~ /lalt_lwin/ ? PC : APPLE
13 end
14
15 `gconftool-2 --type=list --list-type=string --set #{KEY} "#{val}"`
Bonus info for synaptics mouse
sudo vi /usr/share/X11/xorg.conf.d/20-thinkpad.conf
Section "InputClass"
Identifier "Trackpoint Wheel Emulation"
MatchProduct "TPPS/2 IBM TrackPoint|DualPoint Stick|Synaptics Inc. Composite TouchPad / TrackPoint|ThinkPad USB Keyboard with TrackPoint"
MatchDevicePath "/dev/input/event*"
Option "EmulateWheel" "true"
Option "EmulateWheelButton" "2"
Option "Emulate3Buttons" "false"
Option "XAxisMapping" "6 7"
Option "YAxisMapping" "4 5"
Option "ButtonMapping" "1 1 3 4 5"
EndSection