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 341055 - gtk_file_chooser_default_map() clobbers already-set current_folder
gtk_file_chooser_default_map() clobbers already-set current_folder
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Widget: GtkFileChooser
2.9.x
Other Linux
: Normal normal
: ---
Assigned To: gtk-bugs
Federico Mena Quintero
Depends on:
Blocks:
 
 
Reported: 2006-05-08 17:40 UTC by Dan Williams
Modified: 2007-01-25 20:10 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Dan Williams 2006-05-08 17:40:57 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
  • #0 gtk_file_chooser_default_update_current_folder
    at gtkfilechooserdefault.c line 6190
  • #1 _gtk_file_chooser_set_current_folder_path
    at gtkfilechooser.c line 1066
  • #2 delegate_set_current_folder
    at gtkfilechooserutils.c line 297
  • #3 _gtk_file_chooser_set_current_folder_path
    at gtkfilechooser.c line 1066
  • #4 delegate_set_current_folder
    at gtkfilechooserutils.c line 297
  • #5 _gtk_file_chooser_set_current_folder_path
    at gtkfilechooser.c line 1066
  • #6 IA__gtk_file_chooser_set_current_folder_uri
    at gtkfilechooser.c line 1002
  • #7 gedit_cmd_file_open
    at gedit-commands-file.c line 343
  • #47 g_main_context_iterate
    at gmain.c line 2547
  • #48 IA__g_main_loop_run
    at gmain.c line 2751
  • #49 IA__gtk_main
    at gtkmain.c line 999
  • #50 main
    at gedit.c line 566
  • #0 gtk_file_chooser_default_update_current_folder
    at gtkfilechooserdefault.c line 6190
  • #1 _gtk_file_chooser_set_current_folder_path
    at gtkfilechooser.c line 1066
  • #2 IA__gtk_file_chooser_set_current_folder
    at gtkfilechooser.c line 678
  • #3 gtk_file_chooser_default_map
    at gtkfilechooserdefault.c line 5379
  • #77 g_main_context_iterate
    at gmain.c line 2547
  • #78 IA__g_main_loop_run
    at gmain.c line 2751
  • #79 IA__gtk_main
    at gtkmain.c line 999
  • #80 main
    at gedit.c line 566

Comment 1 Dan Williams 2006-05-08 17:51:15 UTC
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.
Comment 2 Joe Halliwell 2006-06-27 22:58:09 UTC
*** Bug 346058 has been marked as a duplicate of this bug. ***
Comment 3 Federico Mena Quintero 2007-01-25 20:10:51 UTC
This works now with 2.10.6.