Skip to content

[MacCatalyst] Fix KeyboardAccelerator with Cmd+Shift modifiers breaks entire MenuBarItem on Mac Catalyst #35318

Merged
kubaflo merged 6 commits into
dotnet:inflight/currentfrom
KarthikRajaKalaimani:fix-35279
May 11, 2026
Merged

[MacCatalyst] Fix KeyboardAccelerator with Cmd+Shift modifiers breaks entire MenuBarItem on Mac Catalyst #35318
kubaflo merged 6 commits into
dotnet:inflight/currentfrom
KarthikRajaKalaimani:fix-35279

Conversation

@KarthikRajaKalaimani

Copy link
Copy Markdown
Contributor

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Issue Details:

KeyboardAccelerator with Cmd+Shift modifiers break entire MenuBarItem on Mac Catalyst

Root Cause:

When defiens a KeyboardAccelerator with an uppercase alphabetic key and a Shift modifier — for example Key="S" with Modifiers="Shift,Cmd" — the platform call UIKeyCommand.Create(...) on Mac Catalyst receives the string "S" (uppercase). Apple's UIKeyCommand API has an undocumented but strict requirement: alphabetic input strings must be lowercase. When an uppercase letter is passed alongside UIKeyModifierFlags.Shift, Mac Catalyst silently discards the entire UIKeyCommand. This doesn't just break that one menu item — it poisons the entire parent UIMenu, causing the whole menu bar item (e.g. the File menu) to stop opening entirely. The symptom then cascades to sibling menus (like the Edit menu's Copy item) appearing to vanish as well, even though they are unrelated to the offending accelerator.

Description of Change:

The fix is a one-line normalization in CreateMenuItemKeyCommand inside KeyboardAcceleratorExtensions.cs (Mac Catalyst / iOS platformlayer): Before passing the key string to UIKeyCommand.Create, single-character alphabetic keys are silently lowercased. The UIKeyModifierFlags.Shift that the user already set is left unchanged — Mac Catalyst correctly interprets "s" + Shift as the Cmd+Shift+S accelerator. Non-alphabetic keys (numbers, function keys, special characters) are passed through untouched. The fix is scoped entirely to the iOS/Mac Catalyst platform layer and has no effect on Android or Windows.

**Tested the behavior in the following platforms: **

  • Android
  • Windows
  • iOS
  • Mac

Reference:

N/A

Issues Fixed:

Fixes #35279

Screenshots

Before After
Before_35279.mov
After_35279.mov

@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35318

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35318"

@dotnet-policy-service dotnet-policy-service Bot added the community ✨ Community Contribution label May 6, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Hey there @@KarthikRajaKalaimani! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label May 6, 2026
@NirmalKumarYuvaraj NirmalKumarYuvaraj added area-controls-menubar Desktop MenuBarItems platform/macos macOS / Mac Catalyst labels May 6, 2026
@sheiksyedm sheiksyedm marked this pull request as ready for review May 6, 2026 07:33
Copilot AI review requested due to automatic review settings May 6, 2026 07:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a Mac Catalyst-specific failure mode where UIKeyCommand.Create(...) silently rejects keyboard accelerators using an uppercase alphabetic key combined with Shift (e.g., Cmd+Shift+S), which can break the entire parent menu.

Changes:

  • Normalize single-character alphabetic accelerator keys to lowercase before calling UIKeyCommand.Create.
  • Add a Mac Catalyst device test to assert UIKeyCommand.Input is lowercase for uppercase alphabetic accelerator keys (including the Cmd+Shift+S repro case).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/Core/src/Platform/iOS/KeyboardAcceleratorExtensions.cs Lowercases single-letter alphabetic keys before creating UIKeyCommand to prevent menu poisoning on Mac Catalyst.
src/Controls/tests/DeviceTests/Elements/MenuFlyoutItem/MenuFlyoutItemKeyboardAcceleratorTests.iOS.cs Adds Mac Catalyst regression tests validating the normalized UIKeyCommand.Input (and modifier flags for the repro case).

// (e.g. "S") combined with UIKeyModifierFlags.Shift causes Mac Catalyst to silently
// reject the UIKeyCommand, which makes the entire parent UIMenu non-functional.
// See: https://github.com/dotnet/maui/issues/35279
var normalizedKey = key.Length == 1 && char.IsLetter(key[0]) ? key.ToLowerInvariant() : key;
Comment on lines +27 to +37
var item = new MenuFlyoutItem { Text = "Test Item" };
item.KeyboardAccelerators.Add(new KeyboardAccelerator
{
Key = inputKey,
Modifiers = KeyboardAcceleratorModifiers.Cmd | KeyboardAcceleratorModifiers.Shift
});

var uiMenuElement = item.CreateMenuItem(MauiContext);
var keyCommand = Assert.IsType<UIKeyCommand>(uiMenuElement);

Assert.Equal(expectedInput, keyCommand.Input);

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expert Review — 3 findings

See inline comments for details.

@MauiBot MauiBot added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) s/agent-fix-win AI found a better alternative fix than the PR labels May 6, 2026

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like tests are failing - could you please have a look?

@dotnet dotnet deleted a comment from MauiBot May 6, 2026
@dotnet dotnet deleted a comment from MauiBot May 6, 2026
@dotnet dotnet deleted a comment from MauiBot May 6, 2026
@dotnet dotnet deleted a comment from MauiBot May 6, 2026
MauiBot
MauiBot previously requested changes May 6, 2026

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Automated review — alternative fix proposed

The expert-reviewer evaluation compared the PR fix against #2 automatically generated candidates and selected try-fix-2 as the strongest fix.

Why: try-fix-2 is the winning candidate because it is the only approach that achieved PASS (4/4 tests) by addressing both root issues: (1) making both test methods async Task with InvokeOnMainThreadAsync to fix UIKit thread-affinity assertions that caused Gate failure, and (2) using char.IsAsciiLetter + char.ToLowerInvariant(key[0]).ToString() to fix the Unicode expansion edge case in the production normalization. The PR's fix has the correct intent but fails in Debug CI due to synchronous UIKit calls off the main thread.

