Repository navigation
[Windows] InputTransparent: Respect wrapper view hit testing - #37392
Conversation
Propagate input transparency to Windows wrapper views while preserving layout child interaction and wrapper state during handler reconnects. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: efff66ab-5dc2-4538-a4ec-1f0c889bf739
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 37392Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 37392" |
|
Azure Pipelines: Successfully started running 1 pipeline(s). There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
This PR fixes a Windows-specific InputTransparent hit-testing gap by ensuring the Windows wrapper container (WrapperView) participates in input transparency updates, so wrapped controls (e.g., Label with transparent background) no longer intercept pointer input meant for underlying controls.
Changes:
- Windows: propagate
InputTransparentupdates to the container wrapper (and handle reconnect scenarios by reassigningWrapperView.Childto the new platform view). - Add Windows device tests covering wrapper/container hit-testing behavior for
Labeland Windows layout behavior withCascadeInputTransparent. - Add an Appium regression test plus HostApp repro page for issue #21384.
Show a summary per file
| File | Description |
|---|---|
| src/Core/src/Handlers/View/ViewHandler.cs | Updates container mapping + input-transparency propagation so Windows wrapper hit-testing tracks InputTransparent, while preserving layout handler behavior. |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue21384.cs | Adds an Appium regression test asserting the button click succeeds when overlaid by an InputTransparent label. |
| src/Controls/tests/TestCases.HostApp/Issues/Issue21384.cs | Adds the HostApp repro page used by the Appium regression scenario. |
| src/Controls/tests/DeviceTests/Elements/Layout/LayoutTests.Windows.cs | Adds a device test verifying layout container hit-testing and CascadeInputTransparent behavior remain correct on Windows. |
| src/Controls/tests/DeviceTests/Elements/Label/LabelTests.Windows.cs | Adds device tests validating wrapper hit-testing tracks InputTransparent, including runtime changes and handler reconnect scenarios. |
Review details
- Files reviewed: 5/5 changed files
- Comments generated: 1
- Review effort level: Lite
This comment has been minimized.
This comment has been minimized.
MauiBot
left a comment
There was a problem hiding this comment.
Expert Review — 2 findings
See inline comments for details.
kubaflo
left a comment
There was a problem hiding this comment.
Could you please resolve conflicts?
### Description of Change This pull request makes a minor update to the UI test pipeline configuration - Pipeline configuration simplification: * Removed the **duplicate** code that set the `$deviceType` variable and appended the `--skin` argument to the test command in `eng/pipelines/common/ui-tests-steps.yml`. The same code was already added at [line 133](https://github.com/dotnet/maui/blob/main/eng/pipelines/common/ui-tests-steps.yml#L133) as part of [PR #33409](#33409). The duplicate code was also added at [line 156](https://github.com/dotnet/maui/blob/main/eng/pipelines/common/ui-tests-steps.yml#L156) as part of [PR #31631](#31631).
<!-- 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! ### Description of Change This follow-up repairs the skill-evaluation failures exposed by #36799 and hardens the credentialed Vally evaluator so skill regressions, infrastructure failures, incomplete trials, parser differences, and reporting-side failures are classified accurately. ### Root Causes - `try-fix-capabilities` could exceed its numeric threshold while remaining red because Vally independently hard-fails execution errors and incomplete trials. Aggregate score never overrides those vetoes. - `pr-review-gh-auth` routed correctly, but its isolated fixture omitted the phase-specific unauthenticated public-GitHub fallback required by the grader. - Later failures exposed evaluator defects rather than skill regressions: PAT authentication did not prove model entitlement, model discovery did not initially match Vally 0.12's effective execution plan, matrix-only token offsets removed run-level rotation entropy, and parallel legs amplified shared PAT contention. - Run `31518503277` restored the synthetic target correctly, but one agent deleted Vally's pre-existing untracked `try-fix/` input to force an empty `git status`; Vally correctly treated that deletion as workspace drift. - Run `31524806025` completed every evaluation successfully, but a transient GitHub API fetch failure occurred before the comment step exported its already-computed verdict, making reporting red despite green suites. - Review found parser-semantic splits between Psych and Vally's pinned `yaml@2.9.0`: duplicate keys could be first-wins in AST policy checks but last-wins at runtime, while YAML merge keys/tags were interpreted differently and could hide executable evaluator fields from trusted validation. ### Changes - Replaced unreliable operational probes with bounded fixtures while preserving repeated trials, behavioral rubrics, strict thresholds, and hard-veto semantics. - Added the unauthenticated GitHub fallback fixture and deterministic skill-invocation/tool-call graders. - Upgraded to Vally 0.12 and made aggregation fail closed on execution errors, incomplete/skipped stimuli, malformed output, invocation failures, and missing mandatory coverage. - Added trusted fixture preparation plus path, symlink, Git, environment, executable, attachment, hook, settings, MCP, executor, and repository-control isolation. - Serialized matrix legs while retaining three trials per stimulus. - Made model discovery use only executed `eval*.vally.yaml` specs and Vally 0.12's effective executor and prompt-grader fields; implicit prompt-grader fallbacks are rejected. - Added model-aware PAT selection with run/rerun/matrix-distributed rotation and exact sentinel probes through the pinned evaluator runtime; reused it in the advisory soak. - Clarified that `try-fix` must preserve every pre-existing untracked path, including evaluator-loaded skill inputs. Trusted validation enforces both the skill contract and restoration fixture instruction while retaining `diff-empty` as the method-independent veto. - Exported the authoritative evaluation verdict before PR-comment API calls, added bounded API retries, and made comment publication advisory so transient GitHub failures cannot erase or invert the commit status. - Reduced soak workflow permissions to `contents: read` and made `/user` transport failures explicit without exposing PATs. - Made required-stimulus policy fail closed when a configured stimulus is renamed or removed, and bound each fixture marker/ref to the YAML stimulus that owns it so a correctly named decoy cannot satisfy the policy. - Parse each eval spec once and reject duplicate semantic mapping keys, textual YAML merge keys, and normalized explicit merge tags recursively before loading. This prevents Psych/Vally parser disagreement from bypassing prompt, ref, repository-control, or executable-environment validation. - Limited frozen-worktree test detection to full immutable commit IDs; ordinary explicit branch bases continue using authoritative PR file metadata. - Added deterministic regressions for model planning, PAT distribution and transport errors, deleted evaluator controls, host-only XAML invocation, evaluator-owned input preservation, required-stimulus rename/decoy/parser bypasses, branch-versus-immutable test detection, and reporting-side verdict preservation. ### Validation Current head: `fd8f3d543e1a1eb90e8432a0cbae07a18b52dbdd`. - Exact-head [Skill Validation run 31807806898](https://github.com/dotnet/maui/actions/runs/31807806898), [`maui-pr` build 1553690](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1553690), Build Analysis, CLA, static checks, Pester, and the hermeticity gate are green. - All evaluated suites passed. Key suites: `try-fix-restore-protocol` **1.00 / 1.00**, `try-fix-capabilities` **0.93 / 0.80**, `pr-review-gh-auth` **1.00 / 0.80**, and `verify-tests-fail-without-fix-capabilities` **0.94 / 0.87**. - Local trusted evaluator/reporting harness: **70 tests, 306 assertions, 0 failures/errors/skips**. - All **16** Vally specs pass strict lint with pinned `@microsoft/vally-cli@0.12.0`. - All **8** skill test directories pass trusted validation and resolve the effective plan to `gpt-5.6-sol` plus `claude-opus-5`; non-eval soak/hermeticity specs do not contaminate matrix selection. - Ruby syntax, Bash syntax, ShellCheck, workflow YAML parsing, Pester (**8 passed**), and `git diff --check` pass. - Final whole-diff review found no high-confidence correctness or security blockers; all review threads are resolved. - `pull_request_target` executes trusted workflow/helper code from default `main`; candidate selector/reporting helper behavior is therefore covered deterministically here and becomes the credentialed trusted path after merge. ### Issues Fixed Follow-up to #36799. --------- Co-authored-by: PureWeen <223556219+Copilot@users.noreply.github.com> Co-authored-by: Vally Fixture <vally-fixture@example.invalid> Copilot-Session: b9f7de2c-86d7-47cd-8ac8-aeff57d0b0f3 Copilot-Session: 806beb89-5041-4c7b-bcbf-998d6fbab8dc
Keep reconnect rebinding scoped to the framework's fresh unparented platform view, cover moved and detached wrappers, and skip the Windows-specific pointer test on MacCatalyst. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: efff66ab-5dc2-4538-a4ec-1f0c889bf739
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: efff66ab-5dc2-4538-a4ec-1f0c889bf739
This comment has been minimized.
This comment has been minimized.
MauiBot
left a comment
There was a problem hiding this comment.
Expert Review — 2 findings
See inline comments for details.
| var inputTransparentLayout = new Grid | ||
| { | ||
| AutomationId = "InputTransparentLayout", | ||
| CascadeInputTransparent = true, |
There was a problem hiding this comment.
🔍 AI-Generated Review (multi-model)
💡 [moderate] Regression Prevention and Test Coverage — The layout scenario in this repro uses CascadeInputTransparent = true with a non-interactive Label child, so the paired UI test InputTransparentClippedLayoutAllowsButtonClick cannot detect a regression of the new if (handler is ILayoutHandler) return; guard in MapInputTransparentToContainer. Removing that guard would set the layout wrapper's IsHitTestVisible to false, which only makes the overlay more transparent to input — the button underneath would still be clickable and the test would still pass. The scenario the guard actually protects is a layout with InputTransparent = true and CascadeInputTransparent = false containing an interactive child that must stay clickable; that is currently only asserted at the property level in LayoutTests.InputTransparentLayoutContainerRemainsHitTestVisible. Consider adding a second overlay here with CascadeInputTransparent = false and a Button child, plus a UI test that taps that inner button, so the guard has end-to-end coverage.
| public void InputTransparentLabelAllowsButtonClick() | ||
| { | ||
| if (Device == TestDevice.Mac) | ||
| Assert.Ignore("Issue #21384 and its fix are Windows-specific."); |
There was a problem hiding this comment.
🔍 AI-Generated Review (multi-model)
💡 [minor] Cross-Platform Behavioral Consistency — This Mac skip is inconsistent with InputTransparentClippedLayoutAllowsButtonClick below, which runs on every device including Mac. If the stated rationale ("Issue #21384 and its fix are Windows-specific") holds, the layout test should be skipped on Mac too; if the label overlay scenario actually fails on MacCatalyst, that is a real behavioral divergence being masked by an unconditional Assert.Ignore with no linked follow-up issue. Please either drop the skip (the iOS/MacCatalyst container path already maps InputTransparent to the wrapper, so the scenario is expected to pass) or reference a tracking issue explaining the MacCatalyst failure.
MauiBot
left a comment
There was a problem hiding this comment.
AI Review Summary
@jfversluis — new AI review results are available based on commit
b283e44.
🗂️ Review Sessions — click to expand
🚦 Gate — Test Before & After Fix
Gate Result: ✅ PASSED
Platform: WINDOWS · Base: main · Merge base: b28e21c0
✅ Fix verified — 2 test(s) reproduce the bug (FAIL without the fix → PASS with it). 1 test(s) pass in both states and are not bug-reproducing; under the "at least one test reproduces the bug and none regress" rule they don't block the gate.
| Test | Without Fix (expect FAIL) | With Fix (expect PASS) |
|---|---|---|
📱 LabelTests (ContainerHitTestingTracksInputTransparent, ContainerHitTestingUpdatesWhenInputTransparentChanges, ContainerCreatedAfterInputTransparentIsNotHitTestVisible, ContainerHitTestingIsRestoredWhenHandlerReconnects, ReconnectingContainerPreservesWrapperInDifferentPanel, ReconnectingContainerPreservesDetachedWrapper) Category=Label |
✅ FAIL — 410s | ✅ PASS — 320s |
📱 LayoutTests (InputTransparentLayoutContainerRemainsHitTestVisible) Category=Layout |
❌ PASS — 921s | ✅ PASS — 309s |
🖥️ Issue21384 Issue21384 |
✅ FAIL — 542s | ✅ PASS — 505s |
🔴 Without fix — 📱 LabelTests (ContainerHitTestingTracksInputTransparent, ContainerHitTestingUpdatesWhenInputTransparentChanges, ContainerCreatedAfterInputTransparentIsNotHitTestVisible, ContainerHitTestingIsRestoredWhenHandlerReconnects, ReconnectingContainerPreservesWrapperInDifferentPanel, ReconnectingContainerPreservesDetachedWrapper): FAIL ✅ · 410s
(no coded error found; showing last 1200 chars)
ss the warning by specifying `x:SuppressXamlTrimWarnings=True` within the closest element. If not, the property path might be trimmed and will not be AOT compatible. [D:\a\1\s\src\Controls\src\Core\Controls.Core.csproj::TargetFramework=net10.0-windows10.0.19041.0]
Platform\Windows\TabbedPage\TabbedPageStyle.xaml(13,13): XamlCompiler warning WMC1510: Ensure the property path is trimming and AOT compatible by making use of 'Compiled Bindings (x:bind)' if possible or by specifying the 'x:DataType' directive with the respective binding data context and marking the type declaration with the 'WinRT.GeneratedBindableCustomProperty' attribute or the 'Microsoft.UI.Xaml.Data.Bindable' attribute. If you are unable to do either but can ensure the data type is attributed correctly, then you can also suppress the warning by specifying `x:SuppressXamlTrimWarnings=True` within the closest element. If not, the property path might be trimmed and will not be AOT compatible. [D:\a\1\s\src\Controls\src\Core\Controls.Core.csproj::TargetFramework=net10.0-windows10.0.19041.0]
0 Error(s)
Time Elapsed 00:05:04.78
Passed: 1
Failed: 6
Skipped: 0
Total: 7
Tests completed with exit code: 1
🟢 With fix — 📱 LabelTests (ContainerHitTestingTracksInputTransparent, ContainerHitTestingUpdatesWhenInputTransparentChanges, ContainerCreatedAfterInputTransparentIsNotHitTestVisible, ContainerHitTestingIsRestoredWhenHandlerReconnects, ReconnectingContainerPreservesWrapperInDifferentPanel, ReconnectingContainerPreservesDetachedWrapper): PASS ✅ · 320s
(no coded error found; showing last 1200 chars)
uppress the warning by specifying `x:SuppressXamlTrimWarnings=True` within the closest element. If not, the property path might be trimmed and will not be AOT compatible. [D:\a\1\s\src\Controls\src\Core\Controls.Core.csproj::TargetFramework=net10.0-windows10.0.19041.0]
Platform\Windows\TabbedPage\TabbedPageStyle.xaml(13,13): XamlCompiler warning WMC1510: Ensure the property path is trimming and AOT compatible by making use of 'Compiled Bindings (x:bind)' if possible or by specifying the 'x:DataType' directive with the respective binding data context and marking the type declaration with the 'WinRT.GeneratedBindableCustomProperty' attribute or the 'Microsoft.UI.Xaml.Data.Bindable' attribute. If you are unable to do either but can ensure the data type is attributed correctly, then you can also suppress the warning by specifying `x:SuppressXamlTrimWarnings=True` within the closest element. If not, the property path might be trimmed and will not be AOT compatible. [D:\a\1\s\src\Controls\src\Core\Controls.Core.csproj::TargetFramework=net10.0-windows10.0.19041.0]
0 Error(s)
Time Elapsed 00:05:01.62
Passed: 7
Failed: 0
Skipped: 0
Total: 7
Tests completed successfully
🔴 Without fix — 📱 LayoutTests (InputTransparentLayoutContainerRemainsHitTestVisible): PASS ❌ · 921s
(no coded error found; showing last 1200 chars)
uppress the warning by specifying `x:SuppressXamlTrimWarnings=True` within the closest element. If not, the property path might be trimmed and will not be AOT compatible. [D:\a\1\s\src\Controls\src\Core\Controls.Core.csproj::TargetFramework=net10.0-windows10.0.19041.0]
Platform\Windows\TabbedPage\TabbedPageStyle.xaml(13,13): XamlCompiler warning WMC1510: Ensure the property path is trimming and AOT compatible by making use of 'Compiled Bindings (x:bind)' if possible or by specifying the 'x:DataType' directive with the respective binding data context and marking the type declaration with the 'WinRT.GeneratedBindableCustomProperty' attribute or the 'Microsoft.UI.Xaml.Data.Bindable' attribute. If you are unable to do either but can ensure the data type is attributed correctly, then you can also suppress the warning by specifying `x:SuppressXamlTrimWarnings=True` within the closest element. If not, the property path might be trimmed and will not be AOT compatible. [D:\a\1\s\src\Controls\src\Core\Controls.Core.csproj::TargetFramework=net10.0-windows10.0.19041.0]
0 Error(s)
Time Elapsed 00:04:48.83
Passed: 2
Failed: 0
Skipped: 0
Total: 2
Tests completed successfully
🟢 With fix — 📱 LayoutTests (InputTransparentLayoutContainerRemainsHitTestVisible): PASS ✅ · 309s
(no coded error found; showing last 1200 chars)
uppress the warning by specifying `x:SuppressXamlTrimWarnings=True` within the closest element. If not, the property path might be trimmed and will not be AOT compatible. [D:\a\1\s\src\Controls\src\Core\Controls.Core.csproj::TargetFramework=net10.0-windows10.0.19041.0]
Platform\Windows\TabbedPage\TabbedPageStyle.xaml(13,13): XamlCompiler warning WMC1510: Ensure the property path is trimming and AOT compatible by making use of 'Compiled Bindings (x:bind)' if possible or by specifying the 'x:DataType' directive with the respective binding data context and marking the type declaration with the 'WinRT.GeneratedBindableCustomProperty' attribute or the 'Microsoft.UI.Xaml.Data.Bindable' attribute. If you are unable to do either but can ensure the data type is attributed correctly, then you can also suppress the warning by specifying `x:SuppressXamlTrimWarnings=True` within the closest element. If not, the property path might be trimmed and will not be AOT compatible. [D:\a\1\s\src\Controls\src\Core\Controls.Core.csproj::TargetFramework=net10.0-windows10.0.19041.0]
0 Error(s)
Time Elapsed 00:04:52.68
Passed: 2
Failed: 0
Skipped: 0
Total: 2
Tests completed successfully
🔴 Without fix — 🖥️ Issue21384: FAIL ✅ · 542s
Error-relevant lines (filtered from the build log):
at Microsoft.Maui.TestCases.Tests.Issues.Issue21384.InputTransparentLabelAllowsButtonClick() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue21384.cs:line 25
🟢 With fix — 🖥️ Issue21384: PASS ✅ · 505s
(no coded error found; showing last 1200 chars)
\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll
NUnit3TestExecutor discovered 2 of 2 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 8/18/2026 4:55:44 PM FixtureSetup for Issue21384(Windows)
>>>>> 8/18/2026 4:55:52 PM InputTransparentClippedLayoutAllowsButtonClick Start
>>>>> 8/18/2026 4:55:54 PM InputTransparentClippedLayoutAllowsButtonClick Stop
Passed InputTransparentClippedLayoutAllowsButtonClick [1 s]
>>>>> 8/18/2026 4:55:54 PM InputTransparentLabelAllowsButtonClick Start
>>>>> 8/18/2026 4:55:55 PM InputTransparentLabelAllowsButtonClick Stop
Passed InputTransparentLabelAllowsButtonClick [1 s]
NUnit Adapter 4.5.0.0: Test execution complete
[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.10] Discovering: Controls.TestCases.WinUI.Tests
[xUnit.net 00:00:00.36] Discovered: Controls.TestCases.WinUI.Tests
Results File: D:\a\1\s\CustomAgentLogsTmp\UITests\TestResults\Issue21384.trx
Test Run Successful.
Total tests: 2
Passed: 2
Total time: 22.2795 Seconds
>>> TRX_RESULT_FILE: D:\a\1\s\CustomAgentLogsTmp\UITests\TestResults\Issue21384.trx
⚠️ Failure Details
- ❌ LayoutTests (InputTransparentLayoutContainerRemainsHitTestVisible) PASSED without fix (should fail) — tests don't catch the bug
📁 Fix files reverted (2 files)
src/Core/src/Handlers/View/ViewHandler.Windows.cssrc/Core/src/Handlers/View/ViewHandler.cs
📋 Pre-Flight — Context & Validation
PR #37392 Pre-Flight
Context
- Title:
[Windows] InputTransparent: Respect wrapper view hit testing - Issue: #21384,
InputTransparent has no effect on Windows - Platform: Windows
- Base:
origin/main(b28e21c0cb) - Materialized PR commit:
017bc8dd96 - Gate: Passed before STEP 5a; do not rerun failure-without-fix verification and do not modify
gate/content.md.
The reported reproduction overlays an InputTransparent=true Label on a
Button. On Windows, a transparent background makes the label handler create a
WrapperView. Disabling hit testing only on the inner TextBlock leaves the
wrapper hit-testable, so it intercepts the pointer instead of allowing the
button underneath to receive it.
Existing PR Approach
The PR extends container input-transparency mapping to Windows. It updates the
WrapperView for non-layout handlers while preserving ILayoutHandler's
specialized LayoutPanel behavior so transparent layouts do not disable their
interactive descendants. It also adds ReconnectContainer() to rebind a
preserved wrapper to a replacement platform view when a disconnected handler is
reused.
Production files in the PR:
src/Core/src/Handlers/View/ViewHandler.cssrc/Core/src/Handlers/View/ViewHandler.Windows.cs
Test files in the PR:
src/Controls/tests/DeviceTests/Elements/Label/LabelTests.Windows.cssrc/Controls/tests/DeviceTests/Elements/Layout/LayoutTests.Windows.cssrc/Controls/tests/TestCases.HostApp/Issues/Issue21384.cssrc/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue21384.cs
Alternative candidates must not merely restate the PR's mechanism: propagating
InputTransparent to every non-layout wrapper plus explicitly rebinding
WrapperView.Child during reconnect.
Bounded Verification
Use this single targeted command; do not run a full class, project, or repository
test suite:
pwsh .github/skills/run-device-tests/scripts/Run-DeviceTests.ps1 -Project Controls -Platform windows -IncludeClasses "Microsoft.Maui.DeviceTests.LabelTests,Microsoft.Maui.DeviceTests.LayoutTests" -IncludeMethods "ContainerHitTestingTracksInputTransparent,ContainerHitTestingUpdatesWhenInputTransparentChanges,ContainerCreatedAfterInputTransparentIsNotHitTestVisible,ContainerHitTestingIsRestoredWhenHandlerReconnects,ReconnectingContainerPreservesWrapperInDifferentPanel,ReconnectingContainerPreservesDetachedWrapper,InputTransparentLayoutContainerRemainsHitTestVisible"The primary regression is
ContainerHitTestingTracksInputTransparent. The remaining listed methods are
the mandatory focused regressions for runtime updates, late wrapper creation,
handler reconnect, wrapper parent preservation, detached wrappers, and layout
child hit testing.
Each candidate gets one implementation/test pass and no more than one focused
correction/retest. The baseline script's RevertedFiles list is the strict edit
allow-list. Restore only with
pwsh .github/scripts/EstablishBrokenBaseline.ps1 -Restore.
🔬 Code Review — Deep Analysis
Expert PR Evaluation
Verdict: LGTM with two non-blocking test-coverage suggestions.
The submitted production fix is sound. It propagates InputTransparent to non-layout Windows wrappers, preserves ILayoutHandler's child-interaction semantics, and safely rebinds a retained WrapperView to the newly created unparented platform view during handler reuse. The reconnect ordering preserves the wrapper's visual-tree position and avoids re-entering derived SetupContainer() overrides. The Gate passed, including failure-first Label and Issue21384 coverage, and the regression-risk scan is clean.
The expert reviewer identified no production correctness, lifecycle, threading, API, or regression-blocking defects. It recommended strengthening end-to-end coverage for the ILayoutHandler carve-out with an interactive child under CascadeInputTransparent = false, and resolving the MacCatalyst-only skip inconsistency in the Label UI test. Both findings are suggestions rather than blockers and are recorded in inline-findings.json.
🛠️ Try-Fix — Analysis & Comparison
Try-Fix Aggregate — PR #37392
Candidates executed: 2 (candidate 1 — Blocked; candidate 2 — Blocked).
Candidate 1 — PR #37392 ([Windows] InputTransparent: Respect wrapper view hit testing)
Result: Blocked (environment blocker at try-fix Step 2 — broken baseline could not be established)
Artifacts: CustomAgentLogsTmp/PRState/37392/PRAgent/try-fix/attempt-1/
(baseline.log, approach.md, reviewer-findings.json, reviewer-findings.diff, result.txt, fix.diff,
test-output.log, analysis.md, restore.log).
1. Approach designed (not applied)
"Container mirrors its child" — two coordinated changes, both confined to the PR-owned production files
src/Core/src/Handlers/View/ViewHandler.cs and src/Core/src/Handlers/View/ViewHandler.Windows.cs:
-
Hit-testing is mirrored, not re-derived.
ViewHandler.Windows.csgains
static void UpdateContainerHitTesting(IViewHandler handler)→
if (handler.ContainerView is WrapperView wrapper && handler.PlatformView is UIElement pv) wrapper.IsHitTestVisible = pv.IsHitTestVisible;
It is invoked fromMapInputTransparent(Windows branch, immediately after the platform view's own
UpdateInputTransparent) and fromMapContainerView(so a wrapper created later — e.g. the moment a transparent
background first forces one — picks up the child's current state). -
The container re-adopts on platform-view identity change.
ViewHandler.csdeclarespartial void ConnectedHandler(PlatformView platformView);and calls it from the sealed
OnConnectHandler(object)afterOnConnectHandler((PlatformView)platformView)returns.
ViewHandler.Windows.csimplements it: ifContainerView is WrapperView wrapperandwrapper.Childis not the
newly connected platform view,wrapper.Child = platformView.
2. Mechanism-level difference from the existing PR
The PR (017bc8dd96) treats the WrapperView as a second, independent InputTransparent policy target: it
extends MapInputTransparentToContainer to Windows so the wrapper re-derives IsHitTestVisible from
view.InputTransparent, which then forces an if (handler is ILayoutHandler) return; carve-out, because
LayoutPanel expresses input transparency through its background brush and must stay hit-test visible so its
children remain interactive. Separately, it repairs the stale reconnect binding from inside the ContainerView
property mapper via ReconnectContainer(), gated on the hasContainerOldValue heuristic.
This candidate starts from a different root-cause hypothesis: the wrapper is a passthrough decoration and must
have no input policy of its own — it must reflect whatever hit-testability its child ended up with. The full
cause-to-effect chain:
ViewExtensions.UpdateInputTransparent(this FrameworkElement, IViewHandler, IView)already sets
IsHitTestVisible = !view.InputTransparenton the platform view. For non-layout views this is exactly the
desired container state, so mirroring reproduces it without re-readingview.InputTransparent.LayoutHandler.Windows.MapInputTransparentreplaces theIView.InputTransparentmapping for layouts and only
callsUpdatePlatformViewBackground, soLayoutPanel.IsHitTestVisibleis never set tofalse. Mirroring
therefore yieldswrapper.IsHitTestVisible == truefor transparent layouts automatically — the
ILayoutHandlertype check disappears entirely, and any future handler with bespoke input semantics is correct by
construction instead of needing a new exception.- The stale-child defect is attributed to platform-view identity change, not to container property mapping.
ViewHandler<T,U>.SetupContainer()(Windows) early-returns whenContainerView is not null, so a reused handler's
preserved wrapper keeps a deadChild. Adopting at connect completion means the wrapper hosts the live child
before any mapper runs, so every subsequent mapper (visibility, opacity, clip, shadow, hit-testing) observes a
consistent wrapper→child tree, and nohasContainerOldValuegate is needed. The insertion point is deliberately
afterOnConnectHandler(PlatformView)so a handler's ownConnectHandlerstill sees an unparented platform view
(required byContainerHitTestingIsRestoredWhenHandlerReconnects'sConnectedPlatformViewsWereUnparented
assertion; adopting in the pre-existingConnectingHandlerpartial would fail it).
This is a different mechanism, not a relocation: policy-mirroring replaces policy-duplication-plus-exception, and
lifecycle-driven adoption replaces mapper-driven repair.
3. Files changed
None. No file was modified. git status --porcelain --untracked-files=no -- src/ returns zero entries.
4. Captured diff
fix.diff and reviewer-findings.diff are both 0 bytes (empty diff) — captured before restoration, not
reconstructed afterwards.
(empty)
5. Test command and result
Command (never executed):
pwsh .github/skills/run-device-tests/scripts/Run-DeviceTests.ps1 -Project Controls -Platform windows -IncludeClasses "Microsoft.Maui.DeviceTests.LabelTests,Microsoft.Maui.DeviceTests.LayoutTests" -IncludeMethods "ContainerHitTestingTracksInputTransparent,ContainerHitTestingUpdatesWhenInputTransparentChanges,ContainerCreatedAfterInputTransparentIsNotHitTestVisible,ContainerHitTestingIsRestoredWhenHandlerReconnects,ReconnectingContainerPreservesWrapperInDifferentPanel,ReconnectingContainerPreservesDetachedWrapper,InputTransparentLayoutContainerRemainsHitTestVisible"Result: not run — result.txt = Blocked. test-output.log records the command and the reason it was skipped.
6. Self-review
0 findings (reviewer-findings.json = []). There is no diff to review; the empty array is the correct output
and is consistent with the empty reviewer-findings.diff snapshot. The designed change was still walked against the
always-active dimensions (Logic and Correctness, Regression Prevention, Complexity Reduction) at design time — no
concrete failing scenario was identified for the design itself; the ordering hazard that was identified
(adoption must not run inside ConnectingHandler) is already resolved in the design.
7. Failure analysis (why Blocked)
pwsh .github/scripts/EstablishBrokenBaseline.ps1 aborted at its repo-wide fail-fast cleanliness check
(line 372, git status --porcelain --untracked-files=no). 44 tracked files under .github/ and eng/ were already
modified or deleted before this attempt began — pre-existing harness/user state that the invocation explicitly
forbids editing, restoring, staging, deleting, or otherwise altering; committing is prohibited too. The script offers
only -BaseBranch, -DryRun, and -Restore, so there is no scoping or override that avoids touching that state.
Because the script never ran, .github/.baseline-state.json was never created. Under the skill's baseline-file
boundary that means there is no RevertedFiles allow-list, so no file — including the two intended targets — was
editable. Editing them regardless would also have stacked the alternative on top of the PR fix still present at
HEAD (017bc8dd96) rather than replacing it, yielding a meaningless comparison, and could not have been undone
with the only permitted restore command.
Unblock options: (a) the owner commits or reverts the 44 harness .github/eng modifications before the
attempt, or (b) EstablishBrokenBaseline.ps1 scopes its cleanliness check to the detected fix files / src/, or
gains an ignore list for harness-owned paths.
8. Restoration
pwsh .github/scripts/EstablishBrokenBaseline.ps1 -Restore was run and reported
No baseline state found / Restored False — the accepted no-state outcome, since baseline state was never created
and no attempt edits were made. Verified afterwards: git status --porcelain --untracked-files=no -- src/ is empty.
Pre-existing untracked and harness-owned dirty paths were left exactly as found.
Candidate 2 — PR #37392 ([Windows] InputTransparent: Respect wrapper view hit testing)
Result: Blocked (environment blocker at try-fix Step 2 — broken baseline could not be established)
Artifacts: CustomAgentLogsTmp/PRState/37392/PRAgent/try-fix/attempt-2/ (baseline.log, approach.md, reviewer-findings.json, reviewer-findings.diff, result.txt, fix.diff, test-output.log, and analysis.md).
1. Approach designed (not applied)
“Remove the wrapper's hit-test surface and rebuild containers atomically.” The candidate attributes interception to the WinUI wrapper's transparent decoration surface, not to a missing second copy of InputTransparent. For pointer-transparent non-layout views it would remove the wrapper's hit-test-producing background/local decoration surface, leaving input policy on the inner platform view. For reconnects it would run the existing container state machine through a full remove/setup transition at the original visual-tree slot, allowing normal setup to establish the replacement platform view relationship rather than assigning WrapperView.Child directly.
The design was not applied because no baseline edit allow-list was created. It also records a validation risk: the mandatory tests assert WrapperView.IsHitTestVisible == false, same-wrapper identity, and a new platform-view identity. Those structural expectations may reject this non-propagation/reconstruction mechanism even if pointer pass-through works; that question could not be tested while baseline establishment was blocked.
2. Explicit distinction from the PR and candidate 1
The PR treats the wrapper as a second input-policy target: it propagates InputTransparent to non-layout wrappers, excludes ILayoutHandler, and explicitly rebinds WrapperView.Child during container mapping on reconnect. This candidate does not assign input transparency or IsHitTestVisible to the wrapper; it removes the native surface that participates in hit testing. It does not repair a preserved wrapper by assigning its child; it asks the normal remove/setup state machine to reconstruct a consistent container relationship.
Candidate 1 proposed mirroring PlatformView.IsHitTestVisible onto WrapperView.IsHitTestVisible and re-adopting the replacement platform view from a connect-completion partial hook. This candidate neither mirrors wrapper/child hit-test state nor introduces any connect-completion partial. Its cause-to-effect chain is different: without a wrapper decoration hit-test surface, the disabled inner platform view has no hit-testable outer surface that can swallow input; an atomic container state transition prevents stale native relationships by construction rather than correcting one after connection.
3. Files changed
None. Baseline creation failed before .github/.baseline-state.json existed, so neither target file was editable. After restoration, git status --porcelain --untracked-files=no -- src/Core/src/Handlers/View/ViewHandler.cs src/Core/src/Handlers/View/ViewHandler.Windows.cs produced no entries.
4. Exact saved diff
fix.diff and reviewer-findings.diff are both 0 bytes:
(empty)5. Test command and result
The only permitted behavior-validation command was:
pwsh .github/skills/run-device-tests/scripts/Run-DeviceTests.ps1 -Project Controls -Platform windows -IncludeClasses "Microsoft.Maui.DeviceTests.LabelTests,Microsoft.Maui.DeviceTests.LayoutTests" -IncludeMethods "ContainerHitTestingTracksInputTransparent,ContainerHitTestingUpdatesWhenInputTransparentChanges,ContainerCreatedAfterInputTransparentIsNotHitTestVisible,ContainerHitTestingIsRestoredWhenHandlerReconnects,ReconnectingContainerPreservesWrapperInDifferentPanel,ReconnectingContainerPreservesDetachedWrapper,InputTransparentLayoutContainerRemainsHitTestVisible"Not run. test-output.log records that validation was skipped because the baseline failed before implementation. result.txt contains Blocked.
6. Inline expert self-review
0 findings (reviewer-findings.json is []). With no code diff, reviewer-findings.diff is correctly empty. The no-diff review covered all eight overarching principles, routed handler dimensions, Windows platform scoping, and the always-active Logic and Correctness, Regression Prevention, and Complexity Reduction dimensions. The design/test-contract concern above was documented as analysis, not fabricated as a line-level finding without a changed line.
7. Failure analysis
pwsh .github/scripts/EstablishBrokenBaseline.ps1 failed its repository-wide cleanliness guard because pre-existing harness/user modifications and deletions remain under .github and eng. Those paths were not touched. The script did not create .github/.baseline-state.json; therefore the skill's RevertedFiles allow-list did not exist and editing either permitted candidate file would have violated the baseline boundary, stacked a candidate on the PR instead of the broken baseline, and left no script-restorable state.
No workaround, stash, alternate index, index flag, temporary commit, worktree, external search, build, or test was used. The gate content was not touched.
8. Restoration
The exact required command was run:
pwsh .github/scripts/EstablishBrokenBaseline.ps1 -RestoreIt reported No baseline state found / Restored False, the expected no-state result because baseline creation failed and no production edit was made. Pre-existing harness/user state was preserved.
🏁 Report — Final Recommendation
⚠️ Final Recommendation: REQUEST CHANGES
Winner: pr-plus-reviewer
pr-plus-reviewer is the strongest candidate because it keeps the submitted production fix unchanged while closing both test-coverage gaps identified by the one expert review. Its required Windows regression validation passed all 9 selected cases from the mandated candidate worktree, and its patch passed git diff --check.
Candidate Comparison
| Rank | Candidate | Implementation and evidence | Assessment |
|---|---|---|---|
| 1 | pr-plus-reviewer |
Same production fix as the PR, plus end-to-end coverage for an interactive child under CascadeInputTransparent = false and consistent MacCatalyst execution of the Label UI test. Required targeted validation: 9 passed, 0 failed. |
Best coverage without increasing production risk. The bounded validation did not execute the changed Appium tests, so their runtime result remains an explicit uncertainty. |
| 2 | pr |
Gate passed: the Label and Issue21384 regressions fail without the fix and pass with it. Expert review found no blocking production, lifecycle, threading, API, or regression defect; regression-risk scan was clean. | Production approach is sound and mergeable on its own, but two useful coverage gaps remain. |
| 3 | try-fix-1 |
Proposed mirroring the platform view's hit-test state to the wrapper and reconnecting from a new connect-completion hook. No diff was produced and no regression test ran because baseline establishment was blocked. | Interesting design, but unimplemented and unvalidated; it cannot outrank passing candidates. |
| 4 | try-fix-2 |
Proposed removing the wrapper hit-test surface and rebuilding containers through the normal state machine. No diff was produced and no regression test ran because baseline establishment was blocked. | Unimplemented and unvalidated, with acknowledged risk of violating required wrapper identity and reconnect behavior. |
Expert Evaluation
The production change correctly:
- propagates Windows
InputTransparentstate to non-layoutWrapperViewinstances; - preserves
ILayoutHandler's background-based child-interaction behavior; - rebinds a retained wrapper to a freshly created, unparented platform view during handler reuse;
- preserves wrapper identity, visual-tree position, and derived-handler mapper replay without re-entering
SetupContainer().
The expert reviewer reported only two suggestion-level findings, both addressed by pr-plus-reviewer. No candidate failed regression validation; the two try-fix alternatives were blocked before implementation and therefore rank below both passing PR-based candidates.
Required Change
Apply the pr-plus-reviewer test-only patch before merge. Because the winning changes are not present in the submitted PR HEAD, the recommendation is REQUEST CHANGES despite the raw production fix being sound.
📱 UI Tests — InputTransparent,ViewBaseTests
Detected UI test categories: InputTransparent,ViewBaseTests
[!WARNING]
No UI test results were produced for the detected categories. The PR build itself was
fine — the deep UI stage was skipped or interrupted on infrastructure (the
merge-for-testing step, emulator/simulator boot, or an Appium hang), not by this PR's code.
This is usually transient; the review re-runs on new commits (a maintainer can also re-run it).
🧭 Next Steps — reviewer patch required (pr-plus-reviewer)
The reviewer-enhanced candidate won, so the submitted PR still needs those changes.
Why: The candidate preserves the expert-approved production fix and adds end-to-end coverage for the ILayoutHandler guard while removing an inconsistent MacCatalyst skip. Its required Windows regression validation passed 9/9, whereas both try-fix alternatives were blocked without code or test evidence.
Apply PRAgent/pr-plus-reviewer/reviewer.patch from the CopilotLogs
artifact (or follow the report's Required submitted-PR change), push the update, and run
the review again.
|
/azp run |
|
Azure Pipelines: Successfully started running 3 pipeline(s). |
Resolve the LabelTests.Windows.cs conflict by retaining both the InputTransparent reconnect coverage and the formatted-text regression test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 590f6f02-a472-4961-b6a5-9b3d0839c4b3
<!-- 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! On Windows, propagate `InputTransparent` to a view's `WrapperView` as well as its inner platform view. This allows pointer input to pass through wrapped controls, including the default-template `Label` with a transparent background overlaying a `Button` from #21384. The fix preserves two important Windows behaviors: - `ILayoutHandler` continues using `LayoutPanel`'s specialized background-based input transparency, so transparent layouts do not disable their interactive child tree. - Reusing a disconnected handler preserves the existing wrapper and its visual-tree position while replacing its stale child with the newly created platform view. Framework reconnect creates and connects the replacement platform view unparented before mapper replay. The reconnect repair therefore only updates `WrapperView.Child`; it does not remove the platform view from arbitrary parent shapes or re-enter virtual `SetupContainer()` overrides that could duplicate subscriptions or one-time setup. Normal mapper replay restores Label/Image sizing and alignment after the child replacement. The default template's implicit `Label` style supplies a transparent background, which causes `LabelHandler` to create a Windows `WrapperView`. The existing mapper disabled hit testing only on the inner `TextBlock`; the effective wrapper remained hit-testable and intercepted pointer input. - Windows Label device tests: **42 total, 40 passed, 0 failed, 2 skipped**. Coverage includes initial state, runtime toggles, late wrapper creation, reconnect hit testing and mapped properties, the framework's unparented replacement-platform-view lifecycle, a wrapper moved to another attached `Panel`, and a detached wrapper. - Failure-first reconnect validation: temporarily removing the reconnect rebinding made all three reconnect-specific tests fail; restoring it made them pass. - Windows Layout device tests: **54/54 passed**, covering both `CascadeInputTransparent` modes and confirming that the wrapper remains hit-testable for child interaction. - Windows Core tests: **1,980 passed, 0 failed, 111 skipped**; the exact CI-reported Slider case and all 90 Slider tests passed locally. - Windows Appium test and HostApp builds completed with **0 warnings and 0 errors**, and both Issue21384 tests are discovered. The reporter-faithful Label pointer test is skipped on MacCatalyst because test remains cross-platform. - Local Appium execution remains blocked before interaction by WinAppDriver's invalid status response. The real Win32 `SendInput` harness below provides behavior-level evidence. Both recordings use the same `AbsoluteLayout` reproduction from #21384 and send five real Win32 mouse clicks to the overlaid button (`SendInput`, not UI Automation invoke). **Before — bug reproduced on parent commit `f377ff1c5e`:** all five clicks are sent, but the click handler receives none and the visible counter remains at 0. https://github.com/user-attachments/assets/d59d3346-355c-434f-b1ac-01c76c361ab1 **After — fixed behavior:** all five equivalent clicks reach the button and the visible counter advances from 0 to 5. The final production code was rerun with the same harness and again received **5/5** clicks. https://github.com/user-attachments/assets/610856db-c094-4657-b4ea-0985b96221dd - Do not update only the inner Windows platform view; a hit-testable `WrapperView` can still intercept input. - Do not disable the wrapper for `ILayoutHandler`; `LayoutPanel` intentionally preserves child interaction through its background-based mapper. - Do not re-enter virtual `SetupContainer()` during reconnect; derived handlers may repeat subscriptions or one-time side effects. - Do not add generalized parent-detachment logic for reconnect; the framework replacement platform view is unparented before mapper replay, and the surviving wrapper's parent must remain unchanged. Fixes #21384 @owaits, once the build artifacts are available, could you please try them with your original reproduction and let us know whether this resolves the issue for you? --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
<!-- 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! On Windows, propagate `InputTransparent` to a view's `WrapperView` as well as its inner platform view. This allows pointer input to pass through wrapped controls, including the default-template `Label` with a transparent background overlaying a `Button` from #21384. The fix preserves two important Windows behaviors: - `ILayoutHandler` continues using `LayoutPanel`'s specialized background-based input transparency, so transparent layouts do not disable their interactive child tree. - Reusing a disconnected handler preserves the existing wrapper and its visual-tree position while replacing its stale child with the newly created platform view. Framework reconnect creates and connects the replacement platform view unparented before mapper replay. The reconnect repair therefore only updates `WrapperView.Child`; it does not remove the platform view from arbitrary parent shapes or re-enter virtual `SetupContainer()` overrides that could duplicate subscriptions or one-time setup. Normal mapper replay restores Label/Image sizing and alignment after the child replacement. The default template's implicit `Label` style supplies a transparent background, which causes `LabelHandler` to create a Windows `WrapperView`. The existing mapper disabled hit testing only on the inner `TextBlock`; the effective wrapper remained hit-testable and intercepted pointer input. - Windows Label device tests: **42 total, 40 passed, 0 failed, 2 skipped**. Coverage includes initial state, runtime toggles, late wrapper creation, reconnect hit testing and mapped properties, the framework's unparented replacement-platform-view lifecycle, a wrapper moved to another attached `Panel`, and a detached wrapper. - Failure-first reconnect validation: temporarily removing the reconnect rebinding made all three reconnect-specific tests fail; restoring it made them pass. - Windows Layout device tests: **54/54 passed**, covering both `CascadeInputTransparent` modes and confirming that the wrapper remains hit-testable for child interaction. - Windows Core tests: **1,980 passed, 0 failed, 111 skipped**; the exact CI-reported Slider case and all 90 Slider tests passed locally. - Windows Appium test and HostApp builds completed with **0 warnings and 0 errors**, and both Issue21384 tests are discovered. The reporter-faithful Label pointer test is skipped on MacCatalyst because test remains cross-platform. - Local Appium execution remains blocked before interaction by WinAppDriver's invalid status response. The real Win32 `SendInput` harness below provides behavior-level evidence. Both recordings use the same `AbsoluteLayout` reproduction from #21384 and send five real Win32 mouse clicks to the overlaid button (`SendInput`, not UI Automation invoke). **Before — bug reproduced on parent commit `f377ff1c5e`:** all five clicks are sent, but the click handler receives none and the visible counter remains at 0. https://github.com/user-attachments/assets/d59d3346-355c-434f-b1ac-01c76c361ab1 **After — fixed behavior:** all five equivalent clicks reach the button and the visible counter advances from 0 to 5. The final production code was rerun with the same harness and again received **5/5** clicks. https://github.com/user-attachments/assets/610856db-c094-4657-b4ea-0985b96221dd - Do not update only the inner Windows platform view; a hit-testable `WrapperView` can still intercept input. - Do not disable the wrapper for `ILayoutHandler`; `LayoutPanel` intentionally preserves child interaction through its background-based mapper. - Do not re-enter virtual `SetupContainer()` during reconnect; derived handlers may repeat subscriptions or one-time side effects. - Do not add generalized parent-detachment logic for reconnect; the framework replacement platform view is unparented before mapper replay, and the surviving wrapper's parent must remain unchanged. Fixes #21384 @owaits, once the build artifacts are available, could you please try them with your original reproduction and let us know whether this resolves the issue for you? --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
<!-- 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! On Windows, propagate `InputTransparent` to a view's `WrapperView` as well as its inner platform view. This allows pointer input to pass through wrapped controls, including the default-template `Label` with a transparent background overlaying a `Button` from #21384. The fix preserves two important Windows behaviors: - `ILayoutHandler` continues using `LayoutPanel`'s specialized background-based input transparency, so transparent layouts do not disable their interactive child tree. - Reusing a disconnected handler preserves the existing wrapper and its visual-tree position while replacing its stale child with the newly created platform view. Framework reconnect creates and connects the replacement platform view unparented before mapper replay. The reconnect repair therefore only updates `WrapperView.Child`; it does not remove the platform view from arbitrary parent shapes or re-enter virtual `SetupContainer()` overrides that could duplicate subscriptions or one-time setup. Normal mapper replay restores Label/Image sizing and alignment after the child replacement. The default template's implicit `Label` style supplies a transparent background, which causes `LabelHandler` to create a Windows `WrapperView`. The existing mapper disabled hit testing only on the inner `TextBlock`; the effective wrapper remained hit-testable and intercepted pointer input. - Windows Label device tests: **42 total, 40 passed, 0 failed, 2 skipped**. Coverage includes initial state, runtime toggles, late wrapper creation, reconnect hit testing and mapped properties, the framework's unparented replacement-platform-view lifecycle, a wrapper moved to another attached `Panel`, and a detached wrapper. - Failure-first reconnect validation: temporarily removing the reconnect rebinding made all three reconnect-specific tests fail; restoring it made them pass. - Windows Layout device tests: **54/54 passed**, covering both `CascadeInputTransparent` modes and confirming that the wrapper remains hit-testable for child interaction. - Windows Core tests: **1,980 passed, 0 failed, 111 skipped**; the exact CI-reported Slider case and all 90 Slider tests passed locally. - Windows Appium test and HostApp builds completed with **0 warnings and 0 errors**, and both Issue21384 tests are discovered. The reporter-faithful Label pointer test is skipped on MacCatalyst because test remains cross-platform. - Local Appium execution remains blocked before interaction by WinAppDriver's invalid status response. The real Win32 `SendInput` harness below provides behavior-level evidence. Both recordings use the same `AbsoluteLayout` reproduction from #21384 and send five real Win32 mouse clicks to the overlaid button (`SendInput`, not UI Automation invoke). **Before — bug reproduced on parent commit `f377ff1c5e`:** all five clicks are sent, but the click handler receives none and the visible counter remains at 0. https://github.com/user-attachments/assets/d59d3346-355c-434f-b1ac-01c76c361ab1 **After — fixed behavior:** all five equivalent clicks reach the button and the visible counter advances from 0 to 5. The final production code was rerun with the same harness and again received **5/5** clicks. https://github.com/user-attachments/assets/610856db-c094-4657-b4ea-0985b96221dd - Do not update only the inner Windows platform view; a hit-testable `WrapperView` can still intercept input. - Do not disable the wrapper for `ILayoutHandler`; `LayoutPanel` intentionally preserves child interaction through its background-based mapper. - Do not re-enter virtual `SetupContainer()` during reconnect; derived handlers may repeat subscriptions or one-time side effects. - Do not add generalized parent-detachment logic for reconnect; the framework replacement platform view is unparented before mapper replay, and the surviving wrapper's parent must remain unchanged. Fixes #21384 @owaits, once the build artifacts are available, could you please try them with your original reproduction and let us know whether this resolves the issue for you? --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
<!-- 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! On Windows, propagate `InputTransparent` to a view's `WrapperView` as well as its inner platform view. This allows pointer input to pass through wrapped controls, including the default-template `Label` with a transparent background overlaying a `Button` from #21384. The fix preserves two important Windows behaviors: - `ILayoutHandler` continues using `LayoutPanel`'s specialized background-based input transparency, so transparent layouts do not disable their interactive child tree. - Reusing a disconnected handler preserves the existing wrapper and its visual-tree position while replacing its stale child with the newly created platform view. Framework reconnect creates and connects the replacement platform view unparented before mapper replay. The reconnect repair therefore only updates `WrapperView.Child`; it does not remove the platform view from arbitrary parent shapes or re-enter virtual `SetupContainer()` overrides that could duplicate subscriptions or one-time setup. Normal mapper replay restores Label/Image sizing and alignment after the child replacement. The default template's implicit `Label` style supplies a transparent background, which causes `LabelHandler` to create a Windows `WrapperView`. The existing mapper disabled hit testing only on the inner `TextBlock`; the effective wrapper remained hit-testable and intercepted pointer input. - Windows Label device tests: **42 total, 40 passed, 0 failed, 2 skipped**. Coverage includes initial state, runtime toggles, late wrapper creation, reconnect hit testing and mapped properties, the framework's unparented replacement-platform-view lifecycle, a wrapper moved to another attached `Panel`, and a detached wrapper. - Failure-first reconnect validation: temporarily removing the reconnect rebinding made all three reconnect-specific tests fail; restoring it made them pass. - Windows Layout device tests: **54/54 passed**, covering both `CascadeInputTransparent` modes and confirming that the wrapper remains hit-testable for child interaction. - Windows Core tests: **1,980 passed, 0 failed, 111 skipped**; the exact CI-reported Slider case and all 90 Slider tests passed locally. - Windows Appium test and HostApp builds completed with **0 warnings and 0 errors**, and both Issue21384 tests are discovered. The reporter-faithful Label pointer test is skipped on MacCatalyst because test remains cross-platform. - Local Appium execution remains blocked before interaction by WinAppDriver's invalid status response. The real Win32 `SendInput` harness below provides behavior-level evidence. Both recordings use the same `AbsoluteLayout` reproduction from #21384 and send five real Win32 mouse clicks to the overlaid button (`SendInput`, not UI Automation invoke). **Before — bug reproduced on parent commit `f377ff1c5e`:** all five clicks are sent, but the click handler receives none and the visible counter remains at 0. https://github.com/user-attachments/assets/d59d3346-355c-434f-b1ac-01c76c361ab1 **After — fixed behavior:** all five equivalent clicks reach the button and the visible counter advances from 0 to 5. The final production code was rerun with the same harness and again received **5/5** clicks. https://github.com/user-attachments/assets/610856db-c094-4657-b4ea-0985b96221dd - Do not update only the inner Windows platform view; a hit-testable `WrapperView` can still intercept input. - Do not disable the wrapper for `ILayoutHandler`; `LayoutPanel` intentionally preserves child interaction through its background-based mapper. - Do not re-enter virtual `SetupContainer()` during reconnect; derived handlers may repeat subscriptions or one-time side effects. - Do not add generalized parent-detachment logic for reconnect; the framework replacement platform view is unparented before mapper replay, and the surviving wrapper's parent must remain unchanged. Fixes #21384 @owaits, once the build artifacts are available, could you please try them with your original reproduction and let us know whether this resolves the issue for you? --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
<!-- 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! On Windows, propagate `InputTransparent` to a view's `WrapperView` as well as its inner platform view. This allows pointer input to pass through wrapped controls, including the default-template `Label` with a transparent background overlaying a `Button` from #21384. The fix preserves two important Windows behaviors: - `ILayoutHandler` continues using `LayoutPanel`'s specialized background-based input transparency, so transparent layouts do not disable their interactive child tree. - Reusing a disconnected handler preserves the existing wrapper and its visual-tree position while replacing its stale child with the newly created platform view. Framework reconnect creates and connects the replacement platform view unparented before mapper replay. The reconnect repair therefore only updates `WrapperView.Child`; it does not remove the platform view from arbitrary parent shapes or re-enter virtual `SetupContainer()` overrides that could duplicate subscriptions or one-time setup. Normal mapper replay restores Label/Image sizing and alignment after the child replacement. The default template's implicit `Label` style supplies a transparent background, which causes `LabelHandler` to create a Windows `WrapperView`. The existing mapper disabled hit testing only on the inner `TextBlock`; the effective wrapper remained hit-testable and intercepted pointer input. - Windows Label device tests: **42 total, 40 passed, 0 failed, 2 skipped**. Coverage includes initial state, runtime toggles, late wrapper creation, reconnect hit testing and mapped properties, the framework's unparented replacement-platform-view lifecycle, a wrapper moved to another attached `Panel`, and a detached wrapper. - Failure-first reconnect validation: temporarily removing the reconnect rebinding made all three reconnect-specific tests fail; restoring it made them pass. - Windows Layout device tests: **54/54 passed**, covering both `CascadeInputTransparent` modes and confirming that the wrapper remains hit-testable for child interaction. - Windows Core tests: **1,980 passed, 0 failed, 111 skipped**; the exact CI-reported Slider case and all 90 Slider tests passed locally. - Windows Appium test and HostApp builds completed with **0 warnings and 0 errors**, and both Issue21384 tests are discovered. The reporter-faithful Label pointer test is skipped on MacCatalyst because test remains cross-platform. - Local Appium execution remains blocked before interaction by WinAppDriver's invalid status response. The real Win32 `SendInput` harness below provides behavior-level evidence. Both recordings use the same `AbsoluteLayout` reproduction from #21384 and send five real Win32 mouse clicks to the overlaid button (`SendInput`, not UI Automation invoke). **Before — bug reproduced on parent commit `f377ff1c5e`:** all five clicks are sent, but the click handler receives none and the visible counter remains at 0. https://github.com/user-attachments/assets/d59d3346-355c-434f-b1ac-01c76c361ab1 **After — fixed behavior:** all five equivalent clicks reach the button and the visible counter advances from 0 to 5. The final production code was rerun with the same harness and again received **5/5** clicks. https://github.com/user-attachments/assets/610856db-c094-4657-b4ea-0985b96221dd - Do not update only the inner Windows platform view; a hit-testable `WrapperView` can still intercept input. - Do not disable the wrapper for `ILayoutHandler`; `LayoutPanel` intentionally preserves child interaction through its background-based mapper. - Do not re-enter virtual `SetupContainer()` during reconnect; derived handlers may repeat subscriptions or one-time side effects. - Do not add generalized parent-detachment logic for reconnect; the framework replacement platform view is unparented before mapper replay, and the surviving wrapper's parent must remain unchanged. Fixes #21384 @owaits, once the build artifacts are available, could you please try them with your original reproduction and let us know whether this resolves the issue for you? --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
<!-- 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! On Windows, propagate `InputTransparent` to a view's `WrapperView` as well as its inner platform view. This allows pointer input to pass through wrapped controls, including the default-template `Label` with a transparent background overlaying a `Button` from #21384. The fix preserves two important Windows behaviors: - `ILayoutHandler` continues using `LayoutPanel`'s specialized background-based input transparency, so transparent layouts do not disable their interactive child tree. - Reusing a disconnected handler preserves the existing wrapper and its visual-tree position while replacing its stale child with the newly created platform view. Framework reconnect creates and connects the replacement platform view unparented before mapper replay. The reconnect repair therefore only updates `WrapperView.Child`; it does not remove the platform view from arbitrary parent shapes or re-enter virtual `SetupContainer()` overrides that could duplicate subscriptions or one-time setup. Normal mapper replay restores Label/Image sizing and alignment after the child replacement. The default template's implicit `Label` style supplies a transparent background, which causes `LabelHandler` to create a Windows `WrapperView`. The existing mapper disabled hit testing only on the inner `TextBlock`; the effective wrapper remained hit-testable and intercepted pointer input. - Windows Label device tests: **42 total, 40 passed, 0 failed, 2 skipped**. Coverage includes initial state, runtime toggles, late wrapper creation, reconnect hit testing and mapped properties, the framework's unparented replacement-platform-view lifecycle, a wrapper moved to another attached `Panel`, and a detached wrapper. - Failure-first reconnect validation: temporarily removing the reconnect rebinding made all three reconnect-specific tests fail; restoring it made them pass. - Windows Layout device tests: **54/54 passed**, covering both `CascadeInputTransparent` modes and confirming that the wrapper remains hit-testable for child interaction. - Windows Core tests: **1,980 passed, 0 failed, 111 skipped**; the exact CI-reported Slider case and all 90 Slider tests passed locally. - Windows Appium test and HostApp builds completed with **0 warnings and 0 errors**, and both Issue21384 tests are discovered. The reporter-faithful Label pointer test is skipped on MacCatalyst because test remains cross-platform. - Local Appium execution remains blocked before interaction by WinAppDriver's invalid status response. The real Win32 `SendInput` harness below provides behavior-level evidence. Both recordings use the same `AbsoluteLayout` reproduction from #21384 and send five real Win32 mouse clicks to the overlaid button (`SendInput`, not UI Automation invoke). **Before — bug reproduced on parent commit `f377ff1c5e`:** all five clicks are sent, but the click handler receives none and the visible counter remains at 0. https://github.com/user-attachments/assets/d59d3346-355c-434f-b1ac-01c76c361ab1 **After — fixed behavior:** all five equivalent clicks reach the button and the visible counter advances from 0 to 5. The final production code was rerun with the same harness and again received **5/5** clicks. https://github.com/user-attachments/assets/610856db-c094-4657-b4ea-0985b96221dd - Do not update only the inner Windows platform view; a hit-testable `WrapperView` can still intercept input. - Do not disable the wrapper for `ILayoutHandler`; `LayoutPanel` intentionally preserves child interaction through its background-based mapper. - Do not re-enter virtual `SetupContainer()` during reconnect; derived handlers may repeat subscriptions or one-time side effects. - Do not add generalized parent-detachment logic for reconnect; the framework replacement platform view is unparented before mapper replay, and the surviving wrapper's parent must remain unchanged. Fixes #21384 @owaits, once the build artifacts are available, could you please try them with your original reproduction and let us know whether this resolves the issue for you? --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
<!-- 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! On Windows, propagate `InputTransparent` to a view's `WrapperView` as well as its inner platform view. This allows pointer input to pass through wrapped controls, including the default-template `Label` with a transparent background overlaying a `Button` from #21384. The fix preserves two important Windows behaviors: - `ILayoutHandler` continues using `LayoutPanel`'s specialized background-based input transparency, so transparent layouts do not disable their interactive child tree. - Reusing a disconnected handler preserves the existing wrapper and its visual-tree position while replacing its stale child with the newly created platform view. Framework reconnect creates and connects the replacement platform view unparented before mapper replay. The reconnect repair therefore only updates `WrapperView.Child`; it does not remove the platform view from arbitrary parent shapes or re-enter virtual `SetupContainer()` overrides that could duplicate subscriptions or one-time setup. Normal mapper replay restores Label/Image sizing and alignment after the child replacement. The default template's implicit `Label` style supplies a transparent background, which causes `LabelHandler` to create a Windows `WrapperView`. The existing mapper disabled hit testing only on the inner `TextBlock`; the effective wrapper remained hit-testable and intercepted pointer input. - Windows Label device tests: **42 total, 40 passed, 0 failed, 2 skipped**. Coverage includes initial state, runtime toggles, late wrapper creation, reconnect hit testing and mapped properties, the framework's unparented replacement-platform-view lifecycle, a wrapper moved to another attached `Panel`, and a detached wrapper. - Failure-first reconnect validation: temporarily removing the reconnect rebinding made all three reconnect-specific tests fail; restoring it made them pass. - Windows Layout device tests: **54/54 passed**, covering both `CascadeInputTransparent` modes and confirming that the wrapper remains hit-testable for child interaction. - Windows Core tests: **1,980 passed, 0 failed, 111 skipped**; the exact CI-reported Slider case and all 90 Slider tests passed locally. - Windows Appium test and HostApp builds completed with **0 warnings and 0 errors**, and both Issue21384 tests are discovered. The reporter-faithful Label pointer test is skipped on MacCatalyst because test remains cross-platform. - Local Appium execution remains blocked before interaction by WinAppDriver's invalid status response. The real Win32 `SendInput` harness below provides behavior-level evidence. Both recordings use the same `AbsoluteLayout` reproduction from #21384 and send five real Win32 mouse clicks to the overlaid button (`SendInput`, not UI Automation invoke). **Before — bug reproduced on parent commit `f377ff1c5e`:** all five clicks are sent, but the click handler receives none and the visible counter remains at 0. https://github.com/user-attachments/assets/d59d3346-355c-434f-b1ac-01c76c361ab1 **After — fixed behavior:** all five equivalent clicks reach the button and the visible counter advances from 0 to 5. The final production code was rerun with the same harness and again received **5/5** clicks. https://github.com/user-attachments/assets/610856db-c094-4657-b4ea-0985b96221dd - Do not update only the inner Windows platform view; a hit-testable `WrapperView` can still intercept input. - Do not disable the wrapper for `ILayoutHandler`; `LayoutPanel` intentionally preserves child interaction through its background-based mapper. - Do not re-enter virtual `SetupContainer()` during reconnect; derived handlers may repeat subscriptions or one-time side effects. - Do not add generalized parent-detachment logic for reconnect; the framework replacement platform view is unparented before mapper replay, and the surviving wrapper's parent must remain unchanged. Fixes #21384 @owaits, once the build artifacts are available, could you please try them with your original reproduction and let us know whether this resolves the issue for you? --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
<!-- 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! On Windows, propagate `InputTransparent` to a view's `WrapperView` as well as its inner platform view. This allows pointer input to pass through wrapped controls, including the default-template `Label` with a transparent background overlaying a `Button` from #21384. The fix preserves two important Windows behaviors: - `ILayoutHandler` continues using `LayoutPanel`'s specialized background-based input transparency, so transparent layouts do not disable their interactive child tree. - Reusing a disconnected handler preserves the existing wrapper and its visual-tree position while replacing its stale child with the newly created platform view. Framework reconnect creates and connects the replacement platform view unparented before mapper replay. The reconnect repair therefore only updates `WrapperView.Child`; it does not remove the platform view from arbitrary parent shapes or re-enter virtual `SetupContainer()` overrides that could duplicate subscriptions or one-time setup. Normal mapper replay restores Label/Image sizing and alignment after the child replacement. The default template's implicit `Label` style supplies a transparent background, which causes `LabelHandler` to create a Windows `WrapperView`. The existing mapper disabled hit testing only on the inner `TextBlock`; the effective wrapper remained hit-testable and intercepted pointer input. - Windows Label device tests: **42 total, 40 passed, 0 failed, 2 skipped**. Coverage includes initial state, runtime toggles, late wrapper creation, reconnect hit testing and mapped properties, the framework's unparented replacement-platform-view lifecycle, a wrapper moved to another attached `Panel`, and a detached wrapper. - Failure-first reconnect validation: temporarily removing the reconnect rebinding made all three reconnect-specific tests fail; restoring it made them pass. - Windows Layout device tests: **54/54 passed**, covering both `CascadeInputTransparent` modes and confirming that the wrapper remains hit-testable for child interaction. - Windows Core tests: **1,980 passed, 0 failed, 111 skipped**; the exact CI-reported Slider case and all 90 Slider tests passed locally. - Windows Appium test and HostApp builds completed with **0 warnings and 0 errors**, and both Issue21384 tests are discovered. The reporter-faithful Label pointer test is skipped on MacCatalyst because test remains cross-platform. - Local Appium execution remains blocked before interaction by WinAppDriver's invalid status response. The real Win32 `SendInput` harness below provides behavior-level evidence. Both recordings use the same `AbsoluteLayout` reproduction from #21384 and send five real Win32 mouse clicks to the overlaid button (`SendInput`, not UI Automation invoke). **Before — bug reproduced on parent commit `f377ff1c5e`:** all five clicks are sent, but the click handler receives none and the visible counter remains at 0. https://github.com/user-attachments/assets/d59d3346-355c-434f-b1ac-01c76c361ab1 **After — fixed behavior:** all five equivalent clicks reach the button and the visible counter advances from 0 to 5. The final production code was rerun with the same harness and again received **5/5** clicks. https://github.com/user-attachments/assets/610856db-c094-4657-b4ea-0985b96221dd - Do not update only the inner Windows platform view; a hit-testable `WrapperView` can still intercept input. - Do not disable the wrapper for `ILayoutHandler`; `LayoutPanel` intentionally preserves child interaction through its background-based mapper. - Do not re-enter virtual `SetupContainer()` during reconnect; derived handlers may repeat subscriptions or one-time side effects. - Do not add generalized parent-detachment logic for reconnect; the framework replacement platform view is unparented before mapper replay, and the surviving wrapper's parent must remain unchanged. Fixes #21384 @owaits, once the build artifacts are available, could you please try them with your original reproduction and let us know whether this resolves the issue for you? --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
<!-- 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! On Windows, propagate `InputTransparent` to a view's `WrapperView` as well as its inner platform view. This allows pointer input to pass through wrapped controls, including the default-template `Label` with a transparent background overlaying a `Button` from #21384. The fix preserves two important Windows behaviors: - `ILayoutHandler` continues using `LayoutPanel`'s specialized background-based input transparency, so transparent layouts do not disable their interactive child tree. - Reusing a disconnected handler preserves the existing wrapper and its visual-tree position while replacing its stale child with the newly created platform view. Framework reconnect creates and connects the replacement platform view unparented before mapper replay. The reconnect repair therefore only updates `WrapperView.Child`; it does not remove the platform view from arbitrary parent shapes or re-enter virtual `SetupContainer()` overrides that could duplicate subscriptions or one-time setup. Normal mapper replay restores Label/Image sizing and alignment after the child replacement. The default template's implicit `Label` style supplies a transparent background, which causes `LabelHandler` to create a Windows `WrapperView`. The existing mapper disabled hit testing only on the inner `TextBlock`; the effective wrapper remained hit-testable and intercepted pointer input. - Windows Label device tests: **42 total, 40 passed, 0 failed, 2 skipped**. Coverage includes initial state, runtime toggles, late wrapper creation, reconnect hit testing and mapped properties, the framework's unparented replacement-platform-view lifecycle, a wrapper moved to another attached `Panel`, and a detached wrapper. - Failure-first reconnect validation: temporarily removing the reconnect rebinding made all three reconnect-specific tests fail; restoring it made them pass. - Windows Layout device tests: **54/54 passed**, covering both `CascadeInputTransparent` modes and confirming that the wrapper remains hit-testable for child interaction. - Windows Core tests: **1,980 passed, 0 failed, 111 skipped**; the exact CI-reported Slider case and all 90 Slider tests passed locally. - Windows Appium test and HostApp builds completed with **0 warnings and 0 errors**, and both Issue21384 tests are discovered. The reporter-faithful Label pointer test is skipped on MacCatalyst because test remains cross-platform. - Local Appium execution remains blocked before interaction by WinAppDriver's invalid status response. The real Win32 `SendInput` harness below provides behavior-level evidence. Both recordings use the same `AbsoluteLayout` reproduction from #21384 and send five real Win32 mouse clicks to the overlaid button (`SendInput`, not UI Automation invoke). **Before — bug reproduced on parent commit `f377ff1c5e`:** all five clicks are sent, but the click handler receives none and the visible counter remains at 0. https://github.com/user-attachments/assets/d59d3346-355c-434f-b1ac-01c76c361ab1 **After — fixed behavior:** all five equivalent clicks reach the button and the visible counter advances from 0 to 5. The final production code was rerun with the same harness and again received **5/5** clicks. https://github.com/user-attachments/assets/610856db-c094-4657-b4ea-0985b96221dd - Do not update only the inner Windows platform view; a hit-testable `WrapperView` can still intercept input. - Do not disable the wrapper for `ILayoutHandler`; `LayoutPanel` intentionally preserves child interaction through its background-based mapper. - Do not re-enter virtual `SetupContainer()` during reconnect; derived handlers may repeat subscriptions or one-time side effects. - Do not add generalized parent-detachment logic for reconnect; the framework replacement platform view is unparented before mapper replay, and the surviving wrapper's parent must remain unchanged. Fixes #21384 @owaits, once the build artifacts are available, could you please try them with your original reproduction and let us know whether this resolves the issue for you? --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
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!
Description of Change
On Windows, propagate
InputTransparentto a view'sWrapperViewas well as its inner platform view. This allows pointer input to pass through wrapped controls, including the default-templateLabelwith a transparent background overlaying aButtonfrom #21384.The fix preserves two important Windows behaviors:
ILayoutHandlercontinues usingLayoutPanel's specialized background-based input transparency, so transparent layouts do not disable their interactive child tree.Framework reconnect creates and connects the replacement platform view unparented before mapper replay. The reconnect repair therefore only updates
WrapperView.Child; it does not remove the platform view from arbitrary parent shapes or re-enter virtualSetupContainer()overrides that could duplicate subscriptions or one-time setup. Normal mapper replay restores Label/Image sizing and alignment after the child replacement.Root Cause
The default template's implicit
Labelstyle supplies a transparent background, which causesLabelHandlerto create a WindowsWrapperView. The existing mapper disabled hit testing only on the innerTextBlock; the effective wrapper remained hit-testable and intercepted pointer input.Tests
Panel, and a detached wrapper.CascadeInputTransparentmodes and confirming that the wrapper remains hit-testable for child interaction.SendInputharness below provides behavior-level evidence.Empirical Windows Validation
Both recordings use the same
AbsoluteLayoutreproduction from #21384 and send five real Win32 mouse clicks to the overlaid button (SendInput, not UI Automation invoke).Before — bug reproduced on parent commit
f377ff1c5e: all five clicks are sent, but the click handler receives none and the visible counter remains at 0.issue21384-before.mp4
After — fixed behavior: all five equivalent clicks reach the button and the visible counter advances from 0 to 5. The final production code was rerun with the same harness and again received 5/5 clicks.
issue21384-after.mp4
What NOT to Do
WrapperViewcan still intercept input.ILayoutHandler;LayoutPanelintentionally preserves child interaction through its background-based mapper.SetupContainer()during reconnect; derived handlers may repeat subscriptions or one-time side effects.Issues Fixed
Fixes #21384
Reporter Validation
@owaits, once the build artifacts are available, could you please try them with your original reproduction and let us know whether this resolves the issue for you?