After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 642929 - GtkFileChooserDialog with GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER loops
GtkFileChooserDialog with GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER loops
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Widget: GtkFileChooser
unspecified
Other Linux
: Normal normal
: ---
Assigned To: Federico Mena Quintero
Federico Mena Quintero
Depends on:
Blocks:
 
 
Reported: 2011-02-21 23:10 UTC by Martin Schobert
Modified: 2011-05-23 19:43 UTC
See Also:
GNOME target: ---
GNOME version: 2.27/2.28


Attachments
test case to reproduce the problem (1.87 KB, text/x-c++src)
2011-02-22 14:24 UTC, Martin Schobert
Details

Description Martin Schobert 2011-02-21 23:10:20 UTC
Hello,

  I use the file chooser dialog to ask the user for a directory, where some files should be written to. Therefore the ctor parameter Gtk::FILE_CHOOSER_ACTION_CREATE_FOLDER is used (see below). The dialog shows a text entry field. The user should enter a directory name into it. If this text entry field is left blank and the user clicks on the select button, the dialog loops and method run() does not return.

Code to reproduce the problem:

The code is directly derived from the sample code from http://library.gnome.org/devel/gtkmm-tutorial/2.21/sec-dialogs-filechooserdialog.html.en.

void ExampleWindow::on_button_folder_clicked()
{
  Gtk::FileChooserDialog dialog("Please choose a folder",
          Gtk::FILE_CHOOSER_ACTION_CREATE_FOLDER);
  dialog.set_transient_for(*this);

  //Add response buttons the the dialog:                                                                                                                                  
  dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
  dialog.add_button("Select", Gtk::RESPONSE_OK);

  std::cout << "run dialog\n";
  int result = dialog.run();
  std::cout << "run() finished\n";

  //Handle the response:                                                                                                                                                  
  switch(result)
  {
    case(Gtk::RESPONSE_OK):
    {
      std::cout << "Select clicked." << std::endl;
      std::cout << "Folder selected: " << dialog.get_filename()
          << std::endl;
      break;
    }
    case(Gtk::RESPONSE_CANCEL):
    {
      std::cout << "Cancel clicked." << std::endl;
      break;
    }
    default:
    {
      std::cout << "Unexpected button clicked." << std::endl;
      break;
    }
  }
}


Possible workaround:

If the create-folder switch is not required, it might be possible to use the select-folder switch. This workaround was used here 

http://gramps.1791082.n4.nabble.com/FileChooserDialog-infinite-loop-fixed-td3084343.html

... but this is not the way I intent to use the file chooser dialog.


I use the gtkmm libs that are available from ubuntu-10-10 package system. I am not sure, whether the problem is fixed in more recent gtkmm versions.
Comment 1 Murray Cumming 2011-02-22 05:32:37 UTC
Thanks, but could you attach a complete (but small-as-possible) test case?
Comment 2 Martin Schobert 2011-02-22 14:24:12 UTC
Created attachment 181587 [details]
test case to reproduce the problem

/*

 Compile:

 g++ test.cc -o test `pkg-config gtkmm-2.4 --cflags --libs`

 Run:
 Click the button 'Choose folder', then click on select, but do not enter
 a string into the text entry field. It will hang.



*/
Comment 3 Murray Cumming 2011-02-22 14:42:12 UTC
Confirmed with latest gtkmm-2,4 and gtkmm-3.0.

I guess it is a GTK+ bug so we need to create a C test case.
Comment 4 André Klapper 2011-03-08 14:25:03 UTC
[Removing ancient GNOME Target.]
Comment 5 Kjell Ahlstedt 2011-05-01 17:24:13 UTC
(In reply to comment #3)
> I guess it is a GTK+ bug so we need to create a C test case.

The gtk+ folks have provided a test case for us:
http://git.gnome.org/browse/gtk+/tree/tests/testfilechooser.c

Call it with
  ./testfilechooser --action=create_folder
and press the Save button without adding a folder name.

It loops. If you start it as a background job, and check now and then with
'ps', you can see that testfilechooser uses a lot of processor time.
Comment 6 Murray Cumming 2011-05-02 06:55:31 UTC
Reassigning then.
Comment 7 Kjell Ahlstedt 2011-05-15 14:23:09 UTC
The infinite loop is in gtk_file_chooser_default_should_respond().

When gtk_file_chooser_default_should_respond() is entered, an 'if' statement
and 3 or 4 'else if' statements are passed, until either the condition
  line 8673
  if (impl->location_entry &&
      impl->toplevel_last_focus_widget == impl->location_entry)
or
  line 8682
  if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
      || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
is met. Both cases result in 'goto save_entry;'

At save_entry, check_save_entry() returns is_empty == TRUE, causing a jump to
file_list. At file_list, impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
and selection_check() returns num_selected == 0. Then action = SAVE_ENTRY,
causing a jump back to save_entry.

The infinite loop is avoided if you replace (line 8594)
      if (is_empty)
        {
          if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
            return FALSE;

          goto file_list;
        }
by
      if (is_empty)
        {
          if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
              impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
            return FALSE;

          goto file_list;
        }

I can't say if this is the correct fix for this bug. It might have bad side
effects that I'm not aware of.


A totally illegimite(?) comment:
Some people consider 'goto' a bad thing. In gtkfilechooserdefault.c there are
13 gotos, 6 of them in gtk_file_chooser_default_should_respond(), not counting
'goto out', which I consider acceptable.
Comment 8 Kjell Ahlstedt 2011-05-15 14:29:22 UTC
"Illegimite" should of course have been "illegitimate".
Comment 9 Federico Mena Quintero 2011-05-23 19:19:09 UTC
(In reply to comment #7)
> At save_entry, check_save_entry() returns is_empty == TRUE, causing a jump to
> file_list. At file_list, impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
> and selection_check() returns num_selected == 0. Then action = SAVE_ENTRY,
> causing a jump back to save_entry.

Excellent, you are absolutely correct - and your fix is the correct one.  I'll push it; thanks for debugging it!

Sorry that that function is so convoluted... it grew over the years to handle different special cases.  Cleanup would be appreciated, if you have time :)
Comment 10 Federico Mena Quintero 2011-05-23 19:43:25 UTC
Pushed.

commit 219e82c9e7089fe45ec5f3f117651d5b7fcd577e
Author: Kjell Ahlstedt <kjell.ahlstedt@bredband.net>
Date:   Mon May 23 15:02:00 2011 -0500

    bgo#642929 - Don't infinite-loop in GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
    
    If the user pressed Enter to confirm the file chooser while the filename entry
    was empty, then gtk_file_chooser_default_should_respond() would go back and forth
    between the cases for handling the filename entry and the file list.

diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c
index 9c6c717..0189838 100644
--- a/gtk/gtkfilechooserdefault.c
+++ b/gtk/gtkfilechooserdefault.c
@@ -8593,7 +8593,8 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
 
       if (is_empty)
         {
-          if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+          if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
+	      || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
             return FALSE;
 
           goto file_list;