| 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
|
|
|