Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tray & Menu bar icon? #2649

Closed
manijak opened this issue Jun 12, 2019 · 38 comments
Closed

Tray & Menu bar icon? #2649

manijak opened this issue Jun 12, 2019 · 38 comments

Comments

@manijak
Copy link

manijak commented Jun 12, 2019

Hi,
Does Avalonia currently support System Tray Icon (Windows) and Menu Bar Icon (MacOS)? In order to minimize and hide the main app window, but still run in the background?

@kekekeks
Copy link
Member

kekekeks commented Jun 12, 2019

Currently blocked by #898 #2582
The same "menu export" infrastructure is needed for tray menus for OSX and Linux

@dichaos
Copy link

dichaos commented Jan 23, 2020

is this still blocked ?

@kekekeks
Copy link
Member

Planned to be available this year.

@616E64726173
Copy link

Is it possible to do this for OS X using MonoMac.Standard or will there be some conflict with Avalonia's codebase?

@kekekeks
Copy link
Member

Using MonoMac for tray icons should work.

@ffgiraldez
Copy link

Any ETA or news about it? I was thinking about create an app that needs system tray support, actually I tried Xamarin.Forms and work well with it, but the poor support of multiple windows make me search other libs and check Avalonia, I just want a way to hook code into the NSAppDelegate and WPF Application in order to support NSStatusItem and NotifyIcon

@t00
Copy link

t00 commented Apr 26, 2020

Lack of System Tray support is indeed a problem - one of the basic Windows persistent application enhancements is not possible. Is there a way to add tray icon using native dll bindings which was already done anywhere else, so that it can be included with conditional compilation flags for Windows build?

@MonkAlex
Copy link
Contributor

Just for windows u can use this code:
https://github.com/MonkAlex/MangaReader/tree/master/MangaReader.Avalonia/Platform/Win
its copied from hardcodet.net, WPF removed
context menu not supported

@t00
Copy link

t00 commented Apr 26, 2020

Brillant, many thanks!

@josegomez
Copy link

We were able to implement this on all 3 platforms (Win, Nix and OSX) but we had to use native bindings and dependencies....
The biggest issue is Linux which works as long as people use "the right" window manager and "the right" notification deamon... its a damn nightmare.
If anyone is interested here's an Implementation for Linux on Avalonia using Eto
https://github.com/sqrldev/SQRLDotNetClient/blob/master/SQRLDotNetClientUI/Platform/Linux/NotifyIcon.cs
One for OSX Using MonoMac
https://github.com/sqrldev/SQRLDotNetClient/blob/master/SQRLDotNetClientUI/Platform/OSX/NotifyIcon.cs

And Windows using Native windows Interop
https://github.com/sqrldev/SQRLDotNetClient/blob/master/SQRLDotNetClientUI/Platform/Win/NotifyIcon.cs

All using a common interface
https://github.com/sqrldev/SQRLDotNetClient/blob/925abc8200be52c5969632eac05368b5b94bb34e/SQRLDotNetClientUI/Models/INotifyIcon.cs

To call it from Avalonia
https://github.com/sqrldev/SQRLDotNetClient/blob/b2463a079559d7a56d73821697c412d2eb4f2b93/SQRLDotNetClientUI/App.xaml.cs#L87-L124

@danwalmsley
Copy link
Member

we could look at https://github.com/hardcodet/wpf-notifyicon for ideas on api design.

@MikeAndrews90
Copy link

@josegomez Many thanks, this is working great.

@josegomez
Copy link

NP @MikeAndrews90 glad it works for you, we've been using it for a while now works great, linux is still kinda ify depending on whether they are running GNOME or KDE, or Random other thing... but it mostly works.
That's always the issue with Linux there are 400 ways of doing the same thing and none of them are "standard"

@seanocali
Copy link

@josegomez Thanks for providing this! I tested it just on Windows and it worked fine except the icon would pop back up in the system tray after quitting the program. I fixed this by manually calling NotifyIcon.Remove() on the Desktop_Exit event. I see there's a deconstructor that does the same thing but for whatever reason it's not firing.

