Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: Source/modules/gamepad/NavigatorGamepad.cpp

Issue 306363002: Gamepad: honor page visibility (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: just a comment that it will be better with Oilpan Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/modules/gamepad/NavigatorGamepad.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 18 matching lines...) Expand all
29 #include "RuntimeEnabledFeatures.h" 29 #include "RuntimeEnabledFeatures.h"
30 #include "core/dom/Document.h" 30 #include "core/dom/Document.h"
31 #include "core/frame/DOMWindow.h" 31 #include "core/frame/DOMWindow.h"
32 #include "core/frame/LocalFrame.h" 32 #include "core/frame/LocalFrame.h"
33 #include "core/frame/Navigator.h" 33 #include "core/frame/Navigator.h"
34 #include "core/page/Page.h" 34 #include "core/page/Page.h"
35 #include "modules/gamepad/GamepadDispatcher.h" 35 #include "modules/gamepad/GamepadDispatcher.h"
36 #include "modules/gamepad/GamepadEvent.h" 36 #include "modules/gamepad/GamepadEvent.h"
37 #include "modules/gamepad/GamepadList.h" 37 #include "modules/gamepad/GamepadList.h"
38 #include "modules/gamepad/WebKitGamepadList.h" 38 #include "modules/gamepad/WebKitGamepadList.h"
39 #include "wtf/TemporaryChange.h"
39 40
40 namespace WebCore { 41 namespace WebCore {
41 42
42 template<typename T> 43 template<typename T>
43 static void sampleGamepad(unsigned index, T& gamepad, const blink::WebGamepad& w ebGamepad) 44 static void sampleGamepad(unsigned index, T& gamepad, const blink::WebGamepad& w ebGamepad)
44 { 45 {
45 gamepad.setId(webGamepad.id); 46 gamepad.setId(webGamepad.id);
46 gamepad.setIndex(index); 47 gamepad.setIndex(index);
47 gamepad.setConnected(webGamepad.connected); 48 gamepad.setConnected(webGamepad.connected);
48 gamepad.setTimestamp(webGamepad.timestamp); 49 gamepad.setTimestamp(webGamepad.timestamp);
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 visitor->trace(m_gamepads); 128 visitor->trace(m_gamepads);
128 visitor->trace(m_webkitGamepads); 129 visitor->trace(m_webkitGamepads);
129 WillBeHeapSupplement<Navigator>::trace(visitor); 130 WillBeHeapSupplement<Navigator>::trace(visitor);
130 } 131 }
131 132
132 void NavigatorGamepad::didConnectOrDisconnectGamepad(unsigned index, const blink ::WebGamepad& webGamepad, bool connected) 133 void NavigatorGamepad::didConnectOrDisconnectGamepad(unsigned index, const blink ::WebGamepad& webGamepad, bool connected)
133 { 134 {
134 ASSERT(index < blink::WebGamepads::itemsLengthCap); 135 ASSERT(index < blink::WebGamepads::itemsLengthCap);
135 ASSERT(connected == webGamepad.connected); 136 ASSERT(connected == webGamepad.connected);
136 137
137 // We should stop listening once we detached.
138 ASSERT(window());
139
140 // 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.
141 if (!m_hasEventListener) 139 if (!m_hasEventListener)
142 return; 140 return;
143 141
144 if (window()->document()->activeDOMObjectsAreStopped() || window()->document ()->activeDOMObjectsAreSuspended())
145 return;
146
147 if (!m_gamepads) 142 if (!m_gamepads)
148 m_gamepads = GamepadList::create(); 143 m_gamepads = GamepadList::create();
149 144
150 Gamepad* gamepad = m_gamepads->item(index); 145 Gamepad* gamepad = m_gamepads->item(index);
151 if (!gamepad) 146 if (!gamepad)
152 gamepad = Gamepad::create(); 147 gamepad = Gamepad::create();
153 sampleGamepad(index, *gamepad, webGamepad); 148 sampleGamepad(index, *gamepad, webGamepad);
154 m_gamepads->set(index, gamepad); 149 m_gamepads->set(index, gamepad);
155 150
156 const AtomicString& eventName = connected ? EventTypeNames::gamepadconnected : EventTypeNames::gamepaddisconnected; 151 const AtomicString& eventName = connected ? EventTypeNames::gamepadconnected : EventTypeNames::gamepaddisconnected;
157 RefPtrWillBeRawPtr<GamepadEvent> event = GamepadEvent::create(eventName, fal se, true, gamepad); 152 dispatchDeviceEvent(GamepadEvent::create(eventName, false, true, gamepad));
158 window()->dispatchEvent(event);
159 } 153 }
160 154
161 NavigatorGamepad::NavigatorGamepad(LocalFrame* frame) 155 NavigatorGamepad::NavigatorGamepad(LocalFrame* frame)
162 : DOMWindowProperty(frame) 156 : DOMWindowProperty(frame)
163 , DeviceSensorEventController(frame ? frame->page() : 0) 157 , DeviceSensorEventController(frame ? frame->page() : 0)
164 , DOMWindowLifecycleObserver(frame ? frame->domWindow() : 0) 158 , DOMWindowLifecycleObserver(frame ? frame->domWindow() : 0)
159 , m_canContinueDispatchingSentinelPtr(0)
165 { 160 {
166 } 161 }
167 162
168 NavigatorGamepad::~NavigatorGamepad() 163 NavigatorGamepad::~NavigatorGamepad()
169 { 164 {
170 } 165 }
171 166
172 const char* NavigatorGamepad::supplementName() 167 const char* NavigatorGamepad::supplementName()
173 { 168 {
174 return "NavigatorGamepad"; 169 return "NavigatorGamepad";
175 } 170 }
176 171
177 void NavigatorGamepad::willDestroyGlobalObjectInFrame() 172 void NavigatorGamepad::willDestroyGlobalObjectInFrame()
178 { 173 {
179 stopUpdating(); 174 stopUpdating();
175 invalidateCanContinueDispatchingSentinel();
180 DOMWindowProperty::willDestroyGlobalObjectInFrame(); 176 DOMWindowProperty::willDestroyGlobalObjectInFrame();
181 } 177 }
182 178
183 void NavigatorGamepad::willDetachGlobalObjectFromFrame() 179 void NavigatorGamepad::willDetachGlobalObjectFromFrame()
184 { 180 {
185 stopUpdating(); 181 stopUpdating();
182 invalidateCanContinueDispatchingSentinel();
186 DOMWindowProperty::willDetachGlobalObjectFromFrame(); 183 DOMWindowProperty::willDetachGlobalObjectFromFrame();
187 } 184 }
188 185
189 void NavigatorGamepad::registerWithDispatcher() 186 void NavigatorGamepad::registerWithDispatcher()
190 { 187 {
191 GamepadDispatcher::instance().addClient(this); 188 GamepadDispatcher::instance().addClient(this);
192 } 189 }
193 190
194 void NavigatorGamepad::unregisterWithDispatcher() 191 void NavigatorGamepad::unregisterWithDispatcher()
195 { 192 {
196 GamepadDispatcher::instance().removeClient(this); 193 GamepadDispatcher::instance().removeClient(this);
197 } 194 }
198 195
199 bool NavigatorGamepad::hasLastData() 196 bool NavigatorGamepad::hasLastData()
200 { 197 {
201 // Gamepad data is polled instead of pushed. 198 // Gamepad data is polled instead of pushed.
202 return false; 199 return false;
203 } 200 }
204 201
205 PassRefPtrWillBeRawPtr<Event> NavigatorGamepad::getLastEvent() 202 PassRefPtrWillBeRawPtr<Event> NavigatorGamepad::getLastEvent()
206 { 203 {
207 // This is called only when hasLastData() is true. 204 // This is called only when hasLastData() is true.
208 ASSERT_NOT_REACHED(); 205 ASSERT_NOT_REACHED();
209 return nullptr; 206 return nullptr;
210 } 207 }
211 208
212 bool NavigatorGamepad::isNullEvent(Event*) 209 bool NavigatorGamepad::isNullEvent(Event*)
213 { 210 {
214 // This is called only when hasLastData() is true.
215 ASSERT_NOT_REACHED();
216 return false; 211 return false;
217 } 212 }
218 213
219 Document* NavigatorGamepad::document() 214 Document* NavigatorGamepad::document()
220 { 215 {
221 return window() ? window()->document() : 0; 216 return window() ? window()->document() : 0;
222 } 217 }
223 218
224 static bool isGamepadEvent(const AtomicString& eventType) 219 static bool isGamepadEvent(const AtomicString& eventType)
225 { 220 {
226 return eventType == EventTypeNames::gamepadconnected || eventType == EventTy peNames::gamepaddisconnected; 221 return eventType == EventTypeNames::gamepadconnected || eventType == EventTy peNames::gamepaddisconnected;
227 } 222 }
228 223
229 void NavigatorGamepad::didAddEventListener(DOMWindow*, const AtomicString& event Type) 224 void NavigatorGamepad::didAddEventListener(DOMWindow*, const AtomicString& event Type)
230 { 225 {
231 if (RuntimeEnabledFeatures::gamepadEnabled() && isGamepadEvent(eventType)) { 226 if (RuntimeEnabledFeatures::gamepadEnabled() && isGamepadEvent(eventType)) {
232 if (page() && page()->visibilityState() == PageVisibilityStateVisible) 227 if (page() && page()->visibilityState() == PageVisibilityStateVisible)
233 startUpdating(); 228 startUpdating();
234 m_hasEventListener = true; 229 m_hasEventListener = true;
235 } 230 }
236 } 231 }
237 232
238 void NavigatorGamepad::didRemoveEventListener(DOMWindow*, const AtomicString& ev entType) 233 void NavigatorGamepad::didRemoveEventListener(DOMWindow* window, const AtomicStr ing& eventType)
239 { 234 {
240 if (isGamepadEvent(eventType)) 235 if (!isGamepadEvent(eventType) || window->hasEventListeners(EventTypeNames:: gamepadconnected) || window->hasEventListeners(EventTypeNames::gamepaddisconnect ed))
241 m_hasEventListener = false; 236 return;
237 m_hasEventListener = false;
242 } 238 }
243 239
244 void NavigatorGamepad::didRemoveAllEventListeners(DOMWindow*) 240 void NavigatorGamepad::didRemoveAllEventListeners(DOMWindow*)
245 { 241 {
246 m_hasEventListener = false; 242 m_hasEventListener = false;
247 } 243 }
248 244
245 void NavigatorGamepad::willBeDestroyed()
246 {
247 invalidateCanContinueDispatchingSentinel();
248 }
249
250 void NavigatorGamepad::pageVisibilityChanged()
251 {
252 DeviceSensorEventController::pageVisibilityChanged();
253
254 if (page()->visibilityState() != PageVisibilityStateVisible || !m_hasEventLi stener)
255 return;
256
257 // Tell the page what has changed. m_gamepads contains the state before we b ecame hidden.
258 // We create a new snapshot and compare them.
259 GamepadList* oldGamepads = m_gamepads.release();
260 gamepads();
261 GamepadList* newGamepads = m_gamepads.get();
262 ASSERT(newGamepads);
263
264 // Set m_gamepads to null so that if we are polled while dispatching it does n't mess up our snapshot.
265 // After we are done, set it back to the new snapshot otherwise we could rep ort these changes multiple
266 // times after we go hidden and then visible again.
267 WTF::TemporaryChange<PersistentWillBeMember<GamepadList> > padsScope(m_gamep ads, nullptr);
268
269 // We need to dispatch multiple events to the page and we have to deal with the fact that we can be destroyed by the event handler.
270 // We use a fancy version of the protecting RefPtr idiom because Supplement' s are not RefCounted. Before we die we change the value
271 // of a local variable via our member pointer. After dispatching the event w e check this local variable which is safe even if we have died.
272 // TODO(b.kelemen): simplify this when we can rely on Oilpan.
273 bool canContinueDispatchingSentinel = true;
274 WTF::TemporaryChange<bool*> sentinelScope(m_canContinueDispatchingSentinelPt r, &canContinueDispatchingSentinel);
275
276 for (unsigned i = 0; i < blink::WebGamepads::itemsLengthCap; ++i) {
277 Gamepad* oldGamepad = oldGamepads ? oldGamepads->item(i) : 0;
278 Gamepad* newGamepad = newGamepads->item(i);
279 bool oldWasConnected = oldGamepad && oldGamepad->connected();
280 bool newIsConnected = newGamepad && newGamepad->connected();
281 bool connectedGamepadChanged = oldWasConnected && newIsConnected && oldG amepad->id() != newGamepad->id();
282
283 if (connectedGamepadChanged || (oldWasConnected && !newIsConnected)) {
284 const AtomicString& eventName = EventTypeNames::gamepaddisconnected;
285 dispatchDeviceEvent(GamepadEvent::create(eventName, false, true, old Gamepad));
286 if (!canContinueDispatchingSentinel || !m_hasEventListener)
287 return;
288 }
289 if (connectedGamepadChanged || (!oldWasConnected && newIsConnected)) {
290 const AtomicString& eventName = EventTypeNames::gamepadconnected;
291 dispatchDeviceEvent(GamepadEvent::create(eventName, false, true, new Gamepad));
292 if (!canContinueDispatchingSentinel || !m_hasEventListener)
293 return;
294 }
295 }
296 }
297
298 void NavigatorGamepad::invalidateCanContinueDispatchingSentinel()
299 {
300 if (m_canContinueDispatchingSentinelPtr)
301 *m_canContinueDispatchingSentinelPtr = false;
302 }
303
249 } // namespace WebCore 304 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/modules/gamepad/NavigatorGamepad.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698