5

I use xinput to change the settings of my USB mouse:

xinput set-ptr-feedback 'USB Optical Mouse' 4 1 1

How can I make these settings persistent after unplugging the mouse or rebooting?

ændrük
  • 76,794

2 Answers2

7

You could cron the command or add it to your startup but neither are particularly elegant. If I were you, I'd add this to my udev rules and let the system detect events and fire off the command when it needs to.

First we need the mouse vendor and product strings. You can find these through lsusb. Look for your mouse. Here's my mouse shows up:

Bus 004 Device 012: ID 1532:000f Razer USA, Ltd 

The In the part 1532:000f, 1532 is the vendor and 000f is the product.

So then we add a rule to udev. udev rules are found in /lib/udev/rules.d/. You can write your own or be cheeky and edit another one. There is a helpful little README in there too that I suggest you peruse (cat /lib/udev/rules.d/README).

Whichever you do you want to add a rule like this. Notice I use the IDs from earlier to make this work.

BUS=="usb", SYSFS{idVendor}=="1532", SYSFS{idProduct}=="000f", ACTION=="add",
RUN+="/usr/bin/xinput set-ptr-feedback 'USB Optical Mouse' 4 1 1"

udev should pick that up immediately.

Note udev can do pretty clever things on its own when it comes to configuring devices. You might not need xinput at all. Here's an example of a custom configuration for a mouse.

Oli
  • 293,335
  • Hmmm... but udevd will run commands as root, so no access to your $DISPLAY... – Riccardo Murri Sep 09 '10 at 09:53
  • True. You could just wump env DISLPAY=:0 in front of the command. But no, making udev do what the xinput command is doing would be an altogether better solution. – Oli Sep 09 '10 at 10:09
  • 1
    Not that easy: you also need the Xauthority cookie to access the display, so env HOME=/home/user DISPLAY=:0 ... is a better stab at it. But then, if gdm changes the display number (e.g., multiple cuncurrent logins), it won't work anyway... (already walked this way for a similar problem and got nowhere).

    One of the links in the "custom configuration" page that you posted suggests using "xorg.conf.d" snippets in Ubuntu 10.04, which seems to be the right way. But then, it's not clear how to translate xinput set-ptr-feedback into Xorg.conf directives...

    – Riccardo Murri Sep 09 '10 at 10:38
  • To address the user issue you can wrap the command in a su command. The run would be: /bin/su username -c '/usr/bin/xinput set-ptr-feedback \'USB Optical Mouse\' 4 1 1' (my escaping might not be right). But yes, this still might not work here. Custom evdev commands through udev are probably the best device specific option though, but yes, xorg rules should work too. But this requires a translation of the xinput command that, like you, I don't know. – Oli Sep 09 '10 at 11:48
2

I can think of no other solution than starting a little daemon that periodically polls xinput --list and runs a command when a device is plugged in or removed.

Sample code:

#! /bin/sh -x
#
# xievd [INTERVAL]
#
# Poll `xinput` device list every INTERVAL seconds (default: 10)
# and run script in ~/.xievd/${device_name}.sh when a device is
# plugged-in (or pulled out).
#
# The device name is the same as given by `xinput --list`, with
# the following transformations applied:
#   * any non-alphanumeric character is deleted (except: space, `_` and `-`)
#   * leading and trailing spaces are removed
#   * any sequence of 1 or more space chars is converted to a single `_`
#

interval=${1:-10}

scripts_dir="$HOME/.xievd"
if [ ! -d "$scripts_dir" ]; then
  echo 1>&2 "xievd: No scripts directory -- exiting."
  exit 1
fi

state_dir="$(mktemp -t -d xievd.XXXXXX)" \
  || { echo 1>&2 "xievd: Cannot create state directory -- exiting."; exit 1; }
trap "rm -rf $state_dir; exit;" TERM QUIT INT ABRT

process_xinput_device_list() {
  touch "${state_dir}/.timestamp"

  # find new devices and run "start" script
  xinput --list --short \
    | fgrep slave \
    | sed -r -e 's/id=[0-9]+.+//;s/[^a-z0-9 _-]//ig;s/^ +//;s/ *$//;s/ +/_/g;' \
    | (while read device; do 
        if [ ! -e "${state_dir}/${device}" ]; then
          # new device, run plug-in script
          [ -x "${scripts_dir}/${device}" ] && "${scripts_dir}/${device}" start
        fi
        touch "${state_dir}/${device}"
      done)

  # find removed devices and run "stop" script
  for d in "$state_dir"/*; do
    if [ "${state_dir}/.timestamp" -nt "$d" ]; then
      # device removed, run "stop" script
      device="$(basename $d)"
      [ -x "${scripts_dir}/${device}" ] && "${scripts_dir}/${device}" stop
      rm -f "$d"
    fi
  done
}

# main loop
while true; do
      process_xinput_device_list
      sleep $interval
      sleep 1
done

# cleanup
rm -rf "$state_dir"

Save the code above in a xievd executable file somewhere in your PATH, add it to your startup applications, and then create a ~/.xievd/USB_Optical_Mouse shell script:

#! /bin/sh
if [ "$1" = "start" ]; then
  xinput set-ptr-feedback 'USB Optical Mouse' 4 1 1
fi
  • I rate this solution as the only usable one on the internet. making udev get a reliable handle on your X session in order to run xinput commands is flaky and unreliable at best... Polling a tiny bash script is an overhead I'm prepared to live with after the last 3 wasted hours of my life :p – pospi Apr 30 '16 at 09:35