<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[170600] trunk/Source/WebKit2</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/170600">170600</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2014-06-30 15:10:56 -0700 (Mon, 30 Jun 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>[iOS][WK2] Move tap highlight to the inverseScaleRootView
https://bugs.webkit.org/show_bug.cgi?id=134424
&lt;rdar://problem/17480880&gt;

Patch by Benjamin Poulain &lt;bpoulain@apple.com&gt; on 2014-06-30
Reviewed by Tim Horton.

Enrica introduced the inverseScaleRootView that is a dynamic version of _highlightRootView.

This patch moves the tap highlight from its own inverse root to inverseScaleRootView. This provides better handling
of scale, better behavior on crash, and remove one extra view from the hierarchy.

The code is pretty much the same, just moved around. Some of the changes:

Now the code needs to handle repainting live when the view scale. To do that, _showTapHighlightXXX was split in two:
-_showTapHighlight to setup the view.
-_updateTapHighlight to update the view based on the current scale.

Since the view updates live on scaling, we need to recompute the coordinates for each update. To do that, the _potentialTapHighlightInformation
was generalized to handle all cases of highlight.

Since we can no longer test for the nullity of _potentialTapHighlightInformation,
a new attribute is introduced for that: _hasTapHighlightForPotentialTap.

The last bit of change concern reentering the tap highlight. This becomes quite simple:
1) _isTapHighlightIDValid is updated before the animation starts
   so that it can be set again during an animation.
2) The animation checks the &quot;finished&quot; flags before removing the view from its superview
   to avoid breaking the new animation.

* UIProcess/API/Cocoa/WKWebView.mm:
(withinEpsilon): Deleted.
* UIProcess/ios/WKContentView.mm:
(-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:]):
Make _updateUnscaledView conditional to scale changes, that thing isn't cheap!

* UIProcess/ios/WKContentViewInteraction.h:
(withinEpsilon):
Move withinEpsilon() from WKContentView to use it from both classes.

* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView cleanupInteraction]):
(-[WKContentView _updateUnscaledView]):
(-[WKContentView _updateTapHighlight]):
(-[WKContentView _showTapHighlight]):
(-[WKContentView _didGetTapHighlightForRequest:color:quads:topLeftRadius:topRightRadius:bottomLeftRadius:bottomRightRadius:]):
(-[WKContentView _cancelInteraction]):
(-[WKContentView _finishInteraction]):
(-[WKContentView _singleTapDidReset:]):
(-[WKContentView _singleTapCommited:]):
(-[WKContentView _showTapHighlightWithColor:quads:topLeftRadius:topRightRadius:bottomLeftRadius:bottomRightRadius:]): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWKContentViewmm">trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWKContentViewInteractionh">trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWKContentViewInteractionmm">trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (170599 => 170600)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-06-30 21:53:58 UTC (rev 170599)
+++ trunk/Source/WebKit2/ChangeLog        2014-06-30 22:10:56 UTC (rev 170600)
</span><span class="lines">@@ -1,3 +1,56 @@
</span><ins>+2014-06-30  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        [iOS][WK2] Move tap highlight to the inverseScaleRootView
+        https://bugs.webkit.org/show_bug.cgi?id=134424
+        &lt;rdar://problem/17480880&gt;
+
+        Reviewed by Tim Horton.
+
+        Enrica introduced the inverseScaleRootView that is a dynamic version of _highlightRootView.
+
+        This patch moves the tap highlight from its own inverse root to inverseScaleRootView. This provides better handling
+        of scale, better behavior on crash, and remove one extra view from the hierarchy.
+
+        The code is pretty much the same, just moved around. Some of the changes:
+
+        Now the code needs to handle repainting live when the view scale. To do that, _showTapHighlightXXX was split in two:
+        -_showTapHighlight to setup the view.
+        -_updateTapHighlight to update the view based on the current scale.
+
+        Since the view updates live on scaling, we need to recompute the coordinates for each update. To do that, the _potentialTapHighlightInformation
+        was generalized to handle all cases of highlight.
+
+        Since we can no longer test for the nullity of _potentialTapHighlightInformation,
+        a new attribute is introduced for that: _hasTapHighlightForPotentialTap.
+
+        The last bit of change concern reentering the tap highlight. This becomes quite simple:
+        1) _isTapHighlightIDValid is updated before the animation starts
+           so that it can be set again during an animation.
+        2) The animation checks the &quot;finished&quot; flags before removing the view from its superview
+           to avoid breaking the new animation.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (withinEpsilon): Deleted.
+        * UIProcess/ios/WKContentView.mm:
+        (-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:]):
+        Make _updateUnscaledView conditional to scale changes, that thing isn't cheap!
+
+        * UIProcess/ios/WKContentViewInteraction.h:
+        (withinEpsilon):
+        Move withinEpsilon() from WKContentView to use it from both classes.
+
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView cleanupInteraction]):
+        (-[WKContentView _updateUnscaledView]):
+        (-[WKContentView _updateTapHighlight]):
+        (-[WKContentView _showTapHighlight]):
+        (-[WKContentView _didGetTapHighlightForRequest:color:quads:topLeftRadius:topRightRadius:bottomLeftRadius:bottomRightRadius:]):
+        (-[WKContentView _cancelInteraction]):
+        (-[WKContentView _finishInteraction]):
+        (-[WKContentView _singleTapDidReset:]):
+        (-[WKContentView _singleTapCommited:]):
+        (-[WKContentView _showTapHighlightWithColor:quads:topLeftRadius:topRightRadius:bottomLeftRadius:bottomRightRadius:]): Deleted.
+
</ins><span class="cx"> 2014-06-30  Anders Carlsson  &lt;andersca@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add code for encoding legacy session history entries
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm (170599 => 170600)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2014-06-30 21:53:58 UTC (rev 170599)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2014-06-30 22:10:56 UTC (rev 170600)
</span><span class="lines">@@ -739,11 +739,6 @@
</span><span class="cx">     _usesMinimalUI = NO;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline bool withinEpsilon(float a, float b)
-{
-    return fabs(a - b) &lt; std::numeric_limits&lt;float&gt;::epsilon();
-}
-
</del><span class="cx"> static void changeContentOffsetBoundedInValidRange(UIScrollView *scrollView, WebCore::FloatPoint contentOffset)
</span><span class="cx"> {
</span><span class="cx">     UIEdgeInsets contentInsets = scrollView.contentInset;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWKContentViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm (170599 => 170600)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm        2014-06-30 21:53:58 UTC (rev 170599)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm        2014-06-30 22:10:56 UTC (rev 170600)
</span><span class="lines">@@ -556,6 +556,8 @@
</span><span class="cx"> - (void)didUpdateVisibleRect:(CGRect)visibleRect unobscuredRect:(CGRect)unobscuredRect unobscuredRectInScrollViewCoordinates:(CGRect)unobscuredRectInScrollViewCoordinates
</span><span class="cx">     scale:(CGFloat)zoomScale minimumScale:(CGFloat)minimumScale inStableState:(BOOL)isStableState isChangingObscuredInsetsInteractively:(BOOL)isChangingObscuredInsetsInteractively
</span><span class="cx"> {
</span><ins>+    double oldDisplayedContentScale = _page-&gt;displayedContentScale();
+
</ins><span class="cx">     double timestamp = monotonicallyIncreasingTime();
</span><span class="cx">     HistoricalVelocityData::VelocityData velocityData;
</span><span class="cx">     if (!isStableState)
</span><span class="lines">@@ -572,7 +574,9 @@
</span><span class="cx"> 
</span><span class="cx">     if (auto drawingArea = _page-&gt;drawingArea())
</span><span class="cx">         drawingArea-&gt;updateDebugIndicator();
</span><del>-    [self _updateUnscaledView];
</del><ins>+
+    if (!withinEpsilon(oldDisplayedContentScale, zoomScale))
+        [self _updateUnscaledView];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)setMinimumSize:(CGSize)size
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWKContentViewInteractionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h (170599 => 170600)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h        2014-06-30 21:53:58 UTC (rev 170599)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h        2014-06-30 22:10:56 UTC (rev 170600)
</span><span class="lines">@@ -100,7 +100,6 @@
</span><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;UITextInputTraits&gt; _traits;
</span><span class="cx">     RetainPtr&lt;UIWebFormAccessory&gt; _formAccessoryView;
</span><del>-    RetainPtr&lt;UIView&gt; _highlightRootView;
</del><span class="cx">     RetainPtr&lt;_UIHighlightView&gt; _highlightView;
</span><span class="cx">     RetainPtr&lt;UIView&gt; _inverseScaleRootView;
</span><span class="cx">     RetainPtr&lt;NSString&gt; _markedText;
</span><span class="lines">@@ -122,7 +121,7 @@
</span><span class="cx">         WebCore::IntSize bottomLeftRadius;
</span><span class="cx">         WebCore::IntSize bottomRightRadius;
</span><span class="cx">     };
</span><del>-    std::unique_ptr&lt;TapHighlightInformation&gt; _potentialTapHighlightInformation;
</del><ins>+    TapHighlightInformation _tapHighlightInformation;
</ins><span class="cx"> 
</span><span class="cx">     WebKit::WKAutoCorrectionData _autocorrectionData;
</span><span class="cx">     WebKit::InteractionInformationAtPosition _positionInformation;
</span><span class="lines">@@ -136,6 +135,7 @@
</span><span class="cx">     BOOL _hasValidPositionInformation;
</span><span class="cx">     BOOL _isTapHighlightIDValid;
</span><span class="cx">     BOOL _potentialTapInProgress;
</span><ins>+    BOOL _hasTapHighlightForPotentialTap;
</ins><span class="cx">     BOOL _selectionNeedsUpdate;
</span><span class="cx">     BOOL _usingGestureForSelection;
</span><span class="cx">     BOOL _inspectorNodeSearchEnabled;
</span><span class="lines">@@ -185,4 +185,9 @@
</span><span class="cx"> - (void)_disableInspectorNodeSearch;
</span><span class="cx"> @end
</span><span class="cx"> 
</span><ins>+static inline bool withinEpsilon(float a, float b)
+{
+    return fabs(a - b) &lt; std::numeric_limits&lt;float&gt;::epsilon();
+}
+
</ins><span class="cx"> #endif // PLATFORM(IOS)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWKContentViewInteractionmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm (170599 => 170600)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm        2014-06-30 21:53:58 UTC (rev 170599)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm        2014-06-30 22:10:56 UTC (rev 170600)
</span><span class="lines">@@ -71,6 +71,7 @@
</span><span class="cx"> 
</span><span class="cx"> static const float highlightDelay = 0.12;
</span><span class="cx"> static const float tapAndHoldDelay  = 0.75;
</span><ins>+const CGFloat minimumTapHighlightRadius = 2.0;
</ins><span class="cx"> 
</span><span class="cx"> @interface WKTextRange : UITextRange {
</span><span class="cx">     CGRect _startRect;
</span><span class="lines">@@ -267,7 +268,6 @@
</span><span class="cx">     [_formInputSession invalidate];
</span><span class="cx">     _formInputSession = nil;
</span><span class="cx">     [_highlightView removeFromSuperview];
</span><del>-    [_highlightRootView removeFromSuperview];
</del><span class="cx">     [_inverseScaleRootView removeFromSuperview];
</span><span class="cx">     [_touchEventGestureRecognizer setDelegate:nil];
</span><span class="cx">     [self removeGestureRecognizer:_touchEventGestureRecognizer.get()];
</span><span class="lines">@@ -339,6 +339,7 @@
</span><span class="cx">     [_inverseScaleRootView setTransform:CGAffineTransformMakeScale(inverseScale, inverseScale)];
</span><span class="cx">     _selectionNeedsUpdate = YES;
</span><span class="cx">     [self _updateChangedSelection];
</span><ins>+    [self _updateTapHighlight];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)_enableInspectorNodeSearch
</span><span class="lines">@@ -507,35 +508,25 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-- (void)_showTapHighlightWithColor:(const WebCore::Color&amp;)color quads:(const Vector&lt;WebCore::FloatQuad&gt;&amp;)highlightedQuads topLeftRadius:(const WebCore::IntSize&amp;)topLeftRadius topRightRadius:(const WebCore::IntSize&amp;)topRightRadius bottomLeftRadius:(const WebCore::IntSize&amp;)bottomLeftRadius bottomRightRadius:(const WebCore::IntSize&amp;)bottomRightRadius
</del><ins>+static NSValue *nsSizeForTapHighlightBorderRadius(WebCore::IntSize borderRadius)
</ins><span class="cx"> {
</span><del>-    if (!highlightedQuadsAreSmallerThanRect(highlightedQuads, _page-&gt;unobscuredContentRect()))
</del><ins>+    return [NSValue valueWithCGSize:CGSizeMake(borderRadius.width() + minimumTapHighlightRadius, borderRadius.height() + minimumTapHighlightRadius)]
+}
+
+- (void)_updateTapHighlight
+{
+    if (![_highlightView superview])
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    const CGFloat UIWebViewMinimumHighlightRadius = 2.0;
-
-    if (!_highlightRootView) {
-        _highlightRootView = adoptNS([[UIView alloc] init]);
-        [_highlightRootView setOpaque:NO];
-        [_highlightRootView layer].anchorPoint = CGPointMake(0, 0);
-
-        _highlightView = adoptNS([[_UIHighlightView alloc] initWithFrame:CGRectZero]);
-        [_highlightView setOpaque:NO];
-        [_highlightView setCornerRadius:UIWebViewMinimumHighlightRadius];
-        [_highlightRootView addSubview:_highlightView.get()];
-    }
-    [self addSubview:_highlightRootView.get()];
-    CGFloat selfScale = [[self layer] transform].m11;
-    CGFloat highlightViewScale = 1 / selfScale;
-    [_highlightRootView setTransform:CGAffineTransformMakeScale(highlightViewScale, highlightViewScale)];
-
</del><span class="cx">     {
</span><del>-        RetainPtr&lt;UIColor&gt; highlightUIKitColor = adoptNS([[UIColor alloc] initWithRed:(color.red() / 255.0) green:(color.green() / 255.0) blue:(color.blue() / 255.0) alpha:(color.alpha() / 255.0)]);
</del><ins>+        RetainPtr&lt;UIColor&gt; highlightUIKitColor = adoptNS([[UIColor alloc] initWithCGColor:cachedCGColor(_tapHighlightInformation.color, WebCore::ColorSpaceDeviceRGB)]);
</ins><span class="cx">         [_highlightView setColor:highlightUIKitColor.get()];
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    CGFloat selfScale = self.layer.transform.m11;
</ins><span class="cx">     bool allHighlightRectsAreRectilinear = true;
</span><span class="cx">     float deviceScaleFactor = _page-&gt;deviceScaleFactor();
</span><ins>+    const Vector&lt;WebCore::FloatQuad&gt;&amp; highlightedQuads = _tapHighlightInformation.quads;
</ins><span class="cx">     const size_t quadCount = highlightedQuads.size();
</span><span class="cx">     RetainPtr&lt;NSMutableArray&gt; rects = adoptNS([[NSMutableArray alloc] initWithCapacity:static_cast&lt;const NSUInteger&gt;(quadCount)]);
</span><span class="cx">     for (size_t i = 0; i &lt; quadCount; ++i) {
</span><span class="lines">@@ -543,7 +534,7 @@
</span><span class="cx">         if (quad.isRectilinear()) {
</span><span class="cx">             FloatRect boundingBox = quad.boundingBox();
</span><span class="cx">             boundingBox.scale(selfScale);
</span><del>-            boundingBox.inflate(UIWebViewMinimumHighlightRadius);
</del><ins>+            boundingBox.inflate(minimumTapHighlightRadius);
</ins><span class="cx">             CGRect pixelAlignedRect = static_cast&lt;CGRect&gt;(enclosingRectExtendedToDevicePixels(boundingBox, deviceScaleFactor));
</span><span class="cx">             [rects addObject:[NSValue valueWithCGRect:pixelAlignedRect]];
</span><span class="cx">         } else {
</span><span class="lines">@@ -560,7 +551,7 @@
</span><span class="cx">         for (size_t i = 0; i &lt; quadCount; ++i) {
</span><span class="cx">             FloatQuad quad = highlightedQuads[i];
</span><span class="cx">             quad.scale(selfScale, selfScale);
</span><del>-            FloatQuad extendedQuad = inflateQuad(quad, UIWebViewMinimumHighlightRadius);
</del><ins>+            FloatQuad extendedQuad = inflateQuad(quad, minimumTapHighlightRadius);
</ins><span class="cx">             [quads addObject:[NSValue valueWithCGPoint:extendedQuad.p1()]];
</span><span class="cx">             [quads addObject:[NSValue valueWithCGPoint:extendedQuad.p2()]];
</span><span class="cx">             [quads addObject:[NSValue valueWithCGPoint:extendedQuad.p3()]];
</span><span class="lines">@@ -570,35 +561,48 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;NSMutableArray&gt; borderRadii = adoptNS([[NSMutableArray alloc] initWithCapacity:4]);
</span><del>-    [borderRadii addObject:[NSValue valueWithCGSize:CGSizeMake(topLeftRadius.width() + UIWebViewMinimumHighlightRadius, topLeftRadius.height() + UIWebViewMinimumHighlightRadius)]];
-    [borderRadii addObject:[NSValue valueWithCGSize:CGSizeMake(topRightRadius.width() + UIWebViewMinimumHighlightRadius, topRightRadius.height() + UIWebViewMinimumHighlightRadius)]];
-    [borderRadii addObject:[NSValue valueWithCGSize:CGSizeMake(bottomLeftRadius.width() + UIWebViewMinimumHighlightRadius, bottomLeftRadius.height() + UIWebViewMinimumHighlightRadius)]];
-    [borderRadii addObject:[NSValue valueWithCGSize:CGSizeMake(bottomRightRadius.width() + UIWebViewMinimumHighlightRadius, bottomRightRadius.height() + UIWebViewMinimumHighlightRadius)]];
</del><ins>+    [borderRadii addObject:nsSizeForTapHighlightBorderRadius(_tapHighlightInformation.topLeftRadius)];
+    [borderRadii addObject:nsSizeForTapHighlightBorderRadius(_tapHighlightInformation.topRightRadius)];
+    [borderRadii addObject:nsSizeForTapHighlightBorderRadius(_tapHighlightInformation.bottomLeftRadius)];
+    [borderRadii addObject:nsSizeForTapHighlightBorderRadius(_tapHighlightInformation.bottomRightRadius)];
</ins><span class="cx">     [_highlightView setCornerRadii:borderRadii.get()];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)_showTapHighlight
+{
+    if (!highlightedQuadsAreSmallerThanRect(_tapHighlightInformation.quads, _page-&gt;unobscuredContentRect()))
+        return;
+
+    if (!_highlightView) {
+        _highlightView = adoptNS([[_UIHighlightView alloc] initWithFrame:CGRectZero]);
+        [_highlightView setOpaque:NO];
+        [_highlightView setCornerRadius:minimumTapHighlightRadius];
+    }
+    [_highlightView layer].opacity = 1;
+    [_inverseScaleRootView addSubview:_highlightView.get()];
+    [self _updateTapHighlight];
+}
+
</ins><span class="cx"> - (void)_didGetTapHighlightForRequest:(uint64_t)requestID color:(const WebCore::Color&amp;)color quads:(const Vector&lt;WebCore::FloatQuad&gt;&amp;)highlightedQuads topLeftRadius:(const WebCore::IntSize&amp;)topLeftRadius topRightRadius:(const WebCore::IntSize&amp;)topRightRadius bottomLeftRadius:(const WebCore::IntSize&amp;)bottomLeftRadius bottomRightRadius:(const WebCore::IntSize&amp;)bottomRightRadius
</span><span class="cx"> {
</span><span class="cx">     if (!_isTapHighlightIDValid || _latestTapHighlightID != requestID)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    _isTapHighlightIDValid = NO;
+
+    _tapHighlightInformation.color = color;
+    _tapHighlightInformation.quads = highlightedQuads;
+    _tapHighlightInformation.topLeftRadius = topLeftRadius;
+    _tapHighlightInformation.topRightRadius = topRightRadius;
+    _tapHighlightInformation.bottomLeftRadius = bottomLeftRadius;
+    _tapHighlightInformation.bottomRightRadius = bottomRightRadius;
+
</ins><span class="cx">     if (_potentialTapInProgress) {
</span><del>-        _potentialTapHighlightInformation = std::make_unique&lt;TapHighlightInformation&gt;();
-        _potentialTapHighlightInformation-&gt;color = color;
-        _potentialTapHighlightInformation-&gt;quads = highlightedQuads;
-        _potentialTapHighlightInformation-&gt;topLeftRadius = topLeftRadius;
-        _potentialTapHighlightInformation-&gt;topRightRadius = topRightRadius;
-        _potentialTapHighlightInformation-&gt;bottomLeftRadius = bottomLeftRadius;
-        _potentialTapHighlightInformation-&gt;bottomRightRadius = bottomRightRadius;
</del><ins>+        _hasTapHighlightForPotentialTap = YES;
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    [self _showTapHighlightWithColor:color
-                               quads:highlightedQuads
-                       topLeftRadius:topLeftRadius
-                      topRightRadius:topRightRadius
-                    bottomLeftRadius:bottomLeftRadius
-                   bottomRightRadius:bottomRightRadius];
</del><ins>+    [self _showTapHighlight];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)_cancelLongPressGestureRecognizer
</span><span class="lines">@@ -798,20 +802,18 @@
</span><span class="cx"> 
</span><span class="cx"> - (void)_cancelInteraction
</span><span class="cx"> {
</span><del>-    _isTapHighlightIDValid = NO;
-    [_highlightRootView removeFromSuperview];
</del><ins>+    [_highlightView removeFromSuperview];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)_finishInteraction
</span><span class="cx"> {
</span><span class="cx">     [UIView animateWithDuration:0.1
</span><span class="cx">                      animations:^{
</span><del>-                         [[_highlightRootView layer] setOpacity:0];
</del><ins>+                         [_highlightView layer].opacity = 0;
</ins><span class="cx">                      }
</span><del>-                     completion:^(BOOL){
-                         _isTapHighlightIDValid = NO;
-                         [_highlightRootView removeFromSuperview];
-                         [[_highlightRootView layer] setOpacity:1];
</del><ins>+                     completion:^(BOOL finished){
+                         if (finished)
+                             [_highlightView removeFromSuperview];
</ins><span class="cx">                      }];
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -917,7 +919,6 @@
</span><span class="cx">     ASSERT(gestureRecognizer == _singleTapGestureRecognizer);
</span><span class="cx">     if (_potentialTapInProgress) {
</span><span class="cx">         _potentialTapInProgress = NO;
</span><del>-        _potentialTapHighlightInformation = nullptr;
</del><span class="cx">         [self _cancelInteraction];
</span><span class="cx">         _page-&gt;cancelPotentialTap();
</span><span class="cx">     }
</span><span class="lines">@@ -952,14 +953,9 @@
</span><span class="cx"> 
</span><span class="cx">     _potentialTapInProgress = NO;
</span><span class="cx"> 
</span><del>-    if (_potentialTapHighlightInformation) {
-        [self _showTapHighlightWithColor:_potentialTapHighlightInformation-&gt;color
-                                   quads:_potentialTapHighlightInformation-&gt;quads
-                           topLeftRadius:_potentialTapHighlightInformation-&gt;topLeftRadius
-                          topRightRadius:_potentialTapHighlightInformation-&gt;topRightRadius
-                        bottomLeftRadius:_potentialTapHighlightInformation-&gt;bottomLeftRadius
-                       bottomRightRadius:_potentialTapHighlightInformation-&gt;bottomRightRadius];
-        _potentialTapHighlightInformation = nullptr;
</del><ins>+    if (_hasTapHighlightForPotentialTap) {
+        [self _showTapHighlight];
+        _hasTapHighlightForPotentialTap = NO;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     _page-&gt;commitPotentialTap();
</span></span></pre>
</div>
</div>

</body>
</html>