Title: [170966] trunk/Source
Revision
170966
Author
[email protected]
Date
2014-07-10 09:19:56 -0700 (Thu, 10 Jul 2014)

Log Message

Phone number highlights should always be visible if the mouse hovers over.
<rdar://problem/17527476> 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.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (170965 => 170966)


--- 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)
@@ -1,3 +1,12 @@
+2014-07-10  Brady Eidson  <[email protected]>
+
+        Phone number highlights should always be visible if the mouse hovers over.
+        <rdar://problem/17527476> and https://bugs.webkit.org/show_bug.cgi?id=134784
+
+        Reviewed by Tim Horton.
+
+        * WebCore.exp.in:
+
 2014-07-10  Timothy Horton  <[email protected]>
 
         Assertions or crashes under _takeViewSnapshot when restoring windows

Modified: trunk/Source/WebCore/WebCore.exp.in (170965 => 170966)


--- 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)
@@ -459,6 +459,7 @@
 __ZN7WebCore14TileController23setTileDebugBorderWidthEf
 __ZN7WebCore14TileController27tileCacheLayerBoundsChangedEv
 __ZN7WebCore14TileController6createEPNS_15PlatformCALayerE
+__ZN7WebCore14areRangesEqualEPKNS_5RangeES2_
 __ZN7WebCore14decodeHostNameEP8NSString
 __ZN7WebCore14encodeHostNameEP8NSString
 __ZN7WebCore14endOfParagraphERKNS_15VisiblePositionENS_27EditingBoundaryCrossingRuleE

Modified: trunk/Source/WebKit2/ChangeLog (170965 => 170966)


--- 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)
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
 2014-07-10  Timothy Horton  <[email protected]>
 
         Assertions or crashes under _takeViewSnapshot when restoring windows
@@ -358,7 +359,49 @@
         (-[WKPreferences _setTiledScrollingIndicatorVisible:]):
         * UIProcess/API/Cocoa/WKPreferencesPrivate.h:
         Expose layer borders, repaint counters, and the tiled scrolling indicator on WKPreferences, as SPI.
+=======
+2014-07-09  Brady Eidson  <[email protected]>
 
+        Phone number highlights should always be visible if the mouse hovers over.
+        <rdar://problem/17527476> 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.
+>>>>>>> Phone number highlights should always be visible if the mouse hovers over.
+
 2014-07-08  Tim Horton  <[email protected]>
 
         WKProcessPoolConfigurationPrivate's maximumProcessCount property has no effect

Modified: trunk/Source/WebKit2/Platform/Logging.h (170965 => 170966)


--- 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)
@@ -51,6 +51,7 @@
     M(TextInput) \
     M(View) \
     M(IDB) \
+    M(Services) \
 
 #define DECLARE_LOG_CHANNEL(name) \
     extern WTFLogChannel JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, name);

Modified: trunk/Source/WebKit2/WebProcess/WebPage/ServicesOverlayController.h (170965 => 170966)


--- 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)
@@ -44,6 +44,17 @@
 
 typedef void* DDHighlightRef;
 
