[macOS] Add NativeDock.Menu API for adding menu items to macOS dock icon#20634
[macOS] Add NativeDock.Menu API for adding menu items to macOS dock icon#20634drasticactions wants to merge 26 commits intomasterfrom
Conversation
|
You can test this PR using the following package version. |
|
|
||
| namespace Avalonia.Native | ||
| { | ||
| internal class AvaloniaNativeDockMenuExporter : INativeMenuExporter, INativeMenuExporterResetHandler |
There was a problem hiding this comment.
Why do we need a separate exporter when tray menu reuses the shared one?
There was a problem hiding this comment.
There was a problem hiding this comment.
I'd suggest to just change that ctor of AvaloniaNativeMenuExporter to accept Action<IAvnMenu> and reuse the existing class
There was a problem hiding this comment.
In my head I was thinking about NativeMenu.Menu and didn't consider what TrayIcon did. I'll try changing it.
| using Avalonia.UnitTests; | ||
| using Xunit; | ||
|
|
||
| namespace Avalonia.Controls.UnitTests |
There was a problem hiding this comment.
You have 6 tests for an attached property registration.
There was a problem hiding this comment.
This is what happens when you use Claude for writing tests and don't actually look at it. Sorry, should have caught that these are basically useless.
Removed and replaced with Appium tests, 464ad50. These just validate that the dock items can be updated, checking the dock itself with Appium seemed very flakey on my machine so I want to validate it doesn't throw before going too crazy.
|
|
||
|
|
||
|
|
||
| virtual HRESULT SetDockMenu(IAvnMenu* dockMenu) override |
There was a problem hiding this comment.
What happens if this is called after initial startup?
There was a problem hiding this comment.
It updates the dock menu. You can dynamically update the dock menu with new menu items (Although IMO it's a bad idea to do it because it won't be obvious to users that the items have changed). I updated the tests and the ControlGallery app (cc90f5c) to show it.
| return s_appMenuItem; | ||
| } | ||
|
|
||
| static IAvnMenu* s_dockMenu = nullptr; |
There was a problem hiding this comment.
Actually, you can just save NSMenu* reference somewhere in app.mm, no need to keep a COM reference here.
There was a problem hiding this comment.
I was following the pattern with what was used for NativeMenu Menu's (Basically copy/paste it but with "Dock" instead.) Yeah, this could be simplified, changed with f47b0d6
|
You can test this PR using the following package version. |
| @@ -0,0 +1,8 @@ | |||
| namespace Avalonia.Native | |||
| { | |||
| internal interface INativeMenuExporterResetHandler | |||
There was a problem hiding this comment.
This part of the change set isn't needed anymore
There was a problem hiding this comment.
Yeah, will revert.
src/Avalonia.Native/IAvnMenu.cs
Outdated
| private Action _queueReset = null!; | ||
| private Action _updateIfNeeded = null!; |
There was a problem hiding this comment.
Since I got rid of the common interface, I changed the internal calls in IAvnMenu to Actions so they could be called by both Menu and DockMenu calls. If you feel this should be different I'm open to it.
|
You can test this PR using the following package version. |
|
You can test this PR using the following package version. |
|
Re. d8c34cc Between Github CI runners and Appium, finding a way to interact with the Dock in macOS has proven very hard. Looking at the TrayIcon tests, those seemed to have been turned off for similar reasons. I'm still thinking of how to solve that, but the test that invokes the dock menu is running and working. |
|
You can test this PR using the following package version. |
|
You can test this PR using the following package version. |
|
You can test this PR using the following package version. |
|
Notes from the API review meeting: |
Changed with d1fefdf |
|
You can test this PR using the following package version. |
|
You can test this PR using the following package version. |
|
You can test this PR using the following package version. |
| { | ||
| internal class AvaloniaNativeMenuExporter : ITopLevelNativeMenuExporter | ||
| { | ||
| internal enum MenuTarget { Application, Window, TrayIcon, Dock } |
There was a problem hiding this comment.
The logic before was checking against which object in the exporter was null. Adding an enum to check against this when it's created and using a switch seemed safer to me, but I'm open to changes to this.
|
You can test this PR using the following package version. |
What does the pull request do?
This PR adds support for a native Dock menu interop for macOS, allowing apps to customize the menu shown when right-clicking the app icon in the dock.
For this, I added some new APIs to the Avalonia.Native codebase and sample usage in ControlGallery. If you right click the dock in ControlGallery, you can open a new window or pull up the main window.
As this adds new APIs, we'll need to do an API review.
What is the current behavior?
There is currently no way to add dock menu items in Avalonia, without pulling in the .NET MacOS SDK bindings and doing it yourself.
What is the updated/expected behavior with this PR?
In
Application.xamlNativeDock.Menulets you add menu items to the macOS dock icon.How was the solution implemented (if it's not obvious)?
I refactored the NativeMenu API to be usable for both the Native taskbar menu and dock for macOS and added the interop code to the Avalonia.Native dylib. The API should function similar to what is done for NativeMenu, only it's for the dock. This only supports macOS.
Checklist
tests/Avalonia.Controls.UnitTests/NativeMenuTests.cs)Breaking changes
Obsoletions / Deprecations
Fixed issues