2016-07-24 10 views
5

キーボード入力(X11イベントループを使用)を聞き取り、スキャンコードを取得しようとしています。これらのスキャンコードは、キーが入力する文字ではなく、キーの物理的な位置を参照する必要があります。問題は、私が得ることができるのは、KeySymsとKeyCodesであり、異なる言語(QWERTYとQWERTZなど)で別々にマッピングされていることです。X11を使用してLinuxでキーコードではなくスキャンコードを取得

私の現在の解決策は、 "/ usr/share/X11/xkb/keycodes/evdev"ファイルを読むことです。キーコードへのキーロケーションのマッピングが含まれています。これを使用して、任意のキーコードをスキャンコードに変換することができます。私の推測は、これは物事を行う安定した方法ではないということです。私はLinuxについてまったく知らない。だからこそ私はここでの質問が良いアイデアかもしれないと思った。

これらのevdevマッピングがほとんどのユーザーのマシンで使用されていると想定するのは安全でしょうか?そうでない場合は、実際に使用されているキーマッピングが他にどこにありますか?それとももっと良い解決策がありますか?

+1

キーが固定された物理的な場所を持つという考えは、文字入力の特定の実装に依存します。人々は、キー自体を自由に並べ替えることができる仮想キーボードを使用することができる。または手書きの入力または音声認識またはこれらのいずれの場合でも、キーに関連付けられた物理的な場所はありません。スキャンコードを持つ物理的なキーボードがあっても、互換性のないモデルがたくさんあります。 '/ usr/share/X11/xkb/keycodes'の他のファイルを参照してください。 –

+0

それは理にかなっています。従来のキーボード以外の特別な入力方法を無視するとします。 "/ usr/share/X11/xkb/keycodes"にあるファイルのいずれかがマッピングに使用されている場合、そのファイルがデバイスによって使用されているかどうかを検出する方法はありますか? – ComfyS

+0

キーボードのジオメトリを調べることで、キーの物理的な位置を取得できます。 'setxkbmap -print -verbose 10'を実行すると、ジオメトリのinclude文が表示されます。 X11/xkb /ジオメトリ(おそらく "pc"という名前のファイル)を調べます。使用中のマッピングも表示されます。私は 'setxkbmap -print'に相当するプログラマティックを知りませんが、確かに一つです。ユーザーがxmodmapを使ってキーボードを再マッピングするとどうなるか分かりませんが、私はそれに対処すると言います。 –

答えて

3

私は同じ問題を抱えていましたが、解決策を見つけました。明白な最初から始めましょう。

「W」や「4」などの特定のキーを取得したい場合は、その場所のどこにあっても、イベントから受け取ったキーコードをKeySymに変換することができます。この場合、「W」​​はXK_WおよびXK_wであり、「4」はXK_4(ほとんどのキーボードではXK_dollar)です。

しかし、時には「th行のキー」などのキーを取得したい場合があります。それを行うにはキー名が必要です。この場合、「W」​​はAD02で、QWERTYキーボードでは「4」はAE04です。

プレイヤーがWASDキーを使用して移動する必要があるゲームを作っているとします。 KeySymsを探すと、QWERTYキーボードで正常に動作しますが、AZERTY、QWERTZ、DVORAKなどの他のキーボードレイアウトを使用している人には問題があります。したがって、この場合はキー名を使用する方がよいでしょう。

実際にキー名を使用するのはかなり簡単ですが、documentationは非常に面倒です(ただし、まだ見てみることをお勧めします)。私は無知だったのでGLFWのソースコード(具体的にはsrc/x11_init.c)を見なければならなかった。この方法にはXkbが必要ですが、既にそれを使用していたので問題はないと思います。

まず、キーボードマップを取得して記号名を取得する必要があります。キー名だけが必要なので、XkbKeyNamesMaskを使用します。

XEvent Event; 
XNextEvent(XDisplay, &Event); 

switch (Event.type) 
{ 
case KeyPress: 
    /* I'm not sure this 'if' is necessary, but better safe than sorry */ 
    if ((Event.xkey.keycode >= KbDesc->min_key_code) && (Event.xkey.keycode <= KbDesc->max_key_code)) 
    { 
     /* Copy key name into Name */ 
     char Name[XkbKeyNameLength + 1]; 
     memcmp(Name, KbDesc->names->keys[Event.xkey.keycode].name, XkbKeyNameLength); 
     Name[XkbKeyNameLength] = '\0'; /* Null terminator */ 

     if (strcmp(Name, "AD02") == 0) /* Is it W (for QWERTY and QWERTZ)/Z (for AZERTY)/comma (for DVORAK)/ц (for Russian) etc... ? */ 
     { 
      /* Do something... */ 
     } 
     else if (strcmp(Name, "AE04") == 0) /* Is it 4 (for most keyboards)/whatever's in its place? */ 
     { 
      /* Do something... */ 
     } 
     /* ... */ 
    } 

    /* ... */ 
} 

をそして、それはこれだけです:

#include <X11/XKBlib.h> 

XkbDescPtr KbDesc = XkbGetMap(XDisplay, 0, XkbUseCoreKbd); 
XkbGetNames(XDisplay, XkbKeyNamesMask, KbDesc); 

その後、イベントループで、あなたは、特定のキーコードのキー名を取得するKbDesc-> names->キー配列を使用することができます。それはこれまでかなりうまくいくようです。私は特別なキーは非常に異なるキー名を持っていることを言及したいと思います。たとえば、左シフトはLFSH、左コントロールはLCTL、スペースはSPCE、エスケープはESCです。

私はそれが役に立ちそうです。

関連する問題