Script for Dynamic Display Management with fglrx
The proprietary fglrx driver from ATI allows dynamic display switching, e.g. to switch to an external display for a presentation. Xorg RandR 1.2 allows the same, but sometimes the newer version is not available, or not compatible e.g. when the proprietary ATI driver needs to be used for some reasons. The current version of it does not support the dynamic switching capabilities of XRandR 1.2.
In these cases, the following switching script provides the same functionality, which you can bind to a keypress such as Fn-F7. The script uses ATI's aticonfig tool for switching, XRandR for resolution adjustment, and Xosd for displaying OSD status messages. Thus, it should work on most Linux-running laptops whith ATI graphics cards (tested with Ubuntu 7.04 and Ubuntu 7.10 on a Thinkpad T43). When an external display is connected, the script switches from internal to both internal and extarnal, then to external only, and finally back to internal display only.
Contents
The Script
<bash>
- !/bin/bash
- Script to switch displays, e.g. by pressing Fn-F7 on Thinkpad Laptops.
- Uses aticonfig from the ATI fglrx driver for dynamic switching, and
- xrandr for resolution changing. OSD done with xosd.sh, which uses
- osd_cat from Xosd.
- Author: Armin Hornung -- www.arminhornung.de
- Date: 2008-05-01
- Partly based on a display switching script from SuSE 10.1
- path to xosd.sh, change to "echo" if not installed
xosd="/usr/local/bin/xosd.sh"
- path to xrandr
xrandr="/usr/bin/xrandr"
INTERNAL="lvds" # internal LCD of Laptop EXTERNAL="crt1" # external monitor, CRT or TFT
- Determine X user, script usually runs as root:
getXuser() {
user=`finger| grep -m1 ":$displaynum " | awk '{print $1}'`
if [ x"$user" = x"" ]; then user=`finger| grep -m1 ":$displaynum" | awk '{print $1}'` fi if [ x"$user" != x"" ]; then userhome=`getent passwd $user | cut -d: -f6` export XAUTHORITY=$userhome/.Xauthority else export XAUTHORITY="" fi
}
for x in /tmp/.X11-unix/*; do
displaynum=`echo $x | sed s#/tmp/.X11-unix/X##` getXuser if [ x"$XAUTHORITY" != x"" ]; then # extract current state
export DISPLAY=":$displaynum" _enabled_monitors=`su $user -c "aticonfig --query-monitor | grep Enabled"` _connected_monitors=`su $user -c "aticonfig --query-monitor | grep Connected"`
fi
done
- determine if internal is active
echo "${_enabled_monitors}" | grep $INTERNAL > /dev/null 2>&1 if [ $? -eq 0 ]; then
_internal_enabled=yes
else
_internal_enabled=no
fi
- determine if external is connected
- (LVDS always assumed to be connected)
echo "${_connected_monitors}" | grep $EXTERNAL > /dev/null 2>&1 if [ $? -eq 0 ]; then
_external_connected=yes
else
_external_connected=no
fi
- determine if external is active
_external_enabled=no echo "${_enabled_monitors}" | grep $EXTERNAL > /dev/null 2>&1 if [ $? -eq 0 ]; then
_external_enabled=yes
fi
- display switching part ####
if [ "${_internal_enabled}" = "yes" ]; then
if [ "${_external_connected}" = "yes" ]; then if [ "${_external_enabled}" = "yes" ]; then # switch to external only, after both enabled: $xosd "Enabling $EXTERNAL" & su $user -c "aticonfig --enable-monitor $EXTERNAL" # adjust resolution back to standard: $xrandr -s 1280x1024 -r 60 else # switch to both enabled, after external only $xosd "Enabling $INTERNAL & $EXTERNAL" & su $user -c "aticonfig --enable-monitor $INTERNAL,$EXTERNAL" # adjust resolution: $xrandr -s 1280x1024 -r 60 fi else $xosd "No external display connected" & if [ "${_external_enabled}" = "yes" ]; then # switch back just if external display got disconnected su $user -c "aticonfig --enable-monitor $INTERNAL" $xrandr -s 1400x1050 -r 60 fi fi
else
# switch back to internal only, after external enabled: $xosd "Enabling $INTERNAL" & su $user -c "aticonfig --enable-monitor $INTERNAL" # adjust resolution back to standard: $xrandr -s 1400x1050 -r 60
fi
exit 0 </bash>
OSD
Using the helper script below, Xosd can be used for displaying status messages.
/usr/local/bin/xosd.sh: <bash>
- !/bin/bash
- 2006-03-09 <pille@struction.de>
- displays text in arguments on X screen using osd_cat (in some nicely preconfigured style)
OSD_CAT=`which osd_cat` XOSD="${OSD_CAT} --delay=2 --age=0 --lines=2 --pos=bottom --align=center --font=-adobe-helvetica-bold-r-normal-*-*-180-*-*-p-*-*-* --colour=green --shadow=1 --offset=25 --indent=25"
- get user running X display (needed when run by script)
- XUSER=`ps -C Xsession -o user h`
XUSER="armin"
if [ "${USER}" == "${XUSER}" ]; then
echo $@ | ${XOSD}
else
echo $@ |su ${XUSER} -c "DISPLAY=${DISPLAY:-:0.0} ${XOSD}"
fi </bash>
Installation
Place the switching script at /etc/acpi/ati-toggle.sh and create /usr/local/bin/xosd.sh. Finally, the script needs to be bound to the key Fn-F7 by creating or editing /etc/acpi/events/ibm-videobtn to: <bash>
- /etc/acpi/events/ibm-videobtn
- This is called when the user presses the video button.
event=ibm/hotkey HKEY 00000080 00001007 action=/etc/acpi/ati-toggle.sh </bash>
References
http://www.arminhornung.de - Source, has scripts available for download Sample Fn-F7 script - A similar script using XRandR 1.2 for switching