世界を動かす技術を、日本語で。

「MacBook Neo」のカーソル遅延を修正する:10秒ごとに1ピクセルの画面を記録する

2026年6月24日原文(gist.github.com)

概要

このスクリプトは Unlag Neo というMacアプリをビルド・起動します。 画面収録アクセシビリティ の権限確認と取得処理を含みます。 フルスクリーン検知や、 ステータスバーアイコン の表示も実装。 Swift で主要ロジックを記述し、Bashでアプリ構造を構築。 権限不足時のアラート表示や再起動処理も備えた設計。

Unlag Neo: macOS 画面収録・権限管理アプリのビルドスクリプト解説

  • Unlag Neo アプリのmacOS用パッケージ生成スクリプト

    • 既存の Unlag Neo.app が存在する場合、エラーを表示して終了
    • 必要なディレクトリ構造( Contents/MacOS, Contents/Resources)の作成
  • Swift コードのコンパイル・埋め込み

    • 権限管理や画面収録ロジックをSwiftで実装
    • swiftc コマンドで直接バイナリを生成し、アプリ本体に配置
  • 画面収録権限 の確認・取得処理

    • CGPreflightScreenCaptureAccess で権限チェック
    • 権限未取得の場合、 CGRequestScreenCaptureAccess でリクエスト
    • 権限がない場合はアラートを表示し、設定画面への誘導・再起動・終了を選択肢として提示
  • アクセシビリティ権限 の確認・取得処理

    • AXIsProcessTrusted でアクセシビリティ権限を確認
    • 未取得時はアラート表示、設定画面誘導、再起動・終了の選択肢
  • フルスクリーンウィンドウ検知 ロジック

    • AXUIElementCGWindowListCopyWindowInfo を利用し、現在のフロントアプリのウィンドウ状態を判定
    • ディスプレイ全体を覆うウィンドウがあるかをチェック
  • ステータスバーアイコン の生成・表示

    • NSStatusBar を利用し、22x22のカスタムアイコン("UN"の文字入り)を描画
    • メニューから「有効化」「フルスクリーン時の一時停止」「ログイン時自動起動」などの設定を切り替え可能
  • 画面キャプチャのダミー実装

    • ScreenCaptureKit を利用し、1x1ピクセルのダミーキャプチャを10秒ごとに実行
    • フレームは破棄されるが、権限維持や動作確認に利用
  • 権限取得後の再起動処理

    • 権限付与後に Unlag Neo を自動で再起動するロジックを実装

権限アラート・ユーザー誘導の詳細

  • 画面収録権限アラート

    • 権限未取得時、「設定を開く」「アプリ再起動」「終了」の選択肢を提示
    • 設定画面を開いた後、「再起動」または「終了」の追加ダイアログを表示
  • アクセシビリティ権限アラート

    • 画面収録権限同様、「設定を開く」「再起動」「終了」の選択肢
    • 状態管理フラグでアラートの多重表示を防止

フルスクリーン検知・ウィンドウ管理

  • AXUIElement 経由でフォーカスウィンドウや全ウィンドウを取得
  • ウィンドウの位置・サイズ情報からディスプレイ全面を覆うかを判定
  • CGWindowListCopyWindowInfo でFinder以外のフロントアプリのウィンドウを解析

ステータスバー&ユーザーインターフェース

  • NSStatusBar でステータスアイコンを設置
  • メニュー項目として各種スイッチ(有効化、フルスクリーン時の一時停止、ログイン時自動起動)を用意
  • メニューアクションで各種設定のオンオフを即時反映

まとめ

  • Unlag Neo はmacOS向けの画面収録権限・アクセシビリティ権限管理およびフルスクリーン検知ツール
  • シンプルなBash+Swift構成で、権限取得や再起動を自動化
  • ステータスバーからの直感的な操作性と、ユーザーへの明確な権限誘導を両立

Hackerたちの意見

スティーブが墓の中でひっくり返ってる

https://www.folklore.org/Shut_Up.html からの関連する引用: 「私たちは [ゲイツ] に、マッキントッシュのマウスカーソルがスムーズに、ちらつきなしで動く様子を見せました。『カーソルを描くのにどんなハードウェアを使ってるの?』と彼は聞きました。多くの現在のパソコンには、小さなビットマップを描くための特別なハードウェアがあり、彼は私たちが似たようなことをしているかもしれないと思ったのです。」

