キーボード入力の旅/GTKとキーボード入力
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
#contents
*はじめに [#q6cf1b26]
ここではキーボード入力に対してGUIツールキットがどういう処...
-下位レイヤーから送られてきた情報をどう抽象化しているか
-コントロールフォーカスの管理
なお、プラットフォームはx11とします。
*サンプルコード [#x0e1c0ef]
読解するにあたり、以下のコードについて各関数でどのような...
#code(C){{
#include <stdio.h>
#include <gtk/gtk.h>
static gboolean
window_delete_event(GtkWidget *widget, GdkEvent *event, g...
{
gtk_main_quit();
return FALSE;
}
static void
button_clicked(GtkWidget *widget, gpointer data)
{
const gchar *entry_text;
entry_text = gtk_entry_get_text(GTK_ENTRY(data));
printf("Entry contents: %s\n", entry_text);
}
int
main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *hbox;
GtkWidget *entry;
GtkWidget *button;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_container_set_border_width(GTK_CONTAINER(window),...
g_signal_connect(G_OBJECT(window), "delete_event",
G_CALLBACK(window_delete_event), NULL);
hbox = gtk_hbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), hbox);
gtk_widget_show(hbox);
entry = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, ...
gtk_widget_show(entry);
button = gtk_button_new_with_label("Button");
g_signal_connect(G_OBJECT(button), "clicked",
G_CALLBACK(button_clicked), entry);
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE,...
gtk_widget_show(button);
gtk_widget_show(window);
gtk_main();
return 0;
}
}}
*gtk_init(gtk/gtkmain.c) [#zdf31aaf]
GTKではまずgtk_init関数を呼び出す必要があります。gtk_init...
-GDKのプラットフォーム依存な部分は個別のディレクトリにま...
-先頭に_が付いているのはプラットフォーム依存関数かと思っ...
-GDKのイベントハンドラとして渡されているgtk_main_do_event...
gtk_init_check [gtk/gtkmain.c]
gtk_parse_args [gtk/gtkmain.c]
g_option_context_parse [glib/goption.c]
pre_parse_hook [gtk/gtkmain.c]
do_pre_parse_initialization [gtk/gtkmain.c]
gdk_pre_parse_libgtk_only [gdk/gdk.c]
g_type_init [gobject/gtype.c]
_gdk_windowing_init [gdk/x11/gdkmain-x11.cな...
gdk_event_handler_set(gtk_main_do_event) [gdk/...
post_parse_hook [gtk/gtkmain.c]
do_post_parse_initialization [gtk/gtkmain.c]
gtk_type_init [gtk/gtktypeutils.c]
_gtk_accel_map_init [gtk/gtkaccelmap.c]
_gtk_rc_init [gtk/gtkrc.c]
gdk_display_open_default_libgtk_only [gdk.c]
gdk_display_open [gdk/x11/gdkdisplay-x11.cなど]
_gdk_x11_screen_new [gdk/x11/gdkscreen-x11.c]
_gdk_visual_init [gdk/x11/gdkvisual-x11.c]
_gdk_windowing_window_init [gdk/x11/gdkwindow-x1...
_gdk_x11_events_init_screen [gdk/x11/gdkevents-x11...
gdk_window_new [gdk/x11/gdkwindow-x11.c]
setup_toplevel_window [gdk/x11/gdkwindow-x11.c]
create_focus_window [gdk/x11/gdkwindow-x11.c]
_gdk_events_init [gdk/x11/gdkevents-x11.c]
_gdk_input_init [gdk/x11/gdkinput-none.c]
_gdk_dnd_init [gdk/x11/gdkdnd-x11.c]
**G_DEFINE_TYPE(gobject/gtype.h) [#mca42105]
キーボード入力とは関係ないのですがGTK、というかGLibのオブ...
display = g_object_new (GDK_TYPE_DISPLAY_X11, NULL);
GDK_TYPE_DISPLAY_X11の正体が何者かというと以下の者です。
#define GDK_TYPE_DISPLAY_X11 (_gdk_display_...
GType _gdk_display_x11_get_type (void);
問題なのはgrepをかけても_gdk_display_x11_get_typeという関...
G_DEFINE_TYPE (GdkDisplayX11, _gdk_display_x11, GDK_TYPE...
となっていました。G_DEFINE_TYPEマクロを展開すると型の登録...
**GdkWindow [#h521c5cd]
gtk_init関数呼び出しで実行されるコードの中でGdkWindow周り...
まず、GdkWindowの定義です。
gdk/gdktypes.h
typedef struct _GdkDrawable GdkWindow;
で、_GdkDrawable構造体の定義。
struct _GdkDrawable
{
GObject parent_instance;
};
次にGdkWindowを使っている所としてgdk_window_new関数です。
GdkWindow *window;
GdkWindowObject *private;
GdkWindowImplX11 *impl;
...
window = g_object_new (GDK_TYPE_WINDOW, NULL);
private = (GdkWindowObject *)window;
impl = GDK_WINDOW_IMPL_X11 (private->impl);
GdkWindowをGdkWindowObjectにキャストしています。何故そん...
gdk/gdkwindow.h
#define GDK_TYPE_WINDOW (gdk_window_object_...
gdk/gdkwindow.c
GType
gdk_window_object_get_type (void)
{
static GType object_type = 0;
if (!object_type)
object_type = g_type_register_static_simple (GDK_TYP...
"GdkWindow",
sizeof (GdkWindowObjectClass),
(GClassInitFunc) gdk_window_class_init,
sizeof (GdkWindowObject),
(GInstanceInitFunc) gdk_window_init,
0);
return object_type;
}
というわけで先ほどget_type関数はマクロから作られると書き...
ついでにimplですが、
gdk/gdkwindow.c
static void
gdk_window_init (GdkWindowObject *window)
{
/* 0-initialization is good for all other fields. */
window->window_type = GDK_WINDOW_CHILD;
window->state = GDK_WINDOW_STATE_WITHDRAWN;
window->impl = g_object_new (_gdk_window_impl_get_type...
}
gdk/x11/gdkwindow-x11.c
G_DEFINE_TYPE (GdkWindowImplX11, gdk_window_impl_x11, GD...
GType
_gdk_window_impl_get_type (void)
{
return gdk_window_impl_x11_get_type ();
}
のようになっています。
*g_signal_emit(gobject/gsignal.c) [#a4e175e5]
gtk_init関数を呼んだ後、ごそごそとウィジェットを作成して...
gtk_container_add (GtkContainer *container,
GtkWidget *widget)
{
...
g_signal_emit (container, container_signals[ADD], 0, w...
}
というわけで、子ウィジットのリストに引数のウィジットを追...
次に呼び出される関数がどうやって登録されているかを見てみ...
container_signals[ADD] =
g_signal_new (I_("add"),
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GtkContainerClass, add),
NULL, NULL,
_gtk_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
GTK_TYPE_WIDGET);
雰囲気から察するにaddシグナルが送られるとGtkContainerClas...
gtk_bin_class_init (GtkBinClass *class)
{
GtkContainerClass *container_class;
container_class = (GtkContainerClass*) class;
container_class->add = gtk_bin_add;
となっており、gtk_bin_add関数が設定されています。
*gtk_widget_show(gtk/gtkwidget.c) [#qfa8b68d]
GTKのウィジェットを表示する手順は以下のようになります。
+*_new関数を使ってオブジェクトを作成
+コンテナオブジェクトに設定(親ウィジェットの設定)
+gtk_widget_show関数を呼ぶ
で、最後のgtk_widget_show関数ですが以下のようになっていま...
gtk_widget_show (GtkWidget *widget)
{
g_return_if_fail (GTK_IS_WIDGET (widget));
if (!GTK_WIDGET_VISIBLE (widget))
{
g_object_ref (widget);
if (!GTK_WIDGET_TOPLEVEL (widget))
gtk_widget_queue_resize (widget);
g_signal_emit (widget, widget_signals[SHOW], 0);
g_object_notify (G_OBJECT (widget), "visible");
g_object_unref (widget);
}
}
先ほど説明したg_signal_emit関数が使われています。今回サン...
gtk_widget_real_show (GtkWidget *widget)
{
if (!GTK_WIDGET_VISIBLE (widget))
{
GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
if (widget->parent &&
GTK_WIDGET_MAPPED (widget->parent) &&
GTK_WIDGET_CHILD_VISIBLE (widget) &&
!GTK_WIDGET_MAPPED (widget))
gtk_widget_map (widget);
}
}
何となく条件は成り立たない気がする(親をshowする前に子をs...
**gtk_window_show(gtk/gtkwindow.c) [#m06561bb]
ちょっと長めなので順を追って見ていきます。まず、まだREALI...
gtk_window_compute_configure_request関数ではウインドウの...
次にgtk_widget_size_allocate関数が呼ばれていますがこの関...
次に、REALIZEされていないのでgtk_widget_realize関数が呼び...
gtk_window_show関数に戻って、gtk_decorated_window_calcula...
以上でif(need_resize)のブロックは終了です。次にgtk_widget...
GtkWindowの子ウィジェットに対して実行されたgtk_widget_map...
GtkHBox: gtk_container_mapを実行
gtk_container_forall
GtkContainerClass.forallとして設定されているgtk_box_...
GtkBoxの子要素に対してgtk_widget_mapを実行
GtkEntryの場合、gtk_entry_realizeを実行
gtk_entry_realize関数ではgdk_window_new関数を使ってエディ...
gdk_window_set_user_data (entry->text_area, entry);
gtk_window_show関数に戻ってくるとgtk_window_move_focus関...
gtk_window_move_focus
gtk_widget_child_focus(GtkWindow)
gtk_window_focus(focusシグナル)
gtk_widget_child_focus(GtkHBox)
gtk_container_focus(focusシグナル)
gtk_container_focus_move
gtk_widget_child_focus(GtkEntry)
gtk_widget_real_focus(focusシグナル)
gtk_widget_grab_focus
gtk_entry_grab_focus(grab_focusシグナ...
gtk_widget_real_grab_focus
_gtk_window_internal_set_focus
gtk_window_real_set_focus(set_f...
*gtk_main(gtk/gtkmain.c) [#b14410e3]
ウインドウと表示するウィジェットを設定後、gtk_main関数を...
g_main_loop_new
g_main_context_default
g_main_context_new
g_main_loop_run
g_main_context_iterate
g_main_context_prepare
g_main_context_query
g_main_context_poll
g_main_context_check
g_main_context_dispatch
g_main_dispatch
処理は大雑把に言うと、
+GMainContext.source_listを調べ
+準備ができていたらGMainContext.pending_dispatchesに詰め
+各処理関数にディスパッチ
ということを行っています。
次に調べないといけないのは、source_listがいつ設定されてい...
**_gdk_events_init(gdk/x11/gdkevents-x11.c) [#n6fb9223]
source_listに要素を追加している関数はg_source_list_add関...
今回注目対象としているキーボード入力を処理するsourceは_gd...
まずgdk_display_source_new関数を呼び出してGdkDisplaySourc...
-g_main_context_prepare
-g_main_context_check
-g_main_dispatch
時にそれぞれ呼び出されます。
static GSourceFuncs event_funcs = {
gdk_event_prepare,
gdk_event_check,
gdk_event_dispatch,
NULL
};
次にディスプレイのコネクションナンバーをポーリング対象と...
**gdk_event_prepare(gdk/x11/gdkevents-x11.c) [#e4e58779]
それではまずgdk_event_prepare関数を見てみましょう。コアは...
retval = (_gdk_event_queue_find_first (display) != NULL ...
gdk_check_xpending (display));
_gdk_event_queue_find_first関数はキューにあるイベントから...
イベントが見つからなかった場合、gdk_check_xpending関数が...
gdk_event_check関数はgdk_event_prepare関数とほぼ同じなの...
**gdk_event_dispatch(gdk/x11/gdkevents-x11.c) [#ub794735]
gdk_event_dispatch関数ではまず_gdk_events_queue関数を呼ん...
_gdk_events_queue関数に進みましょう。Xのイベントを取り出...
変換の詳細はgdk_event_translate関数に続く。淡々と変換が行...
gdk_event_translate [gdk/x11/gdkevents-x11.c]
translate_key_event [gdk/x11/gdkevents-x11.c]
_gdk_x11_get_group_for_state [gdk/x11/gdkkey-x11.c]
gdk_keymap_translate_keyboard_state [gdk/x11/gdkkey-...
_gdk_keymap_add_virtual_modifiers [gdk/x11/gdkkey-x1...
_gdk_keymap_key_is_modifiers [gdk/x11/gdkkey-x11.c]
*gtk_main_do_event(gtk/gtkmain.c) [#n379dbf0]
_gdk_event_funcはgtk_init関数の呼び出し中でgtk_main_do_ev...
gtk_main_do_event関数ではまずgtk_get_event_widget関数を呼...
GtkWidget*
gtk_get_event_widget (GdkEvent *event)
{
GtkWidget *widget;
widget = NULL;
if (event && event->any.window &&
(event->type == GDK_DESTROY || !GDK_WINDOW_DESTROY...
gdk_window_get_user_data (event->any.window, (void**...
return widget;
}
というわけで、イベントが起きたGdkWindowのuser_dataにイベ...
その後、grabされている場合はイベントウィジェットを切り替...
gtk_propagate_event関数ではKEYイベントの場合、特別処理が...
**gtk_entry_key_press(gtk/gtkentry.c) [#i5513919]
gtk_widget_event関数の実際の処理はgtk_widget_event_intern...
gtk_entry_key_press関数ではまずgtk_im_context_filter_keyp...
gtk_entry_init (GtkEntry *entry)
{
...
entry->im_context = gtk_im_multicontext_new ();
g_signal_connect (entry->im_context, "commit",
G_CALLBACK (gtk_entry_commit_cb), entry);
で、gtk_im_context_filter_keypress関数。
gboolean
gtk_im_context_filter_keypress (GtkIMContext *context,
GdkEventKey *key)
{
GtkIMContextClass *klass;
g_return_val_if_fail (GTK_IS_IM_CONTEXT (context), FAL...
g_return_val_if_fail (key != NULL, FALSE);
klass = GTK_IM_CONTEXT_GET_CLASS (context);
return klass->filter_keypress (context, key);
}
GtkIMContext*が指す実際のオブジェクト(GtkIMMulticontext)...
static gboolean
gtk_im_multicontext_filter_keypress (GtkIMContext *conte...
GdkEventKey *event)
{
GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT ...
GtkIMContext *slave = gtk_im_multicontext_get_slave (m...
if (slave)
return gtk_im_context_filter_keypress (slave, event);
else
return FALSE;
}
gtk_im_multicontext_get_slave関数は現在のロケールやインス...
というわけでgtk_im_context_simple_filter_keypress関数が呼...
gtk_entry_commit_cb関数が呼び出されると中心はGtkEntryに戻...
*おわりに [#c55fa81d]
今回はキーボード入力に対してGTKがどのように処理を行ってい...
-GTKはシグナルなどにより実行時に呼び出される関数を変えて...
-GDKのウインドウ(プラットフォームとのインターフェース部...
ん?そういえばマウスでクリックしてフォーカスを切り替える...
終了行:
#contents
*はじめに [#q6cf1b26]
ここではキーボード入力に対してGUIツールキットがどういう処...
-下位レイヤーから送られてきた情報をどう抽象化しているか
-コントロールフォーカスの管理
なお、プラットフォームはx11とします。
*サンプルコード [#x0e1c0ef]
読解するにあたり、以下のコードについて各関数でどのような...
#code(C){{
#include <stdio.h>
#include <gtk/gtk.h>
static gboolean
window_delete_event(GtkWidget *widget, GdkEvent *event, g...
{
gtk_main_quit();
return FALSE;
}
static void
button_clicked(GtkWidget *widget, gpointer data)
{
const gchar *entry_text;
entry_text = gtk_entry_get_text(GTK_ENTRY(data));
printf("Entry contents: %s\n", entry_text);
}
int
main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *hbox;
GtkWidget *entry;
GtkWidget *button;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_container_set_border_width(GTK_CONTAINER(window),...
g_signal_connect(G_OBJECT(window), "delete_event",
G_CALLBACK(window_delete_event), NULL);
hbox = gtk_hbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), hbox);
gtk_widget_show(hbox);
entry = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, ...
gtk_widget_show(entry);
button = gtk_button_new_with_label("Button");
g_signal_connect(G_OBJECT(button), "clicked",
G_CALLBACK(button_clicked), entry);
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE,...
gtk_widget_show(button);
gtk_widget_show(window);
gtk_main();
return 0;
}
}}
*gtk_init(gtk/gtkmain.c) [#zdf31aaf]
GTKではまずgtk_init関数を呼び出す必要があります。gtk_init...
-GDKのプラットフォーム依存な部分は個別のディレクトリにま...
-先頭に_が付いているのはプラットフォーム依存関数かと思っ...
-GDKのイベントハンドラとして渡されているgtk_main_do_event...
gtk_init_check [gtk/gtkmain.c]
gtk_parse_args [gtk/gtkmain.c]
g_option_context_parse [glib/goption.c]
pre_parse_hook [gtk/gtkmain.c]
do_pre_parse_initialization [gtk/gtkmain.c]
gdk_pre_parse_libgtk_only [gdk/gdk.c]
g_type_init [gobject/gtype.c]
_gdk_windowing_init [gdk/x11/gdkmain-x11.cな...
gdk_event_handler_set(gtk_main_do_event) [gdk/...
post_parse_hook [gtk/gtkmain.c]
do_post_parse_initialization [gtk/gtkmain.c]
gtk_type_init [gtk/gtktypeutils.c]
_gtk_accel_map_init [gtk/gtkaccelmap.c]
_gtk_rc_init [gtk/gtkrc.c]
gdk_display_open_default_libgtk_only [gdk.c]
gdk_display_open [gdk/x11/gdkdisplay-x11.cなど]
_gdk_x11_screen_new [gdk/x11/gdkscreen-x11.c]
_gdk_visual_init [gdk/x11/gdkvisual-x11.c]
_gdk_windowing_window_init [gdk/x11/gdkwindow-x1...
_gdk_x11_events_init_screen [gdk/x11/gdkevents-x11...
gdk_window_new [gdk/x11/gdkwindow-x11.c]
setup_toplevel_window [gdk/x11/gdkwindow-x11.c]
create_focus_window [gdk/x11/gdkwindow-x11.c]
_gdk_events_init [gdk/x11/gdkevents-x11.c]
_gdk_input_init [gdk/x11/gdkinput-none.c]
_gdk_dnd_init [gdk/x11/gdkdnd-x11.c]
**G_DEFINE_TYPE(gobject/gtype.h) [#mca42105]
キーボード入力とは関係ないのですがGTK、というかGLibのオブ...
display = g_object_new (GDK_TYPE_DISPLAY_X11, NULL);
GDK_TYPE_DISPLAY_X11の正体が何者かというと以下の者です。
#define GDK_TYPE_DISPLAY_X11 (_gdk_display_...
GType _gdk_display_x11_get_type (void);
問題なのはgrepをかけても_gdk_display_x11_get_typeという関...
G_DEFINE_TYPE (GdkDisplayX11, _gdk_display_x11, GDK_TYPE...
となっていました。G_DEFINE_TYPEマクロを展開すると型の登録...
**GdkWindow [#h521c5cd]
gtk_init関数呼び出しで実行されるコードの中でGdkWindow周り...
まず、GdkWindowの定義です。
gdk/gdktypes.h
typedef struct _GdkDrawable GdkWindow;
で、_GdkDrawable構造体の定義。
struct _GdkDrawable
{
GObject parent_instance;
};
次にGdkWindowを使っている所としてgdk_window_new関数です。
GdkWindow *window;
GdkWindowObject *private;
GdkWindowImplX11 *impl;
...
window = g_object_new (GDK_TYPE_WINDOW, NULL);
private = (GdkWindowObject *)window;
impl = GDK_WINDOW_IMPL_X11 (private->impl);
GdkWindowをGdkWindowObjectにキャストしています。何故そん...
gdk/gdkwindow.h
#define GDK_TYPE_WINDOW (gdk_window_object_...
gdk/gdkwindow.c
GType
gdk_window_object_get_type (void)
{
static GType object_type = 0;
if (!object_type)
object_type = g_type_register_static_simple (GDK_TYP...
"GdkWindow",
sizeof (GdkWindowObjectClass),
(GClassInitFunc) gdk_window_class_init,
sizeof (GdkWindowObject),
(GInstanceInitFunc) gdk_window_init,
0);
return object_type;
}
というわけで先ほどget_type関数はマクロから作られると書き...
ついでにimplですが、
gdk/gdkwindow.c
static void
gdk_window_init (GdkWindowObject *window)
{
/* 0-initialization is good for all other fields. */
window->window_type = GDK_WINDOW_CHILD;
window->state = GDK_WINDOW_STATE_WITHDRAWN;
window->impl = g_object_new (_gdk_window_impl_get_type...
}
gdk/x11/gdkwindow-x11.c
G_DEFINE_TYPE (GdkWindowImplX11, gdk_window_impl_x11, GD...
GType
_gdk_window_impl_get_type (void)
{
return gdk_window_impl_x11_get_type ();
}
のようになっています。
*g_signal_emit(gobject/gsignal.c) [#a4e175e5]
gtk_init関数を呼んだ後、ごそごそとウィジェットを作成して...
gtk_container_add (GtkContainer *container,
GtkWidget *widget)
{
...
g_signal_emit (container, container_signals[ADD], 0, w...
}
というわけで、子ウィジットのリストに引数のウィジットを追...
次に呼び出される関数がどうやって登録されているかを見てみ...
container_signals[ADD] =
g_signal_new (I_("add"),
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GtkContainerClass, add),
NULL, NULL,
_gtk_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
GTK_TYPE_WIDGET);
雰囲気から察するにaddシグナルが送られるとGtkContainerClas...
gtk_bin_class_init (GtkBinClass *class)
{
GtkContainerClass *container_class;
container_class = (GtkContainerClass*) class;
container_class->add = gtk_bin_add;
となっており、gtk_bin_add関数が設定されています。
*gtk_widget_show(gtk/gtkwidget.c) [#qfa8b68d]
GTKのウィジェットを表示する手順は以下のようになります。
+*_new関数を使ってオブジェクトを作成
+コンテナオブジェクトに設定(親ウィジェットの設定)
+gtk_widget_show関数を呼ぶ
で、最後のgtk_widget_show関数ですが以下のようになっていま...
gtk_widget_show (GtkWidget *widget)
{
g_return_if_fail (GTK_IS_WIDGET (widget));
if (!GTK_WIDGET_VISIBLE (widget))
{
g_object_ref (widget);
if (!GTK_WIDGET_TOPLEVEL (widget))
gtk_widget_queue_resize (widget);
g_signal_emit (widget, widget_signals[SHOW], 0);
g_object_notify (G_OBJECT (widget), "visible");
g_object_unref (widget);
}
}
先ほど説明したg_signal_emit関数が使われています。今回サン...
gtk_widget_real_show (GtkWidget *widget)
{
if (!GTK_WIDGET_VISIBLE (widget))
{
GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
if (widget->parent &&
GTK_WIDGET_MAPPED (widget->parent) &&
GTK_WIDGET_CHILD_VISIBLE (widget) &&
!GTK_WIDGET_MAPPED (widget))
gtk_widget_map (widget);
}
}
何となく条件は成り立たない気がする(親をshowする前に子をs...
**gtk_window_show(gtk/gtkwindow.c) [#m06561bb]
ちょっと長めなので順を追って見ていきます。まず、まだREALI...
gtk_window_compute_configure_request関数ではウインドウの...
次にgtk_widget_size_allocate関数が呼ばれていますがこの関...
次に、REALIZEされていないのでgtk_widget_realize関数が呼び...
gtk_window_show関数に戻って、gtk_decorated_window_calcula...
以上でif(need_resize)のブロックは終了です。次にgtk_widget...
GtkWindowの子ウィジェットに対して実行されたgtk_widget_map...
GtkHBox: gtk_container_mapを実行
gtk_container_forall
GtkContainerClass.forallとして設定されているgtk_box_...
GtkBoxの子要素に対してgtk_widget_mapを実行
GtkEntryの場合、gtk_entry_realizeを実行
gtk_entry_realize関数ではgdk_window_new関数を使ってエディ...
gdk_window_set_user_data (entry->text_area, entry);
gtk_window_show関数に戻ってくるとgtk_window_move_focus関...
gtk_window_move_focus
gtk_widget_child_focus(GtkWindow)
gtk_window_focus(focusシグナル)
gtk_widget_child_focus(GtkHBox)
gtk_container_focus(focusシグナル)
gtk_container_focus_move
gtk_widget_child_focus(GtkEntry)
gtk_widget_real_focus(focusシグナル)
gtk_widget_grab_focus
gtk_entry_grab_focus(grab_focusシグナ...
gtk_widget_real_grab_focus
_gtk_window_internal_set_focus
gtk_window_real_set_focus(set_f...
*gtk_main(gtk/gtkmain.c) [#b14410e3]
ウインドウと表示するウィジェットを設定後、gtk_main関数を...
g_main_loop_new
g_main_context_default
g_main_context_new
g_main_loop_run
g_main_context_iterate
g_main_context_prepare
g_main_context_query
g_main_context_poll
g_main_context_check
g_main_context_dispatch
g_main_dispatch
処理は大雑把に言うと、
+GMainContext.source_listを調べ
+準備ができていたらGMainContext.pending_dispatchesに詰め
+各処理関数にディスパッチ
ということを行っています。
次に調べないといけないのは、source_listがいつ設定されてい...
**_gdk_events_init(gdk/x11/gdkevents-x11.c) [#n6fb9223]
source_listに要素を追加している関数はg_source_list_add関...
今回注目対象としているキーボード入力を処理するsourceは_gd...
まずgdk_display_source_new関数を呼び出してGdkDisplaySourc...
-g_main_context_prepare
-g_main_context_check
-g_main_dispatch
時にそれぞれ呼び出されます。
static GSourceFuncs event_funcs = {
gdk_event_prepare,
gdk_event_check,
gdk_event_dispatch,
NULL
};
次にディスプレイのコネクションナンバーをポーリング対象と...
**gdk_event_prepare(gdk/x11/gdkevents-x11.c) [#e4e58779]
それではまずgdk_event_prepare関数を見てみましょう。コアは...
retval = (_gdk_event_queue_find_first (display) != NULL ...
gdk_check_xpending (display));
_gdk_event_queue_find_first関数はキューにあるイベントから...
イベントが見つからなかった場合、gdk_check_xpending関数が...
gdk_event_check関数はgdk_event_prepare関数とほぼ同じなの...
**gdk_event_dispatch(gdk/x11/gdkevents-x11.c) [#ub794735]
gdk_event_dispatch関数ではまず_gdk_events_queue関数を呼ん...
_gdk_events_queue関数に進みましょう。Xのイベントを取り出...
変換の詳細はgdk_event_translate関数に続く。淡々と変換が行...
gdk_event_translate [gdk/x11/gdkevents-x11.c]
translate_key_event [gdk/x11/gdkevents-x11.c]
_gdk_x11_get_group_for_state [gdk/x11/gdkkey-x11.c]
gdk_keymap_translate_keyboard_state [gdk/x11/gdkkey-...
_gdk_keymap_add_virtual_modifiers [gdk/x11/gdkkey-x1...
_gdk_keymap_key_is_modifiers [gdk/x11/gdkkey-x11.c]
*gtk_main_do_event(gtk/gtkmain.c) [#n379dbf0]
_gdk_event_funcはgtk_init関数の呼び出し中でgtk_main_do_ev...
gtk_main_do_event関数ではまずgtk_get_event_widget関数を呼...
GtkWidget*
gtk_get_event_widget (GdkEvent *event)
{
GtkWidget *widget;
widget = NULL;
if (event && event->any.window &&
(event->type == GDK_DESTROY || !GDK_WINDOW_DESTROY...
gdk_window_get_user_data (event->any.window, (void**...
return widget;
}
というわけで、イベントが起きたGdkWindowのuser_dataにイベ...
その後、grabされている場合はイベントウィジェットを切り替...
gtk_propagate_event関数ではKEYイベントの場合、特別処理が...
**gtk_entry_key_press(gtk/gtkentry.c) [#i5513919]
gtk_widget_event関数の実際の処理はgtk_widget_event_intern...
gtk_entry_key_press関数ではまずgtk_im_context_filter_keyp...
gtk_entry_init (GtkEntry *entry)
{
...
entry->im_context = gtk_im_multicontext_new ();
g_signal_connect (entry->im_context, "commit",
G_CALLBACK (gtk_entry_commit_cb), entry);
で、gtk_im_context_filter_keypress関数。
gboolean
gtk_im_context_filter_keypress (GtkIMContext *context,
GdkEventKey *key)
{
GtkIMContextClass *klass;
g_return_val_if_fail (GTK_IS_IM_CONTEXT (context), FAL...
g_return_val_if_fail (key != NULL, FALSE);
klass = GTK_IM_CONTEXT_GET_CLASS (context);
return klass->filter_keypress (context, key);
}
GtkIMContext*が指す実際のオブジェクト(GtkIMMulticontext)...
static gboolean
gtk_im_multicontext_filter_keypress (GtkIMContext *conte...
GdkEventKey *event)
{
GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT ...
GtkIMContext *slave = gtk_im_multicontext_get_slave (m...
if (slave)
return gtk_im_context_filter_keypress (slave, event);
else
return FALSE;
}
gtk_im_multicontext_get_slave関数は現在のロケールやインス...
というわけでgtk_im_context_simple_filter_keypress関数が呼...
gtk_entry_commit_cb関数が呼び出されると中心はGtkEntryに戻...
*おわりに [#c55fa81d]
今回はキーボード入力に対してGTKがどのように処理を行ってい...
-GTKはシグナルなどにより実行時に呼び出される関数を変えて...
-GDKのウインドウ(プラットフォームとのインターフェース部...
ん?そういえばマウスでクリックしてフォーカスを切り替える...
ページ名: