hugopl/gi-crystal

`GLib::SList` of type `Gio::File` raises

GeopJr opened this issue · 2 comments

Example:

require "gtk4"

app = Gtk::Application.new("hello.example.com", Gio::ApplicationFlags::None)

app.activate_signal.connect do
  window = Gtk::ApplicationWindow.new(app)
  window.title = "DnD test"
  window.set_default_size(200, 200)

  button = Gtk::Label.new("Drag-n-Drop a file here")
  window.child = button

  controller = Gtk::DropTarget.new(Gdk::FileList.g_type, Gdk::DragAction::Copy)
  controller.drop_signal.connect(->dnd_drop(GObject::Value, Float64, Float64))
  window.add_controller(controller)

  window.present
end

def dnd_drop(value, x, y)
  files = Gdk::FileList.new(value.to_unsafe, GICrystal::Transfer::Full).files
  p files
  p files.size
  p files[0]

  true
end

exit(app.run)

raises (with error-trace)

In examples/hello_world.cr:15:34

 15 | controller.drop_signal.connect(->dnd_drop(GObject::Value, Float64, Float64))
                                     ^-------
Error: instantiating 'dnd_drop(GObject::Value, Float64, Float64)'


In examples/hello_world.cr:25:10

 25 | p files[0]
             ^
Error: instantiating 'GLib::SList(Gio::File)#[](Int32)'


In lib/gi-crystal/src/bindings/g_lib/slist.cr:25:11

 25 | self[n]?.not_nil!
          ^
Error: instantiating 'GLib::SList(Gio::File)#[]?(Int32)'


In lib/gi-crystal/src/bindings/g_lib/slist.cr:32:7

 32 | to_crystal(value)
      ^---------
Error: instantiating 'to_crystal(Pointer(LibGLib::SList))'


In lib/gi-crystal/src/bindings/g_lib/slist.cr:38:7

 38 | {% if T == String %}
      ^
Error: expanding macro


There was a problem expanding macro 'macro_140293467917264'

Called macro defined in lib/gi-crystal/src/bindings/g_lib/slist.cr:38:7

 38 | {% if T == String %}

Which expanded to:

 > 1 | 
 > 2 |         T.new(data)
 > 3 |       
Error: undefined method 'new' for Gio::File:Module

Gio::File:Module trace:

  macro macro_140293467917264 (in /tmp/gtk4.cr/lib/gi-crystal/src/bindings/g_lib/slist.cr:38):2

            T.new(data)

Edit:
Working dnd example with #72

require "gtk4"

app = Gtk::Application.new("hello.example.com", Gio::ApplicationFlags::None)

app.activate_signal.connect do
  window = Gtk::ApplicationWindow.new(app)
  window.title = "DnD test"
  window.set_default_size(200, 200)

  button = Gtk::Label.new("Drag-n-Drop a file here")
  window.child = button

  controller = Gtk::DropTarget.new(Gdk::FileList.g_type, Gdk::DragAction::Copy)
  controller.enter_signal.connect(->dnd_enter(Float64, Float64))
  controller.drop_signal.connect(->dnd_drop(GObject::Value, Float64, Float64))
  button.add_controller(controller)

  window.present
end

def dnd_enter(x, y)
  puts "entered"
  Gdk::DragAction::Copy
end

def dnd_drop(value, x, y)
  object_ptr = LibGObject.g_value_get_boxed(value.to_unsafe)
  files = Gdk::FileList.new(object_ptr, GICrystal::Transfer::Full).files
  p files
  files.each do |x|
    puts x.uri
  end

  true
end

exit(app.run)

bug is caused because GFile is a interface, so the current code don't know how to create an instance of it, because in fact it need to create an instance of AbstractFile or restore the original Crystal object if this C object is appearing for the first time in Crystal world.

Bindings for GList is probably broken too, but I didn't test.

Awesome! It works! I updated the OP with a working example, thanks 🙇