UbuntuでBluetoothマウスの接続時に自動的に速度の設定を変更する方法

環境

概要

Bluetoothマウスの接続時に自動的にxinputコマンドが走ってマウスポインタの移動速度の設定を変更するような設定をする方法を調べました。

結論

ファイルを3つくらい作ります。

/etc/udev/rules.d/50-mouse.rules

ACTION=="add", KERNEL=="input*", SUBSYSTEM=="input", ATTR{name}=="ELECOM BlueLED Mouse", RUN+="/usr/local/bin/mouse-help-script.sh"

ELECOM BlueLED Mouseの部分は自分のデバイスの名前に合わせて変更してください(デバイスの名前の調べ方は後述)。

以下の2つは実行可能にしてください。

/usr/local/bin/mouse-help-script.sh

#!/bin/sh
at now -f /usr/local/bin/mouse-help-script-2.sh

atを使用しているので、atが入っていない場合はインストールする必要があります。

/usr/local/bin/mouse-help-script-2.sh

#!/bin/sh
DISPLAY=":0.0"
HOME=/home/someone/
XAUTHORITY=$HOME/.Xauthority
export DISPLAY XAUTHORITY HOME

DEVICE_NAME="ELECOM BlueLED Mouse"


for i in `seq 0 9`
do
        if /usr/bin/xinput list | grep -q "$DEVICE_NAME"; then
                /usr/bin/xinput --set-prop "$DEVICE_NAME" "Device Accel Constant Deceleration" 2.0
                break
        fi
        sleep 1
done

HOMEとDEVICE_NAMEは自分の環境に合わせて適宜変更します。 また、ここではxinputによって"Device Accel Constant Deceleration"の値を2.0にしていますが、変更したい設定に合わせてここも適宜変更してください。

説明

Ubuntuでは設定からマウスポインタの移動速度を変更することができますが、マウスによっては移動速度を最低にしてもまだ速すぎる場合があります。 その場合の対処法はいくつかあり、AcrhWikiのマウスのアクセラレーション - ArchWikiが詳しいです。

xorgの設定に書く方法とxinputで設定する方法がありますが、自分の場合なぜか前者はあまりうまく行かないので後者で設定しています。実はxinputによる設定は一時的なものであり、システムを終了して次回起動したときには設定は元に戻っているためまたxinputで設定する必要があります。 前述のページではこれに対処するために.xinitrcにコマンドを載せておいて起動時に自動的に実行されるようにする方法が紹介されています。

しかし、自分の場合はこの方法は使えませんでした。なぜならBluetoothマウスなので、マウスが接続されるタイミングはシステムの起動より遅いです。実はxinputは接続されている機器に対してしか設定を行えませんので、起動時に設定を行う方法では対処できません。また、接続解除→再接続とすると、やはり設定が戻ってしまいます。 そこで、Bluetoothマウスが接続されたタイミングでxinputを実行できるような方法を調べました。

そのためにはudev rulesを作ります。udevはデバイスの接続を管理してくれる何かで、udev rulesを作ることによってデバイスが接続されたときに処理を走らせることができます。作ったudev ruleは所定の場所(Ubuntu 16.04 LTSの場合は/etc/udev/rules.d/以下)に置きます。

ACTION=="add", KERNEL=="input*", SUBSYSTEM=="input", ATTR{name}=="ELECOM BlueLED Mouse", RUN+="/usr/local/bin/mouse-help-script.sh"

中身はこれで、大雑把にいうと「ELECOM BlueLED Mouseという名前のデバイスが接続されたら/usr/local/bin/mouse-help-script.shを実行する」という意味です。(ここに書くべき内容を調べるためにudevadm monitorするなどの苦労もありましたが、省略します。) なのでこのシェルスクリプトにxinputコマンドを書いておけば解決かと思いきや、実はひとつ罠があります。 実はこの処理が走るタイミングは、xinputコマンドで当該デバイスの設定を変更可能になる(デバイスが認識されて利用可能になる)よりも早いです。したがって、用意したシェルスクリプトの中でxinputを実行しても設定変更できません。

これに対する対処法は、1秒待つことです。1秒待っている間にデバイスが認識されて、xinputから設定を変更可能になることを期待します。しかし実は、udev rulesにより実行されるスクリプトはudevの処理をブロックします。つまり、スクリプトの実行が完了しないとデバイスの接続時の処理が進まないため、sleepで1秒待ったところでデバイスが利用可能な状態にはなりません。

そこで、今回の方法ではsleepしてからxinputで設定変更するスクリプトをさらに別に用意し、それをatを介して実行します。この方法では、/usr/local/bin/mouse-help-script.shの実行はatにジョブを登録するだけなので一瞬で終わり、デバイスの認識処理はちゃんと進行します。atによって別に実行された/usr/local/bin/mouse-help-script-2.shは1秒待ってからxinputで設定を変更します。(実際には1秒たっても認識されていない可能性も考慮して、デバイスが認識されるまで最大10秒くらい待ち続けるようになっています。)

なお、atを使用する代わりに

nohup /usr/local/bin/mouse-help-script-2.sh &

とするような方法も考えられますが、これはやはりudevの処理をブロックしてしまうのでだめなようです。

バイスの名前を調べる方法

いくつかあると思いますが、次のコマンドで出てきた一覧から探すのが楽です。

xinput list

参考リンク