Difference between revisions of "Talk:Sample Fn-F7 script"
(22 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
+ | ---- | ||
+ | =X40 + Ubuntu 8.10= | ||
+ | I'm using an IBM ThinkPad X40 w/ Ubuntu 8.10. | ||
+ | I edited the .Xauthority bash script slightly because it wasn't working for me. I simplified it to just switch from one monitor to the other. It switches the display fine; however, the buttons to open programs in the panel get messed up. Right now, the rightmost four slide all the way to the right of the panel, and the rest (3) stay where they were originally. Is anyone else experiencing this? If you're going to test it out, make sure you have at least 7 buttons. Here is the script I'm using to switch screens: | ||
+ | |||
+ | #!/bin/bash | ||
+ | # From: http://www.thinkwiki.org/wiki/Sample_Fn-F7_script | ||
+ | # | ||
+ | # External output may be "VGA" or "VGA-0" or "DVI-0" or "TMDS-1" | ||
+ | EXTERNAL_OUTPUT="VGA" | ||
+ | INTERNAL_OUTPUT="LVDS" | ||
+ | |||
+ | function screen_external(){ | ||
+ | xrandr --output $INTERNAL_OUTPUT --off | ||
+ | xrandr --output $EXTERNAL_OUTPUT --auto | ||
+ | } | ||
+ | |||
+ | function screen_internal(){ | ||
+ | xrandr --output $EXTERNAL_OUTPUT --off | ||
+ | xrandr --output $INTERNAL_OUTPUT --auto | ||
+ | } | ||
+ | |||
+ | function screen_toggle(){ | ||
+ | # Figure out current state | ||
+ | INTERNAL_STATE=$(xrandr | grep ^$INTERNAL_OUTPUT | grep con | sed "s/.*connected //" | sed "s/(.*//") | ||
+ | EXTERNAL_STATE=$(xrandr | grep ^$EXTERNAL_OUTPUT | grep con | sed "s/.*connected //" | sed "s/(.*//") | ||
+ | |||
+ | if [ -z "$INTERNAL_STATE" ]; then | ||
+ | STATE="external" | ||
+ | else | ||
+ | STATE="internal" | ||
+ | fi | ||
+ | |||
+ | case "$STATE" in | ||
+ | internal) | ||
+ | screen_external | ||
+ | ;; | ||
+ | external) | ||
+ | screen_internal | ||
+ | ;; | ||
+ | *) | ||
+ | screen_internal | ||
+ | ;; | ||
+ | esac | ||
+ | } | ||
+ | |||
+ | # based on /etc/acpi/screenblank.sh (Ubuntu 7.10) | ||
+ | # . /usr/share/acpi-support/power-funcs # for getXuser | ||
+ | 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" | ||
+ | screen_toggle | ||
+ | fi | ||
+ | done | ||
+ | ---- | ||
+ | =R50e + Fedora 9= | ||
+ | Using Fedora 9 on a Thinkpad R50e, and works like a charm for me - only had to do one modification: | ||
+ | If the environment is such that X_USER equals USER, then the version with citation marks - like in | ||
+ | |||
+ | $SU "xrandr --output $INTERNAL_OUTPUT --off" | ||
+ | |||
+ | does not work, bash would complain that the command was not found. | ||
+ | It would then have to be | ||
+ | |||
+ | $SU xrandr --output $INTERNAL_OUTPUT --off | ||
+ | |||
+ | However, this does not work anymore then as soon as $SU is not empty. | ||
+ | |||
+ | The simplest solution - can surely be done in a more elegant way - is thus to replace e.g. the first two lines of this kind with | ||
+ | |||
+ | if [ -z "$SU" ]; then | ||
+ | xrandr --output $INTERNAL_OUTPUT --off | ||
+ | xrandr --output $EXTERNAL_OUTPUT --auto | ||
+ | else | ||
+ | $SU "xrandr --output $INTERNAL_OUTPUT --off" | ||
+ | $SU "xrandr --output $EXTERNAL_OUTPUT --auto" | ||
+ | fi | ||
+ | |||
+ | |||
+ | |||
+ | Thanks a lot! --mflechl | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
Note: you will need to change the internal and external resolution until someone fixes this script to figure it out from xrandr, you may also need to change output names from "VGA" and "LVDS" to what your xrandr tells you. | Note: you will need to change the internal and external resolution until someone fixes this script to figure it out from xrandr, you may also need to change output names from "VGA" and "LVDS" to what your xrandr tells you. | ||
why not just use --auto ? | why not just use --auto ? | ||
− | xrandr --output VGA --auto | + | xrandr --output LVDS --auto --output VGA --off |
+ | xrandr --output LVDS --off --output VGA --auto | ||
+ | |||
+ | ---- | ||
− | xrandr --output VGA -- | + | Good point, made the changes --seva |
+ | |||
+ | ---- | ||
+ | |||
+ | # This is to figure out which user and X11 display to work on | ||
+ | # TODO there has to be a better way to do this? | ||
+ | SU="su $(w -h -s | grep ":[0-9]" | head -1 | awk '{print $1}') -c" | ||
+ | export DISPLAY=$(w -h -s | grep ":[0-9]" | head -1 | awk '{print $3}' | ||
+ | |||
+ | |||
+ | concerning detecting what is currently active from xrandr. with VGA off xrandrq shows | ||
+ | |||
+ | Screen 0: minimum 320 x 200, current 1024 x 768, maximum 2048 x 2048 | ||
+ | VGA connected (normal left inverted right) | ||
+ | 1600x1200 60.0 + 59.9 | ||
+ | 1280x1024 75.0 59.9 | ||
+ | 1152x864 74.8 | ||
+ | 1024x768 75.1 60.0 | ||
+ | 800x600 75.0 60.3 | ||
+ | 640x480 75.0 60.0 | ||
+ | 720x400 70.1 | ||
+ | LVDS connected 1024x768+0+0 (normal left inverted right) 304mm x 228mm | ||
+ | 1024x768 60.0*+ 50.0 | ||
+ | 800x600 60.3 | ||
+ | 640x480 60.0 59.9 | ||
+ | |||
+ | with VGA on | ||
+ | VGA connected 1600x1200+0+0 (normal left inverted right) 367mm x 275mm | ||
+ | 1600x1200 60.0*+ 59.9 | ||
+ | 1280x1024 75.0 59.9 | ||
+ | 1152x864 74.8 | ||
+ | 1024x768 75.1 60.0 | ||
+ | 800x600 75.0 60.3 | ||
+ | 640x480 75.0 60.0 | ||
+ | 720x400 70.1 | ||
+ | LVDS connected 1024x768+0+0 (normal left inverted right) 304mm x 228mm | ||
+ | 1024x768 60.0*+ 50.0 | ||
+ | 800x600 60.3 | ||
+ | 640x480 60.0 59.9 | ||
+ | |||
+ | with LVDS off: | ||
+ | |||
+ | |||
+ | djc@Twingo:~$ xrandr --output LVDS --off --output VGA --auto | ||
+ | djc@Twingo:~$ xrandr -q | ||
+ | Screen 0: minimum 320 x 200, current 1600 x 1200, maximum 2048 x 2048 | ||
+ | VGA connected 1600x1200+0+0 (normal left inverted right) 367mm x 275mm | ||
+ | 1600x1200 60.0*+ 59.9 | ||
+ | 1280x1024 75.0 59.9 | ||
+ | 1152x864 74.8 | ||
+ | 1024x768 75.1 60.0 | ||
+ | 800x600 75.0 60.3 | ||
+ | 640x480 75.0 60.0 | ||
+ | 720x400 70.1 | ||
+ | LVDS connected (normal left inverted right) | ||
+ | 1024x768 60.0 + 50.0 | ||
+ | 800x600 60.3 | ||
+ | 640x480 60.0 59.9 | ||
+ | |||
+ | so detection should be possible on the differences between | ||
+ | VGA connected 1600x1200+0+0 (normal left inverted right) 367mm x 275mm | ||
+ | VGA connected (normal left inverted right) | ||
+ | LVDS connected (normal left inverted right) | ||
+ | LVDS connected 1024x768+0+0 (normal left inverted right) 304mm x 228mm | ||
+ | |||
+ | eg between '''xxxx connected nnnnxnn+0+0 (''' and '''xxxx connected (''' | ||
+ | |||
+ | ---- | ||
+ | Regarding 1. acpid runs as root, so I switch to a user account before runinng xrandr, however I need to figure out which user to switch to -- hence the hack. | ||
− | + | Regarding 2. that doesn't tell us if screens are being mirrored or exended, just active, i think that in combination with some other tools (xwininfo -root perhaps?) could work. | |
− | + | --seva | |
---- | ---- | ||
− | + | djc@Twingo:~$ xrandr --output LVDS --auto --output VGA --auto --below LVDS | |
+ | djc@Twingo:~$ xrandr -q | ||
+ | Screen 0: minimum 320 x 200, current 1600 x 1968, maximum 2048 x 2048 | ||
+ | VGA connected 1600x1200+0+768 (normal left inverted right) 367mm x 275mm | ||
+ | ... | ||
+ | LVDS connected 1024x768+0+0 (normal left inverted right) 304mm x 228mm | ||
+ | |||
+ | so the position is in the +0+768 | ||
+ | |||
+ | ---- | ||
+ | |||
+ | Akw, I don't think the script needs to be colorized, it better to leave things the user needs to change in bold instead. | ||
+ | |||
+ | Ordonnateur, I've made the changes so the script now figures out the state from xrandr and doesn't need to store it to a file. | ||
+ | |||
+ | --seva | ||
+ | |||
+ | ---- | ||
+ | |||
+ | This is great work, better than I could do. But here is another bug for you: grep connected is also picking up disconnected. | ||
+ | |||
+ | status) | ||
+ | echo "Current Fn-F7 state is: $STATE" | ||
+ | echo | ||
+ | echo "Attached monitors:" | ||
+ | xrandr | grep connected | sed "s/^/ /" | ||
+ | |||
+ | gives | ||
+ | |||
+ | djc@Twingo:~$ Desktop/thinkpad-fn-f7.sh status | ||
+ | Current Fn-F7 state is: internal | ||
+ | |||
+ | Attached monitors: | ||
+ | VGA disconnected (normal left inverted right) | ||
+ | LVDS connected 1024x768+0+0 (normal left inverted right) 304mm x 228mm | ||
+ | |||
+ | ---- | ||
+ | |||
+ | fixed --seva | ||
+ | |||
+ | Re detecting the X user, it may be just as ugly but have you looked at | ||
+ | /usr/share/acpi-support/power-funcs | ||
+ | |||
+ | for example this is the /etc/acpi/screenblank.sh in Ubuntu 7.10 | ||
+ | |||
+ | #!/bin/bash | ||
+ | . /etc/default/acpi-support | ||
+ | . /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 | ||
+ | fi | ||
+ | done | ||
+ | |||
+ | ---- | ||
+ | Husky69, `w` output looks like this for me: | ||
+ | |||
+ | [seva@brain ~]$ w -h -s | ||
+ | seva tty7 :0 0.00s /usr/bin/gnome-session | ||
+ | |||
+ | So `awk '{print $3}'` is correct, does w output look different for you? | ||
+ | |||
+ | ---- | ||
+ | Thanks for the excellent article. On my x300 running Ubuntu 8.10 the thinkpad-fn-f7 script doesn't work. I changed lines 39 and 40 to: | ||
+ | |||
+ | INTERNAL_STATE=$($SU xrandr | sed -n "s/${INTERNAL_OUTPUT}\Wconnected\W\([0-9]\+[xX][0-9]\++[0-9]\++[0-9]\+\).*/\1/p") | ||
+ | EXTERNAL_STATE=$($SU xrandr | sed -n "s/${EXTERNAL_OUTPUT}\Wconnected\W\([0-9]\+[xX][0-9]\++[0-9]\++[0-9]\+\).*/\1/p") | ||
+ | |||
+ | This finds the state of each monitor, so you can tell whether you're mirroring two active monitors, and leaves the variable empty if the monitor is connected but off. I know more about sed than about monitors, so I'd appreciate your feedback if you see a reason why this script wouldn't work in all situations. | ||
+ | ---- | ||
+ | ===Multiple output switching.=== | ||
+ | |||
+ | Normally I use a dockstation which include a DVI output. So I added a little check on what external output to use: | ||
+ | <bash> | ||
+ | #!/bin/bash | ||
+ | # From: http://www.thinkwiki.org/wiki/Sample_Fn-F7_script | ||
+ | # | ||
+ | # External outputs may be "VGA" or "VGA-0" or "DVI-0" or "TMDS-1" | ||
+ | VGA="VGA-1" | ||
+ | DVI="DVI-D-1" | ||
+ | |||
+ | # Check for external connections | ||
+ | xrandr -q | grep -q "$VGA connected" | ||
+ | if [ $? -eq 0 ] ; then | ||
+ | EXTERNAL_OUTPUT=$VGA | ||
+ | fi | ||
+ | |||
+ | xrandr -q | grep -q "$DVI connected" | ||
+ | if [ $? -eq 0 ] ; then | ||
+ | EXTERNAL_OUTPUT=$DVI | ||
+ | fi | ||
+ | |||
+ | ........ | ||
+ | </bash> | ||
+ | hope you'll find it useful ;)<br /> | ||
+ | [[User:Noxdafox|Noxdafox]] |
Latest revision as of 17:23, 3 November 2010
X40 + Ubuntu 8.10
I'm using an IBM ThinkPad X40 w/ Ubuntu 8.10. I edited the .Xauthority bash script slightly because it wasn't working for me. I simplified it to just switch from one monitor to the other. It switches the display fine; however, the buttons to open programs in the panel get messed up. Right now, the rightmost four slide all the way to the right of the panel, and the rest (3) stay where they were originally. Is anyone else experiencing this? If you're going to test it out, make sure you have at least 7 buttons. Here is the script I'm using to switch screens:
#!/bin/bash # From: http://www.thinkwiki.org/wiki/Sample_Fn-F7_script # # External output may be "VGA" or "VGA-0" or "DVI-0" or "TMDS-1" EXTERNAL_OUTPUT="VGA" INTERNAL_OUTPUT="LVDS" function screen_external(){ xrandr --output $INTERNAL_OUTPUT --off xrandr --output $EXTERNAL_OUTPUT --auto } function screen_internal(){ xrandr --output $EXTERNAL_OUTPUT --off xrandr --output $INTERNAL_OUTPUT --auto } function screen_toggle(){ # Figure out current state INTERNAL_STATE=$(xrandr | grep ^$INTERNAL_OUTPUT | grep con | sed "s/.*connected //" | sed "s/(.*//") EXTERNAL_STATE=$(xrandr | grep ^$EXTERNAL_OUTPUT | grep con | sed "s/.*connected //" | sed "s/(.*//") if [ -z "$INTERNAL_STATE" ]; then STATE="external" else STATE="internal" fi case "$STATE" in internal) screen_external ;; external) screen_internal ;; *) screen_internal ;; esac } # based on /etc/acpi/screenblank.sh (Ubuntu 7.10) # . /usr/share/acpi-support/power-funcs # for getXuser 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" screen_toggle fi done
R50e + Fedora 9
Using Fedora 9 on a Thinkpad R50e, and works like a charm for me - only had to do one modification: If the environment is such that X_USER equals USER, then the version with citation marks - like in
$SU "xrandr --output $INTERNAL_OUTPUT --off"
does not work, bash would complain that the command was not found. It would then have to be
$SU xrandr --output $INTERNAL_OUTPUT --off
However, this does not work anymore then as soon as $SU is not empty.
The simplest solution - can surely be done in a more elegant way - is thus to replace e.g. the first two lines of this kind with
if [ -z "$SU" ]; then xrandr --output $INTERNAL_OUTPUT --off xrandr --output $EXTERNAL_OUTPUT --auto else $SU "xrandr --output $INTERNAL_OUTPUT --off" $SU "xrandr --output $EXTERNAL_OUTPUT --auto" fi
Thanks a lot! --mflechl
Note: you will need to change the internal and external resolution until someone fixes this script to figure it out from xrandr, you may also need to change output names from "VGA" and "LVDS" to what your xrandr tells you.
why not just use --auto ?
xrandr --output LVDS --auto --output VGA --off xrandr --output LVDS --off --output VGA --auto
Good point, made the changes --seva
- This is to figure out which user and X11 display to work on
# TODO there has to be a better way to do this?
SU="su $(w -h -s | grep ":[0-9]" | head -1 | awk '{print $1}') -c" export DISPLAY=$(w -h -s | grep ":[0-9]" | head -1 | awk '{print $3}'
concerning detecting what is currently active from xrandr. with VGA off xrandrq shows
Screen 0: minimum 320 x 200, current 1024 x 768, maximum 2048 x 2048 VGA connected (normal left inverted right) 1600x1200 60.0 + 59.9 1280x1024 75.0 59.9 1152x864 74.8 1024x768 75.1 60.0 800x600 75.0 60.3 640x480 75.0 60.0 720x400 70.1 LVDS connected 1024x768+0+0 (normal left inverted right) 304mm x 228mm 1024x768 60.0*+ 50.0 800x600 60.3 640x480 60.0 59.9
with VGA on
VGA connected 1600x1200+0+0 (normal left inverted right) 367mm x 275mm 1600x1200 60.0*+ 59.9 1280x1024 75.0 59.9 1152x864 74.8 1024x768 75.1 60.0 800x600 75.0 60.3 640x480 75.0 60.0 720x400 70.1 LVDS connected 1024x768+0+0 (normal left inverted right) 304mm x 228mm 1024x768 60.0*+ 50.0 800x600 60.3 640x480 60.0 59.9
with LVDS off:
djc@Twingo:~$ xrandr --output LVDS --off --output VGA --auto djc@Twingo:~$ xrandr -q Screen 0: minimum 320 x 200, current 1600 x 1200, maximum 2048 x 2048 VGA connected 1600x1200+0+0 (normal left inverted right) 367mm x 275mm 1600x1200 60.0*+ 59.9 1280x1024 75.0 59.9 1152x864 74.8 1024x768 75.1 60.0 800x600 75.0 60.3 640x480 75.0 60.0 720x400 70.1 LVDS connected (normal left inverted right) 1024x768 60.0 + 50.0 800x600 60.3 640x480 60.0 59.9
so detection should be possible on the differences between
VGA connected 1600x1200+0+0 (normal left inverted right) 367mm x 275mm VGA connected (normal left inverted right) LVDS connected (normal left inverted right) LVDS connected 1024x768+0+0 (normal left inverted right) 304mm x 228mm
eg between xxxx connected nnnnxnn+0+0 ( and xxxx connected (
Regarding 1. acpid runs as root, so I switch to a user account before runinng xrandr, however I need to figure out which user to switch to -- hence the hack.
Regarding 2. that doesn't tell us if screens are being mirrored or exended, just active, i think that in combination with some other tools (xwininfo -root perhaps?) could work.
--seva
djc@Twingo:~$ xrandr --output LVDS --auto --output VGA --auto --below LVDS djc@Twingo:~$ xrandr -q Screen 0: minimum 320 x 200, current 1600 x 1968, maximum 2048 x 2048 VGA connected 1600x1200+0+768 (normal left inverted right) 367mm x 275mm ... LVDS connected 1024x768+0+0 (normal left inverted right) 304mm x 228mm
so the position is in the +0+768
Akw, I don't think the script needs to be colorized, it better to leave things the user needs to change in bold instead.
Ordonnateur, I've made the changes so the script now figures out the state from xrandr and doesn't need to store it to a file.
--seva
This is great work, better than I could do. But here is another bug for you: grep connected is also picking up disconnected.
status) echo "Current Fn-F7 state is: $STATE" echo echo "Attached monitors:" xrandr | grep connected | sed "s/^/ /"
gives
djc@Twingo:~$ Desktop/thinkpad-fn-f7.sh status Current Fn-F7 state is: internal
Attached monitors: VGA disconnected (normal left inverted right) LVDS connected 1024x768+0+0 (normal left inverted right) 304mm x 228mm
fixed --seva
Re detecting the X user, it may be just as ugly but have you looked at
/usr/share/acpi-support/power-funcs
for example this is the /etc/acpi/screenblank.sh in Ubuntu 7.10
#!/bin/bash . /etc/default/acpi-support . /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 fi done
Husky69, `w` output looks like this for me:
[seva@brain ~]$ w -h -s seva tty7 :0 0.00s /usr/bin/gnome-session
So `awk '{print $3}'` is correct, does w output look different for you?
Thanks for the excellent article. On my x300 running Ubuntu 8.10 the thinkpad-fn-f7 script doesn't work. I changed lines 39 and 40 to:
INTERNAL_STATE=$($SU xrandr | sed -n "s/${INTERNAL_OUTPUT}\Wconnected\W\([0-9]\+[xX][0-9]\++[0-9]\++[0-9]\+\).*/\1/p") EXTERNAL_STATE=$($SU xrandr | sed -n "s/${EXTERNAL_OUTPUT}\Wconnected\W\([0-9]\+[xX][0-9]\++[0-9]\++[0-9]\+\).*/\1/p")
This finds the state of each monitor, so you can tell whether you're mirroring two active monitors, and leaves the variable empty if the monitor is connected but off. I know more about sed than about monitors, so I'd appreciate your feedback if you see a reason why this script wouldn't work in all situations.
Multiple output switching.
Normally I use a dockstation which include a DVI output. So I added a little check on what external output to use: <bash>
- !/bin/bash
- From: http://www.thinkwiki.org/wiki/Sample_Fn-F7_script
- External outputs may be "VGA" or "VGA-0" or "DVI-0" or "TMDS-1"
VGA="VGA-1" DVI="DVI-D-1"
- Check for external connections
xrandr -q | grep -q "$VGA connected" if [ $? -eq 0 ] ; then
EXTERNAL_OUTPUT=$VGA
fi
xrandr -q | grep -q "$DVI connected" if [ $? -eq 0 ] ; then
EXTERNAL_OUTPUT=$DVI
fi
........
</bash>
hope you'll find it useful ;)
Noxdafox