有些设备的触摸屏不准,需要校正后才能正常使用。校正实际上就是配置设备在 Xorg 中的属性,具体属性名与驱动相关,后文描述。
注意: 本文所有的操作都是在 deepin 上完成,包名不同的请自行查找。
下面开始介绍校正方法:
准备
安装需要用到的工具:
- xinput-calibrator : 触摸屏校正工具
 - xinput : 屏幕映射工具,多屏时使用
 
校正
- 执行 
xinput_calibrator --list查看触摸设备列表 - 校正设备 
xinput_calibrator -v --device <device name or id>device name or id从上面的list中得到 
此时会出现校正界面,按照提示点击,成功后程序会输出校正后的数据。
接着根据驱动的不同选择不同的设置方法,查看设备使用的驱动可通过 /var/log/Xorg.0.log 文件得到。
- evdev
使用
evedev驱动时可直接使用xinput_calibrator输出的数据,无需其它设置。测试时使用
xinput设置Evdev Axis Calibration属性。 - 
libinput
使用
libinput驱动时需要将xinput_calibrator输出的数据进行计算才可使用,计算方法参见: Libinput breaks xinput_calibrator在此将计算方法写成了一个脚本,内容如下:
#!/usr/bin/env python3 # -*- coding: UTF-8 -*- import sys def usage(): info = "Usage: " + sys.argv[0] info += " <screen_width> <screen_height>" info += " <click_0_x> <click_0_y>" info += " <click_3_x> <click_3_y>" print(info) print("\tScreen width/hight by the command 'xrandr|grep screen' got") print("\tClick x/y by the command 'xinput_calibrator -v' got") sys.exit(0) def convert(screen_x, screen_y, c0_x, c0_y, c3_x, c3_y): a = (screen_x * 6 / 8) / (c3_x - c0_x) c = ((screen_x / 8) - (a * c0_x)) / screen_x e = (screen_y * 6 / 8) / (c3_y - c0_y) f = ((screen_y / 8) - (e * c0_y)) / screen_y print("Try set 'libinput Calibration Matrix' to '%.1f, 0.0, %.1f, 0.0, %.1f, %.1f, 0.0, 0.0, 1.0'" % (a,c,e, f)) if __name__ == "__main__": if len(sys.argv) != 7: usage() convert(int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3]), int(sys.argv[4]),int(sys.argv[5]),int(sys.argv[6]))测试时使用
xinput设置libinput Calibration Matrix属性。若上面计算的值设置后仍有问题,尝试 Calculate the Coordinate Transformation Matrix 这种计算方法。
如若都不行切换到
evdev驱动,即安装xserver-xorg-input-evdev然后添加99-touchscreen-evdev.conf到/etc/X11/xorg.conf.d目录, 内容如下:Section "InputClass" Identifier "calibration" Driver "evdev" MatchProduct "<touchscreen product>" EndSection其中的
touchscreen product可以从/var/log/Xorg.0.log得到。 
示例
如在 Huawei 上执行校正操作的输出如下:
deepin@deepin-PC:~$ xinput_calibrator -v
DEBUG: XInputExtension version is 2.3
DEBUG: Skipping virtual master devices and devices without axis valuators.
DEBUG: Skipping device 'Virtual core XTEST pointer' id=4, does not report Absolute events.
DEBUG: Skipping device 'SYNA1D31:00 06CB:CD48 Touchpad' id=12, does not report Absolute events.
DEBUG: Selected device: SYNA2393:00 06CB:19AC
DEBUG: Not usbtouchscreen calibrator: Not a usbtouchscreen device
DEBUG: Evdev Axis Calibration not set, setting to axis valuators to be sure.
        Setting calibration data: 0, 3000, 0, 2000
DEBUG: Successfully applied axis calibration.
DEBUG: Read axes swap value of 0.
DEBUG: Read InvertX=0, InvertY=0.
Calibrating EVDEV driver for "SYNA2393:00 06CB:19AC" id=11
        current calibration values (from XInput): min_x=0, max_x=3000 and min_y=0, max_y=2000
DEBUG: Found that 'SYNA2393:00 06CB:19AC' is a sysfs name.
DEBUG: Adding click 0 (X=382, Y=246)
DEBUG: Adding click 1 (X=2647, Y=246)
DEBUG: Adding click 2 (X=376, Y=1761)
DEBUG: Adding click 3 (X=2640, Y=1764)
Doing dynamic recalibration:
        Setting calibration data: 2, 3021, -7, 2015
