1/*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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.
24 */
25
26#include "config.h"
27#include "WKBundlePageOverlay.h"
28
29#include "APIClient.h"
30#include "InjectedBundleRangeHandle.h"
31#include "WKAPICast.h"
32#include "WKArray.h"
33#include "WKBundleAPICast.h"
34#include "WKNumber.h"
35#include "WKRetainPtr.h"
36#include "WKSharedAPICast.h"
37#include "WKStringPrivate.h"
38#include "WebPage.h"
39#include "WebPageOverlay.h"
40#include <WebCore/GraphicsContext.h>
41#include <WebCore/PageOverlay.h>
42#include <WebCore/PlatformMouseEvent.h>
43
44namespace API {
45
46template<> struct ClientTraits<WKBundlePageOverlayClientBase> {
47 typedef std::tuple<WKBundlePageOverlayClientV0, WKBundlePageOverlayClientV1> Versions;
48};
49
50template<> struct ClientTraits<WKBundlePageOverlayAccessibilityClientBase> {
51 typedef std::tuple<WKBundlePageOverlayAccessibilityClientV0> Versions;
52};
53
54}
55
56class PageOverlayClientImpl : API::Client<WKBundlePageOverlayClientBase>, public WebKit::WebPageOverlay::Client {
57public:
58 explicit PageOverlayClientImpl(WKBundlePageOverlayClientBase* client)
59 {
60 initialize(client);
61 }
62
63 virtual void setAccessibilityClient(WKBundlePageOverlayAccessibilityClientBase* client)
64 {
65 m_accessibilityClient.initialize(client);
66 }
67
68private:
69 // WebKit::WebPageOverlay::Client.
70 void willMoveToPage(WebKit::WebPageOverlay& pageOverlay, WebKit::WebPage* page) override
71 {
72 if (!m_client.willMoveToPage)
73 return;
74
75 m_client.willMoveToPage(toAPI(&pageOverlay), toAPI(page), m_client.base.clientInfo);
76 }
77
78 void didMoveToPage(WebKit::WebPageOverlay& pageOverlay, WebKit::WebPage* page) override
79 {
80 if (!m_client.didMoveToPage)
81 return;
82
83 m_client.didMoveToPage(toAPI(&pageOverlay), toAPI(page), m_client.base.clientInfo);
84 }
85
86 void drawRect(WebKit::WebPageOverlay& pageOverlay, WebCore::GraphicsContext& graphicsContext, const WebCore::IntRect& dirtyRect) override
87 {
88 if (!m_client.drawRect)
89 return;
90
91 m_client.drawRect(toAPI(&pageOverlay), graphicsContext.platformContext(), WebKit::toAPI(dirtyRect), m_client.base.clientInfo);
92 }
93
94 bool mouseEvent(WebKit::WebPageOverlay& pageOverlay, const WebCore::PlatformMouseEvent& event) override
95 {
96 switch (event.type()) {
97 case WebCore::PlatformMouseEvent::Type::MousePressed: {
98 if (!m_client.mouseDown)
99 return false;
100
101 return m_client.mouseDown(toAPI(&pageOverlay), WebKit::toAPI(event.position()), WebKit::toAPI(event.button()), m_client.base.clientInfo);
102 }
103 case WebCore::PlatformMouseEvent::Type::MouseReleased: {
104 if (!m_client.mouseUp)
105 return false;
106
107 return m_client.mouseUp(toAPI(&pageOverlay), WebKit::toAPI(event.position()), WebKit::toAPI(event.button()), m_client.base.clientInfo);
108 }
109 case WebCore::PlatformMouseEvent::Type::MouseMoved: {
110 if (event.button() == WebCore::MouseButton::NoButton) {
111 if (!m_client.mouseMoved)
112 return false;
113
114 return m_client.mouseMoved(toAPI(&pageOverlay), WebKit::toAPI(event.position()), m_client.base.clientInfo);
115 }
116
117 // This is a MouseMove event with a mouse button pressed. Call mouseDragged.
118 if (!m_client.mouseDragged)
119 return false;
120
121 return m_client.mouseDragged(toAPI(&pageOverlay), WebKit::toAPI(event.position()), WebKit::toAPI(event.button()), m_client.base.clientInfo);
122 }
123
124 default:
125 return false;
126 }
127 }
128
129#if PLATFORM(MAC)
130 DDActionContext *actionContextForResultAtPoint(WebKit::WebPageOverlay& pageOverlay, WebCore::FloatPoint location, RefPtr<WebCore::Range>& rangeHandle) override
131 {
132 if (m_client.actionContextForResultAtPoint) {
133 WKBundleRangeHandleRef apiRange = nullptr;
134 DDActionContext *actionContext = (DDActionContext *)m_client.actionContextForResultAtPoint(toAPI(&pageOverlay), WKPointMake(location.x(), location.y()), &apiRange, m_client.base.clientInfo);
135
136 if (apiRange)
137 rangeHandle = &WebKit::toImpl(apiRange)->coreRange();
138
139 return actionContext;
140 }
141
142 return nil;
143 }
144
145 void dataDetectorsDidPresentUI(WebKit::WebPageOverlay& pageOverlay) override
146 {
147 if (!m_client.dataDetectorsDidPresentUI)
148 return;
149
150 m_client.dataDetectorsDidPresentUI(toAPI(&pageOverlay), m_client.base.clientInfo);
151 }
152
153 void dataDetectorsDidChangeUI(WebKit::WebPageOverlay& pageOverlay) override
154 {
155 if (!m_client.dataDetectorsDidChangeUI)
156 return;
157
158 m_client.dataDetectorsDidChangeUI(toAPI(&pageOverlay), m_client.base.clientInfo);
159 }
160
161 void dataDetectorsDidHideUI(WebKit::WebPageOverlay& pageOverlay) override
162 {
163 if (!m_client.dataDetectorsDidHideUI)
164 return;
165
166 m_client.dataDetectorsDidHideUI(toAPI(&pageOverlay), m_client.base.clientInfo);
167 }
168#endif // PLATFORM(MAC)
169
170 bool copyAccessibilityAttributeStringValueForPoint(WebKit::WebPageOverlay& pageOverlay, String attribute, WebCore::FloatPoint parameter, String& value) override
171 {
172 if (!m_accessibilityClient.client().copyAccessibilityAttributeValue)
173 return false;
174 auto wkType = m_accessibilityClient.client().copyAccessibilityAttributeValue(toAPI(&pageOverlay), WebKit::toCopiedAPI(attribute), WKPointCreate(WKPointMake(parameter.x(), parameter.y())), m_accessibilityClient.client().base.clientInfo);
175 if (WebKit::toImpl(wkType)->type() != API::String::APIType)
176 return false;
177 value = WebKit::toWTFString(static_cast<WKStringRef>(wkType));
178 return true;
179 }
180
181 bool copyAccessibilityAttributeBoolValueForPoint(WebKit::WebPageOverlay& pageOverlay, String attribute, WebCore::FloatPoint parameter, bool& value) override
182 {
183 if (!m_accessibilityClient.client().copyAccessibilityAttributeValue)
184 return false;
185 auto wkType = m_accessibilityClient.client().copyAccessibilityAttributeValue(toAPI(&pageOverlay), WebKit::toCopiedAPI(attribute), WKPointCreate(WKPointMake(parameter.x(), parameter.y())), m_accessibilityClient.client().base.clientInfo);
186 if (WebKit::toImpl(wkType)->type() != API::Boolean::APIType)
187 return false;
188 value = WKBooleanGetValue(static_cast<WKBooleanRef>(wkType));
189 return true;
190 }
191
192 Vector<String> copyAccessibilityAttributeNames(WebKit::WebPageOverlay& pageOverlay, bool paramerizedNames) override
193 {
194 Vector<String> names;
195 if (!m_accessibilityClient.client().copyAccessibilityAttributeNames)
196 return names;
197 auto wkNames = m_accessibilityClient.client().copyAccessibilityAttributeNames(toAPI(&pageOverlay), paramerizedNames, m_accessibilityClient.client().base.clientInfo);
198
199 size_t count = WKArrayGetSize(wkNames);
200 for (size_t k = 0; k < count; k++) {
201 WKTypeRef item = WKArrayGetItemAtIndex(wkNames, k);
202 if (WebKit::toImpl(item)->type() == API::String::APIType)
203 names.append(WebKit::toWTFString(static_cast<WKStringRef>(item)));
204 }
205
206 return names;
207 }
208
209 API::Client<WKBundlePageOverlayAccessibilityClientBase> m_accessibilityClient;
210};
211
212WKTypeID WKBundlePageOverlayGetTypeID()
213{
214 return WebKit::toAPI(WebKit::WebPageOverlay::APIType);
215}
216
217WKBundlePageOverlayRef WKBundlePageOverlayCreate(WKBundlePageOverlayClientBase* wkClient)
218{
219 auto clientImpl = std::make_unique<PageOverlayClientImpl>(wkClient);
220 return toAPI(&WebKit::WebPageOverlay::create(WTFMove(clientImpl)).leakRef());
221}
222
223void WKBundlePageOverlaySetAccessibilityClient(WKBundlePageOverlayRef bundlePageOverlayRef, WKBundlePageOverlayAccessibilityClientBase* client)
224{
225 static_cast<PageOverlayClientImpl&>(WebKit::toImpl(bundlePageOverlayRef)->client()).setAccessibilityClient(client);
226}
227
228void WKBundlePageOverlaySetNeedsDisplay(WKBundlePageOverlayRef bundlePageOverlayRef, WKRect rect)
229{
230 WebKit::toImpl(bundlePageOverlayRef)->setNeedsDisplay(enclosingIntRect(WebKit::toFloatRect(rect)));
231}
232
233float WKBundlePageOverlayFractionFadedIn(WKBundlePageOverlayRef)
234{
235 // Clients who include the fade opacity during painting interfere
236 // with composited fade, so we'll pretend we're opaque and do the
237 // fade on our own.
238
239 return 1;
240}
241
242void WKBundlePageOverlayClear(WKBundlePageOverlayRef bundlePageOverlayRef)
243{
244 WebKit::toImpl(bundlePageOverlayRef)->clear();
245}
246