GNOME Bugzilla – Bug 154007
GtkFileChooserWidget resize causes application to hang
Last modified: 2011-02-04 16:17:29 UTC
Please describe the problem: When using GtkFileChooserWidget instead of GtkFileChooserDialog, the resize of the GtkWindow containing it to a smaller width than the currently active pathbar button causes GTK to enter a non-exiting loop. (NOTE: The resizing in most cases will not work trough the UI, instead GTK functions must be used). The same effect can be produced by entering a directory of which the name is broader then the currently total width of the pathbar. This does *not* happen with GtkFileChooserDialog Steps to reproduce: 1. Open FileChooser and navigate trough filesystem 2. Enter directory which's display in the patbar is/would be broader than the total pathbar's width so it would cause a resize of the window 3. FileChooser enters loop and display starts to osciallate Actual results: See (3) Expected results: Window should be resized. Does this happen every time? Yes. Other information:
Created attachment 32042 [details] Simple testcase in which FileChooser behaves correctly (using FileChooserDialog) This is a simple testcase in which a resize to an unreasonable width happens, but the Dialog is resizing correctly and shows up with an appropriate size.
Created attachment 32043 [details] Simple testcase in which FileChooser behaves badly (using FileChooserWidget) Another testcase, this time the code is minimally adapted and uses GtkFileChooserWidget. The same resize is being applied but GTK enters an infinite loop.
Comment on attachment 32042 [details] Simple testcase in which FileChooser behaves correctly (using FileChooserDialog) Simple testcase in which GtkFileChooserDialog is being resize to an unreasonable size using gtk_widget_set_size_request(). The Dialog though re-resize back into an appropriate size and no error occurs.
This size allocation loop is caused by the following line in gtkfilechooserdefault.c: gtk_paned_set_position (GTK_PANED (hpaned), 200); /* FIXME: this sucks */ Removing it makes the loop go away. Needs more investigation as to a) why the line is there b) why the loop occurs
I'm pretty sure the /* this sucks */ fixme is about the hardcoded '200'. (Once again proving that fixmes without descriptions of what need to be fixed a bad idea.) It might not be needed at all now that we don't have a (possibly very wide) tree on the left. But it would be good to investigate the loop.
*** Bug 142388 has been marked as a duplicate of this bug. ***
Removing the call to gtk_paned_set_position() doesn't get rid of the looping :(
This isn't fixed in 2.4.14 (target milestone) unfortunately.
*** Bug 163534 has been marked as a duplicate of this bug. ***
Even the "correctly behaving" testcase can easily be brought into an infinite loop by resizing the window horizontally to a small width until a scrollbar appears in the shortcuts treeview. An interesting observation is that if the window is resized so that the add and remove bookmark buttons are shrunk a bit (but not so much that it goes into the resizing loop) and then slowly widened again, the left pane will alternate between two different widths. It looks like this is because in gtk_paned_compute_position, paned->max_position becomes smaller than paned->min_position, and because of this the CLAMP line that sets paned->child1_size alternatingly sets it to paned->min_position and paned->max_position every other call. A simple change to gtk_paned_compute_position that makes sure that max_position never becomes smaller than min_position prevents the resizing loop in the test programs attached in this bug and in testfilechooser when entering a folder with a very long name, however I don't know if this is the right solution or if the actual problem is elsewhere. (I'm seeing this with GTK+ from anoncvs HEAD on Linux/X11)
Created attachment 36693 [details] [review] Possible fix or at least workaround (patch for gtk/gtkpaned.c)
If paned->max_position becomes less than paned->min_position in that function, that looks to me like the GtkPaned got allocated less space than it's requisition. That really should be tracked down before applying the GtkPaned patch, though the GtkPaned patch looks right to me at first glance.
Just for fun I've done some heavy debugging, and think I have found the cause. It's not simple, let's see if I can explain it... You should of course take everything with a grain of salt as this is rather complicated so it is quite possible that I've missed something, but I think the big picture is about right :) Basically what happens for me with testfilechooser when entering a folder with a long name is this: 1. (some stuff) 2. A resize is queued for the dialog window 3. gtk_window_move_resize is called by gtk_container_idle_sizer 4. gtk_window_move_resize sees that the window must be resized: --- Select a file --- last : 0,0 624 x 480 this : 0,0 1369 x 480 alloc : 328,272 624 x 480 req : 1369 x 190 resize: 960 x 480 size_changed: 1 pos_changed: 0 hints_changed: 1 configure_notify_received: 0 configure_request_count: 0 position_constraints_changed: 0 It queues a resize for the window but removes the resizing handler to wait for the configure event 5. Suddenly idle_finished_loading_cb (gtkfilesystemmodel.c) is called, and in turn invokes browse_files_model_finished_loading_cb, which calls gtk_tree_view_set_model which does some stuff that queues a new resize on the dialog window 6. gtk_window_move_resize is called by gtk_container_idle_sizer even though no configure event has been received yet. The children of the dialog are allocated with the old allocation of the dialog: --- Select a file --- last : 0,0 1369 x 480 this : 0,0 1369 x 480 alloc : 328,272 624 x 480 req : 1369 x 190 resize: -1 x -1 size_changed: 0 pos_changed: 0 hints_changed: 0 configure_notify_received: 0 configure_request_count: 1 position_constraints_changed: 0 gtk_widget_size_allocate: GtkFileChooserDialog 624 480 gtk_widget_size_allocate: GtkVBox 624 480 7. The hpaned will shrink the left pane as the allocation isn't enough as we talked about earlier. This causes a scrollbar to appear in the left tree view. 8. Showing the scrollbar queues another resize on the dialog 9. gtk_window_move_resize returns but gtk_container_idle_sizer immediately calls it again due to (8) 10. Start over from step 6. This time the left pane of the hpaned will grow and the scroll bar disappears which queues another resize etc.
Created attachment 36847 [details] Debug output Here are some debug messages from running testfilechooser with inserted references to the steps above.
Created attachment 36848 [details] Debugging code diff Here's a diff with the ugly debugging code I used if anyone is interested. Stepping through the code seems to affect the timing so the bug doesn't trigger, however a breakpoint in _gtk_container_queue_resize with a suitable ignore count is useful. ./testfilechooser --gtk-debug=geometry --gdk-debug=events > chooserlog12 2>&1
2005-02-04 Matthias Clasen <mclasen@redhat.com> * gtk/gtkpaned.c (gtk_paned_compute_position): Work better when there is not enough space. This avoids a nasty size allocation loop in the file chooser. (#154007, reported by Milosz Derezynski, patch by Robert Ögren)