X11: キーイベント時の情報

キーイベント時の情報
KeyPress/KeyRelease イベントが来た時、押されたキーの文字列や KeySym を取得したい場合は、XLookupString 関数などを使います。
キーイベントから KeySym を取得
KeySym XLookupKeysym(XKeyEvent *key_event, int index);

キーイベントの keycode を元に、キーマップデータから KeySym を取得します (修飾子は判断しません)。

index は、キーマップデータのインデックス位置です。
基本的に、0 が Shift OFF 時、1 が Shift ON 時です。詳細は前のページをご覧ください。
NoSymbol (0) が返る場合もあります。
キーイベントから KeySym や文字列を取得
<X11/Xutil.h>
int XLookupString(XKeyEvent *event_struct, char *buffer_return,
    int bytes_buffer, KeySym *keysym_return, XComposeStatus *status_in_out);

キーイベントから、各修飾子を適用した KeySym と、そのキーの文字列 (エディタに出力するような文字列) を取得します。

buffer_returnISO Latin-1 文字、または ASCII 制御文字に変換され、その文字列が返る。
bytes_bufferbuffer_return のバッファバイト数
keysym_returnKeySym が返る
status_in_out基本的に NULL にします
戻り値バッファに格納された文字数
オートリピート
X でキーのオートリピートが ON の場合は、キーが押されている間、一定間隔で KeyPress と KeyRelease イベントが交互に生成されます。

a のキーをずっと押していれば、エディタ上に "aaa..." と入力されることになります。

オートリピートの ON/OFF を切り替えることはできますが、X サーバーのグローバル設定を変更することになるので、すべてのクライアントに適用されてしまいます。

そのため、基本的にはデフォルトのまま (ON の状態) で、オートリピートによる KeyPress と KeyRelease イベントを、自分で解釈して処理した方が良いです。
KeyRelease の直後に、同じ keycode と time で KeyPress が来た場合は、オートリピートによるものと判断できます。
プログラム
XLookupString() で、KeySym と文字列を取得して表示しています。
オートリピート時のイベントも確認してみてください。

ポインタボタンを押すと終了します。

$ cc -o run 16-key2.c util.c -lX11

<16-key2.c>
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "util.h"

int main(int argc,char **argv)
{
    Display *disp;
    XSetWindowAttributes attr;
    Window win;
    XEvent ev;
    KeySym ksym;
    char m[16],*name;
    int len;
    
    disp = XOpenDisplay(NULL);
    if(!disp) return 1;

    //ウィンドウ作成

    attr.background_pixel = 0;
    attr.event_mask = ButtonPressMask | KeyPressMask | KeyReleaseMask;

    win = XCreateWindow(disp, DefaultRootWindow(disp),
        0, 0, 200, 200, 0,
        CopyFromParent, CopyFromParent, CopyFromParent,
        CWBackPixel | CWEventMask, &attr);

    XMapWindow(disp, win);

    //イベント

    while(1)
    {
        XNextEvent(disp, &ev);

        switch(ev.type)
        {
            case KeyPress:
            case KeyRelease:
                len = XLookupString((XKeyEvent *)&ev, m, 15, &ksym, 0);
                m[len] = 0;

                name = XKeysymToString(ksym);
                
                printf("[%s] keycode(%u) keysym(%lu)[%s] time(%lu)",
                    (ev.type == KeyPress)? "Press": "Release",
                    ev.xkey.keycode, ksym,
                    (name)? name: "-", ev.xkey.time);

                if(len)
                {
                    if(m[0] >= 0x20 && m[0] < 0x7f)
                        printf(" '%s'", m);
                    else
                        printf(" <%d>", m[0]);
                }

                printf("\n");
                put_state(ev.xkey.state);
                fflush(stdout);
                break;
            case ButtonPress:
                goto END;
        }
    }

END:
    XCloseDisplay(disp);

    return 0;
}

XLookupString() で取得した文字列は、ASCII 制御文字の場合があるので、Enter キーなら 13、Tab キーなら 9、Delete キーなら 127 になります。
'a' や '1' などの表示可能な文字かどうかは、最初の文字で判断してください。