この記事はNetBSD Advent Calendar 2023の10日目の記事です。
8日目のキーボードに続き、NetBSD 10.0でX上でのマウスについての話です。
なお2023年12月10日現在、NetBSD 10.0はまだRC1です。
先に書いておきます。
身近ないくつかの環境にNetBSD 10.0を(USBメモリにインストールして)動作させてみたところ、標準ではNetBSD 9.xで問題なく使用できていたマウス(ノートパソコンのスライドパッド等を含む)のX上でのポインタ動作が異常に遅くなる環境がありました。例えば以下のような環境です。
一方で、以下の環境では従来通り普通にマウス等のポインティングデバイスが使えました。
ただし、XP-PENのUSB接続ペンタブ(Deco Fun: ペンのみ、ディスプレイ/タッチパネル無し)をX起動前に接続していると上記の環境でもマウスの動作が著しく遅くなることが確認できました。一方、手持ちのWacom タブレット(FAVO~Bamboo,One by Wacom,Intuos 4KまでのUSB接続のもの十数種。最新のWacom Oneは未確認)を接続していても遅くなくることはありませんでした。
dynabookやLIFEBOOKの内蔵ペンタブデバイスやXP-PENのタブレットデバイスは、NetBSD9.x以降標ums(4)が絶対座標系のポインティングデバイスとして認識し、wsmouse(4)として使用することができます。つまり、何も考えなくてもX上で使えます(座標が激しくずれたりすることはありますが)。また、同時に接続しているマウスも同時に使えます。 一方でWacomの過去のUSB接続タブレットは独自デバイスのためums(4)として認識されません。
ということで、以下の条件が重なった場合に動作が激しく遅くなるようです。
どれぐらい遅くなるかというと、例えば上記LIFEBOOKでFullHDの画面を左端から右端まで移動させるのに内蔵スライドパッドを単純になぞった場合以下のようになります。
およそ25倍遅くなっています。もちろんスライドパッドの動作比率を手動調整で変更することもできるでしょうが、とりあえずデフォルトではこんなになりました。 上下移動でもNetBSD 10.0は30倍ほど遅くなっています。縦横双方こんなで見た目的に通常の操作量ではポインタが微塵も動かず、体感的には「100倍遅くなった」と言っても過言ではないと思います。
色々動作確認やソース調査も行った結果、いくつかの要因が絡まってこういう状態になることがわかってきました。
1つめは、NetBSD 10.0から標準で使われるポインティングデバイスのドライバが変更になっていることです。
NetBSD 10.0では、xorg.confが無い、あるいはあっても例のAutoAddDeviceを無効にしていない場合、ポインティングデバイスドライバとして xf86-input-ws (ws(4)) が使われるようになりました。NetBSD 9.xまでは xf86-input-mouse (mousedrv(4))が使われていました。
ws(4)では、対象デバイス(/dev/wsmouseN)がタブレット系であると認識した場合(ioctl(WSMOUSEIO_GTYPE)でWSMOUSE_TYPE_TPANELだった場合)、絶対座標系であると認識し、かつ、raw modeと呼ばれるデバイスが報告する座標系をそのままXserverに渡すようになります(mousedrv(4)では、デバイスの座標系をスクリーン解像度にスケーリングされた値が帰ります。これはこれで複数ディスプレイ等の場合に問題があるのですが…)。
絶対座標系デバイスが報告する座標系は、通常、FullHDや4Kディスプレイと比較して非常に解像度が高い物になっています。たとえばLIFEBOOKやdynabookの内蔵デジタイザは 27648x15552(と同時に32768x32768の実在しないデバイスも検出してしまう)であり、XP-PENのタブレットは論理座標として32768x32768のデータを返してきます。ws(4)はこの値をxinputデバイスの座標系に設定します。実際のスクリーンへのマッピングはここからスケーリング、つまり縮小されて使われます。 これが相対座標系デバイスである通常のマウスにも適用されてしまうと、この大きな座標系の中での変異量として認識され、移動量が極端に小さく、結果ものすごく遅くなってしまいます。
相対座標系のデバイスではこのような問題は起りません。しかし、NetBSDのwsmouse(4)は、複数のデバイスをまとめたwsmux(4)で扱え、相対座標系デバイスも絶対座標系デバイスも一緒にして1つのデバイスとして扱うことができます。
相対座標系デバイスと絶対座標系デバイスが同時に存在している場合、wsmux(4)な/dev/wsmouseに対して先のioctl(WSMOUSEIO_GTYPE)を発行した場合、一体何が返されるでしょうか? 実はこれが不定で、どうも最後に認識した、あるいは操作したデバイスになるのではないかと思われます。実際、手元で確認する限り、TPANELを返してくることがほとんどのようです。このため、xinputの ws(4)では、/dev/wsmouse というデバイスに対して例えばLIFEBOOKでは以下のように最大座標を元にしたプロパティ Axis Calibration が 0,32767,0,32767 と設定されています。
% xinput list-props /dev/wsmouse
Device '/dev/wsmouse':
Device Enabled (164): 1
Coordinate Transformation Matrix (166): 1.000000, 0.000000, 0.000000, 0.
000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
Device Accel Profile (273): 0
Device Accel Constant Deceleration (274): 1.000000
Device Accel Adaptive Deceleration (275): 1.000000
Device Accel Velocity Scaling (276): 10.000000
WS Pointer Axis Calibration (277): 0, 32767, 0, 32767
WS Pointer Axes Swap (278): 0
WS Pointer Middle Button Emulation (279): 2
WS Pointer Middle Button Timeout (280): 50
通常のマウスは/dev/wsmouseとして扱われるので、遅くなってしまうのも当然でしょう。
もう一つ、関連する要素があります。それは例のAutoAddDeviceです。
LIFEBOOKではデフォルト(つまりAutoAddDeviceが有効の状態)では、ポインティングデバイスが3つ登録されます。
% xinput
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
⎜ ↳ /dev/wsmouse1 id=7 [slave pointer (2)]
⎜ ↳ /dev/wsmouse2 id=8 [slave pointer (2)]
⎜ ↳ /dev/wsmouse id=9 [slave pointer (2)]
⎣ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)]
↳ /dev/wskbd id=6 [slave keyboard (3)]
ここで/dev/wsmouse1とwsmouse2は、LIFEBOOKの内蔵タッチパネル/ペンスタイラスが認識されたもので、/dev/wsmouseは通常のwsmux(4)により統合されたマウスデバイスです。
LIFEBOOKでは、NetBSD 10.0カーネルにより以下の様に認識されています。
pms0 at pckbc1 (aux slot)
pms0: Synaptics touchpad version 8.1
pms0: Extended W mode, Palm detect, Multi-finger Report, Multi-finger, Reports m
ax, Reports min
pms0: Probed max coordinates right: 5692, top: 4854
pms0: Probed min coordinates left: 1298, bottom: 1150
pckbc1: using irq 12 for aux slot
wsmouse0 at pms0 mux 0
...
uhidev1 at uhub1 port 8 configuration 1 interface 1
uhidev1: Wacom Co.,Ltd. (0x056a) Pen and multitouch sensor (0x50a8), rev 2.00/0.
01, addr 4, iclass 3/0
uhidev1: 19 report ids
ums0 at uhidev1 reportid 1: 2 buttons
wsmouse1 at ums0 mux 0
...
ums1 at uhidev1 reportid 6: 3 buttons digitizer, tip, barrel, eraser
wsmouse2 at ums1 mux 0
wsmouse0はpms0で本体キーボードの下にある、いわゆるスライドパッドでマウス相当、wsmouse1とwsmouse2はums0とums1になり、ともにディスプレイのペン/タッチセンサーに繋がっています。最初mouse1が画面タッチパネルかと思ったのですが、どうやらそれは間違いで、物理デバイスとしては実在しないがコントローラにはあるデバイスがマウスと五人されているような気がします。実在するタッチパネルは以下の様にuts0となっていますが認識に失敗し使えないようです。
uts0 at uhidev0 reportid 12
uts0: autoconfiguration error: touchscreen has no range report
この状態なので、X起動前にwsmouseは以下の様に3つのデバイスが存在するようになっています。wsmouse1とwsmouse2はともに明示的に絶対座標系のデバイスです。wsmouse0は相対座標系の通常のマウスです。
# wsmuxctl -f /dev/wsmouse -l
wsmouse0
wsmouse1
wsmouse2
このwsmouseデバイスに対し、XのAutoAddDevicesでは以下のようにX inputデバイスとして追加されています。
該当箇所のソース(GitHubのNetBSD srcミラー)
どうやら、「TPANELのデバイスは絶対座標系なので他のデバイスとは独立して設定し使える方がいいよね」と考えているようでwsmux(4)である/dev/wsmouseではなく個別のデバイスである/dev/wsmouseNに対して別個にws(4)を設定、追加しています(この時に座標系のプロパティも登録されます)。
しかしこの処理には問題があるように思えます。
前者のデバイス4つしか見ない問題は、私が特殊なのかもしれませんが、最近の2in1 note pcのように内蔵ポインティングデバイスを既に複数持っている場合、そこにお気に入りのマウス等を外付けでつけると4デバイスはあっという間に越えてしまうような気がします。それを考えると/dev/wsmouseNを決め打ちで見るよりも、/dev/wsmouseからioctl(WSMUXIO_LIST_DEVICES)を使って「接続されているデバイス一覧を参照しそのデバイスを調べるように繰り返す」が正しいように思います(もちろん上限はあっていいと思いますが)。ただ、この処理自体、X起動時にしか呼び出されないので動的に接続した場合には対応できません(「全然動的に動かない動的コンフィグレーション」の所以)。
後者ですが、これでなぜ動いているのか不思議なレベルです。 通常wsmuxに登録されたデバイスは、/dev/wsmouse2で実際のデータが発生しても読み出すのは/dev/wsmouseから行われます。でも/dev/wsmouseと/dev/wsmouse2と、同時にopenして同時に読み出しているように見えます。デバイスのデータは実際にどちらで拾っているのでしょうか? さらに、同じwxmux(4)デバイスであるwskbd(4)では、/dev/wskbdに登録された/dev/wskbd1を独自にopenすると、/dev/wskbdのmuxからは自動的にdetachされるようなのですが、wsmouseの場合はどちらも同時にopenしてreadできてしまいます。もうわけがわかりません。が、実際に/dev/wsmouseには絶対座標系デバイスが存在しており、そのためデバイスタイプはその時の運?でTPANELになり、その時に見えたどれかの座標領域がプロパティに設定されてしまっているのです。
これ、X inputのws(4)側が/dev/wsmouse側からioctl(WSMUXIO_REMOVE_DEVICE)で登録解除するべきなのではないでしょうかね? あるいは X起動前に/dev/wsmouseから絶対座標系デバイスを削除するのを(スクリプト等で)必須にしてからXを起動するとか? その場合は/dev/wsmouseNのスペシャルファイルが存在する限り確認していくとか?
とにかくこのような理由で相対座標系デバイスであるマウス等の論理座標系がタブレットパネルのそれとなり、結果むちゃくちゃ動作が遅い、という現象になっているようです。
いちばん簡単な方法はやはりAutoAddDevicesを無効にしましょう。xorg.confを作っていない場合はX -configure等で作成し、xorg.confのトップレベルに以下を追加します。
Section "ServerFlags"
Option "AutoAddDevices" "False"
EndSection
また、X -configureで作成したxorg.confでは標準ではポインタドライバとしてws(4)ではなくmousedrv(4)を使う物ができますので、絶対座標系デバイスであってもraw modeは使われず、プロパティに領域設定がされることもありません(もちろんAutoAddDevicesを無効にしなければこのエントリは使われないため、自動生成のままでは解消されないので注意が必要)。
これでマウスが異常に遅くなる現象は回避できます。
ただしタブレットが正常に認識し動作するかは微妙かもしれません。特にディスプレイが複数あるような場合、通常はxinput map-to-output等でタブレット領域を設定したくてもデバイスが混合されていると不可能です。そこで次の用にする必要があるでしょう。
これで該当のデバイスは単独で設定できるため、map-to-outputもうまく機能するかもしれません(認識状態によってはうまくできないかもしれません)。
また、当然ですがX起動後に抜き差しするとその時点で使えなくなり、再接続しても復活することはありません(Alt-Ctrl-F1とAlt-Ctrl-F5等を使って一度Xをデタッチして再度アタッチすれば、デバイス名の対応が変らなければ再開できることもあります)。動的なデバイスの変更は対応できていないのです。これはたとえAutoAddDevicesを有効にしていても変りません。
ということでマウスが異常に遅いとストレスが溜まるだけです。xsetやxinputの倍率設定で何とかしよう等と思わず、さっさとAutoAddDevicesを無効にしましょう。
キーボードに続きマウスでも悪影響しかないのですが、これが有効に機能する場面は一体どこなのか今のところさっぱりわかりません。
なお、タブレット等の絶対座標系デバイス(ペンスタイラス/デジタイザ、私は使えても無効にするであろうフィンガータッチパネル)はたとえ今回の設定で独立デバイスとして制御したとしても、実は色々と制限があります。
一番の制限は、筆圧を一切無視されてしまうということ、そして分解能がなんだか低いんだけど、というところですが、それはまたあるかどうかわからない別の機会に。
この記事は2023/12/7におおしまやが書きました。