From 9ded402547b65cab5ef1c4d923f19c3832bdafa7 Mon Sep 17 00:00:00 2001 From: Oleg Romashin Date: Mon, 10 Feb 2014 22:33:29 -0800 Subject: [PATCH] Bug 822898 - Implement pointer events. Detect Pointer Listeners. r=smaug --- content/base/src/nsNodeUtils.cpp | 3 +++ dom/base/nsGlobalWindow.cpp | 1 + dom/base/nsPIDOMWindow.h | 20 ++++++++++++++++++++ dom/events/nsEventListenerManager.cpp | 16 ++++++++++++++++ dom/events/nsEventListenerManager.h | 4 +++- 5 files changed, 43 insertions(+), 1 deletion(-) diff --git a/content/base/src/nsNodeUtils.cpp b/content/base/src/nsNodeUtils.cpp index d4dd3cdeaa6d..bc047c35d73d 100644 --- a/content/base/src/nsNodeUtils.cpp +++ b/content/base/src/nsNodeUtils.cpp @@ -503,6 +503,9 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep, if (elm->MayHaveMouseEnterLeaveEventListener()) { window->SetHasMouseEnterLeaveEventListeners(); } + if (elm->MayHavePointerEnterLeaveEventListener()) { + window->SetHasPointerEnterLeaveEventListeners(); + } } } } diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 6f10cb3c27e5..61b09b7f0c6c 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -555,6 +555,7 @@ nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow *aOuterWindow) mIsHandlingResizeEvent(false), mIsInnerWindow(aOuterWindow != nullptr), mMayHavePaintEventListener(false), mMayHaveTouchEventListener(false), mMayHaveMouseEnterLeaveEventListener(false), + mMayHavePointerEnterLeaveEventListener(false), mIsModalContentWindow(false), mIsActive(false), mIsBackground(false), mInnerWindow(nullptr), mOuterWindow(aOuterWindow), diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index fa50ba111f62..f0751901a47e 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -483,6 +483,25 @@ public: mMayHaveMouseEnterLeaveEventListener = true; } + /** + * Call this to check whether some node (this window, its document, + * or content in that document) has a Pointerenter/leave event listener. + */ + bool HasPointerEnterLeaveEventListeners() + { + return mMayHavePointerEnterLeaveEventListener; + } + + /** + * Call this to indicate that some node (this window, its document, + * or content in that document) has a Pointerenter/leave event listener. + */ + void SetHasPointerEnterLeaveEventListeners() + { + mMayHavePointerEnterLeaveEventListener = true; + } + + virtual JSObject* GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler* aKey) = 0; virtual void CacheXBLPrototypeHandler(nsXBLPrototypeHandler* aKey, JS::Handle aHandler) = 0; @@ -733,6 +752,7 @@ protected: bool mMayHavePaintEventListener; bool mMayHaveTouchEventListener; bool mMayHaveMouseEnterLeaveEventListener; + bool mMayHavePointerEnterLeaveEventListener; // This variable is used on both inner and outer windows (and they // should match). diff --git a/dom/events/nsEventListenerManager.cpp b/dom/events/nsEventListenerManager.cpp index 5572398fdbb8..d5136e459e3d 100644 --- a/dom/events/nsEventListenerManager.cpp +++ b/dom/events/nsEventListenerManager.cpp @@ -94,6 +94,7 @@ nsEventListenerManager::nsEventListenerManager(EventTarget* aTarget) : mMayHaveAudioAvailableEventListener(false), mMayHaveTouchEventListener(false), mMayHaveMouseEnterLeaveEventListener(false), + mMayHavePointerEnterLeaveEventListener(false), mClearingListeners(false), mIsMainThreadELM(NS_IsMainThread()), mNoListenerForEvent(0), @@ -340,6 +341,21 @@ nsEventListenerManager::AddEventListenerInternal( if (window && !aFlags.mInSystemGroup) { window->SetHasTouchEventListeners(); } + } else if (aType >= NS_POINTER_EVENT_START && aType <= NS_POINTER_LOST_CAPTURE) { + nsPIDOMWindow* window = GetInnerWindowForTarget(); + if (aTypeAtom == nsGkAtoms::onpointerenter || + aTypeAtom == nsGkAtoms::onpointerleave) { + mMayHavePointerEnterLeaveEventListener = true; + if (window) { +#ifdef DEBUG + nsCOMPtr d = window->GetExtantDoc(); + NS_WARN_IF_FALSE(!nsContentUtils::IsChromeDoc(d), + "Please do not use pointerenter/leave events in chrome. " + "They are slower than pointerover/out!"); +#endif + window->SetHasPointerEnterLeaveEventListeners(); + } + } } else if (aTypeAtom == nsGkAtoms::onmouseenter || aTypeAtom == nsGkAtoms::onmouseleave) { mMayHaveMouseEnterLeaveEventListener = true; diff --git a/dom/events/nsEventListenerManager.h b/dom/events/nsEventListenerManager.h index 27a6c23d3878..74ebecd9e722 100644 --- a/dom/events/nsEventListenerManager.h +++ b/dom/events/nsEventListenerManager.h @@ -399,6 +399,7 @@ public: bool MayHaveTouchEventListener() { return mMayHaveTouchEventListener; } bool MayHaveMouseEnterLeaveEventListener() { return mMayHaveMouseEnterLeaveEventListener; } + bool MayHavePointerEnterLeaveEventListener() { return mMayHavePointerEnterLeaveEventListener; } size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; @@ -548,9 +549,10 @@ protected: uint32_t mMayHaveAudioAvailableEventListener : 1; uint32_t mMayHaveTouchEventListener : 1; uint32_t mMayHaveMouseEnterLeaveEventListener : 1; + uint32_t mMayHavePointerEnterLeaveEventListener : 1; uint32_t mClearingListeners : 1; uint32_t mIsMainThreadELM : 1; - uint32_t mNoListenerForEvent : 23; + uint32_t mNoListenerForEvent : 22; nsAutoTObserverArray mListeners; mozilla::dom::EventTarget* mTarget; //WEAK