blob: e0cd8082ad84a471f25e2c8b2172f6ca32dc76a1 [file] [log] [blame]
/*
* Copyright (C) 2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "MultiGamepadProvider.h"
#if ENABLE(GAMEPAD) && HAVE(MULTIGAMEPADPROVIDER_SUPPORT)
#import "GameControllerGamepadProvider.h"
#import "HIDGamepadProvider.h"
#import "Logging.h"
#import "PlatformGamepad.h"
#import <wtf/NeverDestroyed.h>
namespace WebCore {
static size_t numberOfGamepadProviders = 2;
MultiGamepadProvider& MultiGamepadProvider::singleton()
{
static NeverDestroyed<MultiGamepadProvider> sharedProvider;
return sharedProvider;
}
void MultiGamepadProvider::startMonitoringGamepads(GamepadProviderClient& client)
{
bool monitorOtherProviders = m_clients.isEmpty();
ASSERT(!m_clients.contains(&client));
m_clients.add(&client);
if (!m_usesOnlyHIDProvider) {
HIDGamepadProvider::singleton().ignoreGameControllerFrameworkDevices();
GameControllerGamepadProvider::singleton().prewarmGameControllerDevicesIfNecessary();
}
if (monitorOtherProviders) {
HIDGamepadProvider::singleton().startMonitoringGamepads(*this);
if (!m_usesOnlyHIDProvider)
GameControllerGamepadProvider::singleton().startMonitoringGamepads(*this);
}
}
void MultiGamepadProvider::stopMonitoringGamepads(GamepadProviderClient& client)
{
ASSERT(m_clients.contains(&client));
bool shouldStopMonitoringOtherProviders = m_clients.remove(&client) && m_clients.isEmpty();
if (shouldStopMonitoringOtherProviders) {
HIDGamepadProvider::singleton().stopMonitoringGamepads(*this);
if (!m_usesOnlyHIDProvider)
GameControllerGamepadProvider::singleton().stopMonitoringGamepads(*this);
}
}
unsigned MultiGamepadProvider::indexForNewlyConnectedDevice()
{
unsigned index = 0;
while (index < m_gamepadVector.size() && m_gamepadVector[index])
++index;
ASSERT(index <= m_gamepadVector.size());
if (index == m_gamepadVector.size())
m_gamepadVector.resize(index + 1);
return index;
}
void MultiGamepadProvider::platformGamepadConnected(PlatformGamepad& gamepad, EventMakesGamepadsVisible eventVisibility)
{
auto index = indexForNewlyConnectedDevice();
LOG(Gamepad, "MultiGamepadProvider adding new platform gamepad to index %i from a %s source", index, gamepad.source());
ASSERT(m_gamepadVector.size() > index);
auto addResult = m_gamepadMap.set(&gamepad, WTF::makeUnique<PlatformGamepadWrapper>(index, &gamepad));
ASSERT(addResult.isNewEntry);
m_gamepadVector[index] = addResult.iterator->value.get();
for (auto& client : m_clients)
client->platformGamepadConnected(*m_gamepadVector[index], eventVisibility);
}
void MultiGamepadProvider::platformGamepadDisconnected(PlatformGamepad& gamepad)
{
LOG(Gamepad, "MultiGamepadProvider disconnecting gamepad from a %s source", gamepad.source());
auto gamepadWrapper = m_gamepadMap.take(&gamepad);
ASSERT(gamepadWrapper);
ASSERT(gamepadWrapper->index() < m_gamepadVector.size());
ASSERT(m_gamepadVector[gamepadWrapper->index()] == gamepadWrapper.get());
m_gamepadVector[gamepadWrapper->index()] = nullptr;
for (auto& client : m_clients)
client->platformGamepadDisconnected(*gamepadWrapper);
}
void MultiGamepadProvider::platformGamepadInputActivity(EventMakesGamepadsVisible eventVisibility)
{
if (eventVisibility == EventMakesGamepadsVisible::Yes)
GameControllerGamepadProvider::singleton().makeInvisibleGamepadsVisible();
for (auto& client : m_clients)
client->platformGamepadInputActivity(eventVisibility);
}
} // namespace WebCore
#endif // ENABLE(GAMEPAD) && HAVE(MULTIGAMEPADPROVIDER_SUPPORT)