Skip to content

Instantly share code, notes, and snippets.

Last active March 20, 2023 10:42
Show Gist options
  • Save seanf/e3be5bf745395d50e975 to your computer and use it in GitHub Desktop.
Save seanf/e3be5bf745395d50e975 to your computer and use it in GitHub Desktop.
Example ThinkPad docking script for multi-monitor
# Save this file (after modifying ID_VENDOR and ID_MODEL if necessary) as /etc/udev/rules.d/81-thinkpad-dock.rules
# These values seem to work for "ThinkPad Mini Dock Plus Series 3"
SUBSYSTEM=="usb", ACTION=="add|remove", ENV{ID_VENDOR}=="17ef", ENV{ID_MODEL}=="100a", RUN+="/etc/sbin/"

Example ThinkPad docking script for multi-monitor

You will probably need to modify these files to suit your multi-monitor layout, your username and your dock model. Tested on Fedora 20 with a series 3 ThinkPad Dock.

Warning: this can and will mess up your display if anything goes wrong.

  1. First, unless you have a ThinkPad Mini Dock Plus Series 3, you need to find the udev identity of your dock, so that we can detect when it is added or removed.

Run this command:

udevadm monitor --environment --udev

Then disconnect the hub, wait a second for the events to be logged, press enter several times (on the laptop keyboard) to put a gap after the events, then reconnect the hub.

Make a note of the last usb device to be removed in the log (just before the gap), for instance:

UDEV  [62731.120389] remove   /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.8 (usb)
ID_MODEL_FROM_DATABASE=ThinkPad Mini Dock Plus Series 3

The same device should be among the first to be added again:

UDEV  [62736.651278] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.8 (usb)
ID_MODEL_FROM_DATABASE=ThinkPad Mini Dock Plus Series 3

Hit Control-C to stop monitoring.

Make sure the values ID_MODEL and ID_VENDOR are shown both for add and remove. We will use these to construct a udev rule. If you try to use a value which isn't there when removing, your rule won't activate for remove events.

If ID_MODEL and ID_VENDOR don't look like hex numbers, you might want to try ID_MODEL_ID and ID_VENDOR_ID.

  1. If you have a ThinkPad Mini Dock Plus Series 3, your values should match the ones above, and you can use this rule as is, otherwise you should adjust ID_MODEL and ID_VENDOR to match your results (or perhaps use ID_MODEL_ID and ID_VENDOR_ID):

Save the file 81-thinkpad-dock.rules (modified if necessary) as /etc/udev/rules.d/81-thinkpad-dock.rules.

  1. Modify the username and the xrandr commands in as appropriate, and save as /etc/sbin/ Make sure it is executable: chmod 755 /etc/sbin/

  2. Try docking and undocking your laptop. If nothing happens, you might have a problem with Xauthority (check the username), or you might be using the wrong rules file for your hardware IDs. If something happens, but you don't get the screen layout you want, check the documentation for xrandr with man xrandr.

You can test the script without physically undocking by running these commands as root:


ACTION=add sbin/


ACTION=remove sbin/

A couple of extra notes:

journalctl -f | grep DOCKING will let you see the script's logging messages as they happen.

If you make a note of the device name returned by udevadm monitor when docking/undocking, you can see what will happen when the udev event is triggered by running commands similar to these:

udevadm test --action=add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.8
udevadm test --action=remove /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.8
#!/bin/sh -e
# Save this file as /etc/sbin/
# NB: you will need to modify the username and tweak the xrandr
# commands to suit your setup.
# wait for the dock state to change
sleep 0.5
#export IFS=$"\n"
if [[ "$ACTION" == "add" ]]; then
logger -t DOCKING "Detected condition: docked"
elif [[ "$ACTION" == "remove" ]]; then
logger -t DOCKING "Detected condition: un-docked"
logger -t DOCKING "Detected condition: unknown"
echo Please set env var \$ACTION to 'add' or 'remove'
exit 1
# invoke from XSetup with NO_KDM_REBOOT otherwise you'll end up in a KDM reboot loop
for p in $*; do
case "$p" in
function switch_to_local {
export DISPLAY=$1
#export XAUTHORITY=$(find /var/run/kdm -name "A${DISPLAY}-*")
#export XAUTHORITY=/var/run/lightdm/sflaniga/xauthority
logger -t DOCKING "Switching off HDMI2/3 and switching on LVDS1"
su $username -c '
/usr/bin/xrandr \
--output HDMI1 --off \
--output HDMI2 --off \
--output HDMI3 --off \
--output VGA1 --off \
--output eDP1 --auto \
--output LVDS1 --auto \
function switch_to_external {
export DISPLAY=$1
#export XAUTHORITY=/var/run/lightdm/sflaniga/xauthority
#export XAUTHORITY=$(find /var/run/kdm -name "A${DISPLAY}-*")
# The Display port on the docking station is on HDMI2 - let's use it and turn off local display
logger -t DOCKING "Switching off LVDS1 and switching on HDMI2/3"
su $username -c '
/usr/bin/xrandr \
--output eDP1 --off \
--output LVDS1 --off \
--output HDMI1 --auto \
--output HDMI2 --auto --pos 1680x0 --rotate left \
--output HDMI3 --auto --pos 0x600 --primary \
--output VGA1 --auto \
# alternative:
# xrandr --output LVDS1 --off --output HDMI3 --primary --auto --pos 0x0
# --output HDMI2 --auto --rotate left --pos 1680x-600
# this will probably fail ("Configure crtc 2 failed"):
#/usr/bin/xrandr --output LVDS1 --auto
case "$DOCKED" in
#undocked event
switch_to_local :0 ;;
#docked event
switch_to_external :0 ;;
Copy link

JosefLitos commented Oct 26, 2020

Hello, I have a problem I seem unable to solve.
I get stuck on the first command, where I get no input or output, simply nothing happens.
The monitor is plugged into my thinkpad w530 workstation and working fine when in Windows, but on arch I seems undetected.

I found out, that when I log on to tty2 on arch, the display turns all white, but nothing else, still not recognized, but when I logout, the display stays white until i power off.

Copy link

vKnmnn commented Sep 9, 2021

Hi, you have given sh in the shebang, but you’re using bash syntax in the script.
Thus, the following edits have to be made so we can run the script with posix shell:

line 15 and 18: use single [ and ]. Also only use a single =
line 36 and 52, keyword function is not defined in posix shell. just delete the word function, but add () behind the function name.
line 41 and 49 use double quotes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment