Skip to content

Commit

Permalink
Cherry-pick 80d228d. rdar://problem/102218556
Browse files Browse the repository at this point in the history
    REGRESSION (255095@main): [iOS] 'caret-color: auto' displays a black caret color
    https://bugs.webkit.org/show_bug.cgi?id=247382
    rdar://101579150

    Reviewed by Wenson Hsieh.

    On iOS, the caret is drawn in the UIProcess, and the caret color is set using
    post-layout data on EditorState. The system default caret color is used whenever
    the Color is invalid.

    Prior to 255095@main, `RenderStyle::caretColor()` returned a Color, rather than
    a StyleColor, and 'currentcolor' was represented using an invalid Color. The
    initial value of caret color was the invalid Color, meaning that if no caret
    color was specified by the author, or a value of 'currentcolor' was specified,
    the system default caret color would be used.

    Now that `RenderStyle::caretColor()` returns a StyleColor rather than a Color,
    it must be resolved prior to its use. StyleColor is only aware of 'currentcolor',
    absolute colors, and system colors. Since there is no "invalid" StyleColor, the
    initial value is `StyleColor::currentColor()`. This color is then resolved to
    the value of the element's color property, which is commonly black ('CanvasText' in
    light mode). The UIProcess always receives a valid Color in the post-layout data,
    and does not use the system default caret color.

    To fix, return an invalid color when 'caret-color: auto' is specified. This
    ensures the UIProcess will prefer the system default caret color. Additionally,
    this solution preserves an improvement introduced by 255095@main, which is that
    explicitly specifying "caret-color: currentcolor" will customize the caret color.

    * LayoutTests/editing/caret/ios/caret-color-auto-expected.txt: Added.
    * LayoutTests/editing/caret/ios/caret-color-auto.html: Added.
    * LayoutTests/editing/caret/ios/caret-color-currentcolor-expected.txt: Added.
    * LayoutTests/editing/caret/ios/caret-color-currentcolor.html: Added.
    * Source/WebCore/editing/FrameSelection.cpp:
    (WebCore::CaretBase::computeCaretColor):

    Canonical link: https://commits.webkit.org/256281@main

Canonical link: https://commits.webkit.org/256138.44@safari-7615.1.12-branch
  • Loading branch information
pxlcoder authored and alancoon committed Nov 14, 2022
1 parent 0191d3f commit b2b4e9a
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 0 deletions.
10 changes: 10 additions & 0 deletions LayoutTests/editing/caret/ios/caret-color-auto-expected.txt
@@ -0,0 +1,10 @@
This test verifies that an 'auto' caret color uses the system default caret color on iOS.

On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".


PASS caretColor is "rgb(66, 107, 242)"
PASS successfullyParsed is true

TEST COMPLETE

48 changes: 48 additions & 0 deletions LayoutTests/editing/caret/ios/caret-color-auto.html
@@ -0,0 +1,48 @@
<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="../../../resources/ui-helper.js"></script>
<script src="../../../resources/js-test.js"></script>
<style>
body, html {
width: 100%;
height: 100%;
margin: 0;
}

#editor {
width: 250px;
font-size: 20px;
padding: 10px;
display: block;
border: 1px solid tomato;
caret-color: auto;
}
</style>
<script>
jsTestIsAsync = true;

addEventListener("load", async () => {
description("This test verifies that an 'auto' caret color uses the system default caret color on iOS.");

if (!window.testRunner)
return;

let editor = document.getElementById("editor");
await UIHelper.activateElementAndWaitForInputSession(editor);
await UIHelper.ensurePresentationUpdate();
caretColor = await UIHelper.selectionCaretBackgroundColor();

shouldBeEqualToString("caretColor", "rgb(66, 107, 242)");

editor.blur();
await UIHelper.waitForKeyboardToHide();
finishJSTest();
});
</script>
</head>
<body>
<div contenteditable id="editor"></div>
</body>
</html>
@@ -0,0 +1,10 @@
This test verifies the used caret color matches the value of an element's color property when 'caret-color: currentcolor' is explicitly specified.

On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".


PASS caretColor is "rgb(255, 0, 0)"
PASS successfullyParsed is true

TEST COMPLETE

49 changes: 49 additions & 0 deletions LayoutTests/editing/caret/ios/caret-color-currentcolor.html
@@ -0,0 +1,49 @@
<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="../../../resources/ui-helper.js"></script>
<script src="../../../resources/js-test.js"></script>
<style>
body, html {
width: 100%;
height: 100%;
margin: 0;
color: red;
}

#editor {
width: 250px;
font-size: 20px;
padding: 10px;
display: block;
border: 1px solid tomato;
caret-color: currentcolor;
}
</style>
<script>
jsTestIsAsync = true;

addEventListener("load", async () => {
description("This test verifies the used caret color matches the value of an element's color property when 'caret-color: currentcolor' is explicitly specified.");

if (!window.testRunner)
return;

let editor = document.getElementById("editor");
await UIHelper.activateElementAndWaitForInputSession(editor);
await UIHelper.ensurePresentationUpdate();
caretColor = await UIHelper.selectionCaretBackgroundColor();

shouldBeEqualToString("caretColor", "rgb(255, 0, 0)");

editor.blur();
await UIHelper.waitForKeyboardToHide();
finishJSTest();
});
</script>
</head>
<body>
<div contenteditable id="editor"></div>
</body>
</html>
2 changes: 2 additions & 0 deletions Source/WebCore/editing/FrameSelection.cpp
Expand Up @@ -1848,6 +1848,8 @@ Color CaretBase::computeCaretColor(const RenderStyle& elementStyle, const Node*
// On iOS, we want to fall back to the tintColor, and only override if CSS has explicitly specified a custom color.
#if PLATFORM(IOS_FAMILY) && !PLATFORM(MACCATALYST)
UNUSED_PARAM(node);
if (elementStyle.hasAutoCaretColor())
return { };
return elementStyle.colorResolvingCurrentColor(elementStyle.caretColor());
#else
RefPtr parentElement = node ? node->parentElement() : nullptr;
Expand Down

0 comments on commit b2b4e9a

Please sign in to comment.