1/* 2 * Copyright (C) 2014 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 "NavigatorGamepad.h" 28 29#if ENABLE(GAMEPAD) 30 31#include "DocumentLoader.h" 32#include "Frame.h" 33#include "Gamepad.h" 34#include "GamepadManager.h" 35#include "GamepadProvider.h" 36#include "Navigator.h" 37#include "PlatformGamepad.h" 38#include <wtf/NeverDestroyed.h> 39#include <wtf/RunLoop.h> 40 41namespace WebCore { 42 43NavigatorGamepad::NavigatorGamepad() 44 : m_navigationStart(std::numeric_limits<double>::infinity()) 45{ 46 GamepadManager::shared().registerNavigator(this); 47} 48 49NavigatorGamepad::~NavigatorGamepad() 50{ 51 GamepadManager::shared().unregisterNavigator(this); 52} 53 54const char* NavigatorGamepad::supplementName() 55{ 56 return "NavigatorGamepad"; 57} 58 59NavigatorGamepad* NavigatorGamepad::from(Navigator* navigator) 60{ 61 NavigatorGamepad* supplement = static_cast<NavigatorGamepad*>(Supplement<Navigator>::from(navigator, supplementName())); 62 if (!supplement) { 63 auto newSupplement = std::make_unique<NavigatorGamepad>(); 64 supplement = newSupplement.get(); 65 provideTo(navigator, supplementName(), WTF::move(newSupplement)); 66 67 if (Frame* frame = navigator->frame()) { 68 if (DocumentLoader* documentLoader = frame->loader().documentLoader()) 69 supplement->m_navigationStart = documentLoader->timing()->navigationStart(); 70 } 71 } 72 return supplement; 73} 74 75Gamepad* NavigatorGamepad::gamepadAtIndex(unsigned index) 76{ 77 if (index >= m_gamepads.size()) 78 return nullptr; 79 return m_gamepads[index].get(); 80} 81 82const Vector<RefPtr<Gamepad>>& NavigatorGamepad::getGamepads(Navigator* navigator) 83{ 84 return NavigatorGamepad::from(navigator)->gamepads(); 85} 86 87const Vector<RefPtr<Gamepad>>& NavigatorGamepad::gamepads() 88{ 89 if (m_gamepads.isEmpty()) 90 return m_gamepads; 91 92 const Vector<PlatformGamepad*>& platformGamepads = GamepadProvider::shared().platformGamepads(); 93 94 for (unsigned i = 0; i < platformGamepads.size(); ++i) { 95 if (!platformGamepads[i]) { 96 ASSERT(!m_gamepads[i]); 97 continue; 98 } 99 100 ASSERT(m_gamepads[i]); 101 m_gamepads[i]->updateFromPlatformGamepad(*platformGamepads[i]); 102 } 103 104 return m_gamepads; 105} 106 107void NavigatorGamepad::gamepadsBecameVisible() 108{ 109 const Vector<PlatformGamepad*>& platformGamepads = GamepadProvider::shared().platformGamepads(); 110 m_gamepads.resize(platformGamepads.size()); 111 112 for (unsigned i = 0; i < platformGamepads.size(); ++i) { 113 if (!platformGamepads[i]) 114 continue; 115 116 m_gamepads[i] = Gamepad::create(*platformGamepads[i]); 117 } 118} 119 120void NavigatorGamepad::gamepadConnected(PlatformGamepad& platformGamepad) 121{ 122 // If this is the first gamepad this Navigator object has seen, then all gamepads just became visible. 123 if (m_gamepads.isEmpty()) { 124 gamepadsBecameVisible(); 125 return; 126 } 127 128 unsigned index = platformGamepad.index(); 129 ASSERT(GamepadProvider::shared().platformGamepads()[index] == &platformGamepad); 130 131 // The new index should already fit in the existing array, or should be exactly one past-the-end of the existing array. 132 ASSERT(index <= m_gamepads.size()); 133 134 if (index < m_gamepads.size()) 135 m_gamepads[index] = Gamepad::create(platformGamepad); 136 else if (index == m_gamepads.size()) 137 m_gamepads.append(Gamepad::create(platformGamepad)); 138} 139 140void NavigatorGamepad::gamepadDisconnected(PlatformGamepad& platformGamepad) 141{ 142 // If this Navigator hasn't seen any gamepads yet its Vector will still be empty. 143 if (!m_gamepads.size()) 144 return; 145 146 ASSERT(platformGamepad.index() < m_gamepads.size()); 147 ASSERT(m_gamepads[platformGamepad.index()]); 148 149 m_gamepads[platformGamepad.index()] = nullptr; 150} 151 152} // namespace WebCore 153 154#endif // ENABLE(GAMEPAD) 155