Please consider applying the candidate diff below (or use it as guidance). Once you push an update, this workflow will re-trigger and re-evaluate.

Candidate diff (`try-fix-2`)
diff --git a/src/Controls/tests/DeviceTests/Elements/MenuFlyoutItem/MenuFlyoutItemKeyboardAcceleratorTests.iOS.cs b/src/Controls/tests/DeviceTests/Elements/MenuFlyoutItem/MenuFlyoutItemKeyboardAcceleratorTests.iOS.cs
index 0694aa3096..301e45ba73 100644
--- a/src/Controls/tests/DeviceTests/Elements/MenuFlyoutItem/MenuFlyoutItemKeyboardAcceleratorTests.iOS.cs
+++ b/src/Controls/tests/DeviceTests/Elements/MenuFlyoutItem/MenuFlyoutItemKeyboardAcceleratorTests.iOS.cs
@@ -1,4 +1,5 @@
 #if MACCATALYST
+using System.Threading.Tasks;
 using Microsoft.Maui.Controls;
 using Microsoft.Maui.Handlers;
 using Microsoft.Maui.Platform;
@@ -20,7 +21,7 @@ namespace Microsoft.Maui.DeviceTests
 		[InlineData("S", "s")]
 		[InlineData("A", "a")]
 		[InlineData("Z", "z")]
-		public void AlphabeticKeyIsNormalisedToLowercase(string inputKey, string expectedInput)
+		public async Task AlphabeticKeyIsNormalisedToLowercase(string inputKey, string expectedInput)
 		{
 			try
 			{
@@ -31,10 +32,12 @@ namespace Microsoft.Maui.DeviceTests
 					Modifiers = KeyboardAcceleratorModifiers.Cmd | KeyboardAcceleratorModifiers.Shift
 				});
 
-				var uiMenuElement = item.CreateMenuItem(MauiContext);
-				var keyCommand = Assert.IsType<UIKeyCommand>(uiMenuElement);
-
-				Assert.Equal(expectedInput, keyCommand.Input);
+				await InvokeOnMainThreadAsync(() =>
+				{
+					var uiMenuElement = item.CreateMenuItem(MauiContext);
+					var keyCommand = Assert.IsType<UIKeyCommand>(uiMenuElement);
+					Assert.Equal(expectedInput, keyCommand.Input);
+				});
 			}
 			finally
 			{
@@ -43,7 +46,7 @@ namespace Microsoft.Maui.DeviceTests
 		}
 
 		[Fact(DisplayName = "Cmd+Shift+S (the issue #35279 repro case) produces Input='s'")]
-		public void CmdShiftSProducesLowercaseInput()
+		public async Task CmdShiftSProducesLowercaseInput()
 		{
 			try
 			{
@@ -54,11 +57,13 @@ namespace Microsoft.Maui.DeviceTests
 					Modifiers = KeyboardAcceleratorModifiers.Cmd | KeyboardAcceleratorModifiers.Shift
 				});
 
