转用 Linux 后一直都比较怀念 macOS 上丝滑的三指拖拽效果,鉴于近几年出的 Windows 本子触控板面积以及跟手性肉眼可见的改善了很多,我觉得是时候在 Linux 上折腾下触控板手势了。
After switching to Linux, I've been missing the smooth three-finger drag experience from macOS. Given that recent Windows laptops have significantly improved touchpad size and responsiveness, I decided it was time to tackle touchpad gestures on Linux.
调研与选型
说干就干,放狗搜了一下,发现类似的实现还不少:
Research and Selection
Let's dive in. After some searching, I found quite a few similar implementations:
- https://github.com/riley-martin/gestures
- https://github.com/bulletmark/libinput-gestures
- https://github.com/Coffee2CodeNL/gebaar-libinput
- https://github.com/osleg/gebaar-libinput-fork
- https://github.com/iberianpig/fusuma
- https://github.com/marsqing/libinput-three-finger-drag
基本上就是两种实现思路:
- 解析
libinput debug-events输出,判断手势进而借用类似xdotool之类的工具发送具体的键盘组合或者鼠标点击或位移指令 - 直接调用
libinputAPI,明显此方法性能最优
There are basically two implementation approaches:
- Parse
libinput debug-eventsoutput, detect gestures, then use tools likexdotoolto send keyboard combinations or mouse click/move commands - Directly call
libinputAPI - this method obviously has the best performance
核心需求
我最在意的手势莫过于三指拖拽,实现这个功能有两个注意的点:
- 拖拽起止会有持续不断的位移指令发出,所以通过 fork shell 不间断发送位移指令的操作是非常低效的,见这个讨论
- 为了媲美 macOS 的丝滑拖拽效果,必须使用尽可能高效的实现
Core Requirements
The gesture I care about most is three-finger drag. There are two key considerations for implementing this:
- Dragging involves continuous position update commands, so forking shells to send movement commands non-stop is very inefficient (see this discussion)
- To match macOS's smooth dragging experience, we must use the most efficient implementation possible
实现方案
于是乎我选择了一个 Rust 实现开抄,负责实现 API 级别的触控手势识别,然后缝合了另一个 Rust 实现,负责实现 API 级别的拖拽效果。
Implementation Approach
I chose a Rust implementation as the base for API-level touch gesture recognition, then integrated another Rust implementation to handle API-level dragging effects.
目前项目已发展到 v0.8.1 版本,主要改进包括:
- 双平台支持:同时支持 X11 和 Wayland(自动检测)
- 性能优化:
- X11 直接使用 libxdo API,延迟最小
- Wayland 优化 ydotool 集成,60 FPS 节流
- 4 线程池防止 PID 耗尽
- 正则缓存(once_cell::Lazy)
- 事件缓存(1秒)减少配置查找
The project has evolved to v0.8.1 with major improvements:
- Dual-platform support: Both X11 and Wayland (auto-detection)
- Performance optimizations:
- X11 uses libxdo API directly for minimal latency
- Wayland optimized ydotool integration with 60 FPS throttling
- 4-worker thread pool preventing PID exhaustion
- Regex caching via once_cell::Lazy
- 1-second event caching for config lookups
性能表现
终极缝合以后的产物效果还不错,基本符合预期:
Performance Metrics
The final stitched-together product works quite well and basically meets expectations:
-
CPU 占用极低
- 极限情况:疯狂三指拖拽某窗口,本 fork 实现 CPU 占用不到 1%
- 原实现 5~10%
- Python、Ruby 等实现 20%+
-
资源占用
- 内存占用不到 5MB
- 程序体积不到 2MB
- 无多余依赖
-
拖拽体验丝滑(如果觉得不够滑,那一定是你本子的触控板太渣)
-
重放手指后支持继续拖动(延迟时间
mouse_up_delay可配) -
拖拽速度
acceleration可配置 -
Extremely low CPU usage
- Extreme case: frantically three-finger dragging a window, this fork uses <1% CPU
- Original implementation: 5-10%
- Python/Ruby implementations: 20%+
-
Resource footprint
- Memory usage <5MB
- Binary size <2MB
- No extra dependencies
-
Smooth dragging experience (if it's not smooth enough, your touchpad is probably to blame)
-
Supports continued dragging after lifting fingers (delay time
mouse_up_delayis configurable) -
Configurable drag speed via
acceleration
安装使用
依赖安装
Ubuntu/Debian:
|
|
Arch Linux:
|
|
Installation & Usage
Install Dependencies
Ubuntu/Debian:
|
|
Arch Linux:
|
|
安装程序
方法 1:直接下载预编译二进制
|
|
方法 2:Cargo 安装
|
|
方法 3:手动编译
|
|
Install Binary
Method 1: Download pre-compiled binary
|
|
Method 2: Install via Cargo
|
|
Method 3: Manual compilation
|
|
配置说明
生成配置文件
|
|
Configuration
Generate Config File
|
|
配置示例
配置文件使用 KDL 格式,示例:
// 三指拖拽(X11 & Wayland 通用)
gesture "drag" swipe any {
fingers 3
acceleration 1.0 // 拖拽速度
mouse_up_delay 500 // 抬手后延迟(ms)
}
// 四指上滑切换工作区
gesture "switch-workspace-up" swipe up {
fingers 4
exec "xdotool" "key" "super+Page_Up"
}
// 四指下滑切换工作区
gesture "switch-workspace-down" swipe down {
fingers 4
exec "xdotool" "key" "super+Page_Down"
}
// 四指左右滑动切换虚拟桌面
gesture "desktop-left" swipe left {
fingers 4
exec "xdotool" "key" "ctrl+alt+Left"
}
gesture "desktop-right" swipe right {
fingers 4
exec "xdotool" "key" "ctrl+alt+Right"
}
// 捏合缩放(Pinch)
gesture "zoom-in" pinch in {
fingers 2
exec "xdotool" "key" "ctrl+plus"
}
gesture "zoom-out" pinch out {
fingers 2
exec "xdotool" "key" "ctrl+minus"
}
Configuration Examples
Config file uses KDL format, example:
// Three-finger drag (X11 & Wayland)
gesture "drag" swipe any {
fingers 3
acceleration 1.0 // Drag speed
mouse_up_delay 500 // Delay after lifting (ms)
}
// Four-finger swipe up to switch workspace
gesture "switch-workspace-up" swipe up {
fingers 4
exec "xdotool" "key" "super+Page_Up"
}
// Four-finger swipe down to switch workspace
gesture "switch-workspace-down" swipe down {
fingers 4
exec "xdotool" "key" "super+Page_Down"
}
// Four-finger horizontal swipe for virtual desktops
gesture "desktop-left" swipe left {
fingers 4
exec "xdotool" "key" "ctrl+alt+Left"
}
gesture "desktop-right" swipe right {
fingers 4
exec "xdotool" "key" "ctrl+alt+Right"
}
// Pinch to zoom
gesture "zoom-in" pinch in {
fingers 2
exec "xdotool" "key" "ctrl+plus"
}
gesture "zoom-out" pinch out {
fingers 2
exec "xdotool" "key" "ctrl+minus"
}
Wayland 配置注意
Wayland 下需要使用 ydotool 替代 xdotool:
// Wayland 示例
gesture "switch-workspace" swipe up {
fingers 4
exec "ydotool" "key" "125:1 33:1 33:0 125:0" // Super+Page_Up
}
Wayland Configuration Notes
On Wayland, use ydotool instead of xdotool:
// Wayland example
gesture "switch-workspace" swipe up {
fingers 4
exec "ydotool" "key" "125:1 33:1 33:0 125:0" // Super+Page_Up
}
Wayland 下必须启动 ydotoold 守护进程:
|
|
On Wayland, the ydotoold daemon must be running:
|
|
运行程序
Systemd 服务(推荐)
|
|
Running the Program
Systemd Service (Recommended)
|
|
手动运行
|
|
Manual Execution
|
|
常见问题
权限问题
需要将用户加入 input 组:
|
|
Common Issues
Permission Issues
Add user to input group:
|
|
三指拖拽不生效
X11:
|
|
Wayland:
|
|
Three-Finger Drag Not Working
X11:
|
|
Wayland:
|
|
桌面环境冲突
某些桌面环境(如 GNOME、KDE)自带手势功能,需要禁用:
GNOME:
|
|
KDE: 系统设置 → 输入设备 → 触摸板 → 禁用手势
Desktop Environment Conflicts
Some DEs (GNOME, KDE) have built-in gestures that need to be disabled:
GNOME:
|
|
KDE: System Settings → Input Devices → Touchpad → Disable gestures
Wayland 下 CPU 占用高
已在 v0.8.1 优化,默认 60 FPS 节流,CPU 占用应在 5% 以内
如果仍然偏高,可降低刷新率:
// 在配置文件中调整(仅影响 Wayland)
// 降低到 30 FPS
fps_limit 30
High CPU Usage on Wayland
Optimized in v0.8.1 with default 60 FPS throttling, CPU usage should be <5%
If still high, reduce frame rate:
// Adjust in config (Wayland only)
// Reduce to 30 FPS
fps_limit 30
项目链接
- GitHub: https://github.com/ferstar/gestures
- 最新发布: https://github.com/ferstar/gestures/releases
- 问题反馈: https://github.com/ferstar/gestures/issues
Project Links
- GitHub: https://github.com/ferstar/gestures
- Latest Release: https://github.com/ferstar/gestures/releases
- Issue Tracker: https://github.com/ferstar/gestures/issues
理论上支持所有使用 libinput 触摸板驱动的 Linux 桌面环境(GNOME、KDE、i3、Sway 等)。
除 X11 和 Wayland 的「三指拖拽」以外,其他功能与原作基本一致,但性能和稳定性有大幅提升。
In theory, it supports all Linux desktop environments using libinput touchpad drivers (GNOME, KDE, i3, Sway, etc.).
Beyond the "three-finger drag" functionality for X11 and Wayland, other features remain largely consistent with the original implementation, but with significantly improved performance and stability.
Enjoy!
|
|