Bug 194873 - [iOS] Callout menu overlaps in-page controls when editing a comment in github.com's issue tracker
Summary: [iOS] Callout menu overlaps in-page controls when editing a comment in github...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: HTML Editing (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Wenson Hsieh
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2019-02-20 14:59 PST by Wenson Hsieh
Modified: 2019-02-22 20:38 PST (History)
6 users (show)

See Also:


Attachments
Work in progress (30.73 KB, patch)
2019-02-20 21:45 PST, Wenson Hsieh
no flags Details | Formatted Diff | Diff
Work in progress (30.73 KB, patch)
2019-02-20 21:56 PST, Wenson Hsieh
no flags Details | Formatted Diff | Diff
Patch (33.64 KB, patch)
2019-02-21 09:00 PST, Wenson Hsieh
thorton: review+
Details | Formatted Diff | Diff
Patch for EWS (31.33 KB, patch)
2019-02-22 15:21 PST, Wenson Hsieh
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Wenson Hsieh 2019-02-20 14:59:54 PST
1. Go to a repository on https://github.com.
2. Open a new issue and insert a paragraph of text.
3. Select some text near the end of the first line.

Observed: black callout bar appears, obscuring header/bold/italic/quotation/code snippet/link buttons.
Expected: it would be great if I could still access these controls...
Comment 1 Wenson Hsieh 2019-02-20 21:29:54 PST
(In reply to Wenson Hsieh from comment #0)
> 1. Go to a repository on https://github.com.

Step 0: Use an iPad
Comment 2 Wenson Hsieh 2019-02-20 21:41:13 PST
<rdar://problem/46701974>
Comment 3 Wenson Hsieh 2019-02-20 21:45:42 PST
Created attachment 362590 [details]
Work in progress
Comment 4 Wenson Hsieh 2019-02-20 21:56:28 PST
Created attachment 362592 [details]
Work in progress
Comment 5 Wenson Hsieh 2019-02-21 09:00:27 PST
Created attachment 362612 [details]
Patch
Comment 6 Tim Horton 2019-02-22 12:03:59 PST
Comment on attachment 362612 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=362612&action=review

> Source/WebKit/Shared/WebPreferences.yaml:1562
> +SmartCalloutBarPositioningEnabled:

Do we really need a pref for this?

> Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm:1122
> +void WebPageProxy::requestEvasionRectsAboveSelection(CompletionHandler<void(const Vector<WebCore::FloatRect>&)>&& callback)

This is "above" because above is where we want to put it by default. Can we get evasion rects below too and end up presenting the callout bar to the left or right?

> Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm:1560
> +    const Vector<FloatPoint, 5> offsetsForHitTesting {{ -30, -51 }, { 31, -50 }, { -60, -34 }, { 60, -36 }, { 0, -20 }};

This is based on popover geometry? (it's in WebPageIOS, so I guess that's OK?)

Why are the numbers all a little fuzzy (where do the 1s and 4s and 6s come from?)

> Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm:1563
> +        if (auto* hitNode = clickableNonEditableNode(centerTopInRootViewCoordinates + offset))

I peeked and I think this /does/ update layout, so you should be OK?

> Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm:1581
> +    auto contextMenuElementSizeLimit = factorOfContentArea * pageScaleFactor() * m_page->mainFrame().view()->unobscuredContentRect().size();

You already have pageScaleFactor() as scaleFactor.

> Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm:1588
> +        RefPtr<Element> element;
> +        if (is<Element>(node))
> +            element = downcast<Element>(node.ptr());
> +        else
> +            element = node->parentElement();

Weird, I would have expected this to be a thing node can do (nearest element).

> Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm:1594
> +        if (bounds.width() > contextMenuElementSizeLimit.width() || bounds.height() > contextMenuElementSizeLimit.height())

Should this be area-based instead, so we can have long skinny bars?
Comment 7 Wenson Hsieh 2019-02-22 13:28:49 PST
Comment on attachment 362612 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=362612&action=review

>> Source/WebKit/Shared/WebPreferences.yaml:1562
>> +SmartCalloutBarPositioningEnabled:
> 
> Do we really need a pref for this?

It's not necessary, but it might help for demoing and testing!

Perhaps that's not a good reason though, so I'll remove this.

>> Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm:1122
>> +void WebPageProxy::requestEvasionRectsAboveSelection(CompletionHandler<void(const Vector<WebCore::FloatRect>&)>&& callback)
> 
> This is "above" because above is where we want to put it by default. Can we get evasion rects below too and end up presenting the callout bar to the left or right?

Yes, as of now, we only hit-test "above" because that's where the bar goes by default. We could additionally do more hit-testing below to force the bar to present on the left or right sides, but I refrained from doing that here because (1) I didn't find any websites that actually did this, and (2) hit-testing is fairly expensive, so without knowing specific websites that would benefit from getting evasion rects below the selection, I'd prefer to limit the amount of hit-testing that needs to happen here :/

>> Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm:1560
>> +    const Vector<FloatPoint, 5> offsetsForHitTesting {{ -30, -51 }, { 31, -50 }, { -60, -34 }, { 60, -36 }, { 0, -20 }};
> 
> This is based on popover geometry? (it's in WebPageIOS, so I guess that's OK?)
> 
> Why are the numbers all a little fuzzy (where do the 1s and 4s and 6s come from?)

Yes, it's based on callout bar geometry, and is therefore specific to iOS. I originally hit-tested a grid-aligned lattice of points above the selection, but then chose to perturb some of the locations a tiny bit (±1, ±1) to ensure that we don't fail detection if a row of points happen to land on a divider or something.

...but now that I think about this some more, it shouldn't be necessary because nodeRespondingToClickEvents is already fuzzy. So I'll un-fuzz these offsets.

>> Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm:1563
>> +        if (auto* hitNode = clickableNonEditableNode(centerTopInRootViewCoordinates + offset))
> 
> I peeked and I think this /does/ update layout, so you should be OK?

Sure! Also, the call to VisibleSelection::toNormalizedRange() above should have already updated layout.

>> Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm:1581
>> +    auto contextMenuElementSizeLimit = factorOfContentArea * pageScaleFactor() * m_page->mainFrame().view()->unobscuredContentRect().size();
> 
> You already have pageScaleFactor() as scaleFactor.

Good catch!

>> Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm:1588
>> +            element = node->parentElement();
> 
> Weird, I would have expected this to be a thing node can do (nearest element).

This comment made me realize that I shouldn't even need to go from Node -> Element; getting the bounds of the renderer and then converting to root view coordinates should suffice. I'll change the logic here to do this.

>> Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm:1594
>> +        if (bounds.width() > contextMenuElementSizeLimit.width() || bounds.height() > contextMenuElementSizeLimit.height())
> 
> Should this be area-based instead, so we can have long skinny bars?

Good call, I'll make this area-based instead.
Comment 8 Wenson Hsieh 2019-02-22 15:21:58 PST
Created attachment 362769 [details]
Patch for EWS
Comment 9 WebKit Commit Bot 2019-02-22 16:48:23 PST
Comment on attachment 362769 [details]
Patch for EWS

Clearing flags on attachment: 362769

Committed r241971: <https://trac.webkit.org/changeset/241971>