MouseLite 是一個 macOS 選單列清量化工具,讓你針對每一支滑鼠或觸控板調整捲動方向、捲動速度、指標靈敏度,以及中鍵和側鍵動作,而不影響其他指標裝置或系統全域設定。
- 控制滑鼠按鍵功能
- 調整靈敏度
- 自然滑動控制
- 設定即時生效,並自動檢查、安裝新版本
- macOS 13 Ventura 或更新版本
- 輔助使用(Accessibility)權限
- 輸入監控(Input Monitoring)權限
MouseLite 是純選單列應用程式,不會出現在 Dock。
- 將
MouseLite.app拖曳到「應用程式」資料夾並開啟。 - 第一次啟動時,依系統提示允許「輔助使用」與「輸入監控」權限。
- 點選選單列的滑鼠圖示,選取裝置後調整快速設定,或選擇「進階設定…」。
- 在「進階設定」中選取裝置,變更會立即套用,不需要按儲存。
若已授權但功能沒有開始運作,請結束並重新開啟 MouseLite,或確認它仍列在「系統設定 > 隱私權與安全性」的兩項權限清單中。
xattr -dr com.apple.quarantine /Applications/MouseLite.app
裝置設定存在 ~/Library/Application Support/MouseLite/settings.sqlite3,資料表為 devices、button_actions、settings 與 device_usage。
- WAL 模式:一個寫入者與多個讀取者可以同時工作。
- 寫入不佔主執行緒:
SettingsStore把編輯依裝置合併(同一台裝置連續拖動只留最後一個值),交給背景序列佇列一次提交。 - 單一寫入連線:所有寫入都在自己的序列佇列上,以
BEGIN IMMEDIATE交易執行,不會有兩個寫入互相卡死。 - 讀取池:預設 2–4 條唯讀連線(
PRAGMA query_only=ON),每次讀取輪流使用下一條,永遠看到最後一次提交的完整快照。 - 批次寫入後會從讀取池重讀;若期間又有新的編輯,就不會用較舊的快照覆蓋畫面,等下一批再更新。
- 結束 App(含 SIGTERM/SIGINT)前會
flush(),確保最後一次拖動已寫入。 - 第一次啟動新版時,會把舊版
UserDefaults的deviceSettingsJSON 與enabled匯入一次;既有設定會升級到 schema v2,並依updated_at建立最近使用順序。 - 資料庫檔與資料夾權限為
0700;若資料庫無法開啟,App 會記下錯誤並以記憶體中的設定繼續運作。
選單預設只列出 3 台最近使用的裝置,其餘收在「其他裝置」子選單;「進階設定」仍會列出全部裝置。
- 使用順序存在
device_usage,與devices分開:插過一次但沒設定過的裝置不會留下設定列,只會留在最近使用清單。 - 移動或點擊裝置(HID 輸入)時更新,每台最多每 60 秒寫一次 SQLite;在設定視窗選取裝置、或變更設定時也會更新。
- 讀取走 reader pool,所以開啟選單不會碰到寫入佇列。
選單列的「檢查更新…」會向 GitHub Releases 查詢;開啟「自動檢查更新」時,啟動後與每 6 小時背景檢查一次。
- 通道:正式版走正式通道;RC 與 main 快照走測試通道。測試通道除了 RC/快照,也會收到比目前 build 新的正式版,所以 RC 最後可以升到正式版;正式通道永遠不會收到測試版。選單的「接收測試版」可切換通道。版本新舊只比
CFBundleVersion(build code),名字不參與比較。 - 簽章:更新檔必須通過 Developer ID 驗證,且與目前執行中的 App 屬於同一個 Team(
SecStaticCodeCheckValidity+anchor apple generic+ team OU),否則拒絕安裝。 - 完整性:下載後比對 GitHub 的
sha256digest,再從簽章密封的Info.plist確認 bundle id 與 build code 都和 release 宣告的一致。 - 通過後以原子替換方式換掉 App,等目前行程結束後自動重新開啟;安裝前會先確認 App 所在資料夾可寫入(例如必須在「應用程式」內)。
從原始碼直接 swift run 或 ad hoc 簽章的建置不會有 MouseLiteRepository/Team,因此更新功能會自動停用。
commit 訊息就是更新日誌,scripts/notes.sh 會直接把它變成 GitHub Release 的內容。完整規則在 commit.md。
本機先啟用檢查(只要一次):
git config core.hooksPath .githooks
之後每次 commit 都會檢查訊息;推送前也可以手動檢查:
scripts/check-commits.sh origin/main..HEAD
PR 的 CI 會跑同一個檢查,而且不接受 merge commit,請用 rebase。
Swift 版本由 mise.toml 決定;Xcode 只提供 SDK。
mise install
swift test
SIGN_IDENTITY=- ARCHIVE=1 ./scripts/build-app.sh # 本機測試包(ad hoc 簽章、未公證)
scripts/build-app.sh 會產生 build/MouseLite.app;加上 ARCHIVE=1 另外產生 build/MouseLite-<label>.zip。
要產生可發佈的簽章版本(Developer ID + 公證):
ARCHIVE=1 NOTARIZE=1 \
APPLE_ID=you@example.com \
APPLE_APP_SPECIFIC_PASSWORD=xxxx-xxxx-xxxx-xxxx \
APPLE_TEAM_ID=TEAMID \
./scripts/build-app.sh
本機需要有 Developer ID Application 憑證;NOTARIZE=1 會用 xcrun notarytool 送出並 staple。
.github/workflows/release.yml 參考 ExpTechTW/FreeAudio 的流程:
-
push 到
main→ 產生快照,標記為 GitHub pre-release,tag 形如26w43a。 -
建立版本 tag(
rc0.1.0、v0.1.0-rc.1、1.1.0或v1.1.0)→ 自動建置、簽章、公證並建立 GitHub Release;App 的 OTA 就是從這些 Release 取得更新。RC 會標成 pre-release。 -
每次發佈都會:跑測試 → 安裝簽章憑證 → 通用(arm64 + x86_64)建置 → Developer ID 簽章 → Apple 公證 → 打包
MouseLite-<label>.zip→ 寫 release notes(最後一行<!-- mouselite-build: <code> -->)→ 建立 GitHub Release。 -
版本由
scripts/version.sh統一決定:正式版 RC 快照 label 1.1.0rc0.1.026w43atrain( CFBundleShortVersionString)1.1.00.1.00.1.0(RC 穩定中)或0.1.1code( CFBundleVersion)126000042126000042126000043GitHub pre-release 否 是 是 目前專案的版本是
0.1.0,第一個 RC 標籤為rc0.1.0(也接受v0.1.0-rc.1、vrc0.1.0)。只有 code 會單調增加,更新器只比較 code;標籤名稱不影響更新判斷。已發佈過的 code 不會再被發佈(避免歷史被改寫後蓋掉較新的版本)。
發佈一個 RC:
git tag rc0.1.0 git push origin rc0.1.0RC 穩定後,在同一個或更新的 commit 上建立正式版:
git tag v0.1.0 git push origin v0.1.0快照 tag 也以數字開頭,但含有
w(例如26w43a),release job 會跳過它們,不會被當成版本。
| Secret | 內容 |
|---|---|
APPLE_CERTIFICATE |
Developer ID Application 憑證+私鑰的 .p12,base64 編碼 |
APPLE_CERTIFICATE_PASSWORD |
匯出 .p12 時設定的密碼 |
APPLE_ID |
公證用的 Apple ID |
APPLE_APP_SPECIFIC_PASSWORD |
該 Apple ID 的 App 專用密碼 |
APPLE_TEAM_ID |
Team ID(可留空,預設從簽章讀取) |
產生 base64 憑證:
base64 -i DeveloperID.p12 | pbcopy
scripts/ci-keychain.sh 會把憑證匯入 runner 的臨時 keychain,並下載 Apple 的 Developer ID 中繼憑證,讓 codesign 與 notarytool 可以非互動執行。