OS XでQuartz Event Services、特にイベントタップを使用して、ストリップされたキーボードPCBに配線されたパッシブ赤外線センサーによって生成されたシミュレートされたキープレスをキャプチャしようとしています。理論的には、イベントタップを使用すると、キーの押下を飲み込んで無視し、キーボード入力を使用してコンピューターを「起動」することができます。また、イベント タップ (1 つの「キー」のみが配線されているため、モーション ディテクターは常に「0」を送信します) を使用して、入力を任意のキーまたはキーの組み合わせに変更し、ホスト マシンで任意の機能を呼び出すこともできます。 . さらに複雑なことに、エンド ホスト マシンは古い G4 Powerbook (PPC) であり、OS X 10.4 以降は実際には何も実行できません。また、現在の開発マシンは、10.9 を実行し、Xcode 5.1 を使用する、はるかに新しい Intel ベースの iMac です。 1.
ここの回答から次のコードを見つけました、そしてそれは完璧なようです。Cocoa で端末アプリケーションを作成すれば、基本的にコードをそのまま使用できます。また、セキュリティ/プライバシー設定でコンピューターを「制御」できるアクセシビリティ アプリのリストにアプリケーションを追加するために必要な場合に備えて、ウィンドウ ベースの Cocoa アプリケーションを作成してみました (Mavericks では補助デバイスのアクセスを有効にすることは推奨されていません)。どちらの種類のアプリも完全には機能しませんでした。私が達成できた最善の方法は、プログラムに修飾キー (コマンド、オプション、シフト、ctl など) のキー押下を認識させることですが、「通常の」キーボードキーのキー押下からは何の応答も得られません。キャプチャされたキーイベントを実際に変更することはできないようです。さらに、マウスイベント、具体的にはマウスクリックのようですが、
これは、Xcode 5 の規則に準拠するように調整された、元のコードのわずかに変更されたバージョンです。ご覧のとおり、重い作業は元の main() ではなく applicationDidFinishLaunching メソッドにあります。明らかに、AppDelegate.h ファイルでメソッド宣言を作成する必要がありましたが、これも元のコードの一部ではありません。
#import "AppDelegate.h"
#import <Cocoa/Cocoa.h>
#import <ApplicationServices/ApplicationServices.h>
#include <Carbon/Carbon.h>
@implementation AppDelegate
CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
NSLog(@"In the callback");
//0x0b is the virtual keycode for "b"
//0x09 is the virtual keycode for "v"
if ((type != kCGEventKeyDown) && (type != kCGEventKeyUp))
NSLog(@"event: %@", event);
if (CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode) == kVK_ANSI_S) {
NSLog(@"event matched");
CGEventSetIntegerValueField(event, kCGKeyboardEventKeycode, kVK_ANSI_1);
}
return event;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSLog(@"Hello?");
CFRunLoopSourceRef runLoopSource;
CFMachPortRef eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, kCGEventMaskForAllEvents, myCGEventCallback, NULL);
if (!eventTap) {
NSLog(@"Couldn't create event tap!");
exit(1);
}
runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
CGEventTapEnable(eventTap, true);
CFRunLoopRun();
CFRelease(eventTap);
CFRelease(runLoopSource);
NSLog(@"goodbye");
}
@end
現時点では、10.4 互換性へのバックポートを試みる前に、概念実証として 10.9 で何かを動作させようとしています。長い投稿で申し訳ありません。ここで初めて助けを求め、徹底的にしようとしています。事前にすべての応答に感謝します!