GNOME Bugzilla – Bug 612802
regression in GtkTreeView from 2.18.x?
Last modified: 2018-02-10 03:20:44 UTC
Hi, In details view mode with Thunar (http://launchpadlibrarian.net/40868278/Gigolo.png), if I enter a subdirectory by using the mouse, once inside I cannot interact with any file or directory: selecting by single-click and launching by double-click don't work, and right-click displays a context menu as if the mouse pointer is over an empty area (i.e. not over an entry). This worked fine in Ubuntu karmic (gtk+ 2.18.x), but behaves like that in Ubuntu lucid (gtk+ 2.19.x, currently .7). Thunar doesn't use directly a GtkTreeView for its details view (http://git.xfce.org/xfce/thunar/tree/thunar/thunar-details-view.h & http://git.xfce.org/xfce/thunar/tree/thunar/thunar-details-view.c), but uses an ExoTreeView from exo (http://git.xfce.org/xfce/exo/tree/exo/exo-tree-view.h & http://git.xfce.org/xfce/exo/tree/exo/exo-tree-view.c). AFAIK, nothing changed in thunar nor exo recently, so I wonder if it's a regression in gtk+ from the 2.18.x series. I don't know exactly where the bug is, but even if this report is closed, at least I'll know it's not in gtk+. ;) Thanks!
My guess is that the fixes for 596473 (and additional fix in 607322) have caused this. The exo tree view and thunar code both do quite some logic in their button press and button release handlers that override the GtkTreeView button press/release methods. That makes it very hard to say whether thunar or gtk+ is to blame here. I would need to write a minimal example in GTK+ that replaces the model on double click. (is that how it navigates through folders? Or does it refill the model or create an entire new tree view?) If that example shows the problem, then it is a bug in GTK+ for sure.
I'm a user of archlinux and we are also investigating this bug in: http://bugs.archlinux.org/task/18904 From what I've seen the problem arises after upgrading GTK2 to version 2.20. Downgrading GTK to version 2.18.9 seems to solve the problem. I've tried to isolate the problem, and it seems to be in the file /usr/lib/libgtk-x11-2.0.so.0 (of course this could be different in other distros) I've upgraded the GTK again to version 2.20 and just replaced that file with the file from the older 2.18.9 version. After that Thunar works fine again. Although it's not a proper solution I hope that it could help somebody here and also help the experts to track down the problem more easily. Best regards. David.
(In reply to comment #1) > I would need to write a minimal example in GTK+ that replaces the model on > double click. I quickly tried this and this works just fine.
Can somebody debug thunar and that exo library it depends on to see where the problem exactly is? As I have mentioned in comment 1, this might be related to bugs 596473 and 607322. I really don't have time to install or compile XFCE from source and debug that code myself. What we need here is a small stand-alone test case that reproduces the problem.
Hi, could you put your test case somewhere ?
I found the problem to be in exo 0.3.106, the piece of code below changes selection->user_func then restore it. The difference of behaviour between gtk 2.18 and 2.20 is that the second condition is not satisfied, even when the first is (and they are both the same). A workaround is easy, but i wonder what would be the change in gtk 2.20 that explains the difference : /* unfortunately GtkTreeView will unselect rows except the clicked one, * which makes dragging from a GtkTreeView problematic. That's why we * remember the selected paths here and restore them later. */ if (event->type == GDK_BUTTON_PRESS && (event->state & gtk_accelerator_get_default_mod_mask ()) == 0 && path != NULL && gtk_tree_selection_path_is_selected (selection, path)) { /* if no custom select function is set, we simply use exo_noop_false here, * to tell the tree view that it may not alter the selection. */ if (G_LIKELY (selection->user_func == NULL)) gtk_tree_selection_set_select_function (selection, (GtkTreeSelectionFunc) exo_noop_false, NULL, NULL); else selected_paths = gtk_tree_selection_get_selected_rows (selection, NULL); } /* call the parent's button press handler */ result = (*GTK_WIDGET_CLASS (exo_tree_view_parent_class)->button_press_event) (widget, event); /* restore previous selection if the path is still selected */ if (event->type == GDK_BUTTON_PRESS && (event->state & gtk_accelerator_get_default_mod_mask ()) == 0 && path != NULL && gtk_tree_selection_path_is_selected (selection, path)) { /* check if we have to restore paths */ if (G_LIKELY (selection->user_func == (GtkTreeSelectionFunc) exo_noop_false)) { /* just reset the select function (previously set to exo_noop_false), * there's no clean way to do this, so what the heck. */ selection->user_func = NULL; } else { /* select all previously selected paths */ for (lp = selected_paths; lp != NULL; lp = lp->next) gtk_tree_selection_select_path (selection, lp->data); } }
Thanks for diving into these sources! (In reply to comment #6) > I found the problem to be in exo 0.3.106, the piece of code below changes > selection->user_func then restore it. > The difference of behaviour between gtk 2.18 and 2.20 is that the second > condition is not satisfied, even when the first is (and they are both the > same). > if (event->type == GDK_BUTTON_PRESS && (event->state & > gtk_accelerator_get_default_mod_mask ()) == 0 > && path != NULL && gtk_tree_selection_path_is_selected (selection, path)) Do you know which part of the condition is no longer satisfied the second time? I can't seem to reproduce this in a little test. As far as I can see, only the return value of gtk_tree_selection_path_is_selected can be different the second time, as event->type, event->state and path are likely unaffected while GtkTreeView's handler is run.
Yep, gtk_tree_selection_path_is_selected is changing; i've put a g_warning before each test : -> two simple clicks on the same row : (thunar:5299): exo-WARNING **: is selected 0 (thunar:5299): exo-WARNING **: is selected 1 (thunar:5299): exo-WARNING **: is selected 1 (thunar:5299): exo-WARNING **: is selected 1 -> one double-click : (thunar:5285): exo-WARNING **: is selected 0 (thunar:5285): exo-WARNING **: is selected 1 (thunar:5285): exo-WARNING **: is selected 1 (thunar:5285): exo-WARNING **: is selected 0
Interesting; when I put likewise g_warnings() directly in the button-press handler in the GtkTreeView source code, then the path stays selected in the double-click case. So it looks like something is de-selecting the selected path in the double-click case. Is there something else in exo/thunar that might be influencing this? As far as I know, tree view does not de-select rows after a successful double click.
You're right : (thunar:17712): exo-WARNING **: BUTTON_PRESS_EVENT (thunar:17712): exo-WARNING **: is selected 0 (thunar:17712): exo-WARNING **: is selected 1 (thunar:17712): exo-WARNING **: BUTTON_PRESS_EVENT (thunar:17712): exo-WARNING **: is selected 1 (thunar:17712): Thunar-WARNING **: thunar : thunar_details_view_row_activated : unselect (thunar:17712): exo-WARNING **: is selected 0 the culprit being the following function, though i guess it's expected that unselect_all/select_path should leave the row selected (when there is only one that is selected). static void thunar_details_view_row_activated (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, ThunarDetailsView *details_view) { GtkTreeSelection *selection; GtkAction *action; _thunar_return_if_fail (THUNAR_IS_DETAILS_VIEW (details_view)); /* be sure to have only the double clicked item selected */ selection = gtk_tree_view_get_selection (tree_view); gtk_tree_selection_unselect_all (selection); gtk_tree_selection_select_path (selection, path); /* emit the "open" action */ action = thunar_gtk_ui_manager_get_action_by_name (THUNAR_STANDARD_VIEW (details_view)->ui_manager, "open"); if (G_LIKELY (action != NULL)) gtk_action_activate (action); }
i was wrong, sorry : disabling gtk_tree_selection_unselect_all (selection); gtk_tree_selection_select_path (selection, path); still gives the same result (row selected before and unselected after), so the problem is somewhere else... I'll investigate more later.
I researched this problem in order to include a workaround in my mod of pcmanfm 0.5.2 at http://igurublog.wordpress.com/downloads/mod-pcmanfm/ This problem exhibits the following in pcmanfm: In double-click mode, if a folder is double-clicked and entered, then subsequent clicks are ignored. However, if an inaccessible folder is double-clicked (and thus not entered), the problem does not appear. Also, in testing I found that the button press events proceeded normally after the problem was triggered - they just did nothing because nothing was selected. IOW the problem, once triggered by entering a folder by double-clicking, is that clicking on an item no longer selects it. I found the trigger for the problem in exo-tree-view.c, in exo_tree_view_button_press_event(). This line does it: gtk_tree_selection_set_select_function (selection, (GtkTreeSelectionFunc) exo_noop_false, NULL, NULL); That line is part of the following code excerpt in that function: /* unfortunately GtkTreeView will unselect rows except the clicked one, * which makes dragging from a GtkTreeView problematic. That's why we * remember the selected paths here and restore them later. */ if (event->type == GDK_BUTTON_PRESS && (event->state & gtk_accelerator_get_default_mod_mask ()) == 0 && path != NULL && gtk_tree_selection_path_is_selected (selection, path)) { /* if no custom select function is set, we simply use exo_noop_false here, * to tell the tree view that it may not alter the selection. */ if (G_LIKELY (selection->user_func == NULL)) gtk_tree_selection_set_select_function (selection, (GtkTreeSelectionFunc) exo_noop_false, NULL, NULL); else selected_paths = gtk_tree_selection_get_selected_rows (selection, NULL); } Changing that segment to the following avoids the problem: if (event->type == GDK_BUTTON_PRESS && (event->state & gtk_accelerator_get_default_mod_mask ()) == 0 && path != NULL && gtk_tree_selection_path_is_selected (selection, path)) { selected_paths = gtk_tree_selection_get_selected_rows (selection, NULL); }
(In reply to comment #12) > IOW the problem, once triggered by > entering a folder by double-clicking, is that clicking on an item no longer > selects it. > > I found the trigger for the problem in exo-tree-view.c, in > exo_tree_view_button_press_event(). This line does it: > > gtk_tree_selection_set_select_function (selection, (GtkTreeSelectionFunc) > exo_noop_false, NULL, NULL); Isn't it exactly the point of this line to disable alteration of the selection? At least that is what the line does and what the comment above it says: > /* if no custom select function is set, we simply use exo_noop_false > here, > * to tell the tree view that it may not alter the selection. > */ > Changing that segment to the following avoids the problem: > > > if (event->type == GDK_BUTTON_PRESS && (event->state & > gtk_accelerator_get_default_mod_mask ()) == 0 > && path != NULL && gtk_tree_selection_path_is_selected (selection, path)) > { > selected_paths = gtk_tree_selection_get_selected_rows (selection, > NULL); > } This basically removes the logic and thus breaks the behavior exo was trying to implement here. As far as I know, the real problem is that the selection function is not properly restored; see analyses 6 and 8.
(In reply to comment #13) > Isn't it exactly the point of this line to disable alteration of the selection? Yes - it appears so. > This basically removes the logic and thus breaks the behavior exo was trying to > implement here. I'm not very familiar with exo, but my interpretation is that the logic used exo_noop_false as the easy method and reverted to saving the selected paths in other cases. I changed the logic so it always uses the second method (saves paths) to avoid the exo issue. This may not be as efficient but should be just as functional, as saving paths should work in all cases. I haven't encountered any issues using it this way thus far. > As far as I know, the real problem is that the selection function is > not properly restored; see analyses 6 and 8. That makes sense. One pcmanfm sets exo_noop_false then selection seems impossible, with the keyboard as well IIRC.
Also, > As far as I know, the real problem is that the selection function is > not properly restored; see analyses 6 and 8. But does this mean that treeview is not properly reseting the exo_noop value when the treeview is reloaded or reset (as it apparently did in prior versions), or that the pcmanfm and thunar code is not properly manually reseting the value after it changes the directory? At any rate, something with the GTK 2.20 update changed the behavior of treeview in this regard.
FYI http://bugzilla.xfce.org/show_bug.cgi?id=6230#c13 http://git.xfce.org/xfce/exo/commit/?id=cd80ae7747aa87ab6d72f08386b0fd4bea7f05b3
(In reply to comment #16) > FYI > http://bugzilla.xfce.org/show_bug.cgi?id=6230#c13 From that comment: ""However the real bug seems to be gtk_tree_view_get_path_at_pos() in exo_tree_view_button_press_event() which doesn't return a path at the 2nd click, while it does in gtk 2.18."". Does anybody have test code for this? If gtk_tree_view_get_path_at_pos() would in general stop returning paths after the first click, a lot more people would have complained ;)
No, but i did put some debug lines in the critical parts of the code and they showed the path returned NULL a couple of times, while I don't see that in 2.18. Maybe I cook a small test for this next week, including gtk_tree_model_get_iter_first() to see if maybe the internal model is gone.
That would be great!
We're moving to gitlab! As part of this move, we are closing bugs that haven't seen activity in more than 5 years. If this issue is still imporant to you and still relevant with GTK+ 3.22 or master, please consider creating a gitlab issue for it.