2009年03月06日

キーボード状態の取得

先日相対移動できるXWarpPointerと
カーソル位置とマウスの状態の取得できるXQueryPointerを使えるようになったので
今度はキーボード状態を取得しようと思った。
xlib経由なのでDirectInputではないけれどメッセージよりはましかもしれない。
キーボードステータスの直接取得はXQueryPointerに対応してXQueryKeymapで得られるようだ。

char keys[32];

を用意して

XQueryKeymap(dpy, keys);

でいい。

http://tronche.com/gui/x/xlib/input/XQueryKeymap.html
をみると


Byte N (from 0) contains the bits for keys 8N to 8N + 7

とか書いてあるのだけれど
ようするに32x8=256っーことなのね、
たったビットの位置のキーが押されているということのようだ。
真面目に実装する場合は配列二つ使ってトリガーチェックしないとだめそう。

まだよくCの事を分かっていなかったので
よもや32byteスタックにぶち込むのかと思ったが
charの配列の場合はポインタを入れるというのが暗黙のルールのようだ。


unsigned long int* lkeys;
lkeys=(unsigned long int *)&keys;

と32bitポインタ型をアサインすると

printf("\n%X %X %X %X\n",lkeys[0],lkeys[1],lkeys[2],lkeys[3]);

みたいに表示できる。

XGetKeyboardMappingとXKeysymToStringで名称とか得られるようだ。
ためしてみると

//const
const unsigned char maskb[8]={1,2,4,8,0x10,0x20,0x40,0x80};
//var
Display *dpy;
int i,j,k;
Window root;
char keys[32];
KeyCode keycode;
KeySym *keysym;

//begen
XQueryKeymap(dpy, &keys[0]);
for (i = 0; i < 32; i++) {
if (keys[i] ){
for (j = 0; j < 8; j++) {
if (keys[i] & maskb[j]) {
keycode = i * 8 + j;
keysym = XGetKeyboardMapping(dpy, keycode, 1, &k);
if (keysym && *keysym)
printf("%s\n", XKeysymToString(*keysym));
}
}
}
}


という感じかな?
イベントで取る場合もXが同様の事をしているだろうからさしてロスは無いと思う。
一つキーを押した場合ループは40回回る。
int配列で最初のチェックをすると8+4+8で20回ですむ
キーマクロとかシフトとかaltとか先にマスクでひいちゃった方が手っ取り早いのかもしれない。

kb2mb2とかもこの手を使っているのだと思ったら違った。

XGrabKeyboardとかXGrabKeyを使っていた。
この二つはキーイベントの横取りをする。
XGrabKeyboardはXUngrabKeyboardの解除とセットで
完全指定Window以外のキー入力を遮断する。
DefaultRootWindow でとったwindowを指定したのだが
起動したコンソールも含めてキー入力がなくなった。
それでもXQueryKeymapでのデータ取得はできた。

XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime);
.
.
.
XUngrabKeyboard(dpy, CurrentTime);

Displayのdpyとroot以外はライブラリー側の変数だ。

kb2mb2は割り当てキー設定時にこのXGrabKeyboardを使い
実行時はXGrabKey使用後イベントルーブで取得していた。

XGrabKey(dpy, maskkey, AnyModifier, root, True, GrabModeAsync, GrabModeAsync);

例えばmaskkeyを「0x3a」にすると「m」が他のアプリで入力できなくなるわけだ。
これらの機能はDirec Inputの排他アクセスに似ている。

kb2mb2の場合は1キー決め打ちなので

XSelectInput(dpy, root, KeyPressMask);

を宣言しておき
XGrabKey実行後にXNextEventでキーイベントを拾って処理をしている。
Xwindowでは使わないRight Windowsキーが前提なのでこの手法が使えるが
イベントループを回すよりは XQueryKeymapで該当部とチェックする方がいいかなと感じた。
ただその場合キーマップを配列の番号とマスクで表現しないといけないので
設定時に位置とマスクは生成しないといけないだろう。

とりあえずキーボードとマウスの取得、ジョイスティックの取得
キーボードとマウスの仮想出力までの下地はそろった。
ラベル:xlib
posted by Xo_ox at 15:50| Comment(0) | FreeBSDアプリ | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。