Difference between revisions of "Sample Fn-F7 script"
Ordonnateur (Talk | contribs) (additional scripts) |
|||
Line 2: | Line 2: | ||
Works like a charm on X61s with Xubuntu 7.10. | Works like a charm on X61s with Xubuntu 7.10. | ||
+ | Working with R60e with some modifications noted below. | ||
+ | ==configuring the virtual screen size== | ||
Add a "Virtual" statement to your /etc/X11/xorg.conf, the total resolution should be large enough to fit all your screens in the configuration you want, for example if you have 1600x1200 monitor to the left of your internal 1024x768 monitor, your total max resolution is 2624x1200 (See [[Xorg RandR 1.2]] for more details): | Add a "Virtual" statement to your /etc/X11/xorg.conf, the total resolution should be large enough to fit all your screens in the configuration you want, for example if you have 1600x1200 monitor to the left of your internal 1024x768 monitor, your total max resolution is 2624x1200 (See [[Xorg RandR 1.2]] for more details): | ||
Line 9: | Line 11: | ||
Device "Videocard0" | Device "Videocard0" | ||
DefaultDepth 24 | DefaultDepth 24 | ||
− | + | SubSection "Display" | |
Viewport 0 0 | Viewport 0 0 | ||
Depth 24 | Depth 24 | ||
Line 18: | Line 20: | ||
Restart X server at this point (i.e. logout and login). | Restart X server at this point (i.e. logout and login). | ||
+ | == configuring acpi == | ||
Create /etc/acpi/events/thinkpad.conf: | Create /etc/acpi/events/thinkpad.conf: | ||
Line 23: | Line 26: | ||
action=/usr/local/sbin/thinkpad-fn-f7 | action=/usr/local/sbin/thinkpad-fn-f7 | ||
+ | or you may (eg Ubuntu 7.10) already have /etc/acpi/ibm-videobtn | ||
+ | # /etc/acpi/events/ibmvideobtn | ||
+ | # This is called when the user presses the video button. It is currently | ||
+ | # a placeholder. | ||
+ | in which case modify the line 'action=/bin/true' to run the script as above. | ||
+ | It may also be necessary to enable acpi events as per [[How to get special keys to work]] with | ||
+ | $echo enable,0xffff > /proc/acpi/ibm/hotkey | ||
+ | |||
+ | ==identify output devices== | ||
Note the names of your output devices as you will have to change EXTERNAL_OUTPUT and INTERNAL_OUTPUT to what xrandr shows, for example VGA and LVDS in this case: | Note the names of your output devices as you will have to change EXTERNAL_OUTPUT and INTERNAL_OUTPUT to what xrandr shows, for example VGA and LVDS in this case: | ||
− | $ xrandr | + | $ xrandr -q |
'''VGA''' connected 1600x1200+0+0 (normal left inverted right x axis y axis) 432mm x 324mm | '''VGA''' connected 1600x1200+0+0 (normal left inverted right x axis y axis) 432mm x 324mm | ||
+ | ... | ||
'''LVDS''' connected (normal left inverted right x axis y axis) | '''LVDS''' connected (normal left inverted right x axis y axis) | ||
+ | ==The bash script== | ||
Create /usr/local/sbin/thinkpad-fn-f7, you can set EXTERNAL_LOCATION to one of: left, right, above, or below. | Create /usr/local/sbin/thinkpad-fn-f7, you can set EXTERNAL_LOCATION to one of: left, right, above, or below. | ||
Line 168: | Line 182: | ||
esac | esac | ||
− | + | == set permissions and restart acpi == | |
As root, run the following commands, | As root, run the following commands, | ||
Line 175: | Line 189: | ||
You should be ready to go, just press Fn-F7 to try. | You should be ready to go, just press Fn-F7 to try. | ||
+ | |||
+ | ==Alternative script using .Xauthority rather than su == | ||
+ | Use this script as an alternative | ||
+ | action=/usr/local/sbin/toggle-display.sh | ||
+ | for /etc/acpi/events/ibm-videobtn | ||
+ | |||
+ | #!/bin/bash | ||
+ | |||
+ | # usr/local/sbin/toggle-display.sh | ||
+ | # thinkwiki(a)djclark.co.uk 2007-11-23 | ||
+ | # based on /etc/acpi/screenblank.sh (Ubuntu 7.10) | ||
+ | |||
+ | # . /usr/share/acpi-support/power-funcs # for getXuser | ||
+ | umask 022; | ||
+ | |||
+ | PATH="$PATH:/usr/bin/X11" | ||
+ | |||
+ | 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 | ||
+ | } | ||
+ | # end of getXuser from /usr/share/acpi-support/power-funcs | ||
+ | |||
+ | for x in /tmp/.X11-unix/*; do | ||
+ | displaynum=`echo $x | sed s#/tmp/.X11-unix/X##` | ||
+ | getXuser; | ||
+ | if [ x"$XAUTHORITY" != x"" ]; then | ||
+ | export DISPLAY=":$displaynum" | ||
+ | # . /usr/share/acpi-support/screenblank.sh | ||
+ | /usr/local/bin/toggle.py | ||
+ | |||
+ | fi | ||
+ | done | ||
+ | |||
+ | Each user has an ~/.Xauthority file with one line for each X display containing a 'magic cookie' (Run "xauth list" to see the contents). The Xserver reads the record in ~/.Xauthority matching its display. When an X client application starts it also looks for that record and passes the magic cookie to the server. If it matches, the connection to the Xserver is allowed. The above example runs the python script below but could run a modified version of /usr/local/sbin/thinkpad-fn-f7 without the USER, and DISPLAY detection SU commands. | ||
+ | |||
+ | == A Python Toggle script == | ||
+ | This is a somewhat over-elaborate script which could be cut down when run by the /usr/local/sbin/toggle-display.sh script above. It was written to explore all the possibilities rather than economy of execution. The appropriate outputs can be specified on the command line and it is not necessary to call it via acpi. |
Revision as of 02:15, 24 November 2007
This guide will help you configure Fn-F7 key combination to toggle between internal, mirror, external, or both screens. This was tested on ThinkPad X60s running Fedora 8, please comment if it works or does not work for you.
Works like a charm on X61s with Xubuntu 7.10. Working with R60e with some modifications noted below.
Contents
configuring the virtual screen size
Add a "Virtual" statement to your /etc/X11/xorg.conf, the total resolution should be large enough to fit all your screens in the configuration you want, for example if you have 1600x1200 monitor to the left of your internal 1024x768 monitor, your total max resolution is 2624x1200 (See Xorg RandR 1.2 for more details):
Section "Screen" Identifier "Screen0" Device "Videocard0" DefaultDepth 24 SubSection "Display" Viewport 0 0 Depth 24 Virtual 2624 1200 EndSubSection EndSection
Restart X server at this point (i.e. logout and login).
configuring acpi
Create /etc/acpi/events/thinkpad.conf:
event=ibm/hotkey HKEY 00000080 00001007 action=/usr/local/sbin/thinkpad-fn-f7
or you may (eg Ubuntu 7.10) already have /etc/acpi/ibm-videobtn
# /etc/acpi/events/ibmvideobtn # This is called when the user presses the video button. It is currently # a placeholder.
in which case modify the line 'action=/bin/true' to run the script as above. It may also be necessary to enable acpi events as per How to get special keys to work with
$echo enable,0xffff > /proc/acpi/ibm/hotkey
identify output devices
Note the names of your output devices as you will have to change EXTERNAL_OUTPUT and INTERNAL_OUTPUT to what xrandr shows, for example VGA and LVDS in this case:
$ xrandr -q VGA connected 1600x1200+0+0 (normal left inverted right x axis y axis) 432mm x 324mm ... LVDS connected (normal left inverted right x axis y axis)
The bash script
Create /usr/local/sbin/thinkpad-fn-f7, you can set EXTERNAL_LOCATION to one of: left, right, above, or below.
#!/bin/bash # External output may be "VGA" or "VGA-0" or "DVI-0" EXTERNAL_OUTPUT="VGA" INTERNAL_OUTPUT="LVDS" EXTERNAL_LOCATION="left" # Figure out which user and X11 display to work on # TODO there has to be a better way to do this? X_USER=$(w -h -s | grep ":[0-9]" | head -1 | awk '{print $1}') export DISPLAY=$(w -h -s | grep ":[0-9]" | head -1 | awk '{print $3}') # Switch to X user if necessary if [ "$X_USER" != "$USER" ]; then SU="su $X_USER -c" fi case "$EXTERNAL_LOCATION" in left|LEFT) EXTERNAL_LOCATION="--left-of $INTERNAL_OUTPUT" ;; right|RIGHT) EXTERNAL_LOCATION="--right-of $INTERNAL_OUTPUT" ;; top|TOP|above|ABOVE) EXTERNAL_LOCATION="--above $INTERNAL_OUTPUT" ;; bottom|BOTTOM|below|BELOW) EXTERNAL_LOCATION="--below $INTERNAL_OUTPUT" ;; *) EXTERNAL_LOCATION="--left-of $INTERNAL_OUTPUT" ;; esac # Figure out current state INTERNAL_STATE=$($SU xrandr | grep ^$INTERNAL_OUTPUT | grep con | sed "s/.*connected //" | sed "s/(.*//") EXTERNAL_STATE=$($SU xrandr | grep ^$EXTERNAL_OUTPUT | grep con | sed "s/.*connected //" | sed "s/(.*//") if [ -z "$INTERNAL_STATE" ]; then STATE="external" elif [ -z "$EXTERNAL_STATE" ]; then STATE="internal" else INTERNAL_STATE=$(echo $INTERNAL_STATE | sed "s/[0-9]*x[0-9]*//") EXTERNAL_STATE=$(echo $EXTERNAL_STATE | sed "s/[0-9]*x[0-9]*//") if [ "$INTERNAL_STATE" = "$EXTERNAL_STATE" ]; then STATE="mirror" else STATE="both" fi fi function screen_external(){ $SU "xrandr --output $INTERNAL_OUTPUT --off" $SU "xrandr --output $EXTERNAL_OUTPUT --auto" } function screen_internal(){ $SU "xrandr --output $EXTERNAL_OUTPUT --off" $SU "xrandr --output $INTERNAL_OUTPUT --auto" } function screen_mirror(){ $SU "xrandr --output $INTERNAL_OUTPUT --auto" $SU "xrandr --output $EXTERNAL_OUTPUT --auto --same-as $INTERNAL_OUTPUT" } function screen_both(){ $SU "xrandr --output $INTERNAL_OUTPUT --auto" $SU "xrandr --output $EXTERNAL_OUTPUT --auto $EXTERNAL_LOCATION" } function screen_toggle(){ case "$STATE" in internal) screen_mirror ;; mirror) screen_external ;; external) screen_both ;; both) screen_internal ;; *) screen_internal ;; esac } # What should we do? DO="$1" if [ -z "$DO" ]; then if [ $(basename $0) = "thinkpad-fn-f7" ]; then DO="toggle" fi fi case "$DO" in toggle) screen_toggle ;; internal) screen_internal ;; external) screen_external ;; mirror) screen_mirror ;; both) screen_both ;; status) echo "Current Fn-F7 state is: $STATE" echo echo "Attached monitors:" $SU xrandr | grep "\Wconnected" | sed "s/^/ /" ;; *) echo "usage: $0 <command>" >&2 echo >&2 echo " commands:" >&2 echo " status" >&2 echo " internal" >&2 echo " external" >&2 echo " mirror" >&2 echo " both" >&2 echo " toggle" >&2 echo >&2 ;; esac
set permissions and restart acpi
As root, run the following commands,
# chmod 755 /usr/local/sbin/thinkpad-fn-f7
# service acpid restart
You should be ready to go, just press Fn-F7 to try.
Alternative script using .Xauthority rather than su
Use this script as an alternative
action=/usr/local/sbin/toggle-display.sh
for /etc/acpi/events/ibm-videobtn
#!/bin/bash
# usr/local/sbin/toggle-display.sh # thinkwiki(a)djclark.co.uk 2007-11-23 # based on /etc/acpi/screenblank.sh (Ubuntu 7.10)
# . /usr/share/acpi-support/power-funcs # for getXuser umask 022;
PATH="$PATH:/usr/bin/X11"
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 } # end of getXuser from /usr/share/acpi-support/power-funcs
for x in /tmp/.X11-unix/*; do displaynum=`echo $x | sed s#/tmp/.X11-unix/X##` getXuser; if [ x"$XAUTHORITY" != x"" ]; then export DISPLAY=":$displaynum"
- . /usr/share/acpi-support/screenblank.sh
/usr/local/bin/toggle.py
fi
done
Each user has an ~/.Xauthority file with one line for each X display containing a 'magic cookie' (Run "xauth list" to see the contents). The Xserver reads the record in ~/.Xauthority matching its display. When an X client application starts it also looks for that record and passes the magic cookie to the server. If it matches, the connection to the Xserver is allowed. The above example runs the python script below but could run a modified version of /usr/local/sbin/thinkpad-fn-f7 without the USER, and DISPLAY detection SU commands.
A Python Toggle script
This is a somewhat over-elaborate script which could be cut down when run by the /usr/local/sbin/toggle-display.sh script above. It was written to explore all the possibilities rather than economy of execution. The appropriate outputs can be specified on the command line and it is not necessary to call it via acpi.