Search code examples
c#gtk

how can I automatically scroll to bottom in GTK TextView


I found weird anomalies in GTK textview, hopefully someone can explain them.

There is a simple function to scroll to bottom of window:

richTextBox.ScrollToIter(richTextBox.Buffer.EndIter, 0, true, 0, 0);

this is probably supposed to work and work in most cases. But sometimes it crashes whole application with MemoryAccessViolation (SIGSEGV in linux)

My application call this everytime I insert a text to TreeView so that I can be always down (you are inserting a text to some window, and you want to see the latest text, like in a chat)

The text is only inserted from main thread and this function is ALSO called only in main thread, so this can't be related to multithreading in my own application, however I found out that TextView is rendering text asynchronously with the rest of application. Like if the thread responsible for painting and processing the text wasn't really a main thread. For example if I load a huge text into a TextView, my application IS responding, even if TextView is somehow loading the text.

For this reason I believe that TextView is actually working with own separate thread, and this thread is changing the text as I am trying to scroll the window. Text being changed invalidates the iter, so somewhere between in the IL code where I am passing richTextBox.Buffer.EndIter to TextView ScrollToBottom function the text is probably changed by this foreign thread and iter is invalidated, which is why I get this memory access exception.

This may be even a bug in GTK, but I am using very stable version (2.1.20) that is shipped with all mono versions until mono3 and even for all windows gtk# versions.

Is there any other way to scroll down "safely"


Solution

  • This seems to work:

    Connect the function that scrolls to SizeAllocated event:

    this.tv.SizeAllocated += new SizeAllocatedHandler(Scroll2);
    

    Create a function for scrolling

    public void Scroll2(object sender, Gtk.SizeAllocatedArgs e)
    {
        tv.ScrollToIter(tv.Buffer.EndIter, 0, false, 0, 0);
    }
    

    I don't know if it's correct, but it didn't crash to me so far and it always scroll to bottom once rendering is done