9 changed files with 199 additions and 2 deletions
@ -0,0 +1,30 @@ |
|||
//
|
|||
// trayicon.h
|
|||
// Avalonia.Native.OSX
|
|||
//
|
|||
// Created by Dan Walmsley on 09/09/2021.
|
|||
// Copyright © 2021 Avalonia. All rights reserved.
|
|||
//
|
|||
|
|||
#ifndef trayicon_h |
|||
#define trayicon_h |
|||
|
|||
#include "common.h" |
|||
|
|||
class AvnTrayIcon : public ComSingleObject<IAvnTrayIcon, &IID_IAvnTrayIcon> |
|||
{ |
|||
private: |
|||
NSStatusItem* _native; |
|||
ComPtr<IAvnTrayIconEvents> _events; |
|||
|
|||
public: |
|||
FORWARD_IUNKNOWN() |
|||
|
|||
AvnTrayIcon(IAvnTrayIconEvents* events); |
|||
|
|||
virtual HRESULT SetIcon (void* data, size_t length) override; |
|||
|
|||
virtual HRESULT SetMenu (IAvnMenu* menu) override; |
|||
}; |
|||
|
|||
#endif /* trayicon_h */ |
|||
@ -0,0 +1,59 @@ |
|||
#include "common.h" |
|||
#include "trayicon.h" |
|||
|
|||
extern IAvnTrayIcon* CreateTrayIcon(IAvnTrayIconEvents* cb) |
|||
{ |
|||
@autoreleasepool |
|||
{ |
|||
return new AvnTrayIcon(cb); |
|||
} |
|||
} |
|||
|
|||
AvnTrayIcon::AvnTrayIcon(IAvnTrayIconEvents* events) |
|||
{ |
|||
_events = events; |
|||
|
|||
_native = [[NSStatusBar systemStatusBar] statusItemWithLength: NSSquareStatusItemLength]; |
|||
} |
|||
|
|||
HRESULT AvnTrayIcon::SetIcon (void* data, size_t length) |
|||
{ |
|||
START_COM_CALL; |
|||
|
|||
@autoreleasepool |
|||
{ |
|||
if(data != nullptr) |
|||
{ |
|||
NSData *imageData = [NSData dataWithBytes:data length:length]; |
|||
NSImage *image = [[NSImage alloc] initWithData:imageData]; |
|||
|
|||
NSSize originalSize = [image size]; |
|||
|
|||
NSSize size; |
|||
size.height = [[NSFont menuFontOfSize:0] pointSize] * 1.333333; |
|||
|
|||
auto scaleFactor = size.height / originalSize.height; |
|||
size.width = originalSize.width * scaleFactor; |
|||
|
|||
[image setSize: size]; |
|||
[_native setImage:image]; |
|||
} |
|||
else |
|||
{ |
|||
[_native setImage:nullptr]; |
|||
} |
|||
return S_OK; |
|||
} |
|||
} |
|||
|
|||
HRESULT AvnTrayIcon::SetMenu (IAvnMenu* menu) |
|||
{ |
|||
START_COM_CALL; |
|||
|
|||
@autoreleasepool |
|||
{ |
|||
|
|||
} |
|||
|
|||
return S_OK; |
|||
} |
|||
@ -0,0 +1,75 @@ |
|||
using System; |
|||
using System.IO; |
|||
using Avalonia.Controls.Platform; |
|||
using Avalonia.Native.Interop; |
|||
using Avalonia.Platform; |
|||
|
|||
namespace Avalonia.Native |
|||
{ |
|||
class TrayIconEvents : CallbackBase, IAvnTrayIconEvents |
|||
{ |
|||
private TrayIconImpl _parent; |
|||
|
|||
public TrayIconEvents (TrayIconImpl parent) |
|||
{ |
|||
_parent = parent; |
|||
} |
|||
|
|||
public void Clicked() |
|||
{ |
|||
} |
|||
|
|||
public void DoubleClicked() |
|||
{ |
|||
} |
|||
} |
|||
|
|||
internal class TrayIconImpl : ITrayIconImpl |
|||
{ |
|||
private readonly IAvnTrayIcon _native; |
|||
|
|||
public TrayIconImpl(IAvaloniaNativeFactory factory) |
|||
{ |
|||
_native = factory.CreateTrayIcon(new TrayIconEvents(this)); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public unsafe void SetIcon(IWindowIconImpl? icon) |
|||
{ |
|||
if(icon is null) |
|||
{ |
|||
_native.SetIcon(null, IntPtr.Zero); |
|||
} |
|||
else |
|||
{ |
|||
using (var ms = new MemoryStream()) |
|||
{ |
|||
icon.Save(ms); |
|||
|
|||
var imageData = ms.ToArray(); |
|||
|
|||
fixed(void* ptr = imageData) |
|||
{ |
|||
_native.SetIcon(ptr, new IntPtr(imageData.Length)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
public void SetToolTipText(string? text) |
|||
{ |
|||
// NOP
|
|||
} |
|||
|
|||
public void SetIsVisible(bool visible) |
|||
{ |
|||
|
|||
} |
|||
|
|||
public INativeMenuExporter? MenuExporter { get; } |
|||
} |
|||
} |
|||
Loading…
Reference in new issue