2016-07-24 21 views
5

Ich versuche, Tastatureingabe zu hören (mit einer X11-Ereignisschleife) und Scancodes erhalten. Diese Scancodes sollten sich auf den physischen Speicherort eines Schlüssels und nicht auf das eingegebene Zeichen beziehen. Das Problem ist, alles, was ich bekommen kann, sind KeySyms und KeyCodes, die für verschiedene Sprachen unterschiedlich zugeordnet sind (QWERTY vs QWERTZ zum Beispiel).Get Scancode anstelle von Keycode unter Linux mit X11

Meine aktuelle Lösung ist das Lesen der Datei "/ usr/share/X11/xkb/keycodes/evdev". Es enthält die Zuordnungen von Schlüsselpositionen zu Schlüsselcodes. Mit diesem kann ich einfach jeden Schlüsselcode zurück in einen Scancode übersetzen. Meine Vermutung ist, dass dies keine stabile Art ist, Dinge zu tun. Ich weiß überhaupt nicht viel über Linux. Deshalb dachte ich, dass es eine gute Idee wäre, hier zu fragen.

Ist es sicher anzunehmen, dass diese Evdev-Mappings von den meisten Computern des Benutzers verwendet werden? Wenn nicht, wo könnte ich sonst noch Schlüssel-Mappings finden? Oder gibt es eine bessere Lösung für all das?

+1

Die Idee, dass ein Schlüssel einen festen physischen Speicherort hat, hängt von einer bestimmten Implementierung der Zeicheneingabe ab. Leute können virtuelle Tastaturen verwenden, wo sie Schlüssel selbst neu anordnen können. Oder handschriftliche Eingabe oder Spracherkennung oder ... In jedem dieser Fälle gibt es keine physischen Orte, die mit Schlüsseln verknüpft sind.Auch wenn es eine physische Tastatur mit Scancodes gibt, gibt es viele inkompatible Modelle, siehe andere Dateien in '/ usr/share/X11/xkb/keycodes'. –

+0

Das macht Sinn. Nehmen wir an, wir ignorieren andere spezielle Eingabemethoden als herkömmliche Tastaturen. Wenn eine der Dateien in "/ usr/share/X11/xkb/keycodes" für das Mapping verwendet werden könnte, gibt es eine Möglichkeit zu erkennen, welche von ihnen von einem Gerät verwendet wird? – ComfyS

+0

Sie können den physischen Speicherort von Schlüsseln ermitteln, indem Sie die Tastaturgeometrie untersuchen. Führen Sie 'setxkbmap -print -verbose 10' aus, und Sie sehen eine Include-Anweisung für die Geometrie. Untersuchen Sie Dateien in X11/xkb/geometry (höchstwahrscheinlich eine namens "pc"). Sie sehen auch, welches Mapping verwendet wird. Ich kenne keine programmatische Entsprechung zu 'setxkbmap -print', aber es gibt definitiv eine. Ich bin nicht sicher, was passiert, wenn der Benutzer seine Tastatur mit xmodmap neu anordnet, aber ich würde sagen, lassen Sie sie damit umgehen. –

Antwort

3

Ich hatte das gleiche Problem und ich habe gerade eine Lösung gefunden. Beginnen wir mit dem Offensichtlichen zuerst.

Wenn Sie spezifische Schlüssel wie "W" oder "4" erhalten möchten, können Sie den Schlüsselcode, den Sie vom Ereignis erhalten, einfach in ein KeySym konvertieren. In diesem Fall ist "W" XK_W und XK_w und "4" ist XK_4 (und XK_dollar auf den meisten Tastaturen).

Aber manchmal möchten Sie Tasten wie „die n-te Schlüssel des m th Reihe“ bekommen. Sie benötigen Schlüsselnamen, um das zu tun. In diesem Fall ist "W" AD02 und "4" ist AE04 auf QWERTY-Tastaturen.

Nehmen wir an, Sie machen ein Spiel, in dem der Spieler die WASD-Tasten verwenden muss, um sich zu bewegen. Wenn Sie nach KeySyms suchen, wird es auf QWERTY-Tastaturen gut funktionieren, aber Leute, die andere Tastaturlayouts wie AZERTY, QWERTZ und DVORAK verwenden, werden Probleme haben. In diesem Fall ist es besser, Schlüsselnamen zu verwenden.

Die Verwendung von Schlüsselnamen ist eigentlich ziemlich einfach, aber die documentation ist sehr chaotisch (aber ich empfehle immer noch, dass Sie einen Blick darauf werfen). Ich musste einen Blick auf GLFW 's Quellcode werfen (speziell src/x11_init.c), weil ich keine Ahnung hatte. Diese Methode benötigt Xkb, aber Sie haben es bereits benutzt, also ist das kein Problem.

Zuerst müssen Sie die Tastaturbelegung erhalten und symbolische Namen erhalten. Wir wollen nur Schlüsselnamen, also verwenden wir XkbKeyNamesMask.

#include <X11/XKBlib.h> 

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

Dann wird in der Ereignisschleife können Sie die Verwendung KbDesc-> Namen-> Schlüssel Array den Schlüsselnamen für einen bestimmten Schlüsselcode zu erhalten:

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... */ 
     } 
     /* ... */ 
    } 

    /* ... */ 
} 

Und das ist es. Es scheint bisher ziemlich gut zu funktionieren. Ich möchte erwähnen, dass spezielle Schlüssel sehr unterschiedliche Schlüsselnamen haben. Zum Beispiel ist Left Shift LFSH, Left Control ist LCTL, Space ist SPCE und Escape ist ESC.

Ich hoffe es hilft.