+struct TelephoneNumberData {
+    TelephoneNumberData(RetainPtr<DDHighlightRef> highlight, PassRefPtr<WebCore::Range> range)
+        : highlight(highlight)
+        , range(range)
+    {
+    }
+
+    RetainPtr<DDHighlightRef> highlight;
+    RefPtr<WebCore::Range> range;
+};
+
 class ServicesOverlayController : private PageOverlay::Client {
 public:
     ServicesOverlayController(WebPage&);
@@ -54,32 +65,39 @@
 
 private:
     void createOverlayIfNeeded();
-    void handleClick(const WebCore::IntPoint&);
+    void handleClick(const WebCore::IntPoint&, DDHighlightRef);
     void clearHighlightState();
-    
+
     virtual void pageOverlayDestroyed(PageOverlay*) override;
     virtual void willMoveToWebPage(PageOverlay*, WebPage*) override;
     virtual void didMoveToWebPage(PageOverlay*, WebPage*) override;
     virtual void drawRect(PageOverlay*, WebCore::GraphicsContext&, const WebCore::IntRect& dirtyRect) override;
     virtual bool mouseEvent(PageOverlay*, const WebMouseEvent&) override;
 
-    void drawTelephoneNumberHighlight(WebCore::GraphicsContext&, const WebCore::IntRect& dirtyRect);
+    bool drawTelephoneNumberHighlightIfVisible(WebCore::GraphicsContext&, const WebCore::IntRect& dirtyRect);
     void drawSelectionHighlight(WebCore::GraphicsContext&, const WebCore::IntRect& dirtyRect);
-    void drawCurrentHighlight(WebCore::GraphicsContext&);
+    void drawHighlight(DDHighlightRef, WebCore::GraphicsContext&);
 
+    void establishHoveredTelephoneHighlight(Boolean& onButton);
+    void maybeCreateSelectionHighlight();
+
+    void clearSelectionHighlight();
+    void clearHoveredTelephoneNumberHighlight();
+
     WebPage* m_webPage;
     PageOverlay* m_servicesOverlay;
     
     Vector<WebCore::LayoutRect> m_currentSelectionRects;
+    RetainPtr<DDHighlightRef> m_selectionHighlight;
+
     Vector<RefPtr<WebCore::Range>> m_currentTelephoneNumberRanges;
+    Vector<RetainPtr<DDHighlightRef>> m_telephoneNumberHighlights;
+    std::unique_ptr<TelephoneNumberData> m_hoveredTelephoneNumberData;
 
+    RetainPtr<DDHighlightRef> m_currentHoveredHighlight;
+    RetainPtr<DDHighlightRef> m_currentMouseDownOnButtonHighlight;
+
     WebCore::IntPoint m_mousePosition;
-    bool m_mouseIsDownOnButton;
-    bool m_mouseIsOverHighlight;
-    bool m_drawingTelephoneNumberHighlight;
-
-    RetainPtr<DDHighlightRef> m_currentHighlight;
-    bool m_currentHighlightIsDirty;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/ServicesOverlayController.mm (170965 => 170966)


--- 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)
@@ -28,6 +28,7 @@
 
 #if ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(MAC)
 
+#import "Logging.h"
 #import "WebPage.h"
 #import "WebProcess.h"
 #import <WebCore/Document.h>
@@ -75,10 +76,6 @@
 ServicesOverlayController::ServicesOverlayController(WebPage& webPage)
     : m_webPage(&webPage)
     , m_servicesOverlay(nullptr)
-    , m_mouseIsDownOnButton(false)
-    , m_mouseIsOverHighlight(false)
-    , m_drawingTelephoneNumberHighlight(false)
-    , m_currentHighlightIsDirty(false)
 {
 }
 
