NotifyIcon

This commit is contained in:
Aigio Liu
2021-02-28 00:13:28 +08:00
parent 523641201e
commit 338ad3f228
19 changed files with 3169 additions and 56 deletions
@@ -0,0 +1,75 @@
using Eto.Drawing;
using Eto.Forms;
namespace System.Application.UI
{
/// <summary>
/// This Implements a Linux GTK3 Tray Icon
/// </summary>
internal sealed class LinuxTrayIcon<TContextMenu> : Form
{
public TrayIndicator? _tray;
readonly bool _startup = true;
/// <summary>
/// Everything has to be sent in on the constructor since things do not auto-refresh / update this is a limitation
/// </summary>
/// <param name="tooTip"></param>
/// <param name="iconPath"></param>
/// <param name="menu"></param>
public LinuxTrayIcon(string tooTip, string iconPath, TContextMenu menu)
{
MainThreadDesktop.BeginInvokeOnMainThread(() =>
{
var ctxMnu = new ContextMenu();
var f = DI.Get<INotifyIcon<TContextMenu>.IUIFrameworkHelper>();
f.ForEachMenuItems(menu, item =>
{
ButtonMenuItem bmi = new ButtonMenuItem
{
Text = item.header,
Command = new Command((s, e) =>
{
MainThreadDesktop.BeginInvokeOnMainThread(() =>
{
item.activated();
});
})
};
ctxMnu.Items.Add(bmi);
});
ClientSize = new Size(200, 200);
var image = new Icon(f.OpenAsset(new Uri(iconPath)));
_tray = new TrayIndicator
{
//Image = Icon.FromResource(iconPath.Replace("resm:", "")),
Image = image,
Menu = ctxMnu,
Title = tooTip
};
_tray.Show();
_tray.Visible = true;
});
}
protected override void OnShown(EventArgs e)
{
if (_startup)
{
Visible = false;
}
}
protected override void OnUnLoad(EventArgs e)
{
base.OnUnLoad(e);
_tray?.Hide();
}
}
}
@@ -0,0 +1,105 @@
using System.Threading;
using System.Threading.Tasks;
using EtoFormsApplication = Eto.Forms.Application;
using EtoPlatform = Eto.Platform;
namespace System.Application.UI
{
public class NotifyIcon<TContextMenu> : INotifyIcon<TContextMenu>
{
public event EventHandler<EventArgs>? Click;
public event EventHandler<EventArgs>? DoubleClick;
public event EventHandler<EventArgs>? RightClick;
LinuxTrayIcon<TContextMenu>? lti;
internal LinuxTrayIcon<TContextMenu>? LtiProp
{
get => lti;
set => lti = value;
}
public Task? TrayIconTask { get; private set; }
CancellationTokenSource? canTok;
/// <summary>
/// Gets or sets the icon for the notify icon. Either a file system path
/// or a <c>resm:</c> manifest resource path can be specified.
/// </summary>
string _iconPath = "";
public string IconPath
{
get => _iconPath;
set
{
_iconPath = value;
UpdateMenu();
}
}
string _toolTip = "";
/// <summary>
/// Gets or sets the tooltip text for the notify icon.
/// </summary>
public string ToolTipText
{
get => _toolTip;
set
{
_toolTip = value;
UpdateMenu();
}
}
TContextMenu? _menu;
/// <summary>
/// Gets or sets the context menu for the notify icon.
/// </summary>
public TContextMenu? ContextMenu
{
get => _menu; set
{
_menu = value;
UpdateMenu();
}
}
/// <summary>
/// Gets or sets if the notify icon is visible in the
/// taskbar notification area or not.
/// </summary>
public bool Visible { get; set; }
public void Remove()
{
MainThreadDesktop.BeginInvokeOnMainThread(() =>
{
lti?._tray?.Hide();
canTok?.Cancel();
});
}
void UpdateMenu()
{
if (!string.IsNullOrEmpty(IconPath) && !string.IsNullOrEmpty(ToolTipText) && ContextMenu != null)
{
canTok = new CancellationTokenSource();
MainThreadDesktop.BeginInvokeOnMainThread(() =>
{
// Because of the way that Linux works this needs to run on its own Thread.
TrayIconTask = Task.Factory.StartNew(() =>
{
new EtoFormsApplication(EtoPlatform.Detect)
.Run(LtiProp =
new LinuxTrayIcon<TContextMenu>(ToolTipText, IconPath, ContextMenu));
}
, canTok.Token, TaskCreationOptions.AttachedToParent, TaskScheduler.Default);
}, MainThreadDesktop.DispatcherPriority.MaxValue);
}
}
}
}
@@ -11,6 +11,10 @@
</Compile>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Eto.Forms" Version="2.5.10" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\System.Application.SteamTools.Client.Desktop\System.Application.SteamTools.Client.Desktop.csproj" />
</ItemGroup>