OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011, Google Inc. All rights reserved. | 2 * Copyright (C) 2011, Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are met: | 5 * modification, are permitted provided that the following conditions are met: |
6 * | 6 * |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 startUpdating(); | 119 startUpdating(); |
120 sampleGamepads<Gamepad>(m_gamepads.get()); | 120 sampleGamepads<Gamepad>(m_gamepads.get()); |
121 } | 121 } |
122 return m_gamepads.get(); | 122 return m_gamepads.get(); |
123 } | 123 } |
124 | 124 |
125 void NavigatorGamepad::trace(Visitor* visitor) | 125 void NavigatorGamepad::trace(Visitor* visitor) |
126 { | 126 { |
127 visitor->trace(m_gamepads); | 127 visitor->trace(m_gamepads); |
128 visitor->trace(m_webkitGamepads); | 128 visitor->trace(m_webkitGamepads); |
| 129 visitor->trace(m_pendingEvents); |
129 WillBeHeapSupplement<Navigator>::trace(visitor); | 130 WillBeHeapSupplement<Navigator>::trace(visitor); |
130 } | 131 } |
131 | 132 |
132 void NavigatorGamepad::didUpdateData() | 133 void NavigatorGamepad::didUpdateData() |
133 { | 134 { |
134 // We should stop listening once we detached. | 135 // We should stop listening once we detached. |
135 ASSERT(window()); | 136 ASSERT(window()); |
136 | 137 |
137 // We register to the dispatcher before sampling gamepads so we need to chec
k if we actually have an event listener. | 138 // We register to the dispatcher before sampling gamepads so we need to chec
k if we actually have an event listener. |
138 if (!m_hasEventListener) | 139 if (!m_hasEventListener) |
139 return; | 140 return; |
140 | 141 |
141 if (window()->document()->activeDOMObjectsAreStopped() || window()->document
()->activeDOMObjectsAreSuspended()) | 142 if (window()->document()->activeDOMObjectsAreStopped() || window()->document
()->activeDOMObjectsAreSuspended()) |
142 return; | 143 return; |
143 | 144 |
144 const GamepadDispatcher::ConnectionChange& change = GamepadDispatcher::insta
nce().latestConnectionChange(); | 145 const GamepadDispatcher::ConnectionChange& change = GamepadDispatcher::insta
nce().latestConnectionChange(); |
145 | 146 |
146 if (!m_gamepads) | 147 if (!m_gamepads) |
147 m_gamepads = GamepadList::create(); | 148 m_gamepads = GamepadList::create(); |
148 | 149 |
149 Gamepad* gamepad = m_gamepads->item(change.index); | 150 Gamepad* gamepad = m_gamepads->item(change.index); |
150 if (!gamepad) | 151 if (!gamepad) |
151 gamepad = Gamepad::create(); | 152 gamepad = Gamepad::create(); |
152 sampleGamepad(change.index, *gamepad, change.pad); | 153 sampleGamepad(change.index, *gamepad, change.pad); |
153 m_gamepads->set(change.index, gamepad); | 154 m_gamepads->set(change.index, gamepad); |
154 | 155 |
155 const AtomicString& eventName = change.pad.connected ? EventTypeNames::gamep
adconnected : EventTypeNames::gamepaddisconnected; | 156 m_pendingEvents.append(gamepad); |
| 157 m_dispatchOneEventRunner.runAsync(); |
| 158 } |
| 159 |
| 160 void NavigatorGamepad::dispatchOneEvent() |
| 161 { |
| 162 ASSERT(window()); |
| 163 ASSERT(!m_pendingEvents.isEmpty()); |
| 164 |
| 165 Gamepad* gamepad = m_pendingEvents.takeFirst(); |
| 166 const AtomicString& eventName = gamepad->connected() ? EventTypeNames::gamep
adconnected : EventTypeNames::gamepaddisconnected; |
156 window()->dispatchEvent(GamepadEvent::create(eventName, false, true, gamepad
)); | 167 window()->dispatchEvent(GamepadEvent::create(eventName, false, true, gamepad
)); |
| 168 |
| 169 if (!m_pendingEvents.isEmpty()) |
| 170 m_dispatchOneEventRunner.runAsync(); |
157 } | 171 } |
158 | 172 |
159 NavigatorGamepad::NavigatorGamepad(LocalFrame* frame) | 173 NavigatorGamepad::NavigatorGamepad(LocalFrame* frame) |
160 : DOMWindowProperty(frame) | 174 : DOMWindowProperty(frame) |
161 , DeviceEventControllerBase(frame ? frame->page() : 0) | 175 , DeviceEventControllerBase(frame ? frame->page() : 0) |
162 , DOMWindowLifecycleObserver(frame ? frame->domWindow() : 0) | 176 , DOMWindowLifecycleObserver(frame ? frame->domWindow() : 0) |
| 177 , m_dispatchOneEventRunner(this, &NavigatorGamepad::dispatchOneEvent) |
163 { | 178 { |
164 } | 179 } |
165 | 180 |
166 NavigatorGamepad::~NavigatorGamepad() | 181 NavigatorGamepad::~NavigatorGamepad() |
167 { | 182 { |
168 } | 183 } |
169 | 184 |
170 const char* NavigatorGamepad::supplementName() | 185 const char* NavigatorGamepad::supplementName() |
171 { | 186 { |
172 return "NavigatorGamepad"; | 187 return "NavigatorGamepad"; |
173 } | 188 } |
174 | 189 |
175 void NavigatorGamepad::willDestroyGlobalObjectInFrame() | 190 void NavigatorGamepad::willDestroyGlobalObjectInFrame() |
176 { | 191 { |
177 stopUpdating(); | 192 stopUpdating(); |
178 DOMWindowProperty::willDestroyGlobalObjectInFrame(); | 193 DOMWindowProperty::willDestroyGlobalObjectInFrame(); |
179 } | 194 } |
180 | 195 |
181 void NavigatorGamepad::willDetachGlobalObjectFromFrame() | 196 void NavigatorGamepad::willDetachGlobalObjectFromFrame() |
182 { | 197 { |
183 stopUpdating(); | 198 stopUpdating(); |
184 DOMWindowProperty::willDetachGlobalObjectFromFrame(); | 199 DOMWindowProperty::willDetachGlobalObjectFromFrame(); |
185 } | 200 } |
186 | 201 |
187 void NavigatorGamepad::registerWithDispatcher() | 202 void NavigatorGamepad::registerWithDispatcher() |
188 { | 203 { |
189 GamepadDispatcher::instance().addController(this); | 204 GamepadDispatcher::instance().addController(this); |
| 205 m_dispatchOneEventRunner.resume(); |
190 } | 206 } |
191 | 207 |
192 void NavigatorGamepad::unregisterWithDispatcher() | 208 void NavigatorGamepad::unregisterWithDispatcher() |
193 { | 209 { |
| 210 m_dispatchOneEventRunner.suspend(); |
194 GamepadDispatcher::instance().removeController(this); | 211 GamepadDispatcher::instance().removeController(this); |
195 } | 212 } |
196 | 213 |
197 bool NavigatorGamepad::hasLastData() | 214 bool NavigatorGamepad::hasLastData() |
198 { | 215 { |
199 // Gamepad data is polled instead of pushed. | 216 // Gamepad data is polled instead of pushed. |
200 return false; | 217 return false; |
201 } | 218 } |
202 | 219 |
203 static bool isGamepadEvent(const AtomicString& eventType) | 220 static bool isGamepadEvent(const AtomicString& eventType) |
204 { | 221 { |
205 return eventType == EventTypeNames::gamepadconnected || eventType == EventTy
peNames::gamepaddisconnected; | 222 return eventType == EventTypeNames::gamepadconnected || eventType == EventTy
peNames::gamepaddisconnected; |
206 } | 223 } |
207 | 224 |
208 void NavigatorGamepad::didAddEventListener(LocalDOMWindow*, const AtomicString&
eventType) | 225 void NavigatorGamepad::didAddEventListener(LocalDOMWindow*, const AtomicString&
eventType) |
209 { | 226 { |
210 if (RuntimeEnabledFeatures::gamepadEnabled() && isGamepadEvent(eventType)) { | 227 if (RuntimeEnabledFeatures::gamepadEnabled() && isGamepadEvent(eventType)) { |
211 if (page() && page()->visibilityState() == PageVisibilityStateVisible) | 228 if (page() && page()->visibilityState() == PageVisibilityStateVisible) |
212 startUpdating(); | 229 startUpdating(); |
213 m_hasEventListener = true; | 230 m_hasEventListener = true; |
214 } | 231 } |
215 } | 232 } |
216 | 233 |
217 void NavigatorGamepad::didRemoveEventListener(LocalDOMWindow* window, const Atom
icString& eventType) | 234 void NavigatorGamepad::didRemoveEventListener(LocalDOMWindow* window, const Atom
icString& eventType) |
218 { | 235 { |
219 if (isGamepadEvent(eventType) | 236 if (isGamepadEvent(eventType) |
220 && !window->hasEventListeners(EventTypeNames::gamepadconnected) | 237 && !window->hasEventListeners(EventTypeNames::gamepadconnected) |
221 && !window->hasEventListeners(EventTypeNames::gamepaddisconnected)) { | 238 && !window->hasEventListeners(EventTypeNames::gamepaddisconnected)) { |
222 m_hasEventListener = false; | 239 didRemoveGamepadEventListeners(); |
223 } | 240 } |
224 } | 241 } |
225 | 242 |
226 void NavigatorGamepad::didRemoveAllEventListeners(LocalDOMWindow*) | 243 void NavigatorGamepad::didRemoveAllEventListeners(LocalDOMWindow*) |
227 { | 244 { |
| 245 didRemoveGamepadEventListeners(); |
| 246 } |
| 247 |
| 248 void NavigatorGamepad::didRemoveGamepadEventListeners() |
| 249 { |
228 m_hasEventListener = false; | 250 m_hasEventListener = false; |
| 251 m_dispatchOneEventRunner.stop(); |
| 252 m_pendingEvents.clear(); |
229 } | 253 } |
230 | 254 |
231 void NavigatorGamepad::pageVisibilityChanged() | 255 void NavigatorGamepad::pageVisibilityChanged() |
232 { | 256 { |
233 // Inform the embedder whether it needs to provide gamepad data for us. | 257 // Inform the embedder whether it needs to provide gamepad data for us. |
234 if (page()->visibilityState() == PageVisibilityStateVisible && (m_hasEventLi
stener || m_gamepads || m_webkitGamepads)) | 258 bool visible = page()->visibilityState() == PageVisibilityStateVisible; |
| 259 if (visible && (m_hasEventListener || m_gamepads || m_webkitGamepads)) |
235 startUpdating(); | 260 startUpdating(); |
236 else | 261 else |
237 stopUpdating(); | 262 stopUpdating(); |
| 263 |
| 264 if (!visible || !m_hasEventListener) |
| 265 return; |
| 266 |
| 267 // Tell the page what has changed. m_gamepads contains the state before we b
ecame hidden. |
| 268 // We create a new snapshot and compare them. |
| 269 GamepadList* oldGamepads = m_gamepads.release(); |
| 270 gamepads(); |
| 271 GamepadList* newGamepads = m_gamepads.get(); |
| 272 ASSERT(newGamepads); |
| 273 |
| 274 for (unsigned i = 0; i < blink::WebGamepads::itemsLengthCap; ++i) { |
| 275 Gamepad* oldGamepad = oldGamepads ? oldGamepads->item(i) : 0; |
| 276 Gamepad* newGamepad = newGamepads->item(i); |
| 277 bool oldWasConnected = oldGamepad && oldGamepad->connected(); |
| 278 bool newIsConnected = newGamepad && newGamepad->connected(); |
| 279 bool connectedGamepadChanged = oldWasConnected && newIsConnected && oldG
amepad->id() != newGamepad->id(); |
| 280 if (connectedGamepadChanged || (oldWasConnected && !newIsConnected)) { |
| 281 oldGamepad->setConnected(false); |
| 282 m_pendingEvents.append(oldGamepad); |
| 283 } |
| 284 if (connectedGamepadChanged || (!oldWasConnected && newIsConnected)) { |
| 285 m_pendingEvents.append(newGamepad); |
| 286 } |
| 287 } |
| 288 |
| 289 if (!m_pendingEvents.isEmpty()) |
| 290 m_dispatchOneEventRunner.runAsync(); |
238 } | 291 } |
239 | 292 |
240 } // namespace WebCore | 293 } // namespace WebCore |
OLD | NEW |