8

I would like to emit a custom signal from a Widget in gtk3.
In GTK2, there was a function called signal_new to create a new signal.
You can see an example here: https://github.com/ruby-gnome2/ruby-gnome2/blob/ec373f87e672dbeeaa157f9148d18b34713bb90e/glib2/sample/type-register.rb

In GTK3 it seems this function isn't available anymore. So what is the new way to create custom signals in ruby's GTK3?

0xAffe
  • 1,156
  • 1
  • 13
  • 29
  • You need to create a new subclass of GtkWidget and, in its `class_init` function, call [`g_signal_new()`](https://developer.gnome.org/gobject/stable/gobject-Signals.html#g-signal-new) passing the GType of your new class as the `itype` object. While there seems to be a facility for this in `GLib::Signal`, it isn't documented; you'll need to ask the maintainers of the ruby gtk3 binding. – andlabs Aug 13 '16 at 01:42
  • 1
    I suspect (haven't used signal_new, and I'm not a Ruby user) all these functions are moved to GObject. There is a method called GObject.signal_new() in Python. – jcoppens Aug 13 '16 at 18:27

1 Answers1

4

GTK3 changed to using a define_signal method instead of signal_new. This method is called on class-level (much like something like attr_accessor).

Here's an example class, using a custom signal called example. I've adapted this from a sample on the glib2 GitHub repo.

class ExampleClass < GLib::Object
  # To use define_signal, the class must first be registered with GLib's
  # type hierarchy.
  type_register

  # This declares the custom signal.
  define_signal(
    'example', # signal name
    nil,       # flags (combination of GLib::Signal's constants)
    nil,       # accumulator; apparently not supported
    nil        # signal return type, where nil is void
  )
end

By default, a signal's handler block accepts one parameter, which is the object which emitted the signal. If you'd like the signal to use additional parameters, you can pass extra arguments to define_signal with their types.

Once you've configured a signal, you can emit it using signal_emit:

example = ExampleClass.new
example.signal_emit('example')

If there were additional arguments to pass, their values can be passed as extra arguments to signal_emit.

This signal can be connected to just like any other GTK3 signal, using signal_connect:

e = ExampleClass.new
e.signal_connect('example') do |sender|
  puts "Handler 1, sent by #{sender}"
end
e.signal_connect('example') do |sender|
  puts "Handler 2, sent by #{sender}"
end
e.signal_emit('example')

This would output something like:

Handler 1, sent by #<ExampleClass:0x0000564d436331e8>
Handler 2, sent by #<ExampleClass:0x0000564d436331e8>

Again, if your signal uses additional parameters, they would be extra arguments passed to signal_connect's block.

Aaron Christiansen
  • 11,584
  • 5
  • 52
  • 78
  • 2
    [glib2: add GLib::Object.define_signal](https://github.com/ruby-gnome2/ruby-gnome2/commit/919d92c3f6e97cc2aeac661390890eb1a7c3a3f5) is the commit where this was added. Good find! – Tom Jan 10 '19 at 17:59