Setting the scroll position of a GtkTextView in GtkScrolledWindow after render

Hey!

I posted this question to the mailing list as well, but perhaps there are people here that know the answer.

I can’t figure out if it’s me or something’s amiss. I’m trying to set the scroll position after rendering a GtkTextView in a GtkScrolledWindow, but it’s reset to a different value, if it works at all. I’ve so far tried to set the vertical adjustment value both after GtkScrolledWindow is mapped or its child (GtkTextView) size-allocated. When using a GtkListBox instead of a GtkTextView and setting the adjustment’s value on “size-allocate”, it works. No such luck with a GtkTextView, however.

The peculiar thing with the GtkTextView is, while the adjustment reports its upper bound to be, for example, 588 and its value 0, immediately after setting it to 493, it reports its value as 11. I figure “size-allocate” is still the wrong event to use here given the adjustment is in flux. What would the right path be to consistently set the scroll position after the first render, and later, after resetting the GtkTextView’s buffer?

This is on Arch Linux with gtk3 v3.24.7+25+g17665f06e3-1.

Thanks in advance!

Honestly, I don’t think there is a way currently. I’ve had a number of issues with this in Builder and every workaround I’ve come up with has various failure cases.

I think the breakage was introduced with scroll animation support which is complicated by the high-priority idle functions scanning ahead to measure text layouts so that a real height value may be calculated.

One crazy workaround I did was to have a GSource that looked at the visual location for a textiter, and then confirmed that the textiter was the same that was found when looking up that visual position. But even that doesn’t always work.

Thanks, @chergert!

You’re right. Looking into https://gitlab.gnome.org/GNOME/gtk/blob/3.24.7/gtk/gtktextview.c#L4508, I can see that it does indeed lay 2000px out at once and does so with the priority GTK_TEXT_VIEW_PRIORITY_VALIDATE (https://gitlab.gnome.org/GNOME/gtk/blob/3.24.7/gtk/gtktextview.c#L4550).

I can also see incremental_validate_callback updates the adjustments every idle tick until text is laid out. I wonder if through listening to those updates I can retry setting the scroll position until it finally sticks. From my initial test check it at least seems the upper bound of the vertical adjustment is refined downwards. That permits differentiating incomplete layouts (where my set position doesn’t stick) from an invalid scroll point (where my set position is really beyond the upper bound). I’ll have to play around with this. Feels like the web where setting the scroll position is quite a challenge. :stuck_out_tongue:

One of the biggest problems is that you can’t trust the GtkTextIter location from gtk_text_view_get_iter_location(), which ultimately means you don’t even know the Y position to scroll to manually.

Good point. Fortunately in this situation I’ve stored the pixel position from an earlier render of the same text and am just trying to restore position when redisplaying it.

After some further testing I’ve come to the same result suggested by everyone — scrolling ends up only working if done after the incremental validation idle callbacks have finished. This can be achieved by setting your own idle callback with a priority value slightly larger than TEXT_VIEW_PRIORITY_VALIDATE. The unfortunately side-effect of this asynchrony is the flash of unscrolled content. For a long document that may end up being hundreds of milliseconds. I wonder if hiding the text before it’s laid out in some manner would be a tolerable compromise. Delayed scrolling is definitely a crappy experience.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.