I would totally use this but unfortunately it's GPL. Anyone know if the Avolonia team still working on their own solution?

@josegomez
Copy link

josegomez commented May 21, 2020

GPL license? 🤔 can I ask why that matters in your case just curious @seanocali

@seanocali
Copy link

seanocali commented May 21, 2020

GPL license? 🤔 can I ask why that matters in your case just curious @seanocali

Because any software I use it in would legally also have to be GPL.

@danwalmsley
Copy link
Member

@seanocali we are planning to support this, after 0.10 release

@MaxXor
Copy link

MaxXor commented May 31, 2020

@danwalmsley I'm very excited for this feature! It's the only thing hindering me from porting my application to Avalonia.

@FG-rgb
Copy link

FG-rgb commented Oct 15, 2020

@danwalmsley I'm very excited for this feature! It's the only thing hindering me from porting my application to Avalonia.

Same here. This is mandatory for me.

@danwalmsley
Copy link
Member

Its definately coming... if someone wants to make a PR it could come sooner... and there is nothing to stop users doing this today by calling the native apis themselves.

It shouldnt be a huge amount to work I dont think to add this.

@FG-rgb
Copy link

FG-rgb commented Oct 16, 2020

Ok. Sorry, you guys are doing a splendid job ;)

@JesseRedfield
Copy link

JesseRedfield commented May 17, 2021

I happened to find this clean implemented MIT licensed native wrapper for osx and windows notification tray icons ;-).

I have been meaning to make it a nuget, it can certainly be ripped apart and implemented here. I didn't have the time honestly to do a linux portion. The C++ Is all CMake with build wrappers, visual studio 2019 for windows builds, standard OSX command line tools and xcode are all that's needed for OSX Builds, and of course latest CMAKE. The binaries are prebuilts right now.

If you need it for a project feel free to take it, fork it, build it, run it, rip it to pieces and re-write it, w/e. If someone is so inclined integrate it into Avalonia.

I needed the tray icons for work, and got as far as something easy to include them, and had to move on from there. Planning a wedding I don't have much free time for free work ;-)

https://github.com/darkfrostystorm/NotificationTrayIconSharp

edit: A linux implementation is missing as I did not need it, but GTK was starting to be added to the cmake etc. GTK seems like the best way to add this feature, there are examples out there. Seems like almost every DE on linux handles GTK tray icons the same, KDE and Gnome were working in examples I found using GTK. I think GTK is used in python to similar ends as well.

At some point this will be my project to get into CI and Nuget feeds, my company is moving a bunch of code from our internal devops to github, and i'll eventually learn how to do that ;-) although the build is not super complicated anyways.

@Mykhailo-Seniutovych
Copy link

So what is the current status of this issue? Any ideas when this feature will be ready?

@kekekeks
Copy link
Member

https://github.com/darkfrostystorm/NotificationTrayIconSharp

@Mykhailo-Seniutovych
Copy link

https://github.com/darkfrostystorm/NotificationTrayIconSharp

I meant when do you plan to make it part of Avalonia itself?

@piksel
Copy link
Contributor

piksel commented Jun 2, 2021

@josegomez Too bad it's GPL:d 😓
I am currently working on an implementation for Tray Icon + HotKey support with the aim of it being xplat and a sharable library.
There is a LOT of duplicated code due to most Win32 classes being internal though. So yeah,

I meant when do you plan to make it part of Avalonia itself?

is there interest of integrating it into the platform itself through a PR? Not binding of course, but just as a heads up if you think it belongs in the core library or not.

@kekekeks
Copy link
Member

kekekeks commented Jun 2, 2021

