← 一覧に戻る

switcha

GitHub ↗ Swift 最終push: 2026/5/22 17:17

WIP(現在進行中)

Work In Progress

このプロジェクトで現在進行中の作業と、過去のスナップショットを記録する。

現在の状況

switcha は DockDoor の代替となる、ゼロから新規開発の macOS ウィンドウ管理アプリ。 コア機能(Dock ホバープレビュー/Cmd+Tab スイッチャー)が、サムネイル表示と クリック操作まで揃い、実用アプリとして一通り完成している。

完了:

  • フェーズ1〜2: プロジェクト雛形、ウィンドウ列挙+ウォームキャッシュ
  • 安定署名(個人チーム証明書。リビルドしても TCC 権限が保持される)
  • フェーズ3: Dock ホバープレビュー(マウス幾何検証で誤発火を解消、ScreenCaptureKit の 実サムネイル表示、カードのクリックで切り替え)
  • フェーズ4: Cmd+Tab スイッチャー(ネイティブ Cmd+Tab を抑止、サムネイルグリッド表示、 キーボード操作、カードのクリックで切り替え)

次にやること(いずれも磨き込み。急ぎではない):

  • スイッチャーの並び順を使用履歴順にする改善
  • 多数ウィンドウ時のスクロール対応
  • 最小限の設定画面(プレビュー遅延・サイズ等の項目が固まったら)

詰まっていること・未決事項:

  • 特になし。コア機能はすべて実機で動作確認済み。

過去のWIPアーカイブ

(新しい「現在の状況」を書く前に、古いものをここに追記でアーカイブする。新しいものが上)

2026-05-22 16:52 時点のスナップショット

コア機能2つともが基本形で動作する状態。完了: フェーズ1〜2、安定署名、フェーズ3 (Dock ホバープレビュー。誤発火解消+実サムネイル表示)、フェーズ4チャンク1(Cmd+Tab スイッチャー基本形。一覧はテキスト表示)。

次にやること: フェーズ4チャンク2(スイッチャーのサムネイル化・並び順改善・スクロール)。 詰まっていること: 特になし。

2026-05-22 16:23 時点のスナップショット

switcha は DockDoor の代替となる、ゼロから新規開発の macOS ウィンドウ管理アプリ。 コア機能はDockホバープレビューとCmd+Tabスイッチャーの2つ。

完了: フェーズ1(雛形)、フェーズ2(ウィンドウ列挙+ウォームキャッシュ)、安定署名、 フェーズ3チャンク1(DockObserver+マウス幾何検証)、フェーズ3チャンク2(プレビュー パネル表示。サムネイルはまだグレー枠)。

次にやること: フェーズ3チャンク3(ScreenCaptureKit でサムネイル取得しグレー枠を実画像に)。

詰まっていること: 特になし。メニューバーアイコンがノッチで隠れる件は macOS の仕様で、 当面は Finder をアクティブにして確認する運用。

ROADMAP(計画)

ロードマップ

今週

  • フェーズ1: プロジェクト雛形(メニューバー常駐+権限オンボーディング)
  • フェーズ2: ウィンドウ列挙+ウォームキャッシュ
  • 安定署名のセットアップ
  • フェーズ3チャンク1: DockObserver(Dock 監視+マウス幾何検証)
  • フェーズ3チャンク2: プレビューパネル表示
  • フェーズ3チャンク3: ScreenCaptureKit でサムネイル取得
  • フェーズ4チャンク1: Cmd+Tab スイッチャー基本形(ネイティブ抑止+ウィンドウ切替)
  • フェーズ4チャンク2: スイッチャーをサムネイル付きグリッドに刷新
  • フェーズ5チャンク1: プレビュー/スイッチャーのカードをクリックで切り替え

今月

  • スイッチャーの並び順を使用履歴順にする
  • 多数ウィンドウ時のスクロール対応
  • 最小限の設定画面(設定項目が固まったら)

今四半期

  • 配布の検討(notarization。無料の個人チームでは不可のため、有料登録の要否を判断)

いつか

  • 設定項目の拡充(プレビューの表示遅延・サイズ・対象アプリのフィルタ等)
  • メニューバーアイコンがノッチで隠れる問題への対応案の検討

DECISIONS(意思決定)

意思決定記録

このプロジェクトで下した重要な意思決定を記録する。 最新が上に来る。


2026-05-22: Cmd+Tab はネイティブを抑止して switcha のスイッチャーに置き換える

背景: ウィンドウスイッチャーの起動キーに、別キーバインド(Option+Tab 等)を割り当てる 案と、Cmd+Tab そのものを置き換える案があった。

