Gtk.jl icon indicating copy to clipboard operation
Gtk.jl copied to clipboard

Inserting text in GtkTextBuffer crashes v1.6 in some conditions

Open jonathanBieler opened this issue 4 years ago • 3 comments

I came across this strange crash in v1.6 (works just fine in prior versions). The example is a bit long but I think all these ingredients are necessary to trigger the issue. In short I have a custom widget v that holds a GtkTextBuffer and a callback that modifies it using insert!. It seems I have to do at least two edits to cause a problem :

function insert_text(str, v)
    it = GtkTextIter(v.buffer, 1)
    insert!(v.buffer, it, str)

    it = GtkTextIter(v.buffer, 2)
    insert!(v.buffer, it, str)
end

Which gives a :

(<unknown>:15129): Gtk-WARNING **: 15:04:25.871: Invalid text buffer iterator: either the iterator is uninitialized, or the characters/pixbufs/widgets in the buffer have been modified since the iterator was created.
You must use marks, character numbers, or line numbers to preserve a position across buffer modifications.
You can apply tags and insert marks without invalidating your iterators,
but any mutation that affects 'indexable' buffer contents (contents that can be referred to by character offset)
will invalidate all outstanding iterators

(<unknown>:15129): Gtk-CRITICAL **: 15:04:25.871: gtk_text_buffer_insert: assertion 'gtk_text_iter_get_buffer (iter) == buffer' failed

Interestingly passing the buffer directly to the function "solves" the problem :

function insert_text(str, buffer)
    it = GtkTextIter(buffer, 1)
    insert!(buffer, it, str)

    it = GtkTextIter(buffer, 2)
    insert!(buffer, it, str)
end

Not sure what the issue is, looks like some kind of memory problem. Full example :

using Gtk
import Gtk: GtkTextIter, mutable

mutable struct Widget{B<:GtkTextBuffer} <: GtkScrolledWindow
    handle::Ptr{Gtk.GObject}
    buffer::B
    view::GtkTextView
    function Widget{B}() where {B<:GtkTextBuffer}

        b = B()
        b.text[String] = "test"
        v = GtkTextView(b)
        sc = GtkScrolledWindow()
        
        push!(sc, v)

        n = new(sc.handle, b, v)
        Gtk.gobject_move_ref(n, sc)
    end
end

PROPAGATE = convert(Cint, false)
INTERRUPT = convert(Cint, true)

get_text_left_of_iter(it::GtkTextIter) = ((mutable(it)-1):mutable(it)).text[String]

@guarded (PROPAGATE) function key_press_cb(widgetptr::Ptr, eventptr::Ptr, user_data)
    
    textview = convert(GtkTextView, widgetptr)
    event = convert(Gtk.GdkEvent, eventptr)
    v = user_data

    if event.keyval == Gtk.GdkKeySyms.Tab
        @info "trying to insert"
        insert_text("test", v)
        return INTERRUPT
    end
    PROPAGATE
end

function insert_text(str, v)
    it = GtkTextIter(v.buffer, 1)
    insert!(v.buffer, it, str)

    it = GtkTextIter(v.buffer, 2)
    insert!(v.buffer, it, str)
end

#= function insert_text(str, buffer)
    it = GtkTextIter(buffer, 1)
    insert!(buffer, it, str)

    it = GtkTextIter(buffer, 2)
    insert!(buffer, it, str)
end =#

w = GtkWindow()
v = Widget{GtkTextBuffer}()

push!(w, v)

it = GtkTextIter(v.buffer, 1)
insert!(v.buffer, it, "test insert")

signal_connect(key_press_cb, v.view, "key-press-event", Cint, (Ptr{Gtk.GdkEvent}, ), false, v)

showall(w)

jonathanBieler avatar Feb 01 '21 14:02 jonathanBieler

I'd note that tests are failing on Julia nightly (Julia v1.6 isn't tested at the moment)

giordano avatar Feb 01 '21 14:02 giordano

On my machine it's the test of GtkRadioButtonGroup that fails, which is also a custom widget, so maybe it's related to my issue :

https://github.com/JuliaGraphics/Gtk.jl/blob/7c8802a6fa5ce0002b529d5017ffe72365ea4b4a/src/buttons.jl#L56

jonathanBieler avatar Feb 01 '21 14:02 jonathanBieler

I have a crash on 1.6 on internal code, which I also need to track down. Don't have time for that right now.

tknopp avatar Feb 01 '21 15:02 tknopp