[Bug Report] Deepin 25 联想 ThinkBook 16G7+ IAH触控板问题修复指南
Tofloor
poster avatar
wxbbilzz
deepin
5 hours ago
Author

Deepin 25 联想 ThinkBook 16 G7+ IAH(Goodix GXTP5100)触控板问题修复指南

适用系统:Deepin 25 / UOS(X11 会话,libinput 1.28.x)
触控板:Goodix GXTP5100(i2c:27c6:01e9,压力感应板 / Force Pad)
同系列机型(ThinkBook 14 G7+ IAH / ASP、ThinkPad X9-15 等)可参考,只需把 DMI 机型标识换成自己的


问题一:触控板光标完全不动(点击正常、滑动没反应)

症状

  • 单击 / 物理按压正常,能收到点击事件
  • 单指或多指滑动时,鼠标指针完全不动
  • libinput debug-events 不输出 POINTER_MOTION,但内核 event11 设备有大量 ABS 坐标事件

原因

GXTP5100 的固件在 HID 描述符中没有正确声明自己是"压力感应板(Force Pad)",libinput 不认识它,导致绝对坐标无法转换成指针移动。上游 libinput 已为部分机型(ThinkBook 14 G7+ IAH、ThinkPad X9-15 等)添加了 quirk,但没有覆盖 ThinkBook 16 G7+ IAH

解决

创建 /etc/libinput/local-overrides.quirks,内容如下:

# ThinkBook 16 G7+ IAH 的 GXTP5100 触控板固件未正确声明为压力感应板
[Lenovo ThinkBook 16 G7+ IAH touchpad]
MatchName=*GXTP5100*
MatchDMIModalias=dmi:*svnLENOVO:*pvrThinkBook16G7+IAH*:*
MatchUdevType=touchpad
ModelPressurePad=1

其他机型请把 MatchDMIModalias 换成自己的机型标识:
cat /sys/class/dmi/id/modalias

生效与验证

重启桌面会话(注销重登 / 重启电脑)即可;也可以不重启,重新绑定 i2c 设备:

sudo sh -c 'echo "i2c-GXTP5100:00" > /sys/bus/i2c/drivers/i2c_hid_acpi/unbind; sleep 2; echo "i2c-GXTP5100:00" > /sys/bus/i2c/drivers/i2c_hid_acpi/bind'

验证:

libinput quirks list /dev/input/event11
# 应输出:ModelPressurePad=1

libinput debug-events --device /dev/input/event11
# 滑动时应出现 POINTER_MOTION

问题二:双击没有反应

症状

  • 单击正常
  • 快速双击桌面图标 / 文件夹打不开
  • 实测两次点击间隔约 520~850ms,系统不识别为双击

原因

系统的双击判定时间 com.deepin.xsettings double-click-time 只有 250ms(低于常见标准 400~500ms)。双击稍微慢一点,就被当成两次独立的单击。

解决

把双击判定时间调宽到 900ms:

# 应用实际读取的 XSETTINGS 双击时间(必改)
gsettings set com.deepin.xsettings double-click-time 900

# 触控板自身的 DoubleClick 设置(建议一起改,保持一致)
gdbus call --session --dest org.deepin.dde.InputDevices1 \
  --object-path /org/deepin/dde/InputDevice1/TouchPad \
  --method org.freedesktop.DBus.Properties.Set \
  org.deepin.dde.InputDevice1.TouchPad DoubleClick '<900>'

验证:双击文件夹 / 图标,能正常打开即可。数值可按个人习惯调整(500~1000 都行)。


问题三:两根手指按压 / 轻触打不开右键菜单

症状

  • 两根手指同时按压触控板,触发的是左键而不是右键
  • 两根手指轻点也没有右键菜单

原因

触控板点击方式被设成了 button-areas(按键区域):左键 / 右键由按压的位置决定,与手指数量无关,所以两指按压也触发左键。需要改成 clickfinger(1 指 = 左键,2 指 = 右键,3 指 = 中键)。

解决

方法一(立即生效,当前会话):

# 找到触控板设备 ID(名称含 GXTP5100)
xinput list

# 把点击方式改为 clickfinger(第 1 个值=button-areas 关,第 2 个值=clickfinger 开)
xinput set-prop <设备ID> "libinput Click Method Enabled" 8 0 1

注:部分系统 xinput set-prop 会报 BadMatch(xinput 1.6.x 与 XInput2 2.4 的兼容问题)。此时可用方法二,或直接用 XInput2 协议设置该属性(类型 INTEGER、格式 8、值 {0,1})。

方法二(永久生效,推荐):创建 /etc/X11/xorg.conf.d/90-gxtp5100-clickfinger.conf

# Goodix GXTP5100 触控板:启用 clickfinger,两指=右键
# 注意:此设备 udev 没有 ID_MODEL,MatchProduct 无法匹配,必须用 MatchIsTouchpad
Section "InputClass"
    Identifier "GXTP5100 clickfinger"
    MatchIsTouchpad "on"
    Driver "libinput"
    Option "ClickMethod" "clickfinger"