DEBUG: Successfully applied axis calibration.
        --> Making the calibration permanent <--
DEBUG: Found that 'SYNA2393:00 06CB:19AC' is a sysfs name.
  copy the snippet below into '/etc/X11/xorg.conf.d/99-calibration.conf' (/usr/share/X11/xorg.conf.d/ in some distro's)
Section "InputClass"
        Identifier    "calibration"
        MatchProduct    "SYNA2393:00 06CB:19AC"
        Option    "Calibration"    "2 3021 -7 2015"
        Option    "SwapAxes"    "0"
EndSection
Xorg.0.log 中设备驱动相关的日志如下:
[  7221.421] (II) config/udev: Adding input device SYNA2393:00 06CB:19AC (/dev/input/event7)
[  7221.421] (**) SYNA2393:00 06CB:19AC: Applying InputClass "evdev touchscreen catchall"
[  7221.421] (**) SYNA2393:00 06CB:19AC: Applying InputClass "libinput touchscreen catchall"
[  7221.421] (**) SYNA2393:00 06CB:19AC: Applying InputClass "calibration"
[  7221.421] (II) LoadModule: "evdev"
[  7221.421] (II) Loading /usr/lib/xorg/modules/input/evdev_drv.so
[  7221.421] (II) Module evdev: vendor="X.Org Foundation"
[  7221.421]    compiled for 1.19.1, module version = 2.10.5
[  7221.421]    Module class: X.Org XInput Driver
[  7221.421]    ABI class: X.Org XInput driver, version 24.1
[  7221.421] (II) Using input driver 'evdev' for 'SYNA2393:00 06CB:19AC'
- evdev
 
执行命令 xinput set-prop 11 Evdev Axis Calibration 2 3021 -7 2015 测试效果
- libinput
 
使用上面的 click 0 和 click 3 的值以及 xrandr 得到的 screen width/height 计算,得到的值如下:
$ python3 ./touchscreen_calibration_convert.py 344 193 382 246 376 1761
Try set 'libinput Calibration Matrix' to '-43.0, 0.0, 47.9, 0.0, 0.1, 0.0, 0.0, 0.0, 1.0'
执行命令 xinput set-prop 11 libinput Calibration Matrix -43.0 0.0 47.9 0.0 0.1 0.0 0.0 0.0 1.0 测试效果。
额外问题
某些设备按照上述步骤设置后仍然有一些问题,这里列出一些遇到过的,一旦出现下面这些情况,请先切换驱动到 evdev 然后进行设置。
上下相反
如点击 左上角 却反馈在 左下角 ,在 90-touchscreen-calibrator.conf 中加上 Option InvertY "true" 。
左右相反
如点击 左上角 却反馈在 右下角 ,在 90-touchscreen-calibrator.conf 中加上 Option InvertX "true" 。
边缘偏移
如点击最右边却反馈在旁边的区域,此时可调整 Option Calibration 的值,其值的含有为: "min-x max-x min-y max-y" 。在四个边缘都试下,然后调整对应的值。
XY 相反
如点击 左上角 却反馈在 右上角 ,在 90-touchscreen-calibrator.conf 中加上 Option SwapAxes "true" 。
持久化
上面的测试无误后,就开始集成到系统中,每次启动时都自动执行。
自动执行通过 xorg.conf.d 钩子执行,添加 90-touchscreen-calibrator.conf 到 /etc/X11/xorg.conf.d/ 目录中。
evdev
示例内容如下:
Section "InputClass"
        Identifier    "calibration"
        MatchProduct    "SYNA2393:00 06CB:19AC"
        Option    "Calibration"    "2 3021 -7 2015"
        Option    "SwapAxes"    "0"
EndSection
libinput
示例内容如下:
Section "InputClass"
        Identifier    "calibration"
        MatchProduct    "SYNA2393:00 06CB:19AC"
        Option    "CalibrationMatrix"    "-43.0 0.0 47.9 0.0 0.1 0.0 0.0 0.0 1.0"
EndSection
设备映射
若存在多块屏幕,这时就需要指定触摸屏对应的设备,使用 xinput --map-output-to <device id> <output name> 。
device name 就是上文中得到的 id , output name 可通过  xrandr 命令得到。
持久化
可添加 90-touchscreen-map 到 /etc/X11/xinit/xinitrc.d 目录,内容就是上面的命令。
参考文档
- 
man 4 evdev: 需要安装xserver-xorg-input-evdev - 
man 4 libinput: 需要安装xserver-xorg-input-libinput