@piksel as long as PR uses NativeMenu infrastructure and supports non-clickable icons (i. e. appindicator is only allowed to export a menu, it can't handle actual clicks on the icon), we'll accept it.

Most of the infrastructure for Linux and macOS is already there, we support synchronizing NativeMenu items to NSMenu and can export menu items via dbusmenu which is almost the same as appindicator.

@piksel
Copy link
Contributor

piksel commented Jun 3, 2021

@kekekeks thanks, thats exactly the type pointers I needed. My current implementation does support double-clicking the icon (to restore a minimize-to-tray app). Maybe that could be left as a platform-specific feature (since it's just there to comply with the common UX pattern for the OS). The current implementation executes the menu item command that has a IsDefault property set (attached).

@seanocali
Copy link

Just a heads up:
JesseRedfield/NotificationTrayIconSharp#6

@piksel
Copy link
Contributor

piksel commented Jun 20, 2021

The windows part of my implementation works but needs some polish, but the macOS and linux platforms turned out to be much harder to do...

@josegomez: The biggest issue is Linux which works as long as people use "the right" window manager and "the right" notification deamon... its a damn nightmare.

You weren't kidding. After several hours trying to get it to work using pure DBUS I finally retorted to using libappindciator via pinvoke.

Regarding the macos port, there is a lot of code-generation stuff not documented (afaict) and the native parts written in Objective C. Adding the correct bits is pretty trivial in an ordinary app, but I have yet to figure out how to do it correctly in the avalonia app-stub.

@JesseRedfield
Copy link

JesseRedfield commented Jul 1, 2021

The issue @seanocali raised is because I wasn't calling true on the blocking for the loop in the demo app. I exposed a wrapper to NSRunloop / windows messages so that you can run notifications in a context where there isn't one already setup. But I never called the blocking call which lowers CPU usage. It's toggle-able incase you are chaining runloop listeners so you can block or peek.

I toggled the default to true in the console test app.

This is a code block for creating an avalonia application that sits in the tray. Pay attention to OSXAppDelegate, you have to mess around a little bit to create an app that only lives in the OSX dock sometimes. This example requires the MonoMac Nuget.

Sometime in the next few weeks I will have a nupkg up, my library also includes TOAST notifications on OSX and windows. Although I am doing more testing on that before pushing it. I am doing just basic Icon/Text notifications.

For the reasons @piksel has mentioned, and because we don't have a business case at my work, I have yet to touch attempting to add any linux stuff. Although, it seems the consensus is if you use GTK as a dependency, you will have the most reliable tray notifications, since most DEs try and support as much of GTK/Gnome convention as they can, since it is arguably the most popular DE. GTK notifications work fine in KDE/Cinnamon/Gnome (of course)/XFCE, as I have seen with another application I found on github. Downside is now GTK is a dependency.

I hope someone gets good use out of my code ;-). Just ignore the fact I am old school and do extern C apis for pinvoking :-)