EndSection

重要坑点:这台触控板在 udev 里没有 ID_MODEL 属性(可用 udevadm info --query=property --name=/dev/input/event11 验证),而 Xorg 的 MatchProduct 只匹配 ID_MODEL,所以写成 MatchProduct "GXTP5100*" 永远匹配不上、重启后不生效。必须改用 MatchIsTouchpad "on"(与 Deepin 自带的 touchpad 类同一匹配方式)。

重启桌面会话后生效。验证:两根手指同时按一下触控板,应弹出右键菜单。

方法三(双保险,可选):登录自启脚本,即使 Xorg 配置意外没生效,登录后也会自动恢复右键。

  1. 创建脚本 ~/.local/bin/fix-touchpad-rightclick.py
#!/usr/bin/env python3
# 登录自启:把 GXTP5100 触控板点击方式设为 clickfinger(两指=右键)
import ctypes, ctypes.util, os, sys, time

for _ in range(20):
    if os.environ.get("DISPLAY") or os.path.exists("/tmp/.X11-unix/X0"):
        break
    time.sleep(0.5)

libx11 = ctypes.CDLL(ctypes.util.find_library("X11"))
libxi = ctypes.CDLL(ctypes.util.find_library("Xi"))
libx11.XOpenDisplay.restype = ctypes.c_void_p
libx11.XOpenDisplay.argtypes = [ctypes.c_char_p]
libx11.XInternAtom.restype = ctypes.c_ulong
libx11.XInternAtom.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int]
libx11.XFlush.argtypes = [ctypes.c_void_p]
libx11.XSync.argtypes = [ctypes.c_void_p, ctypes.c_int]
libx11.XCloseDisplay.argtypes = [ctypes.c_void_p]
libx11.XFree.argtypes = [ctypes.c_void_p]
libxi.XIChangeProperty.restype = ctypes.c_int
libxi.XIChangeProperty.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_ulong,
                                   ctypes.c_ulong, ctypes.c_int, ctypes.c_int,
                                   ctypes.c_void_p, ctypes.c_int]
libxi.XIGetProperty.restype = ctypes.c_int
libxi.XIGetProperty.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_ulong,
                                ctypes.c_long, ctypes.c_long, ctypes.c_int, ctypes.c_ulong,
                                ctypes.POINTER(ctypes.c_ulong), ctypes.POINTER(ctypes.c_int),
                                ctypes.POINTER(ctypes.c_ulong), ctypes.POINTER(ctypes.c_ulong),
                                ctypes.POINTER(ctypes.c_void_p)]

class XIAnyClassInfo(ctypes.Structure):
    pass
class XIDeviceInfo(ctypes.Structure):
    _fields_ = [("deviceid", ctypes.c_int), ("name", ctypes.c_char_p), ("use", ctypes.c_int),
                ("attachment", ctypes.c_int), ("enabled", ctypes.c_int),
                ("num_classes", ctypes.c_int),
                ("classes", ctypes.POINTER(ctypes.POINTER(XIAnyClassInfo)))]

libxi.XIQueryDevice.restype = ctypes.POINTER(XIDeviceInfo)
libxi.XIQueryDevice.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.POINTER(ctypes.c_int)]
libxi.XIFreeDeviceInfo.argtypes = [ctypes.POINTER(XIDeviceInfo)]
XIAllDevices, XISlavePointer = 0, 3

d = libx11.XOpenDisplay(None)
if not d:
    sys.exit("无法连接 X server")
prop = libx11.XInternAtom(d, b"libinput Click Method Enabled", 0)
int_atom = libx11.XInternAtom(d, b"INTEGER", 0)
ndev = ctypes.c_int(0)
info = libxi.XIQueryDevice(d, XIAllDevices, ctypes.byref(ndev))
if not info:
    sys.exit("XIQueryDevice 失败")
done = False
for i in range(ndev.value):
    dev = info[i]
    if dev.use != XISlavePointer:
        continue
    t = ctypes.c_ulong(); fmt = ctypes.c_int(); nitems = ctypes.c_ulong()
    ba = ctypes.c_ulong(); data = ctypes.c_void_p()
    status = libxi.XIGetProperty(d, dev.deviceid, prop, 0, 64, 0, 0,
                                 ctypes.byref(t), ctypes.byref(fmt),
                                 ctypes.byref(nitems), ctypes.byref(ba), ctypes.byref(data))
    if data:
        libx11.XFree(data)
    if status != 0 or nitems.value == 0:
        continue
    if "GXTP" not in (dev.name or b"").decode(errors="replace"):
        continue
    vals = (ctypes.c_ubyte * 2)(0, 1)
    libxi.XIChangeProperty(d, dev.deviceid, prop, int_atom, 8, 0, vals, 2)
    libx11.XFlush(d); libx11.XSync(d, 0)
    print(f"已设置设备 {dev.deviceid} ({dev.name.decode(errors='replace')}) 为 clickfinger")
    done = True
    break
