WacomのペンタブをX上でつかう
タブレットデバイス
タブレットデバイス(いわゆるペンタブ)は、絵や文字を描くときに便利な入力デバイスである。マウスやトラックポイント、タッチパッドに比べて遥かに自然に線などを描くことができる。
X上で使う上での問題点
X上では、タブレットデバイスは、スクリーン全体にマッピングされる。スクリーンののアスペクト比と、タブレットデバイスの物理的なアスペクト比がほぼ一致している場合はそこまで問題にならない。しかし、マルチモニターなどによって、スクリーンとタブレットデバイスのアスペクト比が大きく異なる場合、普通に書き込むと描いた内容が引き伸ばされる。また、スクリーン上の小さな領域に描画したい場合、タブレットデバイスの非常に小さな領域に描く必要があり、物理的なセンサー面の殆どが無駄になる。
私のデスクトップ環境は、2560x1600のモニターの右側に3840x2160のモニターを並べたマルチモニターとなっており、スクリーン全体は6400x2160の大きさである。一方使用しているタブレットデバイスはセンサー面のサイズが21600x13500の16:10のアスペクト比となっている。スクリーン全体のアスペクト比を縦10に変換すると、29.63:10となり、倍弱ほど横長なスクリーン領域となる。そのため、普通にタブレットデバイスをマッピングして描くとかなり横に伸びてしまう。
私のデスクトップ環境
普通のマッピングで描いた様子、横にかなり引き伸ばされる。
目的の状態
- この問題を解決するために、タブレットデバイスをウィンドウに合わせてマッピングする。
- ウィンドウのアスペクト比とタブレットデバイスのアスペクト比が異なる場合、センサー面が無駄になることを許容して、アスペクト比を保つ。
横長のウィンドウへのマッピング
縦長のウィンドウへのマッピング
正しくマッピングされたウィンドウに描いた様子
対処法
- xinputコマンドを用いることで、タブレットデバイスがマッピングされるスクリーン上の領域を変更できる。
xinput set-prop <device id> Coordinate\ Transformation\ Matrix <affine transformation matrix>
<device id>
で、タブレットが割り当てられているIDを選択する。<affine transformation matrix>
は、マッピングされる領域を変換するアフィン行列を展開した9つのfloatの値を入力する。
device idを調べる
xinput list
で繋がっているデバイスのリストが得られる。- ここでは、
Wacom One by Wacom M Pen stylus
がそれで、idは11であることがわかる。
- ここでは、
$ xinput list ⎡ Virtual core pointer id=2 [master pointer (3)] ⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)] ⎜ ↳ ELAN0678:00 04F3:3195 Mouse id=14 [slave pointer (2)] ⎜ ↳ ELAN0678:00 04F3:3195 Touchpad id=15 [slave pointer (2)] ⎜ ↳ TPPS/2 Elan TrackPoint id=17 [slave pointer (2)] ⎜ ↳ Wacom One by Wacom M Pen stylus id=11 [slave pointer (2)] ⎜ ↳ Wacom One by Wacom M Pen eraser id=19 [slave pointer (2)] ⎣ Virtual core keyboard id=3 [master keyboard (2)] ↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)] ↳ Power Button id=6 [slave keyboard (3)] ↳ Video Bus id=7 [slave keyboard (3)] ↳ Power Button id=8 [slave keyboard (3)] ↳ Sleep Button id=9 [slave keyboard (3)] ↳ Integrated Camera: Integrated C id=12 [slave keyboard (3)] ↳ Integrated Camera: Integrated I id=13 [slave keyboard (3)] ↳ AT Translated Set 2 keyboard id=16 [slave keyboard (3)] ↳ ThinkPad Extra Buttons id=18 [slave keyboard (3)] ↳ Solid State System Co.,Ltd. LCS USB Audio id=10 [slave keyboard (3)] $
$ xsetwacom --list devicesp Wacom One by Wacom M Pen stylus id: 11 type: STYLUS Wacom One by Wacom M Pen eraser id: 19 type: ERASER $
アフィン変換行列を求める
- xinputの
Coordinate Transformation Matrix
の引数にはアフィン変換行列を与える。 - スクリーン全体にマッピングされた状態から、目的の状態への変換行列を求める必要がある。
- 具体的には、原点(左上)を中心に、ウィンドウサイズに合わせてスケーリングを行う変換行列と、ウィンドウの左上に合わせて平行移動を行う変換行列の積を求める。
スケーリング
- ウィンドウのアスペクト比とタブレットデバイスのアスペクト比が異なる時、マッピングされる領域のアスペクト比とタブレットデバイスのアスペクト比が同じになるようにする。
- つまり、マッピングされる領域がウィンドウからはみ出す。
- これを行うためには、以下のデータを収集する必要がある。
平行移動
- ウィンドウの左上の座標がスクリーン上でどこになるかを求める。
- ウィンドウの位置
xdotool getwindowgeometry <window id>
- スクリーンのサイズ
xdpyinfo
xrandr
- ウィンドウの位置
実装
- 上に示したようなコマンドを実行して結果をパースし、アフィン行列を計算、xinputでペンタブを設定するプログラムを実装した。
付録(それぞれのコマンドの出力)
- $で始まる行はコマンド入力である。
- ペンタブのサイズ:
xinput watch-props <device id>
$ xinput watch-props 11 Device 'Wacom One by Wacom M Pen stylus': Device Enabled (163): 1 Coordinate Transformation Matrix (165): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000 Device Accel Profile (290): 0 Device Accel Constant Deceleration (291): 1.000000 Device Accel Adaptive Deceleration (292): 1.000000 Device Accel Velocity Scaling (293): 10.000000 Device Node (287): "/dev/input/event13" Wacom Tablet Area (300): 0, 0, 21600, 13500 Wacom Rotation (301): 0 Wacom Pressurecurve (302): 0, 0, 100, 100 Wacom Serial IDs (303): 891, 0, 2, 0, 0 Wacom Serial ID binding (304): 0 Wacom Proximity Threshold (305): 30 Wacom Pressure Threshold (306): 26 Wacom Sample and Suppress (307): 2, 4 Wacom Enable Touch (308): 0 Wacom Hover Click (309): 1 Wacom Enable Touch Gesture (310): 0 Wacom Touch Gesture Parameters (311): 0, 0, 250 Wacom Tool Type (312): "STYLUS" (289) Wacom button action 0 (313): 1572865 Wacom button action 1 (314): 1572866 Wacom button action 2 (315): 1572867 Wacom button action 3 (316): 1572872 Wacom Button Actions (317): "Wacom button action 0" (313), "Wacom button action 1" (314), "Wacom button action 2" (315), "None" (0), "None" (0), "None" (0), "None" (0), "Wacom button action 3" (316) Wacom Pressure Recalibration (318): 1 Wacom Panscroll Threshold (319): 1300 Device Product ID (288): 1386, 891 Wacom Debug Levels (320): 0, 0 $
- ペンタブのサイズ:
xsetwacom --get <device name> Area
$ xsetwacom --get "Wacom One By Wacom M Pen stylus" Area 0 0 21600 13500 $
- ウィンドウのジオメトリ:
xdotool getwindowgeometry <window id>
- ウィンドウのID:
xdotool selectwindow
$ xdotool getwindowgeometry $(xdotool selectwindow) Window 4194313 Position: 1280,0 (screen: 0) Geometry: 1280x1600 $
- スクリーンのサイズ:
xdpyinfo
$ xpyinfo | grep dimensions dimensions: 6400x2160 pixels (1684x568 millimeters) $
- スクリーンのサイズ:
xrandr
$ xrandr | grep Screen Screen 0: minimum 320 x 200, current 6400 x 2160, maximum 16384 x 16384 $