XKB
XKB は、X のキーボードに関する拡張機能です。
キー押しなどのイベントは、X のイベントか、XInput 拡張機能のイベントを使って受け取ります。
XKB を使うと、キーボードの動作に関する詳細な設定などが行えます。
また、コアの X だけでは不十分な機能が拡張されています。
キー押しなどのイベントは、X のイベントか、XInput 拡張機能のイベントを使って受け取ります。
XKB を使うと、キーボードの動作に関する詳細な設定などが行えます。
また、コアの X だけでは不十分な機能が拡張されています。
使い方
XKB は Xlib (X11R6 以降) に含まれているので、別途拡張機能のライブラリをリンクする必要はありません。
インクルードファイルは、<X11/XKBlib.h> が必要です。
クライアントが XKB を明示的に使わない場合でも、Xlib のキーボード関連の関数は、内部で XKB を使うように置き換えられているので、意識せずとも、間接的に XKB が使用される形になります。
インクルードファイルは、<X11/XKBlib.h> が必要です。
クライアントが XKB を明示的に使わない場合でも、Xlib のキーボード関連の関数は、内部で XKB を使うように置き換えられているので、意識せずとも、間接的に XKB が使用される形になります。
初期化
クライアントが明示的に XKB の関数を使用したい場合は、まず初期化を行う必要があります。
X ディスプレイのオープンと XKB の初期化をまとめて行いたい場合は、XkbOpenDisplay() を使うことができます。
個別に XKB の初期化だけ行いたい場合は、XkbLibraryVersion() で XKB のライブラリのバージョンを確認し、XkbQueryExtension() で初期化&拡張機能の情報を取得します。
動的または静的にリンクされている XKB ライブラリのバージョンを確認します。
lib_major_in_out, lib_minor_in_out の各変数に、使用したいバージョンをセットして渡すと、ライブラリで実際に使用できるバージョンが返ります。
戻り値が True で、ライブラリのバージョンに互換性があります。
(現在の最新バージョンは 1.0)
ヘッダで定義されているバージョンを使用したい場合は、lib_major_in_out に XkbMajorVersion を、lib_minor_in_out に XkbMinorVersion をセットします。
サーバーに XKB 拡張機能が存在するかを確認し、バージョンの互換性の確認と初期化を行って、各情報を取得します。
major_in_out, minor_in_out には、XkbLibraryVersion() で取得したバージョンを指定します。
event_rtrn で取得した値は、XKB のイベントを判別するために使います。
戻り値が True で、拡張機能が存在し、バージョンに互換性があります。
X ディスプレイのオープンと XKB の初期化をまとめて行いたい場合は、XkbOpenDisplay() を使うことができます。
個別に XKB の初期化だけ行いたい場合は、XkbLibraryVersion() で XKB のライブラリのバージョンを確認し、XkbQueryExtension() で初期化&拡張機能の情報を取得します。
XKB ライブラリのバージョン確認
Bool XkbLibraryVersion(int *lib_major_in_out, int *lib_minor_in_out);
動的または静的にリンクされている XKB ライブラリのバージョンを確認します。
lib_major_in_out, lib_minor_in_out の各変数に、使用したいバージョンをセットして渡すと、ライブラリで実際に使用できるバージョンが返ります。
戻り値が True で、ライブラリのバージョンに互換性があります。
(現在の最新バージョンは 1.0)
ヘッダで定義されているバージョンを使用したい場合は、lib_major_in_out に XkbMajorVersion を、lib_minor_in_out に XkbMinorVersion をセットします。
XKB の初期化
Bool XkbQueryExtension(Display *dpy, int *opcode_rtrn, int *event_rtrn, int *error_rtrn, int *major_in_out, int *minor_in_out);
サーバーに XKB 拡張機能が存在するかを確認し、バージョンの互換性の確認と初期化を行って、各情報を取得します。
major_in_out, minor_in_out には、XkbLibraryVersion() で取得したバージョンを指定します。
event_rtrn で取得した値は、XKB のイベントを判別するために使います。
戻り値が True で、拡張機能が存在し、バージョンに互換性があります。
キーボードの状態
現在のキーボードの状態を取得するには、XkbGetState() を使います。
device_spec で指定されたキーボードデバイスの現在の状態を、state_return に返します。
XInput 拡張機能におけるデバイス ID、または、XkbUseCoreKbd を指定します。
任意のキーボードデバイスを個別に指定したい場合は、デバイス ID を調べる必要があります。
XkbUseCoreKbd の場合、コアのキーボードデバイスになります (XInput2 におけるマスターキーボードデバイス)。
デバイスを区別せずに、すべてのキーボードを共通に扱いたい場合は、XkbUseCoreKbd を指定します。
Status XkbGetState(Display *display, unsigned int device_spec, XkbStatePtr state_return);
device_spec で指定されたキーボードデバイスの現在の状態を、state_return に返します。
device_spec
XKB 関数では、device_spec 引数で、対象となるキーボードデバイスを指定する場合が多いです。XInput 拡張機能におけるデバイス ID、または、XkbUseCoreKbd を指定します。
任意のキーボードデバイスを個別に指定したい場合は、デバイス ID を調べる必要があります。
XkbUseCoreKbd の場合、コアのキーボードデバイスになります (XInput2 におけるマスターキーボードデバイス)。
デバイスを区別せずに、すべてのキーボードを共通に扱いたい場合は、XkbUseCoreKbd を指定します。
XkbStateRec 構造体
XkbStateRec は、「修飾子」「キーボードグループ」「ポインタボタン」の状態で構成されます。
構造体の実体は XkbStateRec で、そのポインタは XkbStatePtr 型となります。
XKB で定義されている構造体は、基本的に、〜Rec が実体、〜Ptr がポインタ型になります。
typedef struct { unsigned char group; /* effective group index */ unsigned char base_group; /* base group index */ unsigned char latched_group; /* latched group index */ unsigned char locked_group; /* locked group index */ unsigned char mods; /* effective modifiers */ unsigned char base_mods; /* base modifiers */ unsigned char latched_mods; /* latched modifiers */ unsigned char locked_mods; /* locked modifiers */ unsigned char compat_state; /* effective group -> modifiers */ unsigned char grab_mods; /* modifiers used for grabs */ unsigned char compat_grab_mods; /* mods used for compatibility mode grabs */ unsigned char lookup_mods; /* mods used to lookup symbols */ unsigned char compat_lookup_mods; /* mods used for compatibility lookup */ unsigned short ptr_buttons; /* ポインタボタンのマスク */ } XkbStateRec, *XkbStatePtr;
構造体の実体は XkbStateRec で、そのポインタは XkbStatePtr 型となります。
XKB で定義されている構造体は、基本的に、〜Rec が実体、〜Ptr がポインタ型になります。
修飾子 (mods)
キーボードの修飾子は、コアプロトコルで定義されている「Shift、Lock、Control、Mod1〜Mod5」が使用されます。
修飾子はそれぞれ、ON/OFF の状態に切り替えることができるものと考えます。
修飾子はそれぞれ、ON/OFF の状態に切り替えることができるものと考えます。
グループ (group)
XKB では、最大4個のグループを定義することができ、各グループは 0〜3 のインデックスで指定されます。
グループが変更されると、キーに対応する KeySym のセットが変化します。
ただし、一つのグループでは、キーと修飾子の組み合わせで KeySym を変更することができるので、基本的には1つのグループのみが使われることが多いです。
/usr/share/X11/xkb/symbols/jp ファイルに、日本語キーボード用の XKB 定義があるので、参考にしてみてください。
グループが変更されると、キーに対応する KeySym のセットが変化します。
ただし、一つのグループでは、キーと修飾子の組み合わせで KeySym を変更することができるので、基本的には1つのグループのみが使われることが多いです。
/usr/share/X11/xkb/symbols/jp ファイルに、日本語キーボード用の XKB 定義があるので、参考にしてみてください。
base, latched, locked, effective
修飾子キーとグループには、base, latched, locked, effective の4つの種類があります。
base | 現在、物理的または論理的に、実際に押されている状態のキーを示します。 |
---|---|
latched | ラッチ状態のキー。 XKB の機能によって、Shift などの装飾キーを一度押して離すと、ラッチ状態にすることができます (機能の変更が可能)。 この状態で通常のキーを押すと、そのキーは +Shift などの状態となり、その後、ラッチ状態は自動で解除されます。 Shift キーなどを押しながら、同時に別のキーを押すのが難しい場合に、この機能が使われます。 |
locked | ロック状態のキー。 NumLock や CapsLock など、ON/OFF の状態が永続的に切り替わるもの。 |
effective | 現在有効な状態。 base, latched, locked によって計算されます。 各状況によっては、一部無効となる値もありますが、基本的には3つすべてを含んだ状態です。 (グループの場合は、それぞれから判断した一つのインデックス) |
ほか
lookup_mods | KeyPress/KeyRelease イベント時に、キーコードと修飾子から、対応する KeySym に変換する時に使用する、修飾子状態 |
---|---|
grab_mods | パッシブグラブ時の一致判定に使用される修飾子状態 |
compat_* | XKB が無効な状態のクライアントに対して適用される値 |
イベント
キーボードの状態や設定が変化した時などに、XKB イベントを受け取ることができます。
XKB イベント
XKB のイベントであるかを判定するには、XEvent の type メンバが、XkbQueryExtension 関数の event_rtrn 引数で取得したイベントタイプ値と同じであるかどうかを比較します。
すべての XKB イベントでは、このイベントタイプはすべて同じ値になります。
XKB イベントの詳細なイベントタイプを判断するには、xkb_type を参照します。
device は、キーボードのデバイス ID です。イベント選択時などで XkbUseCoreKbd が指定されていた場合、実際のデバイス ID になります。
※XKB のイベント構造体は、XEvent のサイズを超えることはありません。
すべての XKB イベントでは、このイベントタイプはすべて同じ値になります。
XkbAnyEvent 構造体
XKB のすべてのイベント構造体では、先頭に同じデータがあり、それらは XkbAnyEvent 構造体で定義されています。typedef struct { int type; //XkbQueryExtension で取得した値 unsigned long serial; Bool send_event; Display * display; Time time; //イベントが起きたときのタイムスタンプ int xkb_type; //XKB イベントの詳細タイプ unsigned int device; //デバイスID } XkbAnyEvent;
XKB イベントの詳細なイベントタイプを判断するには、xkb_type を参照します。
device は、キーボードのデバイス ID です。イベント選択時などで XkbUseCoreKbd が指定されていた場合、実際のデバイス ID になります。
XkbEvent 共用体
なお、XEvent 共用体と同じように、すべての XKB イベント構造体と XEvent を含んだ、XkbEvent 共用体が定義されています。※XKB のイベント構造体は、XEvent のサイズを超えることはありません。
typedef union _XkbEvent { int type; XkbAnyEvent any; XkbStateNotifyEvent state; XkbMapNotifyEvent map; XkbControlsNotifyEvent ctrls; XkbIndicatorNotifyEvent indicators; XkbBellNotifyEvent bell; XkbAccessXNotifyEvent accessx; XkbNamesNotifyEvent names; XkbCompatMapNotifyEvent compat; XkbActionMessageEvent message; XkbExtensionDeviceNotifyEvent device; XkbNewKeyboardNotifyEvent new_kbd; XEvent core; } XkbEvent;
XKB イベントの選択
受信したい XKB イベントがある場合は、デバイスごとにイベントを選択する必要があります。
※XKB イベントは、X ウィンドウごとに選択することができません。主にキーボード設定関連のイベントが多いので、クライアントを対象にして送られてきます。
XkbSelectEvents と XkbSelectEventDetails の2つの関数を使って、選択または選択解除することができます。
XkbSelectEvents は、指定した XKB イベントの選択と選択解除を行います。
XkbSelectEventDetails は、指定した XKB イベントで、さらに詳細な条件を指定します。
複数の XKB イベントの選択と選択解除を行います。
この関数で選択すると、各イベントは、すべての状況においてイベントが送信されます。
XSelectInput 関数などとは違って、イベントマスク全体を上書きするのではなく、個々のイベントを選択したり選択解除することができます。
bits_to_change に、選択または選択解除したいイベントのマスクを、values_for_bits に、選択するか選択解除するかどうかのフラグをセットします。
指定した XKB イベントに関して、詳細な条件ごとに、選択または選択解除します。
指定したイベントで、指定した変化が起こった時のみイベントを受け取りたい場合に使います。
bits_to_change と values_for_bits に何の値を指定するかは、XKB イベントのタイプによって異なります。
XkbStateNotify イベントであれば、XkbStateNotifyEvent 構造体の changed で使われるのと同じ値を指定します。
※XKB イベントは、X ウィンドウごとに選択することができません。主にキーボード設定関連のイベントが多いので、クライアントを対象にして送られてきます。
XkbSelectEvents と XkbSelectEventDetails の2つの関数を使って、選択または選択解除することができます。
XkbSelectEvents は、指定した XKB イベントの選択と選択解除を行います。
XkbSelectEventDetails は、指定した XKB イベントで、さらに詳細な条件を指定します。
XkbSelectEvents
Bool XkbSelectEvents(Display *display, unsigned int device_spec, unsigned long int bits_to_change, unsigned long int values_for_bits);
複数の XKB イベントの選択と選択解除を行います。
この関数で選択すると、各イベントは、すべての状況においてイベントが送信されます。
device_spec | 対象のデバイスの ID または XkbUseCoreKbd |
---|---|
bits_to_change | 設定を変更するイベントのマスク |
values_for_bits | bits_to_change に対応するそれぞれのイベントを、選択するか解除するかのマスク。 (ON なら選択、OFF なら解除) |
XSelectInput 関数などとは違って、イベントマスク全体を上書きするのではなく、個々のイベントを選択したり選択解除することができます。
bits_to_change に、選択または選択解除したいイベントのマスクを、values_for_bits に、選択するか選択解除するかどうかのフラグをセットします。
//XkbStateNotifyMask を選択 XkbSelectEvents(disp, XkbUseCoreKbd, XkbStateNotifyMask, XkbStateNotifyMask); //XkbStateNotifyMask を解除 XkbSelectEvents(disp, XkbUseCoreKbd, XkbStateNotifyMask, 0);
XkbSelectEventDetails
Bool XkbSelectEventDetails(Display *display, unsigned int device_spec, unsigned int event_type, unsigned long int bits_to_change, unsigned long int values_for_bits);
指定した XKB イベントに関して、詳細な条件ごとに、選択または選択解除します。
指定したイベントで、指定した変化が起こった時のみイベントを受け取りたい場合に使います。
event_type | 対象となる XKB イベントタイプ |
---|---|
bits_to_change | そのイベントの詳細な条件のマスク (設定を変更するものを ON) |
values_for_bits | bits_to_change に対応するビットで、選択するか選択解除するかのフラグ |
bits_to_change と values_for_bits に何の値を指定するかは、XKB イベントのタイプによって異なります。
XkbStateNotify イベントであれば、XkbStateNotifyEvent 構造体の changed で使われるのと同じ値を指定します。
//XkbStateNotify イベントで mods が変化した時のみ受信 XkbSelectEventDetails(disp, XkbUseCoreKbd, XkbStateNotify, XkbModifierStateMask, XkbModifierStateMask);
XkbStateNotify イベント
XkbStateNotify イベントは、修飾子の ON/OFF が変化したり、グループが変更されたり、ポインタボタンの押し状態が変化した時に来ます。
※ウィンドウに関係なく送られてくるので、他のクライアントが作成したウィンドウ上で状態が変化した場合でも、常にイベントが送られてきます。
※ウィンドウに関係なく送られてくるので、他のクライアントが作成したウィンドウ上で状態が変化した場合でも、常にイベントが送られてきます。
typedef struct { int type; unsigned long serial; Bool send_event; Display * display; Time time; int xkb_type; int device; unsigned int changed; int group; int base_group; int latched_group; int locked_group; unsigned int mods; unsigned int base_mods; unsigned int latched_mods; unsigned int locked_mods; int compat_state; unsigned char grab_mods; unsigned char compat_grab_mods; unsigned char lookup_mods; unsigned char compat_lookup_mods; int ptr_buttons; KeyCode keycode; char event_type; char req_major; char req_minor; } XkbStateNotifyEvent; //changed #define XkbModifierStateMask (1L << 0) #define XkbModifierBaseMask (1L << 1) #define XkbModifierLatchMask (1L << 2) #define XkbModifierLockMask (1L << 3) #define XkbGroupStateMask (1L << 4) #define XkbGroupBaseMask (1L << 5) #define XkbGroupLatchMask (1L << 6) #define XkbGroupLockMask (1L << 7) #define XkbCompatStateMask (1L << 8) #define XkbGrabModsMask (1L << 9) #define XkbCompatGrabModsMask (1L << 10) #define XkbLookupModsMask (1L << 11) #define XkbCompatLookupModsMask (1L << 12) #define XkbPointerButtonMask (1L << 13) #define XkbAllStateComponentsMask (0x3fff)
changed | 何が変更されたかを示すフラグ。 |
---|---|
keycode | イベントを引き起こしたキーコード、またはボタン番号。 プログラムによる場合は 0。 |
event_type | req_major または req_minor が 0 以外の場合、コアイベントのタイプ。 キーイベントによる状態変化の場合、KeyPress (2) または KeyRelease (3)。 ボタンイベントの場合、ButtonPress (4) または ButtonRelease (5)。keycode はボタン番号。 それ以外の場合は、状態変更を引き起こしたリクエストのコードが、req_major,req_minor に設定される。keycode は 0。 |
プログラム
XkbStateNotify イベントを受け取って表示します。
閉じるボタンで終了します。
なお、ポインタボタンの状態変化を受け取ると、少々面倒な状態になるので (あらゆる場所でポインタボタンが押されると、毎回イベントが来る)、ポインタボタンの状態変化は受け取らないようにしています。
<e11-xkb1.c>
閉じるボタンで終了します。
$ cc -o run e11-xkb1.c util.c -lX11
なお、ポインタボタンの状態変化を受け取ると、少々面倒な状態になるので (あらゆる場所でポインタボタンが押されると、毎回イベントが来る)、ポインタボタンの状態変化は受け取らないようにしています。
<e11-xkb1.c>
#include <stdio.h> #include <X11/Xlib.h> #include <X11/XKBlib.h> #include "util.h" static unsigned int g_count = 0; static void _put_state(XkbStateNotifyEvent *ev) { unsigned int f = ev->changed; printf("----[%d]-----\n" "device: %d / changed: 0x%x\n", g_count++, ev->device, ev->changed); if(f & XkbModifierStateMask) printf("mods: 0x%x\n", ev->mods); if(f & XkbModifierBaseMask) printf("base_mods: 0x%x\n", ev->base_mods); if(f & XkbModifierLatchMask) printf("latched_mods: 0x%x\n", ev->latched_mods); if(f & XkbModifierLockMask) printf("locked_mods: 0x%x\n", ev->locked_mods); if(f & XkbGroupStateMask) printf("group: %d\n", ev->group); if(f & XkbGroupBaseMask) printf("base_group: %d\n", ev->base_group); if(f & XkbGroupLatchMask) printf("latched_group: %d\n", ev->latched_group); if(f & XkbGroupLockMask) printf("locked_group: %d\n", ev->locked_group); if(f & XkbCompatStateMask) printf("compat_state: 0x%x\n", ev->compat_state); if(f & XkbGrabModsMask) printf("grab_mods: 0x%x\n", ev->grab_mods); if(f & XkbCompatGrabModsMask) printf("compat_grab_mods: 0x%x\n", ev->compat_grab_mods); if(f & XkbLookupModsMask) printf("lookup_mods: 0x%x\n", ev->lookup_mods); if(f & XkbCompatLookupModsMask) printf("compat_lookup_mods: 0x%x\n", ev->compat_lookup_mods); //if(f & XkbPointerButtonMask) printf("ptr_buttons: 0x%x\n", ev->ptr_buttons); printf("keycode: %d / event_type: %d / req_major: %d / req_minor: %d\n", ev->keycode, ev->event_type, ev->req_major, ev->req_minor); } int main(int argc,char **argv) { Display *disp; Window win; XkbEvent ev; int major,minor,opcode,event_type,error_base; unsigned long mask; //XKB ライブラリ major = XkbMajorVersion; minor = XkbMinorVersion; if(!XkbLibraryVersion(&major, &minor)) { printf("unsupported XKB library\n"); return 1; } printf("library: ver %d.%d\n", major, minor); // disp = XOpenDisplay(NULL); if(!disp) return 1; set_display(disp); //XKB 初期化 if(!XkbQueryExtension(disp, &opcode, &event_type, &error_base, &major, &minor)) { XCloseDisplay(disp); printf("unsupported XKB (server)\n"); return 1; } printf("server: ver %d.%d\n", major, minor); printf("opcode: %d\nevent:%d\nerror:%d\n\n", opcode, event_type, error_base); // win = create_test_window2(disp, 200, 200, 0, ButtonPress); //XKB イベント選択 (ポインタボタン以外) mask = XkbAllStateComponentsMask - XkbPointerButtonMask; XkbSelectEventDetails(disp, XkbUseCoreKbd, XkbStateNotify, mask, mask); //イベント XMapWindow(disp, win); while(1) { XNextEvent(disp, (XEvent *)&ev); if(event_quit((XEvent *)&ev)) break; if(ev.type == event_type && ev.any.xkb_type == XkbStateNotify) { _put_state((XkbStateNotifyEvent *)&ev); } } XCloseDisplay(disp); return 0; }
実行例
Shift キー
Shift キーを押して離すと、以下のようになります。
device は、xinput コマンドで調べてみると、id=3 は "Virtual core keyboard" でした。
これは、マスターキーボードデバイスです。
Shift キーが押された時、NumLock と Shift の2つが ON の状態なので、mods は (ShiftMask | Mod2Mask) です。
現在物理的にキーが押されているのは Shift だけなので、base_mods は ShiftMask のみです。
----[4]----- # Shift 押し device: 3 / changed: 0x1f03 mods: 0x11 base_mods: 0x1 compat_state: 0x11 grab_mods: 0x11 compat_grab_mods: 0x11 lookup_mods: 0x11 compat_lookup_mods: 0x11 keycode: 50 / event_type: 2 / req_major: 0 / req_minor: 0 ----[5]----- # Shift 離し device: 3 / changed: 0x1f03 mods: 0x10 base_mods: 0x0 compat_state: 0x10 grab_mods: 0x10 compat_grab_mods: 0x10 lookup_mods: 0x10 compat_lookup_mods: 0x10 keycode: 50 / event_type: 3 / req_major: 0 / req_minor: 0
device は、xinput コマンドで調べてみると、id=3 は "Virtual core keyboard" でした。
これは、マスターキーボードデバイスです。
Shift キーが押された時、NumLock と Shift の2つが ON の状態なので、mods は (ShiftMask | Mod2Mask) です。
現在物理的にキーが押されているのは Shift だけなので、base_mods は ShiftMask のみです。
NumLock の解除とセット
----[82]----- # NumLock 押し device: 3 / changed: 0x2 base_mods: 0x10 keycode: 77 / event_type: 2 / req_major: 0 / req_minor: 0 ----[83]----- # NumLock 離し (解除) device: 3 / changed: 0x1f0b mods: 0x0 base_mods: 0x0 locked_mods: 0x0 compat_state: 0x0 grab_mods: 0x0 compat_grab_mods: 0x0 lookup_mods: 0x0 compat_lookup_mods: 0x0 keycode: 77 / event_type: 3 / req_major: 0 / req_minor: 0 ----[84]----- # NumLock 押し (セット) device: 3 / changed: 0x1f0b mods: 0x10 base_mods: 0x10 locked_mods: 0x10 compat_state: 0x10 grab_mods: 0x10 compat_grab_mods: 0x10 lookup_mods: 0x10 compat_lookup_mods: 0x10 keycode: 77 / event_type: 2 / req_major: 0 / req_minor: 0 ----[85]----- # NumLock 離し device: 3 / changed: 0x2 base_mods: 0x0 keycode: 77 / event_type: 3 / req_major: 0 / req_minor: 0
NumLock が ON の状態で、NumLock キーを押して離した時 (押した瞬間ではない)、NumLock が解除されるので、すべての mods が 0 になっています。
NumLock が OFF の状態で、NumLock キーを押した時 (この場合は押した瞬間)、NumLock が ON になるので、各 mods が Mod2Mask になっています。
CapsLock ON
----[195]----- # CapsLock 押し device: 3 / changed: 0x1f0b mods: 0x13 base_mods: 0x3 locked_mods: 0x12 compat_state: 0x13 grab_mods: 0x13 compat_grab_mods: 0x13 lookup_mods: 0x13 compat_lookup_mods: 0x13 keycode: 66 / event_type: 2 / req_major: 0 / req_minor: 0 ----[196]----- # CapsLock 離し device: 3 / changed: 0x2 base_mods: 0x1 keycode: 66 / event_type: 3 / req_major: 0 / req_minor: 0 ----[197]----- # Shift 離し device: 3 / changed: 0x1f03 mods: 0x12 base_mods: 0x0 compat_state: 0x12 grab_mods: 0x12 compat_grab_mods: 0x12 lookup_mods: 0x12 compat_lookup_mods: 0x12 keycode: 50 / event_type: 3 / req_major: 0 / req_minor: 0
Shift + CapsLock(英数) で、CapsLock の ON/OFF ができます。
CapsLock は LockMask (0x02) です。
Shift + CapsLock を押した瞬間の値は以下のようになっています。
mods (0x13) | mods は現在有効な状態です。 (ShiftMask | LockMask | Mod2Mask) で、Shift, CapsLock, NumLock が ON の状態です。 |
---|---|
base_mods (0x03) | 現在物理的に押されているキー。 NumLock はロック状態でキーは押されていないので、(ShiftMask | LockMask) です。 |
locked_mods (0x12) | ロック状態 (LED が ON になっている状態) の修飾子です。 NumLock と CapsLock が ON になっているので、(LockMask | Mod2Mask) です。 |