キーイベント
キーボード上のキーが押された時は KeyPress イベント、キーが離された時は KeyRelease イベントが来ます。
各キーの押し状態をまとめて取得したい時は、KeymapNotify イベントを処理します。
キーボードの入力イベントは、入力フォーカスがあるウィンドウに対してのみ送られてきます。
入力フォーカスがこのウィンドウに来た時は FocusIn イベント、入力フォーカスがこのウィンドウから離れた時は FocusOut イベントが来ます。
各キーの押し状態をまとめて取得したい時は、KeymapNotify イベントを処理します。
キーボードの入力イベントは、入力フォーカスがあるウィンドウに対してのみ送られてきます。
入力フォーカスがこのウィンドウに来た時は FocusIn イベント、入力フォーカスがこのウィンドウから離れた時は FocusOut イベントが来ます。
KeyPress/KeyRelease イベント
typedef struct { int type; unsigned long serial; Bool send_event; Display *display; Window window; Window root; Window subwindow; Time time; int x, y; int x_root, y_root; unsigned int state; unsigned int keycode; Bool same_screen; } XKeyEvent; typedef XKeyEvent XKeyPressedEvent; typedef XKeyEvent XKeyReleasedEvent;
キーボードのキーが押された時/離された時に来ます。
KeyPressMask, KeyReleaseMask のイベントマスクが必要です。
XEvent 構造体の xkey から参照できます。
基本的に、ポインタイベントの時と同じような値になります。
x,y 座標は、現在のポインタの位置です。このウィンドウ上にポインタがなくても、常に window の原点を基準とした相対位置になります。
keycode は、キーの物理番号です。
FocusIn/FocusOut イベント
typedef struct { int type; unsigned long serial; Bool send_event; Display *display; Window window; int mode; int detail; } XFocusChangeEvent; typedef XFocusChangeEvent XFocusInEvent; typedef XFocusChangeEvent XFocusOutEvent;
入力フォーカスが変わった時に来ます。
FocusChangeMask イベントマスクが必要です。
XEvent 構造体の xfocus から参照できます。
mode | NotifyNormal (0) : 通常イベント NotifyGrab (1) : キーボードグラブが開始されたときのフォーカスイベント NotifyUngrab (2) : キーボードグラブが解放されたときのフォーカスイベント NotifyWhileGrabbed (3) : キーボードグラブ中のフォーカスイベント |
---|---|
detail | フォーカスが変化したウィンドウの関係を表す。 NotifyAncestor, NotifyVirtual, NotifyInferior, NotifyNonlinear, NotifyNonlinearVirtual, NotifyPointer, NotifyPointerRoot, NotifyDetailNone |
KeymapNotify イベント
typedef struct { int type; unsigned long serial; Bool send_event; Display *display; Window window; char key_vector[32]; } XKeymapEvent;
すべての物理キーごとの押し状態が送られてきます。
EnterNotify および FocusIn イベントの直後に、このイベントが生成されます。
KeymapStateMask イベントマスクが必要です。
XEvent 構造体の xkeymap から参照できます。
key_vector は、256 個の物理キーの押し状態のフラグです。
[0] の下位ビットから順に並んでいます。
※各キーの押し状態が変化した時には来ません。常に現在の押し状態のデータを維持したい場合、このイベントの後、KeyPress/KeyRelease を自分で処理して、フラグを更新する必要があります。
XQueryKeymap 関数を使って、現在のデータを取得することも出来ます。
vpod XQueryKeymap(Display *display, char keys_return[32]);
プログラム
キーイベントを確認するプログラムです。
ウィンドウに入力フォーカスがある状態で、キーを押してみてください。
ウィンドウ内でポインタのボタンを押すと終了します。
<13-key.c>
ウィンドウに入力フォーカスがある状態で、キーを押してみてください。
ウィンドウ内でポインタのボタンを押すと終了します。
<13-key.c>
#include <stdio.h> #include <X11/Xlib.h> #include "util.h" int main(int argc,char **argv) { Display *disp; XSetWindowAttributes attr; Window win; XEvent ev; disp = XOpenDisplay(NULL); if(!disp) return 1; //ウィンドウ作成 attr.background_pixel = 0; attr.event_mask = ButtonPressMask | KeymapStateMask | KeyPressMask | KeyReleaseMask | FocusChangeMask; 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: printf("- [Key%s] x(%d) y(%d) keycode(%u)\n", (ev.type == KeyPress)? "Press": "Release", ev.xkey.x, ev.xkey.y, ev.xkey.keycode); put_state(ev.xkey.state); fflush(stdout); break; case FocusIn: case FocusOut: printf("* [Focus%s] mode(%d) detail(%d)\n", (ev.type == FocusIn)? "In": "Out", ev.xfocus.mode, ev.xfocus.detail); fflush(stdout); break; case KeymapNotify: printf("# [Keymap]\n"); fflush(stdout); break; case ButtonPress: goto END; } } END: XCloseDisplay(disp); return 0; }