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.
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'. –
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
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. –