Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 07e24414b519ed16b9978efe831fc90564782bd4
https://github.com/WebKit/WebKit/commit/07e24414b519ed16b9978efe831fc90564782bd4
Author: Joanne Pan <[email protected]>
Date: 2026-08-27 (Thu, 27 Aug 2026)
Changed paths:
A LayoutTests/editing/caret/caret-color-legibility-after-paste-expected.txt
A LayoutTests/editing/caret/caret-color-legibility-after-paste.html
M
LayoutTests/editing/pasteboard/copy-multiparagraph-with-background-color-expected.txt
M
LayoutTests/editing/pasteboard/do-not-copy-unnecessary-styles-2-expected.txt
M LayoutTests/editing/pasteboard/paste-dark-mode-color-filtered-expected.txt
M LayoutTests/editing/pasteboard/paste-dark-mode-color-filtered.html
M LayoutTests/editing/pasteboard/preserve-underline-color-expected.txt
M LayoutTests/fast/events/input-events-paste-rich-datatransfer-expected.txt
M LayoutTests/platform/glib/TestExpectations
M LayoutTests/platform/glib/editing/style/5065910-expected.txt
M
LayoutTests/platform/glib/fast/events/input-events-paste-rich-datatransfer-expected.txt
M
LayoutTests/platform/ios-26/fast/events/input-events-paste-rich-datatransfer-expected.txt
M LayoutTests/platform/ios/TestExpectations
M
LayoutTests/platform/ios/fast/events/input-events-paste-rich-datatransfer-expected.txt
M LayoutTests/platform/mac/editing/style/5065910-expected.txt
M LayoutTests/platform/mac/fast/events/ondrop-text-html-expected.txt
M LayoutTests/platform/win/TestExpectations
M LayoutTests/platform/win/editing/style/5065910-expected.txt
M Source/WebCore/editing/EditingStyle.cpp
M Source/WebCore/editing/FrameSelection.cpp
M Source/WebCore/editing/FrameSelection.h
M Source/WebCore/testing/Internals.cpp
M Source/WebCore/testing/Internals.h
M Source/WebCore/testing/Internals.idl
Log Message:
-----------
mail.yahoo.com: Copying Text change caret color to text color from copied
article and make it difficult to find (when Dark Mode + Dark Text copied)
https://bugs.webkit.org/show_bug.cgi?id=322506
rdar://174933173
Reviewed by Ryosuke Niwa and Wenson Hsieh.
The problem:
Copying dark text from a light page and pasting into an editor that themes
itself dark via author CSS, such as mail.yahoo.com's compose body, leaves the
caret painted in the pasted text's color against the dark surface. On Yahoo,
with text pasted from https://www.phoronix.com/news/Linux-6.19-KVM, that is an
rgb(18, 18, 18) caret on rgb(50, 50, 50), 1.46:1. Two things cause it:
- Copy serializes caret-color: auto as the color it resolved to, so it arrives
in the destination as an author declaration and the code paths conditioned on
the value being auto no longer apply. Because auto resolves to currentColor,
the color that lands is one chosen against the source page's background and
then used against a different one.
- An inline box's background covers only the text on each line, so a caret
positioned past the end of that box sits on the editor's surface while still
using the color chosen for white. A line that wrapped keeps its trailing space
inside the box, so the caret is only past the edge where no such space
follows, as at the end of the pasted run.
The fix:
Drop caret-color from the wrapping style in
EditingStyle::wrappingStyleForSerialization, in the annotating branch, when the
copy context computed to auto.
In CaretBase::computeCaretColor, when caret-color is auto, treat an inline
ancestor's opaque background as sitting behind the caret when the caret's
midpoint along the inline axis falls inside one of that inline's boxes. The
caret
rect picks up in-flow position offsets on the way to the caret painter through
offsetFromContainer, while an inline's display box rect does not, so the box
rects are translated by the same offsets before comparing. Walking outward, the
first opaque inline that does cover the caret wins. Where none reaches it, use
the style that would have applied without those inlines. Otherwise measure
against the background that does reach it and substitute a color clearing 3:1.
The caret painter's own color is preferred, so an editor that themes itself
keeps
painting the caret the color it already uses elsewhere. The system accent comes
next, and then black or white, because four of the eight macOS accent colors
fall
short of 3:1 against one surface or the other.
The accumulation starts at the parent when the node's renderer is a RenderText,
because RenderText::style() returns its parent's style and the innermost
background would otherwise be counted twice.
Only auto is adjusted. CSS UI 4 ยง 5.2.1
(https://drafts.csswg.org/css-ui-4/#caret-color) permits it there, "User agents
may automatically adjust the color of caret to ensure good visibility and
contrast with the surrounding content", and rules it out for an explicit value:
"The caret is colored with the specified color."
The wrapping style is the right place for the removal because it sits downstream
of both base style computations. The other candidate, the
EditingStyle(Position, PropertiesToInclude) constructor, is upstream of them.
Removing the property there deletes an authored caret-color: transparent through
prepareToApplyAt, which compares caret-color without first checking that the
base
style has the property, a guard extractPropertiesNotIn does have. It also stops
extractPropertiesNotIn subtracting the property at all, serializing caret-color
into copy and paste across a shadow boundary where there had been none.
Measured with internals.paintedCaretColor(), which is added because the painted
color
is not observable from computed style. Against the editor's rgb(50, 50, 50) the
pasted rgb(68, 68, 68) caret is 1.32:1. Right after paste, after inserting a
paragraph, after typing a character, and at the end of a wrapped run it becomes
the editor's own rgb(253, 253, 253) at 12.6:1. Mid-run, where the caret really
is
over the pasted white background, it stays rgb(68, 68, 68) at 9.7:1. A source
page with no declared background has no white to inherit from, and the accent
substitutes at 3.2:1.
Content copied by a build without this change carries an explicit caret-color,
which is an author declaration and is left alone, so pasting from an older build
or an existing draft is unchanged.
The test asserts a contrast ratio. It does not assert exact colors, because the
accent comes from NSColor.controlAccentColor at runtime and the test harness
does
not pin it. It is skipped where HAVE(REDESIGNED_TEXT_CURSOR) is off, and on iOS,
which paints the caret in the tint color.
Blink resolves caret-color with no contrast fallback. In
caret_display_item_client.cc it calls ResolveColor, and the only adjustment is a
0.5 alpha for block carets. Gecko has contrast helpers, RelativeLuminanceUtils
and NS_LUMINOSITY_DIFFERENCE, applied to selection text and theme colors. Its
caret path leaves the color alone, and nsIFrame::GetCaretColorAt returns the
computed value unmodified.
Test: editing/caret/caret-color-all-configurations.html
* LayoutTests/editing/caret/caret-color-all-configurations-expected.txt: Added.
* LayoutTests/editing/caret/caret-color-all-configurations.html: Added.
*
LayoutTests/editing/pasteboard/copy-multiparagraph-with-background-color-expected.txt:
* LayoutTests/editing/pasteboard/do-not-copy-unnecessary-styles-2-expected.txt:
* LayoutTests/editing/pasteboard/paste-dark-mode-color-filtered-expected.txt:
* LayoutTests/editing/pasteboard/paste-dark-mode-color-filtered.html:
* LayoutTests/editing/pasteboard/preserve-underline-color-expected.txt:
* LayoutTests/fast/events/input-events-paste-rich-datatransfer-expected.txt:
* LayoutTests/platform/glib/editing/style/5065910-expected.txt:
* LayoutTests/platform/mac/editing/style/5065910-expected.txt:
* LayoutTests/platform/mac/fast/events/ondrop-text-html-expected.txt:
* LayoutTests/platform/win/editing/style/5065910-expected.txt:
* Source/WebCore/editing/EditingStyle.cpp:
(WebCore::EditingStyle::wrappingStyleForSerialization):
* Source/WebCore/editing/FrameSelection.cpp:
(WebCore::backgroundPaintsUnderCaret):
(WebCore::rendererSkippingInlinesNotPaintingUnderCaret):
(WebCore::CaretBase::computeCaretColor):
(WebCore::caretColorForNode):
(WebCore::FrameSelection::paintedCaretColor):
(WebCore::CaretBase::paintCaret const):
* Source/WebCore/editing/FrameSelection.h:
* Source/WebCore/rendering/ios/RenderThemeIOS.mm:
(WebCore::RenderThemeIOS::autocorrectionReplacementMarkerColor const):
* Source/WebCore/testing/Internals.cpp:
(WebCore::Internals::caretColor):
* Source/WebCore/testing/Internals.h:
* Source/WebCore/testing/Internals.idl:
* Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::getPlatformEditorState const):
* Source/WebKitLegacy/mac/WebView/WebFrame.mm:
(-[WebFrame caretColor]):
Canonical link: https://commits.webkit.org/319975@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications