ShikiPad 是面向有线 PS5 DualSense 的 Windows 原生手柄键鼠映射工具。当前版本仅支持 DualSense USB;键盘和鼠标输出依赖 Interception。
- 默认参数集中在
src/Config.cs。当前程序直接new Config(),没有读取 JSON 配置文件;修改参数后需要重新构建和发布。 - 键层字符表位于
src/MappingEngine.cs。 - 触控板手势识别、区域归属、连发、按压互斥和快捷键输出位于
src/MapperForm.cs。 - 鼠标和滚轮积分分别位于
src/RightStickMouseIntegrator.cs、src/LeftStickScrollIntegrator.cs。 Enabled = true是启动时默认启用状态;Interception 输出固定使用扫描码,不再提供无效的虚拟键码开关。
| 目录或文件 | 用途 |
|---|---|
src/ |
程序源码 |
tests/ |
逻辑测试 |
assets/ |
图标与程序清单等构建资源 |
driver/ |
Interception 驱动安装程序 |
docs/ |
发布记录与第三方许可说明 |
scripts/ |
开发和正式发布脚本 |
ShikiPad.exe、interception.dll、install_driver.bat |
根目录可直接使用的程序与安装文件 |
ShikiPad.zip |
本地发布产物;位于根目录但被 Git 忽略 |
请使用官方 DualSense 手柄并通过 USB 连接。当前版本不支持蓝牙、Xbox、DualShock 4 或其他手柄模式。完整触控板报告、触点 ID、静音键等功能也依赖 DualSense USB HID 报告。
| 模式 | 支持情况 | 限制 |
|---|---|---|
| DualSense USB | 按键、摇杆、扳机、Home、触控板按压/手势、Create/Options、静音键 | 启动 ShikiPad 前先连接手柄 |
| 其他模式 | 不支持 | 不提供兼容回退 |
ShikiPad 必须通过 Interception 输出键盘和鼠标,不会回退到 SendInput。
将下面这句话复制给支持本机终端和文件操作的 Agent:
按照 README 帮我安装 https://github.com/ForestOuting/ShikiPad.git
安装过程中遇到 UAC、驱动安装和重启时,仍需按 Agent 的提示手动确认。
首次使用请严格按以下顺序操作,并在确认基础映射正常后再配置 HidHide:
-
将发布包完整解压到固定目录,例如
C:\ShikiPad。不要直接在 ZIP 压缩包中运行程序;确保ShikiPad.exe、interception.dll、install_driver.bat和driver文件夹保持在解压后的原有相对位置。 -
安装 x64 版
.NET 8 Desktop Runtime;当前单文件程序是依赖框架发布,不是自包含运行时。 -
使用可传输数据的 USB 线连接官方 DualSense,并在 Windows 中确认手柄已经被识别。启动 ShikiPad 前保持手柄连接;不要使用蓝牙模式。
-
在解压目录中右键
install_driver.bat,选择“以管理员身份运行”。等待脚本明确显示安装完成和必须重启的提示后再关闭窗口。 -
从 Windows 电源菜单选择“重启”。请执行真正的重新启动,不要用“关机后再开机”代替;重启完成前不要启动 ShikiPad。
-
重启后重新确认 DualSense 仍通过 USB 连接,然后使用以下任一方式启动 ShikiPad:
-
在文件资源管理器中右键
C:\ShikiPad\ShikiPad.exe,选择“以管理员身份运行”。 -
打开管理员 PowerShell,执行:
Set-Location C:\ShikiPad .\ShikiPad.exe
-
-
确认 UAC 中显示的程序路径是
C:\ShikiPad\ShikiPad.exe,然后允许启动。保持 ShikiPad 控制台窗口打开;关闭窗口会退出映射程序。 -
先验证基础映射:右摇杆移动鼠标,L3/R3 触发鼠标左键/右键,左摇杆正上或正下控制滚轮。三项均正常后,首次安装即完成。
以后使用时,只需先用 USB 连接 DualSense,再以管理员身份运行同一路径下的 ShikiPad.exe;不需要重复安装 Interception。ShikiPad 在同一 Windows 会话中只运行一个实例。
基础映射验证成功后,再用 HidHide 隐藏 DualSense,避免系统或游戏产生双重输入:
- 在
Applications中加入ShikiPad.exe的准确路径。 - 取消
Inverse application cloak。 - 在
Devices中勾选对应 DualSense;正常会出现红色锁图标。 - 勾选
Filter-out disconnected、Gaming devices only、Enable device hiding。 - 关闭 HidHide 后重新插拔手柄。
如果需要让 Windows 或游戏重新直接识别手柄,重新启用 Inverse application cloak 或关闭 Enable device hiding,然后重新插拔。
正式打包后,发布压缩包会生成在本地仓库根目录的 ShikiPad.zip。该文件已被 Git 忽略,不会提交到仓库;正式发布时将它作为 GitHub Releases 附件上传。压缩包包含:
| 文件 | 用途 |
|---|---|
driver/install-interception.exe |
Interception 驱动安装器 |
install_driver.bat |
驱动安装脚本 |
ShikiPad.exe |
单文件主程序 |
interception.dll |
Interception 运行库 |
README.md |
中文说明文档 |
RELEASE_NOTES.md |
版本记录 |
THIRD_PARTY_NOTICES.md |
Interception 来源与第三方许可说明 |
SHA256SUMS.txt |
发布包内文件的 SHA-256 校验值 |
BUILD_INFO.txt |
发布版本、源码提交与工作树状态 |
shiki.ico / ShikiPad.manifest |
图标和程序清单 |
正式打包使用 powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\publish_release.ps1。脚本会要求 Git 工作树干净、记录源码提交、重新发布当前工作树、校验 V5.2 文件版本、重建文件清单,并在根目录生成被 Git 忽略的 ShikiPad.zip;该 ZIP 只用于 GitHub Release,不应加入 Git 提交。脚本默认拒绝没有有效 Authenticode 签名的主程序;只有制作内部测试包时才应在命令末尾显式传入 -AllowDirty -AllowUnsigned。shikipad.default 已删除,不属于程序输入,也不会进入新发布包。
开机自启动需在管理员 PowerShell 中执行:
.\ShikiPad.exe --install-startup取消自启动:
.\ShikiPad.exe --uninstall-startup安装命令会创建名为 ShikiPad 的最高权限计划任务,并使用当前目录中的程序路径。移动文件夹后需要重新执行安装命令。普通“启动”文件夹无法可靠地绕过 UAC,因此不推荐。
| 页面 | Enter | Esc |
|---|---|---|
| 主界面 | 打开映射说明 | 退出 ShikiPad |
| 映射说明 | 返回主界面 | 退出 ShikiPad |
关闭控制台窗口也会退出,并释放程序保持中的键盘和鼠标输入。
| 手柄输入 | 输出 |
|---|---|
| 右摇杆 | 鼠标移动 |
| L3 / R3 | 鼠标左键 / 右键;R3 按下时冻结光标 60 ms |
| 左摇杆上 / 下扇区 | 鼠标滚轮 |
| 左摇杆左上 / 左下 / 右上 / 右下 | Left Shift / Ctrl / Win / Left Alt |
| Create / Options | Right Alt / Right Ctrl |
| Home 短按 / 长按 | 开关蓄力锁定 / 按住期间保持蓄力 |
| 静音键短按 / 长按 | 开关 Caps/Fn 模式 / 启用或禁用 ShikiPad |
Home 蓄力可收集多个左摇杆修饰键。先触发修饰键再短按 Home,会把已经收集的修饰键锁定给下一次符合条件的动作;这条蓄力关系不受独立 45 ms 修饰绑定窗口限制。能消费锁定的只有八个动作位置在全部键层中的输出以及 L3/R3 鼠标键;触控板 Delete、Backspace、Caps Lock 不会解除锁定。形成锁定时没有修饰键,则必须再短按 Home 取消。Caps/Fn 把未带 Shift 的 1..0 - = 转成 F1..F12,把小写字母转成带 Shift 的大写字母;只有实际完成上述转换的动作才会自动关闭 Caps/Fn,其他输出不会影响该模式。
Base 只表示在没有按住任何 L1/R1 肩键或 L2/R2 扳机键时,方向键和四个图案键这八个位置对应的 ↑ → Tab Esc ← ↓ Space Enter。肩键与扳机键只负责选择单层或组合层;触控板按压、Home、静音键、L3/R3 鼠标键都属于各自的独立模块,不属于 Base,也不参与键层选择。
修饰键来源只有左摇杆四个斜向扇区的 Left Shift、Left Ctrl、Left Win、Left Alt,以及 Create/Options 的 Right Alt、Right Ctrl。独立的 45 ms 修饰绑定只覆盖两类输入:L3/R3 鼠标键,以及方向键/图案键这八个动作位置在 Base、单层和组合层中的全部输出。Home、触控板三个按压键、静音键、摇杆滚轮、右摇杆移动和触控板滑动都不进入该窗口。
键层先完全按照自己的 45/15/35/20/30 ms 规则解析,修饰键不会获得键层优先级,也不会冻结、回退或改写动作所属键层。动作按下时已经存在的修饰键,或动作按下后 45 ms 内出现的修饰键,只与最终由纯键层逻辑解析出的输出绑定。
绑定归属于动作本身:单次虚拟点按会由修饰键完整包住;非连发的真实保持输出和 L3/R3 会让绑定引用保持到对应动作释放。Base 方向键等连发输入采用完整组合脉冲:首发以及之后每个连发节拍都会依次按下绑定修饰键和动作键,再依次释放动作键和该次绑定修饰键;因此不会出现修饰键一直保持、期间只重复动作键的状态。物理修饰键即使提前松开,已经记录的绑定掩码仍会用于后续每个连发脉冲,直到动作键本身松开。Home 只运行原有蓄力状态机,不作为 45 ms 窗口的被绑定动作;蓄力已经锁住的左摇杆修饰键仍会随 Base 方向键的每个连发脉冲一起触发和释放。
触控板三个按压键始终输出自己模块的 Delete、Backspace 或 Caps Lock,从不查询肩键/扳机键层,也不等待或捕获 45 ms 修饰绑定。
程序退出、断开连接、禁用或发生映射异常时,都会统一清除尚未结算的动作并释放由 ShikiPad 保持的输入。
唯一的固定节拍调度线程每隔约 1 ms 读取 HID 线程刚发布的最新完整状态。HID 线程只解析报告和替换 ControllerState 引用,不执行映射或驱动发送,也不存在第二条映射入口与轮询锁竞争。各模块按以下固定顺序结算:
- 触控板按压
Delete/Backspace/Caps Lock - 触控板手势快捷键
- 左摇杆四个斜向修饰键,以及 Create/Options 修饰键
- L3/R3 鼠标左右键
- 八个动作位置在全部键层中的键盘输出
- 左摇杆鼠标滚轮
- 右摇杆鼠标移动
这个顺序只决定同一轮询周期内的先后,不会赋予任何模块整轮独占权。只要各自条件成立,触控板输出、修饰键、L3/R3、动作键、滚轮和指针都会在本轮执行,不会因另一个模块已经输出而被推迟。每个键盘或鼠标原子动作都同步提交给 Interception,驱动确认成功后才更新程序内部的按住/释放状态;不再使用可能让程序状态与 Windows 实际状态分离的整帧延迟缓存或跨动作批量发送。
左摇杆滚轮和右摇杆移动各自独立积分,并在同一轮询周期分别发送高分辨率滚轮报告与指针报告。滚轮有有效整数累计量时即可首发,后续报告至少间隔 4 ms;推满时仍按 15 ms 累计一个 120 单位标准刻度。组合快捷键、完整修饰脉冲和同轮多个动作仍严格保持既定的 KeyDown/KeyUp 顺序。单次驱动发送失败会立即重试一次;仍失败时停止本轮映射并执行统一释放,不会盲目释放一个无法确认是否部分送达的缓存帧。
| 同时发生的模块 | 是否可在同一轮询输出 | 防冲突边界 |
|---|---|---|
| 触控板按压与触控板手势 | 否 | 继续由先触发者占用本轮触控,直到对应触控序列结束 |
| 触控板键盘输出与修饰键、L3/R3、动作键 | 是 | 同轮依序即时发送;不参加 45 ms 修饰绑定的规则不变 |
| 触控板快捷键与修饰键、L3/R3、动作键 | 是 | 快捷键自身保持原子顺序,并临时隔离不需要的外部修饰键 |
| 修饰键与多个 L3/R3、动作键 | 是 | 45 ms 分别绑定到各动作,固定顺序和引用计数防止提前释放 |
| L3/R3 与动作键 | 是 | 同轮发送各自完整按下/释放和已经捕获的修饰绑定;Home 消费范围保持原规则 |
| 任意键盘或鼠标按钮与滚轮、指针 | 是 | 同轮分别即时发送;连续通道独立积分且不被离散输出跳过 |
| 左摇杆滚轮与右摇杆指针 | 是 | 两边独立积分;同轮都达到输出条件时分别发送高分辨率滚轮与移动报告 |
| R3 按下与右摇杆指针 | 暂停指针 | 只执行明确配置的 R3FreezeMs = 60 防漂移,不影响其他模块 |
| 任意正常释放 | 同轮无条件执行 | 保留原事件位置,不会被同轮其他输出取消或推迟到下一轮 |
| 异常清理 | 立即执行 | 停止本轮后按程序实际记录的持有状态统一释放,不猜测未确认的批量发送结果 |
真正的冲突由各模块自己的规则处理:触控板手势与触控板按压仍按先触发者互斥;快捷键和完整修饰脉冲保持原子顺序;修饰键使用引用计数,多个动作共同持有时不会被其中一个提前释放;R3 仍按参数单独冻结指针 60 ms。所有 KeyUp、鼠标键释放和触控板手势修饰键释放都不受其他模块是否已经输出的限制。Create/Options 与左摇杆修饰键的方向、按下时间和 45 ms 绑定状态仍先于可绑定动作登记,真实 KeyDown 则按上面的固定顺序发送。Home 蓄力、静音键和肩键/扳机键层选择只更新控制状态,不参与输出排他。如果快捷键点按的目标键正被另一个模块保持,程序会先暂时释放该目标键,完整发送快捷键后再恢复原保持状态;触控板手势快捷键也会在原子点按期间暂时释放不需要的外部修饰键,完成后恢复。动作键自己的 45 ms 修饰绑定仍使用保留外部修饰键的普通点按路径。
| 参数 | 当前值 | 作用 |
|---|---|---|
MouseSensitivity |
1.5 | 整体灵敏度 |
MouseMaxSpeed |
20.0 | 推满时的基础最高速度系数 |
RightStickDeadzone |
0.015 | 鼠标移动死区 |
RightStickCurve |
power |
曲线类型;支持 power 和 linear |
RightStickCurveExponent |
3.0 | 半径幂曲线指数 |
RightStickLowSpeedAssist |
0.05 | 只补偿幂曲线靠近中心的低速段;推满速度不变 |
RightStickSmoothingMs |
5 ms | X/Y 输入的短指数平滑 |
| 鼠标帧倍率 | 120.0 | 速度公式内部倍率 |
| 鼠标取整阈值 | 0.5 px | 小数位移达到半像素后输出整数移动 |
MaxMouseFrameSeconds |
0.05 s | 单帧积分上限,避免卡顿后大跳 |
R3FreezeMs |
60 ms | R3 按下瞬间冻结光标的时间 |
右摇杆按连续速度积分:先平滑 X/Y,再计算 radius = sqrt(x*x + y*y) 和 normalized = (radius - deadzone) / (1 - deadzone)。power 曲线使用 normalized ^ exponent + assist * normalized * (1 - normalized) ^ 2;补偿权重在中心附近最大,随半径增加快速衰减,推满时严格为原来的 1.0,linear 曲线则不使用该补偿。每帧位移为 direction * power * MouseMaxSpeed * deltaSec * 120 * MouseSensitivity。X/Y 小数像素分别累计,达到 0.5 px 后输出整数,余数留到下一帧。
只有直接滑动,不再区分或保留“长按后滑”。纵向移动 150、横向移动 180 后识别方向并触发手势。
滑动手势最终只有左区和右区,不再存在缓冲区手势。触控板横坐标 0..1919 按起点分成四段:左确定段 0..549、左过渡段 550..959、右过渡段 960..1369、右确定段 1370..1919。
最终区域同时取决于移动手指的起点和第一次达到 150/180 阈值的方向:
| 起点 | 首次方向 | 最终手势区 |
|---|---|---|
| 左确定段 | 左 / 右 / 上 / 下 | 左区 |
| 左过渡段 | 左 / 上 / 下 | 左区 |
| 左过渡段 | 右 | 右区 |
| 右过渡段 | 右 / 上 / 下 | 右区 |
| 右过渡段 | 左 | 左区 |
| 右确定段 | 左 / 右 / 上 / 下 | 右区 |
区域、已经触发的手势状态以及连发模式一旦确定,在当前移动手指抬起前都保持不变。手指移动到另一侧不会重新定区,也不会改成另一组初始映射。二指延续进入下一移动段时,才按新移动指的起点和首次方向重新定区。
方向按达到阈值的主轴确定:横向和纵向都达到阈值时,绝对位移更大的轴优先。100 的静止阈值只用于二指触发后的静止指约束,不会从 150/180 的手势距离中扣除。二指首次触发时必须同时存在两个有效触点:一指先达到 150/180,另一指尚未达到任何方向的触发阈值,后者就确立为静止指;即使它已经移动 100,也会把触发当帧的位置结算为静止基准。若两指同时达到触发阈值,则本段暂不识别手势。识别后再追加触点不会改变已经锁定的指数量和区域。普通时间连发只会在原轴反向时切换快捷键;垂直轴移动不切换快捷键,但达到自己的阈值后仍会完成一次无反馈结算并清空累计。
| 方向 | 输出 | 连发 |
|---|---|---|
| 左 | Win + Ctrl + ← |
每 550 ms;不抬手反向滑动会改为右方向连发 |
| 右 | Win + Ctrl + → |
每 550 ms;不抬手反向滑动会改为左方向连发 |
| 上 | Win + Shift + M |
不连发 |
| 下 | Win + M |
不连发 |
| 方向 | 输出 | 连发 |
|---|---|---|
| 左 | 首次 Alt + Shift + Tab,随后保持 Alt |
按距离 |
| 右 | 首次 Alt + Tab,随后保持 Alt |
按距离 |
| 下 | Alt + Esc |
每 450 ms;不抬手反向滑动会改为上方向连发 |
| 上 | Alt + Shift + Esc |
每 450 ms;不抬手反向滑动会改为下方向连发 |
左区的左/右手势进入 Alt-Tab 后,手指不抬起就持续保持 Alt。这是特殊的四向距离手势:向上或向下累计 150 发送一次 ↑/↓,向左或向右累计 180 发送一次 ←/→。反向、换向或移动到右侧都不会退出 Alt-Tab 状态。抬起移动手指时释放由手势持有的 Alt。
首次横向达到 180 时只发送一次 Alt-Tab 进入动作,并把该时刻的横纵累计同时清零;不会根据同一报告里的超出距离补发方向键。进入窗口切换器后不再使用 Shift 反向选择,后续按每个独立的 150/180 距离段发送 ↑/↓/←/→。
旧的长按后滑识别以及 Home、End 手势均已删除。显示器移动现在由二指右区左/右直接滑触发;Win + Shift + M 和 Win + M 只作为一指右区直接滑的上/下映射。
| 方向 | 输出 | 连发 |
|---|---|---|
| 上 | Ctrl + Shift + Tab |
每 450 ms |
| 下 | Ctrl + Tab |
每 450 ms |
| 左 | Alt + ← |
每 450 ms |
| 右 | Alt + → |
每 450 ms |
不抬起移动手指时,纵向标签页手势反向移动 150、横向前进/后退手势反向移动 180 后,立即触发反向快捷键并继续按 450 ms 连发。垂直于原手势轴的移动不会切换映射或产生快捷键反馈,但达到 150/180 后仍结算该段并清空横纵累计。
| 方向 | 输出 | 连发 |
|---|---|---|
| 左 | Win + Shift + ←,将当前窗口移动到左侧显示器 |
不连发 |
| 右 | Win + Shift + →,将当前窗口移动到右侧显示器 |
不连发 |
| 上 | Win + Shift + S |
不连发 |
| 下 | Alt + F4 |
不连发 |
二指延续只解决“静止手指不用反复抬起”的问题:首次二指手势识别后,只要静止手指保持同一个 Touch ID 且相对当前基准移动不足 100,移动手指可以抬起再放下继续做二指手势。Touch ID 是手柄触控报告用于跟踪同一个持续接触点的编号;触点在 Touch1/Touch2 槽位之间交换但 ID 不变时仍视为同一指,抬起再落下导致 ID 改变时则视为原静止指已经离开。每个新移动段都按新移动指的落点和首次方向重新定区;静止手指不参与方向和区域判断。移动手指未抬起时,已确定区域保持不变。单次动作必须让移动手指抬起后再滑才会再次触发。
运动指每次实际走满纵向 150 或横向 180 并结算一步时,横纵移动累计一起清零,同时以静止指当时的位置刷新静止基准;正向、反向以及没有快捷键反馈的结算都相同。纯时间到点产生的自动连发没有新的移动步,因此不会刷新静止基准。移动手指离开时也会以静止手指当时的位置刷新下一段基准,随后等待新的移动触点;静止手指本身不需要抬起。静止指一旦抬起、Touch ID 改变,或者在两次基准刷新之间移动达到 100,本轮触控序列立即结束并由原手势继续占用触控板,直到所有触点释放。期间运动指继续滑动、静止指保持在超限位置或重新落下其他手指,都不会识别为单指或二指手势,也不会把静止角色转交给其他触点。
| 按压瞬间的触点 | 真实按键输出 |
|---|---|
| 无触点 | Backspace |
| 两个触点 | Backspace |
| 单指在左确定区 | Delete |
单指在中间按压区 550..1369 |
Caps Lock |
| 单指在右确定区 | Backspace |
三个按键都使用真实 KeyDown/KeyUp,并且属于独立触控板模块,所以无论当前是 Base、L1、R1、L2、R2 还是组合层,都只触发原键,绝不会被当前键层改成字母、数字或标点。Delete、Backspace 复用渐进连发的时间参数,Caps Lock 不连发;三者都在按压瞬间输出,不进入独立 45 ms 修饰绑定。Caps/Fn 已开启时,三个键仍输出原键,并且不会关闭或改变 Caps/Fn 状态。
手势和触控板按压严格按先后顺序互斥:手势先达到阈值,则本次按压不输出按键;按压先发生,则按压占用触控板,本次滑动不触发快捷键。两套逻辑不会同时输出。
- 每步结算:触发后,以最近一次结算点为起点;任一方向达到纵向 150 或横向 180 时结算一次,并立即把横向和纵向累计一起清零,以当前位置作为下一段起点。无论这一步是否产生快捷键反馈都执行清零,不保留斜向余量。
- 时间连发:首次必须先移动 150/180;触发后即使保持不动或移动到另一侧,也按固定时间继续发送。沿当前方向再移动一个阈值只完成无反馈结算,不额外立即触发。
- 反向:普通时间连发只有在原轴反向达到对应阈值时才立即发送反向快捷键,并以反向快捷键的间隔继续连发;垂直轴达到阈值只做无反馈结算。
- 虚拟桌面使用 550 ms;窗口、标签页和浏览前进/后退使用 450 ms。
- 距离连发:只用于左区 Alt-Tab 特殊手势;上下每 150、左右每 180 触发一次对应方向键,不依赖时间,每次触发后横纵累计一起清零。
- 不连发:当前移动触点不抬起时不会再次触发;二指延续中的单次动作要让移动指抬起再放下。
| 参数 | 值 | 作用 |
|---|---|---|
TouchGestureVerticalThreshold |
150 | 首次识别上/下所需距离 |
TouchGestureHorizontalThreshold |
180 | 首次识别左/右所需距离 |
TouchGestureVerticalRepeatDistance |
150 | 纵向反向或距离导航步长 |
TouchGestureHorizontalRepeatDistance |
180 | 横向反向或距离导航步长 |
TouchGestureSideConfirmedWidth |
550 | 左右确定起点段各自宽度;剩余中间范围在 960 处分成左右过渡段 |
TouchGestureHoldStillDistance |
100 | 二指触发后的静止指容差;达到该值立即结束本轮触控序列 |
TouchGestureTimeRepeatDelayMs |
450 ms | 普通时间连发首次等待 |
TouchGestureTimeRepeatIntervalMs |
450 ms | 普通时间连发固定间隔 |
TouchGestureDesktopRepeatIntervalMs |
550 ms | 虚拟桌面首次等待和固定间隔 |
如果手柄打字仍然较慢,可以搭配 Typeless、闪电说等语音输入软件。Create 是 Right Alt,Options 是 Right Ctrl,适合绑定语音输入、确认或辅助快捷键。
左摇杆仍分为上/下滚轮区和四个修饰区,但不再六等分。滚轮区严格以正上方和正下方为中心,中心线两侧各 25 度,因此每个滚轮扇区总宽 50 度且不会向左右偏移;余下 260 度由四个修饰区平均占用,每个修饰区总宽 65 度。原来的纯左/纯右扇区仍不存在。
| 扇区 | 输出 | 进入半径 |
|---|---|---|
| 左上 | Left Shift |
0.50 |
| 左下 | Ctrl |
0.50 |
| 右上 | Win |
0.50 |
| 右下 | Left Alt |
0.50 |
| 上 / 下中间 | 鼠标滚轮 | 0.30 |
修饰键扇区即时跟随当前方向,不锁定第一次进入的扇区。从一个修饰键移到另一个修饰键、滚轮区或死区时会释放前一个输出;目标扇区未达到自己的半径门槛时输出为中立。蓄力开启后,已经收集的修饰键例外,会继续保持直到蓄力解除。
滚轮速度按摇杆半径连续变化。半径先按 (radius - LeftStickEnterDeadzone) / (1 - LeftStickEnterDeadzone) 归一化,经过 5 ms 平滑后使用指数 3.0 曲线。速度从 1500 ms 的慢速下限过渡到 15 ms 累计一个标准滚轮格;累计量达到 0.5 后即可取整发送细微的高分辨率滚轮量,余数继续保留。第一份有效滚轮量不等待固定时间窗,之后最快每 4 ms 发送一次,因此轻推可从 1 单位细微起步,推满也不会重新变成每 1 ms 一份滚轮报告。
| 参数 | 当前值 | 作用 |
|---|---|---|
LeftStickEnterDeadzone |
0.30 | 上/下滚轮扇区门槛;低于此值清空滚轮累计量 |
LeftStickModifierEnterDeadzone |
0.50 | 四个修饰键扇区门槛 |
MouseScrollCurveExponent |
3.0 | 滚轮半径曲线指数 |
MouseScrollSmoothingMs |
5 ms | 归一化半径的短指数平滑 |
ScrollSlowIntervalMs |
1500 ms | 最慢滚轮间隔 |
ScrollFastIntervalMs |
15 ms | 推满时累计 120 单位所需时间 |
ScrollReportIntervalMs |
4 ms | 首发之后两份滚轮报告的最小间隔 |
WheelDelta |
120 | 一个标准滚轮格 |
| 滚轮取整门槛 | 0.5 | 达到后输出整数高分辨率滚轮量 |
MaxWheelDeltaPerFrame |
120 | 单帧滚轮输出上限 |
正常状态下左摇杆同一时刻只保持一个修饰键。Home 蓄力只收集左摇杆产生的多个修饰键,并在解除时统一释放;Create/Options 不归入 Home 蓄力:
- 短按 Home:切换蓄力锁定。锁定形成瞬间已经收集至少一个修饰键时,下一次真实动作键会消费并解除锁定。
- 如果锁定形成时没有修饰键,之后再收集修饰键也不会改变这次锁定的“不可消费”属性,需要再次短按 Home 取消。
- 长按 Home:只在按住期间保持蓄力,松开立即释放。
- Home 本身不会在无修饰键时退化成真实
Left Shift。 - 蓄力只影响收集到的修饰键,不改变动作键所属键层;普通映射里的
1仍输出1。 - “先触发修饰键,再短按 Home”形成的一次性锁定不检查修饰键与下一动作之间是否在 45 ms 内;八个动作位置的任意键层输出或 L3/R3 会消费它。
- Base 方向键消费锁定后,保存的组合仍会用于后续渐进连发:每个节拍都完整按下并释放修饰键与方向键。
- 触控板按压产生的
Delete、Backspace、Caps Lock不消费也不取消该锁定,并且与 Caps/Fn 模式完全独立。
静音键控制 Caps/Fn 模式:
- 短按开启 Caps/Fn;再次短按关闭。
- 未带 Shift 的
1..0、-、=转换为F1..F12。 - 未带 Shift 的字母转换为带 Shift 的大写字母。
- 只有未带 Shift 的字母、
1..0、-、=实际完成大写或 F1–F12 转换后,才会自动关闭 Caps/Fn。 - 方向键、Tab、Esc、Space、Enter、其他标点、L3/R3 和触控板
Backspace、Delete、Caps Lock都不会关闭 Caps/Fn。 - 长按静音键达到 250 ms 后切换 ShikiPad 启用/禁用;长按动作不会再触发短按 Caps/Fn。
| 参数 | 当前值 | 作用 |
|---|---|---|
ClutchLongPressMs |
250 ms | Home 长按保持蓄力、静音键长按启用/禁用的判定时间 |
下表列顺序为 ↑ → □ △ ← ↓ × ○。
| 键层 | ↑ | → | □ | △ | ← | ↓ | × | ○ |
|---|---|---|---|---|---|---|---|---|
| Base | ↑ | → | Tab | Esc | ← | ↓ | Space | Enter |
| R1 | o | p | j | i | n | m | k | l |
| L1 | w | d | q | e | a | s | z | x |
| R2 | 0 | g | y | u | - | = | b | h |
| L2 | r | f | t | 1 | c | v | 3 | 2 |
| R1 + L1 | 4 | , | . | 7 | 5 | 6 | 9 | 8 |
| L2 + R2 | + | / | & | * | _ | ^ | $ | % |
| L1 + R2 | [ | ] | ! | ? | { | } | @ | # |
| R1 + L2 | ( | ) | ; | ' | < | > | 反引号 | \ |
程序发送物理键码,需要 Shift 的符号由对应键层自动按下 Shift。Base 层方向键可连发,Base 层图案键不连发;字符层是虚拟点按,按住不会连发。动作键一旦解析到某个键层并进入保持状态,之后肩键或扳机变化不会重分配该键,必须松开动作键后重新按下。
Base 方向键以及独立触控板模块的 Delete / Backspace 复用同一套渐进连发参数。首发后等待 300 ms,从 120 ms 间隔开始,在 1500 ms 内按三次曲线逐渐加速到最快 12 ms。Caps Lock、Base 图案键和字符层不使用这套连发。
| 参数 | 当前值 | 作用 |
|---|---|---|
RepeatDelayMs |
300 ms | 首发后开始连发的等待时间 |
BaseRepeatSlowIntervalMs |
120 ms | 连发起步间隔 |
BaseRepeatRampMs |
1500 ms | 加速到最快速度所需时间 |
RepeatIntervalMs |
12 ms | 最快连发间隔 |
| 连发曲线指数 | 3.0 | 对频率做三次方加速 |
如果多个键层输入落在同一个轮询时间戳,单层优先级为 R1 > L1 > R2 > L2。组合层只检查按下时间最新的两个仍按住的键层输入,并且二者必须落在组合窗口内。
键层切换恢复为纯键层状态机。动作键按下后,键层前窗只观察肩键/扳机键,不读取任何修饰键状态。组合层作为独立键层处理:帮助形成组合的单层按压仍占用 35 ms 时间线,但不算作组合层自身的本体占用。修饰绑定另用独立 45 ms 窗口记录掩码,只包装最终输出,不参加以下键层归属计算。
| 参数 | 当前值 | 作用 |
|---|---|---|
TriggerPressThreshold |
0.25 | L2/R2 进入键层的按下阈值 |
TriggerReleaseThreshold |
0.15 | L2/R2 退出键层的释放阈值;低于按下阈值形成迟滞,减少边界抖动 |
ComboLayerWindowMs |
25 ms | 两个键层输入形成组合层的最大间隔 |
ActionLayerGraceMs |
35 ms | 动作键与肩键/扳机键之间的纯键层前置判定窗口 |
ActionLayerPostGraceMs |
15 ms | 释放旧键层后按下新键层的空窗归属;发生过键层重叠时不获得此后置窗口 |
LayerOccupancyCarryCutoffMs |
20 ms | 向前追溯键层本体占用的累计截点 |
LayerTakeoverWindowMs |
30 ms | 截点落在旧键层本体后允许继续追溯的累计上限 |
ModifierBindingWindowMs |
45 ms | 八个动作位置与 L3/R3 的独立修饰绑定窗口;边界计入,不影响键层归属 |
ActionLayerGraceMs 是键层向前观察范围;累计本体达到 20 ms 后,只能继续停留在当前边界键层本体内追到 30 ms,不能再跨入更早键层或其前置窗口。ModifierBindingWindowMs 与这条时间线相互独立:动作仍会等待两者中较长的窗口结束再输出,但超过 35 ms 才按下的肩键/扳机键不能再改变该动作的键层。缩短这个窗口可减少快速换层时前一个字符被新键层接管的概率;在 35 ms 内发生的换层仍可能接管。键层参数直接影响快速输入时的归属和延迟,修改时建议一次只调整一个值并进行连续快速输入测试。所有参数会在启动时验证,非法死区、间隔或曲线类型会直接给出启动错误,不再带着无效值运行。
确认已安装 x64 .NET 8 Desktop Runtime 和 Interception、重启过 Windows,并以管理员身份运行 ShikiPad.exe。当前版本不会在 Interception 不可用时回退到其他输出方式。Interception 单次发送失败时会原样重试一次;连续失败会停止本轮映射、保留内部保持记录并打印错误,避免静默结算成错误状态。
正常映射进程在当前 Windows 会话中只允许一个实例。若计划任务已经启动 ShikiPad,请不要再手动启动第二份;需要重启时先关闭原控制台窗口。
如果 Windows 仍能看到物理手柄,同一输入会同时被 ShikiPad 和系统/游戏处理。典型表现是保持 Alt 再按 Tab 时乱跳、Win 修饰键不稳定、游戏同时收到手柄导航。按安装章节配置 HidHide,并在修改后重新插拔手柄。
若配置正确仍有系统抢输入,可尝试把整个文件夹放到 C:\ShikiPad 运行,并确认 HidHide Applications 中记录的是当前 ShikiPad.exe 的准确路径。
正常退出、关闭控制台、手柄断开、禁用 ShikiPad 或映射循环异常都会调用统一释放逻辑。若进程被操作系统强制终止而来不及清理,可重新启动再正常退出,或用实体键盘按下并释放对应修饰键恢复系统状态。