ClipMenuでメニュー項目を選択すると、ペーストするために、Command + v を送信するようになっています。これまでは、Cocoabuilderで紹介されていたCarbon APIを使っていました。
CGPostKeyboardEvent( (CGCharCode)0, (CGKeyCode)55, true ); // command key down
CGPostKeyboardEvent( (CGCharCode)'v', (CGKeyCode)9, true ); // 'v' key down
CGPostKeyboardEvent( (CGCharCode)'v', (CGKeyCode)9, false ); // 'v' key up
CGPostKeyboardEvent( (CGCharCode)0, (CGKeyCode)55, false ); // command key up
でも、これだと、Shiftキーを押しながらメニュー項目を選択すると、Command + v ではなく、Command + Shift + v が送信されてしまいます。CGPostKeyboardEventを呼び出した時点で押し下げされているキーと混ざってしまうんですね。
これまでは問題なかったんですが、新しく、「修飾キー + クリック」にいろいろな機能を割り当てられるように変更したので、問題が生じるようになりました。
そこで、Xcode 3.1のAPIリファレンスを検索してみると、どうもCGPostKeyboardEvent関数の利用は非推奨になっていて、代わりにCGEventCreateKeyboardEvent関数の利用がおすすめのようです。
こちらを使えば、キーボードイベントの作成と、そのイベントをカスタマイズしてからイベントシステムへの送信ができるようになるそうです。対応環境は、Mac OS X 10.4以降と、新しめのAPIですね。
早速試してみました。CGPostKeyboardEventと同じように、command down → v down → v up → command upという手順で呼んでみると、うまく動かない?そこで、CocoabuilderでCGEventCreateKeyboardEventを検索してみると、Dave DeLongさんの質問から始まった二つのスレッドを発見。
DeLongさんは、数時間悪戦苦闘し、思いつく限りググった末に質問を投稿されたようです。お陰で、この関数の使い方が解りました。感謝です!
修飾キーの入力はそれ用のイベントを作るのではなく、CGEventSetFlags関数を使って、文字キーの入力イベントに追加する形にすれば良いんですね。修正したコードは、こうなりました。
CGEventSourceRef sourceRef = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState);
if (!sourceRef) {
NSLog(@"No event source");
return;
}
CGEventRef eventDown, eventUp;
eventDown = CGEventCreateKeyboardEvent(sourceRef, (CGKeyCode)9, true); // v key down
CGEventSetFlags(eventDown, kCGEventFlagMaskCommand); // command key press
eventUp = CGEventCreateKeyboardEvent(sourceRef, (CGKeyCode)9, false); // v key up
CGEventPost(kCGSessionEventTap, eventDown);
CGEventPost(kCGSessionEventTap, eventUp);
CFRelease(eventDown);
CFRelease(eventUp);
CFRelease(sourceRef);
同じスレッドに、CGPostKeyboardEvent関数を使った方法も掲載されていました。Keyboard Maestroの作者さんの投稿?
Cocoabuilder – (Peter N Lewis) Re: Posting Keyboard Events
CGEnableEventStateCombining関数で、キーやマウスの状態を、アプリケーション側で生成するイベントに混ぜ合わせるかどうかを切り替えられるようです。ただ、こちらの関数も、今は非推奨の扱いになっているようで、Mac OS X 10.4よりも古いバージョンに対応させる必要がなければ、積極的に使わない方が良さそうです。
Quartz Event Servicesのリファレンスをざっと眺めてみましたが、キーボードやマウスに関するイベントが作れるので、結構重宝しそうです。
Recent Comments