Sony VAIO Touchpad toggling

Often traveling on trains and flights, I am used to type a lot during these time. Unfortunately, my Vaio Pro13 is a bit fragile, means that under normal typing, the weight of my hands near the touchpad makes the mouse pointer jump around indeterministically. Not only once a long text I typed was deleted due to this behavior. I tried to use the Synaptics feature that automatically disables the touchpad while typing, but I get crazy with the late re-enabling, so I quited using this approach. But there is a different way: On my VAIO there is a nice symbol on the F1 key that should toggle the touchpad state, but unfortunately it doesn’t work. So I tried to come up with a solution, but it was harder than I thought, because I wanted to do it via an ACPI event, which runs outside the user environment.

touchpad-button

The first step in activating a key is finding out whether it sends any event. Using xev it turns out that there is no response, so the easy way of binding a script in the X environment is blocked.

Next one checks with acpi_listen and hurray, in this case we get a response, in my case:

button/fnf1 FNF1 00000080 00000000 K
sony/hotkey SNY5001:00 00000001 0000000c
sony/hotkey SNY5001:00 00000001 0000003b

This means we can add an acpi event and action, by dropping a file sony-touchpad into /etc/acpi/events with the following content:

event=sony/hotkey SNY5001:00 00000001 0000000c
action=/etc/acpi/toggle-touchpad.sh

I choose the Sony SYN event instead of the F1, but I guess both works.

Now for the actual toggling script /etc/acpi/toggle-touchpad.sh:

Update 2014-10-27 Thanks to Mattia Dongili a much simplified version of the script that uses the native sony module and does not need to trick around with systemd!

#!/bin/sh

TP=/sys/devices/platform/sony-laptop/touchpad
test -f "$TP" || exit 0

state=$(cat $TP)
if [ $state = 1 ] ; then
  echo 0 > $TP
else
  echo 1 > $TP
fi

With this setup I can toggle the touchpad on and off with a simple Fn-F1, especially useful when you are typing on a train and the fragile Vaio makes your pointer jump and click around indeterministically.

Old version

For completeness, here the previous version:

If you try this the direct way with writing a script that uses synclient to read and toggle the TouchpadOff value, and drop that as acpi event, it will not work, because the acpi action is run outside the X environment. Several pages on the web I found suggest dumping the full environment of the logged in user, and then load that in the script. But this is overkill. What has to be done is:

  • set the DISPLAY variable
  • set the path to the Xauthoriry file for the running user

Both information can be found using loginctl, which lists users, sessions, seats, and their properties. My script below goes through the list of all sessions, and the first of class user and type x11 is used to determine the logged in user, the display, and then sets DISPLAY and XAUTHORITY environmental variables, before calling the normal synclient incantation to toggle the touchpad. Here is the code:

#!/bin/sh

export LANG=C

toggle_touchpad() {
  current_state=$(synclient -l | grep TouchpadOff | awk '{print$3}')
  if test $current_state = 0
  then
    # current_state == 0
    synclient TouchpadOff=1
  else
    # current_state == 1
    synclient TouchpadOff=0
  fi
  exit 0
}

# find logged in user using loginctl
for i in $(loginctl list-sessions --no-legend | awk '{print$1}') ; do
  type=$(loginctl -pType show-session $i | awk -F= '{print$2}')
  class=$(loginctl -pClass show-session $i | awk -F= '{print$2}')
  user=$(loginctl -pName show-session $i | awk -F= '{print$2}')
  disp=$(loginctl -pDisplay show-session $i | awk -F= '{print$2}')
  if [ "x$type" = "xx11" -a "x$class" = "xuser" ] ; then
    # get user name
    homedir=$(awk -F: -v v="$user" '{if ($1==v) print $6}' /etc/passwd)
    if [ -r "$homedir/.Xauthority" ] ; then
      DISPLAY=$disp
      XAUTHORITY="$homedir/.Xauthority"
      export DISPLAY XAUTHORITY
      toggle_touchpad
    fi
  fi
done

Leave a Reply

Your email address will not be published. Required fields are marked *