デバイス情報のクラス
前回、デバイス情報の一覧を表示しましたが、classes メンバの値は表示していませんでした。
ここでは、各デバイスのクラスの情報について説明します。
デバイスのクラスには、そのデバイスで操作できるボタン・キーや、取得できる値などの情報が格納されています。
classes は、XIAnyClassInfo 構造体のポインタの配列で構成されています。
ただし、実際のクラス構造体は、タイプによって情報が異なるため、まずは、XIAnyClassInfo 構造体の type メンバでクラスのタイプを確認し、その後、(XIAnyClassInfo *) のポインタを各タイプごとの構造体のポインタに型変換してから、値を参照する必要があります。
※ここでは、タッチに関する情報は扱いません。
ここでは、各デバイスのクラスの情報について説明します。
デバイスのクラスには、そのデバイスで操作できるボタン・キーや、取得できる値などの情報が格納されています。
classes は、XIAnyClassInfo 構造体のポインタの配列で構成されています。
ただし、実際のクラス構造体は、タイプによって情報が異なるため、まずは、XIAnyClassInfo 構造体の type メンバでクラスのタイプを確認し、その後、(XIAnyClassInfo *) のポインタを各タイプごとの構造体のポインタに型変換してから、値を参照する必要があります。
クラスタイプと、対応する構造体
XIKeyClass | XIKeyClassInfo |
---|---|
XIButtonClass | XIButtonClassInfo |
XIValuatorClass | XIValuatorClassInfo |
XIScrollClass (ver 2.1) | XIScrollClassInfo |
XITouchClass (ver 2.1) | XITouchClassInfo |
XIGestureClass (ver 2.4) | XIGestureClassInfo |
※ここでは、タッチに関する情報は扱いません。
XIKeyClass
キーボードなどで、キーイベントとして送信できるキーがある場合、1つのキークラスがあります。
typedef struct { int type; int sourceid; int num_keycodes; int *keycodes; } XIKeyClassInfo;
num_keycodes | このデバイスで使用できるキーコード (物理ボタン) の数。1以上 |
---|---|
keycodes | デバイスが送信できるキーコードの配列 (num_keycodes 個) |
XIButtonClass
マウスなどで、ポインタボタンとしてイベントを送信できる場合、1つのボタンクラスがあります。
※そのデバイスで実際に存在しているボタンの情報ではなく、X のポインタボタンとして扱う際のボタンの情報です。
※そのデバイスで実際に存在しているボタンの情報ではなく、X のポインタボタンとして扱う際のボタンの情報です。
typedef struct { int type; int sourceid; int num_buttons; Atom *labels; XIButtonState state; } XIButtonClassInfo; typedef struct { int mask_len; unsigned char *mask; } XIButtonState;
num_buttons | このデバイスで使用できるボタンの数。1 以上 |
---|---|
labels | 各ボタンのラベルを示すアトムの配列 (num_buttons 個)。 値が None の場合があります。 |
state | クライアントから見た時の、現在のボタンの押し状態。 ※ボタンマッピングが適用された後 (Xlib の XSetPointerMapping 関数参考) mask_len は、mask のバイト数。 mask は可変長の配列で、先頭バイト&下位ビットから順に、各ボタンが押されているかどうかのフラグがセットされています。 X のボタン番号がそのままビット位置に対応するため、Button1 (1) は先頭バイトの bit1 (0x02) になります。 一番最初のビットはボタン番号 0 となるため、実際は使用されません。 |
XIValuatorClass
キーやボタンの他に、値として送信できる情報がある場合、バリュエータクラスが、その個数分あります。
X・Y 座標やスクロール、筆圧などです。
X・Y 座標やスクロール、筆圧などです。
typedef struct { int type; int sourceid; int number; Atom label; double min; double max; double value; int resolution; int mode; } XIValuatorClassInfo;
number | このデバイスでのバリュエータ番号 (0〜) |
---|---|
label | None でない場合、種類を示すアトム |
min,max | 許可されている最小値と最大値。 両方ともゼロの場合、このデバイスには最小値も最大値もない。 |
value | 現在の値 |
resolution | 解像度 (units/m) |
mode | XIModeAbsolute で、値は絶対値。 XIModeRelative で相対値。 |
XIScrollClassInfo (ver 2.1)
スクロール (マウスホイール) に関する情報です。
コアの X では、Button4 を垂直ホイール Up、Button5 を垂直ホイール Down、Button6 を水平ホイール Up、Button7 を水平ホイール Down として、ボタンとして扱いますが、XI2 では、ホイールを1単位分のスクロールとして扱うことができます。
デバイスのクラスに、スクロール用のバリュエータクラスがある場合 ("Rel Vert Scroll" など)、垂直/水平ごとに1つ、スクロールクラスがあります。
コアの X では、Button4 を垂直ホイール Up、Button5 を垂直ホイール Down、Button6 を水平ホイール Up、Button7 を水平ホイール Down として、ボタンとして扱いますが、XI2 では、ホイールを1単位分のスクロールとして扱うことができます。
デバイスのクラスに、スクロール用のバリュエータクラスがある場合 ("Rel Vert Scroll" など)、垂直/水平ごとに1つ、スクロールクラスがあります。
typedef struct { int type; int sourceid; int number; int scroll_type; double increment; int flags; } XIScrollClassInfo;
number | このスクロールが適用されるバリュエータ番号。 ("Rel Vert Scroll" などのバリュエータの number の値) |
---|---|
scroll_type | スクロールのタイプ。 XIScrollTypeVertical または XIScrollTypeHorizontal |
increment | スクロールの1単位の値 (正の値) |
flags | フラグ。 XIScrollFlagNoEmulation : サーバーは、このバリュエーターでの従来のボタンイベントをエミュレートしません。 XIScrollFlagPreferred : 同じスクロールタイプが複数ある場合、これが優先される。 |
プログラム
各デバイスの、クラス情報を表示するプログラムです。
<e08-xi2.c>
$ cc -o run e08-xi2.c util.c -lXlib -lXi
<e08-xi2.c>
#include <stdio.h> #include <X11/Xlib.h> #include <X11/extensions/XInput2.h> #include "util.h" //keyclass static void _put_keyclass(XIKeyClassInfo *p) { int i,*pcode; printf("<KeyClass> [srcid:%d] num:%d\n ", p->sourceid, p->num_keycodes); pcode = p->keycodes; for(i = 0; i < p->num_keycodes; i++) printf("%d,", *(pcode++)); printf("\n"); } //buttonclass static void _put_buttonclass(XIButtonClassInfo *p) { int i; printf("<ButtonClass> [srcid:%d] num:%d\n", p->sourceid, p->num_buttons); //labels for(i = 0; i < p->num_buttons; i++) { printf("btn%d: ", i + 1); if(p->labels[i]) { put_atom_name(p->labels[i]); printf("\n"); } else printf("<None>\n"); } //state printf("state:(len:%d) ", p->state.mask_len); for(i = 0; i < p->state.mask_len; i++) printf("0x%02X ", p->state.mask[i]); printf("\n"); } //valuator class static void _put_valclass(XIValuatorClassInfo *p) { printf("<ValuatorClass> [srcid:%d]\n" " number(%d) label(", p->sourceid, p->number); put_atom_name(p->label); printf(")\n"); printf(" min(%.3f) max(%.3f) value(%.3f) reso(%d) mode(%s)\n", p->min, p->max, p->value, p->resolution, (p->mode == XIModeAbsolute)? "Abs": "Rel"); } //scroll class static void _put_scrollclass(XIScrollClassInfo *p) { printf("<ScrollClass> [srcid:%d]\n" " number(%d) type(%s) inc(%.3f) flags(0x%X)\n", p->sourceid, p->number, (p->scroll_type == XIScrollTypeVertical)? "Vert": "Horz", p->increment, p->flags); } int main(int argc,char **argv) { Display *disp; XIDeviceInfo *info,*pi; XIAnyClassInfo **ppclass,*pclass; int major,minor,dnum,i,j,cnum; disp = XOpenDisplay(NULL); if(!disp) return 1; set_display(disp); //version major = 2, minor = 4; if(XIQueryVersion(disp, &major, &minor) != Success) { printf("unsupported XI2\n"); XCloseDisplay(disp); return 1; } //デバイス情報 info = XIQueryDevice(disp, XIAllDevices, &dnum); for(i = 0; i < dnum; i++) { pi = info + i; printf("\n---- [%s] (%d) ---\n", pi->name, pi->deviceid); cnum = pi->num_classes; ppclass = pi->classes; for(j = 0; j < cnum; j++, ppclass++) { pclass = *ppclass; switch(pclass->type) { case XIKeyClass: _put_keyclass((XIKeyClassInfo *)pclass); break; case XIButtonClass: _put_buttonclass((XIButtonClassInfo *)pclass); break; case XIValuatorClass: _put_valclass((XIValuatorClassInfo *)pclass); break; case XIScrollClass: _put_scrollclass((XIScrollClassInfo *)pclass); break; } } } XIFreeDeviceInfo(info); // XCloseDisplay(disp); return 0; }
出力例
---- [Wacom One by Wacom M Pen stylus] (10) --- <ButtonClass> [srcid:10] num:8 btn1: <None> btn2: <None> btn3: <None> btn4: <None> btn5: <None> btn6: <None> btn7: <None> btn8: <None> state:(len:8) 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 <KeyClass> [srcid:10] num:248 ... <ValuatorClass> [srcid:10] number(0) label(Abs X) min(0.000) max(21600.000) value(0.000) reso(100000) mode(Abs) <ValuatorClass> [srcid:10] number(1) label(Abs Y) min(0.000) max(13500.000) value(0.000) reso(100000) mode(Abs) <ValuatorClass> [srcid:10] number(2) label(Abs Pressure) min(0.000) max(65536.000) value(0.000) reso(1) mode(Abs) <ValuatorClass> [srcid:10] number(3) label(Abs Tilt X) min(-64.000) max(63.000) value(0.000) reso(57) mode(Abs) <ValuatorClass> [srcid:10] number(4) label(Abs Tilt Y) min(-64.000) max(63.000) value(0.000) reso(57) mode(Abs) <ValuatorClass> [srcid:10] number(5) label(Abs Wheel) min(-900.000) max(899.000) value(0.000) reso(1) mode(Abs) <ValuatorClass> [srcid:10] number(6) label(Rel Horiz Scroll) min(-1.000) max(-1.000) value(0.000) reso(1) mode(Abs) <ValuatorClass> [srcid:10] number(7) label(Rel Vert Scroll) min(-1.000) max(-1.000) value(0.000) reso(1) mode(Abs) <ScrollClass> [srcid:10] number(6) type(Horz) inc(65535.000) flags(0x0) <ScrollClass> [srcid:10] number(7) type(Vert) inc(65535.000) flags(0x0) ---- [ELECOM ELECOM BlueLED Mouse] (11) --- <ButtonClass> [srcid:11] num:9 btn1: Button Left btn2: Button Middle btn3: Button Right btn4: Button Wheel Up btn5: Button Wheel Down btn6: Button Horiz Wheel Left btn7: Button Horiz Wheel Right btn8: Button Side btn9: Button Extra state:(len:8) 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 <ValuatorClass> [srcid:11] number(0) label(Rel X) min(-1.000) max(-1.000) value(1752.576) reso(0) mode(Rel) <ValuatorClass> [srcid:11] number(1) label(Rel Y) min(-1.000) max(-1.000) value(834.192) reso(0) mode(Rel) <ValuatorClass> [srcid:11] number(2) label(Rel Horiz Scroll) min(-1.000) max(-1.000) value(0.000) reso(0) mode(Rel) <ValuatorClass> [srcid:11] number(3) label(Rel Vert Scroll) min(-1.000) max(-1.000) value(29880.000) reso(0) mode(Rel) <ScrollClass> [srcid:11] number(2) type(Horz) inc(120.000) flags(0x0) <ScrollClass> [srcid:11] number(3) type(Vert) inc(120.000) flags(0x0)
ボタンの state は、ボタンを押した状態でプログラムを実行すると、値を確認できます。
マウス
マウスは、垂直ホイールと、サイドボタンが2つあるタイプです。
X のポインタボタンでは、垂直ホイール・水平ホイールまでの機能は固定されているため、水平ホイールは実際のデバイスには存在しませんが、機能としては存在する形になります。
state は可変長のデータですが、すべてのデバイスで 8byte になっていました。最大で 63 個のボタンに対応する形です。
マウスのバリュエータには、X 座標、Y 座標、水平スクロール、垂直スクロールがあります。
なお、値が相対モードの場合、min,max の値は意味がないので、-1 になっています。
X のポインタボタンでは、垂直ホイール・水平ホイールまでの機能は固定されているため、水平ホイールは実際のデバイスには存在しませんが、機能としては存在する形になります。
state は可変長のデータですが、すべてのデバイスで 8byte になっていました。最大で 63 個のボタンに対応する形です。
マウスのバリュエータには、X 座標、Y 座標、水平スクロール、垂直スクロールがあります。
なお、値が相対モードの場合、min,max の値は意味がないので、-1 になっています。
ペンタブレット
ペンタブレットでは、キークラスもあります。
ドライバの設定によっては、ボタンをキー操作として扱うこともできるので、ペンタブレットからキーイベントを生成できる形になっています。
バリュエータには、X 座標、Y 座標、筆圧、傾き X、傾き Y、ホイール(円形の)、垂直スクロール、水平スクロールがあります。
いくつかの値は実際のデバイスには存在しませんが、ペンタブレットで使用できる一般的な値はすべて存在している形になります。
筆圧の情報を取得したい場合は、ラベルが "Abs Pressure" の値を確認することになります。
ドライバの設定によっては、ボタンをキー操作として扱うこともできるので、ペンタブレットからキーイベントを生成できる形になっています。
バリュエータには、X 座標、Y 座標、筆圧、傾き X、傾き Y、ホイール(円形の)、垂直スクロール、水平スクロールがあります。
いくつかの値は実際のデバイスには存在しませんが、ペンタブレットで使用できる一般的な値はすべて存在している形になります。
筆圧の情報を取得したい場合は、ラベルが "Abs Pressure" の値を確認することになります。
デバイスに関する情報
デバイスのクラスは、基本的に XI イベントに関連する情報ですが、ドライバが管理しているような、デバイスに関する詳細な情報は、デバイスに関連付けられたプロパティから、読み込み&変更することができます。
XIListProperties, XIGetProperty, XIChangeProperty, XIDeleteProperty が、プロパティに関する関数です。
例えばペンタブレットのデバイスでは、以下のようなプロパティが存在します。
それぞれがどのようなデータかはデバイスによるので、このような情報が必要な場合は、個別に処理してください。
XIListProperties, XIGetProperty, XIChangeProperty, XIDeleteProperty が、プロパティに関する関数です。
例えばペンタブレットのデバイスでは、以下のようなプロパティが存在します。
Wacom Debug Levels Device Product ID Wacom Panscroll Threshold Wacom Pressure Recalibration Wacom Button Actions Wacom button action 3 Wacom button action 2 Wacom button action 1 Wacom button action 0 Wacom Tool Type Wacom Touch Gesture Parameters Wacom Enable Touch Gesture Wacom Hover Click Wacom Enable Touch Wacom Sample and Suppress Wacom Pressure Threshold Wacom Proximity Threshold Wacom Serial ID binding Wacom Serial IDs Wacom Pressurecurve Wacom Rotation Wacom Tablet Area Device Node Device Accel Velocity Scaling Device Accel Adaptive Deceleration Device Accel Constant Deceleration Device Accel Profile Coordinate Transformation Matrix Device Enabled
それぞれがどのようなデータかはデバイスによるので、このような情報が必要な場合は、個別に処理してください。