GirCore.Notify libnotify and Sample
Hello
Sample https://github.com/czirok/gir.core.samples/tree/main/NotifyAdw Temporarily, the full Notify bindings are included under the Libs folder.
Gnome flatpak SDK
Notify-0.7.gir included.
Support all platform
https://formulae.brew.sh/formula/libnotify#default https://packages.msys2.org/base/mingw-w64-libnotify
Problem
Namespace Notify conflict with GObject.Notify.
What is the rule for namespace collision?
Currently, I have added a dotless version in the example. "Notify07"
Fixer
src/Generation/Generator/Fixer/Namespace.cs (Modified)
namespace Generator.Fixer;
public static class Namespace
{
private static readonly List<Fixer<GirModel.Namespace>> Fixers = new()
{
new DisableRecordsConflictingWithGObjectsFixer(),
new NamespaceNameConflictFixer(),
};
public static void Fixup(GirModel.Namespace ns)
{
foreach (var fixer in Fixers)
fixer.Fixup(ns);
}
}
src/Generation/Generator/Fixer/Namespace/NamespaceNameConflictFixer.cs (New)
namespace Generator.Fixer.Ns;
internal class NamespaceNameConflictFixer : Fixer<GirModel.Namespace>
{
public void Fixup(GirModel.Namespace ns)
{
IEnumerable<string> classMethodNames = ns.Classes
.SelectMany(AllMethods)
.Select(Method.GetPublicName);
if (classMethodNames.Contains(ns.Name))
{
var name = Model.Namespace.GetPublicName(ns);
var fixedName = $"{name}{ns.Version.DotlessVersion()}";
Model.Namespace.SetPublicName(ns, fixedName);
Log.Information($"Namespace '{ns.Name}' renamed to '{Model.Namespace.GetPublicName(ns)}' due to conflict with method name in the same namespace.");
}
}
public static IEnumerable<GirModel.Method> AllMethods(GirModel.Class cls)
{
var methods = new HashSet<GirModel.Method>();
foreach (var method in cls.Methods)
methods.Add(method);
if (cls.Parent is not null)
foreach (var method in AllMethods(cls.Parent))
methods.Add(method);
foreach (var @interface in cls.Implements)
foreach (var method in Interface.AllMethods(@interface))
methods.Add(method);
return methods;
}
}
public static class VersionExtensions
{
public static string DotlessVersion(this string version)
=> version.Replace(".", "");
}
src/Generation/Generator/Model/Namespace.cs (Modified)
namespace Generator.Model;
internal static class Namespace
{
private static readonly Dictionary<string, string> FixedNames = new();
public static void SetPublicName(GirModel.Namespace @namespace, string name)
{
lock (FixedNames)
{
FixedNames[GetCanonicalName(@namespace)] = name;
}
}
public static string GetPublicName(GirModel.Namespace @namespace)
{
return FixedNames.TryGetValue(GetCanonicalName(@namespace), out var value)
? value
: @namespace.Name.ToPascalCase().EscapeIdentifier();
}
public static string GetCanonicalName(GirModel.Namespace @namespace)
=> $"{@namespace.Name}-{@namespace.Version}";
public static string GetInternalName(GirModel.Namespace @namespace)
=> $"{GetPublicName(@namespace)}.Internal";
}
src/Generation/Generator/Renderer/Public/Constructor/Converter/Class.cs (Fix)
return cls.Fundamental
? $"new {cls.Name}({fromVariableName})"
- : $"{cls.Namespace.Name}.{cls.Name}.CreateIntern({fromVariableName}, {ownedRef.ToString().ToLower()})";
+ : $"{Model.Namespace.GetPublicName(cls.Namespace)}.{cls.Name}.CreateIntern({fromVariableName}, {ownedRef.ToString().ToLower()})";
Namespace Notify conflict with GObject.Notify.
Can you give concrete symbols / class names that do conflict? Currently I can't find a potential conflict? Afaik there is no class Notify?
Yes, normal, (without NamespaceNameConflictFixer) the generator in Notify project generate like this:
using System;
using System.Linq;
using GObject;
using System.Runtime.InteropServices;
#nullable enable
namespace Notify;
// AUTOGENERATED FILE - DO NOT MODIFY
public partial class Notification
{
public static Notification New(string summary, string? body, string? icon)
{
using var summaryNative = GLib.Internal.NonNullableUtf8StringOwnedHandle.Create(summary);
using var bodyNative = GLib.Internal.NullableUtf8StringOwnedHandle.Create(body);
using var iconNative = GLib.Internal.NullableUtf8StringOwnedHandle.Create(icon);
var notificationHandle = Internal.Notification.New(summaryNative, bodyNative, iconNative);
return Notify.Notification.CreateIntern(notificationHandle, true);
}
}
Namespace "Notify", and the GObject.Notify is a method in Object.Methods.Generated.cs L147:
public void Notify(string propertyName)
{
using var propertyNameNative = GLib.Internal.NonNullableUtf8StringOwnedHandle.Create(propertyName);
GObject.Internal.Object.Notify(this.Handle.DangerousGetHandle(), propertyNameNative);
}
And this is the problem.
According to the docs for cs0119 we should be able to fix this issue without renaming but by fully qualifying the call.
Perhaps it must be global::Notify.Notification...
You can try this manually. If it works the generator must be updated to generate the fully qualified path to the CreateIntern method.
Perhaps it must be
global::Notify.Notification...You can try this manually. If it works the generator must be updated to generate the fully qualified path to theCreateInternmethod.
This is not enough unfortunately.
First I tested "global::". But in several files
- *.Functions.Generated.cs
- *.Methods.Generated.cs
- *.Properties.Generated.cs ... generate Notify.Internal.AnythingHere like:
public Notification(params GObject.ConstructArgument[] constructArguments) : this(global::Notify.Internal.NotificationHandle.For<Notification>(constructArguments)) { }
or
global::Notify.Internal.Notification.SetAppName(base.Handle.DangerousGetHandle(), appNameNative);
For this I modified in the gir.core/src/Generation/Generator/Model/Namespace.cs file:
public static string GetInternalName(GirModel.Namespace @namespace)
=> $"global::{GetPublicName(@namespace)}.Internal";
But this, in 55 files, 110 references. This will mess up all Internal namespaces:
namespace global::GLib.Internal
Would you create a PR? Then I can take a more detailed look at it.
Please try to keep the changes at a minimum so it is easy and fast to review.
@badcel Which version should I create a PR from?
You can simply create the PR to add libnotify to gir.core. Then the error should appear, right? Afterwards I can check in detail what to do with the issue and if it is fixed we can merge the PR.
On another note: Do you plan to add librsvg to gir.core like you did for libsecret?
You can simply create the PR to add libnotify to gir.core. Then the error should appear, right? Afterwards I can check in detail what to do with the issue and if it is fixed we can merge the PR.
OK.
On another note: Do you plan to add librsvg to gir.core like you did for libsecret?
Yes, yes, yes, sorry, I'm just a little busy. I'll have time for it on Tuesday. Sorry.
Please, please no pressure and please don't feel pushed by me. I just wanted to confirm you are still interested.
I'm currently pretty occupied, too. This is still a hobby. Additionally there is still some work left before the initial 0.7.0-preview.1 release.
If the code does not make it, it will be in the next release. Perhaps I could even make a separate release for you if you miss the release of the upcoming preview. It is really no big issue for me.
Regarding the sample repository: If the new nugets are published I think I can create a sample repo in the GirCore org and give you push permission.
But like I said, really don't feel pushed. I don't want anyone to feel uncomfortable because of some open source contribution.
You can simply create the PR to add libnotify to gir.core. Then the error should appear, right? Afterwards I can check in detail what to do with the issue and if it is fixed we can merge the PR.
On another note: Do you plan to add librsvg to gir.core like you did for libsecret?
I uploaded the libnotify diff here:
https://github.com/czirok/gir.core/commit/d047c93ee2f173ea3fc19794fae11d3d68ca1076
If you have any questions or requests, just let me know.
I will add Notify-0.7.gir and try to see what I can do to fix the issue beforehand. Afterwards you can create the PR to add the nuget to GirCore.
Do you think it makes sense to add libnotify? The homepage states:
For GLib based applications the GNotification API should be used instead.
As all GirCore based apps are using GLib I think we do not really need this package at all? I just saw that the windows version of libnotify is still on version 0.7.x instead of 0.8.x which looks pretty unmaintained as version 0.8 was released 3 years ago.
This?
https://github.com/gircore/gir.core/blob/main/src/Samples/Gio-2.0/DBus/SendNotification.cs
No, this is a DBus sample on how to invoke notifications via DBus. I needed a simple sample to demonstrate DBus and choose the notification endpoint. DBus is a framework for inter process communication. You can control a lot of services with it. You "just" need to find the appropriate docs.
Please read the Notification docs. There it says to create a Notification (GirCore Notification.New) and pass this Notification on to Application.SendNotification (GirCore Application.SendNotification).
Internally this will call the DBus APIs automatically for you. If you want to experiment with this API a bit: A simple sample in the kind of the DBus one would be very welcome.