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

Unified Diff: Source/core/dom/EventHandlerRegistry.cpp

Issue 206603002: Add EventHandlerRegistry (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Refactoring WIP. Created 6 years, 9 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 side-by-side diff with in-line comments
Download patch
Index: Source/core/dom/EventHandlerRegistry.cpp
diff --git a/Source/core/dom/EventHandlerRegistry.cpp b/Source/core/dom/EventHandlerRegistry.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9760626631a10fa304862da8c1e805e5fbb80909
--- /dev/null
+++ b/Source/core/dom/EventHandlerRegistry.cpp
@@ -0,0 +1,242 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "config.h"
+#include "core/dom/EventHandlerRegistry.h"
+
+#include "core/dom/Document.h"
+#include "core/events/ThreadLocalEventNames.h"
+#include "core/events/WheelEvent.h"
+#include "core/frame/FrameHost.h"
+#include "core/frame/LocalFrame.h"
+#include "core/page/Chrome.h"
+#include "core/page/ChromeClient.h"
+#include "core/page/Page.h"
+#include "core/page/scrolling/ScrollingCoordinator.h"
+
+namespace WebCore {
+
+EventHandlerRegistry::EventHandlerRegistry(Document& document)
+ : DOMWindowLifecycleObserver(document.domWindow())
+ , m_scrollEventHandlerCount(0)
+ , m_wheelEventHandlerCount(0)
+{
+}
+
+EventHandlerRegistry::~EventHandlerRegistry()
+{
+}
+
+const char* EventHandlerRegistry::supplementName()
+{
+ return "EventHandlerRegistry";
+}
+
+EventHandlerRegistry* EventHandlerRegistry::from(Document& document)
+{
+ EventHandlerRegistry* controller = static_cast<EventHandlerRegistry*>(DocumentSupplement::from(document, supplementName()));
+ if (!controller) {
+ controller = new EventHandlerRegistry(document);
+ DocumentSupplement::provideTo(document, supplementName(), adoptPtr(controller));
+ }
+ return controller;
+}
+
+void EventHandlerRegistry::didChangeWheelEventHandlerCount(Document& document, int delta)
+{
+ if (delta < 0)
+ ASSERT(m_wheelEventHandlerCount > 0);
+ m_wheelEventHandlerCount += delta;
+
+ Page* page = document.page();
+ if (!page)
+ return;
+
+ LocalFrame* mainFrame = page->mainFrame();
+ if (mainFrame)
+ mainFrame->notifyChromeClientWheelEventHandlerCountChanged();
+
+ ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator();
+ if (!scrollingCoordinator)
+ return;
+
+ FrameView* frameView = document.view();
+ if (!frameView)
+ return;
+
+ scrollingCoordinator->frameViewWheelEventHandlerCountChanged(frameView);
+}
+
+void EventHandlerRegistry::didChangeScrollEventHandlerCount(Document& document, int delta)
+{
+ if (delta < 0)
+ ASSERT(m_scrollEventHandlerCount > 0);
+ m_scrollEventHandlerCount += delta;
+
+ Page* page = document.page();
+ if (!page)
+ return;
+
+ ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator();
+ if (!scrollingCoordinator)
+ return;
+
+ FrameView* frameView = document.view();
+ if (!frameView)
+ return;
+
+ scrollingCoordinator->frameViewScrollEventHandlerCountChanged(frameView);
+}
+
+static void notifyTouchRectsChanged(Document& document)
+{
+ Page* page = document.page();
+ if (!page)
+ return;
+
+ ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator();
+ if (!scrollingCoordinator)
+ return;
+
+ scrollingCoordinator->touchEventTargetRectsDidChange();
+}
+
+void EventHandlerRegistry::didAddTouchEventHandler(Document& document, Node& handler)
+{
+ // The node should either be in the document, or be the Document node of a child
+ // of the document.
+ ASSERT(&handler.document() == &document
+ || (handler.isDocumentNode() && toDocument(&handler)->parentDocument() == &document));
+
+ if (!m_touchEventTargets.get())
+ m_touchEventTargets = adoptPtr(new TouchEventTargetSet);
+ bool isFirstHandler = m_touchEventTargets->isEmpty();
+
+ if (!m_touchEventTargets->add(&handler).isNewEntry) {
+ // Just incremented refcount, no real change.
+ // If this is a child document node, then the count should never go above 1.
+ ASSERT(!handler.isDocumentNode() || &handler->document() == &document);
+ return;
+ }
+
+ if (isFirstHandler) {
+ if (Document* parent = document.parentDocument()) {
+ didAddTouchEventHandler(*parent, document);
+ } else {
+ // This is the first touch handler on the whole page.
+ if (FrameHost* frameHost = document.frameHost())
+ frameHost->chrome().client().needTouchEvents(true);
+ }
+ }
+
+ // When we're all done with all frames, ensure touch hit rects are marked as dirty.
+ if (!handler.isDocumentNode() || &handler == &document)
+ notifyTouchRectsChanged(document);
+}
+
+void EventHandlerRegistry::didRemoveTouchEventHandler(Document& document, Node& handler, bool clearAll)
+{
+ // Note that we can't assert that |handler| is in this document because it might be in
+ // the process of moving out of it.
+ ASSERT(clearAll || m_touchEventTargets->contains(&handler));
+ if (!m_touchEventTargets.get())
+ return;
+
+ if (clearAll) {
+ if (!m_touchEventTargets->contains(&handler))
+ return;
+ m_touchEventTargets->removeAll(&handler);
+ } else {
+ if (!m_touchEventTargets->remove(&handler)) {
+ // Just decremented refcount, no real update.
+ return;
+ }
+ }
+
+ if (m_touchEventTargets->isEmpty()) {
+ if (Document* parent = document.parentDocument()) {
+ // This was the last handler in the document, update the parent document too.
+ didRemoveTouchEventHandler(*parent, document, clearAll);
+ } else {
+ // We just removed the last touch handler on the whole page.
+ if (FrameHost* frameHost = document.frameHost())
+ frameHost->chrome().client().needTouchEvents(false);
+ }
+ }
+
+ // When we're all done with all frames, ensure touch hit rects are marked as dirty.
+ if (!handler.isDocumentNode() || &handler == &document)
+ notifyTouchRectsChanged(document);
+}
+
+void EventHandlerRegistry::didAddEventHandler(Document& document, const AtomicString& eventType, Node* targetNode)
+{
+ if (eventType == EventTypeNames::wheel || eventType == EventTypeNames::mousewheel)
+ didChangeWheelEventHandlerCount(document, 1);
+ else if (eventType == EventTypeNames::scroll)
+ didChangeScrollEventHandlerCount(document, 1);
+ else if (isTouchEventType(eventType))
+ didAddTouchEventHandler(document, *targetNode);
+}
+
+void EventHandlerRegistry::didRemoveEventHandler(Document& document, const AtomicString& eventType, Node* targetNode)
+{
+ if (eventType == EventTypeNames::wheel || eventType == EventTypeNames::mousewheel)
+ didChangeWheelEventHandlerCount(document, -1);
+ else if (eventType == EventTypeNames::scroll)
+ didChangeScrollEventHandlerCount(document, -1);
+ else if (isTouchEventType(eventType))
+ didRemoveTouchEventHandler(document, *targetNode, false);
+}
+
+void EventHandlerRegistry::didAddEventListener(DOMWindow* window, const AtomicString& eventType)
+{
+ didAddEventHandler(*window->document(), eventType, window->document());
+}
+
+void EventHandlerRegistry::didRemoveEventListener(DOMWindow* window, const AtomicString& eventType)
+{
+ didRemoveEventHandler(*window->document(), eventType, window->document());
+}
+
+void EventHandlerRegistry::didMoveNodeToNewDocument(Node& targetNode, Document& oldDocument)
+{
+ didChangeAllEventHandlers(targetNode, oldDocument, Removed);
+ didChangeAllEventHandlers(targetNode, targetNode.document(), Added);
+}
+
+void EventHandlerRegistry::didRemoveAllEventHandlers(Node& targetNode)
+{
+ didChangeAllEventHandlers(targetNode, targetNode.document(), RemovedAll);
+}
+
+void EventHandlerRegistry::didChangeAllEventHandlers(Node& targetNode, Document& document, ChangeOperation op)
+{
+ if (!targetNode.hasEventListeners())
+ return;
+ EventHandlerRegistry* registry = EventHandlerRegistry::from(document);
+ int wheelHandlerCount = targetNode.getEventListeners(EventTypeNames::wheel).size() +
+ targetNode.getEventListeners(EventTypeNames::mousewheel).size();
+ registry->didChangeWheelEventHandlerCount(
+ document, (op == Added) ? wheelHandlerCount : -wheelHandlerCount);
+
+ int scrollHandlerCount = targetNode.getEventListeners(EventTypeNames::scroll).size();
+ registry->didChangeScrollEventHandlerCount(
+ document, (op == Added) ? scrollHandlerCount : -scrollHandlerCount);
+
+ const Vector<AtomicString> eventTypes = targetNode.eventTypes();
+ for (size_t i = 0; i < eventTypes.size(); ++i) {
+ if (!isTouchEventType(eventTypes[i]))
+ continue;
+ const EventListenerVector& eventListeners =
+ targetNode.getEventListeners(eventTypes[i]);
+ for (size_t j = 0; j < eventListeners.size(); ++j) {
+ if (op == Added)
+ registry->didAddTouchEventHandler(document, targetNode);
+ else
+ registry->didRemoveTouchEventHandler(document, targetNode, op == RemovedAll);
+ }
+ }
+}
+
+} // namespace WebCore

Powered by Google App Engine
This is Rietveld 408576698