Skip to content

Commit

Permalink
Support detailed signals
Browse files Browse the repository at this point in the history
Detailed signals are providing some kind of filtering for signals.

See: https://docs.gtk.org/gobject/concepts.html#the-detail-argument
  • Loading branch information
badcel committed Jan 15, 2023
1 parent e645e17 commit 0315412
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ public void Generate(GirModel.Class obj)
if (obj.Fundamental)
return;

if (!obj.Functions.Any())
return;
//There is always at least the type function (GetGType) available

var source = Renderer.Public.ClassFunctions.Render(obj);
var codeUnit = new CodeUnit(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public InterfaceImplementationFramework(Publisher publisher)

public void Generate(GirModel.Interface obj)
{
//There is always at least the type function (GetGType) available

var source = Renderer.Public.InterfaceImplementationFramework.Render(obj);
var codeUnit = new CodeUnit(
Project: Namespace.GetCanonicalName(obj.Namespace),
Expand Down
20 changes: 20 additions & 0 deletions src/Libs/GObject-2.0/Internal/GTypeProviderHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

namespace GObject.Internal;

#if NET6_0

//TODO: Remove this class once support for dotnet 6 is dropped
public static class GTypeProviderHelper
{
public static nuint GetGType<T>() where T : GObject.Object, GTypeProvider
{
var getGTypeMethod = typeof(T).GetMethod(nameof(GObject.Object.GetGType));

if (getGTypeMethod is null)
throw new Exception($"Method {nameof(GObject.Object.GetGType)} not found on {typeof(T).Name}");

return (nuint) (getGTypeMethod.Invoke(null, null) ?? throw new Exception($"Method {nameof(GObject.Object.GetGType)} on {typeof(T).Name} did not return a result"));
}
}
#endif
5 changes: 3 additions & 2 deletions src/Libs/GObject-2.0/Public/Object.Signals.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ public partial class Object
{
private readonly Dictionary<(SignalDefinition, Delegate), (ulong, Closure)> _signalStore = new();

internal void SignalConnectClosure(SignalDefinition signalDefinition, Delegate callback, Closure closure, bool after)
internal void SignalConnectClosure(SignalDefinition signalDefinition, Delegate callback, Closure closure, bool after, string? detail)
{
var handlerId = Internal.Functions.SignalConnectClosure(Handle, signalDefinition.UnmanagedName, closure.Handle, after);
var detailQuark = GLib.Functions.QuarkFromString(detail);
var handlerId = Internal.Functions.SignalConnectClosureById(Handle, signalDefinition.Id, detailQuark, closure.Handle, after);

if (handlerId == 0)
throw new Exception($"Could not connect to event {signalDefinition.ManagedName}");
Expand Down
9 changes: 7 additions & 2 deletions src/Libs/GObject-2.0/Public/SignalDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@ public interface SignalDefinition
/// <summary>
/// The name of the signal in GObject/C.
/// </summary>
public string UnmanagedName { get; }
string UnmanagedName { get; }

/// <summary>
/// The name of the signal in dotnet.
/// </summary>
public string ManagedName { get; }
string ManagedName { get; }

/// <summary>
/// The Id of the signal in GObject/C
/// </summary>
uint Id { get; }
}
35 changes: 23 additions & 12 deletions src/Libs/GObject-2.0/Public/SignalTSender.cs
Original file line number Diff line number Diff line change
@@ -1,39 +1,50 @@
using System;

namespace GObject;
namespace GObject;

/// <summary>
/// Describes a GSignal.
/// </summary>
public class Signal<TSender> : SignalDefinition
where TSender : Object
where TSender : Object, GTypeProvider
{
private uint? _id;

public string UnmanagedName { get; }
public string ManagedName { get; }
public uint Id => _id ??= GetId();

public Signal(string unmanagedName, string managedName)
{
UnmanagedName = unmanagedName;
ManagedName = managedName;
}

private uint GetId()
{
#if NET7_0_OR_GREATER
var gType = TSender.GetGType();
#else
var gType = Internal.GTypeProviderHelper.GetGType<TSender>();
#endif

return Internal.Functions.SignalLookup(UnmanagedName, gType);
}

/// <summary>
/// Connects an <paramref name="signalHandler"/> to this signal.
/// Connects a <paramref name="signalHandler"/> to this signal.
/// </summary>
/// <param name="o">The object on which connect the handler.</param>
/// <param name="signalHandler">The signal handler function.</param>
/// <param name="after">
/// Define if this action must be called before or after the default handler of this signal.
/// </param>
public void Connect(TSender o, SignalHandler<TSender> signalHandler, bool after = false)
/// <param name="after">Define if this action must be called before or after the default handler of this signal.</param>
/// <param name="detail">Define for which signal detail the connection should be made.</param>
public void Connect(TSender o, SignalHandler<TSender> signalHandler, bool after = false, string? detail = null)
{
var closure = new Closure((returnValue, parameters) => signalHandler(o, EventArgs.Empty));
var closure = new Closure((returnValue, parameters) => signalHandler(o, System.EventArgs.Empty));

o.SignalConnectClosure(this, signalHandler, closure, after);
o.SignalConnectClosure(this, signalHandler, closure, after, detail);
}

/// <summary>
/// Disconnects an <paramref name="signalHandler"/> previously connected to this signal.
/// Disconnects a <paramref name="signalHandler"/> previously connected to this signal.
/// </summary>
/// <param name="o">The object from which disconnect the handler.</param>
/// <param name="signalHandler">The signal handler function.</param>
Expand Down
29 changes: 21 additions & 8 deletions src/Libs/GObject-2.0/Public/SignalTSenderTSignalArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,40 @@
/// Describes a GSignal.
/// </summary>
public class Signal<TSender, TSignalArgs> : SignalDefinition
where TSender : Object
where TSender : Object, GTypeProvider
where TSignalArgs : SignalArgs, new()
{
private uint? _id;

public string UnmanagedName { get; }
public string ManagedName { get; }
public uint Id => _id ??= GetId();

public Signal(string unmanagedName, string managedName)
{
UnmanagedName = unmanagedName;
ManagedName = managedName;
}

private uint GetId()
{
#if NET7_0_OR_GREATER
var gType = TSender.GetGType();
#else
var gType = Internal.GTypeProviderHelper.GetGType<TSender>();
#endif

return Internal.Functions.SignalLookup(UnmanagedName, gType);
}

/// <summary>
/// Connects an <paramref name="action"/> to this signal.
/// Connects a <paramref name="signalHandler"/> to this signal.
/// </summary>
/// <param name="o">The object on which connect the handler.</param>
/// <param name="signalHandler">The signal handler function.</param>
/// <param name="after">
/// Define if this action must be called before or after the default handler of this signal.
/// </param>
public void Connect(TSender o, SignalHandler<TSender, TSignalArgs> signalHandler, bool after = false)
/// <param name="after">Define if this action must be called before or after the default handler of this signal.</param>
/// <param name="detail">Define for which signal detail the connection should be made.</param>
public void Connect(TSender o, SignalHandler<TSender, TSignalArgs> signalHandler, bool after = false, string? detail = null)
{
var closure = new Closure((returnValue, parameters) =>
{
Expand All @@ -33,11 +46,11 @@ public void Connect(TSender o, SignalHandler<TSender, TSignalArgs> signalHandler
signalHandler(o, args);
});

o.SignalConnectClosure(this, signalHandler, closure, after);
o.SignalConnectClosure(this, signalHandler, closure, after, detail);
}

/// <summary>
/// Disconnects an <paramref name="action"/> previously connected to this signal.
/// Disconnects a <paramref name="signalHandler"/> previously connected to this signal.
/// </summary>
/// <param name="o">The object from which disconnect the handler.</param>
/// <param name="signalHandler">The signal handler function.</param>
Expand Down

0 comments on commit 0315412

Please sign in to comment.