決定: CGEvent タップで Cmd+Tab の keyDown を消費し、ネイティブのアプリスイッチャーを 抑止して、switcha のウィンドウスイッチャーに置き換える。

理由: ユーザーが慣れた Cmd+Tab をそのままウィンドウ単位の切り替えにしたいため。実機で keyDown の消費によりネイティブスイッチャーを問題なく抑止できることを確認した。

2026-05-22: DockDoor をフォークせずゼロから新規開発する

背景: 既存 OSS の DockDoor を改良したいが、フォーク(GPL-3.0 を継承)か、ゼロからの 新規開発かの選択があった。

決定: ゼロから Swift で新規開発する。DockDoor のコードはコピーせず、調査で得た知見のみ活用する。

理由: ライセンスの自由度を確保し、最小構成のクリーンなコードベースにするため。難所 (Accessibility・ScreenCaptureKit・権限処理)を自前実装するコスト増は受け入れる。

2026-05-22: コード署名は個人チームの Apple Development 証明書で安定署名する

背景: ad-hoc 署名はリビルドのたびに署名が変わり、アクセシビリティ等の TCC 権限が毎回 外れて開発効率が悪い。

決定: Xcode に個人 Apple ID を追加し、Personal Team(Team ID: 645K6U83T5)の Apple Development 証明書で署名する。

理由: 署名が安定し、TCC 権限がリビルドをまたいで保持される。組織アカウント(Thomson Inc.) ではなく個人チームを選んだのは switcha が個人プロジェクトのため。無料チームは配布用の notarization ができない点は、配布フェーズで改めて検討する。

2026-05-22: ウィンドウのサムネイル取得は ScreenCaptureKit(公開API)を使う

背景: ウィンドウのプレビュー画像取得に、高速なプライベートAPI(CGSHWCaptureWindowList 等) と公開APIの選択があった。

決定: ScreenCaptureKit(公開API)を使い、プライベートAPIには依存しない。

理由: switcha は将来の配布・公開も視野に入れており、プライベートAPI依存は notarization・ 審査・安定性の面でリスクになるため。

2026-05-22: Dock ホバー検出はマウス座標の幾何検証を必須にする

背景: DockDoor は Dock が報告する「選択中の Dock アイテム」を鵜呑みにしており、アイコン 周辺にカーソルを置いただけでプレビューが誤表示される不具合があった。

決定: Dock の AX 選択変更通知は「ホバーが変わったかもしれない」きっかけとしてのみ使い、 選択された Dock アイテムの AX フレーム(アイコン実寸)にマウス座標が入っているかを必ず 検証してから採用する。

理由: DockDoor の誤発火を設計段階で回避するため。検証により、アイコン外のホバーを正しく 却下できることを実機で確認済み。


DEVLOG(作業ログ)

開発日誌

このプロジェクトでの作業を時系列で記録する。 最新のエントリが上に来る。


2026-05-22

17:15 - スイッチャーのサムネイル化とクリック操作(フェーズ4チャンク2・フェーズ5チャンク1)

やったこと:

  • フェーズ4チャンク2: Cmd+Tab スイッチャーをテキスト一覧からサムネイル付きカードの グリッドに刷新。SwitcherModel(ObservableObject)を導入し、selectedIndex のみ @Published にすることで、Tab 連打でも読み込み済みサムネイルがちらつかないように した。各カードにアプリアイコン+タイトル、下部に選択中ウィンドウの完全タイトルを表示
  • フェーズ5チャンク1: ウィンドウ前面化の共通処理を WindowActivator に集約。Dock プレビューと Cmd+Tab スイッチャーのカードをクリック可能にし、クリックで対象 ウィンドウへ切り替わるようにした
  • 実機確認: スイッチャーのグリッド表示・サムネイルのちらつきなし、プレビュー/ スイッチャーどちらもクリック1回でウィンドウ切り替えできることを確認

気づき:

  • .nonactivatingPanel のおかげで、フローティングパネル内のボタンも1回目のクリックで 反応する(first-mouse 対応の追加実装は不要だった)

次回やること:

  • 残りは磨き込み(最小限の設定画面、スイッチャーの並び順を使用履歴順に、多数 ウィンドウのスクロール対応など)。コア機能は完成済み

16:52 - サムネイル表示とCmd+Tabスイッチャー(フェーズ3チャンク3・フェーズ4チャンク1)

