GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Fri Oct 31, 2014 5:57 pm

All times are UTC




Post new topic Reply to topic  [ 3 posts ] 
Author Message
 Post subject: Gtk modal dialogs bug?
PostPosted: Mon Jan 30, 2012 11:45 am 
Offline
Familiar Face

Joined: Fri Jul 01, 2011 6:40 pm
Posts: 48
Location: Croatia
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


Top
 Profile  
 
 Post subject: Re: Gtk modal dialogs bug?
PostPosted: Mon Jan 30, 2012 12:57 pm 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hi.

I tested your app here (Gentoo x86_64 with latest stable GTK+2) and modality works as expected: when any of the dialogs is open, it takes control of the whole app and no interaction is possible with other parts of the app. There are a few rough spots in your code where memory is leaking, but none of them matter with regards to modality.

Maybe this is an Ubuntu bug (I must say that I wouldn't be too surprised if that shows to be the case, since Ubuntu patches GTK+ quite a lot lately)? Can you test this on some other machine with non-Ubuntu OS?

Cheers,
Tadej


Top
 Profile  
 
 Post subject: Re: Gtk modal dialogs bug?
PostPosted: Mon Jan 30, 2012 1:05 pm 
Offline
Familiar Face

Joined: Fri Jul 01, 2011 6:40 pm
Posts: 48
Location: Croatia
I can't test on other OS for now.
But I find this: https://bugs.launchpad.net/ubuntu/+sour ... bug/903302
They say problem is in scrollbars (and maybe ubuntu too) so I don't know what to do now until someone fix this.

As for memory leaks, I still learning gtk and C.
Critics is welcome for me :)

EDIT:
Almost forgot, I have windows 7 im my comp with gtk, and yes, there works as expected so bug IS related to ubuntu. Hm...

But I looks now "Update manager" in Ubuntu, it seems like is written in gtk and his windows works properly with modality and scrolledwindow.
Can here be some workaround until they don't fix issue?


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC


Who is online

Users browsing this forum: Yahoo [Bot] and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group