@@ -220,7 +217,7 @@
 void ServicesOverlayController::selectionRectsDidChange(const Vector<LayoutRect>& rects, const Vector<GapRects>& gapRects)
 {
 #if __MAC_OS_X_VERSION_MIN_REQUIRED > 1090
-    m_currentHighlightIsDirty = true;
+    clearSelectionHighlight();
     m_currentSelectionRects = rects;
 
     compactRectsWithGapRects(m_currentSelectionRects, gapRects);
@@ -228,6 +225,8 @@
     // DataDetectors needs these reversed in order to place the arrow in the right location.
     m_currentSelectionRects.reverse();
 
+    LOG(Services, "ServicesOverlayController - Selection rects changed - Now have %lu\n", rects.size());
+
     createOverlayIfNeeded();
 #else
     UNUSED_PARAM(rects);
@@ -237,18 +236,11 @@
 void ServicesOverlayController::selectedTelephoneNumberRangesChanged(const Vector<RefPtr<Range>>& ranges)
 {
 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED > 1090
-    m_currentHighlightIsDirty = true;
+    LOG(Services, "ServicesOverlayController - Telephone number ranges changed - Had %lu, now have %lu\n", m_currentTelephoneNumberRanges.size(), ranges.size());
     m_currentTelephoneNumberRanges = ranges;
-    m_drawingTelephoneNumberHighlight = false;
+    m_telephoneNumberHighlights.clear();
+    m_telephoneNumberHighlights.resize(ranges.size());
 
-    if (ranges.size() == 1) {
-        if (Frame* frame = ranges[0]->startContainer()->document().frame()) {
-            RefPtr<Range> selectionRange = frame->selection().toNormalizedRange();
-            if (ranges[0]->contains(*selectionRange))
-                m_drawingTelephoneNumberHighlight = true;
-        }
-    }
-    
     createOverlayIfNeeded();
 #else
     UNUSED_PARAM(ranges);
@@ -257,11 +249,10 @@
 
 void ServicesOverlayController::clearHighlightState()
 {
-    m_mouseIsDownOnButton = false;
-    m_mouseIsOverHighlight = false;
-    m_drawingTelephoneNumberHighlight = false;
+    clearSelectionHighlight();
+    clearHoveredTelephoneNumberHighlight();
 
-    m_currentHighlight = nullptr;
+    m_telephoneNumberHighlights.clear();
 }
 
 void ServicesOverlayController::drawRect(PageOverlay* overlay, WebCore::GraphicsContext& graphicsContext, const WebCore::IntRect& dirtyRect)
@@ -271,16 +262,14 @@
         return;
     }
 
-    if (m_drawingTelephoneNumberHighlight)
-        drawTelephoneNumberHighlight(graphicsContext, dirtyRect);
-    else
-        drawSelectionHighlight(graphicsContext, dirtyRect);
+    if (drawTelephoneNumberHighlightIfVisible(graphicsContext, dirtyRect))
+        return;
+
+    drawSelectionHighlight(graphicsContext, dirtyRect);
 }
 
 void ServicesOverlayController::drawSelectionHighlight(WebCore::GraphicsContext& graphicsContext, const WebCore::IntRect& dirtyRect)
 {
-    ASSERT(!m_drawingTelephoneNumberHighlight);
-
     // It's possible to end up drawing the selection highlight before we've actually received the selection rects.
     // If that happens we'll end up here again once we have the rects.
     if (m_currentSelectionRects.isEmpty())
@@ -290,75 +279,66 @@
     if (!WebProcess::shared().hasSelectionServices() && m_currentTelephoneNumberRanges.isEmpty())
         return;
 
-    if (!m_currentHighlight || m_currentHighlightIsDirty) {
-        Vector<CGRect> cgRects;
-        cgRects.reserveCapacity(m_currentSelectionRects.size());
+    if (!m_selectionHighlight)
+        maybeCreateSelectionHighlight();
 
-        for (auto& rect : m_currentSelectionRects)
-            cgRects.append((CGRect)pixelSnappedIntRect(rect));
-
-        if (!cgRects.isEmpty()) {
-            CGRect bounds = m_webPage->corePage()->mainFrame().view()->boundsRect();
-            m_currentHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection(nullptr, cgRects.begin(), cgRects.size(), bounds, DDHighlightNoOutlineWithArrow, YES, NSWritingDirectionNatural, NO, YES));
-            m_currentHighlightIsDirty = false;
-        }
-    }
-
-    if (m_currentHighlight)
-        drawCurrentHighlight(graphicsContext);
+    if (m_selectionHighlight)
+        drawHighlight(m_selectionHighlight.get(), graphicsContext);
 }
 
