From bce05c4b7b75cefd5fcf6a0bdeab037a5a60114d Mon Sep 17 00:00:00 2001 From: "beidson@apple.com" Date: Thu, 10 Jul 2014 16:19:56 +0000 Subject: [PATCH] Phone number highlights should always be visible if the mouse hovers over. and https://bugs.webkit.org/show_bug.cgi?id=134784 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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. git-svn-id: https://svn.webkit.org/repository/webkit/trunk@170966 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- Source/WebCore/ChangeLog | 9 + Source/WebCore/WebCore.exp.in | 1 + Source/WebKit2/ChangeLog | 43 +++ Source/WebKit2/Platform/Logging.h | 1 + .../WebPage/ServicesOverlayController.h | 38 ++- .../WebPage/mac/ServicesOverlayController.mm | 269 +++++++++++------- 6 files changed, 252 insertions(+), 109 deletions(-) diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog index f640b1208200..741f06173635 100644 --- a/Source/WebCore/ChangeLog +++ b/Source/WebCore/ChangeLog @@ -1,3 +1,12 @@ +2014-07-10 Brady Eidson + + Phone number highlights should always be visible if the mouse hovers over. + and https://bugs.webkit.org/show_bug.cgi?id=134784 + + Reviewed by Tim Horton. + + * WebCore.exp.in: + 2014-07-10 Timothy Horton Assertions or crashes under _takeViewSnapshot when restoring windows diff --git a/Source/WebCore/WebCore.exp.in b/Source/WebCore/WebCore.exp.in index 0addc015a69f..09cf22339d33 100644 --- a/Source/WebCore/WebCore.exp.in +++ b/Source/WebCore/WebCore.exp.in @@ -459,6 +459,7 @@ __ZN7WebCore14TileController23setTileDebugBorderColorENS_5ColorE __ZN7WebCore14TileController23setTileDebugBorderWidthEf __ZN7WebCore14TileController27tileCacheLayerBoundsChangedEv __ZN7WebCore14TileController6createEPNS_15PlatformCALayerE +__ZN7WebCore14areRangesEqualEPKNS_5RangeES2_ __ZN7WebCore14decodeHostNameEP8NSString __ZN7WebCore14encodeHostNameEP8NSString __ZN7WebCore14endOfParagraphERKNS_15VisiblePositionENS_27EditingBoundaryCrossingRuleE diff --git a/Source/WebKit2/ChangeLog b/Source/WebKit2/ChangeLog index 547d73c8a44d..77ff4f915afe 100644 --- a/Source/WebKit2/ChangeLog +++ b/Source/WebKit2/ChangeLog @@ -1,3 +1,4 @@ +<<<<<<< HEAD 2014-07-10 Timothy Horton Assertions or crashes under _takeViewSnapshot when restoring windows @@ -358,6 +359,48 @@ (-[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 + + Phone number highlights should always be visible if the mouse hovers over. + 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 diff --git a/Source/WebKit2/Platform/Logging.h b/Source/WebKit2/Platform/Logging.h index f5d984dc4384..0e3e1de79f35 100644 --- a/Source/WebKit2/Platform/Logging.h +++ b/Source/WebKit2/Platform/Logging.h @@ -51,6 +51,7 @@ namespace WebKit { M(TextInput) \ M(View) \ M(IDB) \ + M(Services) \ #define DECLARE_LOG_CHANNEL(name) \ extern WTFLogChannel JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, name); diff --git a/Source/WebKit2/WebProcess/WebPage/ServicesOverlayController.h b/Source/WebKit2/WebProcess/WebPage/ServicesOverlayController.h index 06f289ac527a..e6780a091f9e 100644 --- a/Source/WebKit2/WebProcess/WebPage/ServicesOverlayController.h +++ b/Source/WebKit2/WebProcess/WebPage/ServicesOverlayController.h @@ -44,6 +44,17 @@ class WebPage; typedef void* DDHighlightRef; +struct TelephoneNumberData { + TelephoneNumberData(RetainPtr highlight, PassRefPtr range) + : highlight(highlight) + , range(range) + { + } + + RetainPtr highlight; + RefPtr range; +}; + class ServicesOverlayController : private PageOverlay::Client { public: ServicesOverlayController(WebPage&); @@ -54,32 +65,39 @@ public: 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 m_currentSelectionRects; + RetainPtr m_selectionHighlight; + Vector> m_currentTelephoneNumberRanges; + Vector> m_telephoneNumberHighlights; + std::unique_ptr m_hoveredTelephoneNumberData; - WebCore::IntPoint m_mousePosition; - bool m_mouseIsDownOnButton; - bool m_mouseIsOverHighlight; - bool m_drawingTelephoneNumberHighlight; + RetainPtr m_currentHoveredHighlight; + RetainPtr m_currentMouseDownOnButtonHighlight; - RetainPtr m_currentHighlight; - bool m_currentHighlightIsDirty; + WebCore::IntPoint m_mousePosition; }; } // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/mac/ServicesOverlayController.mm b/Source/WebKit2/WebProcess/WebPage/mac/ServicesOverlayController.mm index 9d8cc124ee43..c2a07d021f77 100644 --- a/Source/WebKit2/WebProcess/WebPage/mac/ServicesOverlayController.mm +++ b/Source/WebKit2/WebProcess/WebPage/mac/ServicesOverlayController.mm @@ -28,6 +28,7 @@ #if ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(MAC) +#import "Logging.h" #import "WebPage.h" #import "WebProcess.h" #import @@ -75,10 +76,6 @@ static IntRect textQuadsToBoundingRectForRange(Range& range) 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 @@ static void compactRectsWithGapRects(Vector& rects, const Vector& rects, const Vector& gapRects) { #if __MAC_OS_X_VERSION_MIN_REQUIRED > 1090 - m_currentHighlightIsDirty = true; + clearSelectionHighlight(); m_currentSelectionRects = rects; compactRectsWithGapRects(m_currentSelectionRects, gapRects); @@ -228,6 +225,8 @@ void ServicesOverlayController::selectionRectsDidChange(const Vector // 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::selectionRectsDidChange(const Vector void ServicesOverlayController::selectedTelephoneNumberRangesChanged(const Vector>& 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 selectionRange = frame->selection().toNormalizedRange(); - if (ranges[0]->contains(*selectionRange)) - m_drawingTelephoneNumberHighlight = true; - } - } - createOverlayIfNeeded(); #else UNUSED_PARAM(ranges); @@ -257,11 +249,10 @@ void ServicesOverlayController::selectedTelephoneNumberRangesChanged(const Vecto 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 @@ void ServicesOverlayController::drawRect(PageOverlay* overlay, WebCore::Graphics 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 @@ void ServicesOverlayController::drawSelectionHighlight(WebCore::GraphicsContext& if (!WebProcess::shared().hasSelectionServices() && m_currentTelephoneNumberRanges.isEmpty()) return; - if (!m_currentHighlight || m_currentHighlightIsDirty) { - Vector cgRects; - cgRects.reserveCapacity(m_currentSelectionRects.size()); - - for (auto& rect : m_currentSelectionRects) - cgRects.append((CGRect)pixelSnappedIntRect(rect)); + if (!m_selectionHighlight) + maybeCreateSelectionHighlight(); - 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); - - auto& range = m_currentTelephoneNumberRanges[0]; - - // 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); - - // 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()))); + // 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(); + + bool foundMatchingRange = false; + + // 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; + } + } - // If the selection rect is completely outside this drawing tile, don't process it further - if (!rect.intersects(dirtyRect)) - return; + if (!foundMatchingRange) + clearHoveredTelephoneNumberHighlight(); + } - if (!m_currentHighlight || m_currentHighlightIsDirty) { - CGRect cgRect = (CGRect)rect; + // Found out which - if any - telephone number is hovered. + if (!m_hoveredTelephoneNumberData) { + Boolean onButton; + establishHoveredTelephoneHighlight(onButton); + } - 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 @@ void ServicesOverlayController::drawCurrentHighlight(WebCore::GraphicsContext& g 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(m_telephoneNumberHighlights[i], m_currentTelephoneNumberRanges[i]); + + m_servicesOverlay->setNeedsDisplay(); + return; + } + + clearHoveredTelephoneNumberHighlight(); + onButton = false; +} + +void ServicesOverlayController::maybeCreateSelectionHighlight() +{ + ASSERT(!m_selectionHighlight); + ASSERT(m_servicesOverlay); + + Vector 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 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 @@ bool ServicesOverlayController::mouseEvent(PageOverlay*, const WebMouseEvent& ev 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 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 -- 2.36.0