libxi.XIFreeDeviceInfo(info)
libx11.XCloseDisplay(d)
sys.exit(0 if done else 1)
  1. 创建自启项 ~/.config/autostart/fix-touchpad-rightclick.desktop
[Desktop Entry]
Type=Application
Name=Fix touchpad right-click (clickfinger)
Comment=Set GXTP5100 touchpad click method to clickfinger
Exec=/home/wxbbi/.local/bin/fix-touchpad-rightclick.py
X-GNOME-Autostart-enabled=true
Terminal=false

脚本原理:用 XInput2 的 XIQueryDevice 枚举设备,找到名称含 GXTP5100 且带有 libinput Click Method Enabled 属性的设备,把属性值设为 {0,1}(button-areas 关、clickfinger 开)。


问题四:左右滑动不能翻页(补充说明)

  • 系统层面,双指左右滑动产生的水平滚动事件(按钮 6/7)是正常的,能正常送达应用
  • 必须用两根手指并排左右滑动;单指滑动只会移动光标,不会翻页
  • 浏览器里双指左右滑 = 前进 / 后退;部分阅读器 / PDF 软件需要应用自身支持水平滚动翻页
  • 如果想单指在边缘滑动也能滚动,可以在系统设置里开启"边缘滚动"

修改的系统设置项(详细清单)

以下为本指南实际修改/新增的系统设置项,全部可逆,未删除任何文件。

1. 系统设置(gsettings / dconf / D-Bus)

设置项 修改前 修改后 修改命令 持久性
com.deepin.xsettings double-click-time(双击判定时间) 250 900 gsettings set com.deepin.xsettings double-click-time 900 永久(写入 dconf)
触控板 DoubleClick(Deepin 触控板服务的双击间隔) 500 900 gdbus call --session --dest org.deepin.dde.InputDevices1 --object-path /org/deepin/dde/InputDevice1/TouchPad --method org.freedesktop.DBus.Properties.Set org.deepin.dde.InputDevice1.TouchPad DoubleClick '<900>' 永久(dde-session-daemon 保存)

2. X 输入设备属性(当前会话生效)

属性 修改前 修改后 说明
libinput Click Method Enabled(触控板点击方式) 1, 0(button-areas 按键区域) 0, 1(clickfinger 多指点按) 仅当前会话生效;重启后由下方 Xorg 配置文件自动恢复

设置命令:

xinput set-prop <触控板设备ID> "libinput Click Method Enabled" 8 0 1

xinput set-propBadMatch(xinput 1.6.x 与 XInput2 2.4 兼容问题),可用 XInput2 协议直接设置该属性(类型 INTEGER、格式 8、值 {0,1})。

3. 新增配置文件

文件 作用 持久性
/etc/libinput/local-overrides.quirks 声明 GXTP5100 为压力感应板(ModelPressurePad=1),修复光标不动 永久
/etc/X11/xorg.conf.d/90-gxtp5100-clickfinger.conf 开机自动应用 clickfinger 点击方式(两指=右键)。用 MatchIsTouchpad "on" 匹配(此设备 udev 无 ID_MODELMatchProduct 无效) 永久
~/.local/bin/fix-touchpad-rightclick.py + ~/.config/autostart/fix-touchpad-rightclick.desktop 登录自启双保险,自动把点击方式设为 clickfinger 永久

4. 排查过程中临时修改、已恢复的设置

设置项 说明
libinput Disable While Typing Enabled 排查"滑动无效"时曾临时关闭(0),排查后已恢复默认(1,打字时禁用触控板)

总结(改动清单)

项目 改动 说明
/etc/libinput/local-overrides.quirks 新增 识别 GXTP5100 为压力感应板,修复光标不动
com.deepin.xsettings double-click-time 250 → 900 放宽双击判定时间,修复双击无效
触控板 DoubleClick 500 → 900 与上保持一致
/etc/X11/xorg.conf.d/90-gxtp5100-clickfinger.conf 新增 启用 clickfinger,两指=右键(用 MatchIsTouchpad 匹配,此设备无 ID_MODEL)
~/.local/bin/fix-touchpad-rightclick.py + ~/.config/autostart/fix-touchpad-rightclick.desktop 新增 登录自启双保险,自动恢复 clickfinger

以上修复不删除任何文件,只新增配置文件、修改系统设置项,风险很低;如不需要,删除对应配置文件、改回设置值即可恢复。


关键词:Deepin、UOS、ThinkBook 16 G7+、Goodix GXTP5100、27C6:01E9、libinput、触控板、压力感应板、Force Pad、双击、右键、clickfinger

Reply Favorite View the author
All Replies

No replies yet