OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 #include "config.h" |
| 5 #include "core/dom/EventHandlerRegistry.h" |
| 6 |
| 7 #include "core/dom/Document.h" |
| 8 #include "core/events/ThreadLocalEventNames.h" |
| 9 #include "core/events/WheelEvent.h" |
| 10 #include "core/frame/FrameHost.h" |
| 11 #include "core/frame/LocalFrame.h" |
| 12 #include "core/page/Chrome.h" |
| 13 #include "core/page/ChromeClient.h" |
| 14 #include "core/page/Page.h" |
| 15 #include "core/page/scrolling/ScrollingCoordinator.h" |
| 16 |
| 17 namespace WebCore { |
| 18 |
| 19 EventHandlerRegistry::EventHandlerRegistry(Document& document) |
| 20 : DOMWindowLifecycleObserver(document.domWindow()) |
| 21 , m_scrollEventHandlerCount(0) |
| 22 , m_wheelEventHandlerCount(0) |
| 23 { |
| 24 } |
| 25 |
| 26 EventHandlerRegistry::~EventHandlerRegistry() |
| 27 { |
| 28 } |
| 29 |
| 30 const char* EventHandlerRegistry::supplementName() |
| 31 { |
| 32 return "EventHandlerRegistry"; |
| 33 } |
| 34 |
| 35 EventHandlerRegistry* EventHandlerRegistry::from(Document& document) |
| 36 { |
| 37 EventHandlerRegistry* controller = static_cast<EventHandlerRegistry*>(Docume
ntSupplement::from(document, supplementName())); |
| 38 if (!controller) { |
| 39 controller = new EventHandlerRegistry(document); |
| 40 DocumentSupplement::provideTo(document, supplementName(), adoptPtr(contr
oller)); |
| 41 } |
| 42 return controller; |
| 43 } |
| 44 |
| 45 void EventHandlerRegistry::didChangeWheelEventHandlerCount(Document& document, i
nt delta) |
| 46 { |
| 47 if (delta < 0) |
| 48 ASSERT(m_wheelEventHandlerCount > 0); |
| 49 m_wheelEventHandlerCount += delta; |
| 50 |
| 51 Page* page = document.page(); |
| 52 if (!page) |
| 53 return; |
| 54 |
| 55 LocalFrame* mainFrame = page->mainFrame(); |
| 56 if (mainFrame) |
| 57 mainFrame->notifyChromeClientWheelEventHandlerCountChanged(); |
| 58 |
| 59 ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator(); |
| 60 if (!scrollingCoordinator) |
| 61 return; |
| 62 |
| 63 FrameView* frameView = document.view(); |
| 64 if (!frameView) |
| 65 return; |
| 66 |
| 67 scrollingCoordinator->frameViewWheelEventHandlerCountChanged(frameView); |
| 68 } |
| 69 |
| 70 void EventHandlerRegistry::didChangeScrollEventHandlerCount(Document& document,
int delta) |
| 71 { |
| 72 if (delta < 0) |
| 73 ASSERT(m_scrollEventHandlerCount > 0); |
| 74 m_scrollEventHandlerCount += delta; |
| 75 |
| 76 Page* page = document.page(); |
| 77 if (!page) |
| 78 return; |
| 79 |
| 80 ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator(); |
| 81 if (!scrollingCoordinator) |
| 82 return; |
| 83 |
| 84 FrameView* frameView = document.view(); |
| 85 if (!frameView) |
| 86 return; |
| 87 |
| 88 scrollingCoordinator->frameViewScrollEventHandlerCountChanged(frameView); |
| 89 } |
| 90 |
| 91 static void notifyTouchRectsChanged(Document& document) |
| 92 { |
| 93 Page* page = document.page(); |
| 94 if (!page) |
| 95 return; |
| 96 |
| 97 ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator(); |
| 98 if (!scrollingCoordinator) |
| 99 return; |
| 100 |
| 101 scrollingCoordinator->touchEventTargetRectsDidChange(); |
| 102 } |
| 103 |
| 104 void EventHandlerRegistry::didAddTouchEventHandler(Document& document, Node& han
dler) |
| 105 { |
| 106 // The node should either be in the document, or be the Document node of a c
hild |
| 107 // of the document. |
| 108 ASSERT(&handler.document() == &document |
| 109 || (handler.isDocumentNode() && toDocument(&handler)->parentDocument() =
= &document)); |
| 110 |
| 111 if (!m_touchEventTargets.get()) |
| 112 m_touchEventTargets = adoptPtr(new TouchEventTargetSet); |
| 113 bool isFirstHandler = m_touchEventTargets->isEmpty(); |
| 114 |
| 115 if (!m_touchEventTargets->add(&handler).isNewEntry) { |
| 116 // Just incremented refcount, no real change. |
| 117 // If this is a child document node, then the count should never go abov
e 1. |
| 118 ASSERT(!handler.isDocumentNode() || &handler->document() == &document); |
| 119 return; |
| 120 } |
| 121 |
| 122 if (isFirstHandler) { |
| 123 if (Document* parent = document.parentDocument()) { |
| 124 didAddTouchEventHandler(*parent, document); |
| 125 } else { |
| 126 // This is the first touch handler on the whole page. |
| 127 if (FrameHost* frameHost = document.frameHost()) |
| 128 frameHost->chrome().client().needTouchEvents(true); |
| 129 } |
| 130 } |
| 131 |
| 132 // When we're all done with all frames, ensure touch hit rects are marked as
dirty. |
| 133 if (!handler.isDocumentNode() || &handler == &document) |
| 134 notifyTouchRectsChanged(document); |
| 135 } |
| 136 |
| 137 void EventHandlerRegistry::didRemoveTouchEventHandler(Document& document, Node&
handler, bool clearAll) |
| 138 { |
| 139 // Note that we can't assert that |handler| is in this document because it m
ight be in |
| 140 // the process of moving out of it. |
| 141 ASSERT(clearAll || m_touchEventTargets->contains(&handler)); |
| 142 if (!m_touchEventTargets.get()) |
| 143 return; |
| 144 |
| 145 if (clearAll) { |
| 146 if (!m_touchEventTargets->contains(&handler)) |
| 147 return; |
| 148 m_touchEventTargets->removeAll(&handler); |
| 149 } else { |
| 150 if (!m_touchEventTargets->remove(&handler)) { |
| 151 // Just decremented refcount, no real update. |
| 152 return; |
| 153 } |
| 154 } |
| 155 |
| 156 if (m_touchEventTargets->isEmpty()) { |
| 157 if (Document* parent = document.parentDocument()) { |
| 158 // This was the last handler in the document, update the parent docu
ment too. |
| 159 didRemoveTouchEventHandler(*parent, document, clearAll); |
| 160 } else { |
| 161 // We just removed the last touch handler on the whole page. |
| 162 if (FrameHost* frameHost = document.frameHost()) |
| 163 frameHost->chrome().client().needTouchEvents(false); |
| 164 } |
| 165 } |
| 166 |
| 167 // When we're all done with all frames, ensure touch hit rects are marked as
dirty. |
| 168 if (!handler.isDocumentNode() || &handler == &document) |
| 169 notifyTouchRectsChanged(document); |
| 170 } |
| 171 |
| 172 void EventHandlerRegistry::didAddEventHandler(Document& document, const AtomicSt
ring& eventType, Node* targetNode) |
| 173 { |
| 174 if (eventType == EventTypeNames::wheel || eventType == EventTypeNames::mouse
wheel) |
| 175 didChangeWheelEventHandlerCount(document, 1); |
| 176 else if (eventType == EventTypeNames::scroll) |
| 177 didChangeScrollEventHandlerCount(document, 1); |
| 178 else if (isTouchEventType(eventType)) |
| 179 didAddTouchEventHandler(document, *targetNode); |
| 180 } |
| 181 |
| 182 void EventHandlerRegistry::didRemoveEventHandler(Document& document, const Atomi
cString& eventType, Node* targetNode) |
| 183 { |
| 184 if (eventType == EventTypeNames::wheel || eventType == EventTypeNames::mouse
wheel) |
| 185 didChangeWheelEventHandlerCount(document, -1); |
| 186 else if (eventType == EventTypeNames::scroll) |
| 187 didChangeScrollEventHandlerCount(document, -1); |
| 188 else if (isTouchEventType(eventType)) |
| 189 didRemoveTouchEventHandler(document, *targetNode, false); |
| 190 } |
| 191 |
| 192 void EventHandlerRegistry::didAddEventListener(DOMWindow* window, const AtomicSt
ring& eventType) |
| 193 { |
| 194 didAddEventHandler(*window->document(), eventType, window->document()); |
| 195 } |
| 196 |
| 197 void EventHandlerRegistry::didRemoveEventListener(DOMWindow* window, const Atomi
cString& eventType) |
| 198 { |
| 199 didRemoveEventHandler(*window->document(), eventType, window->document()); |
| 200 } |
| 201 |
| 202 void EventHandlerRegistry::didMoveNodeToNewDocument(Node& targetNode, Document&
oldDocument) |
| 203 { |
| 204 didChangeAllEventHandlers(targetNode, oldDocument, Removed); |
| 205 didChangeAllEventHandlers(targetNode, targetNode.document(), Added); |
| 206 } |
| 207 |
| 208 void EventHandlerRegistry::didRemoveAllEventHandlers(Node& targetNode) |
| 209 { |
| 210 didChangeAllEventHandlers(targetNode, targetNode.document(), RemovedAll); |
| 211 } |
| 212 |
| 213 void EventHandlerRegistry::didChangeAllEventHandlers(Node& targetNode, Document&
document, ChangeOperation op) |
| 214 { |
| 215 if (!targetNode.hasEventListeners()) |
| 216 return; |
| 217 EventHandlerRegistry* registry = EventHandlerRegistry::from(document); |
| 218 int wheelHandlerCount = targetNode.getEventListeners(EventTypeNames::wheel).
size() + |
| 219 targetNode.getEventListeners(EventTypeNames::mousewheel).size(); |
| 220 registry->didChangeWheelEventHandlerCount( |
| 221 document, (op == Added) ? wheelHandlerCount : -wheelHandlerCount); |
| 222 |
| 223 int scrollHandlerCount = targetNode.getEventListeners(EventTypeNames::scroll
).size(); |
| 224 registry->didChangeScrollEventHandlerCount( |
| 225 document, (op == Added) ? scrollHandlerCount : -scrollHandlerCount); |
| 226 |
| 227 const Vector<AtomicString> eventTypes = targetNode.eventTypes(); |
| 228 for (size_t i = 0; i < eventTypes.size(); ++i) { |
| 229 if (!isTouchEventType(eventTypes[i])) |
| 230 continue; |
| 231 const EventListenerVector& eventListeners = |
| 232 targetNode.getEventListeners(eventTypes[i]); |
| 233 for (size_t j = 0; j < eventListeners.size(); ++j) { |
| 234 if (op == Added) |
| 235 registry->didAddTouchEventHandler(document, targetNode); |
| 236 else |
| 237 registry->didRemoveTouchEventHandler(document, targetNode, op ==
RemovedAll); |
| 238 } |
| 239 } |
| 240 } |
| 241 |
| 242 } // namespace WebCore |
OLD | NEW |