2

ユーザーのキーボードストロークを聞く必要があるプログラムを書いています。

関数 XGrabKeyboard() を使用します。これが私のコードです。

XGrabKeyboard(pDisplay, DefaultRootWindow(pDisplay), True, GrabModeAsync, GrabModeAsync, CurrentTime);
XEvent event;
while (true)
{
  XNextEvent(pDisplay, &event);
  switch (event.type)
  {
  ...
  }
}

ただし、キーボードとカーソルがフリーズします。

man ページを調べたところ、「3 番目のパラメーターは、キーボード イベントを通常どおり報告するかどうかを示すブール値を指定します」としか書かれていません。

true または false の両方、または 3 番目のパラメーター、4 番目と 5 番目のパラメーターの GrabModeAsync と GrabModeSync の両方を試しましたが、機能しません。

XGrabKeyboard() を呼び出した後、キーボードがフリーズし、マウス クリックが応答しません。

何か案は?

4

2 に答える 2

3

XGrabKeyboard() (成功した場合 - 戻り値を確認してください) は、すべてのキー イベントをクライアントにリダイレクトします。

そのため、while(true) 内の "..." がこれらのキー イベントを適切に処理しない場合、または同期イベント (XAllowEvents、GrabModeSync にのみ適用) を解放 (XUngrabKeyboard) またはリリースしない場合、キーボードはロックされているように見えます。上。

boolean パラメーターは owner_events で、キー イベントを常に XGrabKeyboard に提供されたウィンドウに報告するか、通常グラブなしで移動するウィンドウに報告するかを示します。通常、False (グラブ ウィンドウにレポート) が必要です。

XGrabKeyboard の典型的な使用 (ユースケースはわかりません) の場合、必要なパラメーターは次のとおりです。

  • グラブ ウィンドウ = グラブの理由に関連するアプリ内のウィンドウ
  • owner_events=False を指定すると、すべてのイベントがそのウィンドウに送信されます
  • pointer_mode=Async はポインタをねじ込まないようにします
  • keyboard_mode=Async は、すべての主要なイベントをリダイレクトするだけで、AllowEvents の必要性を回避します
  • time = グラブをトリガーするイベントからのタイムスタンプ、理想的には、プロパティを変更して PropertyNotify からタイムスタンプを取得することによって生成されたタイムスタンプ

しかし、それは依存します。おそらくコンパイル可能なプログラムを投稿する必要がある決定的な答えを出すには、コードの「...」部分にバグがある可能性が高いと思います。おそらく他の人が実行できる単一ファイルのテスト ケースにアプリを絞り込んでみてください。または、なぜつかんでいるのか、全体像で何を達成しようとしているのかをもっと説明してください。

于 2012-09-03T13:05:21.830 に答える
1

私は XGrabKeyboard 関数を手伝うことはできません - 私は以前にそれを使用したことがなく、それがどのように機能するかわかりません - しかし、キーボードイベントを取得する別の方法を提案することができます.

XCreateWindow を使用してウィンドウを作成する場合、最後の引数は XSetWindowAttributes オブジェクトです。このオブジェクトにはメンバー event_mask があり、ウィンドウが受け取るイベントを選択するために使用できます。

私はこのように設定しました:

XSetWindowAttributes setWindAttrs
setWindAttrs.event_mask = ExposureMask           
                        | KeyPressMask  
                        | KeyReleaseMask    
                        | ButtonPressMask 
                        | ButtonReleaseMask;

これは、ウィンドウの作成時にこのオブジェクトを XCreateWindow に渡すと、キーボード キーの押下とマウス ボタンのクリックのイベントを受け取ることを意味します。

XPending(pDisplay)また、処理を待っているイベントがまだあるかどうかを確認するために使用できる別のメモ- そのため、行で置き換えることができtrueますwhile(true)

編集: また、フリーズの問題は、while ループのどこにも false を返さないことでしょうか? 投稿のビットを削除しない限り、無限ループに陥る可能性があります。上記で提案したように true を xpending に置き換えてみると、問題が解決するか、イベントを処理した後に false が返される可能性がありますが、XPending のように現在保留中のすべてのイベントを処理するのではなく、フレームごとに 1 つのイベントしか処理しないと思いますそれがあなたのやりたいことです。

于 2012-09-02T18:57:59.920 に答える