[iOS/MacCatalyst] Fix Entry clear button appearing dimmed compared to TextColor - #36472
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 36472Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 36472" |
|
Hey there @@SyedAbdulAzeemSF4852! 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 |
|
Azure Pipelines successfully started running 3 pipeline(s). |
This comment has been minimized.
This comment has been minimized.
kubaflo
left a comment
There was a problem hiding this comment.
Could you please check the ai's suggestions?
Surveyed all 42 maui-copilot (def 27723) builds on improved-reviewer and found two classes of false-FAILED gate verdicts that should be INCONCLUSIVE: 1. New-snapshot VisualTest PRs (e.g. PR #36448, build 14627406): a run that reports SOME real passes AND failures where every failure is a brand-new VerifyScreenshot with no committed baseline ("Baseline snapshot not yet created") took the trust-the-counts path in Get-TestResultFromOutput and returned a plain N-test FAIL, never reaching the baseline-missing check lower in the function (Passed=2, Failed=30 -> FAILED). Now, inside that path, if baseline-missing occurrences >= failCount the run is classified SnapshotBaselineMissing (INCONCLUSIVE). A real pixel diff against an EXISTING baseline prints 'Snapshot different than baseline' (not 'not yet created'), so mixed/real-diff runs still correctly FAIL. 2. Device-test APP_CRASH (PR #36472, build 14627403): both without-fix and with-fix crashed identically with 'XHarness exit code: 80 (APP_CRASH)' and Failed=0 (app died during instrumentation, no test result) yet the pair was scored a genuine FAILED. Added exit-80 to the env-error patterns so an app crash is treated as infra/INCONCLUSIVE, consistent with the existing exit-83/78 and 'Application test run crashed' handling. Both convert false-FAILED -> non-blocking INCONCLUSIVE. Unit-tested 6 scenarios (new-snapshots, real-diff guard, mixed guard, clean pass, exit-80, exit-83 regression) — all pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 15d2af20-e4ab-4e88-9011-cfbd83513bc0
MauiBot
left a comment
There was a problem hiding this comment.
Expert Review — 3 findings
See inline comments for details.
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 , I've verified the failures and resaved the valid ios-26 snapshots. |
This comment has been minimized.
This comment has been minimized.
MauiBot
left a comment
There was a problem hiding this comment.
AI Review Summary
@SyedAbdulAzeemSF4852 — new AI review results are available based on this last commit:
ea5c5fb. To request a fresh review after new comments or commits, comment/review rerun.
🗂️ Review Sessions — click to expand
🚦 Gate — Test Before & After Fix
Gate Result: ✅ PASSED
Platform: IOS · Base: main · Merge base: 76c77c03
| Test | Without Fix (expect FAIL) | With Fix (expect PASS) |
|---|---|---|
📱 EntryHandlerTests (ClearButtonTintMatchesTextColorAtFullOpacity) Category=Entry |
✅ FAIL — 197s | ✅ PASS — 68s |
🔴 Without fix — 📱 EntryHandlerTests (ClearButtonTintMatchesTextColorAtFullOpacity): FAIL ✅ · 197s
(no coded error found; showing last 1200 chars)
,
"exitCode": 1,
"exitCodeName": "TESTS_FAILED",
"platform": "apple",
"device": "iPhone 11 Pro",
"deviceOsVersion": "26.5",
"files": [
{
"name": "test-ios-simulator-64_26.5-991E30C3-4746-420C-9874-F267A4326F45.log",
"type": "executionlog"
},
{
"name": "list-ios-simulator-64_26.5-20260720_150232.log",
"type": "devicelist"
},
{
"name": "test-ios-simulator-64_26.5-20260720_150239.log",
"type": "testlog"
},
{
"name": "iPhone 11 Pro.log",
"type": "systemlog"
},
{
"name": "Microsoft.Maui.Core.DeviceTests.log",
"type": "systemlog"
},
{
"name": "com.microsoft.maui.core.devicetests.log",
"type": "applicationlog"
},
{
"name": "xunit-test-ios-simulator-64_26.5-20260720_150239.xml",
"type": "xmllog"
}
]
}
<<XHARNESS_RESULT_END>>
XHarness exit code: 1 (TESTS_FAILED)
Passed: 0
Failed: 0
Tests completed with exit code: 1
🟢 With fix — 📱 EntryHandlerTests (ClearButtonTintMatchesTextColorAtFullOpacity): PASS ✅ · 68s
(no coded error found; showing last 1200 chars)
neName": "Q67QJ3X3NH-1",
"exitCode": 0,
"exitCodeName": "SUCCESS",
"platform": "apple",
"device": "iPhone 11 Pro",
"deviceOsVersion": "26.5",
"files": [
{
"name": "test-ios-simulator-64_26.5-991E30C3-4746-420C-9874-F267A4326F45.log",
"type": "executionlog"
},
{
"name": "list-ios-simulator-64_26.5-20260720_150408.log",
"type": "devicelist"
},
{
"name": "test-ios-simulator-64_26.5-20260720_150413.log",
"type": "testlog"
},
{
"name": "iPhone 11 Pro.log",
"type": "systemlog"
},
{
"name": "Microsoft.Maui.Core.DeviceTests.log",
"type": "systemlog"
},
{
"name": "com.microsoft.maui.core.devicetests.log",
"type": "applicationlog"
},
{
"name": "xunit-test-ios-simulator-64_26.5-20260720_150413.xml",
"type": "xmllog"
}
]
}
<<XHARNESS_RESULT_END>>
XHarness exit code: 0
Passed: 233
Failed: 0
Tests completed successfully
📁 Fix files reverted (1 files)
src/Core/src/Platform/iOS/TextFieldExtensions.cs
📱 UI Tests — Entry,ViewBaseTests
Detected UI test categories: Entry,ViewBaseTests
❌ Deep UI tests — 221 passed, 3 failed across 2 categories on platform-pool agent (replaces in-process counts above).
🧪 UI Test Execution Results (deep, platform pool)
| Category | Tests | Snapshot diffs |
|---|---|---|
Entry |
109/113 (3 ❌) | — |
ViewBaseTests |
112/112 ✓ | — |
🔍 AI analysis of failures — PR-related vs unrelated
🔍 AI-generated triage (GitHub Copilot CLI) — a heuristic judgement of whether each deep UI test failure is connected to this PR's changes. Verify before relying on it.
Likely unrelated: the failures appear pre-existing, flaky, or infrastructure.
- ● Unrelated — iOS Entry/Editor element lookup timeouts (3 tests): although this PR touches iOS Entry clear-button tinting and related snapshot baselines, these failures are Appium
NoSuchElementException/Timed out waiting for elementduring test-page element discovery in keyboard/placeholder-theme scenarios, not clear-button rendering or the modifiedTextFieldExtensions.UpdateClearButtonColorpath.
Strongest signal: all failures are missing-element/timeouts, while the PR changes only clear-button image tint opacity and snapshots for clear-button/text-keyboard visuals.
❌ Entry — 3 failed tests
KeepEditorCursorAboveKeyboardInScrollView
OpenQA.Selenium.NoSuchElementException : An element could not be located on the page using the given search parameters.; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
at OpenQA.Selenium.WebDriver.UnpackAndThrowOnError(Response errorResponse, String commandToExecute)
at OpenQA.Selenium.WebDriver.ExecuteAsync(String driverCommandToExecute, Dictionary`2 parameters)
at OpenQA.Selenium.Appium.AppiumDriver.Execute(String driverCommandToExecute, Dictionary`2 parameters)
at OpenQA.Selenium.WebDriver.FindElement(String mechanism, String value)
at OpenQA.Selenium.Appium.AppiumDriver.FindElement(String by, String value)
at OpenQA.Selenium.Appium.MobileBy.FindElement(ISearchContext context)
at OpenQA.Selenium.WebDriver.FindElement(By by)
at OpenQA.Selenium.Appium.AppiumDriver.FindElement(By by)
at Microsoft.Maui.TestCases.Tests.KeyboardScrolling.CloseiOSEditorKeyboard(AppiumDr
...
EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnThemeChange
System.TimeoutException : Timed out waiting for element...
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2757
at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2784
at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 793
at Microsoft.Maui.TestCases.Tests.Issues.Issue31889.EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnThemeChange() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue31889.cs:line 50
at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target,
...
KeepEditorCursorAboveKeyboardInGrid
OpenQA.Selenium.NoSuchElementException : An element could not be located on the page using the given search parameters.; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
at OpenQA.Selenium.WebDriver.UnpackAndThrowOnError(Response errorResponse, String commandToExecute)
at OpenQA.Selenium.WebDriver.ExecuteAsync(String driverCommandToExecute, Dictionary`2 parameters)
at OpenQA.Selenium.Appium.AppiumDriver.Execute(String driverCommandToExecute, Dictionary`2 parameters)
at OpenQA.Selenium.WebDriver.FindElement(String mechanism, String value)
at OpenQA.Selenium.Appium.AppiumDriver.FindElement(String by, String value)
at OpenQA.Selenium.Appium.MobileBy.FindElement(ISearchContext context)
at OpenQA.Selenium.WebDriver.FindElement(By by)
at OpenQA.Selenium.Appium.AppiumDriver.FindElement(By by)
at Microsoft.Maui.TestCases.Tests.KeyboardScrolling.CloseiOSEditorKeyboard(AppiumDr
...
📎 Download drop-deep-uitests artifact (TRX + snapshot diffs)
🔗 Regression Cross-Reference
🔍 Regression Cross-Reference
⚠ Overlaps with prior bug-fix PRs — same files modified, but no exact line revert detected.
| File | Fix PR | Fixed issue(s) |
|---|---|---|
src/Core/src/Platform/iOS/TextFieldExtensions.cs |
#32889 | #32886 |
🧪 Regression Tests to Verify
These tests were added by the overlapping fix PRs. Running them to verify no side-effect regressions:
| Fix PR | Type | Test | Filter |
|---|---|---|---|
| #32889 | UITest | Issue32886 | Issue32886 |
🧪 Regression Test Results
❌ FAILED — 0 passed, 1 failed, 0 skipped
| Fix PR | Test | Type | Result |
|---|---|---|---|
| #32889 | Issue32886 | UITest | ❌ FAILED |
📋 Pre-Flight — Context & Validation
Issue: #35517 - [MacCatalyst] [Entry] ClearButtonVisibility color appears dimmed compared to TextColor
PR: #36472 - [WIP][iOS/MacCatalyst] Fix Entry clear button appearing dimmed compared to TextColor
Platforms Affected: iOS, MacCatalyst
Files Changed: 1 implementation, 1 device-test, 15 iOS snapshot files
Key Findings
- The PR changes
src/Core/src/Platform/iOS/TextFieldExtensions.cs, which compiles for both iOS and MacCatalyst, to tint the Entry clear-button image from a CGImage-backed copy before applyingCGBlendMode.SourceIn. - The linked issue is MacCatalyst-focused, but the requested try-fix validation platform is iOS. Regression testing must also run
BuildAndRunHostApp.ps1 -Platform ios -TestFilter "Issue32886"after any candidate's primary test passes. - The PR adds an iOS device test (
ClearButtonTintMatchesTextColorAtFullOpacity) and updates iOS/iOS-26 snapshots, but public review context indicates MacCatalyst snapshot coverage remains a concern. - Local checkout contents did not match PR #36472; PR-specific context was gathered from the public PR ref
refs/remotes/origin/pr/36472and public GitHub REST metadata.
Code Review Summary
Verdict: NEEDS_CHANGES
Confidence: low
Errors: 2 | Warnings: 0 | Suggestions: 0
Key code review findings:
- ✗
src/Core/src/Platform/iOS/TextFieldExtensions.cs:284-291falls back to drawing the originalUIImagewhenimage.CGImageis null, preserving the old reduced-alpha path for symbol/vector/CI-backed images. - ✗
src/Core/src/Platform/iOS/TextFieldExtensions.cs:284affects MacCatalyst too, but only iOS/iOS-26 snapshots were updated even though the linked issue and PR validation claim MacCatalyst behavior.
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #36472 | Draw a CGImage-backed UIImage copy of the clear-button glyph, center it, then fill with TextColor using SourceIn. |
✅ PASSED (Gate) | src/Core/src/Platform/iOS/TextFieldExtensions.cs, src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs, iOS snapshots |
Original PR; gate result supplied by caller. |
🔬 Code Review — Deep Analysis
Code Review — PR #36472
Independent Assessment
What this changes: Re-tints the iOS/MacCatalyst Entry clear button by drawing a CGImage-backed copy before the SourceIn fill, adds an iOS device test asserting full alpha, and updates iOS/iOS-26 UI snapshots.
Inferred motivation: Fix the clear button looking dimmer than Entry.TextColor.
Reconciliation with PR Narrative
Author claims: Fixes dim clear-button tint on iOS/MacCatalyst by avoiding reduced-alpha drawing.
Agreement/disagreement: The intent matches the code, but the implementation still falls back to the old draw path when UIImage.CGImage is null, and MacCatalyst snapshot coverage is not updated despite the PR claiming Mac validation.
Prior Review Reconciliation
| Prior ❌ Error Finding | Source | Status | Evidence |
|---|---|---|---|
CGImage == null fallback preserves old dim-alpha path |
MauiBot inline [major] |
❌ Unresolved | TextFieldExtensions.cs:284-286 still uses : image, then bitmapImage.Draw(...). |
| MacCatalyst snapshot/baseline coverage missing | MauiBot inline [major]/[moderate], expert reviewer |
❌ Unresolved | PR updates only TestCases.iOS.Tests/snapshots/...; existing TestCases.Mac.Tests/snapshots/mac/EntryClearButtonColor...png files are unchanged. |
| iOS-26 snapshots missing | MauiBot inline [major] |
✅ Fixed | Latest diff includes snapshots/ios-26/* updates. |
Blast Radius Assessment
- Runs for all instances: No; only Entries with
ClearButtonVisibility.WhileEditingand non-nullTextColor. - Startup impact: No.
- Static/shared state: No.
- Platform scope: iOS and MacCatalyst shared platform code.
CI Status
- Required-check result:
gh pr checks --requiredunavailable due missing auth. - Supplemental status: public GitHub checks show
maui-prand Build Analysis failed on headea5c5fb; AzDO timeline showsRunOniOS_BlazorDebug ARM64timed out after 45 minutes. - Classification: failure appears infrastructure/timeout, but CI is not green.
- Action taken: invoked
azdo-build-investigator;ci-analysisunavailable; confidence capped low.
Findings
❌ Error — Null-CGImage fallback leaves the original bug unfixed
src/Core/src/Platform/iOS/TextFieldExtensions.cs:284-291
The new code only avoids reduced-alpha drawing when image.CGImage is non-null. If UIKit supplies the clear-button glyph as a symbol/vector/CI-backed UIImage, bitmapImage becomes image, and bitmapImage.Draw(...) is exactly the old behavior the PR is trying to avoid. Please rasterize the non-CGImage case too, or prove/guard that this clear-button image is always CGImage-backed on supported iOS/MacCatalyst versions.
❌ Error — MacCatalyst baselines are not updated for shared MacCatalyst rendering change
src/Core/src/Platform/iOS/TextFieldExtensions.cs:284
This file compiles for both iOS and MacCatalyst, and the PR body claims Mac validation, but only iOS/iOS-26 snapshots are updated. Existing Mac snapshots for clear-button color scenarios under src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/ remain unchanged. Given the previous fix in this area was reverted for Mac Entry snapshot failures, please update/validate MacCatalyst baselines or scope the behavior away from MacCatalyst.
Failure-Mode Probing
- Null
CGImage: the code falls back toimage.Draw, so dim alpha can persist. - MacCatalyst UI tests: shared platform change can alter Mac clear-button screenshots while Mac baselines remain stale.
- TextColor reset: existing null reset path remains intact and covered by prior test.
- Handler reconnect: no new subscriptions/static state; no lifecycle accumulation seen.
Verdict: NEEDS_CHANGES
Confidence: low
Summary: The fix is directionally correct but still has an unresolved fallback path that can preserve the bug, and MacCatalyst coverage is incomplete for shared platform code. CI is also not green, though the observed failure appears to be an infrastructure timeout.
🛠️ Fix — Analysis & Comparison
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | try-fix-1 | Alpha-normalized raster tint: render source image to RGBA, normalize glyph alpha, recolor pixels to TextColor. |
1 file | Directly handles null-CGImage fallback, but is more complex and could not be validated because the isolated worktree failed the MAUI build-task guard. |
|
| 2 | try-fix-2 | Native-sized vector clear glyph: ignore source image alpha and draw a full-opacity vector X with CGContext. |
1 file | Avoids inherited alpha entirely, but risks visual drift from UIKit's private clear glyph. | |
| 3 | try-fix-3 | UIKit template clear-button tint: use AlwaysTemplate image plus UIButton.TintColor at the call site. |
1 file | Avoids custom bitmap generation, but likely conflicts with the PR's pixel/rendering-mode device-test assertions. | |
| PR | PR #36472 | Draw a CGImage-backed UIImage copy, center it, then tint with SourceIn. |
✅ PASSED (Gate) | 17 files | Original PR; gate result supplied by caller. Code review still flags null-CGImage fallback and MacCatalyst baseline certainty. |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| maui-expert-reviewer | 2 | No | NO NEW IDEAS: remaining viable fixes collapse into raster recoloring, vector replacement, template tinting, or CGImage/CoreGraphics mask compositing variants. |
Mandatory Regression Tests
| Candidate | Primary Test | Regression Test BuildAndRunHostApp.ps1 -Platform ios -TestFilter "Issue32886" |
Result |
|---|---|---|---|
| try-fix-1 | Blocked before test execution by missing/out-of-date MAUI build tasks in isolated worktree. | Not run because primary did not pass. | |
| try-fix-2 | Blocked before test execution by missing/out-of-date MAUI build tasks in isolated worktree. | Not run because primary did not pass. | |
| try-fix-3 | Blocked before test execution by missing/out-of-date MAUI build tasks in isolated worktree. | Not run because primary did not pass. |
Exhausted: Yes
Selected Fix: PR #36472 by default — no alternative candidate passed tests or was demonstrably better. However, code review recommends improving the PR's null-CGImage fallback and validating/updating MacCatalyst coverage before merge.
📝 Recommended PR Title & Description
Assessment: ✏️ Recommend updating — the current title still has a [WIP] prefix and the description should reflect the winning pr-plus-reviewer hardening/coverage requirements.
Recommended title
[iOS/MacCatalyst] Entry: Fix dimmed clear button tint
Recommended description
### Issue Details
- When an Entry control has a TextColor set and ClearButtonVisibility is enabled, the clear button (✕) appears faded/dimmed compared to the TextColor.
### Root Cause
- The clear button's image was being drawn directly into the tinting context at reduced opacity, and because CGBlendMode.SourceIn compositing caps the final color's alpha at the alpha of the shape it's masking against, that reduced opacity carried through to the final tinted color — making the clear button appear dim instead of matching TextColor at full opacity.
### Description of Change
- In GetClearButtonTintImage (TextFieldExtensions.cs), the code now builds a plain UIImage from the clear button image's underlying CGImage (preserving CurrentScale and Orientation) and draws that bitmap-backed copy instead of drawing the original image directly, before the existing SourceIn color-fill step — the clear button image now renders with full opacity.
- The fix also hardens the non-CGImage-backed UIImage path so it does not fall back to the old reduced-alpha drawing behavior.
- Because TextFieldExtensions.cs compiles for both iOS and MacCatalyst, the MacCatalyst clear-button baselines are validated and updated for the affected color scenarios.
### Issues Fixed
Fixes #35517
### Validated the behaviour in the following platforms
- [ ] Windows
- [ ] Android
- [x] iOS
- [x] Mac
### Output
| Platform | Before | After |
|----------|----------|----------|
| iOS | <img src="https://github.com/user-attachments/assets/3f4ac9be-0ec8-429b-8bdd-d381163d8119"> | <img src="https://github.com/user-attachments/assets/4a8897c3-0fc0-4ebf-9bf7-0aef1d359dff"> |
| Mac | <img src="https://github.com/user-attachments/assets/2a6c890a-7a72-4d5c-b7c8-fbbd6fa4cb32"> | <img src="https://github.com/user-attachments/assets/2a2318a4-b1dd-4ef5-8907-20befb57c907"> |
🏁 Report — Final Recommendation
Comparative Report — PR #36472
Candidates compared
| Rank | Candidate | Result | Assessment |
|---|---|---|---|
| 1 | pr-plus-reviewer |
Not regression-failed; based on the gate-passing PR fix plus expert feedback | Best technical candidate. It preserves the PR's successful CGImage-backed tinting behavior while requiring the non-CGImage fallback to be hardened and MacCatalyst baselines to be validated/updated. |
| 2 | pr |
✅ Gate passed on iOS | Best empirically validated candidate as submitted, but it leaves two major expert-review issues unresolved: fallback to the old dim path when UIImage.CGImage is null, and missing MacCatalyst baseline validation for a MacCatalyst-focused issue. |
| 3 | try-fix-1 |
Strongest independent alternative because it directly normalizes raster alpha and handles the null-CGImage concern, but it is more complex than the PR and was not validated due the isolated worktree build-task guard. |
|
| 4 | try-fix-3 |
Simpler UIKit-template approach, but likely conflicts with the PR's image/rendering-mode assertions and changes how tinting is represented in ImageForState. |
|
| 5 | try-fix-2 |
Avoids inherited source alpha entirely, but replaces UIKit's private clear-button glyph with custom vector geometry, making it the highest visual-drift risk. |
Regression-test rule
No try-fix-* candidate passed its primary test, so none reached the mandatory Issue32886 regression run. The raw PR is the only candidate with supplied passing gate evidence. No candidate is known to have failed the regression test, but all blocked/unvalidated alternatives rank below the PR-derived candidates.
Winning candidate
Winner: pr-plus-reviewer.
The winning path is to keep the PR's validated implementation strategy and apply the expert reviewer's required hardening/coverage feedback. This is preferable to switching to an unvalidated independent try-fix because all try-fix candidates were blocked before tests, and preferable to merging the raw PR unchanged because the expert review identified concrete remaining correctness and coverage gaps.
Required follow-up before merge
pr-plus-reviewer should be validated in a clean environment after applying the reviewer feedback, especially the MacCatalyst snapshot/baseline update. If that validation cannot be completed, the raw pr candidate remains the only empirically passing implementation but should not be treated as review-clean.
🧭 Next Steps — review latest findings
No alternative fix was selected for this run. Review the session findings and CI results before merging.
MauiBot
left a comment
There was a problem hiding this comment.
Expert Review — 2 findings
See inline comments for details.
|
Azure Pipelines: Successfully started running 1 pipeline(s). There may be pipelines that require an authorized user to comment /azp run to run. |
kubaflo
left a comment
There was a problem hiding this comment.
If it ready? It has [wip] in the title, so I'd rather ask :)
There was a problem hiding this comment.
Pull request overview
Fixes iOS/MacCatalyst Entry clear button (✕) tinting so it no longer appears dimmed when TextColor is set, aligning the rendered glyph opacity with the entry text.
Changes:
- Adjusts clear-button tint image generation to draw a bitmap-backed
UIImagebefore applying theSourceIntint fill, avoiding unintended alpha reduction. - Adds an iOS/MacCatalyst device test that asserts the tinted clear-button image contains fully opaque pixels (max alpha = 255).
Reviewed changes
Copilot reviewed 2 out of 17 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/Core/src/Platform/iOS/TextFieldExtensions.cs | Updates clear-button tint rendering to avoid reduced-alpha rasterization and preserve the expected visual intensity. |
| src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs | Adds a regression test validating clear-button tint opacity when TextColor is applied. |
| var bitmapImage = image.CGImage is CGImage cgImage | ||
| ? new UIImage(cgImage, image.CurrentScale, image.Orientation) | ||
| : image; | ||
| // bitmapImage's Size can be smaller than the original image's Size, so drawing it at | ||
| // CGPoint.Empty shifts it to the top-left instead of centering it. Center it manually |
| const int bitsPerComponent = 8; | ||
| const int bytesPerPixel = 4; // R, G, B, A (CGImageAlphaInfo.PremultipliedLast) | ||
| const int alphaByteOffset = 3; // A is the 4th byte within each RGBA pixel | ||
|
|
||
| var cgImage = image.CGImage; | ||
| Assert.NotNull(cgImage); | ||
|
|
||
| var width = (int)cgImage.Width; | ||
| var height = (int)cgImage.Height; | ||
| var bytesPerRow = width * bytesPerPixel; | ||
| var pixels = new byte[height * bytesPerRow]; | ||
|
|
||
| using var colorSpace = CGColorSpace.CreateDeviceRGB(); | ||
| using (var context = new CGBitmapContext(pixels, width, height, bitsPerComponent, bytesPerRow, colorSpace, CGImageAlphaInfo.PremultipliedLast)) | ||
| { | ||
| context.DrawImage(new CGRect(0, 0, width, height), cgImage); | ||
| } | ||
|
|
a4223bb to
c4e03cc
Compare
… TextColor (#36472) <!-- 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 an Entry control has a TextColor set and ClearButtonVisibility is enabled, the clear button (✕) appears faded/dimmed compared to the TextColor. ### Root Cause - The clear button's image was being drawn directly into the tinting context at reduced opacity, and because CGBlendMode.SourceIn compositing caps the final color's alpha at the alpha of the shape it's masking against, that reduced opacity carried through to the final tinted color — making the clear button appear dim instead of matching TextColor at full opacity. ### Description of Change - In GetClearButtonTintImage (TextFieldExtensions.cs), the code now builds a plain UIImage from the clear button image's underlying CGImage (preserving CurrentScale and Orientation) and draws that bitmap-backed copy instead of drawing the original image directly, before the existing SourceIn color-fill step — the clear button image now renders with full opacity. ### Issues Fixed Fixes #35517 ### Validated the behaviour in the following platforms - [ ] Windows - [ ] Android - [x] iOS - [x] Mac ### Output | Platform | Before | After | |----------|----------|----------| | iOS | <img src="https://github.com/user-attachments/assets/3f4ac9be-0ec8-429b-8bdd-d381163d8119"> | <img src="https://github.com/user-attachments/assets/4a8897c3-0fc0-4ebf-9bf7-0aef1d359dff"> | | Mac | <img src="https://github.com/user-attachments/assets/2a6c890a-7a72-4d5c-b7c8-fbbd6fa4cb32"> | <img src="https://github.com/user-attachments/assets/2a2318a4-b1dd-4ef5-8907-20befb57c907"> |
… TextColor (#36472) <!-- 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 an Entry control has a TextColor set and ClearButtonVisibility is enabled, the clear button (✕) appears faded/dimmed compared to the TextColor. ### Root Cause - The clear button's image was being drawn directly into the tinting context at reduced opacity, and because CGBlendMode.SourceIn compositing caps the final color's alpha at the alpha of the shape it's masking against, that reduced opacity carried through to the final tinted color — making the clear button appear dim instead of matching TextColor at full opacity. ### Description of Change - In GetClearButtonTintImage (TextFieldExtensions.cs), the code now builds a plain UIImage from the clear button image's underlying CGImage (preserving CurrentScale and Orientation) and draws that bitmap-backed copy instead of drawing the original image directly, before the existing SourceIn color-fill step — the clear button image now renders with full opacity. ### Issues Fixed Fixes #35517 ### Validated the behaviour in the following platforms - [ ] Windows - [ ] Android - [x] iOS - [x] Mac ### Output | Platform | Before | After | |----------|----------|----------| | iOS | <img src="https://github.com/user-attachments/assets/3f4ac9be-0ec8-429b-8bdd-d381163d8119"> | <img src="https://github.com/user-attachments/assets/4a8897c3-0fc0-4ebf-9bf7-0aef1d359dff"> | | Mac | <img src="https://github.com/user-attachments/assets/2a6c890a-7a72-4d5c-b7c8-fbbd6fa4cb32"> | <img src="https://github.com/user-attachments/assets/2a2318a4-b1dd-4ef5-8907-20befb57c907"> |
… TextColor (#36472) <!-- 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 an Entry control has a TextColor set and ClearButtonVisibility is enabled, the clear button (✕) appears faded/dimmed compared to the TextColor. ### Root Cause - The clear button's image was being drawn directly into the tinting context at reduced opacity, and because CGBlendMode.SourceIn compositing caps the final color's alpha at the alpha of the shape it's masking against, that reduced opacity carried through to the final tinted color — making the clear button appear dim instead of matching TextColor at full opacity. ### Description of Change - In GetClearButtonTintImage (TextFieldExtensions.cs), the code now builds a plain UIImage from the clear button image's underlying CGImage (preserving CurrentScale and Orientation) and draws that bitmap-backed copy instead of drawing the original image directly, before the existing SourceIn color-fill step — the clear button image now renders with full opacity. ### Issues Fixed Fixes #35517 ### Validated the behaviour in the following platforms - [ ] Windows - [ ] Android - [x] iOS - [x] Mac ### Output | Platform | Before | After | |----------|----------|----------| | iOS | <img src="https://github.com/user-attachments/assets/3f4ac9be-0ec8-429b-8bdd-d381163d8119"> | <img src="https://github.com/user-attachments/assets/4a8897c3-0fc0-4ebf-9bf7-0aef1d359dff"> | | Mac | <img src="https://github.com/user-attachments/assets/2a6c890a-7a72-4d5c-b7c8-fbbd6fa4cb32"> | <img src="https://github.com/user-attachments/assets/2a2318a4-b1dd-4ef5-8907-20befb57c907"> |
… TextColor (#36472) <!-- 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 an Entry control has a TextColor set and ClearButtonVisibility is enabled, the clear button (✕) appears faded/dimmed compared to the TextColor. ### Root Cause - The clear button's image was being drawn directly into the tinting context at reduced opacity, and because CGBlendMode.SourceIn compositing caps the final color's alpha at the alpha of the shape it's masking against, that reduced opacity carried through to the final tinted color — making the clear button appear dim instead of matching TextColor at full opacity. ### Description of Change - In GetClearButtonTintImage (TextFieldExtensions.cs), the code now builds a plain UIImage from the clear button image's underlying CGImage (preserving CurrentScale and Orientation) and draws that bitmap-backed copy instead of drawing the original image directly, before the existing SourceIn color-fill step — the clear button image now renders with full opacity. ### Issues Fixed Fixes #35517 ### Validated the behaviour in the following platforms - [ ] Windows - [ ] Android - [x] iOS - [x] Mac ### Output | Platform | Before | After | |----------|----------|----------| | iOS | <img src="https://github.com/user-attachments/assets/3f4ac9be-0ec8-429b-8bdd-d381163d8119"> | <img src="https://github.com/user-attachments/assets/4a8897c3-0fc0-4ebf-9bf7-0aef1d359dff"> | | Mac | <img src="https://github.com/user-attachments/assets/2a6c890a-7a72-4d5c-b7c8-fbbd6fa4cb32"> | <img src="https://github.com/user-attachments/assets/2a2318a4-b1dd-4ef5-8907-20befb57c907"> |





















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
Root Cause
Description of Change
Issues Fixed
Fixes #35517
Validated the behaviour in the following platforms
Output