web-dev-qa-db-ja.com

一部のアプリがKeyReleaseイベントを残して、次にフォーカスされたアプリ/ウィンドウで消費されるのはなぜですか

dmen をスクリプト内でラップして入力をフィードし、それに基づいて操作しようとしていますが、Returnキーを押してdmenu入力を選択すると、dmenu時にフォーカスされているウィンドウにKeyReleaseイベントが送信されます。閉じます。そのアプリがそれに反応すると(私の場合はFirefoxのJavaScriptで発生しました)、望ましくないことが起こる可能性があります。

しかし、これは私のスクリプトやdmenuに固有のものではありません。また、私がテストした他のダイアログスタイルのXアプリ、特にssh-askpass、ksshaskpass、gpgパスフレーズダイアログなどでも発生します。

簡単なテストは次のとおりです。

  1. Ssh-askpassをキー(組み合わせ)にバインドします。そのためにi3-wm構成を使用します。
  2. ターミナルで以下を実行します。

    xev | grep -EA2 --line-buffered '^Key(Press|Release)' | sed -n 's/^.*\(Press\|Release\|keysym[^)]*\).*$/\1/p'
    
  3. バインドされたキーの組み合わせを押します。
  4. Returnキーを押して、ターミナルで次の出力を確認します。

    Release
    keysym 0xff0d, Return
    
  5. Pressの前のReturnを観察しないでください

これらのアプリがXイベントキューのReleaseを消費しないのはなぜですか?私はバグについて議論しますが、Xまたはアプリでは?

そのようなアプリを(python?)スクリプトでラップする場合、どうすればこれを修正できますか?

1
Klaas

KeyPressイベントを処理したアプリケーションは、通常、後続のKeyReleaseイベントを処理することは期待されていません。ユーザーがキーを押してから別のアプリケーションに切り替えてからキーを離すと、要求されたときにフォーカスの変更が発生することが予想されます。ユーザーがキーを離すまで遅延することは想定されていません。

入力イベントを処理するためのX11のアーキテクチャは非常に単純です。イベントがクライアントによって取得された場合、クライアントはイベントを受信します。または、イベントが取得されていない場合、現在フォーカスを持っているクライアントは、イベント。どのクライアントがKeyReleaseイベントを受信したかに基づいて、KeyPressイベントを個別にディスパッチする規定はありません。

KeyReleaseを受信したクライアントにKeyPressイベントを再ルーティングすることが明らかに間違っている例は、修飾子を使用する場合です。フォーカスの変更時に、モディファイヤが押された場合、それは押されたままになります。 KeyReleaseイベントは、修飾子が押されなくなったときに送信されます。フォーカスが失われたときに押されたすべての修飾子に対してKeyReleaseイベントを送信し、対応するKeyPressイベントを新しくフォーカスされたウィンドウに送信することは理にかなっていますが、実際の正確なレポートではありません。ユーザー入力。これは、同じアプリケーションのウィジェット間のフォーカス変更で特に混乱を招きます。

X11の動作が明らかに正しく、キー押下イベントの再ルーティングの提案が間違っている別の例は、同じアプリケーションのウィジェット間でフォーカスを変更する場合です。アプリケーションがどのウィジェットにフォーカスされているかを気にせずにこの特定のキーを気にする場合、偽のイベントを送信するのは誤りです。ただし、アプリケーションがどのウィジェットがKeyReleaseイベントを受信するかを気にする場合、このイベントは、その時点でフォーカスがあるウィジェットに確実に送信される必要があります。

ほとんどのアプリケーションには、キーリリースイベントではなく、キー押下イベントによってトリガーされるアクションがあります。イベントによってボタンが押された場合、ボタンの効果は、離したときではなく、押したときにトリガーされると予想されます。ウィンドウの閉鎖を引き起こすイベントの動作が異なる場合、ユーザーエクスペリエンスは奇妙になります。

キーを押したためにウィンドウが閉じたときにフォーカスを別のウィンドウに移動させることが明らかに正しい例は、 Esc キーを押したままにして、複数のダイアログボックスを終了します。アプリケーションがリリースを必要とする場合、それは破壊的です Esc ウィンドウを閉じるために離すキー。

あなたが説明するシナリオでは、明らかに何か問題を起こしているのはFirefox/JavaScriptアプリケーションです。ほとんどのキーボードインターフェイスは、キーのリリースではなく、キーの押下に基づいています。特に、それは押す Enterリリースそれではなく、何かが起こることになっています。アプリケーションがキーリリースイベントに反応する場合、適切な方法で一致するKeyReleaseを受信せずに、KeyPressイベントを受信する状況を処理する責任がアプリケーションにあります。

ドラッグアンドドロップやクリックの長さに依存するイベントなど、リリースイベントにインターフェイスが反応すると予想される状況が多数あるため、マウスクリックは多少異なります。それでも、アプリケーションは通常、対応するButtonReleaseを取得しなかった場合、ButtonPressイベントに反応しないはずです。