やったこと:

  • フェーズ3チャンク3: ThumbnailCache(actor)を実装。ScreenCaptureKit でウィンドウを 撮影し CGImage をキャッシュ。各ウィンドウカードが .task で非同期にサムネイルを 読み込み、プレビューのグレー枠を実画像に置き換えた。画面収録権限を付与して動作確認
  • フェーズ4チャンク1: Cmd+Tab ウィンドウスイッチャーの基本形を実装
    • SwitcherController: CGEvent タップで Cmd+Tab を捕捉・消費してネイティブのアプリ スイッチャーを抑止。Tab/Shift+Tab で選択を送り、Cmd を離すと選択ウィンドウを 前面化、Esc で取消
    • SwitcherOverlayView: ウィンドウ一覧をテキスト行で表示(サムネイルは後続チャンク)
    • 一覧は WindowCache(ウォームキャッシュ)+CGWindowList の前面順から即座に構築
  • ネイティブ Cmd+Tab の抑止が効くこと、ウィンドウ単位の切り替えが動くことを実機で確認

気づき:

  • CGEvent タップで Cmd+Tab の keyDown を消費すれば、ネイティブのアプリスイッチャーは 問題なく抑止できた

次回やること:

  • フェーズ4チャンク2: スイッチャーにサムネイル表示、並び順(使用履歴順)の改善、 多数ウィンドウ時のスクロール対応

16:23 - プロジェクト立ち上げ〜Dockホバープレビュー(フェーズ1〜3チャンク2)

やったこと:

  • DockDoor(ejbills/DockDoor, GPL-3.0)を ~/ichirokisanuki/dockdoor-ref に clone して調査。 Cmd+Tab の重さの原因(スイッチャー起動のたびに同期でウィンドウ列挙+スクリーンショット撮影)と、 Dock プレビュー誤発火の原因(Dock の選択状態を鵜呑みにし、マウス座標の幾何検証をしていない)を特定
  • フェーズ1: Xcode プロジェクト雛形を作成(XcodeGen 管理、Makefile、メニューバー常駐アプリ、 アクセシビリティ/画面収録の権限オンボーディング)
  • フェーズ2: ウィンドウモデル(WindowInfo)、列挙(WindowEnumerator: AX + CGWindowList)、 ウォームキャッシュ(WindowCache: イベント+定期更新)を実装・検証
  • 安定署名のセットアップ: Xcode に個人 Apple ID を追加し、Personal Team の Apple Development 証明書を作成。project.yml を ad-hoc から安定署名へ変更し、リビルドしても TCC 権限が 保持されることを実証
  • フェーズ3チャンク1: DockObserver を実装。Dock の AX 選択変更通知をきっかけに、選択された Dock アイテムの AX フレームにマウス座標が入っているかを幾何検証。誤発火を 29 回却下できることを確認
  • フェーズ3チャンク2: PreviewController/PreviewContentView を実装。Dock アイコンの真上に フローティングパネルでプレビュー表示。生存ポーリングでアイコン↔プレビュー間の移動でも ちらつかないようにした

詰まったこと/気づき:

  • 14 インチ MBP のノッチ+メニューバー混雑で switcha のメニューバーアイコンが隠れた。 アプリメニューの少ない Finder をアクティブにすると表示される
  • ad-hoc 署名はリビルドのたびに署名が変わり TCC 権限が外れる。署名方式の変更後は古い TCC エントリが残るため、tccutil reset Accessibility com.ichirokisanuki.switcha でリセット してから付与し直す必要があった

次回やること:

  • フェーズ3チャンク3: ScreenCaptureKit でウィンドウのサムネイルを取得し、プレビューの グレー枠を実画像に置き換える

最近のコミット

README

switcha

macOS 用の軽量なウィンドウ切り替え / Dock プレビューアプリ。

OSS の DockDoor に着想を得つつ、 自分に必要な最小機能だけを、ゼロから新規実装したもの。

コア機能

  1. Dock ホバープレビュー — Dock アイコンにカーソルを合わせると、そのアプリの各ウィンドウのプレビューを表示する
  2. Cmd+Tab ウィンドウスイッチャー — アプリ単位ではなくウィンドウ単位で切り替える

セットアップ

ビルドには フル Xcode(Command Line Tools だけでは不可)と XcodeGen が必要。

brew install xcodegen
make build      # project.yml から .xcodeproj を生成してビルド
make run        # ビルドして起動

.xcodeprojproject.yml から生成するため Git では追跡しない。 Xcode で開きたい場合は make generate 後に switcha.xcodeproj を開く。

使い方

初回起動時に アクセシビリティ画面収録 の権限を求められる。 メニューバーアイコンから許可状況を確認・設定できる。

動作環境

  • macOS 14.0 以降 / Apple Silicon