本文摘要
Touch-Up(shueber/Touch-Up)是一个 macOS 用户态触摸屏驱动,由 Sebastian Hueber 开发:市面上绝大多数触摸屏都遵循 USB HID,在 Windows 上插上就能用,接到 Mac 上却毫无反应,Touch-Up 就是补这个缺口——读取 HID 原始数据、解析成触摸点、注入成系统级鼠标事件,不需要内核扩展,安装后授予辅助功能权限即可使用。它有两个形态:Touch Up 工具 App(默认交互借鉴 iPadOS:轻点=点击、拂动=滚动、手指稍作停留再移动=拖拽、双指捏合=缩放、双指点击=右键,还可以开启「触摸窗口把它带到前台」)和 TouchUpCore 框架(把多点触摸数据暴露给开发者,App 本身就是集成示例,可参考 DebugView)。兼容性方面官方说法是「任何在 Windows 上能用的触摸屏都应该能用」,并在 Iiyama TF3222MC、T2336MSC-B2 和 3M C4667PW 上做过测试,Releases 页面提供带公证的构建包。本文记录我在 Fork(OnesZhang/Touch-Up,分支 feature/multi-finger-swipes,commit d7f2933,8 个文件约 +933/−15)上提交的功能:给三指/四指手势增加可自定义的键盘快捷键映射。做法分两层:TouchUpCore 里扩展 12 种可映射手势(三/四指上、下、左、右滑动 8 种,轻点 2 种,长按 2 种),委托协议 TUCTouchDelegate 新增 performKeyboardShortcutForGesture:(滑动识别完成触发一次)与 beginKeyboardHoldForGesture:/endKeyboardHoldForGesture:(长按按下映射键、手指全部抬起才松开),一次手势会话互斥地只判定为滑动/轻点/长按之一,手指移动超过阈值默认 10mm 判为滑动、几乎没动就抬起判为轻点、停住不动默认 0.35s 判为长按;手指按在屏上的整个会话期间鼠标事件被抑制,所以手势不会顺带移动光标或误点击。App 层整理了 48 条 macOS 常用快捷键目录 ShortcutPreset.catalog(含 8 个媒体键,走 NX_KEYTYPE_*),按调度中心与空间、窗口管理、应用切换、导航编辑、系统、媒体与功能键分类,每个手势可在设置里绑定任意预设或设为 Off 保留原光标行为,默认值接近触控板经典体验:三/四指滑动映射调度中心与空间切换、长按映射 fn、轻点关闭;映射持久化在 UserDefaults,设置界面新增 Multi-Finger Shortcuts 分区并适配新旧两套 SwiftUI 布局。此外顺手修了三个 macOS 兼容性问题:缺少输入监控权限时 HID 注册对 NULL 队列无防护导致启动崩溃(现在优雅降级并在设置页顶部显示权限横幅,点 Grant Access 深链到系统隐私面板)、合成方向键缺少真实方向键的 numericPad 标志且控制类快捷键需要 SecondaryFn 标志否则会被调度中心与空间功能丢弃(参考 SO 61872579 / 45704155)、发送合成快捷键后修饰键状态残留会把后续普通点击变成右键(现在显式释放修饰键,fn 的按住状态用不带 SecondaryFn 的 flagsChanged 释放事件清除);并新增 GitHub Actions 工作流在 macOS runner 上自动构建 App,Fork 上还会把产物挂到滚动的 ci-build release 便于直接下载。

原作者仓库:shueber/Touch-Up | 我的仓库(Fork):OnesZhang/Touch-Up | 本次修改所在分支:feature/multi-finger-swipes

📌

该文章由丸子引导AI辅助制作生成,如有改进意见,欢迎评论区留言。

Touch-Up 是什么

Touch-Up 是一个 macOS 用户态触摸屏驱动,由 Sebastian Hueber(shueber)开发。它的出发点很朴素:市面上绝大多数触摸屏都遵循 USB HID 标准,在 Windows 上插上就能用,但接到 Mac 上却毫无反应——macOS 并不原生支持这些外接触摸屏。

Touch-Up 以用户空间驱动的方式解决了这个问题:它读取触摸屏通过 USB HID 上报的原始数据,将其解析为一个个”触摸点”,再注入成系统级的鼠标事件。整个过程不需要内核扩展,不需要降级安全性,安装后授予辅助功能权限即可使用。

它有两个形态:

  1. Touch Up 工具 App:让你直接用手指操作 Mac。默认交互逻辑借鉴了 iPadOS——
    • 轻点 = 点击
    • 快速拂动 = 滚动
    • 手指稍作停留再移动 = 拖拽
    • 双指捏合 = 缩放
    • 双指点击 = 右键
    • 还有一个很讨喜的选项:触摸窗口即可将其带到前台(类似 iPadOS 的台前调度)
  2. TouchUpCore 框架:把多点触摸数据暴露给开发者,方便在 macOS 上做多点触摸原型——游戏、交互研究等场景都可以直接集成。App 本身就是一个集成示例(可参考其中的 DebugView)。

兼容性方面,官方说法是”任何在 Windows 上能用的触摸屏都应该能用”,并在 Iiyama、3M 的几款商用触摸屏上做过测试。原作者还提供了带公证的构建包,可以在 Releases 页面 直接下载。

