核心控制闭环
手柄采集、鼠标、滚轮、键盘/鼠标按钮、左右修饰键、长按连按和安全释放。
Controller-native productivity for macOS
把 Xbox 手柄转化为 macOS 的指针、滚轮、快捷键和应用窗口导航器。当前已形成可本机安装、菜单栏常驻、可视化配置和可验证运行的原生 App。
MacJoyMouse 不是游戏驱动,也不是虚拟 HID。它采用 Apple 官方用户态框架,把控制器输入标准化后映射到桌面操作,并用 dashboard、悬浮反馈和诊断采集建立可观察性。
手柄采集、鼠标、滚轮、键盘/鼠标按钮、左右修饰键、长按连按和安全释放。
大型手柄 GUI、透明小浮层、双八向圆环、JSON 热重载和菜单栏常驻。
Pointer Assist 调参、真实权限恢复、跨 App 快捷键与长时间设备性能。
App Sandbox 能力冲突、正式签名、notarization、版本元数据和审核材料。
物理手柄与 GUI 假输入先合成统一的内部快照,映射层只处理纯逻辑,输出层集中管理系统事件和按住态。这个边界让同一套后半段可被单元测试、GUI 模拟和真实设备复用。
Extended Gamepad 事件与 8 ms 轮询读取完整控制器状态。
物理快照和 GUI/自动化模拟快照分别存放在线程安全 store。
合成 `InternalOperationSnapshot`,统一轴值、按钮和时间戳。
以 active / idle / paused 节奏调用映射、径向菜单和 Pointer Assist。
处理 deadzone、灵敏度、按下沿、长按、repeat、cycle 和 app target。
发送 CGEvent / App activation,并跟踪所有 held key 与 mouse button。
ConfigStore 将 schema 3 配置热更新到 RuntimeControlStore;PermissionService 和 output toggle 决定高频路径是否允许派发。权限撤销或输出停用时,Frame Loop 进入 paused 并主动释放所有 held output。
AppRuntime 只读取快照并发布变化值。dashboard、配置编辑、右下角浮层和双圆环 panel 都消费状态,不参与原始输入采集。
项目是 SwiftPM 原生 macOS executable,主要依赖 SwiftUI、AppKit、GameController、CoreGraphics、ApplicationServices 和 Foundation。
| 区域 | 关键组件 | 职责 | 失败时行为 |
|---|---|---|---|
| App | AppDelegateAppRuntime | 窗口、菜单栏、透明 panel、生命周期和状态汇总。 | dashboard 可隐藏,应用继续常驻;退出前停止运行时。 |
| Input | ControllerMonitorControllerStateStore | 设备选择、热插拔、轮询和最新控制器快照。 | 无兼容设备时回到 waiting;断开时清空快照。 |
| Normalize | InputMapperSimulatedInputStore | 合并物理与 GUI/自动化输入。 | 无输入时输出空 snapshot,不产生系统动作。 |
| Runtime | FrameLoopRuntimeControlStore | 120 Hz active、idle 降频、权限/输出门控。 | 进入 paused 并释放 held output。 |
| Mapping | MappingEngineRadialMenuController | 摇杆、按钮时序、双圆环方向和应用目标。 | 无效/空槽不输出,扳机先松取消选择。 |
| Output | OutputDispatcherAppActivation | 键鼠事件、modifier flags、drag 和窗口队列。 | 窗口 ID 不可用走 fallback;releaseAll 清理按住态。 |
| Config | AppConfigConfigStore | schema、校验、迁移、保存和热重载。 | 非法修改保留最后一次成功配置并显示 warning。 |
| Assist | AXTargetScannerPointerAssistEngine | 低频扫描可点击目标,高频路径做几何修正。 | 默认关闭;无目标/无权限时退化为原始指针。 |
当前产品能力覆盖连续控制、离散命令、状态反馈和配置四类工作流,重点是让手柄在桌面环境下可预测地完成重复操作。
左摇杆控制相对指针,右摇杆控制垂直滚动;支持 deadzone、反向、曲线和独立三档灵敏度。左摇杆档位为 1.0x、0.1x、0.01x。
press 立即保持,默认 280 ms 后开始连按;另有 tap、hold、repeat、cycle 和 downWhilePressed,覆盖快捷键、持续方向键和拖拽。
左右 Command、Shift、Option、Control 使用不同 key code。旧配置中的泛化名称自动迁移为左侧键,避免 Y/Option 等绑定发生侧别偏差。
按住左扳机显示两个透明圆环,左右摇杆各控制八个方向。保持扳机并松摇杆即提交;一次扳机按住可连续选择多个动作。
目标未运行时打开,已运行但非前台时激活,已在前台时按窗口 ID 队列循环。三窗口测试证明逻辑不限制为两个窗口。
大型 Xbox 手柄图用于查看和编辑真实键位;右下角无边框半透明浮层反馈按键和摇杆;dashboard 下方固定展示双圆环配置。
schema 3 JSON 支持默认生成、外部修改、热重载、错误回退和 GUI 即时保存。配置状态与实时诊断拆分,减少输入反馈引发的整页刷新。
dashboard、JSONL、资源 CSV、GUI 截图、acceptance analyzer 和 soak suite 共同覆盖功能与稳定性证据。
这个时序让用户能在扳机保持期间连续执行多个命令,同时保留明确的取消动作。
按住左扳机,双圆环 panel 显示并接管普通摇杆输出。
推动左或右摇杆;对应八分区实时高亮,另一摇杆可独立选择。
保持扳机,先松开摇杆。控制器产生一次 tapKey 或 activateApp。
扳机仍按住,圆环保持可见,可继续选择另一个方向并再次松摇杆。
若扳机先松开,当前选择取消;之后松摇杆不会补发动作。
响应速度和资源使用不是二选一。Frame Loop 根据输入和门控状态在 active、idle、paused 三种模式间切换。
有效轴值或按住态存在,目标 120 Hz;活动期抑制 App Nap。
无有效输入时降至配置的 10-20 Hz,避免持续空转。
权限缺失或 output disabled;立即 releaseAll,继续保留 UI 与配置。
App 可运行但不能发送系统事件,dashboard 明确显示权限/输出原因。
权限撤销、输出停用、循环停止和退出都释放本应用持有的键鼠状态。
非法 JSON 或非法范围不会覆盖当前可用配置。
deadzone 内漂移和 72,000 帧空闲逻辑运行均不得生成动作。
Pointer Assist 默认关闭,无目标时也不得改写指针位移。
测试通过是必要条件。真实 GameController 数据、TCC、前台 App 对 CGEvent 的接受和 AX 窗口行为仍需单独采集证据。
项目的下一阶段价值主要来自兼容性、分发和真实设备证据。继续增加按钮语义的边际收益已经低于把系统边界做稳。
| 风险 | 当前状态 | 影响 | 推荐动作 |
|---|---|---|---|
| Steam / 虚拟控制器 | 暂缓 | 设备显示已连接,但所有原始轴值可能持续为 0。 | 先完全退出 Steam;未来按输入活跃度仲裁全部候选设备。 |
| Pointer Assist 体验 | 部分完成 | 代码链路存在,但不同 App 的 AX 树、目标密度和手感差异大。 | 建立真实应用矩阵与长时间 CPU/目标命中基线。 |
| App Store 沙盒 | 阻塞 | 任意键鼠注入、AX 扫描和任意 App Apple Events 与 sandbox 冲突。 | 优先 Developer ID 完整版;若上 Store,单独定义精简能力集。 |
| 发布工程化 | 待建设 | 当前包缺正式版本、图标、发布签名、notarization 和 archive。 | 建立 Xcode release target、正式 bundle ID 和可重复分发流水线。 |
| 真机证据 | 需补齐 | 单元测试不能证明真实 TCC、CGEvent、App 窗口和 30 分钟负载。 | 保存严格 acceptance capture、soak、GUI 和干净 Mac 安装记录。 |
核心功能已经形成产品雏形。下一阶段不应扩大范围,而应把设备兼容、发布身份和可重复验收变成稳定资产。
保持功能闭环和文档可追踪。
用真实数据关闭剩余技术风险。
优先保留完整系统控制能力。
手柄作为桌面无障碍和远距离输入设备,价值不只在“替代鼠标”,还在空间化快捷操作、可视化配置和低学习成本。双圆环与窗口队列是区别于简单键位映射器的产品表达。
保持本地优先、零账号、零云依赖。先完成 Developer ID 直接分发的可信安装体验,再决定是否维护功能显著受限的 App Store 版本。
本报告用于快速理解。需要决策或执行时,以对应的 Markdown 基线和 OpenSpec 为准。