Browse Source

support trayicon clicked on osx.

pull/6610/head
Dan Walmsley 4 years ago
parent
commit
abf4242280
  1. 8
      src/Avalonia.Controls/Platform/ITrayIconImpl.cs
  2. 60
      src/Avalonia.Controls/TrayIcon.cs
  3. 4
      src/Avalonia.DesignerSupport/Remote/TrayIconStub.cs
  4. 6
      src/Avalonia.Native/TrayIconImpl.cs
  5. 36
      src/Windows/Avalonia.Win32/TrayIconImpl.cs

8
src/Avalonia.Controls/Platform/ITrayIconImpl.cs

@ -23,6 +23,14 @@ namespace Avalonia.Platform
/// </summary> /// </summary>
void SetIsVisible (bool visible); void SetIsVisible (bool visible);
/// <summary>
/// Gets the MenuExporter to allow native menus to be exported to the TrayIcon.
/// </summary>
INativeMenuExporter? MenuExporter { get; } INativeMenuExporter? MenuExporter { get; }
/// <summary>
/// Gets or Sets the Action that is called when the TrayIcon is clicked.
/// </summary>
Action? OnClicked { get; set; }
} }
} }

60
src/Avalonia.Controls/TrayIcon.cs

@ -22,6 +22,15 @@ namespace Avalonia.Controls
_impl = impl; _impl = impl;
_impl.SetIsVisible(IsVisible); _impl.SetIsVisible(IsVisible);
_impl.OnClicked = () => Clicked?.Invoke(this, EventArgs.Empty);
Clicked += TrayIcon_Clicked;
}
private void TrayIcon_Clicked(object sender, EventArgs e)
{
} }
public TrayIcon () : this(PlatformManager.CreateTrayIcon()) public TrayIcon () : this(PlatformManager.CreateTrayIcon())
@ -52,28 +61,12 @@ namespace Avalonia.Controls
} }
} }
private static void Lifetime_Exit(object sender, ControlledApplicationLifetimeExitEventArgs e) /// <summary>
{ /// Raised when the TrayIcon is clicked.
var trayIcons = GetTrayIcons(Application.Current); /// Note, this is only supported on Win32.
/// Linux and OSX this event is not raised.
foreach(var icon in trayIcons) /// </summary>
{ public event EventHandler? Clicked;
icon.Dispose();
}
}
private static void Icons_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
}
private static void RemoveIcons (IEnumerable<TrayIcon> icons)
{
foreach(var icon in icons)
{
icon.Dispose();
}
}
/// <summary> /// <summary>
/// Defines the <see cref="TrayIcons"/> attached property. /// Defines the <see cref="TrayIcons"/> attached property.
@ -132,6 +125,29 @@ namespace Avalonia.Controls
public INativeMenuExporter? NativeMenuExporter => _impl.MenuExporter; public INativeMenuExporter? NativeMenuExporter => _impl.MenuExporter;
private static void Lifetime_Exit(object sender, ControlledApplicationLifetimeExitEventArgs e)
{
var trayIcons = GetTrayIcons(Application.Current);
foreach (var icon in trayIcons)
{
icon.Dispose();
}
}
private static void Icons_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
}
private static void RemoveIcons(IEnumerable<TrayIcon> icons)
{
foreach (var icon in icons)
{
icon.Dispose();
}
}
protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change) protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change)
{ {
base.OnPropertyChanged(change); base.OnPropertyChanged(change);

4
src/Avalonia.DesignerSupport/Remote/TrayIconStub.cs

@ -11,7 +11,9 @@ namespace Avalonia.DesignerSupport.Remote
public Action DoubleClicked { get; set; } public Action DoubleClicked { get; set; }
public Action RightClicked { get; set; } public Action RightClicked { get; set; }
public INativeMenuExporter MenuExporter => throw new NotImplementedException(); public INativeMenuExporter MenuExporter => null;
public Action OnClicked { get; set; }
public void Dispose() public void Dispose()
{ {

6
src/Avalonia.Native/TrayIconImpl.cs

@ -4,6 +4,8 @@ using Avalonia.Controls.Platform;
using Avalonia.Native.Interop; using Avalonia.Native.Interop;
using Avalonia.Platform; using Avalonia.Platform;
#nullable enable
namespace Avalonia.Native namespace Avalonia.Native
{ {
class TrayIconEvents : CallbackBase, IAvnTrayIconEvents class TrayIconEvents : CallbackBase, IAvnTrayIconEvents
@ -34,7 +36,9 @@ namespace Avalonia.Native
MenuExporter = new AvaloniaNativeMenuExporter(_native, factory); MenuExporter = new AvaloniaNativeMenuExporter(_native, factory);
} }
public Action? OnClicked { get; set; }
public void Dispose() public void Dispose()
{ {

36
src/Windows/Avalonia.Win32/TrayIconImpl.cs

@ -23,10 +23,20 @@ namespace Avalonia.Win32
private IconImpl? _icon; private IconImpl? _icon;
private string? _tooltipText; private string? _tooltipText;
private readonly Win32NativeToManagedMenuExporter _exporter; private readonly Win32NativeToManagedMenuExporter _exporter;
private static Dictionary<int, TrayIconImpl> s_trayIcons = new Dictionary<int, TrayIconImpl>(); private static Dictionary<int, TrayIconImpl> s_trayIcons = new Dictionary<int, TrayIconImpl>();
private bool _disposedValue; private bool _disposedValue;
public TrayIconImpl()
{
_exporter = new Win32NativeToManagedMenuExporter();
_uniqueId = ++_nextUniqueId;
s_trayIcons.Add(_uniqueId, this);
}
public Action? OnClicked { get; set; }
public INativeMenuExporter MenuExporter => _exporter; public INativeMenuExporter MenuExporter => _exporter;
internal static void ProcWnd(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) internal static void ProcWnd(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
@ -37,15 +47,6 @@ namespace Avalonia.Win32
} }
} }
public TrayIconImpl()
{
_exporter = new Win32NativeToManagedMenuExporter();
_uniqueId = ++_nextUniqueId;
s_trayIcons.Add(_uniqueId, this);
}
public void SetIcon(IWindowIconImpl? icon) public void SetIcon(IWindowIconImpl? icon)
{ {
_icon = icon as IconImpl; _icon = icon as IconImpl;
@ -63,7 +64,6 @@ namespace Avalonia.Win32
UpdateIcon(!_iconAdded); UpdateIcon(!_iconAdded);
} }
private void UpdateIcon(bool remove = false) private void UpdateIcon(bool remove = false)
{ {
var iconData = new NOTIFYICONDATA() var iconData = new NOTIFYICONDATA()
@ -105,9 +105,7 @@ namespace Avalonia.Win32
switch (lParam.ToInt32()) switch (lParam.ToInt32())
{ {
case (int)WindowsMessage.WM_LBUTTONUP: case (int)WindowsMessage.WM_LBUTTONUP:
break; OnClicked?.Invoke();
case (int)WindowsMessage.WM_LBUTTONDBLCLK:
break; break;
case (int)WindowsMessage.WM_RBUTTONUP: case (int)WindowsMessage.WM_RBUTTONUP:
@ -264,11 +262,11 @@ namespace Avalonia.Win32
} }
} }
~TrayIconImpl() ~TrayIconImpl()
{ {
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: false); Dispose(disposing: false);
} }
public void Dispose() public void Dispose()
{ {

Loading…
Cancel
Save