Hello,
Before posting here I read all available materials on gtkDialogs and modality and try to get it working properly for whole a week!
So, here is probably bug in gtk.
To illustrate problem I make a sample.
UI: (main1.glade)
Code:
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkMessageDialog" id="dialog1">
<property name="height_request">150</property>
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="type_hint">dialog</property>
<property name="skip_taskbar_hint">True</property>
<property name="message_type">error</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="button3">
<property name="label" translatable="yes">Cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button4">
<property name="label" translatable="yes">OK</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<child>
<object class="GtkViewport" id="viewport1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkTable" id="table1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_rows">2</property>
<property name="n_columns">2</property>
<child>
<object class="GtkEntry" id="entry1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">•</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">First</property>
</object>
</child>
<child>
<object class="GtkEntry" id="entry2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">•</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">button3</action-widget>
<action-widget response="0">button4</action-widget>
</action-widgets>
</object>
<object class="GtkMessageDialog" id="dialog2">
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="type_hint">dialog</property>
<property name="skip_taskbar_hint">True</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="button5">
<property name="label" translatable="yes">Cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button6">
<property name="label" translatable="yes">OK</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkTable" id="table2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_rows">2</property>
<property name="n_columns">2</property>
<child>
<object class="GtkEntry" id="entry3">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">•</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Second</property>
</object>
</child>
<child>
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry4">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">•</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">button5</action-widget>
<action-widget response="0">button6</action-widget>
</action-widgets>
</object>
<object class="GtkWindow" id="window1">
<property name="width_request">300</property>
<property name="height_request">100</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">External dialog demo</property>
<property name="window_position">center</property>
<child>
<object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">with scrolledwindow = modal don't work</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="button1_clicked_cb" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button2">
<property name="label" translatable="yes">without scrolledwindow = modal works</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="button2_clicked_cb" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
</interface>
Program: (main.c)
Code:
// compile with: `pkg-config gtk+-2.0 --libs gmodule-2.0` -export-dynamic
#include <stdlib.h>
#include <gtk/gtk.h>
GtkBuilder *builder;
GtkWidget *window;
GtkDialog *dialog1, *dialog2;
G_MODULE_EXPORT void
button1_clicked_cb(GtkObject *object, gpointer user_data)
{
builder = gtk_builder_new();
gtk_builder_add_from_file(builder, "main1.glade", NULL);
dialog1 = GTK_DIALOG(gtk_builder_get_object(builder, "dialog1"));
gtk_builder_connect_signals(builder, NULL);
g_object_unref(G_OBJECT(builder));
gtk_window_set_title(GTK_WINDOW(GTK_DIALOG(dialog1)), "Bugy!");
gtk_window_set_modal(GTK_WINDOW(GTK_DIALOG(dialog1)), TRUE);
gtk_window_set_transient_for(GTK_WINDOW(GTK_DIALOG(dialog1)), GTK_WINDOW(window));
//
int x, y;
gdk_window_get_origin(GDK_WINDOW(GTK_WIDGET(window)->window), &x, &y);
gtk_window_move(GTK_WINDOW(dialog1), x+8, y);
//
gtk_dialog_run(GTK_DIALOG(dialog1));
gtk_widget_destroy(GTK_WIDGET(GTK_DIALOG(dialog1)));
g_object_unref(G_OBJECT(dialog1));
}
G_MODULE_EXPORT void
button2_clicked_cb(GtkObject *object, gpointer user_data)
{
builder = gtk_builder_new();
gtk_builder_add_from_file(builder, "main1.glade", NULL);
dialog2 = GTK_DIALOG(gtk_builder_get_object(builder, "dialog2"));
gtk_builder_connect_signals(builder, NULL);
g_object_unref(G_OBJECT(builder));
gtk_window_set_title(GTK_WINDOW(GTK_DIALOG(dialog2)), "OK");
gtk_window_set_modal(GTK_WINDOW(GTK_DIALOG(dialog2)), TRUE);
gtk_window_set_transient_for(GTK_WINDOW(GTK_DIALOG(dialog2)), GTK_WINDOW(window));
//
int x, y;
gdk_window_get_origin(GDK_WINDOW(GTK_WIDGET(window)->window), &x, &y);
gtk_window_move(GTK_WINDOW(dialog2), x+8, y);
//
gtk_dialog_run(GTK_DIALOG(dialog2));
gtk_widget_destroy(GTK_WIDGET(GTK_DIALOG(dialog2)));
g_object_unref(G_OBJECT(dialog2));
}
int main(int argc, char **argv)
{
gtk_init(&argc, &argv);
builder = gtk_builder_new();
gtk_builder_add_from_file(builder, "main1.glade", NULL);
window = GTK_WIDGET(gtk_builder_get_object(builder, "window1"));
gtk_builder_connect_signals(builder, NULL);
g_object_unref(G_OBJECT(builder));
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show(window);
gtk_main();
return 0;
}
Problem is that gtkscrolledwindow in dialog breaks his modality. If I set size of container enough to fit all gtkscrolledwindow contents then modality will not be broken, dialog will work as expected. In real life this is not solution because we use other widgets where gtkscrolledwindow with scrollbars is required like gtktextview or gtktreeview.
Same is in gtk3. Same is with normal toplevel windows when they should to be modal in relation to main window.
By looking other software, like synaptic, which uses this they work properly. That means here must be workaround. Or maybe is not a bug?
I would like any advice from experienced users how to avoid this problem and get modal gtkdialogs (and windows) with gtkscrollviews to work as expected in mean of modality, please.
nime
Gtk 2.24, Ubuntu 11.10/64