The context
I'm converting a C/GTK+ GUI application to C#. I'm using the GTKSharp bindings version 3.22.0 in VS2017.
The application declares several signals like
g_signal_new ("SIG_NAME", params...);
and emits them via g_signal_emit_by_name(... "SIG_NAME"...).
The problem
I can't find a way to translate that behaviour into GTK#.
I've looked into GTK#'s source code to see how custom signals are defined and handled, like here, but I haven't been able to mimic the behaviour implemented there.
The approach
- Approach #1
I've tried defining a custom object like this:
using System;
using Gtk;
public class MyApp
{
public class MyCustomObj : GLib.Object
{
public delegate void MyDelegateSignalHandler(int arg0, int arg1);
public delegate void MyDelegate(int arg0, int arg1);
public class MyDelegateArgs : GLib.SignalArgs
{
public int a { get; set; }
}
public MyCustomObj() : base()
{}
[GLib.Signal("MyEvent")]
public event MyDelegate MyDelegateEvent
{
add
{
GLib.Object.GetObject(Handle).AddSignalHandler("MyEvent", value, new MyDelegateSignalHandler((a, b) => { }));
}
remove
{
GLib.Object.GetObject(Handle).RemoveSignalHandler("MyEvent", value);
}
}
}
public static void Main(string[] args)
{
MyCustomObj newObj = new MyCustomObj();
newObj.MyDelegateEvent += new MyCustomObj.MyDelegate((a, b) => { });
GLib.Signal.Emit(newObj, "MyEvent", 1, 2);
}
}
That is:
- A custom
GLibobject type,MyCustomObj, is declared - A
MyDelegateevent is declared - An instance of
MyCustomObjis created and a callback is attached to its new event - A
MyEventsignal is emitted.
When AddSignalHandler() is called, however, GTK isn't too happy about that:
(CustomSignal.exe:9276): GLib-GObject-[1;33mWARNING[0m **: ../../glib-2.50.2/gobject/gsignal.c:2423: signal 'MyEvent' is invalid for instance '05cc4000' of type '__gtksharp_0_MyApp+2bMyCustomObj'
And therefore GLib.Signal.Emit reports
Invalid signal name: MyEvent
- Approach #2
However, GObject's definition uses AddSignalHandler this way:
public void AddNotification (string property, NotifyHandler handler)
{
AddSignalHandler ("notify::" + property, handler, typeof(NotifyArgs));
}
So it seems that a signal named notify::<whatever> is handled just fine. Let's try this:
public class MyCustomObj : GLib.Object
{
public MyCustomObj() : base()
{}
[GLib.Signal("notify::abc")]
public event GLib.NotifyHandler MyDelegateEvent
{
add
{
GLib.Object.GetObject(Handle).AddSignalHandler("notify::abc", value, typeof(GLib.NotifyArgs));
}
remove
{
GLib.Object.GetObject(Handle).RemoveSignalHandler("notify::acb", value);
}
}
}
public static void Main(string[] args)
{
MyCustomObj newObj = new MyCustomObj();
newObj.MyDelegateEvent += new GLib.NotifyHandler((o, e) => { Console.WriteLine("Signal received"); });
GLib.Signal.Emit(newObj, "notify::abc");
Console.ReadLine();
}
And this actually works. Moreover, [GLib.Signal("notify::abc")] is unnecessary as the signal is correctly registered and handled. Renaming the signal name to anything that is not notify::..., however, causes the application to raise the usual warning:
(CustomSignal.exe:9276): GLib-GObject-[1;33mWARNING[0m **: ../../glib-2.50.2/gobject/gsignal.c:2423: signal '...' is invalid for instance '05cc4000' of type '__gtksharp_0_MyApp+2bMyCustomObj'
I could use a hand as I'm out of ideas.