Skip to content

Commit

Permalink
Cherry-pick 29bdd50. rdar://problem/113604753
Browse files Browse the repository at this point in the history
    Cherry-pick 92ab433. rdar://problem/113036183

        [WebKit] [iOS] Respect `NSUnderlineStyleAttributeName` when setting attributed marked text
        https://bugs.webkit.org/show_bug.cgi?id=259604
        rdar://113036183

        Reviewed by Richard Robinson.

        After the changes in rdar://108610748, UIKit will use `NSUnderlineStyle` with an attribute value of
        `NSUnderlineStyleThick` to indicate "highlighted" segments of marked text when live conversion is
        active. Currently, our code only checks against `NSBackgroundColor`, so without the changes in this
        patch, it would no longer be possible to know which segment in marked text is the selected segment
        when using live conversion.

        Fix this by checking for this case, alongside the existing `NSBackgroundColor` check.

        Test: KeyboardInputTests.MarkedTextSegmentsWithUnderlines

        * Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm:
        (extractUnderlines):
        * Tools/TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm:

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

Identifier: 265870.280@safari-7616-branch
  • Loading branch information
whsieh authored and MyahCobbs committed Aug 9, 2023
1 parent 362c1d0 commit 9418a0b
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 2 deletions.
9 changes: 7 additions & 2 deletions Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Original file line number Diff line number Diff line change
Expand Up @@ -5729,8 +5729,13 @@ static BOOL shouldUseHighlightsForMarkedText(NSAttributedString *string)

Vector<WebCore::CompositionUnderline> underlines;
[string enumerateAttributesInRange:NSMakeRange(0, string.length) options:0 usingBlock:[&underlines](NSDictionary<NSAttributedStringKey, id> *attributes, NSRange range, BOOL *) {
bool thick = attributes[NSBackgroundColorAttributeName];
underlines.append({ static_cast<unsigned>(range.location), static_cast<unsigned>(NSMaxRange(range)), WebCore::CompositionUnderlineColor::GivenColor, WebCore::Color::black, thick });
underlines.append({
static_cast<unsigned>(range.location),
static_cast<unsigned>(NSMaxRange(range)),
WebCore::CompositionUnderlineColor::GivenColor,
WebCore::Color::black,
[attributes[NSUnderlineStyleAttributeName] isEqual:@(NSUnderlineStyleThick)] || attributes[NSBackgroundColorAttributeName]
});
}];

std::sort(underlines.begin(), underlines.end(), [](auto& a, auto& b) {
Expand Down
73 changes: 73 additions & 0 deletions Tools/TestWebKitAPI/Tests/ios/KeyboardInputTestsIOS.mm
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#if PLATFORM(IOS_FAMILY)

#import "CGImagePixelReader.h"
#import "PlatformUtilities.h"
#import "TestCocoa.h"
#import "TestInputDelegate.h"
Expand All @@ -41,6 +42,7 @@
#import <WebKit/_WKProcessPoolConfiguration.h>
#import <WebKitLegacy/WebEvent.h>
#import <cmath>
#import <pal/spi/cocoa/NSAttributedStringSPI.h>

namespace TestWebKitAPI {

Expand Down Expand Up @@ -1049,6 +1051,77 @@ static BOOL shouldSimulateKeyboardInputOnTextInsertionOverride(id, SEL)
Util::runFor(100_ms);
}

#if HAVE(REDESIGNED_TEXT_CURSOR)

TEST(KeyboardInputTests, MarkedTextSegmentsWithUnderlines)
{
auto frame = CGRectMake(0, 0, 100, 100);
auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:frame configuration:configuration.get() addToWindow:NO]);

auto window = adoptNS([[UIWindow alloc] initWithFrame:[webView frame]]);
[window addSubview:webView.get()];

[webView _setEditable:YES];
[webView synchronouslyLoadHTMLString:@"<meta name='viewport' content='width=device-width'><meta charset='utf-8'><body>なんですか?</body>"];
[webView selectAll:nil];

auto setMarkedTextWithUnderlines = [&](NSUnderlineStyle firstUnderlineStyle, NSUnderlineStyle secondUnderlineStyle) {
auto composition = adoptNS([[NSMutableAttributedString alloc] initWithString:@"なんですか?"]);
[composition addAttributes:@{
NSMarkedClauseSegmentAttributeName: @(0),
NSUnderlineStyleAttributeName: @(firstUnderlineStyle),
NSUnderlineColorAttributeName: UIColor.tintColor
} range:NSMakeRange(0, 5)];

[composition addAttributes:@{
NSMarkedClauseSegmentAttributeName: @(1),
NSUnderlineStyleAttributeName: @(secondUnderlineStyle),
NSUnderlineColorAttributeName: UIColor.tintColor
} range:NSMakeRange(5, 1)];

[[webView textInputContentView] setAttributedMarkedText:composition.get() selectedRange:NSMakeRange(0, 6)];
};

setMarkedTextWithUnderlines(NSUnderlineStyleSingle, NSUnderlineStyleThick);
[webView waitForNextPresentationUpdate];

auto snapshotConfiguration = adoptNS([[WKSnapshotConfiguration alloc] init]);
[snapshotConfiguration setAfterScreenUpdates:YES];

auto takeSnapshot = [&] {
__block RetainPtr<CGImage> result;
__block bool done = false;
[webView takeSnapshotWithConfiguration:snapshotConfiguration.get() completionHandler:^(UIImage *snapshot, NSError *error) {
result = snapshot.CGImage;
done = true;
}];
Util::run(&done);
return result;
};

auto snapshotBefore = takeSnapshot();

setMarkedTextWithUnderlines(NSUnderlineStyleThick, NSUnderlineStyleSingle);
[webView waitForNextPresentationUpdate];

auto snapshotAfter = takeSnapshot();

CGImagePixelReader snapshotReaderBefore { snapshotBefore.get() };
CGImagePixelReader snapshotReaderAfter { snapshotAfter.get() };

unsigned numberOfDifferentPixels = 0;
for (int x = 0; x < 200; ++x) {
for (int y = 0; y < 200; ++y) {
if (snapshotReaderBefore.at(x, y) != snapshotReaderAfter.at(x, y))
numberOfDifferentPixels++;
}
}
EXPECT_GT(numberOfDifferentPixels, 0U);
}

#endif // HAVE(REDESIGNED_TEXT_CURSOR)

} // namespace TestWebKitAPI

#endif // PLATFORM(IOS_FAMILY)

0 comments on commit 9418a0b

Please sign in to comment.