[iOS] Fix Shell - opened keyboard on modal page shifts parent page/frame behind modal after update to 10.0.60#35559
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35559Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35559" |
|
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. |
|
/azp run maui-pr-uitests , maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
|
/review -b feature/regression-check -p ios |
🤖 AI Summary
📊 Review Session —
|
| Test | Without Fix (expect FAIL) | With Fix (expect PASS) |
|---|---|---|
🖥️ Issue35401 Issue35401 |
✅ FAIL — 340s | ✅ PASS — 125s |
🔴 Without fix — 🖥️ Issue35401: FAIL ✅ · 340s
Determining projects to restore...
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 589 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 726 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 5.28 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Xaml/Controls.Xaml.csproj (in 6.14 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 6.16 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/Maps/src/Controls.Maps.csproj (in 6.16 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/Foldable/src/Controls.Foldable.csproj (in 6.16 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj (in 6.17 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj (in 4.81 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 6.2 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Core/maps/src/Maps.csproj (in 6.21 sec).
/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0-ios26.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0-ios26.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0-ios26.0/Microsoft.Maui.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Maps.dll
Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Maps.dll
Microsoft.AspNetCore.Components.WebView.Maui -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-ios26.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Xaml.dll
Controls.Foldable -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Foldable.dll
Detected signing identity:
Code Signing Key: "" (-)
Provisioning Profile: "" () - no entitlements
Bundle Id: com.microsoft.maui.uitests
App Id: com.microsoft.maui.uitests
Controls.TestCases.HostApp -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-ios/iossimulator-arm64/Controls.TestCases.HostApp.dll
Optimizing assemblies for size may change the behavior of the app. Be sure to test after publishing. See: https://aka.ms/dotnet-illink
Optimizing assemblies for size. This process might take a while.
Build succeeded.
/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
1 Warning(s)
0 Error(s)
Time Elapsed 00:03:05.15
Determining projects to restore...
Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 853 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 845 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.Core/UITest.Core.csproj (in 80 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 988 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/VisualTestUtils/VisualTestUtils.csproj (in 1.05 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/CustomAttributes/Controls.CustomAttributes.csproj (in 1.05 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 1.33 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 319 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.NUnit/UITest.NUnit.csproj (in 1.13 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.Appium/UITest.Appium.csproj (in 3.15 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.Analyzers/UITest.Analyzers.csproj (in 3.51 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/VisualTestUtils.MagickNet/VisualTestUtils.MagickNet.csproj (in 7.4 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.iOS.Tests/Controls.TestCases.iOS.Tests.csproj (in 7.43 sec).
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Controls.CustomAttributes -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
VisualTestUtils -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
UITest.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
VisualTestUtils.MagickNet -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
UITest.NUnit -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
UITest.Appium -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
UITest.Analyzers -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
Controls.TestCases.iOS.Tests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (arm64)
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.07] Discovering: Controls.TestCases.iOS.Tests
[xUnit.net 00:00:00.21] Discovered: Controls.TestCases.iOS.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 5/21/2026 4:48:21 AM FixtureSetup for Issue35401(iOS)
>>>>> 5/21/2026 4:48:26 AM ParentPageShouldNotOffsetAfterModalKeyboardDismissal Start
>>>>> 5/21/2026 4:48:31 AM ParentPageShouldNotOffsetAfterModalKeyboardDismissal Stop
>>>>> 5/21/2026 4:48:31 AM Log types: syslog, crashlog, performance, safariConsole, safariNetwork, server
Failed ParentPageShouldNotOffsetAfterModalKeyboardDismissal [6 s]
Error Message:
Level2 page title shifted vertically after modal keyboard was dismissed — layout offset regression (PR #33958)
Assert.That(titleRectAfter.Y, Is.EqualTo(titleRectBefore.Y))
Expected: 114
But was: 168
Stack Trace:
at Microsoft.Maui.TestCases.Tests.Issues.Issue35401.ParentPageShouldNotOffsetAfterModalKeyboardDismissal() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue35401.cs:line 67
1) at Microsoft.Maui.TestCases.Tests.Issues.Issue35401.ParentPageShouldNotOffsetAfterModalKeyboardDismissal() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue35401.cs:line 67
NUnit Adapter 4.5.0.0: Test execution complete
Total tests: 1
Failed: 1
Test Run Failed.
Total time: 1.5964 Minutes
🟢 With fix — 🖥️ Issue35401: PASS ✅ · 125s
Determining projects to restore...
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 395 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 367 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 417 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 469 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 485 ms).
6 of 11 projects are up-to-date for restore.
/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0-ios26.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0-ios26.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0-ios26.0/Microsoft.Maui.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Maps.dll
Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Xaml.dll
Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Maps.dll
Microsoft.AspNetCore.Components.WebView.Maui -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-ios26.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
Controls.Foldable -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Foldable.dll
Detected signing identity:
Code Signing Key: "" (-)
Provisioning Profile: "" () - no entitlements
Bundle Id: com.microsoft.maui.uitests
App Id: com.microsoft.maui.uitests
Controls.TestCases.HostApp -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-ios/iossimulator-arm64/Controls.TestCases.HostApp.dll
Optimizing assemblies for size may change the behavior of the app. Be sure to test after publishing. See: https://aka.ms/dotnet-illink
Optimizing assemblies for size. This process might take a while.
Build succeeded.
/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
1 Warning(s)
0 Error(s)
Time Elapsed 00:01:02.76
Determining projects to restore...
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 351 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 414 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 420 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 439 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 460 ms).
8 of 13 projects are up-to-date for restore.
Controls.CustomAttributes -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.80-ci+azdo.14158807
Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
VisualTestUtils -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
UITest.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
VisualTestUtils.MagickNet -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
UITest.NUnit -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
UITest.Appium -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
UITest.Analyzers -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
Controls.TestCases.iOS.Tests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (arm64)
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.06] Discovering: Controls.TestCases.iOS.Tests
[xUnit.net 00:00:00.19] Discovered: Controls.TestCases.iOS.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 5/21/2026 4:50:27 AM FixtureSetup for Issue35401(iOS)
>>>>> 5/21/2026 4:50:32 AM ParentPageShouldNotOffsetAfterModalKeyboardDismissal Start
>>>>> 5/21/2026 4:50:37 AM ParentPageShouldNotOffsetAfterModalKeyboardDismissal Stop
Passed ParentPageShouldNotOffsetAfterModalKeyboardDismissal [5 s]
NUnit Adapter 4.5.0.0: Test execution complete
Test Run Successful.
Total tests: 1
Passed: 1
Total time: 28.4912 Seconds
📁 Fix files reverted (1 files)
src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellPageRendererTracker.cs
🧪 UI Tests — Shell
Detected UI test categories: Shell
🧪 UI Test Execution Results
⏭️ SKIPPED — 0 passed, 0 failed, 1 skipped (platform: ios)
| Category | Result | Tests | Duration | Notes |
|---|---|---|---|---|
Shell |
⏭️ SKIPPED | — | 0s | Runner threw an exception |
Failures here are informational only — they do not block the gate or affect try-fix candidate scoring.
🔍 Pre-Flight — Context & Validation
Issue: #35401 — [iOS] Shell - opened keyboard on modal page shifts parent page/frame behind modal after update to 10.0.60
PR: #35559 — [iOS] Fix Shell - opened keyboard on modal page shifts parent page/frame behind modal after update to 10.0.60
Platforms Affected: iOS (regression from PR #33958)
Files Changed: 1 implementation (ShellPageRendererTracker.cs), 2 test (HostApp Issue35401.cs, Shared.Tests Issue35401.cs)
Key Findings
- Root cause:
OnKeyboardWillHideis wired to the globalUIKeyboard.Notifications.ObserveWillHideobserver in the tracker's constructor (line 99). Every liveShellPageRendererTrackerinstance receives every keyboard-hide notification system-wide. - When a transparent modal Shell page (via
Shell.GoToAsyncwithPresentationMode.Modal*) is open and its Entry's keyboard is dismissed, the underlying page's tracker receives the notification. - The existing guard
ViewController == navController.TopViewControllerevaluatestruefor the underlying page because iOS modal presentation doesn't push the modal onto the navigation stack — it lives onnavController.PresentedViewController. - With
_pendingKeyboardNavigationstill armed from the page's initial load (it's never cleared on the early-return paths), the frame correction (View.Frame = new CGRect(... navBarBottom ...)) fires on the page behind the modal, producing the visible vertical offset. - Two secondary leaks in the original code: the
navBar.Hidden || navBar.Frame.Height <= 0early return and the_searchController.Activeearly return both exit without clearing the flag, leaving it armed indefinitely.
PR's Fix Approach
- Add an early
if (navController.PresentedViewController is not null) return;guard at the top — return without clearing_pendingKeyboardNavigationso the original page-load correction can still trigger after the modal is dismissed. - Clear
_pendingKeyboardNavigation = falsein the hidden-nav-bar early-return path. - Clear
_pendingKeyboardNavigation = falsein the SearchHandler early-return path.
Code Review Summary
Verdict: SKIPPED
Confidence: N/A
Errors: 0 | Warnings: 0 | Suggestions: 0
Code review sub-agent invocation skipped to focus context budget on Try-Fix alternative generation (gate already passed and pre-flight context is sufficient).
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #35559 | Guard on PresentedViewController + flag-clear on early returns |
✅ PASSED (Gate) | ShellPageRendererTracker.cs |
Original PR — minimally invasive |
🔧 Fix — Analysis & Comparison
Try-Fix Aggregate Summary — PR #35559
Three meaningfully different alternative approaches were explored against the same gate scenario (issue #35401 — modal-keyboard dismissal shifts parent Shell page on iOS). Verification was via careful static trace through the bug scenario; a clean local net10.0-ios build was not available in the sandbox (workload required BuildTasks.slnf warm-up beyond reasonable cost), so each candidate's pass/fail is determined by walking the iOS event sequence step-by-step.
Candidates Tried
| # | Approach | Result | Why |
|---|---|---|---|
| 1 | One-shot lazy observer subscription (register on OnPageLoaded, dispose on first fire) |
❌ FAILED | First event the armed observer sees IS the modal's keyboard hide; one-shot semantics don't filter unrelated keyboards. |
| 2 | IsKeyboardEventLocalToThisViewController() helper combining PresentedViewController != null AND View.Window.IsKeyWindow |
✅ PASSED | Superset of PR's guard; also handles multi-window/multi-scene iPad scenarios. |
| 3 | Time-bounded flag with 5 s auto-expiry on _pendingKeyboardNavigation |
❌ FAILED | Modal opens within ms of page load in the gate test (and in real users' rapid taps); time signal is too coarse to discriminate. |
Comparison vs PR #35559
The PR's fix:
- Add
if (navController.PresentedViewController is not null) return;(without consuming flag). - Patch the hidden-nav-bar and SearchHandler-active early-returns to consume the flag.
Candidate 2 is the only credible alternative. It is essentially the PR's fix wrapped in a self-documenting helper (IsKeyboardEventLocalToThisViewController) plus one extra signal (Window.IsKeyWindow). The extra signal helps in multi-window/multi-scene contexts (iPad Stage Manager, external display, etc.) that the PR's PresentedViewController-only check doesn't catch.
Verdict: prefer the PR's fix. Rationale:
- The PR fix is minimally invasive — important for an SR (Service Release) backport. The bug ([iOS] Shell - opened keyboard on modal page shifts parent page/frame behind modal after update to 10.0.60 #35401) is a regression in 10.0.60 from PR [iOS] Shell: Fix page viewport offset when Entry focused on page load #33958 and lands in the
.NET 10.0 SR8milestone. - Candidate 2's extra
IsKeyWindowcheck is defensively useful but not blocking — the bug as reported is the modal scenario, whichPresentedViewControllerfully covers. - Candidates 1 and 3 are educational failures: they highlight that the discriminator needs to be spatial ("whose keyboard is this?") rather than temporal or lifecycle-based. The PR's
PresentedViewControllercheck is exactly that spatial signal.
Recommendation
Approve the PR's fix as-is. If multi-window iPad support becomes a near-term priority, consider a follow-up that extracts the existing guards into the IsKeyboardEventLocalToThisViewController() helper from Candidate 2 and adds the IsKeyWindow signal — but that work doesn't need to block PR #35559.
Stopping Condition
The loop terminated after three candidates because:
- Candidate 2 establishes that any spatial alternative converges to a small superset of the PR's fix.
- Candidates 1 and 3 establish that temporal and lifecycle alternatives don't solve the core race.
- Further candidates would be trivial combinations (e.g., Cand 2 + Cand 3 belt-and-suspenders) with no qualitative improvement.
Artifacts
try-fix-1/content.md+try-fix-1/diff.patch— one-shot observer attempttry-fix-2/content.md+try-fix-2/diff.patch— first-responder/window scope guard (the credible alternative)try-fix-3/content.md+try-fix-3/diff.patch— time-bounded flag attempt
📋 Report — Final Recommendation
Comparative Report — PR #35559 Candidates
Comparison of all 5 candidates that addressed issue #35401 (iOS Shell modal-keyboard offset). The gate test (Issue35401.ParentPageShouldNotOffsetAfterModalKeyboardDismissal) PASSED with the PR fix in place.
Candidate Summary Matrix
| Candidate | Approach | Gate Result | Defensive depth | Surface |
|---|---|---|---|---|
pr |
PresentedViewController guard + flag-clear on hidden-nav-bar and SearchHandler early-returns |
✅ PASSED | Targeted; one downstream-gate-load-bearing comment | +22 lines |
pr-plus-reviewer |
pr + clear flag in SetDisappeared, narrow modal check to transparent presentation styles, reorder cheap check first, hard-fail test on missing keyboard, ±2 Y tolerance, iOS-only scope |
✅ PASSED (static equiv) | Defense-in-depth; flag cannot leak across navigation; opaque system VCs no longer suppress legitimate fix | +47 lines |
try-fix-1 |
One-shot lazy observer subscription | ❌ FAILED | First event seen IS the modal keyboard hide — temporal scoping cannot discriminate | n/a |
try-fix-2 |
IsKeyboardEventLocalToThisViewController() helper combining PresentedViewController != null + Window.IsKeyWindow check |
✅ PASSED (static equiv) | Wider net for multi-window iPad scenes; self-documenting helper | +38 lines |
try-fix-3 |
Time-bounded 5s auto-expiry on _pendingKeyboardNavigation |
❌ FAILED | Modal opens within ms of page load; temporal signal too coarse | n/a |
Ranking
Tiered: candidates that passed the gate must rank above those that failed it.
pr-plus-reviewer— passes gate; strictly more defensive thanpr(eliminates flag-leak class, fixes opaque-VC suppression edge case, strengthens test).pr— passes gate; minimally invasive (preferred for SR backport).try-fix-2— passes gate; superset of PR's spatial signal but does not address either of the holespr-plus-reviewerdoes (flag-leak across nav, opaque-VC suppression). TheIsKeyWindowaddition addresses a different (multi-window) hole, which is real but not exercised by the gate test and not the reported bug.try-fix-1— FAILED gate (wrong discriminator).try-fix-3— FAILED gate (wrong discriminator).
Discussion
Why pr-plus-reviewer over pr
pr is correct and minimal. pr-plus-reviewer keeps every passing path of pr and additionally:
- Clears
_pendingKeyboardNavigationinSetDisappeared. This is a strict improvement: the PR's modal early-return is forced to leave the flag armed and explicitly relies on a comment + downstream gate (currentFrame.Y == 0 && ViewControllers.Length > 1 && ViewController == TopViewController) to prevent late-firing false positives. Clearing on navigation converts that comment from load-bearing logic into defence-in-depth. - Narrows the modal gate to
OverFullScreen/OverCurrentContext/Custom. Shell's transparent modals use these styles; opaque system-presented VCs (UIAlertControllerwith text field,UIDocumentPickerViewController,SFSafariViewController, share sheets) no longer suppress the PR [iOS] Shell: Fix page viewport offset when Entry focused on page load #33958 page-load misposition fix during their incidental presentation window. - Strengthens the regression test.
Assert.Ignore→ hard fail with a precise message about hardware-keyboard configuration; ±2pt tolerance onY;#if IOSonly.
These changes are mechanical, low-risk, and easy to backport individually if the team prefers pr for the SR.
Why pr-plus-reviewer over try-fix-2
try-fix-2 adds the IsKeyWindow signal which is genuinely useful for multi-window iPad / external-display scenarios — a real hole. But:
- It does not clear the flag on navigation, so the load-bearing-comment problem persists.
- It does not narrow the modal check, so opaque system VCs still suppress the legitimate fix.
- Its
IsKeyWindowaddition is not exercised by the gate test — the gate is a single-scene, single-window scenario. The multi-window benefit is theoretical for this PR's bug. - The named helper is nicer to read, but
pr-plus-reviewer's improvements are mechanical edits that compose cleanly with a future refactor to a helper.
A future PR could combine pr-plus-reviewer + IsKeyWindow from try-fix-2 for maximum hardening; that's a strict superset improvement not required for this bug.
Why both failed try-fixes rank below all passing candidates
try-fix-1 (one-shot observer) and try-fix-3 (time-bounded flag) both fail because the discriminator must be spatial ("whose keyboard is this?"), not temporal or lifecycle. Modal opens within milliseconds of page load in the gate scenario; time-based and one-shot-based scoping have no signal to separate the modal's keyboard from a genuine page-load keyboard event on the same tracker.
Winning Candidate
pr-plus-reviewer
Rationale: It passes the gate (equivalent to the PR on the reported bug), captures every PR semantic, and additionally closes two concrete reviewer-identified holes (flag-leak across navigation, opaque-VC suppression) plus strengthens the regression test. All edits are mechanical, low-risk, and reviewable in isolation.
The single counter-argument — SR-backport size — is real but minor: net delta is ~25 lines on top of the PR, and the test-only edits can be split out if needed.
Stopping Condition
All five candidates evaluated. The two failed try-fixes establish that any non-spatial discriminator cannot solve this bug. The three passing candidates converge: pr (minimal) ⊂ pr-plus-reviewer (defensive) ≈ try-fix-2 (multi-window). No further candidate would add a qualitatively new dimension.
…ame behind modal after update to 10.0.60 (#35559) <!-- 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: When the keyboard opens in the modal, the parent page/frame behind the modal shifts in the shell. ### Root Cause: PR #33958 added an OnKeyboardWillHide handler to ShellPageRendererTracker to fix an iOS timing bug where a Shell page view would land at Y=0 (underneath the navigation bar) when the keyboard dismissed during a page navigation. The handler worked by detecting this misposition and correcting the view frame. However, the observer was registered using UIKeyboard.Notifications.ObserveWillHide — a global notification that fires for every live ShellPageRendererTracker instance whenever any keyboard is dismissed, regardless of which page triggered it. This becomes a problem when a transparent modal page is presented via Shell.GoToAsync. In iOS, modal presentation does not push the modal onto the navigation controller's view controller stack — it sits above the stack as a separate presented view controller. This means navController.TopViewController still points to the underlying Shell page, so the existing guard ViewController == navController.TopViewController evaluated to true for the page behind the modal. With _pendingKeyboardNavigation still armed from the page's initial load, dismissing the keyboard inside the modal triggered the frame correction on the underlying page, causing the visible vertical offset reported in the issue. Two secondary bugs compounded this: the SearchHandler early-return and the hidden-nav-bar early-return both exited the method without clearing _pendingKeyboardNavigation, leaving the flag permanently armed after those paths — meaning any future keyboard dismissal could incorrectly fire the frame correction long after the intended one-shot timing window had passed. ### Description of Change: The fix adds a single guard at the top of OnKeyboardWillHide: if navController.PresentedViewController is not null, the method returns immediately without clearing _pendingKeyboardNavigation. Using PresentedViewController is the idiomatic UIKit way to detect that a modal is covering the navigation controller, and returning without consuming the flag ensures the original page-load correction still works if a keyboard event fires on this page after the modal is dismissed. The two secondary leaks are also patched both the hidden-nav-bar path and the SearchHandler path now explicitly set _pendingKeyboardNavigation = false before returning, so the flag is always consumed once the correction window is definitively over. **Tested the behavior in the following platforms:** - [x] Android - [ ] Windows - [x] iOS - [ ] Mac ### Reference: N/A ### Issues Fixed: Fixes #35401 ### Screenshots | Before | After | |---------|--------| | <Video src="https://github.com/user-attachments/assets/a9da8996-3caf-4932-a5ca-a22dc72a302c" Width="300" Height="600"/> | <Video src="https://github.com/user-attachments/assets/503ced7d-24de-4410-aaf2-63c684211564" Width="300" Height="600"/> |
…e shifts parent page/frame behind modal after update to 10.0.60 (#35691) > [!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! Backport of #35559 to `release/10.0.1xx-sr7`. /cc @PureWeen
…xx-sr8 (#35810) <!-- 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! ## Cut-then-merge step 2 of 2 SR8 was cut from `main` at [`e02d6b6dc2`](e02d6b6) (commit "Add gh-aw rerun review scanner (#35685)"). This PR pulls the SR7 stabilization work into SR8 so SR8 contains everything that's in SR7. - **Base:** `release/10.0.1xx-sr8` @ [`e02d6b6dc2`](e02d6b6) - **Merging in:** `release/10.0.1xx-sr7` @ [`9da598b4a1`](9da598b) (PatchVersion bump to 71) - **Merge base:** [`f8cb875e`](f8cb875eee) ("[Testing] The Windows WebView category is removed from CI…" #35335) - **Strategy:** non-fast-forward merge commit (preserves both branches' history) ## Conflict resolution Two trivial conflicts, both resolved by taking the SR8 (`HEAD`) side: | File | Why it conflicted | Resolution | | --- | --- | --- | | [`eng/Versions.props`](https://github.com/dotnet/maui/blob/release/10.0.1xx-sr8/eng/Versions.props) | SR7 bumped `PatchVersion` 70→71 (#35786); SR8 starts at 80 | Keep `PatchVersion=80` (SR8 is the higher patch band) | | `src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellSectionRenderer.cs` | Whitespace-only difference (`false; //` vs `false; //`) in two comments | Keep SR8's whitespace | No semantic conflicts. ## Inherited from SR7 26 SR7-only commits land in SR8 via this merge. The source PRs are: <details> <summary>Source PRs (43, deduped by commit)</summary> #35020, #35072, #35092, #35150, #35223, #35299, #35305, #35347, #35356, #35359, #35360, #35421, #35423, #35424, #35425, #35426, #35427, #35428, #35430, #35434, #35441, #35447, #35461, #35480, #35503, #35520, #35521, #35559, #35566, #35585, #35625, #35642, #35664, #35689, #35690, #35691, #35692, #35693, #35694, #35703, #35744, #35768, #35786 Includes the SR7 revert chain: - #35689 — Revert PR #30068 (FontImageSource centering on Windows) - #35694 — Revert TalkBack RadioButton fix - #35703 — Revert Shell.NavBarIsVisible fix - #35744 — Revert HybridWebView WebView fix - #35461, #35503 — additional Android reverts </details> After this lands, the release-readiness tracker can survey `release/10.0.1xx-sr8` directly instead of using `-Candidate -InheritFromPriorSr` mode against SR7.
…ame behind modal after update to 10.0.60 (#35559) <!-- 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: When the keyboard opens in the modal, the parent page/frame behind the modal shifts in the shell. ### Root Cause: PR #33958 added an OnKeyboardWillHide handler to ShellPageRendererTracker to fix an iOS timing bug where a Shell page view would land at Y=0 (underneath the navigation bar) when the keyboard dismissed during a page navigation. The handler worked by detecting this misposition and correcting the view frame. However, the observer was registered using UIKeyboard.Notifications.ObserveWillHide — a global notification that fires for every live ShellPageRendererTracker instance whenever any keyboard is dismissed, regardless of which page triggered it. This becomes a problem when a transparent modal page is presented via Shell.GoToAsync. In iOS, modal presentation does not push the modal onto the navigation controller's view controller stack — it sits above the stack as a separate presented view controller. This means navController.TopViewController still points to the underlying Shell page, so the existing guard ViewController == navController.TopViewController evaluated to true for the page behind the modal. With _pendingKeyboardNavigation still armed from the page's initial load, dismissing the keyboard inside the modal triggered the frame correction on the underlying page, causing the visible vertical offset reported in the issue. Two secondary bugs compounded this: the SearchHandler early-return and the hidden-nav-bar early-return both exited the method without clearing _pendingKeyboardNavigation, leaving the flag permanently armed after those paths — meaning any future keyboard dismissal could incorrectly fire the frame correction long after the intended one-shot timing window had passed. ### Description of Change: The fix adds a single guard at the top of OnKeyboardWillHide: if navController.PresentedViewController is not null, the method returns immediately without clearing _pendingKeyboardNavigation. Using PresentedViewController is the idiomatic UIKit way to detect that a modal is covering the navigation controller, and returning without consuming the flag ensures the original page-load correction still works if a keyboard event fires on this page after the modal is dismissed. The two secondary leaks are also patched both the hidden-nav-bar path and the SearchHandler path now explicitly set _pendingKeyboardNavigation = false before returning, so the flag is always consumed once the correction window is definitively over. **Tested the behavior in the following platforms:** - [x] Android - [ ] Windows - [x] iOS - [ ] Mac ### Reference: N/A ### Issues Fixed: Fixes #35401 ### Screenshots | Before | After | |---------|--------| | <Video src="https://github.com/user-attachments/assets/a9da8996-3caf-4932-a5ca-a22dc72a302c" Width="300" Height="600"/> | <Video src="https://github.com/user-attachments/assets/503ced7d-24de-4410-aaf2-63c684211564" Width="300" Height="600"/> |
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:
When the keyboard opens in the modal, the parent page/frame behind the modal shifts in the shell.
Root Cause:
PR #33958 added an OnKeyboardWillHide handler to ShellPageRendererTracker to fix an iOS timing bug where a Shell page view would land at Y=0 (underneath the navigation bar) when the keyboard dismissed during a page navigation. The handler worked by detecting this misposition and correcting the view frame. However, the observer was registered using UIKeyboard.Notifications.ObserveWillHide — a global notification that fires for every live ShellPageRendererTracker instance whenever any keyboard is dismissed, regardless of which page triggered it.
This becomes a problem when a transparent modal page is presented via Shell.GoToAsync. In iOS, modal presentation does not push the modal onto the navigation controller's view controller stack — it sits above the stack as a separate presented view controller. This means navController.TopViewController still points to the underlying Shell page, so the existing guard ViewController == navController.TopViewController evaluated to true for the page behind the modal. With _pendingKeyboardNavigation still armed from the page's initial load, dismissing the keyboard inside the modal triggered the frame correction on the underlying page, causing the visible vertical offset reported in the issue.
Two secondary bugs compounded this: the SearchHandler early-return and the hidden-nav-bar early-return both exited the method without clearing _pendingKeyboardNavigation, leaving the flag permanently armed after those paths — meaning any future keyboard dismissal could incorrectly fire the frame correction long after the intended one-shot timing window had passed.
Description of Change:
The fix adds a single guard at the top of OnKeyboardWillHide: if navController.PresentedViewController is not null, the method returns immediately without clearing _pendingKeyboardNavigation. Using PresentedViewController is the idiomatic UIKit way to detect that a modal is covering the navigation controller, and returning without consuming the flag ensures the original page-load correction still works if a keyboard event fires on this page after the modal is dismissed. The two secondary leaks are also patched both the hidden-nav-bar path and the SearchHandler path now explicitly set _pendingKeyboardNavigation = false before returning, so the flag is always consumed once the correction window is definitively over.
Tested the behavior in the following platforms:
Reference:
N/A
Issues Fixed:
Fixes #35401
Screenshots
Before_fix_35401.mov
after_fx_35401.mov