GNOME Bugzilla – Bug 656848
Cursor row doesn't get set when populating the tree after it gets the focus
Last modified: 2018-02-10 03:22:01 UTC
After patching bug #492206 (see comment #17 there for the patch) to make GtkTreeView not change the selection when it gets focused, I noticed the following. 1. Create a treeview 2. Add columns and set an empty model If the treeview is focused (by giving it explicit focus, or by making it the first widget in the window), you get what you expect: a treeview with a focus rectangle around the whole empty area. Now do this: 1. Create a treeview 2. Add columns and a model 3. Populate the model with rows If the treeview is focused explicitly or through being the first widget in the window, you get what you expect: a treeview with the first row being the cursor row (i.e. it has a focus rectangle), but no rows are selected. But if you do this: 1. Create a treeview 2. Add columns and an empty model 3. Make the tree grab the focus 4. Populate the model with rows I.e. if the treeview has the focus and *then* you add rows, then you get no cursor row and no focus indicator. This is a problem in the file chooser, where we populate the file list asynchronously, and the treeview has the focus by then. So, once the file list appears, you get no indication of what has the focus. I'm attaching a test program that lets you test this. It has a "random focusable widget" (an entry) that you can use to control whether the treeview has the focus before or after it gets populated.
Created attachment 194168 [details] testtreecursor.c
Some notes: * By the time we hit gtk_tree_view_bin_draw(), it looks like some assertions should be in place: either the tree is empty (no cursor), or it's not empty and we *have* a cursor, or as a corner case, there are only unfocusable rows in the tree (what to do here?). But in bin_draw(), it's probably too late to pick a cursor row if there isn't one yet - we'd need to invalidate a row from the draw handler, which is iffy - so that needs to happen earlier, when the model changes. * Look at gtk_tree_view_set_model(). * Look at gtk_tree_view_row_inserted() / deleted() / changed() / rows_reordered() - those are the mutation functions, and the cursor needs to be set by the time they are done. One could say that it is the app's responsibility for what row to focus when it mutates the tree. But even if we do a best-effort job of picking a focused row when the tree changes, the app is still free to change that afterwards - so it's OK for the mutation functions to pick a cursor row themselves.
There's been a bunch of changes in the cursor handling code recently. So I'm not sure how much of this still applies. But the generic question is: Given an empty model that (quickly) populates itself - like the filechooser - how should we treat the cursor? Should we: a) keep no cursor set until the user interacts with the treeview (focussing it or clicking/keynaving)? b) set the cursor on the first row that gets added and then update it according to some rules? c) something else? d) all of the above?
(a) sounds right - don't set the cursor until the user interacts with the treeview. *Then*, when the user focuses the treeview for the first time, we can 1. if clicked upon, set the cursor on the clicked row or 2. if Tabbed into, set the cursor on the first visible+selectable row There needs to be a find_first_selectable_row() somewhere; I believe there is already such a walk-the-tree function. If there are no selectable rows, we should draw a dotted line around the whole tree, like if the model were empty.
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.