using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using MonoMac.AppKit;
using MonoMac.Foundation;
using NotificationIconSharp;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace AvaloniaApplicationDemo
{
    public class App : Application
    {
        private MainWindowView _mainWindow = null;
        private NotificationIcon _notificationIcon = null;

        public override void Initialize()
        {
            AvaloniaXamlLoader.Load(this);
        }

        public override void OnFrameworkInitializationCompleted()
        {
            /// Handle Initializing the NSApplication and setting an appropriate
            /// app delegate override for the app.  This currently uses Avalonia's
            /// MonoMac.NetStandard fork from the old Mono framework, this can be
            /// moved to Native if we ever have issues, but these APIs haven't
            /// changed in 13 years based on monos checkins
            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                NSApplication.Init();
                NSApplication.SharedApplication.Delegate = new OSXAppDelegate();
            }
            if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
            {

                desktop.MainWindow = new MainWindowView();
            }
            base.OnFrameworkInitializationCompleted();
            if (_notificationIcon == null)
            {
                // Create the notification tray icon, this should be the main thread anyways
                _notificationIcon = new NotificationIcon("path to icon.png/ico");
                _notificationIcon.NotificationIconSelected += Icon_NotificationIconSelected;
            }
        }

        /// <summary>
        /// show and/or create the main window instance if necessary
        /// </summary>
        public void RestoreMainWindow()
        {
            var desktopApplicationLifetime = Current.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime;
            if (_mainWindow == null)
            {
                _mainWindow = new MainWindowView();
                _mainWindow.Closing += MainWindow_Closing;
            }
            if (desktopApplicationLifetime?.MainWindow != _mainWindow)
            {
                desktopApplicationLifetime.MainWindow = _mainWindow;
            }
            _mainWindow.Show();
            _mainWindow.WindowState = WindowState.Normal;
            _mainWindow.BringIntoView();
            _mainWindow.Focus();
            ShowApplicationInstance();
        }

        /// <summary>
        /// Exit the application
        /// </summary>
        public void Exit()
        {
            (Current.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime).Shutdown(0);
        }

        /// <summary>
        /// OSX Helper function used to Hide the dock icon when running as a daemon
        /// </summary>
        public static void HideApplicationInstance()
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                NSApplication.SharedApplication.ActivationPolicy = NSApplicationActivationPolicy.Accessory;
            }
        }

        /// <summary>
        /// OSX Helper function used to Show the dock icon when running as a daemon
        /// </summary>
        public static void ShowApplicationInstance()
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                NSApplication.SharedApplication.ActivationPolicy = NSApplicationActivationPolicy.Regular;
            }
        }

        private void MainWindow_Closing(object sender, CancelEventArgs e)
        {
            _mainWindow?.Hide();
            _mainWindow = null;
            HideApplicationInstance();
        }

        private void Icon_NotificationIconSelected(NotificationIcon icon)
        {
            Dispatcher.UIThread.Post(() =>
            {
                RestoreMainWindow(); // Restore main window on notification icon click
            });
        }
    }

    /// <summary>
    /// OSX Helper class, overrides Avalonias default AppDelegate to give us more
    /// control over a few pieces of behavior allowing us to get away with some
    /// stuff in a system daemon that the Avalonia devs didn't anticipate ;-)
    /// </summary>
    public class OSXAppDelegate : NSApplicationDelegate
    {
        public OSXAppDelegate()
        {
            AvaloniaLocator.CurrentMutable.Bind<OSXAppDelegate>().ToConstant(this);
        }

        /// <summary>
        /// Because we are creating our own mac application delegate we are removing / overriding 
        /// the one that Avalonia creates. This causes the application to not be handled as it should.
        /// This is the Avalonia Implementation: https://github.com/AvaloniaUI/Avalonia/blob/5a2ef35dacbce0438b66d9f012e5f629045beb3d/native/Avalonia.Native/src/OSX/app.mm
        /// So what we are doing here is re-creating this implementation to mimick their behavior.
        /// </summary>
        /// <param name="notification"></param>
        public override void WillFinishLaunching(NSNotification notification)
        {
            if (NSApplication.SharedApplication.ActivationPolicy != NSApplicationActivationPolicy.Regular)
            {
                foreach (var x in NSRunningApplication.GetRunningApplications(@"com.apple.dock"))
                {
                    x.Activate(NSApplicationActivationOptions.ActivateIgnoringOtherWindows);
                    break;
                }

                NSApplication.SharedApplication.ActivationPolicy = NSApplicationActivationPolicy.Accessory;
            }
        }

        /// <summary>
        /// Because we are creating our own mac application delegate we are removing / overriding 
        /// the one that Avalonia creates. This causes the application to not be handled as it should.
        /// This is the Avalonia Implementation: https://github.com/AvaloniaUI/Avalonia/blob/5a2ef35dacbce0438b66d9f012e5f629045beb3d/native/Avalonia.Native/src/OSX/app.mm
        /// So what we are doing here is re-creating this implementation to mimick their behavior.
        /// </summary>
        /// <param name="notification"></param>
        public override void DidFinishLaunching(NSNotification notification)
        {
            NSRunningApplication.CurrentApplication.Activate(NSApplicationActivationOptions.ActivateIgnoringOtherWindows);
        }
    }

@nathanAjacobs
Copy link

Is this still planned to be supported directly in Avalonia?

@FG-rgb
Copy link

FG-rgb commented Aug 30, 2021

