他のアプリのイベントを監視したい.

他のアプリが受け取ったイベントを監視する方法を調べたので 環境はOSX 10.9 Marvericks.でも10.0以降なら大丈夫そう.

OSXに限らずグラフィカルなOSは基本的にイベント駆動形式をとっている. マウスの右クリックやキーダウンによってOSがイベントを発行し,それをアプリに配信する. イベントを受け取ったアプリはそれに応じて処理を実行し,終わったら次のイベントが配信されてくるまで待機する. WindowsAPIをいじったことがある人なら多分巨大なswitch文にげんなりしたことがあると思う. 今回はOSの環境そのものを弄るアプリを作りたい.そのためには自分に配信されたイベントだけでなく他のアプリに配信されたイベントを監視する必要がある.

結論から言ってしまうとイベントの監視にはEventMonitorという機構を使う.OSXがデフォルトで備えている機構でGlobalEventMonitorとLocalEventMonitorの2種類がある.WindowsAPIでいうとPeekMessage関数かな?キーを打つとカチカチ音を鳴らすアプリ(名前忘れた)がこの機構を使ってたはず.

GlobalEventMonitor システム全体に配信されたイベントを監視する.今回はこれを使う.

LocalEventMonitor 自分に配信されたイベントを監視する.

EventMonitorの使い方は結構簡単で以下のコードを実行するだけ. .hファイル内で

@property NSEvent *globalEventMonitor;

.mファイル内で

@synthesize globalEventMonitor = _globalEventMonitor;

した後.以下のコードをdidFinishLanchingあたりで実行すればいいだけ.

// set up global event monitor
- (void)setEventMonitor
{
  _globalEventMonitor =
    [NSEvent addGlobalMonitorForEventsMatchingMask:(NSLeftMouseDownMask)
                                           handler:^(NSEvent *incomingEvent) {
    NSEvent *result = incomingEvent;
    NSLog(@"%@", result);
  }];

}

アプリが終了するときにEventMonitorを削除する必要がある.

- (void)applicationWillTerminate:(NSNotification *)notification
{
  //remove global event monitor
  if (_globalEventMonitor) {
    [NSEvent removeMonitor:_globalEventMonitor];
    _globalEventMonitor = nil;
  }

}

EventMonitorは下手をすればキーロガーなどに利用出来てしまう.そのためOSXに明示的に信頼出来るアプリとして登録しておく必要がある. システム環境設定->セキュリティとプライバシー->アクセシビリティ に.appファイルをD&Dしておく.