From c9e2181c9f49443ffc19019973d86ef3a83f5921 Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Tue, 26 Apr 2011 15:31:21 +0300 Subject: [PATCH] Bug 651984 - Add ability to detect if a page has registered touch event listeners, r=jst --- content/base/src/nsNodeUtils.cpp | 3 +++ content/events/public/nsIEventListenerManager.h | 14 ++++++++++---- content/events/src/nsEventListenerManager.cpp | 9 ++++++++- content/events/test/test_bug648573.html | 6 ++++++ dom/base/nsDOMWindowUtils.cpp | 13 +++++++++++++ dom/base/nsPIDOMWindow.h | 9 +++++++-- dom/interfaces/base/nsIDOMWindowUtils.idl | 7 ++++++- 7 files changed, 53 insertions(+), 8 deletions(-) diff --git a/content/base/src/nsNodeUtils.cpp b/content/base/src/nsNodeUtils.cpp index fc9762a1b9a..45a55852223 100644 --- a/content/base/src/nsNodeUtils.cpp +++ b/content/base/src/nsNodeUtils.cpp @@ -558,6 +558,9 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, PRBool aClone, PRBool aDeep, window->SetHasAudioAvailableEventListeners(); } #endif + if (elm->MayHaveTouchEventListener()) { + window->SetHasTouchEventListeners(); + } } } } diff --git a/content/events/public/nsIEventListenerManager.h b/content/events/public/nsIEventListenerManager.h index 7d12e86b423..fbf367b44a4 100644 --- a/content/events/public/nsIEventListenerManager.h +++ b/content/events/public/nsIEventListenerManager.h @@ -56,8 +56,8 @@ class nsCxPusher; * Event listener manager interface. */ #define NS_IEVENTLISTENERMANAGER_IID \ -{ 0xe86a148b, 0x0563, 0x454f, \ - { 0x8c, 0xf2, 0xbd, 0xc4, 0x7c, 0xe6, 0xbe, 0x91 } } +{ 0x8e8667ed, 0x10d3, 0x41e8, \ + { 0x93, 0xfa, 0xa4, 0xc4, 0xea, 0x16, 0x85, 0xd5 } } class nsIEventListenerManager : public nsISupports { @@ -69,6 +69,7 @@ public: mMayHaveCapturingListeners(PR_FALSE), mMayHaveSystemGroupListeners(PR_FALSE), mMayHaveAudioAvailableEventListener(PR_FALSE), + mMayHaveTouchEventListener(PR_FALSE), mNoListenerForEvent(0) {} @@ -212,14 +213,19 @@ public: */ PRBool MayHaveAudioAvailableEventListener() { return mMayHaveAudioAvailableEventListener; } - + /** + * Returns PR_TRUE if there may be a touch event listener registered, + * PR_FALSE if there definitely isn't. + */ + PRBool MayHaveTouchEventListener() { return mMayHaveTouchEventListener; } protected: PRUint32 mMayHavePaintEventListener : 1; PRUint32 mMayHaveMutationListeners : 1; PRUint32 mMayHaveCapturingListeners : 1; PRUint32 mMayHaveSystemGroupListeners : 1; PRUint32 mMayHaveAudioAvailableEventListener : 1; - PRUint32 mNoListenerForEvent : 27; + PRUint32 mMayHaveTouchEventListener : 1; + PRUint32 mNoListenerForEvent : 26; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIEventListenerManager, diff --git a/content/events/src/nsEventListenerManager.cpp b/content/events/src/nsEventListenerManager.cpp index 0f78a1346d9..45459b23584 100644 --- a/content/events/src/nsEventListenerManager.cpp +++ b/content/events/src/nsEventListenerManager.cpp @@ -507,7 +507,14 @@ nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener, nsPIDOMWindow* window = GetInnerWindowForTarget(); if (window) window->SetHasOrientationEventListener(); - } else if (aType >= NS_MOZTOUCH_DOWN && aType <= NS_MOZTOUCH_UP) { + } else if ((aType >= NS_MOZTOUCH_DOWN && aType <= NS_MOZTOUCH_UP) || + (aTypeAtom == nsGkAtoms::ontouchstart || + aTypeAtom == nsGkAtoms::ontouchend || + aTypeAtom == nsGkAtoms::ontouchmove || + aTypeAtom == nsGkAtoms::ontouchenter || + aTypeAtom == nsGkAtoms::ontouchleave || + aTypeAtom == nsGkAtoms::ontouchcancel)) { + mMayHaveTouchEventListener = PR_TRUE; nsPIDOMWindow* window = GetInnerWindowForTarget(); if (window) window->SetHasTouchEventListeners(); diff --git a/content/events/test/test_bug648573.html b/content/events/test/test_bug648573.html index deb0ed9a6ff..8e4053270fb 100644 --- a/content/events/test/test_bug648573.html +++ b/content/events/test/test_bug648573.html @@ -20,6 +20,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=648573 /** Test for Bug 648573 **/ +ok(!SpecialPowers.DOMWindowUtils.mayHaveTouchEventListeners, + "There shouldn't be any touch event listeners yet."); + ok("createTouch" in document, "Should have createTouch function"); ok("createTouchList" in document, "Should have createTouchList function"); ok(document.createEvent("touchevent"), "Should be able to create TouchEvent objects"); @@ -98,6 +101,9 @@ function runEventTest(type) { for (var i = 0; i < events.length; ++i) { runEventTest(events[i]); } + +ok(SpecialPowers.DOMWindowUtils.mayHaveTouchEventListeners, + "There should be touch event listeners."); diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index b36379adc17..ec8cfc7e240 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -1861,3 +1861,16 @@ nsDOMWindowUtils::LeafLayersPartitionWindow(PRBool* aResult) #endif return NS_OK; } + +NS_IMETHODIMP +nsDOMWindowUtils::GetMayHaveTouchEventListeners(PRBool* aResult) +{ + if (!IsUniversalXPConnectCapable()) { + return NS_ERROR_DOM_SECURITY_ERR; + } + + nsPIDOMWindow* innerWindow = mWindow->GetCurrentInnerWindow(); + *aResult = innerWindow ? innerWindow->HasTouchEventListeners() : PR_FALSE; + return NS_OK; +} + diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index 9289e03908c..5a9464436f8 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -78,8 +78,8 @@ class nsIArray; class nsPIWindowRoot; #define NS_PIDOMWINDOW_IID \ -{ 0x8d8be7db, 0xffaa, 0x4962, \ - { 0xa7, 0x27, 0xb7, 0x0f, 0xc9, 0xfa, 0xd3, 0x0e } } +{ 0xafc4849b, 0x21d3, 0x45ea, \ + { 0x8b, 0xfd, 0x61, 0xec, 0x12, 0x5d, 0x38, 0x64 } } class nsPIDOMWindow : public nsIDOMWindowInternal { @@ -442,6 +442,11 @@ public: MaybeUpdateTouchState(); } + PRBool HasTouchEventListeners() + { + return mMayHaveTouchEventListener; + } + /** * Call this to check whether some node (this window, its document, * or content in that document) has a MozAudioAvailable event listener. diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index 70fdbbead03..5ce06a617a0 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -66,7 +66,7 @@ interface nsITransferable; interface nsIQueryContentEventResult; interface nsIDOMWindow; -[scriptable, uuid(3828e648-af61-47e1-b9bc-89ca51bc19f2)] +[scriptable, uuid(663e33d7-eca2-42e8-af92-5df6a5e222df)] interface nsIDOMWindowUtils : nsISupports { /** @@ -881,4 +881,9 @@ interface nsIDOMWindowUtils : nsISupports { * the bounds of the window. Always returns true in non-DEBUG builds. */ boolean leafLayersPartitionWindow(); + + /** + * true if the (current inner) window may have event listeners for touch events. + */ + readonly attribute boolean mayHaveTouchEventListeners; };