Event Monitor
Cocoa Event-Handling Guide: Monitoring Events
Mac OS X v10.6 から NSEvent に Event Monitor が導入された。Local Monitor と Global Monitor の2種類があり、前者はアプリ内のイベント、後者は他のアプリのイベントをキャプチャすることができる。API はこんな感じで Blocks で処理を記述するようになっている。
NSEvent Class Reference
+ (id)addGlobalMonitorForEventsMatchingMask:(NSEventMask)mask handler:(void (^)(NSEvent*))block; + (id)addLocalMonitorForEventsMatchingMask:(NSEventMask)mask handler:(NSEvent* (^)(NSEvent*))block;受け取れるイベントはほぼすべて
NSFlagsChanged NSLeftMouseDragged NSRightMouseDragged NSOtherMouseDragged NSLeftMouseUp NSRightMouseUp NSOtherMouseUp NSLeftMouseDown NSRightMouseDown NSOtherMouseDown NSMouseMoved NSFlagsChanged NSScrollWheel NSTabletPoint NSTabletProximity NSKeyDown (Key repeats are determined by sending the event an isARepeat message.)使い方は簡単でアプリ起動時などに上記クラスメソッドを呼び出してイベントハンドラを登録するだけ。こんな感じ。
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // Insert code here to initialize your application [NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask handler:^(NSEvent* event) { NSLog(@"GlobalMonitor: %@", event); }]; [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask handler:^(NSEvent* event) { NSLog(@"LocalMonitor: %@", event); return event; }]; }
制約
便利な Event Monitor だが実は標準では使えない。Global Monitor を使ってイベントを受け取るにはユニバーサルアクセスの「補助装置にアクセスできるようにする」にチェックを入れる必要がある。
これが無いと Global Monitor からのイベントは受け取れない。Local Monitor はこの設定の有無に関わらわず受け取ることができる。
考察
とても強力な API だが、ユニバーサルアクセスの設定が必要なのと、何よりも悪用される可能性が高いことから使い道はかなり限られる。別の言い方をすると非常に簡単にキーロガーやイベントロガーの作成が可能なので、もし「補助装置にアクセスができるようにする」にチェックが入っていると簡単にそういったソフトの標的になりうる。この為、Global Event Monitor を使いこの設定を前提としたアプリケーションの配布は行うべきではないだろう(ユーザが一旦設定してしまうと悪意を持った他のアプリに容易にイベントを盗聴されてしまう可能性が高まる)。便利なんだが....残念。
ソースコード
GitHub からどうぞ。
EventMonitorSample at 2011-02-03 from xcatsan/MacOSX-Sample-Code - GitHub
※「補助装置にアクセスできるようにする」を有効にする場合は考察で述べた危険性があることを十分に理解した上で行って下さい(自己責任です)。
[参考情報] Carbon API を使ったホットキーの実装
Mac OS X でホットキーを実現しようとすると Carbon API を使う必要がある。こんな感じ。
- (void)applicationDidFinishLaunching:(NSNotification *)notification { : EventTypeSpec eventTypeSpecList[] ={ { kEventClassKeyboard, kEventHotKeyPressed } }; InstallApplicationEventHandler(&hotKeyHandler, GetEventTypeCount(eventTypeSpecList), eventTypeSpecList, self, NULL); EventHotKeyID hotKeyID; hotKeyID.id = 0; hotKeyID.signature = 'htky'; UInt32 hotKeyCode = 49; UInt32 hotKeyModifier = cmdKey + optionKey; OSStatus status = RegisterEventHotKey(hotKeyCode, hotKeyModifier, hotKeyID, GetApplicationEventTarget(), 0, &_hotKeyRef); : }[参考情報] (旧) Cocoaの日々: ホットキー
利用方法に特に問題はないが Carbon API なのでいずれは利用できなくなるという根本的な問題がある。
参考情報
Global hotkeys in Cocoa on Snow Leopard
Shortcut Recorder
Responses
Leave a Response