1/*
2 * Copyright (C) 2016 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 "WebGamepadProvider.h"
28
29#if ENABLE(GAMEPAD)
30
31#include "GamepadData.h"
32#include "WebGamepad.h"
33#include "WebProcess.h"
34#include "WebProcessPoolMessages.h"
35#include <WebCore/GamepadProviderClient.h>
36#include <wtf/NeverDestroyed.h>
37
38namespace WebKit {
39using namespace WebCore;
40
41WebGamepadProvider& WebGamepadProvider::singleton()
42{
43 static NeverDestroyed<WebGamepadProvider> provider;
44 return provider;
45}
46
47WebGamepadProvider::WebGamepadProvider()
48{
49}
50
51WebGamepadProvider::~WebGamepadProvider()
52{
53}
54
55void WebGamepadProvider::setInitialGamepads(const Vector<GamepadData>& gamepadDatas)
56{
57 ASSERT(m_gamepads.isEmpty());
58
59 m_gamepads.resize(gamepadDatas.size());
60 m_rawGamepads.resize(gamepadDatas.size());
61 for (size_t i = 0; i < gamepadDatas.size(); ++i) {
62 if (gamepadDatas[i].isNull())
63 continue;
64
65 m_gamepads[i] = std::make_unique<WebGamepad>(gamepadDatas[i]);
66 m_rawGamepads[i] = m_gamepads[i].get();
67 }
68}
69
70void WebGamepadProvider::gamepadConnected(const GamepadData& gamepadData)
71{
72 if (m_gamepads.size() <= gamepadData.index()) {
73 m_gamepads.resize(gamepadData.index() + 1);
74 m_rawGamepads.resize(gamepadData.index() + 1);
75 }
76
77 ASSERT(!m_gamepads[gamepadData.index()]);
78
79 m_gamepads[gamepadData.index()] = std::make_unique<WebGamepad>(gamepadData);
80 m_rawGamepads[gamepadData.index()] = m_gamepads[gamepadData.index()].get();
81
82 for (auto* client : m_clients)
83 client->platformGamepadConnected(*m_gamepads[gamepadData.index()]);
84}
85
86void WebGamepadProvider::gamepadDisconnected(unsigned index)
87{
88 ASSERT(m_gamepads.size() > index);
89
90 std::unique_ptr<WebGamepad> disconnectedGamepad = WTFMove(m_gamepads[index]);
91 m_rawGamepads[index] = nullptr;
92
93 for (auto* client : m_clients)
94 client->platformGamepadDisconnected(*disconnectedGamepad);
95}
96
97void WebGamepadProvider::gamepadActivity(const Vector<GamepadData>& gamepadDatas, bool shouldMakeGamepadsVisible)
98{
99 ASSERT(m_gamepads.size() == gamepadDatas.size());
100
101 for (size_t i = 0; i < m_gamepads.size(); ++i) {
102 if (m_gamepads[i])
103 m_gamepads[i]->updateValues(gamepadDatas[i]);
104 }
105
106 for (auto* client : m_clients)
107 client->platformGamepadInputActivity(shouldMakeGamepadsVisible);
108}
109
110void WebGamepadProvider::startMonitoringGamepads(GamepadProviderClient& client)
111{
112 bool processHadGamepadClients = !m_clients.isEmpty();
113
114 ASSERT(!m_clients.contains(&client));
115 m_clients.add(&client);
116
117 if (!processHadGamepadClients)
118 WebProcess::singleton().send(Messages::WebProcessPool::StartedUsingGamepads(), 0);
119}
120
121void WebGamepadProvider::stopMonitoringGamepads(GamepadProviderClient& client)
122{
123 bool processHadGamepadClients = !m_clients.isEmpty();
124
125 ASSERT(m_clients.contains(&client));
126 m_clients.remove(&client);
127
128 if (processHadGamepadClients && m_clients.isEmpty())
129 WebProcess::singleton().send(Messages::WebProcessPool::StoppedUsingGamepads(), 0);
130}
131
132const Vector<PlatformGamepad*>& WebGamepadProvider::platformGamepads()
133{
134 return m_rawGamepads;
135}
136
137}
138
139#endif // ENABLE(GAMEPAD)
140