-void ServicesOverlayController::drawTelephoneNumberHighlight(WebCore::GraphicsContext& graphicsContext, const WebCore::IntRect& dirtyRect)
+bool ServicesOverlayController::drawTelephoneNumberHighlightIfVisible(WebCore::GraphicsContext& graphicsContext, const WebCore::IntRect& dirtyRect)
 {
-    ASSERT(m_drawingTelephoneNumberHighlight);
-    ASSERT(m_currentTelephoneNumberRanges.size() == 1);
+    // Make sure the hovered telephone number highlight is still hovered.
+    if (m_hoveredTelephoneNumberData) {
+        Boolean onButton;
+        if (!DDHighlightPointIsOnHighlight(m_hoveredTelephoneNumberData->highlight.get(), (CGPoint)m_mousePosition, &onButton))
+            clearHoveredTelephoneNumberHighlight();
 
-    auto& range = m_currentTelephoneNumberRanges[0];
+        bool foundMatchingRange = false;
 
-    // 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);
+        // Make sure the hovered highlight still corresponds to a current telephone number range.
+        for (auto& range : m_currentTelephoneNumberRanges) {
+            if (areRangesEqual(range.get(), m_hoveredTelephoneNumberData->range.get())) {
+                foundMatchingRange = true;
+                break;
+            }
+        }
 
-    // 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->ownerDocument().view();
-    if (!viewForRange)
-        return;
-    FrameView& mainFrameView = *m_webPage->corePage()->mainFrame().view();
-    rect.setLocation(mainFrameView.windowToContents(viewForRange->contentsToWindow(rect.location())));
+        if (!foundMatchingRange)
+            clearHoveredTelephoneNumberHighlight();
+    }
 
-    // If the selection rect is completely outside this drawing tile, don't process it further
-    if (!rect.intersects(dirtyRect))
-        return;
+    // Found out which - if any - telephone number is hovered.
+    if (!m_hoveredTelephoneNumberData) {
+        Boolean onButton;
+        establishHoveredTelephoneHighlight(onButton);
+    }
 
-    if (!m_currentHighlight || m_currentHighlightIsDirty) {
-        CGRect cgRect = (CGRect)rect;
-
-        m_currentHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection(nullptr, &cgRect, 1, viewForRange->boundsRect(), DDHighlightOutlineWithArrow, YES, NSWritingDirectionNatural, NO, YES));
-        m_currentHighlightIsDirty = false;
+    // If a telephone number is actually hovered, draw it.
+    if (m_hoveredTelephoneNumberData) {
+        drawHighlight(m_hoveredTelephoneNumberData->highlight.get(), graphicsContext);
+        return true;
     }
 
-    if (m_currentHighlight)
-        drawCurrentHighlight(graphicsContext);
+    return false;
 }
 
-void ServicesOverlayController::drawCurrentHighlight(WebCore::GraphicsContext& graphicsContext)
+void ServicesOverlayController::drawHighlight(DDHighlightRef highlight, WebCore::GraphicsContext& graphicsContext)
 {
-    ASSERT(m_currentHighlight);
+    ASSERT(highlight);
 
     Boolean onButton;
-    m_mouseIsOverHighlight = DDHighlightPointIsOnHighlight(m_currentHighlight.get(), (CGPoint)m_mousePosition, &onButton);
+    bool mouseIsOverHighlight = DDHighlightPointIsOnHighlight(highlight, (CGPoint)m_mousePosition, &onButton);
 
-    // If the mouse is not over the DDHighlight we have no drawing to do.
-    if (!m_mouseIsOverHighlight)
+    if (!mouseIsOverHighlight) {
+        LOG(Services, "ServicesOverlayController::drawHighlight - Mouse is not over highlight, so drawing nothing");
         return;
+    }
 
     CGContextRef cgContext = graphicsContext.platformContext();
     
-    CGLayerRef highlightLayer = DDHighlightGetLayerWithContext(m_currentHighlight.get(), cgContext);
-    CGRect highlightBoundingRect = DDHighlightGetBoundingRect(m_currentHighlight.get());
+    CGLayerRef highlightLayer = DDHighlightGetLayerWithContext(highlight, cgContext);
+    CGRect highlightBoundingRect = DDHighlightGetBoundingRect(highlight);
     
     GraphicsContextStateSaver stateSaver(graphicsContext);
 
@@ -371,55 +351,144 @@
     CGContextDrawLayerInRect(cgContext, highlightDrawRect, highlightLayer);
 }
 
