From 6f0bfbf3aa244115305bf5ea823a69459b5c5f0a Mon Sep 17 00:00:00 2001
From: Steveice10 <1269164+Steveice10@users.noreply.github.com>
Date: Sun, 22 Oct 2023 20:11:37 -0700
Subject: [PATCH] Exclude access key markers from native menu titles on macOS.
(#13338)
* Add integration test for access key indicators in macOS menu bar titles.
Tests for access key indicators displaying as plain underscores in macOS menu bar items.
* Exclude access key markers from native menu titles on macOS.
macOS does not support access key markers, so they just display as extra underscores.
---
samples/IntegrationTestApp/MainWindow.axaml | 3 +++
src/Avalonia.Native/IAvnMenu.cs | 19 +++++++++++++++++--
src/Avalonia.Native/IAvnMenuItem.cs | 16 +++++++++++++++-
.../NativeMenuTests.cs | 9 +++++++++
4 files changed, 44 insertions(+), 3 deletions(-)
diff --git a/samples/IntegrationTestApp/MainWindow.axaml b/samples/IntegrationTestApp/MainWindow.axaml
index 1c88f2c95f..375bd1851b 100644
--- a/samples/IntegrationTestApp/MainWindow.axaml
+++ b/samples/IntegrationTestApp/MainWindow.axaml
@@ -18,6 +18,9 @@
+
+
+
diff --git a/src/Avalonia.Native/IAvnMenu.cs b/src/Avalonia.Native/IAvnMenu.cs
index 515835a3bd..dc0176a8ad 100644
--- a/src/Avalonia.Native/IAvnMenu.cs
+++ b/src/Avalonia.Native/IAvnMenu.cs
@@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
+using Avalonia.Compatibility;
using Avalonia.Reactive;
using Avalonia.Controls;
+using Avalonia.Controls.Primitives;
namespace Avalonia.Native.Interop
{
@@ -47,6 +49,20 @@ namespace Avalonia.Native.Interop.Impl
private List<__MicroComIAvnMenuItemProxy> _menuItems = new List<__MicroComIAvnMenuItemProxy>();
private Dictionary _menuItemLookup = new Dictionary();
+ private void UpdateTitle(string title)
+ {
+ if (OperatingSystemEx.IsMacOS())
+ {
+ // macOS does not process access key markers, so remove them.
+ title = AccessText.RemoveAccessKeyMarker(title);
+ }
+ if (string.IsNullOrWhiteSpace(title))
+ {
+ title = "";
+ }
+ SetTitle(title);
+ }
+
public void RaiseNeedsUpdate()
{
(ManagedMenu as INativeMenuExporterEventsImplBridge).RaiseNeedsUpdate();
@@ -127,8 +143,7 @@ namespace Avalonia.Native.Interop.Impl
((INotifyCollectionChanged)ManagedMenu.Items).CollectionChanged += OnMenuItemsChanged;
- if (!string.IsNullOrWhiteSpace(title))
- SetTitle(title);
+ UpdateTitle(title);
}
public void Deinitialise()
diff --git a/src/Avalonia.Native/IAvnMenuItem.cs b/src/Avalonia.Native/IAvnMenuItem.cs
index 424d2c7310..540a4fd8c8 100644
--- a/src/Avalonia.Native/IAvnMenuItem.cs
+++ b/src/Avalonia.Native/IAvnMenuItem.cs
@@ -1,7 +1,9 @@
using System;
using System.IO;
+using Avalonia.Compatibility;
using Avalonia.Reactive;
using Avalonia.Controls;
+using Avalonia.Controls.Primitives;
using Avalonia.Media.Imaging;
using Avalonia.Platform.Interop;
@@ -22,7 +24,19 @@ namespace Avalonia.Native.Interop.Impl
public NativeMenuItemBase ManagedMenuItem { get; set; }
- private void UpdateTitle(string title) => SetTitle(title ?? "");
+ private void UpdateTitle(string title)
+ {
+ if (OperatingSystemEx.IsMacOS())
+ {
+ // macOS does not process access key markers, so remove them.
+ title = AccessText.RemoveAccessKeyMarker(title);
+ }
+ if (string.IsNullOrWhiteSpace(title))
+ {
+ title = "";
+ }
+ SetTitle(title);
+ }
private void UpdateIsChecked(bool isChecked) => SetIsChecked(isChecked.AsComBool());
diff --git a/tests/Avalonia.IntegrationTests.Appium/NativeMenuTests.cs b/tests/Avalonia.IntegrationTests.Appium/NativeMenuTests.cs
index eb7740aa43..aff8a6e8d7 100644
--- a/tests/Avalonia.IntegrationTests.Appium/NativeMenuTests.cs
+++ b/tests/Avalonia.IntegrationTests.Appium/NativeMenuTests.cs
@@ -49,5 +49,14 @@ namespace Avalonia.IntegrationTests.Appium
Assert.True(buttonTab.Selected);
}
+
+ [PlatformFact(TestPlatforms.MacOS)]
+ public void MacOS_Sanitizes_Access_Key_Markers_When_Included_In_Menu_Title()
+ {
+ var menuBar = _session.FindElementByXPath("/XCUIElementTypeApplication/XCUIElementTypeMenuBar");
+
+ Assert.True(menuBar.FindElementsByName("_Options").Count == 0);
+ Assert.True(menuBar.FindElementsByName("Options").Count == 1);
+ }
}
}