これ、すごくいい修正なんだけど、インストールしたらスタート時に立ち上がるように設定して、そのまま忘れちゃうんだよね。5年後にはバグが4回も修正されてるのに、今でもスクリプトが10秒ごとにランダムなピクセルを記録してる。いつになったらこのハッキーな修正が必要なくなったか分かるんだろう。

カレンダーに入れとけばいいんじゃない?「~/.dirtyhack.sh のハッキーなバグ修正がまだ必要か確認する(chmod -x ~/.dirtyhack.sh)」って。

バグが何かは分からないけど、これはひどい修正だね。これをやってるのは、WindowServerにカーソルをハードウェアオーバーレイとして扱うんじゃなくて、合成させることなんだ。OPにとってはかなり深刻な問題なんだろうけど…うーん。

ひどい修正だけど、最小限の侵襲でバグを解決してるから、まあ仕方ないかな。カーソルの遅延が続くのは、時間が経つにつれてめっちゃイライラするのが分かる。

10年前に書いた修正を思い出すな。ノートパソコンがバッテリーで動かしてるときに、高周波の音が出ることがあったんだ。CPUがP2より低いパフォーマンス状態に入るときだけ起こることに気づいて、バッテリーで動くときに自動で始まるbashスクリプトを書いて、数秒ごとにハッシュを計算するようにしたんだ。これで音が解決した。ひどい修正だけど、バッテリーの消費量は測ってないから、まあ…大丈夫だった。

でも、システムが遅延するとき、ハードウェアカーソルからソフトウェアカーソルに切り替わるんだよね(CGCursorIsDrawnInFramebuffer() が 0 から 1 に変わる)。だから、MacBook Neo ではその切り替えが何かしらの理由で滞ってるのかも。MacBook Neo のハードウェアについては全く知識がないけど、GPUについてはちょっと知ってる(Windows 用の GPU 加速ドライバーや関連するカーソル処理コードも書いたことがあるから)。だから、ちょっと大胆な予想をしてみると、この遅延は GPU コマンドキューがフラッシュされるのを待ってるからかもしれない。背景情報として、GPU は CPU が書き込むキューからコマンドを受け取るんだ。これらのコマンドは、GPU が加速するために設計された描画操作を実行する。ハードウェアカーソルは基本的に小さなビットマップで、画面上のどこにでも配置できて、位置レジスタを更新するだけで動かせる(通常はマウスの割り込みごとに行われる)。ハードウェアが自動的に描画するんだ。一方、ソフトウェアカーソルはグラフィックススタックによって手動で描画される。下に何があったかを保存してカーソルを描いて、動かす必要があるときは元のデータを戻して、新しい位置にデータを保存して、そこでカーソルを描く。ソフトウェアカーソルに切り替えるときやフレームバッファにソフトウェアで書き込むときは、コマンドキューをフラッシュする必要がある。GPU がキューに入っているものを描き終えるのを待たないと、ソフトウェアが描こうとしているもの、カーソルを含めて上に描かれちゃうかもしれないから。もっと悪いことに、コマンドがブリット(例えばウィンドウをスクロールする)だった場合、カーソルの前の位置に残骸が残ることになる。

でも、ソフトウェアカーソルの操作もキューに入るんじゃないの?問題が見えないんだけど。

すごく分かりやすくて興味深い返答だった!おかげでGPUに興味が出てきたよ、ありがとう。

ソフトウェアカーソルはグラフィックススタックによって手動で描画されます。まず、その下にあったものを保存してカーソルを描き、移動が必要なときには元のデータを戻して新しい位置にデータを保存し、そこにカーソルを描きます。ハードウェアレイヤーが使われていない場合、カーソルレイヤーはコンポジタ内の他のレイヤーと同じように扱われます。現代のコンポジタは、そんな風にピクセルを保存したり書き込んだりしません。単に再描画するだけです。 >(通常はマウスの割り込みごとに行われます); コンポジタがフレームを作るたびに行われます。 >また、ソフトウェアが描きたいものの上に描画されることもあります。コンポジタは、次のディスプレイのリフレッシュで表示されるすべてを合成します。お互いの足を踏み合うことはなく、コンポジタがすべてのハードウェアレイヤー(プレーン)をレンダリングして同期しているだけです。

コンポジットデスクトップでハードウェアカーソルはどう機能するの?カーソルは、他のサーフェスの上に配置する小さな矩形のテクスチャに過ぎないよね。フレームバッファを読む必要も書き込む必要もないし、今はただの3DサーフェスのZスタックだよ。

Hacker Newsで議論の続きを見る