+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->highlight)
+        m_currentHoveredHighlight = nullptr;
+    if (m_currentMouseDownOnButtonHighlight == m_hoveredTelephoneNumberData->highlight)
+        m_currentMouseDownOnButtonHighlight = nullptr;
+    m_hoveredTelephoneNumberData = nullptr;
+}
+
+void ServicesOverlayController::establishHoveredTelephoneHighlight(Boolean& onButton)
+{
+    ASSERT(m_currentTelephoneNumberRanges.size() == m_telephoneNumberHighlights.size());
+
+    for (unsigned i = 0; i < 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]->ownerDocument().view();
+            if (!viewForRange)
+                continue;
+            FrameView& mainFrameView = *m_webPage->corePage()->mainFrame().view();
+            rect.setLocation(mainFrameView.windowToContents(viewForRange->contentsToWindow(rect.location())));
+
+            CGRect cgRect = rect;
+            m_telephoneNumberHighlights[i] = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection(nullptr, &cgRect, 1, viewForRange->boundsRect(), DDHighlightOutlineWithArrow, YES, NSWritingDirectionNatural, NO, YES));
+        }
+
+        if (!DDHighlightPointIsOnHighlight(m_telephoneNumberHighlights[i].get(), (CGPoint)m_mousePosition, &onButton))
+            continue;
+
+        if (!m_hoveredTelephoneNumberData || m_hoveredTelephoneNumberData->highlight != m_telephoneNumberHighlights[i])
+            m_hoveredTelephoneNumberData = std::make_unique<TelephoneNumberData>(m_telephoneNumberHighlights[i], m_currentTelephoneNumberRanges[i]);
+
+        m_servicesOverlay->setNeedsDisplay();
+        return;
+    }
+
+    clearHoveredTelephoneNumberHighlight();
+    _onButton_ = false;
+}
+
+void ServicesOverlayController::maybeCreateSelectionHighlight()
+{
+    ASSERT(!m_selectionHighlight);
+    ASSERT(m_servicesOverlay);
+
+    Vector<CGRect> cgRects;
+    cgRects.reserveCapacity(m_currentSelectionRects.size());
+
+    for (auto& rect : m_currentSelectionRects)
+        cgRects.append((CGRect)pixelSnappedIntRect(rect));
+
+    if (!cgRects.isEmpty()) {
+        CGRect bounds = m_webPage->corePage()->mainFrame().view()->boundsRect();
+        m_selectionHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection(nullptr, cgRects.begin(), cgRects.size(), bounds, DDHighlightNoOutlineWithArrow, YES, NSWritingDirectionNatural, NO, YES));
+
+        m_servicesOverlay->setNeedsDisplay();
+    }
+}
+
 bool ServicesOverlayController::mouseEvent(PageOverlay*, const WebMouseEvent& event)
 {
     m_mousePosition = m_webPage->corePage()->mainFrame().view()->rootViewToContents(event.position());
 
-    bool mouseWasOverHighlight = m_mouseIsOverHighlight;
+    DDHighlightRef oldHoveredHighlight = m_currentHoveredHighlight.get();
+
     Boolean _onButton_ = false;
-    m_mouseIsOverHighlight = m_currentHighlight ? DDHighlightPointIsOnHighlight(m_currentHighlight.get(), (CGPoint)m_mousePosition, &onButton) : false;
+    establishHoveredTelephoneHighlight(onButton);
+    if (m_hoveredTelephoneNumberData) {
+        ASSERT(m_hoveredTelephoneNumberData->highlight);
+        m_currentHoveredHighlight = m_hoveredTelephoneNumberData->highlight;
+    } else {
+        if (!m_selectionHighlight)
+            maybeCreateSelectionHighlight();
 
-    if (mouseWasOverHighlight != m_mouseIsOverHighlight)
+        if (m_selectionHighlight && DDHighlightPointIsOnHighlight(m_selectionHighlight.get(), (CGPoint)m_mousePosition, &onButton))
+            m_currentHoveredHighlight = m_selectionHighlight;
+        else
+            m_currentHoveredHighlight = nullptr;
+    }
+
+    if (oldHoveredHighlight != m_currentHoveredHighlight)
         m_servicesOverlay->setNeedsDisplay();
 
     // If this event has nothing to do with the left button, it clears the current mouse down tracking and we're done processing it.
     if (event.button() != WebMouseEvent::LeftButton) {
-        m_mouseIsDownOnButton = false;
+        m_currentMouseDownOnButtonHighlight = nullptr;
         return false;
     }
 
-    if (!m_currentHighlight)
-        return false;
-
     // Check and see if the mouse went up and we have a current mouse down highlight button.
     if (event.type() == WebEvent::MouseUp) {
-        bool mouseWasDownOnButton = m_mouseIsDownOnButton;
-        m_mouseIsDownOnButton = false;
+        RetainPtr<DDHighlightRef> mouseDownHighlight = std::move(m_currentMouseDownOnButtonHighlight);
 
         // If the mouse lifted while still over the highlight button that it went down on, then that is a click.
-        if (m_mouseIsOverHighlight && onButton && mouseWasDownOnButton) {
-            handleClick(m_mousePosition);
+        if (onButton && mouseDownHighlight) {
+            handleClick(m_mousePosition, mouseDownHighlight.get());
             return true;
         }
         
         return false;
     }
-    
+
     // Check and see if the mouse moved within the confines of the DD highlight button.
     if (event.type() == WebEvent::MouseMove) {
         // Moving with the mouse button down is okay as long as the mouse never leaves the highlight button.
-        if (m_mouseIsOverHighlight && onButton)
+        if (m_currentMouseDownOnButtonHighlight && onButton)
             return true;
 
-        m_mouseIsDownOnButton = false;
-        
+        m_currentMouseDownOnButtonHighlight = nullptr;
         return false;
     }
-    
+
     // Check and see if the mouse went down over a DD highlight button.
     if (event.type() == WebEvent::MouseDown) {
-        if (m_mouseIsOverHighlight && onButton) {
-            m_mouseIsDownOnButton = true;
+        if (m_currentHoveredHighlight && onButton) {
+            m_currentMouseDownOnButtonHighlight = m_currentHoveredHighlight;
             m_servicesOverlay->setNeedsDisplay();
             return true;
         }
@@ -430,25 +499,27 @@
     return false;
 }
 
-void ServicesOverlayController::handleClick(const WebCore::IntPoint& clickPoint)
+void ServicesOverlayController::handleClick(const WebCore::IntPoint& clickPoint, DDHighlightRef highlight)
 {
+    ASSERT(highlight);
+
     FrameView* frameView = m_webPage->mainFrameView();
     if (!frameView)
         return;
 
     IntPoint windowPoint = frameView->contentsToWindow(clickPoint);
 
-    if (m_drawingTelephoneNumberHighlight) {
-        ASSERT(m_currentTelephoneNumberRanges.size() == 1);
-        m_webPage->handleTelephoneNumberClick(m_currentTelephoneNumberRanges[0]->text(), windowPoint);
-    } else {
+    if (highlight == m_selectionHighlight) {
         Vector<String> selectedTelephoneNumbers;
         selectedTelephoneNumbers.reserveCapacity(m_currentTelephoneNumberRanges.size());
         for (auto& range : m_currentTelephoneNumberRanges)
             selectedTelephoneNumbers.append(range->text());
 
         m_webPage->handleSelectionServiceClick(m_webPage->corePage()->mainFrame().selection(), selectedTelephoneNumbers, windowPoint);
-    }
+    } else if (m_hoveredTelephoneNumberData && m_hoveredTelephoneNumberData->highlight == highlight)
+        m_webPage->handleTelephoneNumberClick(m_hoveredTelephoneNumberData->range->text(), windowPoint);
+    else
+        ASSERT_NOT_REACHED();
 }
     
 } // namespace WebKit
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to