<!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>[170966] trunk/Source</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/170966">170966</a></dd>
<dt>Author</dt> <dd>beidson@apple.com</dd>
<dt>Date</dt> <dd>2014-07-10 09:19:56 -0700 (Thu, 10 Jul 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Phone number highlights should always be visible if the mouse hovers over.
&lt;rdar://problem/17527476&gt; and https://bugs.webkit.org/show_bug.cgi?id=134784

Reviewed by Tim Horton.

Source/WebCore:
* WebCore.exp.in:

Source/WebKit2:
This is a fairly extensive rewrite of ServicesOverlayController.
It allows one selection highlight for the entire selection, and as many telephone number highlights as there are numbers.
If a telephone number highlight is hovered over, it wins and is painted.
If no telephone number highlight is hovered but the selection highlight is, then it is painted.

The purposes of each method are self evident by their name, and the concepts are mostly the same as they used to be.

The exception is establishHoveredTelephoneHighlight which gets a more detailed explanation below.

* Platform/Logging.h: Add a Services logging channel.

* WebProcess/WebPage/ServicesOverlayController.h:
(WebKit::TelephoneNumberData::TelephoneNumberData):

* WebProcess/WebPage/mac/ServicesOverlayController.mm:
(WebKit::ServicesOverlayController::ServicesOverlayController):
(WebKit::ServicesOverlayController::selectionRectsDidChange):
(WebKit::ServicesOverlayController::selectedTelephoneNumberRangesChanged):
(WebKit::ServicesOverlayController::clearHighlightState):
(WebKit::ServicesOverlayController::drawRect):
(WebKit::ServicesOverlayController::drawSelectionHighlight):
(WebKit::ServicesOverlayController::maybeDrawTelephoneNumberHighlight):
(WebKit::ServicesOverlayController::drawHighlight):
(WebKit::ServicesOverlayController::clearSelectionHighlight):
(WebKit::ServicesOverlayController::clearHoveredTelephoneNumberHighlight):
(WebKit::ServicesOverlayController::establishHoveredTelephoneHighlight): Starts walking the telephone number ranges and
    creating a highlight for each one that doesn’t already have a highlight. If that highlight is also being hovered by
    the mouse, then it is set as the hovered telephone number highlight and the method stops creating new highlights.
(WebKit::ServicesOverlayController::maybeCreateSelectionHighlight):
(WebKit::ServicesOverlayController::mouseEvent):
(WebKit::ServicesOverlayController::handleClick):
(WebKit::ServicesOverlayController::drawTelephoneNumberHighlight): Deleted.
(WebKit::ServicesOverlayController::drawCurrentHighlight): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCoreexpin">trunk/Source/WebCore/WebCore.exp.in</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2PlatformLoggingh">trunk/Source/WebKit2/Platform/Logging.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageServicesOverlayControllerh">trunk/Source/WebKit2/WebProcess/WebPage/ServicesOverlayController.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPagemacServicesOverlayControllermm">trunk/Source/WebKit2/WebProcess/WebPage/mac/ServicesOverlayController.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (170965 => 170966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-07-10 16:13:54 UTC (rev 170965)
+++ trunk/Source/WebCore/ChangeLog        2014-07-10 16:19:56 UTC (rev 170966)
</span><span class="lines">@@ -1,3 +1,12 @@
</span><ins>+2014-07-10  Brady Eidson  &lt;beidson@apple.com&gt;
+
+        Phone number highlights should always be visible if the mouse hovers over.
+        &lt;rdar://problem/17527476&gt; and https://bugs.webkit.org/show_bug.cgi?id=134784
+
+        Reviewed by Tim Horton.
+
+        * WebCore.exp.in:
+
</ins><span class="cx"> 2014-07-10  Timothy Horton  &lt;timothy_horton@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Assertions or crashes under _takeViewSnapshot when restoring windows
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCoreexpin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.exp.in (170965 => 170966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.exp.in        2014-07-10 16:13:54 UTC (rev 170965)
+++ trunk/Source/WebCore/WebCore.exp.in        2014-07-10 16:19:56 UTC (rev 170966)
</span><span class="lines">@@ -459,6 +459,7 @@
</span><span class="cx"> __ZN7WebCore14TileController23setTileDebugBorderWidthEf
</span><span class="cx"> __ZN7WebCore14TileController27tileCacheLayerBoundsChangedEv
</span><span class="cx"> __ZN7WebCore14TileController6createEPNS_15PlatformCALayerE
</span><ins>+__ZN7WebCore14areRangesEqualEPKNS_5RangeES2_
</ins><span class="cx"> __ZN7WebCore14decodeHostNameEP8NSString
</span><span class="cx"> __ZN7WebCore14encodeHostNameEP8NSString
</span><span class="cx"> __ZN7WebCore14endOfParagraphERKNS_15VisiblePositionENS_27EditingBoundaryCrossingRuleE
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (170965 => 170966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-07-10 16:13:54 UTC (rev 170965)
+++ trunk/Source/WebKit2/ChangeLog        2014-07-10 16:19:56 UTC (rev 170966)
</span><span class="lines">@@ -1,3 +1,4 @@
</span><ins>+&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD
</ins><span class="cx"> 2014-07-10  Timothy Horton  &lt;timothy_horton@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Assertions or crashes under _takeViewSnapshot when restoring windows
</span><span class="lines">@@ -358,7 +359,49 @@
</span><span class="cx">         (-[WKPreferences _setTiledScrollingIndicatorVisible:]):
</span><span class="cx">         * UIProcess/API/Cocoa/WKPreferencesPrivate.h:
</span><span class="cx">         Expose layer borders, repaint counters, and the tiled scrolling indicator on WKPreferences, as SPI.
</span><ins>+=======
+2014-07-09  Brady Eidson  &lt;beidson@apple.com&gt;
</ins><span class="cx"> 
</span><ins>+        Phone number highlights should always be visible if the mouse hovers over.
+        &lt;rdar://problem/17527476&gt; and https://bugs.webkit.org/show_bug.cgi?id=134784
+
+        Reviewed by Tim Horton.
+
+        This is a fairly extensive rewrite of ServicesOverlayController.
+        It allows one selection highlight for the entire selection, and as many telephone number highlights as there are numbers.
+        If a telephone number highlight is hovered over, it wins and is painted.
+        If no telephone number highlight is hovered but the selection highlight is, then it is painted.
+       
+        The purposes of each method are self evident by their name, and the concepts are mostly the same as they used to be.
+
+        The exception is establishHoveredTelephoneHighlight which gets a more detailed explanation below.
+        
+        * Platform/Logging.h: Add a Services logging channel.
+
+        * WebProcess/WebPage/ServicesOverlayController.h:
+        (WebKit::TelephoneNumberData::TelephoneNumberData):
+
+        * WebProcess/WebPage/mac/ServicesOverlayController.mm:
+        (WebKit::ServicesOverlayController::ServicesOverlayController):
+        (WebKit::ServicesOverlayController::selectionRectsDidChange):
+        (WebKit::ServicesOverlayController::selectedTelephoneNumberRangesChanged):
+        (WebKit::ServicesOverlayController::clearHighlightState):
+        (WebKit::ServicesOverlayController::drawRect):
+        (WebKit::ServicesOverlayController::drawSelectionHighlight):
+        (WebKit::ServicesOverlayController::maybeDrawTelephoneNumberHighlight):
+        (WebKit::ServicesOverlayController::drawHighlight):
+        (WebKit::ServicesOverlayController::clearSelectionHighlight):
+        (WebKit::ServicesOverlayController::clearHoveredTelephoneNumberHighlight):
+        (WebKit::ServicesOverlayController::establishHoveredTelephoneHighlight): Starts walking the telephone number ranges and
+            creating a highlight for each one that doesn’t already have a highlight. If that highlight is also being hovered by
+            the mouse, then it is set as the hovered telephone number highlight and the method stops creating new highlights.
+        (WebKit::ServicesOverlayController::maybeCreateSelectionHighlight):
+        (WebKit::ServicesOverlayController::mouseEvent):
+        (WebKit::ServicesOverlayController::handleClick):
+        (WebKit::ServicesOverlayController::drawTelephoneNumberHighlight): Deleted.
+        (WebKit::ServicesOverlayController::drawCurrentHighlight): Deleted.
+&gt;&gt;&gt;&gt;&gt;&gt;&gt; Phone number highlights should always be visible if the mouse hovers over.
+
</ins><span class="cx"> 2014-07-08  Tim Horton  &lt;timothy_horton@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WKProcessPoolConfigurationPrivate's maximumProcessCount property has no effect
</span></span></pre></div>
<a id="trunkSourceWebKit2PlatformLoggingh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Platform/Logging.h (170965 => 170966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Platform/Logging.h        2014-07-10 16:13:54 UTC (rev 170965)
+++ trunk/Source/WebKit2/Platform/Logging.h        2014-07-10 16:19:56 UTC (rev 170966)
</span><span class="lines">@@ -51,6 +51,7 @@
</span><span class="cx">     M(TextInput) \
</span><span class="cx">     M(View) \
</span><span class="cx">     M(IDB) \
</span><ins>+    M(Services) \
</ins><span class="cx"> 
</span><span class="cx"> #define DECLARE_LOG_CHANNEL(name) \
</span><span class="cx">     extern WTFLogChannel JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, name);
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageServicesOverlayControllerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/ServicesOverlayController.h (170965 => 170966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/ServicesOverlayController.h        2014-07-10 16:13:54 UTC (rev 170965)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ServicesOverlayController.h        2014-07-10 16:19:56 UTC (rev 170966)
</span><span class="lines">@@ -44,6 +44,17 @@
</span><span class="cx"> 
</span><span class="cx"> typedef void* DDHighlightRef;
</span><span class="cx"> 
</span><ins>+struct TelephoneNumberData {
+    TelephoneNumberData(RetainPtr&lt;DDHighlightRef&gt; highlight, PassRefPtr&lt;WebCore::Range&gt; range)
+        : highlight(highlight)
+        , range(range)
+    {
+    }
+
+    RetainPtr&lt;DDHighlightRef&gt; highlight;
+    RefPtr&lt;WebCore::Range&gt; range;
+};
+
</ins><span class="cx"> class ServicesOverlayController : private PageOverlay::Client {
</span><span class="cx"> public:
</span><span class="cx">     ServicesOverlayController(WebPage&amp;);
</span><span class="lines">@@ -54,32 +65,39 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     void createOverlayIfNeeded();
</span><del>-    void handleClick(const WebCore::IntPoint&amp;);
</del><ins>+    void handleClick(const WebCore::IntPoint&amp;, DDHighlightRef);
</ins><span class="cx">     void clearHighlightState();
</span><del>-    
</del><ins>+
</ins><span class="cx">     virtual void pageOverlayDestroyed(PageOverlay*) override;
</span><span class="cx">     virtual void willMoveToWebPage(PageOverlay*, WebPage*) override;
</span><span class="cx">     virtual void didMoveToWebPage(PageOverlay*, WebPage*) override;
</span><span class="cx">     virtual void drawRect(PageOverlay*, WebCore::GraphicsContext&amp;, const WebCore::IntRect&amp; dirtyRect) override;
</span><span class="cx">     virtual bool mouseEvent(PageOverlay*, const WebMouseEvent&amp;) override;
</span><span class="cx"> 
</span><del>-    void drawTelephoneNumberHighlight(WebCore::GraphicsContext&amp;, const WebCore::IntRect&amp; dirtyRect);
</del><ins>+    bool drawTelephoneNumberHighlightIfVisible(WebCore::GraphicsContext&amp;, const WebCore::IntRect&amp; dirtyRect);
</ins><span class="cx">     void drawSelectionHighlight(WebCore::GraphicsContext&amp;, const WebCore::IntRect&amp; dirtyRect);
</span><del>-    void drawCurrentHighlight(WebCore::GraphicsContext&amp;);
</del><ins>+    void drawHighlight(DDHighlightRef, WebCore::GraphicsContext&amp;);
</ins><span class="cx"> 
</span><ins>+    void establishHoveredTelephoneHighlight(Boolean&amp; onButton);
+    void maybeCreateSelectionHighlight();
+
+    void clearSelectionHighlight();
+    void clearHoveredTelephoneNumberHighlight();
+
</ins><span class="cx">     WebPage* m_webPage;
</span><span class="cx">     PageOverlay* m_servicesOverlay;
</span><span class="cx">     
</span><span class="cx">     Vector&lt;WebCore::LayoutRect&gt; m_currentSelectionRects;
</span><ins>+    RetainPtr&lt;DDHighlightRef&gt; m_selectionHighlight;
+
</ins><span class="cx">     Vector&lt;RefPtr&lt;WebCore::Range&gt;&gt; m_currentTelephoneNumberRanges;
</span><ins>+    Vector&lt;RetainPtr&lt;DDHighlightRef&gt;&gt; m_telephoneNumberHighlights;
+    std::unique_ptr&lt;TelephoneNumberData&gt; m_hoveredTelephoneNumberData;
</ins><span class="cx"> 
</span><ins>+    RetainPtr&lt;DDHighlightRef&gt; m_currentHoveredHighlight;
+    RetainPtr&lt;DDHighlightRef&gt; m_currentMouseDownOnButtonHighlight;
+
</ins><span class="cx">     WebCore::IntPoint m_mousePosition;
</span><del>-    bool m_mouseIsDownOnButton;
-    bool m_mouseIsOverHighlight;
-    bool m_drawingTelephoneNumberHighlight;
-
-    RetainPtr&lt;DDHighlightRef&gt; m_currentHighlight;
-    bool m_currentHighlightIsDirty;
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPagemacServicesOverlayControllermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/ServicesOverlayController.mm (170965 => 170966)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/mac/ServicesOverlayController.mm        2014-07-10 16:13:54 UTC (rev 170965)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/ServicesOverlayController.mm        2014-07-10 16:19:56 UTC (rev 170966)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION) &amp;&amp; PLATFORM(MAC)
</span><span class="cx"> 
</span><ins>+#import &quot;Logging.h&quot;
</ins><span class="cx"> #import &quot;WebPage.h&quot;
</span><span class="cx"> #import &quot;WebProcess.h&quot;
</span><span class="cx"> #import &lt;WebCore/Document.h&gt;
</span><span class="lines">@@ -75,10 +76,6 @@
</span><span class="cx"> ServicesOverlayController::ServicesOverlayController(WebPage&amp; webPage)
</span><span class="cx">     : m_webPage(&amp;webPage)
</span><span class="cx">     , m_servicesOverlay(nullptr)
</span><del>-    , m_mouseIsDownOnButton(false)
-    , m_mouseIsOverHighlight(false)
-    , m_drawingTelephoneNumberHighlight(false)
-    , m_currentHighlightIsDirty(false)
</del><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -220,7 +217,7 @@
</span><span class="cx"> void ServicesOverlayController::selectionRectsDidChange(const Vector&lt;LayoutRect&gt;&amp; rects, const Vector&lt;GapRects&gt;&amp; gapRects)
</span><span class="cx"> {
</span><span class="cx"> #if __MAC_OS_X_VERSION_MIN_REQUIRED &gt; 1090
</span><del>-    m_currentHighlightIsDirty = true;
</del><ins>+    clearSelectionHighlight();
</ins><span class="cx">     m_currentSelectionRects = rects;
</span><span class="cx"> 
</span><span class="cx">     compactRectsWithGapRects(m_currentSelectionRects, gapRects);
</span><span class="lines">@@ -228,6 +225,8 @@
</span><span class="cx">     // DataDetectors needs these reversed in order to place the arrow in the right location.
</span><span class="cx">     m_currentSelectionRects.reverse();
</span><span class="cx"> 
</span><ins>+    LOG(Services, &quot;ServicesOverlayController - Selection rects changed - Now have %lu\n&quot;, rects.size());
+
</ins><span class="cx">     createOverlayIfNeeded();
</span><span class="cx"> #else
</span><span class="cx">     UNUSED_PARAM(rects);
</span><span class="lines">@@ -237,18 +236,11 @@
</span><span class="cx"> void ServicesOverlayController::selectedTelephoneNumberRangesChanged(const Vector&lt;RefPtr&lt;Range&gt;&gt;&amp; ranges)
</span><span class="cx"> {
</span><span class="cx"> #if PLATFORM(MAC) &amp;&amp; __MAC_OS_X_VERSION_MIN_REQUIRED &gt; 1090
</span><del>-    m_currentHighlightIsDirty = true;
</del><ins>+    LOG(Services, &quot;ServicesOverlayController - Telephone number ranges changed - Had %lu, now have %lu\n&quot;, m_currentTelephoneNumberRanges.size(), ranges.size());
</ins><span class="cx">     m_currentTelephoneNumberRanges = ranges;
</span><del>-    m_drawingTelephoneNumberHighlight = false;
</del><ins>+    m_telephoneNumberHighlights.clear();
+    m_telephoneNumberHighlights.resize(ranges.size());
</ins><span class="cx"> 
</span><del>-    if (ranges.size() == 1) {
-        if (Frame* frame = ranges[0]-&gt;startContainer()-&gt;document().frame()) {
-            RefPtr&lt;Range&gt; selectionRange = frame-&gt;selection().toNormalizedRange();
-            if (ranges[0]-&gt;contains(*selectionRange))
-                m_drawingTelephoneNumberHighlight = true;
-        }
-    }
-    
</del><span class="cx">     createOverlayIfNeeded();
</span><span class="cx"> #else
</span><span class="cx">     UNUSED_PARAM(ranges);
</span><span class="lines">@@ -257,11 +249,10 @@
</span><span class="cx"> 
</span><span class="cx"> void ServicesOverlayController::clearHighlightState()
</span><span class="cx"> {
</span><del>-    m_mouseIsDownOnButton = false;
-    m_mouseIsOverHighlight = false;
-    m_drawingTelephoneNumberHighlight = false;
</del><ins>+    clearSelectionHighlight();
+    clearHoveredTelephoneNumberHighlight();
</ins><span class="cx"> 
</span><del>-    m_currentHighlight = nullptr;
</del><ins>+    m_telephoneNumberHighlights.clear();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ServicesOverlayController::drawRect(PageOverlay* overlay, WebCore::GraphicsContext&amp; graphicsContext, const WebCore::IntRect&amp; dirtyRect)
</span><span class="lines">@@ -271,16 +262,14 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (m_drawingTelephoneNumberHighlight)
-        drawTelephoneNumberHighlight(graphicsContext, dirtyRect);
-    else
-        drawSelectionHighlight(graphicsContext, dirtyRect);
</del><ins>+    if (drawTelephoneNumberHighlightIfVisible(graphicsContext, dirtyRect))
+        return;
+
+    drawSelectionHighlight(graphicsContext, dirtyRect);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ServicesOverlayController::drawSelectionHighlight(WebCore::GraphicsContext&amp; graphicsContext, const WebCore::IntRect&amp; dirtyRect)
</span><span class="cx"> {
</span><del>-    ASSERT(!m_drawingTelephoneNumberHighlight);
-
</del><span class="cx">     // It's possible to end up drawing the selection highlight before we've actually received the selection rects.
</span><span class="cx">     // If that happens we'll end up here again once we have the rects.
</span><span class="cx">     if (m_currentSelectionRects.isEmpty())
</span><span class="lines">@@ -290,75 +279,66 @@
</span><span class="cx">     if (!WebProcess::shared().hasSelectionServices() &amp;&amp; m_currentTelephoneNumberRanges.isEmpty())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    if (!m_currentHighlight || m_currentHighlightIsDirty) {
-        Vector&lt;CGRect&gt; cgRects;
-        cgRects.reserveCapacity(m_currentSelectionRects.size());
</del><ins>+    if (!m_selectionHighlight)
+        maybeCreateSelectionHighlight();
</ins><span class="cx"> 
</span><del>-        for (auto&amp; rect : m_currentSelectionRects)
-            cgRects.append((CGRect)pixelSnappedIntRect(rect));
-
-        if (!cgRects.isEmpty()) {
-            CGRect bounds = m_webPage-&gt;corePage()-&gt;mainFrame().view()-&gt;boundsRect();
-            m_currentHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection(nullptr, cgRects.begin(), cgRects.size(), bounds, DDHighlightNoOutlineWithArrow, YES, NSWritingDirectionNatural, NO, YES));
-            m_currentHighlightIsDirty = false;
-        }
-    }
-
-    if (m_currentHighlight)
-        drawCurrentHighlight(graphicsContext);
</del><ins>+    if (m_selectionHighlight)
+        drawHighlight(m_selectionHighlight.get(), graphicsContext);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ServicesOverlayController::drawTelephoneNumberHighlight(WebCore::GraphicsContext&amp; graphicsContext, const WebCore::IntRect&amp; dirtyRect)
</del><ins>+bool ServicesOverlayController::drawTelephoneNumberHighlightIfVisible(WebCore::GraphicsContext&amp; graphicsContext, const WebCore::IntRect&amp; dirtyRect)
</ins><span class="cx"> {
</span><del>-    ASSERT(m_drawingTelephoneNumberHighlight);
-    ASSERT(m_currentTelephoneNumberRanges.size() == 1);
</del><ins>+    // Make sure the hovered telephone number highlight is still hovered.
+    if (m_hoveredTelephoneNumberData) {
+        Boolean onButton;
+        if (!DDHighlightPointIsOnHighlight(m_hoveredTelephoneNumberData-&gt;highlight.get(), (CGPoint)m_mousePosition, &amp;onButton))
+            clearHoveredTelephoneNumberHighlight();
</ins><span class="cx"> 
</span><del>-    auto&amp; range = m_currentTelephoneNumberRanges[0];
</del><ins>+        bool foundMatchingRange = false;
</ins><span class="cx"> 
</span><del>-    // FIXME: This will choke if the range wraps around the edge of the view.
-    // What should we do in that case?
-    IntRect rect = textQuadsToBoundingRectForRange(*range);
</del><ins>+        // Make sure the hovered highlight still corresponds to a current telephone number range.
+        for (auto&amp; range : m_currentTelephoneNumberRanges) {
+            if (areRangesEqual(range.get(), m_hoveredTelephoneNumberData-&gt;range.get())) {
+                foundMatchingRange = true;
+                break;
+            }
+        }
</ins><span class="cx"> 
</span><del>-    // Convert to the main document's coordinate space.
-    // FIXME: It's a little crazy to call contentsToWindow and then windowToContents in order to get the right coordinate space.
-    // We should consider adding conversion functions to ScrollView for contentsToDocument(). Right now, contentsToRootView() is
-    // not equivalent to what we need when you have a topContentInset or a header banner.
-    FrameView* viewForRange = range-&gt;ownerDocument().view();
-    if (!viewForRange)
-        return;
-    FrameView&amp; mainFrameView = *m_webPage-&gt;corePage()-&gt;mainFrame().view();
-    rect.setLocation(mainFrameView.windowToContents(viewForRange-&gt;contentsToWindow(rect.location())));
</del><ins>+        if (!foundMatchingRange)
+            clearHoveredTelephoneNumberHighlight();
+    }
</ins><span class="cx"> 
</span><del>-    // If the selection rect is completely outside this drawing tile, don't process it further
-    if (!rect.intersects(dirtyRect))
-        return;
</del><ins>+    // Found out which - if any - telephone number is hovered.
+    if (!m_hoveredTelephoneNumberData) {
+        Boolean onButton;
+        establishHoveredTelephoneHighlight(onButton);
+    }
</ins><span class="cx"> 
</span><del>-    if (!m_currentHighlight || m_currentHighlightIsDirty) {
-        CGRect cgRect = (CGRect)rect;
-
-        m_currentHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection(nullptr, &amp;cgRect, 1, viewForRange-&gt;boundsRect(), DDHighlightOutlineWithArrow, YES, NSWritingDirectionNatural, NO, YES));
-        m_currentHighlightIsDirty = false;
</del><ins>+    // If a telephone number is actually hovered, draw it.
+    if (m_hoveredTelephoneNumberData) {
+        drawHighlight(m_hoveredTelephoneNumberData-&gt;highlight.get(), graphicsContext);
+        return true;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (m_currentHighlight)
-        drawCurrentHighlight(graphicsContext);
</del><ins>+    return false;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ServicesOverlayController::drawCurrentHighlight(WebCore::GraphicsContext&amp; graphicsContext)
</del><ins>+void ServicesOverlayController::drawHighlight(DDHighlightRef highlight, WebCore::GraphicsContext&amp; graphicsContext)
</ins><span class="cx"> {
</span><del>-    ASSERT(m_currentHighlight);
</del><ins>+    ASSERT(highlight);
</ins><span class="cx"> 
</span><span class="cx">     Boolean onButton;
</span><del>-    m_mouseIsOverHighlight = DDHighlightPointIsOnHighlight(m_currentHighlight.get(), (CGPoint)m_mousePosition, &amp;onButton);
</del><ins>+    bool mouseIsOverHighlight = DDHighlightPointIsOnHighlight(highlight, (CGPoint)m_mousePosition, &amp;onButton);
</ins><span class="cx"> 
</span><del>-    // If the mouse is not over the DDHighlight we have no drawing to do.
-    if (!m_mouseIsOverHighlight)
</del><ins>+    if (!mouseIsOverHighlight) {
+        LOG(Services, &quot;ServicesOverlayController::drawHighlight - Mouse is not over highlight, so drawing nothing&quot;);
</ins><span class="cx">         return;
</span><ins>+    }
</ins><span class="cx"> 
</span><span class="cx">     CGContextRef cgContext = graphicsContext.platformContext();
</span><span class="cx">     
</span><del>-    CGLayerRef highlightLayer = DDHighlightGetLayerWithContext(m_currentHighlight.get(), cgContext);
-    CGRect highlightBoundingRect = DDHighlightGetBoundingRect(m_currentHighlight.get());
</del><ins>+    CGLayerRef highlightLayer = DDHighlightGetLayerWithContext(highlight, cgContext);
+    CGRect highlightBoundingRect = DDHighlightGetBoundingRect(highlight);
</ins><span class="cx">     
</span><span class="cx">     GraphicsContextStateSaver stateSaver(graphicsContext);
</span><span class="cx"> 
</span><span class="lines">@@ -371,55 +351,144 @@
</span><span class="cx">     CGContextDrawLayerInRect(cgContext, highlightDrawRect, highlightLayer);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void ServicesOverlayController::clearSelectionHighlight()
+{
+    if (!m_selectionHighlight)
+        return;
+
+    if (m_currentHoveredHighlight == m_selectionHighlight)
+        m_currentHoveredHighlight = nullptr;
+    if (m_currentMouseDownOnButtonHighlight == m_selectionHighlight)
+        m_currentMouseDownOnButtonHighlight = nullptr;
+    m_selectionHighlight = nullptr;
+}
+
+void ServicesOverlayController::clearHoveredTelephoneNumberHighlight()
+{
+    if (!m_hoveredTelephoneNumberData)
+        return;
+
+    if (m_currentHoveredHighlight == m_hoveredTelephoneNumberData-&gt;highlight)
+        m_currentHoveredHighlight = nullptr;
+    if (m_currentMouseDownOnButtonHighlight == m_hoveredTelephoneNumberData-&gt;highlight)
+        m_currentMouseDownOnButtonHighlight = nullptr;
+    m_hoveredTelephoneNumberData = nullptr;
+}
+
+void ServicesOverlayController::establishHoveredTelephoneHighlight(Boolean&amp; onButton)
+{
+    ASSERT(m_currentTelephoneNumberRanges.size() == m_telephoneNumberHighlights.size());
+
+    for (unsigned i = 0; i &lt; m_currentTelephoneNumberRanges.size(); ++i) {
+        if (!m_telephoneNumberHighlights[i]) {
+            // FIXME: This will choke if the range wraps around the edge of the view.
+            // What should we do in that case?
+            IntRect rect = textQuadsToBoundingRectForRange(*m_currentTelephoneNumberRanges[i]);
+
+            // Convert to the main document's coordinate space.
+            // FIXME: It's a little crazy to call contentsToWindow and then windowToContents in order to get the right coordinate space.
+            // We should consider adding conversion functions to ScrollView for contentsToDocument(). Right now, contentsToRootView() is
+            // not equivalent to what we need when you have a topContentInset or a header banner.
+            FrameView* viewForRange = m_currentTelephoneNumberRanges[i]-&gt;ownerDocument().view();
+            if (!viewForRange)
+                continue;
+            FrameView&amp; mainFrameView = *m_webPage-&gt;corePage()-&gt;mainFrame().view();
+            rect.setLocation(mainFrameView.windowToContents(viewForRange-&gt;contentsToWindow(rect.location())));
+
+            CGRect cgRect = rect;
+            m_telephoneNumberHighlights[i] = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection(nullptr, &amp;cgRect, 1, viewForRange-&gt;boundsRect(), DDHighlightOutlineWithArrow, YES, NSWritingDirectionNatural, NO, YES));
+        }
+
+        if (!DDHighlightPointIsOnHighlight(m_telephoneNumberHighlights[i].get(), (CGPoint)m_mousePosition, &amp;onButton))
+            continue;
+
+        if (!m_hoveredTelephoneNumberData || m_hoveredTelephoneNumberData-&gt;highlight != m_telephoneNumberHighlights[i])
+            m_hoveredTelephoneNumberData = std::make_unique&lt;TelephoneNumberData&gt;(m_telephoneNumberHighlights[i], m_currentTelephoneNumberRanges[i]);
+
+        m_servicesOverlay-&gt;setNeedsDisplay();
+        return;
+    }
+
+    clearHoveredTelephoneNumberHighlight();
+    onButton = false;
+}
+
+void ServicesOverlayController::maybeCreateSelectionHighlight()
+{
+    ASSERT(!m_selectionHighlight);
+    ASSERT(m_servicesOverlay);
+
+    Vector&lt;CGRect&gt; cgRects;
+    cgRects.reserveCapacity(m_currentSelectionRects.size());
+
+    for (auto&amp; rect : m_currentSelectionRects)
+        cgRects.append((CGRect)pixelSnappedIntRect(rect));
+
+    if (!cgRects.isEmpty()) {
+        CGRect bounds = m_webPage-&gt;corePage()-&gt;mainFrame().view()-&gt;boundsRect();
+        m_selectionHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection(nullptr, cgRects.begin(), cgRects.size(), bounds, DDHighlightNoOutlineWithArrow, YES, NSWritingDirectionNatural, NO, YES));
+
+        m_servicesOverlay-&gt;setNeedsDisplay();
+    }
+}
+
</ins><span class="cx"> bool ServicesOverlayController::mouseEvent(PageOverlay*, const WebMouseEvent&amp; event)
</span><span class="cx"> {
</span><span class="cx">     m_mousePosition = m_webPage-&gt;corePage()-&gt;mainFrame().view()-&gt;rootViewToContents(event.position());
</span><span class="cx"> 
</span><del>-    bool mouseWasOverHighlight = m_mouseIsOverHighlight;
</del><ins>+    DDHighlightRef oldHoveredHighlight = m_currentHoveredHighlight.get();
+
</ins><span class="cx">     Boolean onButton = false;
</span><del>-    m_mouseIsOverHighlight = m_currentHighlight ? DDHighlightPointIsOnHighlight(m_currentHighlight.get(), (CGPoint)m_mousePosition, &amp;onButton) : false;
</del><ins>+    establishHoveredTelephoneHighlight(onButton);
+    if (m_hoveredTelephoneNumberData) {
+        ASSERT(m_hoveredTelephoneNumberData-&gt;highlight);
+        m_currentHoveredHighlight = m_hoveredTelephoneNumberData-&gt;highlight;
+    } else {
+        if (!m_selectionHighlight)
+            maybeCreateSelectionHighlight();
</ins><span class="cx"> 
</span><del>-    if (mouseWasOverHighlight != m_mouseIsOverHighlight)
</del><ins>+        if (m_selectionHighlight &amp;&amp; DDHighlightPointIsOnHighlight(m_selectionHighlight.get(), (CGPoint)m_mousePosition, &amp;onButton))
+            m_currentHoveredHighlight = m_selectionHighlight;
+        else
+            m_currentHoveredHighlight = nullptr;
+    }
+
+    if (oldHoveredHighlight != m_currentHoveredHighlight)
</ins><span class="cx">         m_servicesOverlay-&gt;setNeedsDisplay();
</span><span class="cx"> 
</span><span class="cx">     // If this event has nothing to do with the left button, it clears the current mouse down tracking and we're done processing it.
</span><span class="cx">     if (event.button() != WebMouseEvent::LeftButton) {
</span><del>-        m_mouseIsDownOnButton = false;
</del><ins>+        m_currentMouseDownOnButtonHighlight = nullptr;
</ins><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (!m_currentHighlight)
-        return false;
-
</del><span class="cx">     // Check and see if the mouse went up and we have a current mouse down highlight button.
</span><span class="cx">     if (event.type() == WebEvent::MouseUp) {
</span><del>-        bool mouseWasDownOnButton = m_mouseIsDownOnButton;
-        m_mouseIsDownOnButton = false;
</del><ins>+        RetainPtr&lt;DDHighlightRef&gt; mouseDownHighlight = std::move(m_currentMouseDownOnButtonHighlight);
</ins><span class="cx"> 
</span><span class="cx">         // If the mouse lifted while still over the highlight button that it went down on, then that is a click.
</span><del>-        if (m_mouseIsOverHighlight &amp;&amp; onButton &amp;&amp; mouseWasDownOnButton) {
-            handleClick(m_mousePosition);
</del><ins>+        if (onButton &amp;&amp; mouseDownHighlight) {
+            handleClick(m_mousePosition, mouseDownHighlight.get());
</ins><span class="cx">             return true;
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         return false;
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     // Check and see if the mouse moved within the confines of the DD highlight button.
</span><span class="cx">     if (event.type() == WebEvent::MouseMove) {
</span><span class="cx">         // Moving with the mouse button down is okay as long as the mouse never leaves the highlight button.
</span><del>-        if (m_mouseIsOverHighlight &amp;&amp; onButton)
</del><ins>+        if (m_currentMouseDownOnButtonHighlight &amp;&amp; onButton)
</ins><span class="cx">             return true;
</span><span class="cx"> 
</span><del>-        m_mouseIsDownOnButton = false;
-        
</del><ins>+        m_currentMouseDownOnButtonHighlight = nullptr;
</ins><span class="cx">         return false;
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     // Check and see if the mouse went down over a DD highlight button.
</span><span class="cx">     if (event.type() == WebEvent::MouseDown) {
</span><del>-        if (m_mouseIsOverHighlight &amp;&amp; onButton) {
-            m_mouseIsDownOnButton = true;
</del><ins>+        if (m_currentHoveredHighlight &amp;&amp; onButton) {
+            m_currentMouseDownOnButtonHighlight = m_currentHoveredHighlight;
</ins><span class="cx">             m_servicesOverlay-&gt;setNeedsDisplay();
</span><span class="cx">             return true;
</span><span class="cx">         }
</span><span class="lines">@@ -430,25 +499,27 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ServicesOverlayController::handleClick(const WebCore::IntPoint&amp; clickPoint)
</del><ins>+void ServicesOverlayController::handleClick(const WebCore::IntPoint&amp; clickPoint, DDHighlightRef highlight)
</ins><span class="cx"> {
</span><ins>+    ASSERT(highlight);
+
</ins><span class="cx">     FrameView* frameView = m_webPage-&gt;mainFrameView();
</span><span class="cx">     if (!frameView)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     IntPoint windowPoint = frameView-&gt;contentsToWindow(clickPoint);
</span><span class="cx"> 
</span><del>-    if (m_drawingTelephoneNumberHighlight) {
-        ASSERT(m_currentTelephoneNumberRanges.size() == 1);
-        m_webPage-&gt;handleTelephoneNumberClick(m_currentTelephoneNumberRanges[0]-&gt;text(), windowPoint);
-    } else {
</del><ins>+    if (highlight == m_selectionHighlight) {
</ins><span class="cx">         Vector&lt;String&gt; selectedTelephoneNumbers;
</span><span class="cx">         selectedTelephoneNumbers.reserveCapacity(m_currentTelephoneNumberRanges.size());
</span><span class="cx">         for (auto&amp; range : m_currentTelephoneNumberRanges)
</span><span class="cx">             selectedTelephoneNumbers.append(range-&gt;text());
</span><span class="cx"> 
</span><span class="cx">         m_webPage-&gt;handleSelectionServiceClick(m_webPage-&gt;corePage()-&gt;mainFrame().selection(), selectedTelephoneNumbers, windowPoint);
</span><del>-    }
</del><ins>+    } else if (m_hoveredTelephoneNumberData &amp;&amp; m_hoveredTelephoneNumberData-&gt;highlight == highlight)
+        m_webPage-&gt;handleTelephoneNumberClick(m_hoveredTelephoneNumberData-&gt;range-&gt;text(), windowPoint);
+    else
+        ASSERT_NOT_REACHED();
</ins><span class="cx"> }
</span><span class="cx">     
</span><span class="cx"> } // namespace WebKit
</span></span></pre>
</div>
</div>

</body>
</html>