yusuk****@cheru*****
yusuk****@cheru*****
2002年 12月 25日 (水) 02:36:32 JST
田畑です。 いろいろ調べたんで gtk+のGtkIMContextの説明を書いておきます。 *キーイベント *コミットした文字列 *プリエディットの変化 *プリエディットの中身 をどういうパスでやりとりするかの設計がミソな感じです。 テキストフィールドの基底クラスGtkTextViewはGtkIMContextの インスタンスを一つもっていて、入力関係の処理を全部まかせています。 相互のやりとりは *GtkTextViewはGtkIMContextのメソッドを呼び出す *GtkIMContextはシグナルを発行して、(普通は)GtkTextViewが 受け取る というように行われます。 例えばim-uimでのオブジェクトの構成は次のようになっています。 GtkTextView(テキストフィールド) <>-- GtkIMMultiContext(ディスパッチャとなるInputContext) <>-- IMUIMContext(UIMのコンテキスト) <>-- GtkIMContextSimple(キーイベントをそのままコミット するInputContext) テキストフィールドにキーイベントがくると、->filter_keypress() が順によばれてイベントが流れていきます。 (IMUIMContextがGtkIMContextSimpleにイベントを投げるかどうかは、 入力モードに依存します。) 文字列のコミットが必要な場合はシグナルを発生させて、文字列を 伝達していきます。GtkIMMultiContextのcommitシグナルは GtkTextViewに接続されていて、IMUIMContextのcommitシグナルは GtkIMMultiContextに接続されています。 文字列のコミットの他に、プリエディットの変更と周辺文字列の取得も シグナルを用いて行われます。 以下にgtkの gtk/gtkimcontext.h を引用して、コメントをつけときます。 struct _GtkIMContextClass { GtkObjectClass parent_class; /* Signals */ /* GtkIMContextが発生(emit)するシグナルです。 */ /* IMContextがpreeditを変更した時に発生するシグナルです preedit_startとpreedit_endはそんなに重要ではないと思います。*/ void (*preedit_start) (GtkIMContext *context); void (*preedit_end) (GtkIMContext *context); void (*preedit_changed) (GtkIMContext *context); /* IMContextが文字列をコミットする時に発生させるシグナルです */ void (*commit) (GtkIMContext *context, const gchar *str); /* 以下二つはよくわかってないです。 */ gboolean (*retrieve_surrounding) (GtkIMContext *context); gboolean (*delete_surrounding) (GtkIMContext *context, gint offset, gint n_chars); /* Virtual functions */ /* 外部から呼ばれる関数です */ /* 入力対象のwindowをセットします */ void (*set_client_window) (GtkIMContext *context, GdkWindow *window); /* TextWidgetはpreedit_changedのシグナルを受け取ると、 InputContextに対してこのメソッドを呼び出して 現在のプリエディットを取得します。 */ void (*get_preedit_string) (GtkIMContext *context, gchar **str, /* attrs 文字列の属性、アンダーラインや背景の色、 フォント、サイズなどいろいろな情報 */ PangoAttrList **attrs, gint *cursor_pos); /* Textウィジェットはキー入力があると、このメソッドを呼び出します。 */ gboolean (*filter_keypress) (GtkIMContext *context, GdkEventKey *event); /* focusが出入りしたときによばれます */ void (*focus_in) (GtkIMContext *context); void (*focus_out) (GtkIMContext *context); /* リセットは、テキストウィジェットのフォーカスが移ったなどに 呼ばれます。一般的には*/ void (*reset) (GtkIMContext *context); /* こっから下は説明できるほど理解していません */ void (*set_cursor_location) (GtkIMContext *context, GdkRectangle *area); void (*set_use_preedit) (GtkIMContext *context, gboolean use_preedit); void (*set_surrounding) (GtkIMContext *context, const gchar *text, gint len, gint cursor_index); gboolean (*get_surrounding) (GtkIMContext *context, gchar **text, gint *cursor_index); ... } -- PUBLISH OR PERISH! Yusuke TABATA (yusuk****@cheru*****)