在接触到这个项目之前,我为了在 Mac 上用触摸屏,试过不少零散方案,要么是内核扩展(新系统上早就不让装了),要么行为怪异、滚动和缩放都不正常。Touch-Up 是我用过最接近”即插即用”的方案,而且代码结构清晰、完全用户态,所以决定基于它继续做点事情。

我(OnesZhang)修改了什么

我 Fork 了原仓库,并在 feature/multi-finger-swipes 分支上提交了一个功能(commit d7f2933),核心一句话概括:

给三指 / 四指手势增加了可自定义的键盘快捷键映射。

改动规模:8 个文件,约 +933 / -15 行。

1. 三指 / 四指手势识别(TouchUpCore)

原版的多指手势主要服务于光标操作(点击、拖动、滚动、捏合)。我在 TouchUpCore 中扩展了手势枚举,新增了 12 种可映射手势:

  • 三指 / 四指 滑动(上、下、左、右),共 8 种
  • 三指 / 四指 轻点,共 2 种
  • 三指 / 四指 长按,共 2 种

同时在委托协议(TUCTouchDelegate)里新增了三个回调:

  • performKeyboardShortcutForGesture: —— 滑动识别完成时触发一次
  • beginKeyboardHoldForGesture: / endKeyboardHoldForGesture: —— 长按开始时按下映射键、手指全部抬起时松开

一次手势会话只会被判定为滑动、轻点、长按三者之一,互斥且只触发一次,避免一次滑动连发多遍快捷键。

2. 快捷键目录与注入(App 层)

我整理了一个精选的 macOS 常用快捷键目录(ShortcutPreset.catalog,共 48 条,其中音量、亮度、播放控制等 8 条走 NX_KEYTYPE_* 媒体键),按类别覆盖:

类别例子
调度中心与空间调度中心 ⌃↑、应用窗口 ⌃↓、左右切换空间 ⌃←/⌃→、移动窗口到其他空间
窗口管理关闭 ⌘W、最小化 ⌘M、退出 ⌘Q、隐藏 ⌘H、循环切换窗口 ⌘`
应用切换⌘⇥ / ⌘⇧⇥
导航编辑翻页、行首行尾、词间移动、复制剪切粘贴撤销、全选
系统Spotlight ⌘Space、锁定屏幕 ⌃⌘Q、截图 ⌘⇧3/4/5、Launchpad、显示桌面
媒体与功能键音量、静音、亮度、播放控制,以及 fn 键

每种手势都可以在设置里绑定任意一个预设,或者设为 Off 保留原有的光标行为。默认值接近 macOS 触控板的经典体验:三/四指滑动映射为调度中心和空间切换,长按默认映射为 fn 键,轻点默认关闭。

手势判定规则:

  • 手指移动超过阈值(默认 10mm)→ 触发滑动快捷键(触发一次)
  • 没怎么移动就抬起 → 轻点
  • 停住不动(默认 0.35s)→ 长按,按住映射键不放,直到手指抬起才松开
  • 手指按在屏上的整个会话期间,鼠标事件被抑制——手势不会顺带移动光标或产生误点击

映射持久化在 UserDefaults 里,设置界面新增了 “Multi-Finger Shortcuts” 分区,新旧两套 SwiftUI 设置布局都做了适配。

一律保持原版行为。 驱动层是按指数组独立开关的:某个指数组里只要有任意一条映射才会进入手势模式,全部为 Off 就完全退回原版光标管线——所以「三指配了、四指没配」不会互相影响,改动范围严格跟着配置走。

3. 顺手修掉的几个坑

测试过程中撞上了几个 macOS 兼容性问题,一并修复了:

  • 缺少”输入监控”权限时启动崩溃:HID 设备注册时没有对 NULL 队列做防护,导致 App 一启动就崩。现在会优雅降级,并在设置界面顶部显示一条权限横幅,点击 “Grant Access” 直接深链到系统隐私设置面板。
  • 合成方向键被调度中心忽略:真实的方向键事件带 numericPad 标志,不带这个标志的合成事件会被调度中心和”空间”功能丢弃;同理,控制类快捷键需要 SecondaryFn 标志(参考 SO 61872579 / 45704155)。合成事件现在会补上正确的标志。
  • 修饰键状态残留:发送完合成快捷键后及时释放修饰键状态,否则后续的普通点击会被系统当成右键点击;fn 键的”按住”状态用一次不带 SecondaryFn 的 flagsChanged 释放事件来清除,与物理松键的形态一致。
  • 新增 GitHub Actions 工作流(.github/workflows/build.yml),在 macOS runner 上自动构建 App,方便后续合并前验证;Fork 上还会把构建产物挂到一个滚动的 ci-build release,可以直接下载来试。

为什么值得 Fork 一份

Touch-Up 本体已经把最难的部分做完了:用户态 HID 解析、多屏支持、设备独占、旋转补偿、边缘死区……这些它都有。我加的这层”手势 → 快捷键”本质上是把触摸屏从”能用鼠标”推进到”能享受触控板级手势”——毕竟外接触摸屏的用户里,不少是把 Mac 当工作站、离不开调度中心和多空间切换的人。

欢迎试用、提 issue 或 PR:

致谢

感谢 Sebastian Hueber 开源了 Touch-Up。本 Fork 保留原有 MIT License,所有底层驱动与框架设计的功劳都属于原作者;我新增的代码同样以 MIT 协议开放。