-				var uiMenuElement = item.CreateMenuItem(MauiContext);
-				var keyCommand = Assert.IsType<UIKeyCommand>(uiMenuElement);
-
-				Assert.Equal("s", keyCommand.Input);
-				Assert.Equal(UIKeyModifierFlags.Command | UIKeyModifierFlags.Shift, keyCommand.ModifierFlags);
+				await InvokeOnMainThreadAsync(() =>
+				{
+					var uiMenuElement = item.CreateMenuItem(MauiContext);
+					var keyCommand = Assert.IsType<UIKeyCommand>(uiMenuElement);
+					Assert.Equal("s", keyCommand.Input);
+					Assert.Equal(UIKeyModifierFlags.Command | UIKeyModifierFlags.Shift, keyCommand.ModifierFlags);
+				});
 			}
 			finally
 			{
diff --git a/src/Core/src/Platform/iOS/KeyboardAcceleratorExtensions.cs b/src/Core/src/Platform/iOS/KeyboardAcceleratorExtensions.cs
index 171144a042..cad5f0f49f 100644
--- a/src/Core/src/Platform/iOS/KeyboardAcceleratorExtensions.cs
+++ b/src/Core/src/Platform/iOS/KeyboardAcceleratorExtensions.cs
@@ -46,11 +46,21 @@ namespace Microsoft.Maui.Platform
 
 		static UIKeyCommand CreateMenuItemKeyCommand(this IMenuFlyoutItem virtualView, int index, UIImage? uiImage, Selector selector, UIKeyModifierFlags modifierFlags, string key)
 		{
+			// UIKeyCommand requires lowercase input for alphabetic keys. Using an uppercase
+			// letter (e.g. "S") combined with UIKeyModifierFlags.Shift causes Mac Catalyst to
+			// silently reject the UIKeyCommand, making the entire parent UIMenu non-functional.
+			// Using char.IsAsciiLetter (A-Z/a-z only) matches the valid UIKeyCommand input
+			// range, and the char-level ToLowerInvariant avoids any multi-char Unicode expansion.
+			// See: https://github.com/dotnet/maui/issues/35279
+			var normalizedKey = key.Length == 1 && char.IsAsciiLetter(key[0])
+				? char.ToLowerInvariant(key[0]).ToString()
+				: key;
+
 			var keyCommand = UIKeyCommand.Create(
 				title: virtualView.Text,
 				uiImage,
 				selector,
-				key,
+				normalizedKey,
 				modifierFlags,
 				new NSString(index.ToString()));
 

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you pleas check the ai's suggestions?

@dotnet dotnet deleted a comment from MauiBot May 8, 2026
@MauiBot MauiBot added s/agent-review-incomplete and removed s/agent-changes-requested AI agent recommends changes - found a better alternative or issues labels May 8, 2026
@dotnet dotnet deleted a comment from MauiBot May 11, 2026
@dotnet dotnet deleted a comment from KarthikRajaKalaimani May 11, 2026
@MauiBot

MauiBot commented May 11, 2026

Copy link
Copy Markdown
Collaborator

🤖 AI Summary

👋 @KarthikRajaKalaimani — new AI review results are available. Please review the latest session below.

📊 Review Session8cd3763 · Test case improved · 2026-05-11 16:16 UTC
🚦 Gate — Test Before & After Fix

Gate Result: ❌ FAILED

Platform: IOS · Base: main · Merge base: f8cb875e

🩺 Test does not reproduce the bug — ran the same in both states (PASS without fix, PASS with fix). The repro test is not exercising the issue. Strengthen the test before reviewing the fix.

Test Without Fix (expect FAIL) With Fix (expect PASS)
📱 MenuFlyoutItemKeyboardAcceleratorTests (AlphabeticKeyIsNormalisedToLowercase, CmdShiftSProducesLowercaseInput, MultiCharacterKeyPassesThroughUnchanged) Category=MenuFlyout ❌ PASS — 358s ✅ PASS — 206s
🔴 Without fix — 📱 MenuFlyoutItemKeyboardAcceleratorTests (AlphabeticKeyIsNormalisedToLowercase, CmdShiftSProducesLowercaseInput, MultiCharacterKeyPassesThroughUnchanged): PASS ❌ · 358s

(truncated to last 15,000 chars)

6-05-11 08:24:46.624969-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Button'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6279960] 2026-05-11 08:24:46.625030-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'CarouselView'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6280000] 2026-05-11 08:24:46.625082-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'CheckBox'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6280040] 2026-05-11 08:24:46.625188-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'CollectionView'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6280120] 2026-05-11 08:24:46.625268-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Compatibility'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6280150] 2026-05-11 08:24:46.625329-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'ContentView'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6280180] 2026-05-11 08:24:46.625373-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'DatePicker'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6280220] 2026-05-11 08:24:46.625417-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Dispatcher'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6280260] 2026-05-11 08:24:46.625483-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Editor'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6280380] 2026-05-11 08:24:46.625532-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Element'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6280430] 2026-05-11 08:24:46.625759-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Entry'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6280560] 2026-05-11 08:24:46.625848-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'FlexLayout'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6280600] 2026-05-11 08:24:46.625903-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'FlyoutPage'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6280640] 2026-05-11 08:24:46.625977-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Frame'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6280760] 2026-05-11 08:24:46.626088-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Gesture'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6280800] 2026-05-11 08:24:46.626197-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'HybridWebView'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6280840] 2026-05-11 08:24:46.626297-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Image'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6280870] 2026-05-11 08:24:46.626376-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Label'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6280920] 2026-05-11 08:24:46.626468-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Layout'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6281080] 2026-05-11 08:24:46.626526-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Lifecycle'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6281130] 2026-05-11 08:24:46.626642-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'ListView'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6281160] 2026-05-11 08:24:46.626739-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Map'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6281200] 2026-05-11 08:24:46.626821-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Mapper'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6281240] 2026-05-11 08:24:46.626943-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Excluded test (filtered by Trait; 'Category':'Memory'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6281380] 2026-05-11 08:24:46.627034-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Modal'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6281420] 2026-05-11 08:24:46.627119-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'NavigationPage'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6281460] 2026-05-11 08:24:46.627197-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Page'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6281490] 2026-05-11 08:24:46.627290-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Path'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6281540] 2026-05-11 08:24:46.627721-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Picker'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6281570] 2026-05-11 08:24:46.627853-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'RadioButton'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6281630] 2026-05-11 08:24:46.627941-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'RefreshView'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6281730] 2026-05-11 08:24:46.628072-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'ScrollView'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6288320] 2026-05-11 08:24:46.628186-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'SearchBar'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6288470] 2026-05-11 08:24:46.628243-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Shape'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6288500] 2026-05-11 08:24:46.628313-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Shell'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6288520] 2026-05-11 08:24:46.628376-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Slider'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6288540] 2026-05-11 08:24:46.628429-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'SwipeView'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6288570] 2026-05-11 08:24:46.628475-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'TabbedPage'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6288600] 2026-05-11 08:24:46.628552-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'TextInput'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6288620] 2026-05-11 08:24:46.628609-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Toolbar'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6288640] 2026-05-11 08:24:46.628726-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'TemplatedView'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6292940] 2026-05-11 08:24:46.628830-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'View'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6293020] 2026-05-11 08:24:46.628931-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'VisualElement'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6293050] 2026-05-11 08:24:46.629000-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'VisualElementTree'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6293080] 2026-05-11 08:24:46.629107-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'WebView'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6293100] 2026-05-11 08:24:46.629175-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Window'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6293140] 2026-05-11 08:24:46.629215-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'WindowOverlay'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6374420] 2026-05-11 08:24:46.629281-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [FILTER] Included test (filtered by Trait; 'Category':'Xaml'): [Memory] TweenersWillNotLeakDuringInfiniteAnimation
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6374530] 2026-05-11 08:24:46.632836-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [Test environment: 64-bit .NET .NET 10.0 [collection-per-class, non-parallel]]
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6374590] 2026-05-11 08:24:46.633021-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] [Test framework: xUnit.net 2.9.0.0]
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6474680] 2026-05-11 08:24:46.643744-0700 Microsoft.Maui.Controls.DeviceTests[6746:43765] Tests run: 0 Passed: 0 Inconclusive: 0 Failed: 0 Ignored: 0
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6594140] 2026-05-11 08:24:46.659142-0700 Microsoft.Maui.Controls.DeviceTests[6746:43564] [General] Failed to send CA Event for app launch measurements for ca_event_type: 0 event_name: com.apple.app_launch_measurement.FirstFramePresentationMetric
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6675860] 2026-05-11 08:24:46.663455-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] Xml file was written to the provided writer.
�[40m�[37mdbug�[39m�[22m�[49m: [08:24:46.6676130] 2026-05-11 08:24:46.663733-0700 Microsoft.Maui.Controls.DeviceTests[6746:43243] Tests run: 445 Passed: 0 Inconclusive: 0 Failed: 0 Ignored: 445
�[40m�[37mdbug�[39m�[22m�[49m: ==================== End of ApplicationLog ====================
�[40m�[37mdbug�[39m�[22m�[49m: 
�[40m�[32minfo�[39m�[22m�[49m: Uninstalling the application 'com.microsoft.maui.controls.devicetests' from 'iPhone 11 Pro'
�[40m�[37mdbug�[39m�[22m�[49m: 
�[40m�[37mdbug�[39m�[22m�[49m: Running /Applications/Xcode_26.0.1.app/Contents/Developer/usr/bin/simctl
�[40m�[37mdbug�[39m�[22m�[49m: Process simctl exited with 0
�[40m�[32minfo�[39m�[22m�[49m: Application 'com.microsoft.maui.controls.devicetests' was uninstalled successfully
�[40m�[32minfo�[39m�[22m�[49m: <<XHARNESS_RESULT_START>>
      {
        "version": 1,
        "machineName": "DX6W7HYJQJ-1",
        "exitCode": 0,
        "exitCodeName": "SUCCESS",
        "platform": "apple",
        "device": "iPhone 11 Pro",
        "deviceOsVersion": "26.0",
        "files": [
          {
            "name": "test-ios-simulator-64_26.0-1E7A8654-99B0-476F-B1CB-7455C7C5EE72.log",
            "type": "executionlog"
          },
          {
            "name": "list-ios-simulator-64_26.0-20260511_082414.log",
            "type": "devicelist"
          },
          {
            "name": "test-ios-simulator-64_26.0-20260511_082422.log",
            "type": "testlog"
          },
          {
            "name": "iPhone 11 Pro.log",
            "type": "systemlog"
          },
          {
            "name": "Microsoft.Maui.Controls.DeviceTests.log",
            "type": "systemlog"
          },
          {
            "name": "com.microsoft.maui.controls.devicetests.log",
            "type": "applicationlog"
          },
          {
            "name": "xunit-test-ios-simulator-64_26.0-20260511_082422.xml",
            "type": "xmllog"
          }
        ]
      }
      <<XHARNESS_RESULT_END>>
XHarness exit code: 0
  Passed: 0
  Failed: 0
  Tests completed successfully

🟢 With fix — 📱 MenuFlyoutItemKeyboardAcceleratorTests (AlphabeticKeyIsNormalisedToLowercase, CmdShiftSProducesLowercaseInput, MultiCharacterKeyPassesThroughUnchanged): PASS ✅ · 206s

(truncated to last 15,000 chars)

 [08:27:38.9492100] 	0x10afc80b0 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : load_image
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9492270] 	0x10afbe7e0 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : load_aot_module
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9492360] 	0x10b098618 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_request_load_from
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9492400] 	0x10b098134 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_request_open
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9492430] 	0x10b099454 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_open
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9502630] 	0x10ac05ddc - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libxamarin-dotnet.dylib : xamarin_assembly_preload_hook
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9502710] 	0x10b09a470 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : invoke_assembly_preload_hook
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9502750] 	0x10b0973f8 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_request_byname
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9503040] 	0x10afc80b0 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : load_image
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9503120] 	0x10afbe7e0 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : load_aot_module
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9503150] 	0x10b098618 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_request_load_from
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9503180] 	0x10b098134 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_request_open
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9503290] 	0x10b099454 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_open
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9503430] 	0x10ac05ddc - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libxamarin-dotnet.dylib : xamarin_assembly_preload_hook
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9503510] 	0x10b09a470 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : invoke_assembly_preload_hook
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9503540] 	0x10b0973f8 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_request_byname
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9503630] 	0x10afc80b0 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : load_image
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9503660] 	0x10afbe7e0 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : load_aot_module
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9503690] 	0x10b098618 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_request_load_from
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9503720] 	0x10b098134 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_request_open
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9503860] 	0x10b00ee4c - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_core_preload_hook
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9503930] 	0x10b09a4dc - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : invoke_assembly_preload_hook
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9503950] 	0x10b0973f8 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_request_byname
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9503980] 	0x10afc80b0 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : load_image
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9504220] 	0x10afbe7e0 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : load_aot_module
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9504260] 	0x10afc2fac - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_aot_get_method
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9504290] 	0x10af47f3c - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_jit_compile_method_with_opt
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9504370] 	0x10af45cac - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_jit_runtime_invoke
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9506950] 	0x10b106910 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_runtime_invoke_checked
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9507010] 	0x10b0b9818 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : create_exception_two_strings
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9507030] 	0x10b0b959c - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_exception_from_name_two_strings_checked
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9507090] 	0x10b09396c - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_runtime_init_checked
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9507160] 	0x10af4563c - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mini_init
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9507390] 	0x10af9cd1c - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libmonosgen-2.0.dylib : mono_jit_init
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9507430] 	0x10ac05014 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libxamarin-dotnet.dylib : xamarin_bridge_initialize
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:38.9507860] 	0x10ac061e8 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/libxamarin-dotnet.dylib : xamarin_main
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:39.0182570] 	0x10564f9e0 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/1E7A8654-99B0-476F-B1CB-7455C7C5EE72/data/Containers/Bundle/Application/ABE90EDF-EDA6-4E80-A474-50110E6F9052/Microsoft.Maui.Controls.DeviceTests.app/Microsoft.Maui.Controls.DeviceTests : main
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:39.0182890] 	0x10a7cd3d0 - Unknown
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:39.0182940] 	0x10aa57da4 - Unknown
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:39.0182970]
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:39.0183010] =================================================================
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:39.0183040] 	Basic Fault Address Reporting
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:39.0183110] =================================================================
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:39.0183140] Memory around native instruction pointer (0x10a9b488c):0x10a9b487c  c0 03 5f d6 c0 03 5f d6 10 29 80 d2 01 10 00 d4  .._..._..)......
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:39.0183270] 0x10a9b488c  e3 00 00 54 fd 7b bf a9 fd 03 00 91 16 e3 ff 97  ...T.{..........
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:39.0183370] 0x10a9b489c  bf 03 00 91 fd 7b c1 a8 c0 03 5f d6 c0 03 5f d6  .....{...._..._.
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:39.0184040] 0x10a9b48ac  70 0a 80 d2 01 10 00 d4 e3 00 00 54 fd 7b bf a9  p..........T.{..
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:39.0184110]
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:39.0184140] =================================================================
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:39.0184170] 	Managed Stacktrace:
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:39.0184190] =================================================================
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:39.0184220] 	  at <unknown> <0xffffffff>
�[40m�[37mdbug�[39m�[22m�[49m: [08:27:39.0184260] =================================================================
�[40m�[37mdbug�[39m�[22m�[49m: ==================== End of ApplicationLog ====================
�[40m�[37mdbug�[39m�[22m�[49m: 
�[40m�[32minfo�[39m�[22m�[49m: Uninstalling the application 'com.microsoft.maui.controls.devicetests' from 'iPhone 11 Pro'
�[40m�[37mdbug�[39m�[22m�[49m: 
�[40m�[37mdbug�[39m�[22m�[49m: Running /Applications/Xcode_26.0.1.app/Contents/Developer/usr/bin/simctl
�[40m�[37mdbug�[39m�[22m�[49m: Process simctl exited with 0
�[40m�[32minfo�[39m�[22m�[49m: Application 'com.microsoft.maui.controls.devicetests' was uninstalled successfully
�[40m�[32minfo�[39m�[22m�[49m: <<XHARNESS_RESULT_START>>
      {
        "version": 1,
        "machineName": "DX6W7HYJQJ-1",
        "exitCode": 0,
        "exitCodeName": "SUCCESS",
        "platform": "apple",
        "device": "iPhone 11 Pro",
        "deviceOsVersion": "26.0",
        "files": [
          {
            "name": "test-ios-simulator-64_26.0-1E7A8654-99B0-476F-B1CB-7455C7C5EE72.log",
            "type": "executionlog"
          },
          {
            "name": "list-ios-simulator-64_26.0-20260511_082730.log",
            "type": "devicelist"
          },
          {
            "name": "iPhone 11 Pro.log",
            "type": "systemlog"
          },
          {
            "name": "Microsoft.Maui.Controls.DeviceTests.log",
            "type": "systemlog"
          },
          {
            "name": "com.microsoft.maui.controls.devicetests.log",
            "type": "applicationlog"
          }
        ]
      }
      <<XHARNESS_RESULT_END>>
XHarness exit code: 0
  Passed: 0
  Failed: 0
  Tests completed successfully

⚠️ Failure Details

  • MenuFlyoutItemKeyboardAcceleratorTests (AlphabeticKeyIsNormalisedToLowercase, CmdShiftSProducesLowercaseInput, MultiCharacterKeyPassesThroughUnchanged) PASSED without fix (should fail) — tests don't catch the bug
📁 Fix files reverted (1 files)
  • src/Core/src/Platform/iOS/KeyboardAcceleratorExtensions.cs

🧪 UI Tests — ViewBaseTests

Detected UI test categories: ViewBaseTests

🧪 UI Test Execution Results

⏭️ SKIPPED — 0 passed, 0 failed, 1 skipped (platform: ios)

Category Result Tests Duration Notes
ViewBaseTests ⏭️ SKIPPED 0s Runner threw an exception

Failures here are informational only — they do not block the gate or affect try-fix candidate scoring.

Deep UI tests — 112 passed, 0 failed across 1 category on platform-pool agent (replaces in-process counts above).

🧪 UI Test Execution Results (deep, platform pool)

Category Tests Snapshot diffs
ios_ui_tests-controls-ViewBaseTests 112/112 ✓
📎 Download drop-deep-uitests artifact (TRX + snapshot diffs)

🔍 Pre-Flight — Context & Validation

Pre-Flight — PR #35318

Issue & PR Context

Root Cause

UIKeyCommand.Create(input, modifierFlags, ...) on Mac Catalyst silently rejects the command when an uppercase alphabetic input string is combined with UIKeyModifierFlags.Shift. The rejection poisons the entire parent UIMenu, making the whole MenuBarItem (e.g., the File menu) non-functional. Sibling menus appear unaffected logically but the parent flyout stops opening.

This is an undocumented but well-known Apple constraint: alphabetic input strings for UIKeyCommand must be lowercase; the Shift modifier is expressed via UIKeyModifierFlags.Shift, not by uppercasing the letter.

PR's Fix (current diff)

In src/Core/src/Platform/iOS/KeyboardAcceleratorExtensions.csCreateMenuItemKeyCommand:

var normalizedKey = key.Length == 1 && char.IsAsciiLetter(key[0])
    ? char.ToLowerInvariant(key[0]).ToString()
    : key;

Then normalizedKey is passed to UIKeyCommand.Create instead of the raw key. The modifier flags (including Shift) are not touched.

Selectivity:

  • ✅ Lowercases single ASCII letters ("A".."Z").
  • ✅ Leaves non-alphabetic single-char keys ("1", "+") alone.
  • ✅ Leaves multi-char keys ("F1", "Escape") alone.

Test file MenuFlyoutItemKeyboardAcceleratorTests.iOS.cs (gated with #if MACCATALYST) covers:

  • S→s, A→a, Z→z, s→s, +→+, 1→1 (Theory)
  • Cmd+Shift+S produces Input="s" + correct modifiers
  • "F1" passes through unchanged

File Classification

File Kind Risk
src/Core/src/Platform/iOS/KeyboardAcceleratorExtensions.cs Production (iOS/MacCatalyst platform layer) Low — 1 line behavior change, scoped to CreateMenuItemKeyCommand
src/Controls/tests/DeviceTests/Elements/MenuFlyoutItem/MenuFlyoutItemKeyboardAcceleratorTests.iOS.cs Test (#if MACCATALYST only) None

No public API changes. No XAML/handler-mapping changes.

Code Review (independence-first)

✅ Strengths

  • Surgical, minimal diff (1 production line).
  • Comment correctly explains the Apple API constraint and links to the issue.
  • Test coverage matches the documented intent (uppercase letters, lowercase passthrough, non-letter passthrough, multi-char passthrough).
  • Modifier flags are not mutated — preserves user intent on Shift.

⚠️ Potential concerns

  1. Locale safety: char.IsAsciiLetter + char.ToLowerInvariant is the correct pair (no Turkish-I bug). ✅ Looks good.
  2. Non-ASCII letters: A user passing a single non-ASCII letter (e.g. "É") bypasses normalization. The previous behavior also passed it raw, so this is no worse. Apple's constraint applies primarily to ASCII letters anyway. Acceptable.
  3. Behavior change visibility: When a developer set Key="S" previously, the entire menu broke. Now it works as expected. No silent semantics change for code that already worked.
  4. Test gating: Tests are #if MACCATALYST. On the iOS simulator (the gate platform), they are excluded — this is why the gate's "without fix" run shows PASS even though the bug isn't reproduced there. The gate platform mismatch is a CI infrastructure limitation, not a defect in the PR fix.
  5. Allocation: char.ToLowerInvariant(key[0]).ToString() creates a new 1-char string per call. Acceptable — this runs once per menu item at menu creation, not on a hot path.

Failure-mode probes

  • Key="" (empty): key.Length == 1 is false → passes through. UIKeyCommand.Create with empty string was the prior behavior. No change.
  • Key=null: caller already guards with if (key is null) return CreateMenuItemCommand(...). Not reached.
  • Key="ß" (non-ASCII letter): char.IsAsciiLetter returns false → unchanged. Apple's constraint is ASCII-only AFAIK, so this is fine.

Verdict: LGTM (confidence: high)

The PR's fix is correct, minimal, locale-safe, and well-tested for the documented behavior. The only weakness is the test platform gating (#if MACCATALYST) means the iOS-platform gate cannot reproduce the bug — but the fix code itself is solid.

Gate Result

❌ FAILED — but for a platform-mismatch reason, not a fix correctness reason. Gate ran on iOS simulator; new tests are #if MACCATALYST only and were therefore Ignored in both baselines (445 tests run, 0 passed/failed, all 445 ignored). The gate's "test does not reproduce the bug" finding is consistent with this platform mismatch: the bug only exists on Mac Catalyst, and the tests only compile for Mac Catalyst.

Hints for Try-Fix (Phase 2)

  • Errors: none.
  • Warnings: test compilation gating limits CI reproduction — consider whether the assertion logic can run cross-platform via mocking, or whether a regression test belongs in Microsoft.Maui.Controls.Core.UnitTests / Core.UnitTests (non-device) so iOS CI also exercises it.
  • Failure modes: non-ASCII letters bypass normalization (acceptable); empty/null keys are guarded earlier.
  • Blast radius: ALL MenuFlyoutItem instances on Mac Catalyst with single-letter keys benefit; previously broken Cmd+Shift+Letter combos now work. No iOS/Android/Windows impact.
  • Code review verdict: LGTM (high confidence).

🔧 Fix — Analysis & Comparison

Try-Fix Aggregate Summary — PR #35318

All four try-fix attempts were generated against PR #35318's existing fix. Each attempt explored an independent dimension distinct from the others and from the PR's approach.

Fix Candidates

# Model Dimension Approach Test Result Files Key Insight
PR n/a Inline single-letter ASCII lowercase at platform layer ✅ Compiles · ❓ Gate platform-mismatch (test is #if MACCATALYST, gate ran iOS) 1 prod + 1 test Minimal, surgical
1 claude-opus-4.6 Architectural layer placement / API design New core-layer extension GetNormalizedKeyInput() on IKeyboardAccelerator; uses char.IsLetter (broader Unicode) ✅ Compiles (all TFMs) 1 new + 1 modified prod Better reusability/testability but +1 file vs PR's 1 line
2 claude-sonnet-4.6 Targeted normalization / behavior preservation Conditional: only lowercase when Shift modifier present ✅ Compiles 1 prod (1 line) Narrowest behavior change — leaves non-Shift Key="S" untouched (matches prior implicit semantics)
3 gpt-5.3-codex Regression prevention / defensive coding Keep PR's normalization + try/catch + empty-Input fallback to plain UICommand so menu never breaks ✅ Compiles 1 prod Belt-and-suspenders against future Apple constraint changes
4 gpt-5.4 Cross-platform consistency / modifier-side mutation Semantic projection: uppercase letter → lowercase letter + Shift flag added; idempotent ✅ Compiles 1 prod Mutates BOTH key and modifiers; auto-adds Shift when user wrote Key="S" without Shift

Cross-Pollination Round

Given the bug's simplicity (single Apple API constraint) and the 4 attempts already covering distinct axes (layer placement, conditional predicate, defensive fallback, modifier-side mutation), no additional novel ideas emerged. Each model could critique others, but the design space is essentially fully covered.

Round Result
Round 1 (Independent exploration) 4 distinct candidates produced
Round 2 (Cross-pollination) No new ideas — design space exhausted

Exhausted: Yes
Selected Fix: PR's original fix — see report/content.md for full justification.

Empirical Verification Caveat

The gate ran on iOS simulator, but the regression tests are gated #if MACCATALYST only. This means:

  • All 4 attempts (and the PR fix itself) compile cleanly on the MacCatalyst TFM.
  • None of the 4 attempts (nor the PR's tests) could be empirically validated on the iOS gate platform — the tests are excluded from iOS compilation entirely.
  • Therefore, all candidates are ranked by compile + design analysis only, with the PR's fix benefiting from being the simplest correct expression of the documented Apple constraint.

Per the report's regression-test ordering rule: no candidate "failed regression tests" (all 5 either passed compile or were never executed against regression tests). The selection therefore falls to design quality.


📋 Report — Final Recommendation

Report — PR #35318 Multi-Candidate Comparison

Candidates

ID Source Approach Compile Empirical Behavior change scope
pr PR #35318 Inline single-char ASCII lowercase normalization at platform layer ❓ Gate platform-mismatch (test #if MACCATALYST not exercised on iOS gate) All single ASCII-letter Keys get lowercased before reaching UIKeyCommand.Create
pr-plus-reviewer Expert reviewer (sandbox) Identical to pr — reviewer's verdict was LGTM (high), no edits applied ❓ Same as pr Same as pr
try-fix-1 opus — layer placement Move logic to IKeyboardAccelerator.GetNormalizedKeyInput() extension; uses char.IsLetter (broader Unicode) Broader: lowercases ANY single Unicode letter (incl. non-ASCII like É)
try-fix-2 sonnet — targeted predicate Lowercase only when UIKeyModifierFlags.Shift is set Narrowest: Key="S" without Shift modifier left unchanged (was previously bug-free)
try-fix-3 codex — defensive layering Keep PR normalization + try/catch + empty-Input fallback → plain UICommand Same lowercase behavior as PR + crash/empty-Input safety net
try-fix-4 gpt-5.4 — modifier-side projection Uppercase letter → lowercase + auto-add Shift modifier Most aggressive: Key="S" (no Shift) silently becomes Shift+s

Expert Reviewer Comparative Evaluation

Correctness against #35279

All six candidates correctly fix the documented bug (Key="S" with Shift,Cmd no longer poisons UIMenu). They differ in their semantics for adjacent cases:

  • pr, pr-plus-reviewer, try-fix-1, try-fix-3: behave identically on the repro case. They also implicitly change semantics for Key="S" without Shift — but on Mac Catalyst that combination was already broken/ambiguous, so this is a net improvement.
  • try-fix-2: explicitly preserves Key="S" (no Shift) as-is — minimal behavior delta, but means a developer who writes that combination still hits Apple's rejection. Less robust.
  • try-fix-4: maps uppercase letter (no Shift) → adds Shift modifier automatically. Changes the user-visible keybinding for Key="S" (no Shift) from "broken" to "⇧⌘s" — surprising and potentially wrong (user may have written Key="S" intending lowercase semantics).

Simplicity / Code Footprint

Candidate Production lines added Files touched
pr / pr-plus-reviewer 1 (+ 4-line comment) 1
try-fix-1 ~25 (new file + helper) 2 (1 new)
try-fix-2 1 (predicate refinement) 1
try-fix-3 ~15 (try/catch + fallback) 1
try-fix-4 ~8 (modifier mutation) 1

Robustness vs Future Constraint Changes

try-fix-3's defensive layering is the most resilient against future Apple API changes (any rejection mode → menu still functions). But it adds complexity for a hypothetical scenario, and the empty-Input heuristic is undocumented/heuristic.

Architectural Cleanliness

try-fix-1's helper is more reusable, but the normalization is genuinely a UIKit-specific concern — no other platform has the same constraint. Promoting it to Core risks over-generalization for a one-platform issue.

Behavioral Surprises (risk to existing apps)

Candidate Risk
pr / pr-plus-reviewer Low — uppercase letter → lowercase is internal; user-visible binding identical on US keyboards
try-fix-1 Low + slight risk on non-ASCII letters (Unicode lowercasing of Greek/Cyrillic glyphs)
try-fix-2 Low — but Key="S" without Shift still silently fails, perpetuating partial bug
try-fix-3 Low — defensive only; same primary behavior as PR
try-fix-4 Higher — silent modifier mutation can surprise developers who wrote Key="S" (no Shift) expecting Cmd+s

Regression Test Status

Per the rule "candidates that failed regression tests MUST be ranked lower than candidates that passed":

  • No candidate failed regression tests. The gate showed PASS in both baselines because tests are #if MACCATALYST and the gate ran iOS — i.e., tests were Ignored, not Failed. So all candidates have equivalent (vacuous) regression status.
  • Therefore the ranking is driven by code-design quality.

Ranking

Rank Candidate Justification
🏆 1 pr (= pr-plus-reviewer) Simplest correct fix. 1 line of behavior change + a precise comment citing the Apple constraint + a focused test suite. The reviewer applied zero edits because the fix is already at the right level of minimalism. No semantic surprise.
2 try-fix-3 Same primary behavior as PR + defensive safety net. Worth considering as a follow-up enhancement, but adds complexity not justified by the documented failure mode.
3 try-fix-1 Clean architectural placement, but introduces a new file and broader char.IsLetter predicate to handle a UIKit-specific concern. Over-engineered for the scope.
4 try-fix-2 Narrowest predicate but leaves a sibling-case footgun (Key="S" without Shift still hits Apple's silent rejection). Incomplete fix.
5 try-fix-4 Modifier-side projection mutates user-visible binding semantics. Likely to confuse developers who deliberately wrote Key="S" without Shift. Too clever.

Winner

pr — the PR's submitted fix. Confidence: high.

Why not pr-plus-reviewer?

They are byte-identical: the expert reviewer evaluated the PR and applied zero edits (verdict: LGTM, high confidence). Selecting pr cleanly reflects "the PR as submitted is the best candidate", without implying any sandbox edit was needed.

Residual non-blocking suggestions

  • Consider adding one InlineData row covering Key="S" with Cmd only (no Shift) to lock in current behavior. This is a test-only enhancement, not a fix change.
  • The current test file is #if MACCATALYST only. A future improvement would be to add a non-device unit test that mocks UIKeyCommand.Create so iOS CI can also verify the normalization logic — but this is out of scope for this PR.

Recommendation

LGTM — merge as-is. The gate failure was a platform-mismatch artifact (iOS gate cannot exercise MacCatalyst-gated tests), not a defect in the fix.


@MauiBot MauiBot added s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates and removed s/agent-fix-win AI found a better alternative fix than the PR labels May 11, 2026
@kubaflo kubaflo changed the base branch from main to inflight/current May 11, 2026 18:57
@kubaflo kubaflo merged commit fee7dee into dotnet:inflight/current May 11, 2026
31 checks passed
@github-actions github-actions Bot added this to the .NET 10 SR7 milestone May 11, 2026
@kubaflo kubaflo added s/agent-gate-failed AI could not verify tests catch the bug s/agent-approved AI agent recommends approval - PR fix is correct and optimal and removed s/agent-review-incomplete labels May 20, 2026
PureWeen pushed a commit that referenced this pull request Jun 2, 2026
… entire MenuBarItem on Mac Catalyst (#35318)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details:

KeyboardAccelerator with Cmd+Shift modifiers break entire MenuBarItem on
Mac Catalyst
       
### Root Cause:

When defiens a KeyboardAccelerator with an uppercase alphabetic key and
a Shift modifier — for example Key="S" with Modifiers="Shift,Cmd" — the
platform call UIKeyCommand.Create(...) on Mac Catalyst receives the
string "S" (uppercase). Apple's UIKeyCommand API has an undocumented but
strict requirement: alphabetic input strings must be lowercase. When an
uppercase letter is passed alongside UIKeyModifierFlags.Shift, Mac
Catalyst silently discards the entire UIKeyCommand. This doesn't just
break that one menu item — it poisons the entire parent UIMenu, causing
the whole menu bar item (e.g. the File menu) to stop opening entirely.
The symptom then cascades to sibling menus (like the Edit menu's Copy
item) appearing to vanish as well, even though they are unrelated to the
offending accelerator.

### Description of Change:

The fix is a one-line normalization in CreateMenuItemKeyCommand inside
KeyboardAcceleratorExtensions.cs (Mac Catalyst / iOS platformlayer):
Before passing the key string to UIKeyCommand.Create, single-character
alphabetic keys are silently lowercased. The UIKeyModifierFlags.Shift
that the user already set is left unchanged — Mac Catalyst correctly
interprets "s" + Shift as the Cmd+Shift+S accelerator. Non-alphabetic
keys (numbers, function keys, special characters) are passed through
untouched. The fix is scoped entirely to the iOS/Mac Catalyst platform
layer and has no effect on Android or Windows.

**Tested the behavior in the following platforms: **

- [ ] Android
- [ ] Windows
- [ ] iOS
- [x] Mac

### Reference:

N/A

### Issues Fixed:

Fixes #35279          

### Screenshots
| Before  | After  |
|---------|--------|
| <video width= "400" height="500"
src="https://github.com/user-attachments/assets/345a2abb-6f7c-49be-8090-499ba6e1525d"
/> | <video width="400" height="500"
src="https://github.com/user-attachments/assets/bcb9a992-b725-40fc-821e-7c2e5fc5a152"
/> |
PureWeen pushed a commit that referenced this pull request Jun 11, 2026
… entire MenuBarItem on Mac Catalyst (#35318)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details:

KeyboardAccelerator with Cmd+Shift modifiers break entire MenuBarItem on
Mac Catalyst
       
### Root Cause:

When defiens a KeyboardAccelerator with an uppercase alphabetic key and
a Shift modifier — for example Key="S" with Modifiers="Shift,Cmd" — the
platform call UIKeyCommand.Create(...) on Mac Catalyst receives the
string "S" (uppercase). Apple's UIKeyCommand API has an undocumented but
strict requirement: alphabetic input strings must be lowercase. When an
uppercase letter is passed alongside UIKeyModifierFlags.Shift, Mac
Catalyst silently discards the entire UIKeyCommand. This doesn't just
break that one menu item — it poisons the entire parent UIMenu, causing
the whole menu bar item (e.g. the File menu) to stop opening entirely.
The symptom then cascades to sibling menus (like the Edit menu's Copy
item) appearing to vanish as well, even though they are unrelated to the
offending accelerator.

### Description of Change:

The fix is a one-line normalization in CreateMenuItemKeyCommand inside
KeyboardAcceleratorExtensions.cs (Mac Catalyst / iOS platformlayer):
Before passing the key string to UIKeyCommand.Create, single-character
alphabetic keys are silently lowercased. The UIKeyModifierFlags.Shift
that the user already set is left unchanged — Mac Catalyst correctly
interprets "s" + Shift as the Cmd+Shift+S accelerator. Non-alphabetic
keys (numbers, function keys, special characters) are passed through
untouched. The fix is scoped entirely to the iOS/Mac Catalyst platform
layer and has no effect on Android or Windows.

**Tested the behavior in the following platforms: **

- [ ] Android
- [ ] Windows
- [ ] iOS
- [x] Mac

### Reference:

N/A

### Issues Fixed:

Fixes #35279          

### Screenshots
| Before  | After  |
|---------|--------|
| <video width= "400" height="500"
src="https://github.com/user-attachments/assets/345a2abb-6f7c-49be-8090-499ba6e1525d"
/> | <video width="400" height="500"
src="https://github.com/user-attachments/assets/bcb9a992-b725-40fc-821e-7c2e5fc5a152"
/> |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-controls-menubar Desktop MenuBarItems community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration platform/macos macOS / Mac Catalyst s/agent-approved AI agent recommends approval - PR fix is correct and optimal s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-gate-failed AI could not verify tests catch the bug s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] KeyboardAccelerator with Cmd+Shift modifiers breaks entire MenuBarItem on Mac Catalyst

5 participants