I love Avalonia, and try to keep it up in productive code.
But I can say I workarounded that for Windows, as I'm currently on Windows only (for the future on other Platforms, too).
Therefore I implemented a windows only Tray/Notify-Icon class.
This was not trivial at all.
E.g. If you would like to show a tooltip by hovering the icon... , or show the ContextMenu on rightclick... or other content like custom dialogs... you need a helper window, because avalonia popups are not support without a window, and can not be set to an absolute position (like in WPF).
This Window must be hidden in Taskbar, therefore you need a WinApi call, as workaround, because this actually does not work for Windows with SystemDecorations.None...
Than you must manually position it at the Mouse cursor, or the correct desktop position...
Than you have problems of the Contextmenu has a subcontextmenu, because this submenu does not auto close on window Contextmenu outside click, and so on...
Many small things that should be corrected....

Therefore an official variant would be the best solution.

@MeertenR
Copy link

MeertenR commented Aug 30, 2021

I am about to adopt Avalonia as it seems like a true diamond in the rough.
But man.. no tray icon. Is it not a priority?
I am really looking forward to this.
Not doing the GPL thing or the other handful-of-DLLs thing, if this will get directly implemented Avalonia-style.

@danwalmsley
Copy link
Member

@MeertenR work has started to add apis for this.

@maxkatz6
Copy link
Member

#6560

@duke-darius
Copy link

The issue @seanocali raised is because I wasn't calling true on the blocking for the loop in the demo app. I exposed a wrapper to NSRunloop / windows messages so that you can run notifications in a context where there isn't one already setup. But I never called the blocking call which lowers CPU usage. It's toggle-able incase you are chaining runloop listeners so you can block or peek.

I toggled the default to true in the console test app.

This is a code block for creating an avalonia application that sits in the tray. Pay attention to OSXAppDelegate, you have to mess around a little bit to create an app that only lives in the OSX dock sometimes. This example requires the MonoMac Nuget.

Sometime in the next few weeks I will have a nupkg up, my library also includes TOAST notifications on OSX and windows. Although I am doing more testing on that before pushing it. I am doing just basic Icon/Text notifications.

For the reasons @piksel has mentioned, and because we don't have a business case at my work, I have yet to touch attempting to add any linux stuff. Although, it seems the consensus is if you use GTK as a dependency, you will have the most reliable tray notifications, since most DEs try and support as much of GTK/Gnome convention as they can, since it is arguably the most popular DE. GTK notifications work fine in KDE/Cinnamon/Gnome (of course)/XFCE, as I have seen with another application I found on github. Downside is now GTK is a dependency.

I hope someone gets good use out of my code ;-). Just ignore the fact I am old school and do extern C apis for pinvoking :-)

