入力メソッド
日本語などを入力するためには、入力メソッドによる操作が必要になります。
X において入力メソッドを使用するためには、まず最初にロケールを設定した後、XOpenIM() で入力メソッドを開きます。
この関数で返される XIM (XID) は、1つのアプリケーションに対して1つ必要になります。
現在のロケールと、X ロケール修飾子で指定されている入力メソッドを開きます。
X において入力メソッドを使用するためには、まず最初にロケールを設定した後、XOpenIM() で入力メソッドを開きます。
この関数で返される XIM (XID) は、1つのアプリケーションに対して1つ必要になります。
入力メソッドを開く/閉じる
XIM XOpenIM(Display *display, XrmDatabase db, char *res_name, char *res_class); Status XCloseIM(XIM im);
現在のロケールと、X ロケール修飾子で指定されている入力メソッドを開きます。
db | 入力メソッドによって使用されるリソースデータベース。 NULL でなし。 |
---|---|
res_name res_class | アプリケーションのリソース名とクラス名。 この入力メソッドで使用されるコンテキストにおいて、共通のリソースを検索するために使用される。 使用しないのであれば、NULL でよい。 |
戻り値 | 失敗時、NULL が返ります。 |
コールバック関数
デスクトップの起動時にクライアントのアプリケーションを起動する場合、入力メソッドのサーバーが起動する前に、アプリケーションが起動されてしまう場合があります。
その場合は、入力メソッドが開けないので、代わりに、入力メソッドが使用可能な状態になった時に呼ばれるコールバック関数を登録できます。
XRegisterIMInstantiateCallback でコールバック関数を登録し、XUnregisterIMInstantiateCallback でコールバック関数を削除します。
XOpenIM() で NULL が返った場合、コールバック関数を登録し、コールバック関数が来たら XOpenIM() で開いて、コールバック関数を削除します。
その場合は、入力メソッドが開けないので、代わりに、入力メソッドが使用可能な状態になった時に呼ばれるコールバック関数を登録できます。
Bool XRegisterIMInstantiateCallback(Display *display, XrmDatabase db, char *res_name, char *res_class, XIDProc callback, XPointer *client_data); Bool XUnregisterIMInstantiateCallback(Display *display, XrmDatabase db, char *res_name, char *res_class, XIDProc callback, XPointer *client_data); typedef void (*XIDProc)(Display *display, XPointer client_data, XPointer call_data);
XRegisterIMInstantiateCallback でコールバック関数を登録し、XUnregisterIMInstantiateCallback でコールバック関数を削除します。
XOpenIM() で NULL が返った場合、コールバック関数を登録し、コールバック関数が来たら XOpenIM() で開いて、コールバック関数を削除します。
入力スタイル
入力メソッドを開いたら、その入力メソッドがサポートしている入力スタイルを取得する必要があります。
入力メソッドは、入力中の情報として、「ステータス領域」「前編集領域」「補助領域」を表示する場合があります。
前編集は、変換前のテキストが表示される領域です。Xlib では、以下のスタイルがサポートされています。
入力メソッドによって、サポートしているスタイルが異なります。
現在では主に「on-the-spot」か「off-the-spot」が使われます。
指定した入力メソッドが設定している値を読み込みます。
可変引数には、「値の名前の文字列のポインタ」と「値を取得する変数のポインタ」の2つをペアにして渡し、NULL ポインタで終了します。
※終了時の NULL は、数値の 0 として渡さず、明確に (void *)0 としてください。
成功した場合は NULL を返し、それ以外の場合は、取得できなかった最初の名前を返します。
入力メソッドは、入力中の情報として、「ステータス領域」「前編集領域」「補助領域」を表示する場合があります。
前編集は、変換前のテキストが表示される領域です。Xlib では、以下のスタイルがサポートされています。
on-the-spot | アプリケーションが自身の領域で、変換前のテキストを表示します |
---|---|
over-the-spot | 挿入ポイントの上に前編集ウィンドウを表示 |
off-the-spot | アプリケーションウィンドウの下部など、位置を指定せずに前編集ウィンドウを表示 |
ルートウィンドウ | ルートウィンドウの子として前編集ウィンドウを表示 |
入力メソッドによって、サポートしているスタイルが異なります。
現在では主に「on-the-spot」か「off-the-spot」が使われます。
IM の値を取得
char *XGetIMValues(XIM im,...);
指定した入力メソッドが設定している値を読み込みます。
可変引数には、「値の名前の文字列のポインタ」と「値を取得する変数のポインタ」の2つをペアにして渡し、NULL ポインタで終了します。
※終了時の NULL は、数値の 0 として渡さず、明確に (void *)0 としてください。
成功した場合は NULL を返し、それ以外の場合は、取得できなかった最初の名前を返します。
値の名前
名前の文字列は、以下のマクロ名で定義されています。XNQueryInputStyle | サポートしている入力スタイルのリスト (XIMStyles **)。 使用後は XFree() で解放する。 |
---|---|
XNQueryIMValuesList | サポートされている XIM のプロパティ名のリスト (XIMValuesList **)。 XFree() で解放する。 |
XNQueryICValuesList | サポートされている XIC のプロパティ名のリスト (XIMValuesList **)。 XFree() で解放する。 |
XNQueryInputStyle
入力スタイルのリストは、XNQueryInputStyle の名前で取得します。
確保された XIMStyles 構造体のポインタが返るので、値は (XIMStyles **) で渡します。
使用後は、XIMStyles のポインタを XFree() で解放します。
スタイル値は、前編集とステータス領域に関するフラグが指定されています。
XIMPreeditCallbacks の場合は、on-the-spot スタイル。
XIMPreeditNothing の場合は、off-the-spot スタイルとなります。
確保された XIMStyles 構造体のポインタが返るので、値は (XIMStyles **) で渡します。
使用後は、XIMStyles のポインタを XFree() で解放します。
typedef unsigned long XIMStyle; typedef struct { unsigned short count_styles; //配列個数 XIMStyle *supported_styles; //スタイル値の配列 } XIMStyles; //前編集のフラグ #define XIMPreeditArea 0x0001L #define XIMPreeditCallbacks 0x0002L #define XIMPreeditPosition 0x0004L #define XIMPreeditNothing 0x0008L #define XIMPreeditNone 0x0010L //ステータスのフラグ #define XIMStatusArea 0x0100L #define XIMStatusCallbacks 0x0200L #define XIMStatusNothing 0x0400L #define XIMStatusNone 0x0800L
スタイル値は、前編集とステータス領域に関するフラグが指定されています。
XIMPreeditArea | 以下の領域値が必要。 XNArea, XNAreaNeeded |
---|---|
XIMPreeditPosition | 以下の位置の値が必要。 XNSpotLocation, XNFocusWindow |
XIMPreeditCallbacks | コールバック関数が必要。 XNPreeditStartCallback、XNPreeditDoneCallback、XNPreeditDrawCallback、XNPreeditCaretCallback |
XIMPreeditNothing | 前編集に関する値は必要ない。 |
XIMPreeditNone | 入力メソッドは、前編集を提供しません。 |
XIMPreeditCallbacks の場合は、on-the-spot スタイル。
XIMPreeditNothing の場合は、off-the-spot スタイルとなります。
IM 破棄時のコールバック
入力メソッドが何らかの理由でサービスを停止した場合、IM にコールバック関数を設定することで、それを検知することができます。
名前に XNDestroyCallback マクロ、値に XIMCallback 構造体のポインタを指定します。
このコールバックが呼び出された後は、入力メソッドが閉じられ、関連する入力コンテキストも Xlib によって破棄されます。
よって、クライアントは、この関数内で XCloseIM() や XDestroyIC() を呼ばないこと。
char *XSetIMValues(XIM im,...);
名前に XNDestroyCallback マクロ、値に XIMCallback 構造体のポインタを指定します。
typedef struct { XPointer client_data; XIMProc callback; } XIMCallback; typedef void (*XIMProc)(XIM im, XPointer client_data, XPointer call_data); //call_data は常に NULL
このコールバックが呼び出された後は、入力メソッドが閉じられ、関連する入力コンテキストも Xlib によって破棄されます。
よって、クライアントは、この関数内で XCloseIM() や XDestroyIC() を呼ばないこと。
プログラム
入力メソッドを開いて、プロパティ値を表示します。
<22-im1.c>
$ cc -o run 22-im1.c util.c -lX11
<22-im1.c>
#include <stdio.h> #include <X11/Xlib.h> #include "util.h" static void _put_style(XIMStyle n) { if(n & XIMPreeditArea) printf(" PreeditArea"); if(n & XIMPreeditCallbacks) printf(" PreeditCallbacks"); if(n & XIMPreeditPosition) printf(" PreeditPosition"); if(n & XIMPreeditNothing) printf(" PreeditNothing"); if(n & XIMPreeditNone) printf(" PreeditNone"); if(n & XIMStatusArea) printf(" StatusArea"); if(n & XIMStatusCallbacks) printf(" StatusCallbacks"); if(n & XIMStatusNothing) printf(" StatusNothing"); if(n & XIMStatusNone) printf(" StatusNone"); printf("\n"); } int main(int argc,char **argv) { Display *disp; XIM im; XIMStyles *styles = NULL; XIMValuesList *imval = NULL, *icval = NULL; int i; disp = XOpenDisplay(NULL); if(!disp) return 1; init_locale(); //IM 開く im = XOpenIM(disp, NULL, NULL, NULL); if(!im) { printf("failed XOpenIM\n"); XCloseDisplay(disp); return 0; } //IM プロパティの取得 XGetIMValues(im, XNQueryInputStyle, &styles, XNQueryIMValuesList, &imval, XNQueryICValuesList, &icval, (void *)0); //入力スタイル if(styles) { printf("-- input style --\n"); for(i = 0; i < styles->count_styles; i++) { printf("[%d]", i); _put_style(styles->supported_styles[i]); } XFree(styles); } //IM 値の名前 if(imval) { printf("\n-- IM values --\n"); for(i = 0; i < imval->count_values; i++) printf("[%d] %s\n", i, imval->supported_values[i]); XFree(imval); } //IC 値の名前 if(icval) { printf("\n-- IC values --\n"); for(i = 0; i < icval->count_values; i++) printf("[%d] %s\n", i, icval->supported_values[i]); XFree(icval); } // XCloseIM(im); XCloseDisplay(disp); return 0; }
結果 (fcitx5 の場合)
※fcitx の場合、XIMPreeditCallbacks が使用できるようにするには、「アドオン」→「X Input Method フロントエンド」で、「XIM で On The Spot スタイルを使う」のチェックが ON になっている必要があります。
IC は、入力コンテキストを意味します。
入力メソッドによって、表示される値は異なります。
-- input style -- [0] PreeditPosition StatusNothing [1] PreeditCallbacks StatusNothing [2] PreeditNothing StatusNothing [3] PreeditPosition StatusCallbacks [4] PreeditCallbacks StatusCallbacks [5] PreeditNothing StatusCallbacks -- IM values -- [0] queryInputStyle -- IC values -- [0] inputStyle [1] clientWindow [2] focusWindow [3] filterEvents [4] preeditAttributes [5] statusAttributes [6] fontSet [7] area [8] areaNeeded [9] colorMap [10] stdColorMap [11] foreground [12] background [13] backgroundPixmap [14] spotLocation [15] lineSpace [16] separatorofNestedList
IC は、入力コンテキストを意味します。
入力メソッドによって、表示される値は異なります。
On The Spot が使用出来ない場合
fcitx で、「XIM で On The Spot スタイルを使う」が OFF の場合は、以下のようになります。
[0] PreeditPosition StatusArea [1] PreeditPosition StatusNothing [2] PreeditPosition StatusNone [3] PreeditNothing StatusNothing [4] PreeditNothing StatusNone