我 ThinkPad 笔记本电脑的小红点(指点杆,Trackpoint)经常漂移,且漂移时力气巨大,根本拉不回来。虽然禁用设备就能解决问题,但触摸板上方的实体按键与小红点隶属同一输入设备,也会一并被禁用。
实在不想抛弃实用的实体按键,遂(借助 ChatGPT)思考解决方案。
探索:使用 udevadm 配置设备#
udevadm 是 Linux 系统中用于管理、监控和调试 udev(用户空间设备管理器)的命令行工具。它是 udev 架构的核心组成部分之一,常用于设备事件处理、规则调试和系统诊断。
首先尝试通过 udevadm 对设备属性进行修改,观察能否单独禁用小红点。通过 libinput list-devices 寻找 TrackPoint 设备:
> sudo libinput list-devices
...(Other Devices)
Device: Elan TrackPoint
Kernel: /dev/input/event5
Group: 7
Seat: seat0, default
Capabilities: pointer
......
Accel profiles: flat *adaptive custom
Rotation: n/a
...(Other Devices)bash定位到输入设备名称后,即可使用 udevadm 规则修改设备属性。
在 udev 的规则文件夹中新建规则并编辑:
sudo nano /etc/udev/rules.d/99-trackpoint-modify.rulesbash写入如下所示的规则即可修改把 Trackpoint 的灵敏度降到最低,注意设备名与上文查询到的保持一致:
ATTRS{name}=="Elan TrackPoint", ENV{LIBINPUT_ATTR_ACCEL_PROFILE}="flat", ENV{LIBINPUT_ATTR_ACCEL_SPEED}="-1"plaintext如果想完全禁用,可以写入如下规则(会同时禁用实体按键):
ATTRS{name}=="Elan TrackPoint", ENV{LIBINPUT_IGNORE_DEVICE}="1"plaintext在这之后,输入命令应用规则,重启即可。
sudo udevadm control --reload-rules
sudo udevadm triggerbash然而该种方法并不能单独禁用小红点,达到最优体验。在 ChatGPT 的介绍下,找到了最优解决方案。
最终方案:使用 Python 脚本过滤设备事件#
发现 udev 自带的设备配置项无法很好地满足我们的需求,我们可以撰写一个Python脚本,接管 Trackpoint 设备,并过滤掉小红点的移动事件,只保留按键事件,从而达到部分禁用功能的目的。
编写 Python 程序#
Python3 的 evdev 库提供了 Linux下通用输入事件的接口。借助这个包,我们可以接管 Trackpoint 设备,并自定义功能。
使用如下命令安装 evdev 库:
sudo apt install python3-evdevbash在指定目录下新建一个 Python 文件,编写程序:
nano ~/Applications/filter_trackpoint.pybash#!/usr/bin/env python3
from evdev import InputDevice, UInput, ecodes, list_devices
import subprocess
# 需要注意,/dev/input/eventX 编号在每次启动时可能变化,因此不建议写死路径
# 可通过 udev 属性(如 `ID_INPUT_POINTINGSTICK=1`)动态查找设备。
def is_trackpoint(dev_path):
out = subprocess.check_output(
["udevadm", "info", dev_path],
text=True
)
# 拥有“ID_INPUT_POINTINGSTICK=1” 配置项的即目标设备
return "ID_INPUT_POINTINGSTICK=1" in out
# 此处将枚举所有设备,寻找 Trackpoint 设备并返回路径
def find_trackpoint():
for path in list_devices():
if is_trackpoint(path):
return path
raise Exception("TrackPoint not found")
DEVICE = find_trackpoint()
print("Using device:", DEVICE)
# 通过 evdev 接管设备事件流(grab)
dev = InputDevice(DEVICE)
dev.grab()
# 创建虚拟设备(复制能力)
ui = UInput.from_device(dev, name="Filtered TrackPoint")
print("Started filtering TrackPoint...")
for event in dev.read_loop():
# 丢弃移动事件
if event.type == ecodes.EV_REL and event.code in (ecodes.REL_X, ecodes.REL_Y):
continue
# 其他全部透传(按键等)
ui.write_event(event)
ui.syn()python此时运行程序无报错,TrackPoint 被禁用,且物理按键正常工作,说明操作成功。
sudo python3 ~/Applications/filter_trackpoint.pyplaintext设置 systemd 服务#
为避免每次使用时都需要手动开启,我们可以将其注册为系统服务,后台自启。只需在文件夹中新建一个服务:
sudo nano /etc/systemd/system/trackpoint-filter.servicebash然后写入相关配置(注意替换脚本路径):
[Unit]
Description=TrackPoint Filter
After=multi-user.target
[Service]
ExecStart=/usr/bin/python3 /path/to/filter_trackpoint.py
Restart=always
[Install]
WantedBy=multi-user.targetplaintext接着启动服务即可:
sudo systemctl daemon-reload
sudo systemctl enable --now trackpoint-filterbash后记#
相比在 Windows 上依赖驱动层行为,Linux 提供了更开放的输入设备接口, 允许用户在用户态对输入事件进行精细控制,这也是本方案能够实现的基础。
在 Windows 上重装不同版本驱动无数次、尝试无数遍都没能解决的问题,在 Linux 上用一个小脚本就轻松搞定了。
本方案的运行环境:
- 硬件设备:ThinkPad T480s
- 操作系统:Ubuntu 24.04 (GNOME桌面环境,基于Wayland)
- Python 3.12.3