using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using MonoMac.AppKit;
using MonoMac.Foundation;
using NotificationIconSharp;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace AvaloniaApplicationDemo
{
    public class App : Application
    {
        private MainWindowView _mainWindow = null;
        private NotificationIcon _notificationIcon = null;

        public override void Initialize()
        {
            AvaloniaXamlLoader.Load(this);
        }

        public override void OnFrameworkInitializationCompleted()
        {
            /// Handle Initializing the NSApplication and setting an appropriate
            /// app delegate override for the app.  This currently uses Avalonia's
            /// MonoMac.NetStandard fork from the old Mono framework, this can be
            /// moved to Native if we ever have issues, but these APIs haven't
            /// changed in 13 years based on monos checkins
            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                NSApplication.Init();
                NSApplication.SharedApplication.Delegate = new OSXAppDelegate();
            }
            if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
            {

                desktop.MainWindow = new MainWindowView();
            }
            base.OnFrameworkInitializationCompleted();
            if (_notificationIcon == null)
            {
                // Create the notification tray icon, this should be the main thread anyways
                _notificationIcon = new NotificationIcon("path to icon.png/ico");
                _notificationIcon.NotificationIconSelected += Icon_NotificationIconSelected;
            }
        }

        /// <summary>
        /// show and/or create the main window instance if necessary
        /// </summary>
        public void RestoreMainWindow()
        {
            var desktopApplicationLifetime = Current.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime;
            if (_mainWindow == null)
            {
                _mainWindow = new MainWindowView();
                _mainWindow.Closing += MainWindow_Closing;
            }
            if (desktopApplicationLifetime?.MainWindow != _mainWindow)
            {
                desktopApplicationLifetime.MainWindow = _mainWindow;
            }
            _mainWindow.Show();
            _mainWindow.WindowState = WindowState.Normal;
            _mainWindow.BringIntoView();
            _mainWindow.Focus();
            ShowApplicationInstance();
        }

        /// <summary>
        /// Exit the application
        /// </summary>
        public void Exit()
        {
            (Current.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime).Shutdown(0);
        }

        /// <summary>
        /// OSX Helper function used to Hide the dock icon when running as a daemon
        /// </summary>
        public static void HideApplicationInstance()
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                NSApplication.SharedApplication.ActivationPolicy = NSApplicationActivationPolicy.Accessory;
            }
        }

        /// <summary>
        /// OSX Helper function used to Show the dock icon when running as a daemon
        /// </summary>
        public static void ShowApplicationInstance()
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                NSApplication.SharedApplication.ActivationPolicy = NSApplicationActivationPolicy.Regular;
            }
        }

        private void MainWindow_Closing(object sender, CancelEventArgs e)
        {
            _mainWindow?.Hide();
            _mainWindow = null;
            HideApplicationInstance();
        }

        private void Icon_NotificationIconSelected(NotificationIcon icon)
        {
            Dispatcher.UIThread.Post(() =>
            {
                RestoreMainWindow(); // Restore main window on notification icon click
            });
        }
    }

    /// <summary>
    /// OSX Helper class, overrides Avalonias default AppDelegate to give us more
    /// control over a few pieces of behavior allowing us to get away with some
    /// stuff in a system daemon that the Avalonia devs didn't anticipate ;-)
    /// </summary>
    public class OSXAppDelegate : NSApplicationDelegate
    {
        public OSXAppDelegate()
        {
            AvaloniaLocator.CurrentMutable.Bind<OSXAppDelegate>().ToConstant(this);
        }

        /// <summary>
        /// Because we are creating our own mac application delegate we are removing / overriding 
        /// the one that Avalonia creates. This causes the application to not be handled as it should.
        /// This is the Avalonia Implementation: https://github.com/AvaloniaUI/Avalonia/blob/5a2ef35dacbce0438b66d9f012e5f629045beb3d/native/Avalonia.Native/src/OSX/app.mm
        /// So what we are doing here is re-creating this implementation to mimick their behavior.
        /// </summary>
        /// <param name="notification"></param>
        public override void WillFinishLaunching(NSNotification notification)
        {
            if (NSApplication.SharedApplication.ActivationPolicy != NSApplicationActivationPolicy.Regular)
            {
                foreach (var x in NSRunningApplication.GetRunningApplications(@"com.apple.dock"))
                {
                    x.Activate(NSApplicationActivationOptions.ActivateIgnoringOtherWindows);
                    break;
                }

                NSApplication.SharedApplication.ActivationPolicy = NSApplicationActivationPolicy.Accessory;
            }
        }

        /// <summary>
        /// Because we are creating our own mac application delegate we are removing / overriding 
        /// the one that Avalonia creates. This causes the application to not be handled as it should.
        /// This is the Avalonia Implementation: https://github.com/AvaloniaUI/Avalonia/blob/5a2ef35dacbce0438b66d9f012e5f629045beb3d/native/Avalonia.Native/src/OSX/app.mm
        /// So what we are doing here is re-creating this implementation to mimick their behavior.
        /// </summary>
        /// <param name="notification"></param>
        public override void DidFinishLaunching(NSNotification notification)
        {
            NSRunningApplication.CurrentApplication.Activate(NSApplicationActivationOptions.ActivateIgnoringOtherWindows);
        }
    }

YOOOO You really did it with this one!!!!
Literally like 4 issues resolved in one fell swoop.
Hats off :)

@OmegaRogue
Copy link

OmegaRogue commented Nov 30, 2023

https://www.freedesktop.org/wiki/Specifications/systemtray-spec/ support for this would be nice, this is the normal spec for linux, not everything supports the kde appindicator spec, without this avalonia apps crash on launch on various window managers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests