2 * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
28 #if (ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)) && PLATFORM(MAC)
30 #include "GraphicsLayerClient.h"
31 #include "PageOverlay.h"
34 #include <wtf/MonotonicTime.h>
36 typedef struct __DDHighlight *DDHighlightRef;
45 class ServicesOverlayController : private PageOverlay::Client {
46 WTF_MAKE_FAST_ALLOCATED;
48 explicit ServicesOverlayController(Page&);
49 ~ServicesOverlayController();
51 void selectedTelephoneNumberRangesChanged();
52 void selectionRectsDidChange(const Vector<LayoutRect>&, const Vector<GapRects>&, bool isTextOnly);
55 class Highlight : public RefCounted<Highlight>, private GraphicsLayerClient {
56 WTF_MAKE_NONCOPYABLE(Highlight);
58 static Ref<Highlight> createForSelection(ServicesOverlayController&, RetainPtr<DDHighlightRef>, Ref<Range>&&);
59 static Ref<Highlight> createForTelephoneNumber(ServicesOverlayController&, RetainPtr<DDHighlightRef>, Ref<Range>&&);
64 DDHighlightRef ddHighlight() const { return m_ddHighlight.get(); }
65 Range& range() const { return m_range.get(); }
66 GraphicsLayer* layer() const { return m_graphicsLayer.get(); }
69 TelephoneNumberType = 1 << 0,
70 SelectionType = 1 << 1,
73 Type type() const { return m_type; }
78 void setDDHighlight(DDHighlightRef);
81 Highlight(ServicesOverlayController&, Type, RetainPtr<DDHighlightRef>, Ref<Range>&&);
83 // GraphicsLayerClient
84 void notifyFlushRequired(const GraphicsLayer*) override;
85 void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const FloatRect& inClip, GraphicsLayerPaintBehavior) override;
86 float deviceScaleFactor() const override;
88 void didFinishFadeOutAnimation();
90 RetainPtr<DDHighlightRef> m_ddHighlight;
92 std::unique_ptr<GraphicsLayer> m_graphicsLayer;
94 ServicesOverlayController* m_controller;
97 // PageOverlay::Client
98 void willMoveToPage(PageOverlay&, Page*) override;
99 void didMoveToPage(PageOverlay&, Page*) override;
100 void drawRect(PageOverlay&, GraphicsContext&, const IntRect& dirtyRect) override;
101 bool mouseEvent(PageOverlay&, const PlatformMouseEvent&) override;
102 void didScrollFrame(PageOverlay&, Frame&) override;
104 void createOverlayIfNeeded();
105 void handleClick(const IntPoint&, Highlight&);
107 void drawHighlight(Highlight&, GraphicsContext&);
109 void invalidateHighlightsOfType(Highlight::Type);
110 void buildPotentialHighlightsIfNeeded();
112 void replaceHighlightsOfTypePreservingEquivalentHighlights(HashSet<RefPtr<Highlight>>&, Highlight::Type);
113 void removeAllPotentialHighlightsOfType(Highlight::Type);
114 void buildPhoneNumberHighlights();
115 void buildSelectionHighlight();
117 void determineActiveHighlight(bool& mouseIsOverButton);
118 void clearActiveHighlight();
119 Highlight* activeHighlight() const { return m_activeHighlight.get(); }
121 Highlight* findTelephoneNumberHighlightContainingSelectionHighlight(Highlight&);
123 bool hasRelevantSelectionServices();
125 bool mouseIsOverHighlight(Highlight&, bool& mouseIsOverButton) const;
126 Seconds remainingTimeUntilHighlightShouldBeShown(Highlight*) const;
127 void determineActiveHighlightTimerFired();
129 static bool highlightsAreEquivalent(const Highlight* a, const Highlight* b);
131 Vector<RefPtr<Range>> telephoneNumberRangesForFocusedFrame();
133 void didCreateHighlight(Highlight*);
134 void willDestroyHighlight(Highlight*);
135 void didFinishFadingOutHighlight(Highlight*);
137 Frame& mainFrame() const;
138 Page& page() const { return m_page; }
141 PageOverlay* m_servicesOverlay { nullptr };
143 RefPtr<Highlight> m_activeHighlight;
144 RefPtr<Highlight> m_nextActiveHighlight;
145 HashSet<RefPtr<Highlight>> m_potentialHighlights;
146 HashSet<RefPtr<Highlight>> m_animatingHighlights;
148 HashSet<Highlight*> m_highlights;
150 // FIXME: These should move onto Highlight.
151 Vector<LayoutRect> m_currentSelectionRects;
152 bool m_isTextOnly { false };
154 Highlight::Type m_dirtyHighlightTypes { 0 };
156 MonotonicTime m_lastSelectionChangeTime;
157 MonotonicTime m_nextActiveHighlightChangeTime;
158 MonotonicTime m_lastMouseUpTime;
160 RefPtr<Highlight> m_currentMouseDownOnButtonHighlight;
161 IntPoint m_mousePosition;
163 Timer m_determineActiveHighlightTimer;
164 Timer m_buildHighlightsTimer;
167 } // namespace WebCore
169 #endif // (ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)) && PLATFORM(MAC)