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 "PageOverlay.h"
31#include "WKAPICast.h"
32#include "WKBundleAPICast.h"
33#include <WebCore/GraphicsContext.h>
34
35namespace API {
36
37template<> struct ClientTraits<WKBundlePageOverlayClientBase> {
38    typedef std::tuple<WKBundlePageOverlayClientV0> Versions;
39};
40
41template<> struct ClientTraits<WKBundlePageOverlayAccessibilityClientBase> {
42    typedef std::tuple<WKBundlePageOverlayAccessibilityClientV0> Versions;
43};
44
45}
46
47using namespace WebCore;
48using namespace WebKit;
49
50class PageOverlayClientImpl : API::Client<WKBundlePageOverlayClientBase>, public PageOverlay::Client {
51public:
52    explicit PageOverlayClientImpl(WKBundlePageOverlayClientBase* client)
53    {
54        initialize(client);
55    }
56
57    virtual void setAccessibilityClient(WKBundlePageOverlayAccessibilityClientBase* client)
58    {
59        m_accessibilityClient.initialize(client);
60    }
61
62private:
63    // PageOverlay::Client.
64    virtual void pageOverlayDestroyed(PageOverlay*)
65    {
66        delete this;
67    }
68
69    virtual void willMoveToWebPage(PageOverlay* pageOverlay, WebPage* page)
70    {
71        if (!m_client.willMoveToPage)
72            return;
73
74        m_client.willMoveToPage(toAPI(pageOverlay), toAPI(page), m_client.base.clientInfo);
75    }
76
77    virtual void didMoveToWebPage(PageOverlay* pageOverlay, WebPage* page)
78    {
79        if (!m_client.didMoveToPage)
80            return;
81
82        m_client.didMoveToPage(toAPI(pageOverlay), toAPI(page), m_client.base.clientInfo);
83    }
84
85    virtual void drawRect(PageOverlay* pageOverlay, GraphicsContext& graphicsContext, const IntRect& dirtyRect)
86    {
87        if (!m_client.drawRect)
88            return;
89
90        m_client.drawRect(toAPI(pageOverlay), graphicsContext.platformContext(), toAPI(dirtyRect), m_client.base.clientInfo);
91    }
92
93    virtual bool mouseEvent(PageOverlay* pageOverlay, const WebMouseEvent& event)
94    {
95        switch (event.type()) {
96        case WebEvent::MouseDown: {
97            if (!m_client.mouseDown)
98                return false;
99
100            return m_client.mouseDown(toAPI(pageOverlay), toAPI(event.position()), toAPI(event.button()), m_client.base.clientInfo);
101        }
102        case WebEvent::MouseUp: {
103            if (!m_client.mouseUp)
104                return false;
105
106            return m_client.mouseUp(toAPI(pageOverlay), toAPI(event.position()), toAPI(event.button()), m_client.base.clientInfo);
107        }
108        case WebEvent::MouseMove: {
109            if (event.button() == WebMouseEvent::NoButton) {
110                if (!m_client.mouseMoved)
111                    return false;
112
113                return m_client.mouseMoved(toAPI(pageOverlay), toAPI(event.position()), m_client.base.clientInfo);
114            }
115
116            // This is a MouseMove event with a mouse button pressed. Call mouseDragged.
117            if (!m_client.mouseDragged)
118                return false;
119
120            return m_client.mouseDragged(toAPI(pageOverlay), toAPI(event.position()), toAPI(event.button()), m_client.base.clientInfo);
121        }
122
123        default:
124            return false;
125        }
126    }
127
128    virtual WKTypeRef copyAccessibilityAttributeValue(PageOverlay* pageOverlay, WKStringRef attribute, WKTypeRef parameter)
129    {
130        if (!m_accessibilityClient.client().copyAccessibilityAttributeValue)
131            return 0;
132        return m_accessibilityClient.client().copyAccessibilityAttributeValue(toAPI(pageOverlay), attribute, parameter, m_accessibilityClient.client().base.clientInfo);
133    }
134
135    virtual WKArrayRef copyAccessibilityAttributeNames(PageOverlay* pageOverlay, bool paramerizedNames)
136    {
137        if (!m_accessibilityClient.client().copyAccessibilityAttributeNames)
138            return 0;
139        return m_accessibilityClient.client().copyAccessibilityAttributeNames(toAPI(pageOverlay), paramerizedNames, m_accessibilityClient.client().base.clientInfo);
140    }
141
142    API::Client<WKBundlePageOverlayAccessibilityClientBase> m_accessibilityClient;
143};
144
145WKTypeID WKBundlePageOverlayGetTypeID()
146{
147    return toAPI(PageOverlay::APIType);
148}
149
150WKBundlePageOverlayRef WKBundlePageOverlayCreate(WKBundlePageOverlayClientBase* wkClient)
151{
152    if (wkClient && wkClient->version)
153        return 0;
154
155    auto clientImpl = std::make_unique<PageOverlayClientImpl>(wkClient);
156
157    // FIXME: Looks like this leaks the clientImpl.
158    return toAPI(PageOverlay::create(clientImpl.release()).leakRef());
159}
160
161void WKBundlePageOverlaySetAccessibilityClient(WKBundlePageOverlayRef bundlePageOverlayRef, WKBundlePageOverlayAccessibilityClientBase* client)
162{
163    if (client && client->version)
164        return;
165    static_cast<PageOverlayClientImpl*>(toImpl(bundlePageOverlayRef)->client())->setAccessibilityClient(client);
166}
167
168void WKBundlePageOverlaySetNeedsDisplay(WKBundlePageOverlayRef bundlePageOverlayRef, WKRect rect)
169{
170    toImpl(bundlePageOverlayRef)->setNeedsDisplay(enclosingIntRect(toFloatRect(rect)));
171}
172
173float WKBundlePageOverlayFractionFadedIn(WKBundlePageOverlayRef)
174{
175    // Clients who include the fade opacity during painting interfere
176    // with composited fade, so we'll pretend we're opaque and do the
177    // fade on our own.
178
179    return 1;
180}
181
182void WKBundlePageOverlayClear(WKBundlePageOverlayRef bundlePageOverlayRef)
183{
184    toImpl(bundlePageOverlayRef)->clear();
185}
186