转载自:
http://blog.csdn.net/hwizhao/archive/2009/02/10/3873577.aspx
modal dialog 的实现
gtk中,modal dialog的实现一般是说通过g_main_loop的嵌套来实现的。但最近发现并非如此。
是否为modal dialog, 主要由是否调用如下函数控制:
1、gtk_window_set_modal(window, TRUE);而这个函数主要做几件事情:
(1)、向window manager设置_NET_WM_STATE atom中_NET_WM_STATE_MODAL 的值
(2)、gtk_grab_add(window)
gtk_grab_add(window)后,和这个window在一个group的窗口收到的点击事件等都不被处理
当这个modal window 被hide或关掉后,再调用gtk_grab_remove(window)函数。
2、gtk_window_set_type_hint(window, GDK_WINDOW_TYPE_HINT_DIALOG);
当设置了这个属性后,window manager将会将原来的窗口始终显示在点击出的窗口之下,即使之前的窗口已经获得了focus。
mainloop的嵌套
当已有了一个main loop在跑的情况下,在这个main loop的回调函数中可以new并run另一个main loop, 这时第一个main loop被block在执行这个回调函数中,而新生成的main loop由于和第一个main loop使用同一个context,将代替第一个main loop处理事件循环。
gboolean
shutdown_loop(GtkWidget *widget, GdkEventAny *evt, gpointer user_data)
{
GMainLoop *loop = (GMainLoop *)user_data;
if(g_main_loop_is_running(loop))
g_main_loop_quit(loop);
return FALSE;
}
g_boolean
show_modal_window(GtkWidget *widget, GdkEventButton *evt)
{
...
GMainLoop *loop = g_main_loop_new(NULL, FALSE); // NULL ensures that this loop uses default context
g_signal_connect(window, "delete_event", G_CALLBACK(shutdown_loop), loop);
g_main_loop_run(loop);
g_main_loop_unref(loop);
return FALSE;
}
当一个dialog是否为modal,并不由其是否实现红色部分的代码(嵌套main loop)控制,而是由上面说过的两个函数决定的。
第二个loop的存在,使得即使在没有第一个loop的情况下,单独调用show_modal_window, 仍然可以处理消息循环。
g_object_notify的使用方法
0、注册部分
g_object_class_install_property(gobject_class,
PROP_MODAL,
g_param_spec_boolean("modal", P_("Modal"), P_("if true, the window is modal( other windows are not usable while this one is up)"), FALSE, GTK_PARAM_READWRITE)
);
1、emit部分
g_object_notify(G_OBJECT(window), "modal");
2. connect部分
g_signal_connect(window, "notify::modal", G_CALLBACK(notify_modal_received), NULL);
3、回调函数
void notify_modal_received(GtkWidget *window, GParamSpec *pspec)
{
printf("notify modal received");
}
4.调用顺序和运行结果:
1->2->3
notify modal received
5.g_object_notify作用描述:
提交一个“notify”信号给‘window‘对象的‘pspec‘属性
g_object_notify的另类使用
我们可以通过使用exo库提供的函数来进行多个对象中的属性关联
Thunar 1.0.0部分代码
thunar/thunar-preferences-dialog.c:
GtkWidget *button; button = gtk_radio_button_new_with_mnemonic (NULL, _("_Object1")); exo_mutual_binding_new (G_OBJECT (dialog->preferences), "misc-single-click", G_OBJECT (button), "active");// 关联两个对象‘dialog->preferences’和‘button’的属性 g_signal_connect (G_OBJECT (button), "toggled", G_CALLBACK (g_object_notify), "active");//radio button选中时发送notify给active gtk_table_attach (GTK_TABLE (table), button, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_widget_show (button); button = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (button), _("_Object2")); exo_mutual_binding_new_with_negation (G_OBJECT (dialog->preferences), "misc-single-click", G_OBJECT (button), "active"); g_signal_connect (G_OBJECT (button), "toggled", G_CALLBACK (g_object_notify), "active"); gtk_table_attach (GTK_TABLE (table), button, 0, 1, 1, 2, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_widget_show (button);