Mos

一个用于在 macOS 上平滑你的鼠标滚动效果或单独设置滚动方向的小工具, 让你的滚轮爽如触控板 | A lightweight tool used to smooth scrolling and set scroll direction independently for your mouse on macOS

21,050 stars Swift Markdown Skills API Spec #homebrew#macos#mouse#osx
AI Prompts & Specs

Repository: Caldis/Mos


Stars: 19783

CLAUDE.md

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

IMPORTANT

This Project's macoOS Deployment Target 10.13+, so every API should be compatible with it.

Project Overview

Mos is a macOS utility application that provides smooth scrolling for mouse wheels, making them behave more like trackpads. Built with Swift and Xcode, it's a menu bar application that intercepts and modifies scroll events in real-time.

Build System & Development Commands

Building the Application


- Primary IDE: Xcode (requires Xcode 9.0+, Swift 4.0+)
- Project File: Mos.xcodeproj
- Build Target: macOS application bundle

Dependencies


- Charts: Data visualization for the monitor window
- LoginServiceKit: Auto-launch functionality
- Dependencies are managed via Swift Package Manager (SPM)

Creating Distribution Package


bash
cd dmg/

Requires create-dmg tool: https://github.com/create-dmg/create-dmg


Requires Mos.app in dmg/ directory (copy from build output)


./create-dmg.command

The script automatically:
- Reads version from Info.plist
- Creates DMG with custom background and icon
- Generates versioned DMG filename (Mos.X.X.X.dmg)
- Includes application and Applications folder link

Running and Development

First-time setup:

bash

1. Open the project


open Mos.xcodeproj

2. Xcode will automatically resolve SPM dependencies (Charts, LoginServiceKit)


3. Wait for package resolution to complete (shown in top status bar)


4. Build and run (⌘+R)

Runtime requirements:
- App requires Accessibility permissions to intercept events
- On first launch, grant permissions in System Preferences → Security & Privacy → Accessibility
- Use the Monitor window during development to visualize scroll events in real-time

Architecture Overview

Minimum macOS version: 10.13, all API should be compatible with it

Core Components

ScrollCore Engine (Mos/ScrollCore/):
- ScrollCore.swift: Main scrolling interception and processing engine
- ScrollPoster.swift: Smooth scroll event posting using CVDisplayLink
- Interpolator.swift: Smooth scrolling interpolation algorithms
- ScrollEvent.swift: Event data structures
- ScrollFilter.swift: Event filtering and processing logic

ButtonCore System (Mos/ButtonCore/):
- ButtonCore.swift: Core mouse button event interception and processing
- ButtonFilter.swift: Event filtering logic for button actions
- ButtonUtils.swift: Button binding configuration utilities
- ShortcutExecutor.swift: System shortcut execution engine

Key Recording System (Mos/Keys/):
- KeyRecorder.swift: Event recording orchestrator with timeout protection
- KeyPopover.swift: Popover UI component for displaying recording status
- KeyPreview.swift: Visual preview of recorded key combinations
- KeyCode.swift: Comprehensive keyboard and mouse button code mappings
- SystemShortcut.swift: System shortcut definitions and management

Manager Pattern (Mos/Managers/):
- WindowManager: Controls window lifecycle and presentation
- StatusItemManager: Menu bar status item and menu management
- ShortcutManager: Global shortcut registration and management

Configuration System (Mos/Options/):
- Options.swift: Centralized configuration using UserDefaults
- Application.swift: Per-application settings and exception handling

Window Architecture

The app uses multiple specialized windows:

IntroductionWindow: First-time setup and permission requests
PreferencesWindow: Complex tabbed preferences with multiple view controllers:
- GeneralView: Basic scrolling settings
- ScrollingView: Advanced scrolling configuration options
- ButtonsView: Mouse button recording and action binding
- ApplicationView: Per-application exception rules
- AboutView: Application information and credits
- UpdateView: Update checking and management
MonitorWindow: Real-time scroll event visualization using Charts framework
WelcomeWindow: User onboarding experience

Each window follows the WindowController + ViewController pattern.

Key Technical Details

Event Interception: Uses Interceptor utility (wraps CGEventTap) for low-level event capture
- ScrollCore: Captures scroll wheel events (scrollWheel)
- ButtonCore: Captures mouse button events (leftMouseDown, rightMouseDown, otherMouseDown) and key events
Smooth Scrolling: CVDisplayLink-based event posting for 60fps smoothness via ScrollPoster
Event Recording: KeyRecorder orchestrates event capture with timeout protection and visual feedback
Permissions: Requires accessibility permissions (LSUIElement=true for menu bar app)
Localization: Supports 11 languages + English with dual .xcstrings system
Per-App Settings: Application class enables different scroll behaviors per application
Singleton Pattern: Core systems (ScrollCore, ButtonCore, Options, managers) use singleton pattern

File Structure Patterns

Managers: Singleton pattern for system integration (WindowManager, StatusItemManager, ShortcutManager)
Windows: WindowController + ViewController pairs, each in separate subdirectories
ScrollCore: Core scrolling logic and algorithms (ScrollCore, ScrollPoster, Interpolator, ScrollFilter)
ButtonCore: Mouse button event handling and shortcut execution
Keys: Key/mouse event recording system (KeyRecorder, KeyPopover, KeyPreview, KeyCode, SystemShortcut)
Utils: Utility classes (Interceptor for CGEventTap, EventMonitor, Logger, Constants)
Extension: Swift extensions for CGEvent and other system types
Options: Configuration management (Options, Application)
Components: Reusable UI components (PrimaryButton)

Development Guidelines

Adding New Features


1. Follow the manager pattern for system integration
2. Use WindowController + ViewController for new windows
3. Add configuration options to Options.swift
4. Consider per-app exceptions via Application class
5. For button-related features, extend ButtonCore system and use KeyRecorder for event capture
6. UI components should support both Light and Dark mode with dynamic color adaptation
7. Use Interceptor utility (in Utils/) to wrap CGEventTap for event interception
8. Follow localization patterns - all strings must be localizable

Modifying Scroll Behavior


- Core logic is in ScrollCore/ScrollCore.swift
- Interpolation algorithms in ScrollCore/Interpolator.swift
- Event filtering in ScrollCore/ScrollFilter.swift

UI Changes


- Storyboard files are localized - modify Base.lproj first
- Follow existing popover patterns for menu bar UI
- Monitor window uses Charts framework for visualization

Testing


- Test with various mouse types and scroll behaviors
- Verify accessibility permissions are properly requested
- Test per-application exception system
- Use Monitor window to verify scroll event processing

Common Development Issues

Build fails with SPM errors:

bash

Clear SPM cache and DerivedData


rm -rf ~/Library/Developer/Xcode/DerivedData

Re-resolve packages in Xcode: File → Packages → Reset Package Caches

Scrolling not working at runtime:
- Check Accessibility permissions in System Preferences → Security & Privacy → Accessibility
- Verify ScrollCore.shared.start() is called after permissions granted
- Use Monitor window to verify events are being captured

Button bindings not triggering:
- Open Monitor window to see if events are being captured
- Check ButtonCore.shared.start() is called
- Verify key codes in KeyCode.swift match expected values

UI not updating after preference changes:
- Options are stored in UserDefaults - verify Options.shared singleton is being used
- Check if NotificationCenter observers are properly registered
- Preferences window uses bindings - verify @objc dynamic on properties

Localization

The app supports 12 languages using Xcode's String Catalog system (.xcstrings).

Two separate localization files:
- Mos/Localizable.xcstrings - Code strings via NSLocalizedString()
- Mos/mul.lproj/Main.xcstrings - Auto-generated from Storyboard (never merge these)

Key requirements:
- Use NSLocalizedString() (not String(localized:)) for macOS 10.13 compatibility
- Follow macOS official terminology (e.g., "偏好设置" not "设置")
- Preserve modifier key symbols: ⌘⌥⌃⇧
- Never translate: "Mos", person names, brand names

For detailed translation guidelines, see LOCALIZATION.md

Important Considerations

Accessibility: App requires accessibility permissions to intercept events
System Integration: Menu bar app behavior, auto-launch functionality
Performance: Real-time event processing at system level
Localization: All UI strings must be localized following the guidelines above
Distribution: Cannot be uploaded to App Store per license restrictions

README.md

<p align="center">
<a href="http://mos.caldis.me/">
<img width="320" src="https://github.com/Caldis/Mos/blob/master/dmg/dmg-icon.png?raw=true">
</a>
</p>


Mos

!Xcode 9.0+
!Swift 4.0+

一个用于在MacOS上平滑你的鼠标滚动效果的小工具, 让你的滚轮爽如触控板。

中文 | English |
Русский |
Indonesia


主页

http://mos.caldis.me/


特性

- 平滑你的鼠标滚动体验, 并可自定义加速度与曲线, 也可按滚动方向分别处理
- 支持分离触控板/鼠标事件, 可按垂直/水平方向分别设置平滑与反向
- 支持自订鼠标快捷键, 绑定各种系统快捷键
- 支持按应用处理不同的配置策略

下载及安装

Homebrew安装

Mos可通过Homebrew来安装:

bash
$ brew install --cask mos@beta

应用将被安装至 /Applications/Mos.app

若有新版本,可用以下命令升级:

bash
$ brew update
$ brew upgrade mos@beta

重新启动应用即可。

手动安装

- GithubRelease


帮助

- Wiki


鸣谢


- Charts
- iconfont.cn
- LoginServiceKit
- Smoothscroll-for-websites


贡献

如果您觉得 Mos 的本地化做的有任何不妥之处, 欢迎您提交任何关于文本修改的意见, 您可以通过提交 Github Issue 的方式告诉我们, 如果您善于编码, 我们非常欢迎您提交一个 PR !

我们欢迎任何形式的贡献,有任何建议或意见您可以给我们 提问


## LICENSE

Copyright (c) 2017 Caldis rights reserved.

署名-非商业性使用协议

And you can not upload it to the App Store.