2

実験として、次のことを達成しようとしています。

  • Shift キーのように、スペースバーを修飾キーとして機能させます。スペースバー キーを押したままにしておくと、キーを入力すると、異なる文字が出力されます。スペースバーを放すと状態が通常に戻り、それを押すだけで通常のスペース キーのように動作します。

キーダウンとキーアップのイベントを処理することを考えていましたが、どうやらhandleEvent:client:IMKServerInputプロトコルではキーダウンとマウスのイベントのみをキャッチするようです。

ココアの経験があまりないので、いくつかの方法を試しましたが成功しませんでした:

  • インターネットアーカイブを介してテクニカルノート2128を調べたところ、plistアイテムの適切な説明が得られました。それでも、キーアップについては何もありません。
  • IMKStateSetting ProtocolrecognizedEvents:にNSKeyUpMask を追加しようとしましたが、それもイベントをキャッチしていないようです。
  • addLocalMonitorForEventsMatchingMask:handler:で少しテストしました が、何も起こりません。
  • NSFlagsChangedスペースバーでイベントを発生させる方法が見つかりませんでした。
  • Quartz Event Serviceについて読んCGEventTapでください。これは、下位レベルでユーザー入力を処理しているようです。まだこのルートには進んでいません。
  • IOHIDマネージャー?

IMKit は受動的にイベントを受信することしかできないという結論に達しました。アプリケーションではないためkeyUp:、オーバーライドする方法はありません-AFAIK、IMKitはNSResponderクラスを継承しません。

残念なことに、cocoa はあまりにも広範すぎて、私のような初心者が飛び込むためのドキュメンテーションがはるかに少ない (または役に立たないもので溢れている) のです。

誰でも正しい方向に私を助けることができますか?

4

2 に答える 2

1

考えられるすべての代替案を 1 つずつ試し、最終的にはグローバルな EventTap をCGEventTap.

コードは基本的に次のようになります。

// Create an event tap.
CGEventMask eventMask = ((1 << kCGEventKeyDown) | (1 << kCGEventKeyUp));
CFMachPortRef eventTap = CGEventTapCreate(kCGSessionEventTap,
                            kCGHeadInsertEventTap,
                            0,
                            eventMask,
                            myCGEventCallback,
                            NULL);

if (!eventTap) {
    NSLog(@"failed to create event tap\n");
    return NO;
} else {
    // Create a run loop source.
    runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
    // Add to the current run loop.
    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
    // Enable the event tap.
    CGEventTapEnable(eventTap, true);
    return YES;
}

wheremyCGEventCallbackはグローバルな状態を処理します。

その間、私が見つけたもののいくつかを以下に示します。

  • The Key-Input Message Sequenceドキュメントによると、アプリケーションは、チェーン内の他の一連のハンドラーを試行した後、keydown イベントのみをインプット メソッド キットに渡します。IMKServerInputNSKeyUp イベントを「キャッチ」することはできません。NSKeyUpMasktoを追加するだけでは機能しrecognizedEvents:ません。
  • addLocalMonitorForEventsMatchingMask:handler:イベントをキャッチしCGEventTapCreateForPSNません。これは、インプット メソッドが別のプロセスとして実行される可能性がありますが、イベント自体は TextEdit などのアプリケーションから起動され、インプット メソッドに渡されるためだと思います。
  • IOHIDManager:新しいハードウェア デバイスを追加し、ドライバーを作成するためのものです。
  • グローバルな EventTap を作成するには、プロセスを sudo 権限で実行するか (Input Method を にコピーしても/Library/Input Methodssudo 権限では実行されません)、アプリケーションをアクセシビリティ コントロールに登録する必要があります。これは、Mavericks のシステム環境設定 → セキュリティとプライバシー → プライバシー タブ → アクセシビリティにあります。
于 2014-06-08T11:14:23.417 に答える