Archive for May, 2010

MacBook Pro 15”, SSD

May 28th, 2010  |  Published in 日常

MacBook Pro 15” を買った。オプションは Core i7 2.66GHz, 128GB SSD, ハイレゾアンチグレアディスプレイ。

SSD が素晴らしい

大量のドキュメントを Evernote に入れているユーザには SSD が必須と言える。
たとえば、CPU やメモリが強力だけどストレージが HDD な Mac で Evernote を使うよりも、 CPU やメモリは少ないけれどフラッシュメモリがストレージな iPad から使うほうがぐっとスムーズな使いごこちがある。
どちらの長所もあわせもつ MacBook + SSD は現時点で唯一 Evernote をストレスなく “編集” できる環境だ。

ビルドがものすごく速くなった

スクリプト系言語の REPL のインタラクティブ性にはまだ届かないけれど、 Xcode でビルド → iPhone シミュレータで実行して確認 → コードに戻る のループをずばばばっと速く回せるようになったことは大きい。ぼくは深く考えずにコードを変えてみて、その現象から次の手を考える、というループを回す開発スタイルなので (いや、深く考えてコード書いたほうがいいんだろうけれど…)、 SSD によるビルド時間の短縮は生産性に直結する。
一度この速さを知ってしまうと、これまでどうしてあんな遅い環境で我慢できていたんだろうと思ってしまう。けっきょくのところ、コンピュータは I/O がボトルネックになっているところがいまだに大きいし、これからもそうなんだろう。

モディファイヤキーつきでキー入力をエミュレートする

May 15th, 2010  |  Published in CS

Mac アプリをつくっててだいぶハマってしまったのでその小話。

キーボード入力をエミュレートするには、 Foundation の CGEventCreateKeyboardEvent() を使うのが基本です。ドキュメントにもそう書いてある。

Quartz Event Services Reference:

CGEventRef event1, event2, event3, event4;
event1 = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)56, true);
event2 = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)6, true);
event3 = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)6, false);
event4 = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)56, false);
56 はシフトキーを表し、 6 は z キー。つまり、大文字の z (‘Z’) をタイプするよというサンプルコード、のはずなのですが、 Mac OS X 10.6.3 でやってみてもまるでうまくいかない。たんに z が入力されるにとどまります。

で、ぐぐっていると スタックがオーバーフローして:

CGEventRef event1, event2;
event1 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)6, true);//'z' keydown event
CGEventSetFlags(event1, kCGEventFlagMaskShift);//set shift key down for above event
CGEventPost(kCGSessionEventTap, event1);//post event
のように、 CGEventSetFlags() をかまして、モディファイヤキーが押されているのをイベントに修飾せよ、とある。なるほど。

それでやってみると、たしかに Z が入力されます。I’m feeling lucky! と思うもつかのま、こんどは z に戻らない。むむむ、これは…

そこから一週間ほどもがいていたのですが、状態をリセットすればいいんじゃなかろうかと気づいてやってみたらうまくいった。バッドノウハウすぎるだろこれ..

けっきょくうまくいったコードは以下のようなものになりました。

- (void) postKey:(uint16_t) key withModifiers:(uint16_t) modifiers down:(BOOL)down
{
   CGEventRef event = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)key, down);


if (modifiers & MODE_SHIFT) { CGEventSetFlags(event, NSShiftKeyMask); } else if (modifiers & MODE_CONTROL) { CGEventSetFlags(event, kCGEventFlagMaskControl); } else if (modifiers & MODE_OPTION) { CGEventSetFlags(event, kCGEventFlagMaskAlternate); } else if (modifiers & MODE_COMMAND) { CGEventSetFlags(event, kCGEventFlagMaskCommand); } else CGEventSetFlags(event, 0); // <<<<<<< これ
CGEventPost(kCGSessionEventTap, event); CFRelease(event); }

CGEventSetFlags に指定するフラグは OR でとればよいので、もっとかんたんに書けるはず。しかし今夜はここで力尽きた..


教訓: 仕様、コードに一致していないドキュメントはむしろ害になり得るので気をつけよう。自戒自戒。

Tags: