Browse Source

some progress....

pull/6610/head
Jumar Macato 5 years ago
parent
commit
b216b1afbe
  1. 358
      src/Avalonia.FreeDesktop/DBusSystemTray/SNIDBus.cs
  2. 2
      src/Avalonia.X11/X11Platform.cs
  3. 11
      src/Avalonia.X11/X11TrayIconImpl.cs

358
src/Avalonia.FreeDesktop/DBusSystemTray/SNIDBus.cs

@ -1,55 +1,229 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reactive.Disposables;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Tmds.DBus;
[assembly: InternalsVisibleTo(Tmds.DBus.Connection.DynamicAssemblyName)]
namespace Avalonia.FreeDesktop.DBusSystemTray
{
public class SNIDBus
{
public SNIDBus()
{
}
public async void Initialize()
private static int trayinstanceID = 0;
private static int GetTID()
{
trayinstanceID = (int)new Random().Next(0, 100);
return trayinstanceID;
}
public async void Initialize()
{
var x = Process.GetCurrentProcess().Id;
var y = GetTID();
var serviceName = $"AvaloniaSNITest_{Guid.NewGuid()}";
var sysTraySrvName = $"org.kde.StatusNotifierItem-{x}-{y}";
var tx = new StatusNotifierItem();
var path =
Connection.Session.CreateProxy<IStatusNotifierWatcher>("org.kde.StatusNotifierWatcher",
await DBusHelper.Connection.RegisterObjectAsync(tx);
await DBusHelper.Connection.RegisterServiceAsync(sysTraySrvName, () =>
{
});
while (!await DBusHelper.Connection.IsServiceActiveAsync(sysTraySrvName))
{
await Task.Delay(1000);
}
var yx = DBusHelper.Connection.CreateProxy<IStatusNotifierItem>(sysTraySrvName, tx.ObjectPath);
var snw =
DBusHelper.Connection.CreateProxy<IStatusNotifierWatcher>("org.kde.StatusNotifierWatcher",
"/StatusNotifierWatcher");
await path.RegisterStatusNotifierHostAsync(serviceName);
await path.WatchPropertiesAsync(x =>
{
while (!await DBusHelper.Connection.IsServiceActiveAsync("org.kde.StatusNotifierWatcher"))
{
await Task.Delay(1000);
}
await snw.RegisterStatusNotifierItemAsync(sysTraySrvName);
tx.Ready();
await yx.ActivateAsync(1, 1);
}
}
internal class StatusNotifierItem : IStatusNotifierItem
{
private event Action<PropertyChanges> OnPropertyChange;
public event Action OnTitleChanged;
public event Action OnIconChanged;
public event Action OnAttentionIconChanged;
public event Action OnOverlayIconChanged;
});
await path.WatchStatusNotifierHostRegisteredAsync(() =>
{
public Action NewToolTipAsync;
public ObjectPath ObjectPath { get; }
}, z =>
{
readonly StatusNotifierItemProperties props;
public StatusNotifierItem()
{
var ID = Guid.NewGuid().ToString().Replace("-", "");
ObjectPath = new ObjectPath($"/StatusNotifierItem");
props = new StatusNotifierItemProperties();
props.Title = "Avalonia Test Tray";
props.Id = ID;
//
//
// public string Category { get; set; } = default;
//
// public string Id { get; set; } = default;
//
// public string Title { get; set; } = default;
//
// public string Status { get; set; } = default;
//
// public int WindowId { get; set; } = default;
}
});
// static class StatusNotifierItemExtensions
// {
// public static Task<string> GetCategoryAsync(this IStatusNotifierItem o) => o.GetAsync<string>("Category");
// public static Task<string> GetIdAsync(this IStatusNotifierItem o) => o.GetAsync<string>("Id");
// public static Task<string> GetTitleAsync(this IStatusNotifierItem o) => o.GetAsync<string>("Title");
// public static Task<string> GetStatusAsync(this IStatusNotifierItem o) => o.GetAsync<string>("Status");
// public static Task<int> GetWindowIdAsync(this IStatusNotifierItem o) => o.GetAsync<int>("WindowId");
//
// public static Task<string> GetIconThemePathAsync(this IStatusNotifierItem o) =>
// o.GetAsync<string>("IconThemePath");
//
// public static Task<ObjectPath> GetMenuAsync(this IStatusNotifierItem o) => o.GetAsync<ObjectPath>("Menu");
// public static Task<bool> GetItemIsMenuAsync(this IStatusNotifierItem o) => o.GetAsync<bool>("ItemIsMenu");
// public static Task<string> GetIconNameAsync(this IStatusNotifierItem o) => o.GetAsync<string>("IconName");
//
// public static Task<(int, int, byte[])[]> GetIconPixmapAsync(this IStatusNotifierItem o) =>
// o.GetAsync<(int, int, byte[])[]>("IconPixmap");
//
// public static Task<string> GetOverlayIconNameAsync(this IStatusNotifierItem o) =>
// o.GetAsync<string>("OverlayIconName");
//
// public static Task<(int, int, byte[])[]> GetOverlayIconPixmapAsync(this IStatusNotifierItem o) =>
// o.GetAsync<(int, int, byte[])[]>("OverlayIconPixmap");
//
// public static Task<string> GetAttentionIconNameAsync(this IStatusNotifierItem o) =>
// o.GetAsync<string>("AttentionIconName");
//
// public static Task<(int, int, byte[])[]> GetAttentionIconPixmapAsync(this IStatusNotifierItem o) =>
// o.GetAsync<(int, int, byte[])[]>("AttentionIconPixmap");
//
// public static Task<string> GetAttentionMovieNameAsync(this IStatusNotifierItem o) =>
// o.GetAsync<string>("AttentionMovieName");
//
// public static Task<(string, (int, int, byte[])[], string, string)>
// GetToolTipAsync(this IStatusNotifierItem o) =>
// o.GetAsync<(string, (int, int, byte[])[], string, string)>("ToolTip");
// }
public async Task ContextMenuAsync(int X, int Y)
{
}
public async Task ActivateAsync(int X, int Y)
{
// OnPropertyChange?.Invoke(new PropertyChanges());
}
public async Task SecondaryActivateAsync(int X, int Y)
{
throw new NotImplementedException();
}
public async Task ScrollAsync(int Delta, string Orientation)
{
}
public async Task<IDisposable> WatchNewTitleAsync(Action handler, Action<Exception> onError = null)
{
OnTitleChanged += handler;
return Disposable.Create(() => OnTitleChanged -= handler);
}
public async Task<IDisposable> WatchNewIconAsync(Action handler, Action<Exception> onError = null)
{
OnIconChanged += handler;
return Disposable.Create(() => OnIconChanged -= handler);
}
public async Task<IDisposable> WatchNewAttentionIconAsync(Action handler, Action<Exception> onError = null)
{
OnAttentionIconChanged += handler;
return Disposable.Create(() => OnAttentionIconChanged -= handler);
}
public async Task<IDisposable> WatchNewOverlayIconAsync(Action handler, Action<Exception> onError = null)
{
OnOverlayIconChanged += handler;
return Disposable.Create(() => OnOverlayIconChanged -= handler);
}
public async Task<IDisposable> WatchNewToolTipAsync(Action handler, Action<Exception> onError = null)
{
NewToolTipAsync += handler;
return Disposable.Create(() => NewToolTipAsync -= handler);
}
public async Task<IDisposable> WatchNewStatusAsync(Action<string> handler, Action<Exception> onError = null)
{
NewStatusAsync += handler;
return Disposable.Create(() => NewStatusAsync -= handler);
}
public Action<string> NewStatusAsync { get; set; }
public async Task<StatusNotifierItemProperties> GetAllAsync()
{
return props;
}
public async Task<IDisposable> WatchPropertiesAsync(Action<PropertyChanges> handler)
{
OnPropertyChange += handler;
return Disposable.Create(() => OnPropertyChange -= handler);
}
public void Ready()
{
OnTitleChanged?.Invoke();
}
}
[DBusInterface("org.kde.StatusNotifierWatcher")]
interface IStatusNotifierWatcher : IDBusObject
{
Task RegisterStatusNotifierItemAsync(string Service);
Task RegisterStatusNotifierHostAsync(string Service);
Task<IDisposable> WatchStatusNotifierItemRegisteredAsync(Action<string> handler, Action<Exception> onError = null);
Task<IDisposable> WatchStatusNotifierItemUnregisteredAsync(Action<string> handler, Action<Exception> onError = null);
Task<IDisposable> WatchStatusNotifierItemRegisteredAsync(Action<string> handler,
Action<Exception> onError = null);
Task<IDisposable> WatchStatusNotifierItemUnregisteredAsync(Action<string> handler,
Action<Exception> onError = null);
Task<IDisposable> WatchStatusNotifierHostRegisteredAsync(Action handler, Action<Exception> onError = null);
Task<T> GetAsync<T>(string prop);
Task<StatusNotifierWatcherProperties> GetAllAsync();
@ -60,54 +234,23 @@ namespace Avalonia.FreeDesktop.DBusSystemTray
[Dictionary]
class StatusNotifierWatcherProperties
{
private string[] _RegisteredStatusNotifierItems = default(string[]);
public string[] RegisteredStatusNotifierItems
{
get
{
return _RegisteredStatusNotifierItems;
}
public string[] RegisteredStatusNotifierItems { get; set; } = default;
set
{
_RegisteredStatusNotifierItems = (value);
}
}
private bool _IsStatusNotifierHostRegistered = default(bool);
public bool IsStatusNotifierHostRegistered
{
get
{
return _IsStatusNotifierHostRegistered;
}
public bool IsStatusNotifierHostRegistered { get; set; } = default;
set
{
_IsStatusNotifierHostRegistered = (value);
}
}
private int _ProtocolVersion = default(int);
public int ProtocolVersion
{
get
{
return _ProtocolVersion;
}
set
{
_ProtocolVersion = (value);
}
}
public int ProtocolVersion { get; set; } = default;
}
static class StatusNotifierWatcherExtensions
{
public static Task<string[]> GetRegisteredStatusNotifierItemsAsync(this IStatusNotifierWatcher o) => o.GetAsync<string[]>("RegisteredStatusNotifierItems");
public static Task<bool> GetIsStatusNotifierHostRegisteredAsync(this IStatusNotifierWatcher o) => o.GetAsync<bool>("IsStatusNotifierHostRegistered");
public static Task<int> GetProtocolVersionAsync(this IStatusNotifierWatcher o) => o.GetAsync<int>("ProtocolVersion");
public static Task<string[]> GetRegisteredStatusNotifierItemsAsync(this IStatusNotifierWatcher o) =>
o.GetAsync<string[]>("RegisteredStatusNotifierItems");
public static Task<bool> GetIsStatusNotifierHostRegisteredAsync(this IStatusNotifierWatcher o) =>
o.GetAsync<bool>("IsStatusNotifierHostRegistered");
public static Task<int> GetProtocolVersionAsync(this IStatusNotifierWatcher o) =>
o.GetAsync<int>("ProtocolVersion");
}
[DBusInterface("org.gtk.Actions")]
@ -118,7 +261,11 @@ namespace Avalonia.FreeDesktop.DBusSystemTray
Task<IDictionary<string, (bool, Signature, object[])>> DescribeAllAsync();
Task ActivateAsync(string ActionName, object[] Parameter, IDictionary<string, object> PlatformData);
Task SetStateAsync(string ActionName, object Value, IDictionary<string, object> PlatformData);
Task<IDisposable> WatchChangedAsync(Action<(string[] removals, IDictionary<string, bool> enableChanges, IDictionary<string, object> stateChanges, IDictionary<string, (bool, Signature, object[])> additions)> handler, Action<Exception> onError = null);
Task<IDisposable> WatchChangedAsync(
Action<(string[] removals, IDictionary<string, bool> enableChanges, IDictionary<string, object> stateChanges
, IDictionary<string, (bool, Signature, object[])> additions)> handler,
Action<Exception> onError = null);
}
[DBusInterface("org.gtk.Application")]
@ -136,19 +283,7 @@ namespace Avalonia.FreeDesktop.DBusSystemTray
[Dictionary]
class ApplicationProperties
{
private bool _Busy = default(bool);
public bool Busy
{
get
{
return _Busy;
}
set
{
_Busy = (value);
}
}
public bool Busy { get; set; } = default;
}
static class ApplicationExtensions
@ -178,23 +313,66 @@ namespace Avalonia.FreeDesktop.DBusSystemTray
[Dictionary]
class ProfilerProperties
{
private IDictionary<string, object> _Capabilities = default(IDictionary<string, object>);
public IDictionary<string, object> Capabilities
{
get
{
return _Capabilities;
}
set
{
_Capabilities = (value);
}
}
public IDictionary<string, object> Capabilities { get; set; } = default;
}
static class ProfilerExtensions
{
public static Task<IDictionary<string, object>> GetCapabilitiesAsync(this IProfiler o) => o.GetAsync<IDictionary<string, object>>("Capabilities");
public static Task<IDictionary<string, object>> GetCapabilitiesAsync(this IProfiler o) =>
o.GetAsync<IDictionary<string, object>>("Capabilities");
}
[DBusInterface("org.kde.StatusNotifierItem")]
interface IStatusNotifierItem : IDBusObject
{
Task ContextMenuAsync(int X, int Y);
Task ActivateAsync(int X, int Y);
Task SecondaryActivateAsync(int X, int Y);
Task ScrollAsync(int Delta, string Orientation);
Task<IDisposable> WatchNewTitleAsync(Action handler, Action<Exception> onError = null);
Task<IDisposable> WatchNewIconAsync(Action handler, Action<Exception> onError = null);
Task<IDisposable> WatchNewAttentionIconAsync(Action handler, Action<Exception> onError = null);
Task<IDisposable> WatchNewOverlayIconAsync(Action handler, Action<Exception> onError = null);
Task<IDisposable> WatchNewToolTipAsync(Action handler, Action<Exception> onError = null);
Task<IDisposable> WatchNewStatusAsync(Action<string> handler, Action<Exception> onError = null);
Task<StatusNotifierItemProperties> GetAllAsync();
Task<IDisposable> WatchPropertiesAsync(Action<PropertyChanges> handler);
}
[Dictionary]
class StatusNotifierItemProperties
{
public string Category { get; set; } = default;
public string Id { get; set; } = default;
public string Title { get; set; } = default;
public string Status { get; set; } = default;
public int WindowId { get; set; } = default;
public string IconThemePath { get; set; } = default;
public ObjectPath Menu { get; set; } = default;
public bool ItemIsMenu { get; set; } = default;
public string IconName { get; set; } = default;
public (int, int, byte[])[] IconPixmap { get; set; } = default;
public string OverlayIconName { get; set; } = default;
public (int, int, byte[])[] OverlayIconPixmap { get; set; } = default;
public string AttentionIconName { get; set; } = default;
public (int, int, byte[])[] AttentionIconPixmap { get; set; } = default;
public string AttentionMovieName { get; set; } = default;
public (string, (int, int, byte[])[], string, string) ToolTip { get; set; } = default;
}
}

2
src/Avalonia.X11/X11Platform.cs

@ -103,7 +103,7 @@ namespace Avalonia.X11
public ITrayIconImpl CreateTrayIcon ()
{
return new X11TrayIconImpl();
return new X11TrayIconImpl(this);
}
public IWindowImpl CreateWindow()

11
src/Avalonia.X11/X11TrayIconImpl.cs

@ -1,4 +1,5 @@
using System;
using System.Linq;
using Avalonia.Controls.Platform;
using Avalonia.FreeDesktop.DBusSystemTray;
using Avalonia.Platform;
@ -7,11 +8,17 @@ namespace Avalonia.X11
{
class X11TrayIconImpl : ITrayIconImpl
{
private readonly AvaloniaX11Platform _avaloniaX11Platform;
public INativeMenuExporter MenuExporter => null;
public Action OnClicked { get; set; }
private SNIDBus sni = new SNIDBus();
public X11TrayIconImpl(AvaloniaX11Platform avaloniaX11Platform)
{
_avaloniaX11Platform = avaloniaX11Platform;
}
public void Dispose()
{
@ -30,7 +37,7 @@ namespace Avalonia.X11
public void SetToolTipText(string text)
{
sni.Initialize();
sni.Initialize();
}
}
}

Loading…
Cancel
Save