GNOME Bugzilla – Bug 642929
GtkFileChooserDialog with GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER loops
Last modified: 2011-05-23 19:43:25 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.
Thanks, but could you attach a complete (but small-as-possible) test case?
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. */
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.
[Removing ancient GNOME Target.]
(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.
Reassigning then.
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.
"Illegimite" should of course have been "illegitimate".
(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 :)
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;