GNOME Bugzilla – Bug 341055
gtk_file_chooser_default_map() clobbers already-set current_folder
Last modified: 2007-01-25 20:10:51 UTC
Gedit uses the following code to set the current_folder on the GtkFileChooser to the folder it wants to: if (default_path != NULL) gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (open_dialog), default_path); g_free (default_path); selector_width = gedit_prefs_manager_get_opensave_dialog_width (); selector_height = gedit_prefs_manager_get_opensave_dialog_height (); gtk_window_resize (GTK_WINDOW (open_dialog), selector_width, selector_height); g_signal_connect (open_dialog, "response", G_CALLBACK (open_dialog_response_cb), window); gtk_widget_show (open_dialog); However, it appears that GTK is clobbering the already-set current folder when the widget actually gets mapped. It appears this is due to the async changes. Sequence of events: In gedit_cmd_file_open(): 1) gedit creates file chooser widget 2) gedit sets current folder on the widget, which calls gtk_file_chooser_default_update_current_folder(). This sets impl->update_current_folder_handle to the handle for the first current_folder request. Since the callback is async, it doesn't execute now. Note that impl->reload_state is probably still RELOAD_EMPTY, since the async bits haven't run yet. 3) gedit calls gtk_widget_show (open_dialog);, which eventually maps the file chooser 4) gtk executes gtk_file_chooser_default_map() for the file chooser, which exectues the RELOAD_EMPTY statements, which calls gtk_file_chooser_set_current_folder() 5) In this _second_ call to gtk_file_chooser_set_current_folder(), which is really gtk_file_chooser_default_update_current_folder(), mpl->update_current_folder_handle gets set to the default directory which was specified from #4 above 6) Eventually the first async call for #2 above runs, which executes the following code: if (handle != impl->update_current_folder_handle) goto out; However, since impl->update_current_folder_handle is now the handle from #5 above, and 'handle' is the handle from #2 above, we break out and dont' set the directory to what it should be set to, which is what gedit wants. Backtrace: Breakpoint 1, gtk_file_chooser_default_update_current_folder (chooser=Variable "chooser" is not available. ) at gtkfilechooserdefault.c:6190 6190 data = g_new0 (struct UpdateCurrentFolderData, 1); (gdb) bt
+ Trace 68093
I guess the real problem here is that the async bits for setting the current folder that gedit requests don't get run before the mapping of the GtkFileChooser, which means that the impl->reload_state doesn't reflect requests that have been made already. Note that tests/testfilechooser.c doesn't catch this because it doesn't set the current directory before it shows the widget. It only allows the current folder to be set after it's already showing onscreen. One possible solution here is to set impl->reload_state to RELOAD_HAS_FOLDER in gtk_file_chooser_default_update_current_folder() to make sure the race with gtk_file_chooser_default_map() doesn't happen. A better solution would be to suppress the impl->reload_state code in gtk_file_chooser_default_map() if impl->update_current_folder_handle != NULL. If that's the case, then we know that somebody has already requested a current_folder set operation, and that we don't need to do anything. If the request errors out or gets cancelled, code for that might get a bit tricky though.
*** Bug 346058 has been marked as a duplicate of this bug. ***
This works now with 2.10.6.